The Ath9K radio on the BTHH2B board, Lantiq Xway Danube 50712, requires eeprom 
calibration/fixup data which is stored on the first 16k of NAND flash. The data 
amounts to some 3137 bytes, the remainder are 00. I have rev 1.3 and 1.5 boards 
and these data are identical on both - the Mac address is part of the uboot 
environment data stored on NOR. 

Two operations are required:

1. PCI Fixup data - the first 43 bytes of the eeprom calibration data are "pci 
fixup data". At boot, PCI is probed before NAND is ready so I hard coded these 
data into ath_eep.c where they are passed to the function ltq_pci_ath_fixup. 
This works fine although I believe it would be preferable to describe these 
data in the devicetree file.

2. The radio calibration data is not required until after NAND is ready and is 
available via an MTD partition. There was some discussion 14 months ago about 
providing a device tree mechanism to identify the MTD partition, offset and 
size of the eeprom data but as far as I can see this idea has not made it into 
Trunk.

I would be grateful for any suggestions/help on preparing a patch to implement 
these functions in the devicetree. The relevant part of ath_eep.c is below.

TIA, Dermot

ath_eep.c

.....
static unsigned short bthh2b_pci_fixup_data[] =
{
0xa55a,0x0000,0x0003, 0x6000,0x168c,0x0027, 0x6008,0x0001,0x0280, 
0x602c,0x168c,0x2081, 0x5000,0x168c,0x0028,
0x5008,0x0001,0x0280, 0x502c,0x168c,0x2081, 0x5064,0x0cc0,0x0504, 
0x570c,0xff01,0x2200, 0x506c,0x3c11,0x0003,
0x4004,0x073f,0x0000, 0x4074,0x0003,0x0000, 0x4000,0x0000,0x01c2, 
0x6034,0x0044,0x0000,
0xffff,
};

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;
    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;

    eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);

    if (!eep_res) {
        dev_err(&pdev->dev, "failed to load eeprom address\n");
        return -ENODEV;
    }
    if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS) {
        dev_err(&pdev->dev, "eeprom has an invalid size\n");
        return -EINVAL;
    }

    eep = ioremap(eep_res->start, resource_size(eep_res));
    memcpy_fromio(ath9k_pdata.eeprom_data, eep, ATH9K_PLAT_EEP_MAX_WORDS);

    if (of_find_property(np, "ath,eep-swap", NULL)) {
        ath9k_pdata.endian_check = true;

        dev_info(&pdev->dev, "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) checksum */
        eepdata = (u16 *) (&ath9k_pdata.eeprom_data[0x204>>1]); /* after 
checksum */
        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, 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, bthh2b_pci_fixup_data);    /* was 
ath9k_pdata.eeprom_data, now bthh2b_pci_fixup_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 __init of_ath9k_eeprom_init(void)
{
    return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
}
arch_initcall(of_ath9k_eeprom_init);

                                          
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to