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 <[email protected]>
* Copyright (C) 2011 John Crispin <[email protected]>
* Copyright (C) 2011 Andrej Vlašić <[email protected]>
* Copyright (C) 2013 Álvaro Fernández Rojas <[email protected]>
* Copyright (C) 2013 Daniel Gimpelevich
<[email protected]>
*
* 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
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel