diff options
author | Oleksij Rempel <linux@rempel-privat.de> | 2018-06-07 21:55:50 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-06-14 08:05:35 +0200 |
commit | bd7b0120579a914a0bc0f8360ce6c146689d68b1 (patch) | |
tree | 00b4d87e22e888e81246b348a58361057a017ab9 | |
parent | fe040e0977fab29216f5039e8f9b04e6dbec859a (diff) | |
download | barebox-bd7b0120579a914a0bc0f8360ce6c146689d68b1.tar.gz barebox-bd7b0120579a914a0bc0f8360ce6c146689d68b1.tar.xz |
MIPS: ath79: provide driver for Atheros ART partition
this partition contains calibration data for WiFi and
some board specific data, like MAC address.
For now we care only about MAC.
Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | arch/mips/mach-ath79/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/mach-ath79/art.c | 112 |
2 files changed, 113 insertions, 0 deletions
diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile index 3772daebad..b827b363cf 100644 --- a/arch/mips/mach-ath79/Makefile +++ b/arch/mips/mach-ath79/Makefile @@ -1,2 +1,3 @@ obj-y += reset.o obj-y += bbu.o +obj-y += art.o diff --git a/arch/mips/mach-ath79/art.c b/arch/mips/mach-ath79/art.c new file mode 100644 index 0000000000..984d087363 --- /dev/null +++ b/arch/mips/mach-ath79/art.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2. +/* + * Copyright (c) 2018 Oleksij Rempel <linux@rempel-privat.de> + */ + +#include <common.h> +#include <fcntl.h> +#include <init.h> +#include <libfile.h> +#include <net.h> +#include <unistd.h> + +#define AR93000_EPPROM_OFFSET 0x1000 + +struct ar9300_eeprom { + u8 eeprom_version; + u8 template_version; + u8 mac_addr[6]; +}; + +static int art_set_mac(struct device_d *dev, struct ar9300_eeprom *eeprom) +{ + struct device_node *node = dev->device_node; + struct device_node *rnode; + + if (!node) + return -ENOENT; + + rnode = of_parse_phandle_from(node, NULL, + "barebox,provide-mac-address", 0); + if (!rnode) + return -ENOENT; + + of_eth_register_ethaddr(rnode, &eeprom->mac_addr[0]); + + return 0; +} + +static int art_read_mac(struct device_d *dev, const char *file) +{ + int fd, rbytes; + struct ar9300_eeprom eeprom; + + fd = open_and_lseek(file, O_RDONLY, AR93000_EPPROM_OFFSET); + if (fd < 0) { + dev_err(dev, "Failed to open eeprom path %s %d\n", + file, fd); + return fd; + } + + rbytes = read_full(fd, &eeprom, sizeof(eeprom)); + close(fd); + if (rbytes < sizeof(eeprom)) { + dev_err(dev, "Failed to read %s\n", file); + return rbytes < 0 ? rbytes : -EIO; + } + + dev_dbg(dev, "ART version: %x.%x\n", + eeprom.eeprom_version, eeprom.template_version); + dev_dbg(dev, "mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + eeprom.mac_addr[0], + eeprom.mac_addr[1], + eeprom.mac_addr[2], + eeprom.mac_addr[3], + eeprom.mac_addr[4], + eeprom.mac_addr[5]); + + if (!is_valid_ether_addr(&eeprom.mac_addr[0])) { + dev_err(dev, "bad MAC addr\n"); + return -EILSEQ; + } + + return art_set_mac(dev, &eeprom); +} + +static int art_probe(struct device_d *dev) +{ + char *path; + int ret; + + dev_dbg(dev, "found ART partition\n"); + + ret = of_find_path(dev->device_node, "device-path", &path, 0); + if (ret) { + dev_err(dev, "can't find path\n"); + return ret; + } + + return art_read_mac(dev, path); +} + +static struct of_device_id art_dt_ids[] = { + { + .compatible = "qca,art", + }, { + /* sentinel */ + } +}; + +static struct driver_d art_driver = { + .name = "qca-art", + .probe = art_probe, + .of_compatible = art_dt_ids, +}; + +static int art_of_driver_init(void) +{ + platform_driver_register(&art_driver); + + return 0; +} +late_initcall(art_of_driver_init); |