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

Reply via email to