Advertisement
Pteridium

ARV wifi patch

Apr 4th, 2014
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.61 KB | None | 0 0
  1. /*
  2.  *  Copyright (C) 2011 Luca Olivetti <luca@ventoso.org>
  3.  *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
  4.  *  Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com>
  5.  *  Copyright (C) 2013 Álvaro Fernández Rojas <noltari@gmail.com>
  6.  *  Copyright (C) 2013 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
  7.  *
  8.  *  This program is free software; you can redistribute it and/or modify it
  9.  *  under the terms of the GNU General Public License version 2 as published
  10.  *  by the Free Software Foundation.
  11.  */
  12.  
  13. #include <linux/init.h>
  14. #include <linux/module.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/etherdevice.h>
  17. #include <linux/ath5k_platform.h>
  18. #include <linux/ath9k_platform.h>
  19. #include <linux/pci.h>
  20. #include <linux/err.h>
  21. #include <linux/mtd/mtd.h>
  22. #include <pci-ath-fixup.h>
  23. #include <lantiq_soc.h>
  24. #include <linux/of_net.h>
  25.  
  26. extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
  27. struct ath5k_platform_data ath5k_pdata;
  28. struct ath9k_platform_data ath9k_pdata = {
  29.     .led_pin = -1,
  30. };
  31. static u8 athxk_eeprom_mac[6];
  32.  
  33. static int ath9k_pci_plat_dev_init(struct pci_dev *dev)
  34. {
  35.     dev->dev.platform_data = &ath9k_pdata;
  36.     return 0;
  37. }
  38.  
  39. static int ath9k_eep_load;
  40. int __init of_ath9k_eeprom_probe(struct platform_device *pdev)
  41. {
  42.     struct device_node *np = pdev->dev.of_node, *mtd_np;
  43.     struct resource *eep_res, *mac_res;
  44.     void __iomem *eep, *mac;
  45.     int mac_offset, led_pin;
  46.     u32 mac_inc = 0, pci_slot = 0;
  47.     int i;
  48.     u16 *eepdata, sum, el;
  49.     struct mtd_info *the_mtd;
  50.     size_t flash_readlen;
  51.     const __be32 *list;
  52.     const char *part;
  53.     phandle phandle;
  54.  
  55.     if (!of_find_property(np,"ath,arv-ath9k-fix",NULL))
  56.     {
  57.         list = of_get_property(np, "ath,eep-flash", &i);
  58.         if (!list || (i !=  (2 * sizeof(*list)))) {
  59.             dev_err(&pdev->dev, "failed to find ath,eep-flash\n");
  60.             return -ENODEV;
  61.         }
  62.  
  63.         phandle = be32_to_cpup(list++);
  64.         if (!phandle) {
  65.             dev_err(&pdev->dev, "failed to find phandle\n");
  66.             return -ENODEV;
  67.         }
  68.  
  69.         mtd_np = of_find_node_by_phandle(phandle);
  70.         if (!mtd_np) {
  71.             dev_err(&pdev->dev, "failed to find mtd node\n");
  72.             return -ENODEV;
  73.         }
  74.  
  75.         part = of_get_property(mtd_np, "label", NULL);
  76.         if (!part)
  77.             part = mtd_np->name;
  78.  
  79.         the_mtd = get_mtd_device_nm(part);
  80.         if (the_mtd == ERR_PTR(-ENODEV)) {
  81.             dev_err(&pdev->dev, "failed to find mtd device\n");
  82.             return -ENODEV;
  83.         }
  84.  
  85.         i = mtd_read(the_mtd, be32_to_cpup(list),
  86.                 ATH9K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
  87.                 (void *) ath9k_pdata.eeprom_data);
  88.         put_mtd_device(the_mtd);
  89.         if ((sizeof(ath9k_pdata.eeprom_data) != flash_readlen) || i) {
  90.             dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
  91.             return -ENODEV;
  92.         }
  93.  
  94.         if (of_find_property(np, "ath,eep-swap", NULL))
  95.             for (i = 0; i < ATH9K_PLAT_EEP_MAX_WORDS; i++)
  96.                 ath9k_pdata.eeprom_data[i] = swab16(ath9k_pdata.eeprom_data[i]);
  97.  
  98.         if (of_find_property(np, "ath,eep-endian", NULL)) {
  99.             ath9k_pdata.endian_check = true;
  100.  
  101.             dev_info(&pdev->dev, "endian check enabled.\n");
  102.         }
  103.  
  104.         if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
  105.             memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data + mac_offset, 6);
  106.         } else {
  107.             random_ether_addr(athxk_eeprom_mac);
  108.             if (of_get_mac_address_mtd(np, athxk_eeprom_mac))
  109.                 dev_warn(&pdev->dev, "using random mac\n");
  110.         }
  111.  
  112.         if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  113.             athxk_eeprom_mac[5] += mac_inc;
  114.  
  115.         ath9k_pdata.macaddr = athxk_eeprom_mac;
  116.         ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
  117.  
  118.         if (!of_property_read_u32(np, "ath,pci-slot", &pci_slot)) {
  119.             ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
  120.             dev_info(&pdev->dev, "pci slot: %u\n", pci_slot);
  121.             if (ath9k_eep_load) {
  122.                 struct pci_dev *d = NULL;
  123.                 while ((d = pci_get_device(PCI_VENDOR_ID_ATHEROS,
  124.                         PCI_ANY_ID, d)) != NULL)
  125.                     pci_fixup_device(pci_fixup_early, d);
  126.             }
  127.         }
  128.  
  129.         if (!of_property_read_u32(np, "ath,led-pin", &led_pin)) {
  130.             ath9k_pdata.led_pin = led_pin;
  131.  
  132.             dev_info(&pdev->dev, "using led pin %d.\n", led_pin);
  133.         }
  134.     }
  135.     else
  136.     {
  137.         /* ath9k patch for Arcadyan/Astoria boards. */
  138.  
  139.         eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  140.         mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  141.  
  142.         dev_info(&pdev->dev,"eeprom expected size : %u\n",ATH9K_PLAT_EEP_MAX_WORDS<<1);
  143.         dev_info(&pdev->dev,"mac expected size : %u\n",6);
  144.         dev_info(&pdev->dev,"eeprom read size : %u\n",resource_size(eep_res));
  145.         dev_info(&pdev->dev,"mac address size : %u\n",resource_size(mac_res));
  146.  
  147.         if (!eep_res)
  148.         {
  149.             dev_err(&pdev->dev, "failed to load eeprom addres\n");
  150.             return -ENODEV;
  151.         }
  152.         if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS<<1)
  153.         {
  154.             dev_err(&pdev->dev, "eeprom size mismatch\n");
  155.             return -EINVAL;
  156.         }
  157.  
  158.         eep = ioremap(eep_res->start, resource_size(eep_res));
  159.         //ath9k_pdata.eeprom_data=kmalloc(ATH9K_PLAT_EEP_MAX_WORDS<<1,GFP_KERNEL);
  160.         memcpy_fromio(ath9k_pdata.eeprom_data, eep, ATH9K_PLAT_EEP_MAX_WORDS<<1);
  161.  
  162.         if (of_find_property(np, "ath,eep-swap",NULL))
  163.         {
  164.             for (i=0; i<ATH9K_PLAT_EEP_MAX_WORDS; i++)
  165.                 ath9k_pdata.eeprom_data[i]=swab16(ath9k_pdata.eeprom_data[i]);
  166.         }
  167.  
  168.         if (of_find_property(np, "ath,eep-endian",NULL))
  169.         {
  170.             ath9k_pdata.endian_check = "true";
  171.             dev_info(&pdev->dev,"eeprom endian check enabled.\n");
  172.         }
  173.  
  174.         if (of_find_property(np, "ath,eep-csum", NULL))
  175.         {
  176.             sum=ath9k_pdata.eeprom_data[0x200>>1];
  177.             el=sum/sizeof(u16)-2;       /* skip length and old cheksum */
  178.             eepdata=(u16 *)(&ath9k_pdata.eeprom_data[0x204>>1]);        /* after cheksum */
  179.             for (i=0; i<el; i++)
  180.                 sum^=*eepdata++;
  181.             sum^=0xffff;
  182.             ath9k_pdata.eeprom_data[0x202>>1]=sum;
  183.             dev_info(&pdev->dev,"checksum fixed.\n");
  184.         }
  185.  
  186.         if (!of_property_read_u32(np,"ath,mac-offset",&mac_offset))
  187.         {
  188.             memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data + mac_offset, 6);
  189.         }
  190.         else
  191.         {
  192.             if (mac_res)
  193.             {
  194.                 if (resource_size(mac_res)!=6)
  195.                 {
  196.                     dev_err(&pdev->dev, "mac has an invalid size.\n");
  197.                     return -EINVAL;
  198.                 }
  199.                 mac=ioremap(mac_res->start, resource_size(mac_res));
  200.                 memcpy_fromio(athxk_eeprom_mac, mac, 6);
  201.             }
  202.             else
  203.             {
  204.                 dev_warn(&pdev->dev,"using random mac.\n");
  205.                 random_ether_addr(athxk_eeprom_mac);
  206.             }
  207.         }
  208.  
  209.         if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  210.             athxk_eeprom_mac[5]+=mac_inc;
  211.  
  212.         ath9k_pdata.macaddr=athxk_eeprom_mac;
  213.         ltq_pci_plat_dev_init=ath9k_pci_plat_dev_init;
  214.  
  215.         if (!of_property_read_u32(np,"ath,pci-slot", &pci_slot))
  216.         {
  217.             ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
  218.             dev_info(&pdev->dev,"pci slot: %u.\n",pci_slot);
  219.         }
  220.     }
  221.  
  222.     dev_info(&pdev->dev, "loaded ath9k eeprom\n");
  223.  
  224.     return 0;
  225. }
  226.  
  227. static struct of_device_id ath9k_eeprom_ids[] = {
  228.     { .compatible = "ath9k,eeprom" },
  229.     { }
  230. };
  231.  
  232. static struct platform_driver ath9k_eeprom_driver = {
  233.     .driver     = {
  234.         .name       = "ath9k,eeprom",
  235.         .owner  = THIS_MODULE,
  236.         .of_match_table = of_match_ptr(ath9k_eeprom_ids),
  237.     },
  238. };
  239.  
  240. static int __init of_ath9k_eeprom_init(void)
  241. {
  242.     int ret = platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
  243.  
  244.     if (ret)
  245.         ath9k_eep_load = 1;
  246.  
  247.     return ret;
  248. }
  249.  
  250. static int __init of_ath9k_eeprom_init_late(void)
  251. {
  252.     if (!ath9k_eep_load)
  253.         return 0;
  254.     return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
  255. }
  256. late_initcall(of_ath9k_eeprom_init_late);
  257. subsys_initcall(of_ath9k_eeprom_init);
  258.  
  259. static int ath5k_pci_plat_dev_init(struct pci_dev *dev)
  260. {
  261.     dev->dev.platform_data = &ath5k_pdata;
  262.     return 0;
  263. }
  264.  
  265. int __init of_ath5k_eeprom_probe(struct platform_device *pdev)
  266. {
  267.     struct device_node *np = pdev->dev.of_node, *mtd_np;
  268.     struct resource *eep_res, *mac_res;
  269.     void __iomem *eep, *mac;
  270.     int mac_offset;
  271.     u32 mac_inc = 0, pci_slot = 0;
  272.     int i;
  273.     u16 *eepdata, sum, el;
  274.     struct mtd_info *the_mtd;
  275.     size_t flash_readlen;
  276.     const __be32 *list;
  277.     const char *part;
  278.     phandle phandle;
  279.  
  280.     if (!of_find_property(np,"ath,arv-ath5k-fix",NULL))
  281.     {
  282.         list = of_get_property(np, "ath,eep-flash", &i);
  283.         if (!list || (i !=  (2 * sizeof(*list)))) {
  284.             dev_err(&pdev->dev, "failed to find ath,eep-flash\n");
  285.             return -ENODEV;
  286.         }
  287.  
  288.         phandle = be32_to_cpup(list++);
  289.         if (!phandle) {
  290.             dev_err(&pdev->dev, "failed to find phandle\n");
  291.             return -ENODEV;
  292.         }
  293.  
  294.         mtd_np = of_find_node_by_phandle(phandle);
  295.         if (!mtd_np) {
  296.             dev_err(&pdev->dev, "failed to find mtd node\n");
  297.             return -ENODEV;
  298.         }
  299.  
  300.         part = of_get_property(mtd_np, "label", NULL);
  301.         if (!part)
  302.             part = mtd_np->name;
  303.  
  304.         the_mtd = get_mtd_device_nm(part);
  305.         if (the_mtd == ERR_PTR(-ENODEV)) {
  306.             dev_err(&pdev->dev, "failed to find mtd device\n");
  307.             return -ENODEV;
  308.         }
  309.  
  310.         i = mtd_read(the_mtd, be32_to_cpup(list),
  311.                 ATH5K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
  312.                 (void *) ath5k_pdata.eeprom_data);
  313.         put_mtd_device(the_mtd);
  314.         if ((sizeof(ath5k_pdata.eeprom_data) != flash_readlen) || i) {
  315.             dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
  316.             return -ENODEV;
  317.         }
  318.  
  319.         if (of_find_property(np, "ath,eep-swap", NULL))
  320.             for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS; i++)
  321.                 ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]);
  322.  
  323.         if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
  324.             memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data + mac_offset, 6);
  325.         } else {
  326.             random_ether_addr(athxk_eeprom_mac);
  327.             if (of_get_mac_address_mtd(np, athxk_eeprom_mac))
  328.                 dev_warn(&pdev->dev, "using random mac\n");
  329.         }
  330.  
  331.         if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  332.             athxk_eeprom_mac[5] += mac_inc;
  333.  
  334.         ath5k_pdata.macaddr = athxk_eeprom_mac;
  335.         ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
  336.     }
  337.     else
  338.     {
  339.         /* ath5k patch for Arcadyan/Astoria boards. */
  340.  
  341.         eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  342.         mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  343.  
  344.         dev_info(&pdev->dev,"eeprom expected size : %u\n",ATH5K_PLAT_EEP_MAX_WORDS<<1);
  345.         dev_info(&pdev->dev,"mac expected size : %u\n",6);
  346.         dev_info(&pdev->dev,"eeprom read size : %u\n",resource_size(eep_res));
  347.         dev_info(&pdev->dev,"mac address size : %u\n",resource_size(mac_res));
  348.  
  349.         if (!eep_res)
  350.         {
  351.             dev_err(&pdev->dev, "failed to load eeprom addres\n");
  352.             return -ENODEV;
  353.         }
  354.         if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS<<1)
  355.         {
  356.             dev_err(&pdev->dev, "eeprom size mismatch\n");
  357.             return -EINVAL;
  358.         }
  359.  
  360.         eep = ioremap(eep_res->start, resource_size(eep_res));
  361.  
  362.         ath5k_pdata.eeprom_data=kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1,GFP_KERNEL);
  363.         memcpy_fromio(ath5k_pdata.eeprom_data, eep, ATH5K_PLAT_EEP_MAX_WORDS<<1);
  364.  
  365.         if (of_find_property(np, "ath,eep-swap",NULL))
  366.         {
  367.             for (i=0; i<ATH5K_PLAT_EEP_MAX_WORDS; i++)
  368.                 ath5k_pdata.eeprom_data[i]=swab16(ath5k_pdata.eeprom_data[i]);
  369.         }
  370.  
  371.         if (of_find_property(np, "ath,eep-csum", NULL))
  372.         {
  373.             sum=ath5k_pdata.eeprom_data[0x200>>1];
  374.             el=sum/sizeof(u16)-2;       /* skip length and old cheksum */
  375.             eepdata=(u16 *)(&ath5k_pdata.eeprom_data[0x204>>1]);    /* after cheksum */
  376.             for (i=0; i<el; i++)
  377.                 sum^=*eepdata++;
  378.             sum^=0xffff;
  379.             ath5k_pdata.eeprom_data[0x202>>1]=sum;
  380.             dev_info(&pdev->dev,"checksum fixed.\n");
  381.         }
  382.  
  383.         if (!of_property_read_u32(np,"ath,mac-offset",&mac_offset))
  384.         {
  385.             memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data + mac_offset, 6);
  386.         }
  387.         else
  388.         {
  389.             if (mac_res)
  390.             {
  391.                 if (resource_size(mac_res)!=6)
  392.                 {
  393.                     dev_err(&pdev->dev, "mac has an invalid size.\n");
  394.                     return -EINVAL;
  395.                 }
  396.                 dev_info(&pdev->dev,"loading MAC.\n");
  397.                 mac=ioremap(mac_res->start, resource_size(mac_res));
  398.                 memcpy_fromio(athxk_eeprom_mac, mac, 6);
  399.                 dev_info(&pdev->dev,"loaded MAC.\n");
  400.             }
  401.             else
  402.             {
  403.                 dev_warn(&pdev->dev,"using random mac.\n");
  404.                 random_ether_addr(athxk_eeprom_mac);
  405.             }
  406.         }
  407.  
  408.         if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  409.             athxk_eeprom_mac[5]+=mac_inc;
  410.  
  411.         ath5k_pdata.macaddr=athxk_eeprom_mac;
  412.         ltq_pci_plat_dev_init=ath5k_pci_plat_dev_init;
  413.  
  414.         if (!of_property_read_u32(np,"ath,pci-slot", &pci_slot))
  415.         {
  416.             ltq_pci_ath_fixup(pci_slot, ath5k_pdata.eeprom_data);
  417.             dev_info(&pdev->dev,"pci slot: %u.\n",pci_slot);
  418.         }
  419.         dev_info(&pdev->dev,"eeprom init finished.\n");
  420.     }
  421.  
  422.     dev_info(&pdev->dev, "loaded ath5k eeprom\n");
  423.  
  424.     return 0;
  425. }
  426.  
  427. static struct of_device_id ath5k_eeprom_ids[] = {
  428.     { .compatible = "ath5k,eeprom" },
  429.     { }
  430. };
  431.  
  432. static struct platform_driver ath5k_eeprom_driver = {
  433.     .driver     = {
  434.         .name       = "ath5k,eeprom",
  435.         .owner  = THIS_MODULE,
  436.         .of_match_table = of_match_ptr(ath5k_eeprom_ids),
  437.     },
  438. };
  439.  
  440. static int __init of_ath5k_eeprom_init(void)
  441. {
  442.     return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe);
  443. }
  444. subsys_initcall(of_ath5k_eeprom_init);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement