brintos

brintos / linux-shallow public Read only

0
0
Text · 10.9 KiB · ae09228 Raw
453 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) KEBA Industrial Automation Gmbh 20244 *5 * Driver for KEBA system FPGA6 *7 * The KEBA system FPGA implements various devices. This driver registers8 * auxiliary devices for every device within the FPGA.9 */10 11#include <linux/device.h>12#include <linux/i2c.h>13#include <linux/misc/keba.h>14#include <linux/module.h>15#include <linux/pci.h>16 17#define CP500 "cp500"18 19#define PCI_VENDOR_ID_KEBA		0xCEBA20#define PCI_DEVICE_ID_KEBA_CP035	0x270621#define PCI_DEVICE_ID_KEBA_CP505	0x270322#define PCI_DEVICE_ID_KEBA_CP520	0x269623 24#define CP500_SYS_BAR		025#define CP500_ECM_BAR		126 27/* BAR 0 registers */28#define CP500_VERSION_REG	0x0029#define CP500_RECONFIG_REG	0x11	/* upper 8-bits of STARTUP register */30#define CP500_AXI_REG		0x4031 32/* Bits in BUILD_REG */33#define CP500_BUILD_TEST        0x8000	/* FPGA test version */34 35/* Bits in RECONFIG_REG */36#define CP500_RECFG_REQ		0x01	/* reconfigure FPGA on next reset */37 38/* MSIX */39#define CP500_AXI_MSIX		340#define CP500_NUM_MSIX		841#define CP500_NUM_MSIX_NO_MMI	242#define CP500_NUM_MSIX_NO_AXI	343 44/* EEPROM */45#define CP500_HW_CPU_EEPROM_NAME	"cp500_cpu_eeprom"46 47#define CP500_IS_CP035(dev)	((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035)48#define CP500_IS_CP505(dev)	((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505)49#define CP500_IS_CP520(dev)	((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP520)50 51struct cp500_dev_info {52	off_t offset;53	size_t size;54};55 56struct cp500_devs {57	struct cp500_dev_info startup;58	struct cp500_dev_info i2c;59};60 61/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */62static struct cp500_devs cp035_devices = {63	.startup   = { 0x0000, SZ_4K },64	.i2c       = { 0x4000, SZ_4K },65};66 67/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */68static struct cp500_devs cp505_devices = {69	.startup   = { 0x0000, SZ_4K },70	.i2c       = { 0x5000, SZ_4K },71};72 73/* list of devices within FPGA of CP520 family (CP520, CP530) */74static struct cp500_devs cp520_devices = {75	.startup     = { 0x0000, SZ_4K },76	.i2c         = { 0x5000, SZ_4K },77};78 79struct cp500 {80	struct pci_dev *pci_dev;81	struct cp500_devs *devs;82	int msix_num;83	struct {84		int major;85		int minor;86		int build;87	} version;88 89	/* system FPGA BAR */90	resource_size_t sys_hwbase;91	struct keba_i2c_auxdev *i2c;92 93	/* ECM EtherCAT BAR */94	resource_size_t ecm_hwbase;95 96	void __iomem *system_startup_addr;97};98 99/* I2C devices */100static struct i2c_board_info cp500_i2c_info[] = {101	{	/* temperature sensor */102		I2C_BOARD_INFO("emc1403", 0x4c),103	},104	{	/*105		 * CPU EEPROM106		 * CP035 family: CPU board107		 * CP505 family: bridge board108		 * CP520 family: carrier board109		 */110		I2C_BOARD_INFO("24c32", 0x50),111		.dev_name = CP500_HW_CPU_EEPROM_NAME,112	},113	{	/* interface board EEPROM */114		I2C_BOARD_INFO("24c32", 0x51),115	},116	{	/*117		 * EEPROM (optional)118		 * CP505 family: CPU board119		 * CP520 family: MMI board120		 */121		I2C_BOARD_INFO("24c32", 0x52),122	},123	{	/* extension module 0 EEPROM (optional) */124		I2C_BOARD_INFO("24c32", 0x53),125	},126	{	/* extension module 1 EEPROM (optional) */127		I2C_BOARD_INFO("24c32", 0x54),128	},129	{	/* extension module 2 EEPROM (optional) */130		I2C_BOARD_INFO("24c32", 0x55),131	},132	{	/* extension module 3 EEPROM (optional) */133		I2C_BOARD_INFO("24c32", 0x56),134	}135};136 137static ssize_t cp500_get_fpga_version(struct cp500 *cp500, char *buf,138				      size_t max_len)139{140	int n;141 142	if (CP500_IS_CP035(cp500))143		n = scnprintf(buf, max_len, "CP035");144	else if (CP500_IS_CP505(cp500))145		n = scnprintf(buf, max_len, "CP505");146	else147		n = scnprintf(buf, max_len, "CP500");148 149	n += scnprintf(buf + n, max_len - n, "_FPGA_%d.%02d",150		       cp500->version.major, cp500->version.minor);151 152	/* test versions have test bit set */153	if (cp500->version.build & CP500_BUILD_TEST)154		n += scnprintf(buf + n, max_len - n, "Test%d",155			       cp500->version.build & ~CP500_BUILD_TEST);156 157	n += scnprintf(buf + n, max_len - n, "\n");158 159	return n;160}161 162static ssize_t version_show(struct device *dev, struct device_attribute *attr,163			    char *buf)164{165	struct cp500 *cp500 = dev_get_drvdata(dev);166 167	return cp500_get_fpga_version(cp500, buf, PAGE_SIZE);168}169static DEVICE_ATTR_RO(version);170 171static ssize_t keep_cfg_show(struct device *dev, struct device_attribute *attr,172			     char *buf)173{174	struct cp500 *cp500 = dev_get_drvdata(dev);175	unsigned long keep_cfg = 1;176 177	/*178	 * FPGA configuration stream is kept during reset when RECONFIG bit is179	 * zero180	 */181	if (ioread8(cp500->system_startup_addr + CP500_RECONFIG_REG) &182		CP500_RECFG_REQ)183		keep_cfg = 0;184 185	return sysfs_emit(buf, "%lu\n", keep_cfg);186}187 188static ssize_t keep_cfg_store(struct device *dev, struct device_attribute *attr,189			      const char *buf, size_t count)190{191	struct cp500 *cp500 = dev_get_drvdata(dev);192	unsigned long keep_cfg;193 194	if (kstrtoul(buf, 10, &keep_cfg) < 0)195		return -EINVAL;196 197	/*198	 * In normal operation "keep_cfg" is "1". This means that the FPGA keeps199	 * its configuration stream during a reset.200	 * In case of a firmware update of the FPGA, the configuration stream201	 * needs to be reloaded. This can be done without a powercycle by202	 * writing a "0" into the "keep_cfg" attribute. After a reset/reboot th203	 * new configuration stream will be loaded.204	 */205	if (keep_cfg)206		iowrite8(0, cp500->system_startup_addr + CP500_RECONFIG_REG);207	else208		iowrite8(CP500_RECFG_REQ,209			 cp500->system_startup_addr + CP500_RECONFIG_REG);210 211	return count;212}213static DEVICE_ATTR_RW(keep_cfg);214 215static struct attribute *cp500_attrs[] = {216	&dev_attr_version.attr,217	&dev_attr_keep_cfg.attr,218	NULL219};220ATTRIBUTE_GROUPS(cp500);221 222static void cp500_i2c_release(struct device *dev)223{224	struct keba_i2c_auxdev *i2c =225		container_of(dev, struct keba_i2c_auxdev, auxdev.dev);226 227	kfree(i2c);228}229 230static int cp500_register_i2c(struct cp500 *cp500)231{232	int retval;233 234	cp500->i2c = kzalloc(sizeof(*cp500->i2c), GFP_KERNEL);235	if (!cp500->i2c)236		return -ENOMEM;237 238	cp500->i2c->auxdev.name = "i2c";239	cp500->i2c->auxdev.id = 0;240	cp500->i2c->auxdev.dev.release = cp500_i2c_release;241	cp500->i2c->auxdev.dev.parent = &cp500->pci_dev->dev;242	cp500->i2c->io = (struct resource) {243		 /* I2C register area */244		 .start = (resource_size_t) cp500->sys_hwbase +245			  cp500->devs->i2c.offset,246		 .end   = (resource_size_t) cp500->sys_hwbase +247			  cp500->devs->i2c.offset +248			  cp500->devs->i2c.size - 1,249		 .flags = IORESOURCE_MEM,250	};251	cp500->i2c->info_size = ARRAY_SIZE(cp500_i2c_info);252	cp500->i2c->info = cp500_i2c_info;253 254	retval = auxiliary_device_init(&cp500->i2c->auxdev);255	if (retval) {256		kfree(cp500->i2c);257		cp500->i2c = NULL;258 259		return retval;260	}261	retval = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");262	if (retval) {263		auxiliary_device_uninit(&cp500->i2c->auxdev);264		cp500->i2c = NULL;265 266		return retval;267	}268 269	return 0;270}271 272static void cp500_register_auxiliary_devs(struct cp500 *cp500)273{274	struct device *dev = &cp500->pci_dev->dev;275 276	if (cp500_register_i2c(cp500))277		dev_warn(dev, "Failed to register i2c!\n");278}279 280static void cp500_unregister_dev(struct auxiliary_device *auxdev)281{282	auxiliary_device_delete(auxdev);283	auxiliary_device_uninit(auxdev);284}285 286static void cp500_unregister_auxiliary_devs(struct cp500 *cp500)287{288 289	if (cp500->i2c) {290		cp500_unregister_dev(&cp500->i2c->auxdev);291		cp500->i2c = NULL;292	}293}294 295static irqreturn_t cp500_axi_handler(int irq, void *dev)296{297	struct cp500 *cp500 = dev;298	u32 axi_address = ioread32(cp500->system_startup_addr + CP500_AXI_REG);299 300	/*301	 * FPGA signals AXI response error, print AXI address to indicate which302	 * IP core was affected303	 */304	dev_err(&cp500->pci_dev->dev, "AXI response error at 0x%08x\n",305		axi_address);306 307	return IRQ_HANDLED;308}309 310static int cp500_enable(struct cp500 *cp500)311{312	int axi_irq = -1;313	int ret;314 315	if (cp500->msix_num > CP500_NUM_MSIX_NO_AXI) {316		axi_irq = pci_irq_vector(cp500->pci_dev, CP500_AXI_MSIX);317		ret = request_irq(axi_irq, cp500_axi_handler, 0,318				  CP500, cp500);319		if (ret != 0) {320			dev_err(&cp500->pci_dev->dev,321				"Failed to register AXI response error!\n");322			return ret;323		}324	}325 326	return 0;327}328 329static void cp500_disable(struct cp500 *cp500)330{331	int axi_irq;332 333	if (cp500->msix_num > CP500_NUM_MSIX_NO_AXI) {334		axi_irq = pci_irq_vector(cp500->pci_dev, CP500_AXI_MSIX);335		free_irq(axi_irq, cp500);336	}337}338 339static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)340{341	struct device *dev = &pci_dev->dev;342	struct resource startup;343	struct cp500 *cp500;344	u32 cp500_vers;345	char buf[64];346	int ret;347 348	cp500 = devm_kzalloc(dev, sizeof(*cp500), GFP_KERNEL);349	if (!cp500)350		return -ENOMEM;351	cp500->pci_dev = pci_dev;352	cp500->sys_hwbase = pci_resource_start(pci_dev, CP500_SYS_BAR);353	cp500->ecm_hwbase = pci_resource_start(pci_dev, CP500_ECM_BAR);354	if (!cp500->sys_hwbase || !cp500->ecm_hwbase)355		return -ENODEV;356 357	if (CP500_IS_CP035(cp500))358		cp500->devs = &cp035_devices;359	else if (CP500_IS_CP505(cp500))360		cp500->devs = &cp505_devices;361	else if (CP500_IS_CP520(cp500))362		cp500->devs = &cp520_devices;363	else364		return -ENODEV;365 366	ret = pci_enable_device(pci_dev);367	if (ret)368		return ret;369	pci_set_master(pci_dev);370 371	startup = *pci_resource_n(pci_dev, CP500_SYS_BAR);372	startup.end = startup.start + cp500->devs->startup.size - 1;373	cp500->system_startup_addr = devm_ioremap_resource(&pci_dev->dev,374							   &startup);375	if (IS_ERR(cp500->system_startup_addr)) {376		ret = PTR_ERR(cp500->system_startup_addr);377		goto out_disable;378	}379 380	cp500->msix_num = pci_alloc_irq_vectors(pci_dev, CP500_NUM_MSIX_NO_MMI,381						CP500_NUM_MSIX, PCI_IRQ_MSIX);382	if (cp500->msix_num < CP500_NUM_MSIX_NO_MMI) {383		dev_err(&pci_dev->dev,384			"Hardware does not support enough MSI-X interrupts\n");385		ret = -ENODEV;386		goto out_disable;387	}388 389	cp500_vers = ioread32(cp500->system_startup_addr + CP500_VERSION_REG);390	cp500->version.major = (cp500_vers & 0xff);391	cp500->version.minor = (cp500_vers >> 8) & 0xff;392	cp500->version.build = (cp500_vers >> 16) & 0xffff;393	cp500_get_fpga_version(cp500, buf, sizeof(buf));394 395	dev_info(&pci_dev->dev, "FPGA version %s", buf);396 397	pci_set_drvdata(pci_dev, cp500);398 399 400	ret = cp500_enable(cp500);401	if (ret != 0)402		goto out_free_irq;403 404	cp500_register_auxiliary_devs(cp500);405 406	return 0;407 408out_free_irq:409	pci_free_irq_vectors(pci_dev);410out_disable:411	pci_clear_master(pci_dev);412	pci_disable_device(pci_dev);413 414	return ret;415}416 417static void cp500_remove(struct pci_dev *pci_dev)418{419	struct cp500 *cp500 = pci_get_drvdata(pci_dev);420 421	cp500_unregister_auxiliary_devs(cp500);422 423	cp500_disable(cp500);424 425	pci_set_drvdata(pci_dev, 0);426 427	pci_free_irq_vectors(pci_dev);428 429	pci_clear_master(pci_dev);430	pci_disable_device(pci_dev);431}432 433static struct pci_device_id cp500_ids[] = {434	{ PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP035) },435	{ PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP505) },436	{ PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP520) },437	{ }438};439MODULE_DEVICE_TABLE(pci, cp500_ids);440 441static struct pci_driver cp500_driver = {442	.name = CP500,443	.id_table = cp500_ids,444	.probe = cp500_probe,445	.remove = cp500_remove,446	.dev_groups = cp500_groups,447};448module_pci_driver(cp500_driver);449 450MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>");451MODULE_DESCRIPTION("KEBA CP500 system FPGA driver");452MODULE_LICENSE("GPL");453