From a2e503b82e568f0c05908295cb5cabd397f3622b Mon Sep 17 00:00:00 2001 From: ludiazv Date: Thu, 23 May 2024 09:55:55 +0200 Subject: [PATCH] fix/improve MAC address management --- ...0001-drv-fix-MAC-address-for-UWE5622.patch | 610 ++++++++++++++++++ .../sunxi-kmeta/bsp/uwe5622/uwe5622-6_6.scc | 3 + .../bsp/uwe5622/uwe5622-fragment.cfg | 2 + 3 files changed, 615 insertions(+) create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/0001-drv-fix-MAC-address-for-UWE5622.patch diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/0001-drv-fix-MAC-address-for-UWE5622.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/0001-drv-fix-MAC-address-for-UWE5622.patch new file mode 100644 index 0000000..db4bbe0 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/0001-drv-fix-MAC-address-for-UWE5622.patch @@ -0,0 +1,610 @@ +From 5e8062c5f6500526633934006c2858812961f6f4 Mon Sep 17 00:00:00 2001 +From: OpenEmbedded +Date: Wed, 22 May 2024 15:36:46 +0200 +Subject: [PATCH] drv fix MAC address for UWE5622 + +--- + drivers/misc/Kconfig | 1 + + drivers/misc/Makefile | 1 + + drivers/misc/sunxi-addr/Kconfig | 7 + + drivers/misc/sunxi-addr/Makefile | 6 + + drivers/misc/sunxi-addr/sha256.c | 178 +++++++++++++ + drivers/misc/sunxi-addr/sunxi-addr.c | 358 +++++++++++++++++++++++++++ + 6 files changed, 551 insertions(+) + create mode 100644 drivers/misc/sunxi-addr/Kconfig + create mode 100644 drivers/misc/sunxi-addr/Makefile + create mode 100644 drivers/misc/sunxi-addr/sha256.c + create mode 100644 drivers/misc/sunxi-addr/sunxi-addr.c + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index cadd4a820..605e4d2ba 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -579,4 +579,5 @@ source "drivers/misc/cardreader/Kconfig" + source "drivers/misc/uacce/Kconfig" + source "drivers/misc/pvpanic/Kconfig" + source "drivers/misc/mchp_pci1xxxx/Kconfig" ++source "drivers/misc/sunxi-addr/Kconfig" + endmenu +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index f2a4d1ff6..06e857d70 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -67,3 +67,4 @@ obj-$(CONFIG_TMR_MANAGER) += xilinx_tmr_manager.o + obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o + obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o + obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o ++obj-$(CONFIG_SUNXI_ADDR_MGT) += sunxi-addr/ +diff --git a/drivers/misc/sunxi-addr/Kconfig b/drivers/misc/sunxi-addr/Kconfig +new file mode 100644 +index 000000000..d7d0ca3bd +--- /dev/null ++++ b/drivers/misc/sunxi-addr/Kconfig +@@ -0,0 +1,7 @@ ++config SUNXI_ADDR_MGT ++ tristate "Allwinner Network MAC Addess Manager" ++ depends on BT || ETHERNET || WLAN ++ depends on NVMEM_SUNXI_SID ++ help ++ allwinner network mac address management ++ +diff --git a/drivers/misc/sunxi-addr/Makefile b/drivers/misc/sunxi-addr/Makefile +new file mode 100644 +index 000000000..9bafcece5 +--- /dev/null ++++ b/drivers/misc/sunxi-addr/Makefile +@@ -0,0 +1,6 @@ ++# ++# Makefile for wifi mac addr manager drivers ++# ++sunxi_addr-objs := sunxi-addr.o sha256.o ++obj-$(CONFIG_SUNXI_ADDR_MGT) += sunxi_addr.o ++ +diff --git a/drivers/misc/sunxi-addr/sha256.c b/drivers/misc/sunxi-addr/sha256.c +new file mode 100644 +index 000000000..78825810c +--- /dev/null ++++ b/drivers/misc/sunxi-addr/sha256.c +@@ -0,0 +1,178 @@ ++/* ++ * Local implement of sha256. ++ * ++ * Copyright (C) 2013 Allwinner. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++#include ++#include ++ ++/****************************** MACROS ******************************/ ++#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b)))) ++#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) ++#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) ++#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22)) ++#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25)) ++#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3)) ++#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10)) ++ ++/**************************** VARIABLES *****************************/ ++static const uint32_t k[64] = { ++ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, ++ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, ++ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, ++ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, ++ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, ++ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, ++ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, ++ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, ++ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, ++ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, ++ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, ++ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, ++ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, ++ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, ++ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, ++ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ++}; ++ ++struct sha256_ctx { ++ uint8_t data[64]; /* current 512-bit chunk of message data, just like a buffer */ ++ uint32_t datalen; /* sign the data length of current chunk */ ++ uint64_t bitlen; /* the bit length of the total message */ ++ uint32_t state[8]; /* store the middle state of hash abstract */ ++}; ++ ++/*********************** FUNCTION DEFINITIONS ***********************/ ++static void sha256_transform(struct sha256_ctx *ctx, const uint8_t *data) ++{ ++ uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; ++ ++ /* initialization */ ++ for (i = 0, j = 0; i < 16; ++i, j += 4) ++ m[i] = (data[j] << 24) | (data[j + 1] << 16) | ++ (data[j + 2] << 8) | (data[j + 3]); ++ for ( ; i < 64; ++i) ++ m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; ++ ++ a = ctx->state[0]; ++ b = ctx->state[1]; ++ c = ctx->state[2]; ++ d = ctx->state[3]; ++ e = ctx->state[4]; ++ f = ctx->state[5]; ++ g = ctx->state[6]; ++ h = ctx->state[7]; ++ ++ for (i = 0; i < 64; ++i) { ++ t1 = h + EP1(e) + CH(e, f, g) + k[i] + m[i]; ++ t2 = EP0(a) + MAJ(a, b, c); ++ h = g; ++ g = f; ++ f = e; ++ e = d + t1; ++ d = c; ++ c = b; ++ b = a; ++ a = t1 + t2; ++ } ++ ++ ctx->state[0] += a; ++ ctx->state[1] += b; ++ ctx->state[2] += c; ++ ctx->state[3] += d; ++ ctx->state[4] += e; ++ ctx->state[5] += f; ++ ctx->state[6] += g; ++ ctx->state[7] += h; ++} ++ ++static void sha256_init(struct sha256_ctx *ctx) ++{ ++ ctx->datalen = 0; ++ ctx->bitlen = 0; ++ ctx->state[0] = 0x6a09e667; ++ ctx->state[1] = 0xbb67ae85; ++ ctx->state[2] = 0x3c6ef372; ++ ctx->state[3] = 0xa54ff53a; ++ ctx->state[4] = 0x510e527f; ++ ctx->state[5] = 0x9b05688c; ++ ctx->state[6] = 0x1f83d9ab; ++ ctx->state[7] = 0x5be0cd19; ++} ++ ++static void sha256_update(struct sha256_ctx *ctx, const uint8_t *data, size_t len) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < len; ++i) { ++ ctx->data[ctx->datalen] = data[i]; ++ ctx->datalen++; ++ if (ctx->datalen == 64) { ++ /* 64 byte = 512 bit means the buffer ctx->data has ++ * fully stored one chunk of message, ++ * so do the sha256 hash map for the current chunk. ++ */ ++ sha256_transform(ctx, ctx->data); ++ ctx->bitlen += 512; ++ ctx->datalen = 0; ++ } ++ } ++} ++ ++static void sha256_final(struct sha256_ctx *ctx, uint8_t *hash) ++{ ++ uint32_t i; ++ ++ i = ctx->datalen; ++ ++ /* Pad whatever data is left in the buffer. */ ++ if (ctx->datalen < 56) { ++ ctx->data[i++] = 0x80; /* pad 10000000 = 0x80 */ ++ while (i < 56) ++ ctx->data[i++] = 0x00; ++ } else { ++ ctx->data[i++] = 0x80; ++ while (i < 64) ++ ctx->data[i++] = 0x00; ++ sha256_transform(ctx, ctx->data); ++ memset(ctx->data, 0, 56); ++ } ++ ++ /* Append to the padding the total message's length in bits and transform. */ ++ ctx->bitlen += ctx->datalen * 8; ++ ctx->data[63] = ctx->bitlen; ++ ctx->data[62] = ctx->bitlen >> 8; ++ ctx->data[61] = ctx->bitlen >> 16; ++ ctx->data[60] = ctx->bitlen >> 24; ++ ctx->data[59] = ctx->bitlen >> 32; ++ ctx->data[58] = ctx->bitlen >> 40; ++ ctx->data[57] = ctx->bitlen >> 48; ++ ctx->data[56] = ctx->bitlen >> 56; ++ sha256_transform(ctx, ctx->data); ++ ++ /* copying the final state to the output hash(use big endian). */ ++ for (i = 0; i < 4; ++i) { ++ hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; ++ hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; ++ } ++} ++ ++int hmac_sha256(const uint8_t *plaintext, ssize_t psize, uint8_t *output) ++{ ++ struct sha256_ctx ctx; ++ ++ sha256_init(&ctx); ++ sha256_update(&ctx, plaintext, psize); ++ sha256_final(&ctx, output); ++ return 0; ++} +diff --git a/drivers/misc/sunxi-addr/sunxi-addr.c b/drivers/misc/sunxi-addr/sunxi-addr.c +new file mode 100644 +index 000000000..3ba0a113f +--- /dev/null ++++ b/drivers/misc/sunxi-addr/sunxi-addr.c +@@ -0,0 +1,358 @@ ++/* ++ * The driver of SUNXI NET MAC ADDR Manager. ++ * ++ * Copyright (C) 2013 Allwinner. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define ADDR_MGT_DBG(fmt, arg...) printk(KERN_DEBUG "[ADDR_MGT] %s: " fmt "\n",\ ++ __func__, ## arg) ++#define ADDR_MGT_ERR(fmt, arg...) printk(KERN_ERR "[ADDR_MGT] %s: " fmt "\n",\ ++ __func__, ## arg) ++ ++#define MODULE_CUR_VERSION "v1.0.9" ++ ++#define MATCH_STR_LEN 20 ++#define ADDR_VAL_LEN 6 ++#define ADDR_STR_LEN 18 ++#define ID_LEN 16 ++#define HASH_LEN 32 ++ ++#define TYPE_ANY 0 ++#define TYPE_BURN 1 ++#define TYPE_IDGEN 2 ++#define TYPE_USER 3 ++#define TYPE_RAND 4 ++ ++#define ADDR_FMT_STR 0 ++#define ADDR_FMT_VAL 1 ++ ++#define IS_TYPE_INVALID(x) ((x < TYPE_ANY) || (x > TYPE_RAND)) ++ ++#define ADDR_CLASS_ATTR_ADD(name) \ ++static ssize_t addr_##name##_show(const struct class *class, \ ++ const struct class_attribute *attr, char *buffer) \ ++{ \ ++ char addr[ADDR_STR_LEN]; \ ++ if (IS_TYPE_INVALID(get_addr_by_name(ADDR_FMT_STR, addr, #name))) \ ++ return 0; \ ++ return sprintf(buffer, "%.17s\n", addr); \ ++} \ ++static ssize_t addr_##name##_store(const struct class *class, \ ++ const struct class_attribute *attr, \ ++ const char *buffer, size_t count) \ ++{ \ ++ if (count != ADDR_STR_LEN) { \ ++ ADDR_MGT_ERR("Length wrong."); \ ++ return -EINVAL; \ ++ } \ ++ set_addr_by_name(TYPE_USER, ADDR_FMT_STR, buffer, #name); \ ++ return count; \ ++} \ ++static CLASS_ATTR_RW(addr_##name); ++ ++struct addr_mgt_info { ++ unsigned int type_def; ++ unsigned int type_cur; ++ unsigned int flag; ++ char *addr; ++ char *name; ++}; ++ ++static struct addr_mgt_info info[] = { ++ {TYPE_ANY, TYPE_ANY, 1, NULL, "wifi"}, ++ {TYPE_ANY, TYPE_ANY, 0, NULL, "bt" }, ++ {TYPE_ANY, TYPE_ANY, 1, NULL, "eth" }, ++}; ++ ++extern int hmac_sha256(const uint8_t *plaintext, ssize_t psize, uint8_t *output); ++extern int sunxi_get_soc_chipid(unsigned char *chipid); ++ ++static int addr_parse(int fmt, const char *addr, int check) ++{ ++ char val_buf[ADDR_VAL_LEN]; ++ char cmp_buf[ADDR_VAL_LEN]; ++ int ret = ADDR_VAL_LEN; ++ ++ if (fmt == ADDR_FMT_STR) ++ ret = sscanf(addr, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &val_buf[0], &val_buf[1], &val_buf[2], ++ &val_buf[3], &val_buf[4], &val_buf[5]); ++ else ++ memcpy(val_buf, addr, ADDR_VAL_LEN); ++ ++ if (ret != ADDR_VAL_LEN) ++ return -1; ++ ++ if (check && (val_buf[0] & 0x3)) ++ return -1; ++ ++ memset(cmp_buf, 0x00, ADDR_VAL_LEN); ++ if (memcmp(val_buf, cmp_buf, ADDR_VAL_LEN) == 0) ++ return -1; ++ ++ memset(cmp_buf, 0xFF, ADDR_VAL_LEN); ++ if (memcmp(val_buf, cmp_buf, ADDR_VAL_LEN) == 0) ++ return -1; ++ ++ return 0; ++} ++ ++static struct addr_mgt_info *addr_find_by_name(char *name) ++{ ++ int i = 0; ++ for (i = 0; i < ARRAY_SIZE(info); i++) { ++ if (strcmp(info[i].name, name) == 0) ++ return &info[i]; ++ } ++ return NULL; ++} ++ ++static int get_addr_by_name(int fmt, char *addr, char *name) ++{ ++ struct addr_mgt_info *t; ++ ++ t = addr_find_by_name(name); ++ if (t == NULL) { ++ ADDR_MGT_ERR("can't find addr named: %s", name); ++ return -1; ++ } ++ ++ if (IS_TYPE_INVALID(t->type_cur)) { ++ ADDR_MGT_ERR("addr type invalid"); ++ return -1; ++ } ++ ++ if (addr_parse(ADDR_FMT_VAL, t->addr, t->flag)) { ++ ADDR_MGT_ERR("addr parse fail(%s)", t->addr); ++ return -1; ++ } ++ ++ if (fmt == ADDR_FMT_STR) ++ sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X", ++ t->addr[0], t->addr[1], t->addr[2], ++ t->addr[3], t->addr[4], t->addr[5]); ++ else ++ memcpy(addr, t->addr, ADDR_VAL_LEN); ++ ++ return t->type_cur; ++} ++ ++static int set_addr_by_name(int type, int fmt, const char *addr, char *name) ++{ ++ struct addr_mgt_info *t; ++ ++ t = addr_find_by_name(name); ++ if (t == NULL) { ++ ADDR_MGT_ERR("can't find addr named: %s", name); ++ return -1; ++ } ++ ++ if (addr_parse(fmt, addr, t->flag)) { ++ ADDR_MGT_ERR("addr parse fail(%s)", addr); ++ return -1; ++ } ++ ++ t->type_cur = type; ++ if (fmt == ADDR_FMT_STR) ++ sscanf(addr, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &t->addr[0], &t->addr[1], &t->addr[2], ++ &t->addr[3], &t->addr[4], &t->addr[5]); ++ else ++ memcpy(t->addr, addr, ADDR_VAL_LEN); ++ ++ return 0; ++} ++ ++int get_custom_mac_address(int fmt, char *name, char *addr) ++{ ++ return get_addr_by_name(fmt, addr, name); ++} ++EXPORT_SYMBOL_GPL(get_custom_mac_address); ++ ++static int addr_factory(struct device_node *np, ++ int idx, int type, char *mac, char *name) ++{ ++ int ret, i; ++ char match[MATCH_STR_LEN]; ++ const char *p; ++ char id[ID_LEN], hash[HASH_LEN], cmp_buf[ID_LEN]; ++ struct timespec64 curtime; ++ ++ switch (type) { ++ case TYPE_BURN: ++ sprintf(match, "addr_%s", name); ++ ret = of_property_read_string_index(np, match, 0, &p); ++ if (ret) ++ return -1; ++ ++ ret = sscanf(p, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac[0], &mac[1], &mac[2], ++ &mac[3], &mac[4], &mac[5]); ++ ++ if (ret != ADDR_VAL_LEN) ++ return -1; ++ break; ++ case TYPE_IDGEN: ++ if (idx > HASH_LEN / ADDR_VAL_LEN - 1) ++ return -1; ++ if (sunxi_get_soc_chipid(id)) ++ return -1; ++ memset(cmp_buf, 0x00, ID_LEN); ++ if (memcmp(id, cmp_buf, ID_LEN) == 0) ++ return -1; ++ if (hmac_sha256(id, ID_LEN, hash)) ++ return -1; ++ memcpy(mac, &hash[idx * ADDR_VAL_LEN], ADDR_VAL_LEN); ++ break; ++ case TYPE_RAND: ++ for (i = 0; i < ADDR_VAL_LEN; i++) { ++ ktime_get_real_ts64(&curtime); ++ mac[i] = (char)curtime.tv_nsec; ++ } ++ break; ++ default: ++ ADDR_MGT_ERR("unsupport type: %d", type); ++ return -1; ++ } ++ return 0; ++} ++ ++static int addr_init(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ int type, i, j; ++ char match[MATCH_STR_LEN]; ++ char addr[ADDR_VAL_LEN]; ++ int type_tab[] = {TYPE_BURN, TYPE_IDGEN, TYPE_RAND}; ++ ++ /* init addr type and value */ ++ for (i = 0; i < ARRAY_SIZE(info); i++) { ++ sprintf(match, "type_addr_%s", info[i].name); ++ if (of_property_read_u32(np, match, &type)) { ++ ADDR_MGT_DBG("Failed to get type_def_%s, use default: %d", ++ info[i].name, info[i].type_def); ++ } else { ++ info[i].type_def = type; ++ info[i].type_cur = type; ++ } ++ ++ if (IS_TYPE_INVALID(info[i].type_def)) ++ return -1; ++ if (info[i].type_def != TYPE_ANY) { ++ if (addr_factory(np, i, info[i].type_def, addr, info[i].name)) ++ return -1; ++ } else { ++ for (j = 0; j < ARRAY_SIZE(type_tab); j++) { ++ if (!addr_factory(np, i, type_tab[j], addr, info[i].name)) { ++ info[i].type_cur = type_tab[j]; ++ break; ++ } ++ } ++ } ++ ++ if (info[i].flag) ++ addr[0] &= 0xFC; ++ ++ if (addr_parse(ADDR_FMT_VAL, addr, info[i].flag)) ++ return -1; ++ else { ++ info[i].addr = devm_kzalloc(&pdev->dev, ADDR_VAL_LEN, GFP_KERNEL); ++ memcpy(info[i].addr, addr, ADDR_VAL_LEN); ++ } ++ } ++ return 0; ++} ++ ++static ssize_t summary_show(const struct class *class, ++ const struct class_attribute *attr, char *buffer) ++{ ++ int i = 0, ret = 0; ++ ++ ret += sprintf(&buffer[ret], "name cfg cur address\n"); ++ for (i = 0; i < ARRAY_SIZE(info); i++) { ++ ret += sprintf(&buffer[ret], ++ "%4s %d %d %02X:%02X:%02X:%02X:%02X:%02X\n", ++ info[i].name, info[i].type_def, info[i].type_cur, ++ info[i].addr[0], info[i].addr[1], info[i].addr[2], ++ info[i].addr[3], info[i].addr[4], info[i].addr[5]); ++ } ++ return ret; ++} ++static CLASS_ATTR_RO(summary); ++ ++ADDR_CLASS_ATTR_ADD(wifi); ++ADDR_CLASS_ATTR_ADD(bt); ++ADDR_CLASS_ATTR_ADD(eth); ++ ++static struct attribute *addr_class_attrs[] = { ++ &class_attr_summary.attr, ++ &class_attr_addr_wifi.attr, ++ &class_attr_addr_bt.attr, ++ &class_attr_addr_eth.attr, ++ NULL ++}; ++ATTRIBUTE_GROUPS(addr_class); ++ ++static struct class addr_class = { ++ .name = "addr_mgt", ++ .class_groups = addr_class_groups, ++}; ++ ++static const struct of_device_id addr_mgt_ids[] = { ++ { .compatible = "allwinner,sunxi-addr_mgt" }, ++ { /* Sentinel */ } ++}; ++ ++static int addr_mgt_probe(struct platform_device *pdev) ++{ ++ int status; ++ ++ ADDR_MGT_DBG("module version: %s", MODULE_CUR_VERSION); ++ status = class_register(&addr_class); ++ if (status < 0) { ++ ADDR_MGT_ERR("class register error, status: %d.", status); ++ return -1; ++ } ++ ++ if (addr_init(pdev)) { ++ ADDR_MGT_ERR("failed to init addr."); ++ class_unregister(&addr_class); ++ return -1; ++ } ++ ADDR_MGT_DBG("success."); ++ return 0; ++} ++ ++static int addr_mgt_remove(struct platform_device *pdev) ++{ ++ class_unregister(&addr_class); ++ return 0; ++} ++ ++static struct platform_driver addr_mgt_driver = { ++ .probe = addr_mgt_probe, ++ .remove = addr_mgt_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "sunxi-addr-mgt", ++ .of_match_table = addr_mgt_ids, ++ }, ++}; ++ ++module_platform_driver_probe(addr_mgt_driver, addr_mgt_probe); ++ ++MODULE_AUTHOR("Allwinnertech"); ++MODULE_DESCRIPTION("Network MAC Addess Manager"); ++MODULE_LICENSE("GPL"); ++ diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-6_6.scc b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-6_6.scc index 27fcdd5..af87361 100644 --- a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-6_6.scc +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-6_6.scc @@ -4,3 +4,6 @@ include uwe5622-6_5.scc patch uwe5622-v6.6-fix-tty-sdio.patch + +# Add driver for MAC address fix +patch 0001-drv-fix-MAC-address-for-UWE5622.patch diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-fragment.cfg b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-fragment.cfg index 5d0a3df..9e1d8b8 100644 --- a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-fragment.cfg +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/uwe5622/uwe5622-fragment.cfg @@ -7,3 +7,5 @@ CONFIG_UNISOC_WIFI_PS=y CONFIG_TTY_OVERY_SDIO=m CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_LIB_SHA256=y + +CONFIG_NVMEM_SUNXI_SID=m