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: Support EEPROM sections as separate devices

The main EEPROM of KEBA CP500 devices is divided into two sections. One
section for type label data like device name, order number, serial
number and so on. The second section is reserved for arbitrary data
stored by the user.

The two sections have a defined range. The first 3 kB for the type label
and the remaining 1 kB for user data. The type label is written during
production and can fill up the whole 3 kB. Thus, the range is fixed and
cannot be changed dynamically.

The two sections cannot be presented as NVMEM cells. A NVMEM cell is
always read and written at once, because the data presented to the user
can differ from the data stored in the physical NVMEM cell. Thus, NVMEM
cells would lead to reading 3 kB for every type label access, even if
only the device name is read. So performance would suffer. But it is
also an indication that NVMEM cells are designed for small data cells
within NVMEM devices.

Register separate NVMEM devices for every section. This enables safe
access to every section. Also different access rights are then possible.

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

authored by

Gerhard Engleder and committed by
Greg Kroah-Hartman
c6576d91 366898e7

+102 -3
+102 -3
drivers/misc/keba/cp500.c
··· 14 14 #include <linux/module.h> 15 15 #include <linux/mtd/partitions.h> 16 16 #include <linux/nvmem-consumer.h> 17 + #include <linux/nvmem-provider.h> 17 18 #include <linux/pci.h> 18 19 #include <linux/spi/flash.h> 19 20 #include <linux/spi/spi.h> ··· 47 46 #define CP500_NUM_MSIX_NO_AXI 3 48 47 49 48 /* EEPROM */ 50 - #define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom" 51 49 #define CP500_EEPROM_DA_OFFSET 0x016F 52 50 #define CP500_EEPROM_DA_ESC_TYPE_MASK 0x01 53 51 #define CP500_EEPROM_ESC_LAN9252 0x00 54 52 #define CP500_EEPROM_ESC_ET1100 0x01 53 + #define CP500_EEPROM_CPU_NAME "cpu_eeprom" 54 + #define CP500_EEPROM_CPU_OFFSET 0 55 + #define CP500_EEPROM_CPU_SIZE 3072 56 + #define CP500_EEPROM_USER_NAME "user_eeprom" 57 + #define CP500_EEPROM_USER_OFFSET 3072 58 + #define CP500_EEPROM_USER_SIZE 1024 55 59 56 60 /* SPI flash running at full speed */ 57 61 #define CP500_FLASH_HZ (33 * 1000 * 1000) ··· 100 94 .i2c = { 0x5000, SZ_4K }, 101 95 }; 102 96 97 + struct cp500_nvmem { 98 + struct nvmem_device *nvmem; 99 + unsigned int offset; 100 + }; 101 + 103 102 struct cp500 { 104 103 struct pci_dev *pci_dev; 105 104 struct cp500_devs *devs; ··· 125 114 /* ECM EtherCAT BAR */ 126 115 resource_size_t ecm_hwbase; 127 116 117 + /* NVMEM devices */ 118 + struct cp500_nvmem nvmem_cpu; 119 + struct cp500_nvmem nvmem_user; 120 + 128 121 void __iomem *system_startup_addr; 129 122 }; 130 123 ··· 145 130 * CP520 family: carrier board 146 131 */ 147 132 I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR), 148 - .dev_name = CP500_HW_CPU_EEPROM_NAME, 149 133 }, 150 134 { /* interface board EEPROM */ 151 135 I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 1), ··· 400 386 return 0; 401 387 } 402 388 389 + static int cp500_nvmem_read(void *priv, unsigned int offset, void *val, 390 + size_t bytes) 391 + { 392 + struct cp500_nvmem *nvmem = priv; 393 + int ret; 394 + 395 + ret = nvmem_device_read(nvmem->nvmem, nvmem->offset + offset, bytes, 396 + val); 397 + if (ret != bytes) 398 + return ret; 399 + 400 + return 0; 401 + } 402 + 403 + static int cp500_nvmem_write(void *priv, unsigned int offset, void *val, 404 + size_t bytes) 405 + { 406 + struct cp500_nvmem *nvmem = priv; 407 + int ret; 408 + 409 + ret = nvmem_device_write(nvmem->nvmem, nvmem->offset + offset, bytes, 410 + val); 411 + if (ret != bytes) 412 + return ret; 413 + 414 + return 0; 415 + } 416 + 417 + static int cp500_nvmem_register(struct cp500 *cp500, struct nvmem_device *nvmem) 418 + { 419 + struct device *dev = &cp500->pci_dev->dev; 420 + struct nvmem_config nvmem_config = {}; 421 + struct nvmem_device *tmp; 422 + 423 + /* 424 + * The main EEPROM of CP500 devices is logically split into two EEPROMs. 425 + * The first logical EEPROM with 3 kB contains the type label which is 426 + * programmed during production of the device. The second logical EEPROM 427 + * with 1 kB is not programmed during production and can be used for 428 + * arbitrary user data. 429 + */ 430 + 431 + nvmem_config.dev = dev; 432 + nvmem_config.owner = THIS_MODULE; 433 + nvmem_config.id = NVMEM_DEVID_NONE; 434 + nvmem_config.type = NVMEM_TYPE_EEPROM; 435 + nvmem_config.root_only = true; 436 + nvmem_config.reg_read = cp500_nvmem_read; 437 + nvmem_config.reg_write = cp500_nvmem_write; 438 + 439 + cp500->nvmem_cpu.nvmem = nvmem; 440 + cp500->nvmem_cpu.offset = CP500_EEPROM_CPU_OFFSET; 441 + nvmem_config.name = CP500_EEPROM_CPU_NAME; 442 + nvmem_config.size = CP500_EEPROM_CPU_SIZE; 443 + nvmem_config.priv = &cp500->nvmem_cpu; 444 + tmp = devm_nvmem_register(dev, &nvmem_config); 445 + if (IS_ERR(tmp)) 446 + return PTR_ERR(tmp); 447 + 448 + cp500->nvmem_user.nvmem = nvmem; 449 + cp500->nvmem_user.offset = CP500_EEPROM_USER_OFFSET; 450 + nvmem_config.name = CP500_EEPROM_USER_NAME; 451 + nvmem_config.size = CP500_EEPROM_USER_SIZE; 452 + nvmem_config.priv = &cp500->nvmem_user; 453 + tmp = devm_nvmem_register(dev, &nvmem_config); 454 + if (IS_ERR(tmp)) 455 + return PTR_ERR(tmp); 456 + 457 + return 0; 458 + } 459 + 403 460 static int cp500_nvmem_match(struct device *dev, const void *data) 404 461 { 405 462 const struct cp500 *cp500 = data; ··· 486 401 return 1; 487 402 488 403 return 0; 404 + } 405 + 406 + static void cp500_devm_nvmem_put(void *data) 407 + { 408 + struct nvmem_device *nvmem = data; 409 + 410 + nvmem_device_put(nvmem); 489 411 } 490 412 491 413 static int cp500_nvmem(struct notifier_block *nb, unsigned long action, ··· 523 431 return NOTIFY_DONE; 524 432 } 525 433 434 + ret = devm_add_action_or_reset(dev, cp500_devm_nvmem_put, nvmem); 435 + if (ret) 436 + return ret; 437 + 438 + ret = cp500_nvmem_register(cp500, nvmem); 439 + if (ret) 440 + return ret; 441 + 526 442 ret = nvmem_device_read(nvmem, CP500_EEPROM_DA_OFFSET, sizeof(esc_type), 527 443 (void *)&esc_type); 528 - nvmem_device_put(nvmem); 529 444 if (ret != sizeof(esc_type)) { 530 445 dev_warn(dev, "Failed to read device assembly!\n"); 531 446