Tki2000, in the openwrt subforum of seguridadwireless, published a modified ath_eep.c file because, since the Lantiq target moved to kernel 3.10 some routers cannot read calibration data nor mac. The code also applies a patch made by Noltari that disables regdomain limitations, but still don't read the mac rightly. Here is the code that can be used as a draft to make the wifi work in those routers.
/* * Copyright (C) 2011 Luca Olivetti <l...@ventoso.org> * Copyright (C) 2011 John Crispin <blo...@openwrt.org> * Copyright (C) 2011 Andrej Vlašić <andrej.vlas...@gmail.com> * Copyright (C) 2013 Álvaro Fernández Rojas <nolt...@gmail.com> * Copyright (C) 2013 Daniel Gimpelevich <dan...@gimpelevich.san-francisco.ca.us> * * 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 <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/etherdevice.h> #include <linux/ath5k_platform.h> #include <linux/ath9k_platform.h> #include <linux/pci.h> #include <linux/err.h> #include <linux/mtd/mtd.h> #include <pci-ath-fixup.h> #include <lantiq_soc.h> #include <linux/of_net.h> 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; } int __init of_ath9k_eeprom_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node, *mtd_np; struct resource *eep_res, *mac_res; void __iomem *eep, *mac; int mac_offset; u32 mac_inc = 0, pci_slot = 0; int i; u16 *eepdata, sum, el; struct mtd_info *the_mtd; size_t flash_readlen; const __be32 *list; const char *part; phandle phandle; //struct property *pp; //struct device_node *dn; if (!of_find_property(np,"ath,arv-ath9k-fix",NULL)) { list = of_get_property(np, "ath,eep-flash", &i); if (!list || (i != (2 * sizeof(*list)))) { dev_err(&pdev->dev, "failed to find ath,eep-flash\n"); return -ENODEV; } phandle = be32_to_cpup(list++); if (!phandle) { dev_err(&pdev->dev, "failed to find phandle\n"); return -ENODEV; } mtd_np = of_find_node_by_phandle(phandle); if (!mtd_np) { dev_err(&pdev->dev, "failed to find mtd node\n"); return -ENODEV; } part = of_get_property(mtd_np, "label", NULL); if (!part) part = mtd_np->name; the_mtd = get_mtd_device_nm(part); if (the_mtd == ERR_PTR(-ENODEV)) { dev_err(&pdev->dev, "failed to find mtd device\n"); return -ENODEV; } i = mtd_read(the_mtd, be32_to_cpup(list), ATH9K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen, (void *) ath9k_pdata.eeprom_data); 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 (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) { memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data + mac_offset, 6); } else { random_ether_addr(athxk_eeprom_mac); if (of_get_mac_address_mtd(np, athxk_eeprom_mac)) dev_warn(&pdev->dev, "using random mac\n"); } 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); } } else { // Noltari patch code arv7518pw eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dev_info(&pdev->dev,"eeprom expected size : %u \n",ATH9K_PLAT_EEP_MAX_WORDS<<1); dev_info(&pdev->dev,"mac expected size : %u\n",6); dev_info(&pdev->dev,"eeprom read size : %u\n",resource_size(eep_res)); dev_info(&pdev->dev,"mac address size : %u\n",resource_size(mac_res)); if (!eep_res) { dev_err(&pdev->dev, "failed to load eeprom addres\n"); return -ENODEV; } if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS<<1) { dev_err(&pdev->dev, "eeprom size mismatch\n"); return -EINVAL; } eep = ioremap(eep_res->start, resource_size(eep_res)); //ath9k_pdata.eeprom_data=kmalloc(ATH9K_PLAT_EEP_MAX_WORDS<<1,GFP_KERNEL); memcpy_fromio(ath9k_pdata.eeprom_data, eep, ATH9K_PLAT_EEP_MAX_WORDS<<1); 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,"eeprom endian check enabled.\n"); } if (of_find_property(np, "ath,eep-csum", NULL)) { sum=ath9k_pdata.eeprom_data[0x200>>1]; el=sum/sizeof(u16)-2; // skip length and old cheksum eepdata=(u16 *)(&ath9k_pdata.eeprom_data[0x204>>1]); // after cheksum for (i=0; i<el; i++) sum^=*eepdata++; sum^=0xffff; ath9k_pdata.eeprom_data[0x202>>1]=sum; dev_info(&pdev->dev,"checksum fixed.\n"); } if (!of_property_read_u32(np,"ath,mac-offset",&mac_offset)) { memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data +mac_offset, 6); } else { if (mac_res) { if (resource_size(mac_res)!=6) { dev_err(&pdev->dev, "mac has an invalid size.\n"); return -EINVAL; } mac=ioremap(mac_res->start, resource_size(mac_res)); memcpy_fromio(athxk_eeprom_mac, mac, 6); } else { 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); } } 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 ath9k_eep_loaded; static int __init of_ath9k_eeprom_init(void) { int ret = platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe); if (!ret) ath9k_eep_loaded = 1; return ret; } static int __init of_ath9k_eeprom_init_late(void) { if (ath9k_eep_loaded) 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; return 0; } int __init of_ath5k_eeprom_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node, *mtd_np; struct resource *eep_res, *mac_res; void __iomem *eep, *mac; int mac_offset; u32 mac_inc = 0, pci_slot = 0; int i; u16 *eepdata, sum, el; struct mtd_info *the_mtd; size_t flash_readlen; const __be32 *list; const char *part; phandle phandle; if (!of_find_property(np,"ath,arv-ath5k-fix",NULL)) { list = of_get_property(np, "ath,eep-flash", &i); if (!list || (i != (2 * sizeof(*list)))) { dev_err(&pdev->dev, "failed to find ath,eep-flash\n"); return -ENODEV; } phandle = be32_to_cpup(list++); if (!phandle) { dev_err(&pdev->dev, "failed to find phandle\n"); return -ENODEV; } mtd_np = of_find_node_by_phandle(phandle); if (!mtd_np) { dev_err(&pdev->dev, "failed to find mtd node\n"); return -ENODEV; } part = of_get_property(mtd_np, "label", NULL); if (!part) part = mtd_np->name; the_mtd = get_mtd_device_nm(part); if (the_mtd == ERR_PTR(-ENODEV)) { dev_err(&pdev->dev, "failed to find mtd device\n"); return -ENODEV; } i = mtd_read(the_mtd, be32_to_cpup(list), ATH5K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen, (void *) ath5k_pdata.eeprom_data); put_mtd_device(the_mtd); if ((sizeof(ath5k_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 < ATH5K_PLAT_EEP_MAX_WORDS; i++) ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]); if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) { memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data + mac_offset, 6); } else { random_ether_addr(athxk_eeprom_mac); if (of_get_mac_address_mtd(np, athxk_eeprom_mac)) dev_warn(&pdev->dev, "using random mac\n"); } if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc)) athxk_eeprom_mac[5] += mac_inc; ath5k_pdata.macaddr = athxk_eeprom_mac; ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init; } else { // Noltari patch for ath5k arv4518pw. Applicable for other ath5k lantiqs. eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dev_info(&pdev->dev,"eeprom expected size : %u \n",ATH5K_PLAT_EEP_MAX_WORDS<<1); dev_info(&pdev->dev,"mac expected size : %u\n",6); dev_info(&pdev->dev,"eeprom read size : %u\n",resource_size(eep_res)); dev_info(&pdev->dev,"mac address size : %u\n",resource_size(mac_res)); if (!eep_res) { dev_err(&pdev->dev, "failed to load eeprom addres\n"); return -ENODEV; } if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS<<1) { dev_err(&pdev->dev, "eeprom size mismatch\n"); return -EINVAL; } eep = ioremap(eep_res->start, resource_size(eep_res)); ath5k_pdata.eeprom_data=kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1,GFP_KERNEL); memcpy_fromio(ath5k_pdata.eeprom_data, eep, ATH5K_PLAT_EEP_MAX_WORDS<<1); if (of_find_property(np, "ath,eep-swap",NULL)) { for (i=0; i<ATH5K_PLAT_EEP_MAX_WORDS; i++) ath5k_pdata.eeprom_data[i]=swab16(ath5k_pdata.eeprom_data[i]); } if (of_find_property(np, "ath,eep-csum", NULL)) { sum=ath5k_pdata.eeprom_data[0x200>>1]; el=sum/sizeof(u16)-2; // skip length and old cheksum eepdata=(u16 *)(&ath5k_pdata.eeprom_data[0x204>>1]); // after cheksum for (i=0; i<el; i++) sum^=*eepdata++; sum^=0xffff; ath5k_pdata.eeprom_data[0x202>>1]=sum; dev_info(&pdev->dev,"checksum fixed.\n"); } if (!of_property_read_u32(np,"ath,mac-offset",&mac_offset)) { memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data +mac_offset, 6); } else { if (mac_res) { if (resource_size(mac_res)!=6) { dev_err(&pdev->dev, "mac has an invalid size.\n"); return -EINVAL; } dev_info(&pdev->dev,"loading MAC.\n"); mac=ioremap(mac_res->start, resource_size(mac_res)); memcpy_fromio(athxk_eeprom_mac, mac, 6); dev_info(&pdev->dev,"loaded MAC.\n"); } else { 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; ath5k_pdata.macaddr=athxk_eeprom_mac; ltq_pci_plat_dev_init=ath5k_pci_plat_dev_init; if (!of_property_read_u32(np,"ath,pci-slot", &pci_slot)) { ltq_pci_ath_fixup(pci_slot, ath5k_pdata.eeprom_data); dev_info(&pdev->dev,"pci slot: %u.\n",pci_slot); } dev_info(&pdev->dev,"eeprom init finished.\n"); } dev_info(&pdev->dev, "loaded ath5k eeprom\n"); return 0; } static struct of_device_id ath5k_eeprom_ids[] = { { .compatible = "ath5k,eeprom" }, { } }; static struct platform_driver ath5k_eeprom_driver = { .driver = { .name = "ath5k,eeprom", .owner = THIS_MODULE, .of_match_table = of_match_ptr(ath5k_eeprom_ids), }, }; static int __init of_ath5k_eeprom_init(void) { return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe); } //device_initcall(of_ath5k_eeprom_init); subsys_initcall(of_ath5k_eeprom_init); The dts files must be modified as follows: ath5k_eep { compatible = "ath5k,eeprom"; reg = <0 0x3f0400 0x1000 0 0x3f0016 0x6>; ath,mac-increment = <1>; ath,eep-swap; ath,arv-ath5k-fix; _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel