diff --git a/target/linux/lantiq/patches-4.4/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch b/target/linux/lantiq/patches-4.4/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch index fffd42d0ec..73b3c3a3c0 100644 --- a/target/linux/lantiq/patches-4.4/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch +++ b/target/linux/lantiq/patches-4.4/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch @@ -5,28 +5,15 @@ Subject: [PATCH 35/36] owrt: lantiq: wifi and ethernet eeprom handling Signed-off-by: John Crispin --- - arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h | 6 + .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 + arch/mips/lantiq/xway/Makefile | 3 + - arch/mips/lantiq/xway/ath_eep.c | 299 +++++++++++++++++++++ - arch/mips/lantiq/xway/eth_mac.c | 25 ++ - arch/mips/lantiq/xway/pci-ath-fixup.c | 118 ++++++++ + arch/mips/lantiq/xway/ath5k_eep.c | 136 +++++++++++++++++++++ + arch/mips/lantiq/xway/eth_mac.c | 25 ++++ drivers/net/ethernet/lantiq_etop.c | 6 +- - 7 files changed, 459 insertions(+), 1 deletion(-) - create mode 100644 arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h - create mode 100644 arch/mips/lantiq/xway/ath_eep.c + 5 files changed, 172 insertions(+), 1 deletion(-) + create mode 100644 arch/mips/lantiq/xway/ath5k_eep.c create mode 100644 arch/mips/lantiq/xway/eth_mac.c - create mode 100644 arch/mips/lantiq/xway/pci-ath-fixup.c ---- /dev/null -+++ b/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h -@@ -0,0 +1,6 @@ -+#ifndef _PCI_ATH_FIXUP -+#define _PCI_ATH_FIXUP -+ -+void ltq_pci_ath_fixup(unsigned slot, u16 *cal_data) __init; -+ -+#endif /* _PCI_ATH_FIXUP */ --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -104,5 +104,8 @@ int xrx200_gphy_boot(struct device *dev, @@ -45,12 +32,12 @@ Signed-off-by: John Crispin obj-y += vmmc.o tffs.o +obj-y += eth_mac.o -+obj-$(CONFIG_PCI) += ath_eep.o pci-ath-fixup.o ++obj-$(CONFIG_PCI) += ath5k_eep.o + obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o --- /dev/null -+++ b/arch/mips/lantiq/xway/ath_eep.c -@@ -0,0 +1,299 @@ ++++ b/arch/mips/lantiq/xway/ath5k_eep.c +@@ -0,0 +1,136 @@ +/* + * Copyright (C) 2011 Luca Olivetti + * Copyright (C) 2011 John Crispin @@ -65,181 +52,18 @@ Signed-off-by: John Crispin + */ + +#include -+#include +#include +#include +#include -+#include +#include +#include +#include -+#include +#include + +extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev); +struct ath5k_platform_data ath5k_pdata; -+struct ath9k_platform_data ath9k_pdata = { -+ .led_pin = -1, -+}; +static u8 athxk_eeprom_mac[6]; + -+static int ath9k_pci_plat_dev_init(struct pci_dev *dev) -+{ -+ dev->dev.platform_data = &ath9k_pdata; -+ return 0; -+} -+ -+static int ath9k_eep_load; -+int __init of_ath9k_eeprom_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node, *mtd_np = NULL; -+ int mac_offset, led_pin; -+ u32 mac_inc = 0, pci_slot = 0; -+ int i; -+ struct mtd_info *the_mtd; -+ size_t flash_readlen; -+ const __be32 *list; -+ const char *part; -+ phandle phandle; -+ u16 dev_ids[2] = { 0 }; -+ -+ list = of_get_property(np, "ath,eep-flash", &i); -+ if (!list || (i != (2 * sizeof(*list)))) -+ return -ENODEV; -+ -+ phandle = be32_to_cpup(list++); -+ if (phandle) -+ mtd_np = of_find_node_by_phandle(phandle); -+ -+ if (!mtd_np) -+ return -ENODEV; -+ -+ part = of_get_property(mtd_np, "label", NULL); -+ if (!part) -+ part = mtd_np->name; -+ -+ the_mtd = get_mtd_device_nm(part); -+ if (IS_ERR(the_mtd)) -+ return -ENODEV; -+ -+ i = mtd_read(the_mtd, be32_to_cpup(list), ATH9K_PLAT_EEP_MAX_WORDS << 1, -+ &flash_readlen, (void *) ath9k_pdata.eeprom_data); -+ -+ if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) { -+ size_t mac_readlen; -+ mtd_read(the_mtd, mac_offset, 6, &mac_readlen, -+ (void *) athxk_eeprom_mac); -+ } -+ put_mtd_device(the_mtd); -+ -+ if ((sizeof(ath9k_pdata.eeprom_data) != flash_readlen) || i) { -+ dev_err(&pdev->dev, "failed to load eeprom from mtd\n"); -+ return -ENODEV; -+ } -+ -+ if (of_find_property(np, "ath,eep-swap", NULL)) -+ for (i = 0; i < ATH9K_PLAT_EEP_MAX_WORDS; i++) -+ ath9k_pdata.eeprom_data[i] = swab16(ath9k_pdata.eeprom_data[i]); -+ -+ if (of_find_property(np, "ath,eep-endian", NULL)) { -+ ath9k_pdata.endian_check = true; -+ -+ dev_info(&pdev->dev, "endian check enabled.\n"); -+ } -+ -+ if (!is_valid_ether_addr(athxk_eeprom_mac) && ltq_get_eth_mac()) -+ memcpy(athxk_eeprom_mac, ltq_get_eth_mac(), 6); -+ -+ if (!is_valid_ether_addr(athxk_eeprom_mac)) { -+ dev_warn(&pdev->dev, "using random mac\n"); -+ random_ether_addr(athxk_eeprom_mac); -+ } -+ -+ if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc)) -+ athxk_eeprom_mac[5] += mac_inc; -+ -+ ath9k_pdata.macaddr = athxk_eeprom_mac; -+ ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init; -+ -+ if (!of_property_read_u32(np, "ath,pci-slot", &pci_slot)) { -+ ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data); -+ -+ dev_info(&pdev->dev, "pci slot: %u\n", pci_slot); -+ if (ath9k_eep_load) { -+ struct pci_dev *d = NULL; -+ while ((d = pci_get_device(PCI_VENDOR_ID_ATHEROS, -+ PCI_ANY_ID, d)) != NULL) -+ pci_fixup_device(pci_fixup_early, d); -+ } -+ -+ } -+ -+ if (!of_property_read_u16_array(np, "ath,device-id", dev_ids, 2)) { -+ struct pci_dev *d = NULL; -+ -+ while ((d = pci_get_device(PCI_VENDOR_ID_ATHEROS, -+ dev_ids[0], d)) != NULL) -+ d->device = dev_ids[1]; -+ } -+ -+ if (!of_property_read_u32(np, "ath,led-pin", &led_pin)) { -+ ath9k_pdata.led_pin = led_pin; -+ dev_info(&pdev->dev, "using led pin %d.\n", led_pin); -+ } -+ -+ if (of_property_read_bool(np, "ath,led-active-high")) { -+ ath9k_pdata.led_active_high = true; -+ dev_info(&pdev->dev, "inverted LED polarity\n"); -+ } -+ -+ if (of_property_read_bool(np, "ath,disable-2ghz")) { -+ ath9k_pdata.disable_2ghz = true; -+ dev_info(&pdev->dev, "disabled 2.4 GHz band\n"); -+ } -+ -+ if (of_property_read_bool(np, "ath,disable-5ghz")) { -+ ath9k_pdata.disable_5ghz = true; -+ dev_info(&pdev->dev, "disabled 5 GHz band\n"); -+ } -+ -+ dev_info(&pdev->dev, "loaded ath9k eeprom\n"); -+ -+ return 0; -+} -+ -+static struct of_device_id ath9k_eeprom_ids[] = { -+ { .compatible = "ath9k,eeprom" }, -+ { } -+}; -+ -+static struct platform_driver ath9k_eeprom_driver = { -+ .driver = { -+ .name = "ath9k,eeprom", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(ath9k_eeprom_ids), -+ }, -+}; -+ -+static int __init of_ath9k_eeprom_init(void) -+{ -+ int ret = platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe); -+ -+ if (ret) -+ ath9k_eep_load = 1; -+ -+ return ret; -+} -+ -+static int __init of_ath9k_eeprom_init_late(void) -+{ -+ if (!ath9k_eep_load) -+ return 0; -+ return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe); -+} -+late_initcall(of_ath9k_eeprom_init_late); -+subsys_initcall(of_ath9k_eeprom_init); -+ -+ +static int ath5k_pci_plat_dev_init(struct pci_dev *dev) +{ + dev->dev.platform_data = &ath5k_pdata; @@ -378,127 +202,6 @@ Signed-off-by: John Crispin + return !eth_mac_set; +} +early_param("ethaddr", setup_ethaddr); ---- /dev/null -+++ b/arch/mips/lantiq/xway/pci-ath-fixup.c -@@ -0,0 +1,118 @@ -+/* -+ * Atheros AP94 reference board PCI initialization -+ * -+ * Copyright (C) 2009-2010 Gabor Juhos -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+struct ath_fixup { -+ u16 *cal_data; -+ unsigned slot; -+}; -+ -+static int ath_num_fixups; -+static struct ath_fixup ath_fixups[2]; -+ -+static void ath_pci_fixup(struct pci_dev *dev) -+{ -+ void __iomem *mem; -+ struct pci_dev *bridge = pci_upstream_bridge(dev); -+ u16 *cal_data = NULL; -+ u16 cmd; -+ u32 bar0; -+ u32 val; -+ u32 base; -+ unsigned i; -+ -+ for (i = 0; i < ath_num_fixups; i++) { -+ if (ath_fixups[i].cal_data == NULL) -+ continue; -+ -+ if (ath_fixups[i].slot != PCI_SLOT(dev->devfn)) -+ continue; -+ -+ cal_data = ath_fixups[i].cal_data; -+ break; -+ } -+ -+ if (cal_data == NULL) -+ return; -+ -+ if (*cal_data != 0xa55a) { -+ pr_err("pci %s: invalid calibration data\n", pci_name(dev)); -+ return; -+ } -+ -+ pr_info("pci %s: fixup device configuration\n", pci_name(dev)); -+ -+ base = dev->resource[0].start; -+ mem = ioremap(base, 0x10000); -+ if (!mem) { -+ pr_err("pci %s: ioremap error\n", pci_name(dev)); -+ return; -+ } -+ -+ if (bridge) { -+ pci_enable_device(dev); -+ } -+ -+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); -+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, base); -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; -+ pci_write_config_word(dev, PCI_COMMAND, cmd); -+ -+ /* set pointer to first reg address */ -+ cal_data += 3; -+ while (*cal_data != 0xffff) { -+ u32 reg; -+ reg = *cal_data++; -+ val = *cal_data++; -+ val |= (*cal_data++) << 16; -+ -+ ltq_w32(swab32(val), mem + reg); -+ udelay(100); -+ } -+ -+ pci_read_config_dword(dev, PCI_VENDOR_ID, &val); -+ dev->vendor = val & 0xffff; -+ dev->device = (val >> 16) & 0xffff; -+ -+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); -+ dev->revision = val & 0xff; -+ dev->class = val >> 8; /* upper 3 bytes */ -+ -+ pr_info("pci %s: fixup info: [%04x:%04x] revision %02x class %#08x\n", -+ pci_name(dev), dev->vendor, dev->device, dev->revision, dev->class); -+ -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); -+ pci_write_config_word(dev, PCI_COMMAND, cmd); -+ -+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); -+ -+ if (bridge) { -+ pci_disable_device(dev); -+ } -+ -+ iounmap(mem); -+} -+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath_pci_fixup); -+ -+void __init ltq_pci_ath_fixup(unsigned slot, u16 *cal_data) -+{ -+ if (ath_num_fixups >= ARRAY_SIZE(ath_fixups)) -+ return; -+ -+ ath_fixups[ath_num_fixups].slot = slot; -+ ath_fixups[ath_num_fixups].cal_data = cal_data; -+ ath_num_fixups++; -+} --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -840,7 +840,11 @@ ltq_etop_init(struct net_device *dev)