From 57aaf63cb13ca342bfeba6772df3a4e05a35e4ab Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Fri, 12 Aug 2016 16:51:31 +0530 Subject: [PATCH] net: thunderx: Add 81xx support to BGX driver This patch adds support for BGX module on 81xx where a BGX can be split and have different LMACs configured in different modes. Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../net/ethernet/cavium/thunder/thunder_bgx.c | 112 ++++++++++++++++-- .../net/ethernet/cavium/thunder/thunder_bgx.h | 11 ++ 2 files changed, 113 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 44974270093d..9c3c273f4535 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -50,6 +50,7 @@ struct bgx { int lmac_count; void __iomem *reg_base; struct pci_dev *pdev; + bool is_81xx; }; static struct bgx *bgx_vnic[MAX_BGX_THUNDER]; @@ -803,9 +804,17 @@ static void bgx_print_qlm_mode(struct bgx *bgx, u8 lmacid) struct device *dev = &bgx->pdev->dev; struct lmac *lmac; char str[20]; + u8 dlm; + + if (lmacid > MAX_LMAC_PER_BGX) + return; lmac = &bgx->lmac[lmacid]; - sprintf(str, "BGX%d QLM mode", bgx->bgx_id); + dlm = (lmacid / 2) + (bgx->bgx_id * 2); + if (!bgx->is_81xx) + sprintf(str, "BGX%d QLM mode", bgx->bgx_id); + else + sprintf(str, "BGX%d DLM%d mode", bgx->bgx_id, dlm); switch (lmac->lmac_type) { case BGX_MODE_SGMII: @@ -857,26 +866,81 @@ static void lmac_set_lane2sds(struct lmac *lmac) static void bgx_set_lmac_config(struct bgx *bgx, u8 idx) { struct lmac *lmac; + struct lmac *olmac; u64 cmr_cfg; + u8 lmac_type; + u8 lane_to_sds; lmac = &bgx->lmac[idx]; - lmac->lmacid = idx; - /* Read LMAC0 type to figure out QLM mode - * This is configured by low level firmware + if (!bgx->is_81xx) { + /* Read LMAC0 type to figure out QLM mode + * This is configured by low level firmware + */ + cmr_cfg = bgx_reg_read(bgx, 0, BGX_CMRX_CFG); + lmac->lmac_type = (cmr_cfg >> 8) & 0x07; + lmac->use_training = + bgx_reg_read(bgx, 0, BGX_SPUX_BR_PMD_CRTL) & + SPU_PMD_CRTL_TRAIN_EN; + lmac_set_lane2sds(lmac); + return; + } + + /* On 81xx BGX can be split across 2 DLMs + * firmware programs lmac_type of LMAC0 and LMAC2 */ - cmr_cfg = bgx_reg_read(bgx, 0, BGX_CMRX_CFG); - lmac->lmac_type = (cmr_cfg >> 8) & 0x07; - lmac->use_training = - bgx_reg_read(bgx, 0, BGX_SPUX_BR_PMD_CRTL) & + if ((idx == 0) || (idx == 2)) { + cmr_cfg = bgx_reg_read(bgx, idx, BGX_CMRX_CFG); + lmac_type = (u8)((cmr_cfg >> 8) & 0x07); + lane_to_sds = (u8)(cmr_cfg & 0xFF); + /* Check if config is not reset value */ + if ((lmac_type == 0) && (lane_to_sds == 0xE4)) + lmac->lmac_type = BGX_MODE_INVALID; + else + lmac->lmac_type = lmac_type; + lmac->use_training = + bgx_reg_read(bgx, idx, BGX_SPUX_BR_PMD_CRTL) & + SPU_PMD_CRTL_TRAIN_EN; + lmac_set_lane2sds(lmac); + + /* Set LMAC type of other lmac on same DLM i.e LMAC 1/3 */ + olmac = &bgx->lmac[idx + 1]; + olmac->lmac_type = lmac->lmac_type; + olmac->use_training = + bgx_reg_read(bgx, idx + 1, BGX_SPUX_BR_PMD_CRTL) & SPU_PMD_CRTL_TRAIN_EN; - lmac_set_lane2sds(lmac); + lmac_set_lane2sds(olmac); + } +} + +static bool is_dlm0_in_bgx_mode(struct bgx *bgx) +{ + struct lmac *lmac; + + if (!bgx->is_81xx) + return true; + + lmac = &bgx->lmac[1]; + if (lmac->lmac_type == BGX_MODE_INVALID) + return false; + + return true; } static void bgx_get_qlm_mode(struct bgx *bgx) { + struct lmac *lmac; + struct lmac *lmac01; + struct lmac *lmac23; u8 idx; + /* Init all LMAC's type to invalid */ + for (idx = 0; idx < MAX_LMAC_PER_BGX; idx++) { + lmac = &bgx->lmac[idx]; + lmac->lmac_type = BGX_MODE_INVALID; + lmac->lmacid = idx; + } + /* It is assumed that low level firmware sets this value */ bgx->lmac_count = bgx_reg_read(bgx, 0, BGX_CMR_RX_LMACS) & 0x7; if (bgx->lmac_count > MAX_LMAC_PER_BGX) @@ -884,7 +948,28 @@ static void bgx_get_qlm_mode(struct bgx *bgx) for (idx = 0; idx < bgx->lmac_count; idx++) bgx_set_lmac_config(bgx, idx); - bgx_print_qlm_mode(bgx, 0); + + if (!bgx->is_81xx) { + bgx_print_qlm_mode(bgx, 0); + return; + } + + if (bgx->lmac_count) { + bgx_print_qlm_mode(bgx, 0); + bgx_print_qlm_mode(bgx, 2); + } + + /* If DLM0 is not in BGX mode then LMAC0/1 have + * to be configured with serdes lanes of DLM1 + */ + if (is_dlm0_in_bgx_mode(bgx) || (bgx->lmac_count > 2)) + return; + for (idx = 0; idx < bgx->lmac_count; idx++) { + lmac01 = &bgx->lmac[idx]; + lmac23 = &bgx->lmac[idx + 2]; + lmac01->lmac_type = lmac23->lmac_type; + lmac01->lane_to_sds = lmac23->lane_to_sds; + } } #ifdef CONFIG_ACPI @@ -1059,6 +1144,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct device *dev = &pdev->dev; struct bgx *bgx = NULL; u8 lmac; + u16 sdevid; bgx = devm_kzalloc(dev, sizeof(*bgx), GFP_KERNEL); if (!bgx) @@ -1080,6 +1166,10 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_disable_device; } + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &sdevid); + if (sdevid == PCI_SUBSYS_DEVID_81XX_BGX) + bgx->is_81xx = true; + /* MAP configuration registers */ bgx->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0); if (!bgx->reg_base) { @@ -1105,6 +1195,8 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) { dev_err(dev, "BGX%d failed to enable lmac%d\n", bgx->bgx_id, lmac); + while (lmac) + bgx_lmac_disable(bgx, --lmac); goto err_enable; } } diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h index b7b91c857dba..38e9fb4ae8c4 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h @@ -9,6 +9,14 @@ #ifndef THUNDER_BGX_H #define THUNDER_BGX_H +/* PCI device ID */ +#define PCI_DEVICE_ID_THUNDER_BGX 0xA026 + +/* Subsystem device IDs */ +#define PCI_SUBSYS_DEVID_88XX_BGX 0xA126 +#define PCI_SUBSYS_DEVID_81XX_BGX 0xA226 +#define PCI_SUBSYS_DEVID_83XX_BGX 0xA326 + #define MAX_BGX_THUNDER 8 /* Max 4 nodes, 2 per node */ #define MAX_BGX_PER_CN88XX 2 #define MAX_BGX_PER_CN81XX 2 @@ -215,6 +223,9 @@ enum LMAC_TYPE { BGX_MODE_XLAUI = 4, /* 4 lanes, 10.3125 Gbaud */ BGX_MODE_10G_KR = 3,/* 1 lane, 10.3125 Gbaud */ BGX_MODE_40G_KR = 4,/* 4 lanes, 10.3125 Gbaud */ + BGX_MODE_RGMII = 5, + BGX_MODE_QSGMII = 6, + BGX_MODE_INVALID = 7, }; #endif /* THUNDER_BGX_H */ -- 2.20.1