Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

misc: keba: Add SPI controller device

Add support for the SPI controller auxiliary device. This enables access
to the SPI flash of the FPGA and some other SPI devices.

The actual list of SPI devices is detected by reading some bits out of
the previously registered I2C EEPROM.

Signed-off-by: Gerhard Engleder <eg@keba.com>
Link: https://lore.kernel.org/r/20241011191257.19702-4-gerhard@engleder-embedded.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Gerhard Engleder and committed by
Greg Kroah-Hartman
79484830 14afb749

+219 -15
+204 -15
drivers/misc/keba/cp500.c
··· 12 12 #include <linux/i2c.h> 13 13 #include <linux/misc/keba.h> 14 14 #include <linux/module.h> 15 + #include <linux/mtd/partitions.h> 16 + #include <linux/nvmem-consumer.h> 15 17 #include <linux/pci.h> 18 + #include <linux/spi/flash.h> 19 + #include <linux/spi/spi.h> 16 20 17 21 #define CP500 "cp500" 18 22 ··· 47 43 48 44 /* EEPROM */ 49 45 #define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom" 46 + #define CP500_EEPROM_DA_OFFSET 0x016F 47 + #define CP500_EEPROM_DA_ESC_TYPE_MASK 0x01 48 + #define CP500_EEPROM_ESC_LAN9252 0x00 49 + #define CP500_EEPROM_ESC_ET1100 0x01 50 + 51 + /* SPI flash running at full speed */ 52 + #define CP500_FLASH_HZ (33 * 1000 * 1000) 53 + 54 + /* LAN9252 */ 55 + #define CP500_LAN9252_HZ (10 * 1000 * 1000) 50 56 51 57 #define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035) 52 58 #define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505) ··· 69 55 70 56 struct cp500_devs { 71 57 struct cp500_dev_info startup; 58 + struct cp500_dev_info spi; 72 59 struct cp500_dev_info i2c; 73 60 }; 74 61 75 62 /* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */ 76 63 static struct cp500_devs cp035_devices = { 77 - .startup = { 0x0000, SZ_4K }, 78 - .i2c = { 0x4000, SZ_4K }, 64 + .startup = { 0x0000, SZ_4K }, 65 + .spi = { 0x1000, SZ_4K }, 66 + .i2c = { 0x4000, SZ_4K }, 79 67 }; 80 68 81 69 /* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */ 82 70 static struct cp500_devs cp505_devices = { 83 - .startup = { 0x0000, SZ_4K }, 84 - .i2c = { 0x5000, SZ_4K }, 71 + .startup = { 0x0000, SZ_4K }, 72 + .spi = { 0x4000, SZ_4K }, 73 + .i2c = { 0x5000, SZ_4K }, 85 74 }; 86 75 87 76 /* list of devices within FPGA of CP520 family (CP520, CP530) */ 88 77 static struct cp500_devs cp520_devices = { 89 - .startup = { 0x0000, SZ_4K }, 90 - .i2c = { 0x5000, SZ_4K }, 78 + .startup = { 0x0000, SZ_4K }, 79 + .spi = { 0x4000, SZ_4K }, 80 + .i2c = { 0x5000, SZ_4K }, 91 81 }; 92 82 93 83 struct cp500 { ··· 103 85 int minor; 104 86 int build; 105 87 } version; 88 + struct notifier_block nvmem_notifier; 89 + atomic_t nvmem_notified; 106 90 107 91 /* system FPGA BAR */ 108 92 resource_size_t sys_hwbase; 93 + struct keba_spi_auxdev *spi; 109 94 struct keba_i2c_auxdev *i2c; 110 95 111 96 /* ECM EtherCAT BAR */ ··· 118 97 }; 119 98 120 99 /* I2C devices */ 100 + #define CP500_EEPROM_ADDR 0x50 121 101 static struct i2c_board_info cp500_i2c_info[] = { 122 102 { /* temperature sensor */ 123 103 I2C_BOARD_INFO("emc1403", 0x4c), ··· 129 107 * CP505 family: bridge board 130 108 * CP520 family: carrier board 131 109 */ 132 - I2C_BOARD_INFO("24c32", 0x50), 110 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR), 133 111 .dev_name = CP500_HW_CPU_EEPROM_NAME, 134 112 }, 135 113 { /* interface board EEPROM */ 136 - I2C_BOARD_INFO("24c32", 0x51), 114 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 1), 137 115 }, 138 116 { /* 139 117 * EEPROM (optional) 140 118 * CP505 family: CPU board 141 119 * CP520 family: MMI board 142 120 */ 143 - I2C_BOARD_INFO("24c32", 0x52), 121 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 2), 144 122 }, 145 123 { /* extension module 0 EEPROM (optional) */ 146 - I2C_BOARD_INFO("24c32", 0x53), 124 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 3), 147 125 }, 148 126 { /* extension module 1 EEPROM (optional) */ 149 - I2C_BOARD_INFO("24c32", 0x54), 127 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 4), 150 128 }, 151 129 { /* extension module 2 EEPROM (optional) */ 152 - I2C_BOARD_INFO("24c32", 0x55), 130 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 5), 153 131 }, 154 132 { /* extension module 3 EEPROM (optional) */ 155 - I2C_BOARD_INFO("24c32", 0x56), 133 + I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 6), 134 + } 135 + }; 136 + 137 + /* SPI devices */ 138 + static struct mtd_partition cp500_partitions[] = { 139 + { 140 + .name = "system-flash-parts", 141 + .size = MTDPART_SIZ_FULL, 142 + .offset = 0, 143 + .mask_flags = 0 144 + } 145 + }; 146 + static const struct flash_platform_data cp500_w25q32 = { 147 + .type = "w25q32", 148 + .name = "system-flash", 149 + .parts = cp500_partitions, 150 + .nr_parts = ARRAY_SIZE(cp500_partitions), 151 + }; 152 + static const struct flash_platform_data cp500_m25p16 = { 153 + .type = "m25p16", 154 + .name = "system-flash", 155 + .parts = cp500_partitions, 156 + .nr_parts = ARRAY_SIZE(cp500_partitions), 157 + }; 158 + static struct spi_board_info cp500_spi_info[] = { 159 + { /* system FPGA configuration bitstream flash */ 160 + .modalias = "m25p80", 161 + .platform_data = &cp500_m25p16, 162 + .max_speed_hz = CP500_FLASH_HZ, 163 + .chip_select = 0, 164 + .mode = SPI_MODE_3, 165 + }, { /* LAN9252 EtherCAT slave controller */ 166 + .modalias = "lan9252", 167 + .platform_data = NULL, 168 + .max_speed_hz = CP500_LAN9252_HZ, 169 + .chip_select = 1, 170 + .mode = SPI_MODE_3, 156 171 } 157 172 }; 158 173 ··· 328 269 return 0; 329 270 } 330 271 272 + static void cp500_spi_release(struct device *dev) 273 + { 274 + struct keba_spi_auxdev *spi = 275 + container_of(dev, struct keba_spi_auxdev, auxdev.dev); 276 + 277 + kfree(spi); 278 + } 279 + 280 + static int cp500_register_spi(struct cp500 *cp500, u8 esc_type) 281 + { 282 + int info_size; 283 + int ret; 284 + 285 + cp500->spi = kzalloc(sizeof(*cp500->spi), GFP_KERNEL); 286 + if (!cp500->spi) 287 + return -ENOMEM; 288 + 289 + if (CP500_IS_CP035(cp500)) 290 + cp500_spi_info[0].platform_data = &cp500_w25q32; 291 + if (esc_type == CP500_EEPROM_ESC_LAN9252) 292 + info_size = ARRAY_SIZE(cp500_spi_info); 293 + else 294 + info_size = ARRAY_SIZE(cp500_spi_info) - 1; 295 + 296 + cp500->spi->auxdev.name = "spi"; 297 + cp500->spi->auxdev.id = 0; 298 + cp500->spi->auxdev.dev.release = cp500_spi_release; 299 + cp500->spi->auxdev.dev.parent = &cp500->pci_dev->dev; 300 + cp500->spi->io = (struct resource) { 301 + /* SPI register area */ 302 + .start = (resource_size_t) cp500->sys_hwbase + 303 + cp500->devs->spi.offset, 304 + .end = (resource_size_t) cp500->sys_hwbase + 305 + cp500->devs->spi.offset + 306 + cp500->devs->spi.size - 1, 307 + .flags = IORESOURCE_MEM, 308 + }; 309 + cp500->spi->info_size = info_size; 310 + cp500->spi->info = cp500_spi_info; 311 + 312 + ret = auxiliary_device_init(&cp500->spi->auxdev); 313 + if (ret) { 314 + kfree(cp500->spi); 315 + cp500->spi = NULL; 316 + 317 + return ret; 318 + } 319 + ret = __auxiliary_device_add(&cp500->spi->auxdev, "keba"); 320 + if (ret) { 321 + auxiliary_device_uninit(&cp500->spi->auxdev); 322 + cp500->spi = NULL; 323 + 324 + return ret; 325 + } 326 + 327 + return 0; 328 + } 329 + 330 + static int cp500_nvmem_match(struct device *dev, const void *data) 331 + { 332 + const struct cp500 *cp500 = data; 333 + struct i2c_client *client; 334 + 335 + /* match only CPU EEPROM below the cp500 device */ 336 + dev = dev->parent; 337 + client = i2c_verify_client(dev); 338 + if (!client || client->addr != CP500_EEPROM_ADDR) 339 + return 0; 340 + while ((dev = dev->parent)) 341 + if (dev == &cp500->pci_dev->dev) 342 + return 1; 343 + 344 + return 0; 345 + } 346 + 347 + static int cp500_nvmem(struct notifier_block *nb, unsigned long action, 348 + void *data) 349 + { 350 + struct nvmem_device *nvmem; 351 + struct cp500 *cp500; 352 + struct device *dev; 353 + int notified; 354 + u8 esc_type; 355 + int ret; 356 + 357 + if (action != NVMEM_ADD) 358 + return NOTIFY_DONE; 359 + cp500 = container_of(nb, struct cp500, nvmem_notifier); 360 + dev = &cp500->pci_dev->dev; 361 + 362 + /* process CPU EEPROM content only once */ 363 + notified = atomic_read(&cp500->nvmem_notified); 364 + if (notified) 365 + return NOTIFY_DONE; 366 + nvmem = nvmem_device_find(cp500, cp500_nvmem_match); 367 + if (IS_ERR_OR_NULL(nvmem)) 368 + return NOTIFY_DONE; 369 + if (!atomic_try_cmpxchg_relaxed(&cp500->nvmem_notified, &notified, 1)) { 370 + nvmem_device_put(nvmem); 371 + 372 + return NOTIFY_DONE; 373 + } 374 + 375 + ret = nvmem_device_read(nvmem, CP500_EEPROM_DA_OFFSET, sizeof(esc_type), 376 + (void *)&esc_type); 377 + nvmem_device_put(nvmem); 378 + if (ret != sizeof(esc_type)) { 379 + dev_warn(dev, "Failed to read device assembly!\n"); 380 + 381 + return NOTIFY_DONE; 382 + } 383 + esc_type &= CP500_EEPROM_DA_ESC_TYPE_MASK; 384 + 385 + if (cp500_register_spi(cp500, esc_type)) 386 + dev_warn(dev, "Failed to register SPI!\n"); 387 + 388 + return NOTIFY_OK; 389 + } 390 + 331 391 static void cp500_register_auxiliary_devs(struct cp500 *cp500) 332 392 { 333 393 struct device *dev = &cp500->pci_dev->dev; ··· 463 285 464 286 static void cp500_unregister_auxiliary_devs(struct cp500 *cp500) 465 287 { 466 - 288 + if (cp500->spi) { 289 + cp500_unregister_dev(&cp500->spi->auxdev); 290 + cp500->spi = NULL; 291 + } 467 292 if (cp500->i2c) { 468 293 cp500_unregister_dev(&cp500->i2c->auxdev); 469 294 cp500->i2c = NULL; ··· 577 396 578 397 pci_set_drvdata(pci_dev, cp500); 579 398 399 + cp500->nvmem_notifier.notifier_call = cp500_nvmem; 400 + ret = nvmem_register_notifier(&cp500->nvmem_notifier); 401 + if (ret != 0) 402 + goto out_free_irq; 580 403 581 404 ret = cp500_enable(cp500); 582 405 if (ret != 0) 583 - goto out_free_irq; 406 + goto out_unregister_nvmem; 584 407 585 408 cp500_register_auxiliary_devs(cp500); 586 409 587 410 return 0; 588 411 412 + out_unregister_nvmem: 413 + nvmem_unregister_notifier(&cp500->nvmem_notifier); 589 414 out_free_irq: 590 415 pci_free_irq_vectors(pci_dev); 591 416 out_disable: ··· 608 421 cp500_unregister_auxiliary_devs(cp500); 609 422 610 423 cp500_disable(cp500); 424 + 425 + nvmem_unregister_notifier(&cp500->nvmem_notifier); 611 426 612 427 pci_set_drvdata(pci_dev, 0); 613 428
+15
include/linux/misc/keba.h
··· 7 7 #include <linux/auxiliary_bus.h> 8 8 9 9 struct i2c_board_info; 10 + struct spi_board_info; 10 11 11 12 /** 12 13 * struct keba_i2c_auxdev - KEBA I2C auxiliary device ··· 21 20 struct resource io; 22 21 int info_size; 23 22 struct i2c_board_info *info; 23 + }; 24 + 25 + /** 26 + * struct keba_spi_auxdev - KEBA SPI auxiliary device 27 + * @auxdev: auxiliary device object 28 + * @io: address range of SPI controller IO memory 29 + * @info_size: number of SPI devices to be probed 30 + * @info: SPI devices to be probed 31 + */ 32 + struct keba_spi_auxdev { 33 + struct auxiliary_device auxdev; 34 + struct resource io; 35 + int info_size; 36 + struct spi_board_info *info; 24 37 }; 25 38 26 39 #endif /* _LINUX_MISC_KEBA_H */