From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 13 Jul 2023 18:29:19 +0200 Subject: [PATCH] nvmem: core: support "mac-base" fixed layout cells Fixed layout binding allows specifying "mac-base" NVMEM cells. It's used for base MAC address (that can be used for calculating relative addresses). It can be stored in a raw binary format or as an ASCII string. --- --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -2,6 +2,7 @@ menuconfig NVMEM bool "NVMEM Support" imply NVMEM_LAYOUTS + select GENERIC_NET_UTILS help Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -7,9 +7,12 @@ */ #include +#include +#include #include #include #include +#include #include #include #include @@ -796,6 +799,62 @@ static int nvmem_validate_keepouts(struc return 0; } +static int nvmem_mac_base_raw_read(void *context, const char *id, int index, unsigned int offset, + void *buf, size_t bytes) +{ + if (WARN_ON(bytes != ETH_ALEN)) + return -EINVAL; + + if (index) + eth_addr_add(buf, index); + + return 0; +} + +static int nvmem_mac_base_ascii_read(void *context, const char *id, int index, unsigned int offset, + void *buf, size_t bytes) +{ + u8 mac[ETH_ALEN]; + + if (WARN_ON(bytes != 3 * ETH_ALEN - 1)) + return -EINVAL; + + if (!mac_pton(buf, mac)) + return -EINVAL; + + if (index) + eth_addr_add(mac, index); + + ether_addr_copy(buf, mac); + + return 0; +} + +static int nvmem_mac_base_hex_read(void *context, const char *id, int index, unsigned int offset, + void *buf, size_t bytes) +{ + u8 mac[ETH_ALEN], *hexstr; + int i; + + if (WARN_ON(bytes != 2 * ETH_ALEN)) + return -EINVAL; + + hexstr = (u8 *)buf; + for (i = 0; i < ETH_ALEN; i++) { + if (!isxdigit(hexstr[i * 2]) || !isxdigit(hexstr[i * 2 + 1])) + return -EINVAL; + + mac[i] = (hex_to_bin(hexstr[i * 2]) << 4) | hex_to_bin(hexstr[i * 2 + 1]); + } + + if (index) + eth_addr_add(mac, index); + + ether_addr_copy(buf, mac); + + return 0; +} + static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { struct device *dev = &nvmem->dev; @@ -835,6 +894,25 @@ static int nvmem_add_cells_from_dt(struc if (nvmem->fixup_dt_cell_info) nvmem->fixup_dt_cell_info(nvmem, &info); + if (of_device_is_compatible(np, "fixed-layout")) { + if (of_device_is_compatible(child, "mac-base")) { + if (info.bytes == ETH_ALEN) { + info.raw_len = info.bytes; + info.bytes = ETH_ALEN; + info.read_post_process = nvmem_mac_base_raw_read; + } else if (info.bytes == 2 * ETH_ALEN) { + info.raw_len = info.bytes; + info.bytes = ETH_ALEN; + info.read_post_process = nvmem_mac_base_hex_read; + } else if (info.bytes == 3 * ETH_ALEN - 1) { + info.raw_len = info.bytes; + info.bytes = ETH_ALEN; + info.read_post_process = nvmem_mac_base_ascii_read; + } + + } + } + ret = nvmem_add_one_cell(nvmem, &info); kfree(info.name); if (ret) {