From ba1224e577f68c0486806583d809f1f3d653d2a1 Mon Sep 17 00:00:00 2001 From: hwspeedy Date: Wed, 13 Dec 2023 15:55:14 +0100 Subject: [PATCH 1/3] Drivers/FPGA/DFL - Intel PAC N3000 missing modules select When adding the Intel PAC N3000 Nios interface a lot of modules that it depend on did not get selected. UIO_DFL, MFD_INTEL_M10_BMC_CORE, MFD_INTEL_M10_BMC_SPI, SENSORS_INTEL_M10_BMC_HWMON, SPI_ALTERA, FPGA_DFL_FME, FPGA_DFL_FME_MGR, FPGA_DFL_FME_REGION, FPGA_DFL_FME_BRIDGE, FPGA_DFL_AFU, FPGA_DFL_PCI, ALTERA_FREEZE_BRIDGE, FPGA_M10_BMC_SEC_UPDATE, ALTERA_PR_IP_CORE, FPGA_MGR_ALTERA_CVP, FPGA_MGR_ALTERA_PS_SPI --- drivers/fpga/Kconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 2f689ac4ba3a..43e02a801025 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -203,6 +203,22 @@ config FPGA_DFL_NIOS_INTEL_PAC_N3000 tristate "FPGA DFL NIOS Driver for Intel PAC N3000" depends on FPGA_DFL select REGMAP + select UIO_DFL + select MFD_INTEL_M10_BMC_CORE + select MFD_INTEL_M10_BMC_SPI + select SENSORS_INTEL_M10_BMC_HWMON + select SPI_ALTERA + select FPGA_DFL_FME + select FPGA_DFL_FME_MGR + select FPGA_DFL_FME_REGION + select FPGA_DFL_FME_BRIDGE + select FPGA_DFL_AFU + select FPGA_DFL_PCI + select ALTERA_FREEZE_BRIDGE + select FPGA_M10_BMC_SEC_UPDATE + select ALTERA_PR_IP_CORE + select FPGA_MGR_ALTERA_CVP + select FPGA_MGR_ALTERA_PS_SPI help This is the driver for the N3000 Nios private feature on Intel PAC (Programmable Acceleration Card) N3000. It communicates From f22d4909909a421c80a38ecb2f4c06bbfd41f694 Mon Sep 17 00:00:00 2001 From: hwspeedy Date: Wed, 13 Dec 2023 22:29:17 +0100 Subject: [PATCH 2/3] Update Kconfig Fixed Tabs, thanx --- drivers/fpga/Kconfig | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 43e02a801025..a0f9b6cefbfa 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -203,22 +203,22 @@ config FPGA_DFL_NIOS_INTEL_PAC_N3000 tristate "FPGA DFL NIOS Driver for Intel PAC N3000" depends on FPGA_DFL select REGMAP - select UIO_DFL - select MFD_INTEL_M10_BMC_CORE - select MFD_INTEL_M10_BMC_SPI - select SENSORS_INTEL_M10_BMC_HWMON - select SPI_ALTERA - select FPGA_DFL_FME - select FPGA_DFL_FME_MGR - select FPGA_DFL_FME_REGION - select FPGA_DFL_FME_BRIDGE - select FPGA_DFL_AFU - select FPGA_DFL_PCI - select ALTERA_FREEZE_BRIDGE - select FPGA_M10_BMC_SEC_UPDATE - select ALTERA_PR_IP_CORE - select FPGA_MGR_ALTERA_CVP - select FPGA_MGR_ALTERA_PS_SPI + select UIO_DFL + select MFD_INTEL_M10_BMC_CORE + select MFD_INTEL_M10_BMC_SPI + select SENSORS_INTEL_M10_BMC_HWMON + select SPI_ALTERA + select FPGA_DFL_FME + select FPGA_DFL_FME_MGR + select FPGA_DFL_FME_REGION + select FPGA_DFL_FME_BRIDGE + select FPGA_DFL_AFU + select FPGA_DFL_PCI + select ALTERA_FREEZE_BRIDGE + select FPGA_M10_BMC_SEC_UPDATE + select ALTERA_PR_IP_CORE + select FPGA_MGR_ALTERA_CVP + select FPGA_MGR_ALTERA_PS_SPI help This is the driver for the N3000 Nios private feature on Intel PAC (Programmable Acceleration Card) N3000. It communicates From 4463c1bc6e281e6a4917109d730b93bd4cecb05e Mon Sep 17 00:00:00 2001 From: root Date: Sun, 17 Dec 2023 05:23:36 +0100 Subject: [PATCH 3/3] ADD: Missing DFL intel-m10-bmc-retimer driver from Xu Yilun, 2020 WIP: The driver does not show linkstatus, retimer versions Error: fpgainfo uses direct hacking on the regmap for SPI, which requires root access. This driver could potential fix that issue. Moved the driver to FPGA and tried my best to fix issues due to old patch. --- drivers/fpga/Kconfig | 14 ++ drivers/fpga/Makefile | 2 + drivers/fpga/dfl-n3000-nios.c | 11 +- drivers/fpga/dfl.c | 9 ++ drivers/fpga/intel-m10-bmc-retimer.c | 230 +++++++++++++++++++++++++++ drivers/mfd/intel-m10-bmc-spi.c | 19 ++- include/linux/dfl.h | 1 + include/linux/mfd/intel-m10-bmc.h | 16 ++ 8 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 drivers/fpga/intel-m10-bmc-retimer.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index a0f9b6cefbfa..3be28f025bd9 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -216,9 +216,11 @@ config FPGA_DFL_NIOS_INTEL_PAC_N3000 select FPGA_DFL_PCI select ALTERA_FREEZE_BRIDGE select FPGA_M10_BMC_SEC_UPDATE + select FPGA_M10_BMC_RETIMER select ALTERA_PR_IP_CORE select FPGA_MGR_ALTERA_CVP select FPGA_MGR_ALTERA_PS_SPI + help This is the driver for the N3000 Nios private feature on Intel PAC (Programmable Acceleration Card) N3000. It communicates @@ -273,6 +275,18 @@ config FPGA_M10_BMC_SEC_UPDATE (BMC) and provides support for secure updates for the BMC image, the FPGA image, the Root Entry Hashes, etc. +config FPGA_M10_BMC_RETIMER + tristate "Intel(R) MAX 10 BMC ethernet retimer support" + depends on MFD_INTEL_M10_BMC_CORE + select PHYLIB + help + This driver supports the ethernet retimer (Parkvale) on + Intel(R) MAX 10 BMC, which is used by Intel PAC N3000 FPGA based + Smart NIC. + + To compile this driver as a module, choose M here. The module + will be called intel-m10-bmc-retimer. + config FPGA_MGR_MICROCHIP_SPI tristate "Microchip Polarfire SPI FPGA manager" depends on SPI diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 352a2612623e..653e229128c3 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -27,6 +27,8 @@ obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o # FPGA Secure Update Drivers obj-$(CONFIG_FPGA_M10_BMC_SEC_UPDATE) += intel-m10-bmc-sec-update.o +# FPGA Retimer Drivers +obj-$(CONFIG_FPGA_M10_BMC_RETIMER) += intel-m10-bmc-retimer.o # FPGA Bridge Drivers obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o diff --git a/drivers/fpga/dfl-n3000-nios.c b/drivers/fpga/dfl-n3000-nios.c index 9ddf1d1d392f..96ec3649d0a5 100644 --- a/drivers/fpga/dfl-n3000-nios.c +++ b/drivers/fpga/dfl-n3000-nios.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -159,6 +160,8 @@ struct n3000_nios { struct regmap *regmap; struct device *dev; struct platform_device *altera_spi; + struct intel_m10bmc_platdata m10bmc_pdata; + struct intel_m10bmc_retimer_pdata m10bmc_retimer_pdata; }; static ssize_t nios_fw_version_show(struct device *dev, @@ -412,7 +415,8 @@ static struct spi_board_info m10_n3000_info = { .chip_select = 0, }; -static int create_altera_spi_controller(struct n3000_nios *nn) +static int create_altera_spi_controller(struct n3000_nios *nn, + struct device *retimer_master) { struct altera_spi_platform_data pdata = { 0 }; struct platform_device_info pdevinfo = { 0 }; @@ -431,6 +435,9 @@ static int create_altera_spi_controller(struct n3000_nios *nn) pdata.bits_per_word_mask = SPI_BPW_RANGE_MASK(1, FIELD_GET(N3000_NS_PARAM_DATA_WIDTH, v)); + nn->m10bmc_retimer_pdata.retimer_master = retimer_master; + nn->m10bmc_pdata.retimer = &nn->m10bmc_retimer_pdata; + m10_n3000_info.platform_data = &nn->m10bmc_pdata; pdata.num_devices = 1; pdata.devices = &m10_n3000_info; @@ -549,7 +556,7 @@ static int n3000_nios_probe(struct dfl_device *ddev) if (ret) return ret; - ret = create_altera_spi_controller(nn); + ret = create_altera_spi_controller(nn, dfl_dev_get_base_dev(ddev)); if (ret) dev_err(dev, "altera spi controller create failed: %d\n", ret); diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index dd7a783d53b5..a1c03ebeaa8e 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -496,6 +496,15 @@ void dfl_driver_unregister(struct dfl_driver *dfl_drv) } EXPORT_SYMBOL(dfl_driver_unregister); +struct device *dfl_dev_get_base_dev(struct dfl_device *dfl_dev) +{ + if (!dfl_dev || !dfl_dev->cdev) + return NULL; + + return dfl_dev->cdev->parent; +} +EXPORT_SYMBOL_GPL(dfl_dev_get_base_dev); + #define is_header_feature(feature) ((feature)->id == FEATURE_ID_FIU_HEADER) /** diff --git a/drivers/fpga/intel-m10-bmc-retimer.c b/drivers/fpga/intel-m10-bmc-retimer.c new file mode 100644 index 000000000000..f2f747a1181f --- /dev/null +++ b/drivers/fpga/intel-m10-bmc-retimer.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Intel Max10 BMC Retimer Interface Driver + * + * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. + * + */ +#include +#include +#include +#include +#include + +#define NUM_CHIP 2 +#define MAX_LINK 4 + +#define BITS_MASK(nbits) ((1 << (nbits)) - 1) + +#define N3000BMC_RETIMER_DEV_NAME "n3000bmc-retimer" +#define M10BMC_RETIMER_MII_NAME "m10bmc retimer mii" + +struct m10bmc_retimer { + struct device *dev; + struct intel_m10bmc *m10bmc; + int num_devs; + struct device *base_dev; + struct mii_bus *retimer_mii_bus; +}; + +#define RETIMER_LINK_STAT_BIT(retimer_id, link_id) \ + BIT(((retimer_id) << 2) + (link_id)) + +static u32 retimer_get_link(struct m10bmc_retimer *retimer, int index) +{ + unsigned int val; + + if (m10bmc_sys_read(retimer->m10bmc, PKVL_LINK_STATUS, &val)) { + dev_err(retimer->dev, "fail to read PKVL_LINK_STATUS\n"); + return 0; + } + + if (val & BIT(index)) + return 1; + + return 0; +} + +static int m10bmc_retimer_phy_match(struct phy_device *phydev) +{ + if (phydev->mdio.bus->name && + !strcmp(phydev->mdio.bus->name, M10BMC_RETIMER_MII_NAME)) { + return 1; + } + + return 0; +} + +static int m10bmc_retimer_phy_probe(struct phy_device *phydev) +{ + struct m10bmc_retimer *retimer = phydev->mdio.bus->priv; + + phydev->priv = retimer; + + return 0; +} + +static void m10bmc_retimer_phy_remove(struct phy_device *phydev) +{ + if (phydev->attached_dev) + phy_disconnect(phydev); +} + +static int m10bmc_retimer_read_status(struct phy_device *phydev) +{ + struct m10bmc_retimer *retimer = phydev->priv; + + phydev->link = retimer_get_link(retimer, phydev->mdio.addr); + + phydev->duplex = DUPLEX_FULL; + + return 0; +} + +static int m10bmc_retimer_get_features(struct phy_device *phydev) +{ + linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + phydev->supported); + + linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, + phydev->supported); + + linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, + phydev->supported); + + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported); + + return 0; +} + +static struct phy_driver m10bmc_retimer_phy_driver = { + .phy_id = 0xffffffff, + .phy_id_mask = 0xffffffff, + .name = "m10bmc retimer PHY", + .match_phy_device = m10bmc_retimer_phy_match, + .probe = m10bmc_retimer_phy_probe, + .remove = m10bmc_retimer_phy_remove, + .read_status = m10bmc_retimer_read_status, + .get_features = m10bmc_retimer_get_features, + .read_mmd = genphy_read_mmd_unsupported, + .write_mmd = genphy_write_mmd_unsupported, +}; + +static int m10bmc_retimer_read(struct mii_bus *bus, int addr, int regnum) +{ + struct m10bmc_retimer *retimer = bus->priv; + + if (addr < retimer->num_devs && + (regnum == MII_PHYSID1 || regnum == MII_PHYSID2)) + return 0; + + return 0xffff; +} + +static int m10bmc_retimer_write(struct mii_bus *bus, int addr, int regnum, u16 val) +{ + return 0; +} + +static int m10bmc_retimer_mii_bus_init(struct m10bmc_retimer *retimer) +{ + struct mii_bus *bus; + int ret; + + bus = devm_mdiobus_alloc(retimer->dev); + if (!bus) + return -ENOMEM; + + bus->priv = (void *)retimer; + bus->name = M10BMC_RETIMER_MII_NAME; + bus->read = m10bmc_retimer_read; + bus->write = m10bmc_retimer_write; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", + dev_name(retimer->base_dev)); + bus->parent = retimer->dev; + bus->phy_mask = ~(BITS_MASK(retimer->num_devs)); + + ret = mdiobus_register(bus); + if (ret) + return ret; + + retimer->retimer_mii_bus = bus; + + return 0; +} + +static void m10bmc_retimer_mii_bus_uinit(struct m10bmc_retimer *retimer) +{ + mdiobus_unregister(retimer->retimer_mii_bus); +} + +static int intel_m10bmc_retimer_probe(struct platform_device *pdev) +{ + struct intel_m10bmc_retimer_pdata *pdata = dev_get_platdata(&pdev->dev); + struct intel_m10bmc *m10bmc = dev_get_drvdata(pdev->dev.parent); + struct m10bmc_retimer *retimer; + + retimer = devm_kzalloc(&pdev->dev, sizeof(*retimer), GFP_KERNEL); + if (!retimer) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, retimer); + + retimer->dev = &pdev->dev; + retimer->m10bmc = m10bmc; + retimer->base_dev = pdata->retimer_master; + retimer->num_devs = NUM_CHIP * MAX_LINK; + + return m10bmc_retimer_mii_bus_init(retimer); +} + +static int intel_m10bmc_retimer_remove(struct platform_device *pdev) +{ + struct m10bmc_retimer *retimer = dev_get_drvdata(&pdev->dev); + + m10bmc_retimer_mii_bus_uinit(retimer); + + return 0; +} + +static struct platform_driver intel_m10bmc_retimer_driver = { + .probe = intel_m10bmc_retimer_probe, + .remove = intel_m10bmc_retimer_remove, + .driver = { + .name = N3000BMC_RETIMER_DEV_NAME, + }, +}; + +static int __init intel_m10bmc_retimer_init(void) +{ + int ret; + + ret = phy_driver_register(&m10bmc_retimer_phy_driver, THIS_MODULE); + if (ret) + return ret; + + return platform_driver_register(&intel_m10bmc_retimer_driver); +} +module_init(intel_m10bmc_retimer_init); + +static void __exit intel_m10bmc_retimer_exit(void) +{ + platform_driver_unregister(&intel_m10bmc_retimer_driver); + phy_driver_unregister(&m10bmc_retimer_phy_driver); +} +module_exit(intel_m10bmc_retimer_exit); + +MODULE_ALIAS("platform:" N3000BMC_RETIMER_DEV_NAME); +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel MAX 10 BMC retimer driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(INTEL_M10_BMC_CORE); diff --git a/drivers/mfd/intel-m10-bmc-spi.c b/drivers/mfd/intel-m10-bmc-spi.c index cbeb7de9e041..c2a68c39fcd8 100644 --- a/drivers/mfd/intel-m10-bmc-spi.c +++ b/drivers/mfd/intel-m10-bmc-spi.c @@ -4,6 +4,7 @@ * * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. */ +#define DEBUG #include #include #include @@ -24,6 +25,20 @@ static const struct regmap_access_table m10bmc_access_table = { .n_yes_ranges = ARRAY_SIZE(m10bmc_regmap_range), }; +static void m10bmc_init_cells_platdata(struct intel_m10bmc_platdata *pdata, + struct mfd_cell *cells, int n_cell) +{ + int i; + + for (i = 0; i < n_cell; i++) { + if (!strcmp(cells[i].name, "n3000bmc-retimer")) { + cells[i].platform_data = pdata->retimer; + cells[i].pdata_size = + pdata->retimer ? sizeof(*pdata->retimer) : 0; + } + } +} + static struct regmap_config intel_m10bmc_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -60,7 +75,8 @@ static int check_m10bmc_version(struct intel_m10bmc *ddata) static int intel_m10_bmc_spi_probe(struct spi_device *spi) { - const struct spi_device_id *id = spi_get_device_id(spi); + struct intel_m10bmc_platdata *pdata = dev_get_platdata(&spi->dev); + const struct spi_device_id *id = spi_get_device_id(spi); const struct intel_m10bmc_platform_info *info; struct device *dev = &spi->dev; struct intel_m10bmc *ddata; @@ -72,6 +88,7 @@ static int intel_m10_bmc_spi_probe(struct spi_device *spi) info = (struct intel_m10bmc_platform_info *)id->driver_data; ddata->dev = dev; + m10bmc_init_cells_platdata(pdata, info->cells, info->n_cells); ddata->regmap = devm_regmap_init_spi_avmm(spi, &intel_m10bmc_regmap_config); if (IS_ERR(ddata->regmap)) { diff --git a/include/linux/dfl.h b/include/linux/dfl.h index 0a7a00a0ee7f..c4c4d2854398 100644 --- a/include/linux/dfl.h +++ b/include/linux/dfl.h @@ -92,4 +92,5 @@ void dfl_driver_unregister(struct dfl_driver *dfl_drv); dfl_driver_unregister) void *dfh_find_param(struct dfl_device *dfl_dev, int param_id, size_t *pcount); +struct device *dfl_dev_get_base_dev(struct dfl_device *dfl_dev); #endif /* __LINUX_DFL_H */ diff --git a/include/linux/mfd/intel-m10-bmc.h b/include/linux/mfd/intel-m10-bmc.h index ee66c9751003..bc4d0f51faaa 100644 --- a/include/linux/mfd/intel-m10-bmc.h +++ b/include/linux/mfd/intel-m10-bmc.h @@ -184,6 +184,22 @@ #define M10BMC_FLASH_INT_US 1 #define M10BMC_FLASH_TIMEOUT_US 10000 +/* PKVL related registers, in system register region */ +#define PKVL_LINK_STATUS 0x164 + +/** + * struct intel_m10bmc_retimer_pdata - subdev retimer platform data + * + * @retimer_master: the NIC device which connects to the retimers on m10bmc + */ +struct intel_m10bmc_retimer_pdata { + struct device *retimer_master; +}; + +struct intel_m10bmc_platdata { + struct intel_m10bmc_retimer_pdata *retimer; +}; + /** * struct m10bmc_csr_map - Intel MAX 10 BMC CSR register map */