Skip to content

Commit 02daa22

Browse files
vadimp-nvidiajwrdegoede
authored andcommitted
platform: mellanox: Add initial support for PCIe based programming logic device
Extend driver to support logic implemented by FPGA device connected through PCIe bus. The motivation two support new generation of Nvidia COME module equipped with Lattice LFD2NX-40 FPGA device. In order to support new Nvidia COME module FPGA device driver initialization flow is modified. In case FPGA device is detected, system resources are to be mapped to this device, otherwise system resources are to be mapped same as it has been done before for Lattice LPC based CPLD. FPGA device is associated with three PCIe devices: - PCIe-LPC bridge for main register space access. - PCIe-I2C bridge for I2C controller access. - PCIe-JTAG bridge for JTAG access. Signed-off-by: Vadim Pasternak <[email protected]> Reviewed-by: Michael Shych <[email protected]> Reviewed-by: Hans de Goede <[email protected]> Reviewed-by: Ilpo Järvinen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Hans de Goede <[email protected]>
1 parent ada9ecc commit 02daa22

File tree

1 file changed

+132
-2
lines changed

1 file changed

+132
-2
lines changed

drivers/platform/x86/mlx-platform.c

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/i2c-mux.h>
1313
#include <linux/io.h>
1414
#include <linux/module.h>
15+
#include <linux/pci.h>
1516
#include <linux/platform_device.h>
1617
#include <linux/platform_data/i2c-mux-reg.h>
1718
#include <linux/platform_data/mlxreg.h>
@@ -331,6 +332,12 @@
331332
#define MLXPLAT_I2C_MAIN_BUS_NOTIFIED 0x01
332333
#define MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED 0x02
333334

335+
/* Lattice FPGA PCI configuration */
336+
#define PCI_VENDOR_ID_LATTICE 0x1204
337+
#define PCI_DEVICE_ID_LATTICE_I2C_BRIDGE 0x9c2f
338+
#define PCI_DEVICE_ID_LATTICE_JTAG_BRIDGE 0x9c30
339+
#define PCI_DEVICE_ID_LATTICE_LPC_BRIDGE 0x9c32
340+
334341
/* mlxplat_priv - platform private data
335342
* @pdev_i2c - i2c controller platform device
336343
* @pdev_mux - array of mux platform devices
@@ -362,6 +369,7 @@ struct mlxplat_priv {
362369

363370
static struct platform_device *mlxplat_dev;
364371
static int mlxplat_i2c_main_complition_notify(void *handle, int id);
372+
static void __iomem *i2c_bridge_addr, *jtag_bridge_addr;
365373

366374
/* Regions for LPC I2C controller and LPC base register space */
367375
static const struct resource mlxplat_lpc_resources[] = {
@@ -5544,6 +5552,9 @@ static struct mlxreg_core_platform_data *mlxplat_fan;
55445552
static struct mlxreg_core_platform_data
55455553
*mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS];
55465554
static const struct regmap_config *mlxplat_regmap_config;
5555+
static struct pci_dev *lpc_bridge;
5556+
static struct pci_dev *i2c_bridge;
5557+
static struct pci_dev *jtag_bridge;
55475558

55485559
/* Platform default reset function */
55495560
static int mlxplat_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused)
@@ -6172,15 +6183,131 @@ static void mlxplat_lpc_cpld_device_exit(void)
61726183
{
61736184
}
61746185

6186+
static int
6187+
mlxplat_pci_fpga_device_init(unsigned int device, const char *res_name, struct pci_dev **pci_bridge,
6188+
void __iomem **pci_bridge_addr)
6189+
{
6190+
void __iomem *pci_mem_addr;
6191+
struct pci_dev *pci_dev;
6192+
int err;
6193+
6194+
pci_dev = pci_get_device(PCI_VENDOR_ID_LATTICE, device, NULL);
6195+
if (!pci_dev)
6196+
return -ENODEV;
6197+
6198+
err = pci_enable_device(pci_dev);
6199+
if (err) {
6200+
dev_err(&pci_dev->dev, "pci_enable_device failed with error %d\n", err);
6201+
goto fail_pci_enable_device;
6202+
}
6203+
6204+
err = pci_request_region(pci_dev, 0, res_name);
6205+
if (err) {
6206+
dev_err(&pci_dev->dev, "pci_request_regions failed with error %d\n", err);
6207+
goto fail_pci_request_regions;
6208+
}
6209+
6210+
err = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64));
6211+
if (err) {
6212+
err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
6213+
if (err) {
6214+
dev_err(&pci_dev->dev, "dma_set_mask failed with error %d\n", err);
6215+
goto fail_pci_set_dma_mask;
6216+
}
6217+
}
6218+
6219+
pci_set_master(pci_dev);
6220+
6221+
pci_mem_addr = devm_ioremap(&pci_dev->dev, pci_resource_start(pci_dev, 0),
6222+
pci_resource_len(pci_dev, 0));
6223+
if (!pci_mem_addr) {
6224+
dev_err(&mlxplat_dev->dev, "ioremap failed\n");
6225+
err = -EIO;
6226+
goto fail_ioremap;
6227+
}
6228+
6229+
*pci_bridge = pci_dev;
6230+
*pci_bridge_addr = pci_mem_addr;
6231+
6232+
return 0;
6233+
6234+
fail_ioremap:
6235+
fail_pci_set_dma_mask:
6236+
pci_release_regions(pci_dev);
6237+
fail_pci_request_regions:
6238+
pci_disable_device(pci_dev);
6239+
fail_pci_enable_device:
6240+
return err;
6241+
}
6242+
6243+
static void
6244+
mlxplat_pci_fpga_device_exit(struct pci_dev *pci_bridge,
6245+
void __iomem *pci_bridge_addr)
6246+
{
6247+
iounmap(pci_bridge_addr);
6248+
pci_release_regions(pci_bridge);
6249+
pci_disable_device(pci_bridge);
6250+
}
6251+
6252+
static int
6253+
mlxplat_pci_fpga_devices_init(struct resource **hotplug_resources,
6254+
unsigned int *hotplug_resources_size)
6255+
{
6256+
int err;
6257+
6258+
err = mlxplat_pci_fpga_device_init(PCI_DEVICE_ID_LATTICE_LPC_BRIDGE,
6259+
"mlxplat_lpc_bridge", &lpc_bridge,
6260+
&mlxplat_mlxcpld_regmap_ctx.base);
6261+
if (err)
6262+
goto mlxplat_pci_fpga_device_init_lpc_fail;
6263+
6264+
err = mlxplat_pci_fpga_device_init(PCI_DEVICE_ID_LATTICE_I2C_BRIDGE,
6265+
"mlxplat_i2c_bridge", &i2c_bridge,
6266+
&i2c_bridge_addr);
6267+
if (err)
6268+
goto mlxplat_pci_fpga_device_init_i2c_fail;
6269+
6270+
err = mlxplat_pci_fpga_device_init(PCI_DEVICE_ID_LATTICE_JTAG_BRIDGE,
6271+
"mlxplat_jtag_bridge", &jtag_bridge,
6272+
&jtag_bridge_addr);
6273+
if (err)
6274+
goto mlxplat_pci_fpga_device_init_jtag_fail;
6275+
6276+
return 0;
6277+
6278+
mlxplat_pci_fpga_device_init_jtag_fail:
6279+
mlxplat_pci_fpga_device_exit(i2c_bridge, i2c_bridge_addr);
6280+
mlxplat_pci_fpga_device_init_i2c_fail:
6281+
mlxplat_pci_fpga_device_exit(lpc_bridge, mlxplat_mlxcpld_regmap_ctx.base);
6282+
mlxplat_pci_fpga_device_init_lpc_fail:
6283+
return err;
6284+
}
6285+
6286+
static void mlxplat_pci_fpga_devices_exit(void)
6287+
{
6288+
mlxplat_pci_fpga_device_exit(jtag_bridge, jtag_bridge_addr);
6289+
mlxplat_pci_fpga_device_exit(i2c_bridge, i2c_bridge_addr);
6290+
mlxplat_pci_fpga_device_exit(lpc_bridge, mlxplat_mlxcpld_regmap_ctx.base);
6291+
}
6292+
61756293
static int
61766294
mlxplat_pre_init(struct resource **hotplug_resources, unsigned int *hotplug_resources_size)
61776295
{
6178-
return mlxplat_lpc_cpld_device_init(hotplug_resources, hotplug_resources_size);
6296+
int err;
6297+
6298+
err = mlxplat_pci_fpga_devices_init(hotplug_resources, hotplug_resources_size);
6299+
if (err == -ENODEV)
6300+
return mlxplat_lpc_cpld_device_init(hotplug_resources, hotplug_resources_size);
6301+
6302+
return err;
61796303
}
61806304

61816305
static void mlxplat_post_exit(void)
61826306
{
6183-
mlxplat_lpc_cpld_device_exit();
6307+
if (lpc_bridge)
6308+
mlxplat_pci_fpga_devices_exit();
6309+
else
6310+
mlxplat_lpc_cpld_device_exit();
61846311
}
61856312

61866313
static int mlxplat_post_init(struct mlxplat_priv *priv)
@@ -6366,6 +6493,9 @@ static int mlxplat_i2c_main_init(struct mlxplat_priv *priv)
63666493
mlxplat_i2c->regmap = priv->regmap;
63676494
mlxplat_i2c->handle = priv;
63686495

6496+
/* Set mapped base address of I2C-LPC bridge over PCIe */
6497+
if (lpc_bridge)
6498+
mlxplat_i2c->addr = i2c_bridge_addr;
63696499
priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld",
63706500
nr, priv->hotplug_resources,
63716501
priv->hotplug_resources_size,

0 commit comments

Comments
 (0)