Guest User

ARV4518PWR01 wireless working (TKI2000, brunorro)

a guest
Mar 22nd, 2014
184
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. int __init of_ath9k_eeprom_probe(struct platform_device *pdev)
  40. {
  41.         struct device_node *np = pdev->dev.of_node, *mtd_np;
  42.         struct resource *eep_res, *mac_res;
  43.         void __iomem *eep, *mac;
  44.         int mac_offset;
  45.         u32 mac_inc = 0, pci_slot = 0;
  46.         int i;
  47.         u16 *eepdata, sum, el;
  48.         struct mtd_info *the_mtd;
  49.         size_t flash_readlen;
  50.         const __be32 *list;
  51.         const char *part;
  52.         phandle phandle;
  53.         //struct property *pp;
  54.         //struct device_node *dn;
  55.  
  56.         if (!of_find_property(np,"ath,arv7518pw-fix",NULL))
  57.         {
  58.                 list = of_get_property(np, "ath,eep-flash", &i);
  59.                 if (!list || (i !=  (2 * sizeof(*list))))
  60.                 {
  61.                         dev_err(&pdev->dev, "failed to find ath,eep-flash\n");
  62.                         return -ENODEV;
  63.                 }
  64.  
  65.                 phandle = be32_to_cpup(list++);
  66.                 if (!phandle)
  67.                 {
  68.                         dev_err(&pdev->dev, "failed to find phandle\n");
  69.                         return -ENODEV;
  70.                 }
  71.  
  72.                 mtd_np = of_find_node_by_phandle(phandle);
  73.                 if (!mtd_np)
  74.                 {
  75.                         dev_err(&pdev->dev, "failed to find mtd node\n");
  76.                         return -ENODEV;
  77.                 }
  78.  
  79.                 part = of_get_property(mtd_np, "label", NULL);
  80.                 if (!part)
  81.                         part = mtd_np->name;
  82.  
  83.                 the_mtd = get_mtd_device_nm(part);
  84.                 if (the_mtd == ERR_PTR(-ENODEV))
  85.                 {
  86.                         dev_err(&pdev->dev, "failed to find mtd device\n");
  87.                         return -ENODEV;
  88.                 }
  89.  
  90.                 i = mtd_read(the_mtd, be32_to_cpup(list),
  91.                         ATH9K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
  92.                         (void *) ath9k_pdata.eeprom_data);
  93.                 put_mtd_device(the_mtd);
  94.                 if ((sizeof(ath9k_pdata.eeprom_data) != flash_readlen) || i)
  95.                 {
  96.                         dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
  97.                         return -ENODEV;
  98.                 }
  99.  
  100.                 if (of_find_property(np, "ath,eep-swap", NULL))
  101.                         for (i = 0; i < ATH9K_PLAT_EEP_MAX_WORDS; i++)
  102.                                 ath9k_pdata.eeprom_data[i] = swab16(ath9k_pdata.eeprom_data[i]);
  103.  
  104.                 if (of_find_property(np, "ath,eep-endian", NULL))
  105.                 {
  106.                         ath9k_pdata.endian_check = true;
  107.                         dev_info(&pdev->dev, "endian check enabled.\n");
  108.                 }
  109.  
  110.                 if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset))
  111.                 {
  112.                         memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data + mac_offset, 6);
  113.                 }
  114.                 else
  115.                 {
  116.                         random_ether_addr(athxk_eeprom_mac);
  117.                         if (of_get_mac_address_mtd(np, athxk_eeprom_mac))
  118.                                 dev_warn(&pdev->dev, "using random mac\n");
  119.                 }
  120.  
  121.                 if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  122.                         athxk_eeprom_mac[5] += mac_inc;
  123.  
  124.                 ath9k_pdata.macaddr = athxk_eeprom_mac;
  125.                 ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
  126.  
  127.                 if (!of_property_read_u32(np, "ath,pci-slot", &pci_slot))
  128.                 {
  129.                         ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
  130.                         dev_info(&pdev->dev, "pci slot: %u\n", pci_slot);
  131.                 }
  132.         }
  133.         else
  134.         {
  135.                 // Noltari patch code arv7518pw
  136.  
  137.                 eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  138.                 mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  139.  
  140.                 dev_info(&pdev->dev,"eeprom expected size : %u\n",ATH9K_PLAT_EEP_MAX_WORDS<<1);
  141.                 dev_info(&pdev->dev,"mac expected size : %u\n",6);
  142.                 dev_info(&pdev->dev,"eeprom read size : %u\n",resource_size(eep_res));
  143.                 dev_info(&pdev->dev,"mac address size : %u\n",resource_size(mac_res));
  144.  
  145.                 if (!eep_res)
  146.                 {
  147.                         dev_err(&pdev->dev, "failed to load eeprom addres\n");
  148.                         return -ENODEV;
  149.                 }
  150.                 if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS<<1)
  151.                 {
  152.                         dev_err(&pdev->dev, "eeprom size mismatch\n");
  153.                         return -EINVAL;
  154.                 }
  155.  
  156.                 eep = ioremap(eep_res->start, resource_size(eep_res));
  157.                 memcpy_fromio(ath9k_pdata.eeprom_data, eep, ATH9K_PLAT_EEP_MAX_WORDS<<1);
  158.  
  159.                 if (of_find_property(np, "ath,eep-swap",NULL))
  160.                 {
  161.                         for (i=0; i<ATH9K_PLAT_EEP_MAX_WORDS; i++)
  162.                                 ath9k_pdata.eeprom_data[i]=swab16(ath9k_pdata.eeprom_data[i]);
  163.                 }
  164.  
  165.                 if (of_find_property(np, "ath,eep-endian",NULL))
  166.                 {
  167.                         ath9k_pdata.endian_check = "true";
  168.                         dev_info(&pdev->dev,"eeprom endian check enabled.\n");
  169.                 }
  170.  
  171.                 if (of_find_property(np, "ath,eep-csum", NULL))
  172.                 {
  173.                         sum=ath9k_pdata.eeprom_data[0x200>>1];
  174.                         el=sum/sizeof(u16)-2;           // skip length and old cheksum
  175.                         eepdata=(u16 *)(&ath9k_pdata.eeprom_data[0x204>>1]);            // after cheksum
  176.                         for (i=0; i<el; i++)
  177.                                 sum^=*eepdata++;
  178.                         sum^=0xffff;
  179.                         ath9k_pdata.eeprom_data[0x202>>1]=sum;
  180.                         dev_info(&pdev->dev,"checksum fixed.\n");
  181.                 }
  182.  
  183.                 if (!of_property_read_u32(np,"ath,mac-offset",&mac_offset))
  184.                 {
  185.                         memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data+mac_offset, 6);
  186.                 }
  187.                 else
  188.                 {
  189.                         if (mac_res)
  190.                         {
  191.                                 if (resource_size(mac_res)!=6)
  192.                                 {
  193.                                         dev_err(&pdev->dev, "mac has an invalid size.\n");
  194.                                         return -EINVAL;
  195.                                 }
  196.                                 mac=ioremap(mac_res->start, resource_size(mac_res));
  197.                                 memcpy_fromio(athxk_eeprom_mac, mac, 6);
  198.                         }
  199.                         else
  200.                         {
  201.                                 dev_warn(&pdev->dev,"using random mac.\n");
  202.                                 random_ether_addr(athxk_eeprom_mac);
  203.                         }
  204.                 }
  205.  
  206.                 if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  207.                         athxk_eeprom_mac[5]+=mac_inc;
  208.  
  209.                 ath9k_pdata.macaddr=athxk_eeprom_mac;
  210.                 ltq_pci_plat_dev_init=ath9k_pci_plat_dev_init;
  211.  
  212.                 if (!of_property_read_u32(np,"ath,pci-slot", &pci_slot))
  213.                 {
  214.                         ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
  215.                         dev_info(&pdev->dev,"pci slot: %u.\n",pci_slot);
  216.                 }
  217.         }
  218.  
  219.         dev_info(&pdev->dev, "loaded ath9k eeprom\n");
  220.  
  221.         return 0;
  222. }
  223.  
  224. static struct of_device_id ath9k_eeprom_ids[] = {
  225.         { .compatible = "ath9k,eeprom" },
  226.         { }
  227. };
  228.  
  229. static struct platform_driver ath9k_eeprom_driver = {
  230.         .driver         = {
  231.                 .name           = "ath9k,eeprom",
  232.                 .owner  = THIS_MODULE,
  233.                 .of_match_table = of_match_ptr(ath9k_eeprom_ids),
  234.         },
  235. };
  236.  
  237. static int ath9k_eep_loaded;
  238. static int __init of_ath9k_eeprom_init(void)
  239. {
  240.         int ret = platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
  241.  
  242.         if (!ret)
  243.                 ath9k_eep_loaded = 1;
  244.  
  245.         return ret;
  246. }
  247.  
  248. static int __init of_ath9k_eeprom_init_late(void)
  249. {
  250.         if (ath9k_eep_loaded)
  251.                 return 0;
  252.         return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
  253. }
  254. late_initcall(of_ath9k_eeprom_init_late);
  255. subsys_initcall(of_ath9k_eeprom_init);
  256.  
  257. static int ath5k_pci_plat_dev_init(struct pci_dev *dev)
  258. {
  259.         dev->dev.platform_data = &ath5k_pdata;
  260.         return 0;
  261. }
  262.  
  263. int __init of_ath5k_eeprom_probe(struct platform_device *pdev)
  264. {
  265.         struct device_node *np = pdev->dev.of_node, *mtd_np;
  266.         struct resource *eep_res, *mac_res;
  267.         void __iomem *eep, *mac;
  268.         int mac_offset;
  269.         u32 mac_inc = 0, pci_slot = 0;
  270.         int i;
  271.         u16 *eepdata, sum, el;
  272.         struct mtd_info *the_mtd;
  273.         size_t flash_readlen;
  274.         const __be32 *list;
  275.         const char *part;
  276.         phandle phandle;
  277.  
  278.         if (!of_find_property(np,"ath,arv4518pw-fix",NULL))
  279.         {
  280.  
  281.                 list = of_get_property(np, "ath,eep-flash", &i);
  282.                 if (!list || (i !=  (2 * sizeof(*list))))
  283.                 {
  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.                 {
  291.                         dev_err(&pdev->dev, "failed to find phandle\n");
  292.                         return -ENODEV;
  293.                 }
  294.  
  295.                 mtd_np = of_find_node_by_phandle(phandle);
  296.                 if (!mtd_np)
  297.                 {
  298.                         dev_err(&pdev->dev, "failed to find mtd node\n");
  299.                         return -ENODEV;
  300.                 }
  301.  
  302.                 part = of_get_property(mtd_np, "label", NULL);
  303.                 if (!part)
  304.                         part = mtd_np->name;
  305.  
  306.                 the_mtd = get_mtd_device_nm(part);
  307.                 if (the_mtd == ERR_PTR(-ENODEV))
  308.                 {
  309.                         dev_err(&pdev->dev, "failed to find mtd device\n");
  310.                         return -ENODEV;
  311.                 }
  312.  
  313.                 i = mtd_read(the_mtd, be32_to_cpup(list),
  314.                         ATH5K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
  315.                         (void *) ath5k_pdata.eeprom_data);
  316.                 put_mtd_device(the_mtd);
  317.                 if ((sizeof(ath5k_pdata.eeprom_data) != flash_readlen) || i)
  318.                 {
  319.                         dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
  320.                         return -ENODEV;
  321.                 }
  322.  
  323.                 if (of_find_property(np, "ath,eep-swap", NULL))
  324.                         for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS; i++)
  325.                                 ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]);
  326.  
  327.                 if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset))
  328.                 {
  329.                         memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data + mac_offset, 6);
  330.                 }
  331.                 else
  332.                 {
  333.                         random_ether_addr(athxk_eeprom_mac);
  334.                         if (of_get_mac_address_mtd(np, athxk_eeprom_mac))
  335.                                 dev_warn(&pdev->dev, "using random mac\n");
  336.                 }
  337.  
  338.                 if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  339.                         athxk_eeprom_mac[5] += mac_inc;
  340.  
  341.                 ath5k_pdata.macaddr = athxk_eeprom_mac;
  342.                 ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
  343.         }
  344.         else
  345.         {
  346.                 // Noltari patch for ath5k arv4518pw. Applicable for other ath5k lantiqs.
  347.  
  348.                 eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  349.                 mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  350.  
  351.                 dev_info(&pdev->dev,"eeprom expected size : %u\n",ATH5K_PLAT_EEP_MAX_WORDS<<1);
  352.                 dev_info(&pdev->dev,"mac expected size : %u\n",6);
  353.                 dev_info(&pdev->dev,"eeprom read size : %u\n",resource_size(eep_res));
  354.                 dev_info(&pdev->dev,"mac address size : %u\n",resource_size(mac_res));
  355.  
  356.                 if (!eep_res)
  357.                 {
  358.                         dev_err(&pdev->dev, "failed to load eeprom addres\n");
  359.                         return -ENODEV;
  360.                 }
  361.                 if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS<<1)
  362.                 {
  363.                         dev_err(&pdev->dev, "eeprom size mismatch\n");
  364.                         return -EINVAL;
  365.                 }
  366.  
  367.                 eep = ioremap(eep_res->start, resource_size(eep_res));
  368.                 ath5k_pdata.eeprom_data = kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1,GFP_KERNEL);
  369.                 memcpy_fromio(ath5k_pdata.eeprom_data, eep, ATH5K_PLAT_EEP_MAX_WORDS<<1);
  370.  
  371.                 if (of_find_property(np, "ath,eep-swap",NULL))
  372.                 {
  373.                         dev_info(&pdev->dev,"swapping eeprom nibbles\n");
  374.                         for (i=0; i<ATH5K_PLAT_EEP_MAX_WORDS; i++){
  375.                                 //dev_info(&pdev->dev,"swapping position %u\n", i);
  376.                                 ath5k_pdata.eeprom_data[i]=swab16(ath5k_pdata.eeprom_data[i]);
  377.                         }
  378.                         dev_info(&pdev->dev,"swapped\n");
  379.                 }
  380.  
  381.                 if (of_find_property(np, "ath,eep-csum", NULL))
  382.                 {
  383.                         sum=ath5k_pdata.eeprom_data[0x200>>1];
  384.                         el=sum/sizeof(u16)-2;           // skip length and old cheksum
  385.                         eepdata=(u16 *)(&ath5k_pdata.eeprom_data[0x204>>1]);            // after cheksum
  386.                         for (i=0; i<el; i++)
  387.                                 sum^=*eepdata++;
  388.                         sum^=0xffff;
  389.                         ath5k_pdata.eeprom_data[0x202>>1]=sum;
  390.                         dev_info(&pdev->dev,"checksum fixed.\n");
  391.                 }
  392.  
  393.                 if (!of_property_read_u32(np,"ath,mac-offset",&mac_offset))
  394.                 {
  395.                         memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data+mac_offset, 6);
  396.                 }
  397.                 else
  398.                 {
  399.                         if (mac_res)
  400.                         {
  401.                                 if (resource_size(mac_res)!=6)
  402.                                 {
  403.                                         dev_err(&pdev->dev, "mac has an invalid size.\n");
  404.                                         return -EINVAL;
  405.                                 }
  406.                                 dev_info(&pdev->dev,"loading MAC.\n");
  407.                                 mac=ioremap(mac_res->start, resource_size(mac_res));
  408.                                 memcpy_fromio(athxk_eeprom_mac, mac, 6);
  409.                                 dev_info(&pdev->dev,"loaded MAC.\n");
  410.                         }
  411.                         else
  412.                         {
  413.                                 dev_warn(&pdev->dev,"using random mac.\n");
  414.                                 random_ether_addr(athxk_eeprom_mac);
  415.                         }
  416.                 }
  417.  
  418.                 if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
  419.                         athxk_eeprom_mac[5]+=mac_inc;
  420.  
  421.                 ath5k_pdata.macaddr=athxk_eeprom_mac;
  422.                 ltq_pci_plat_dev_init=ath5k_pci_plat_dev_init;
  423.  
  424.                 if (!of_property_read_u32(np,"ath,pci-slot", &pci_slot))
  425.                 {
  426.                         ltq_pci_ath_fixup(pci_slot, ath5k_pdata.eeprom_data);
  427.                         dev_info(&pdev->dev,"pci slot: %u.\n",pci_slot);
  428.                 }
  429.                 dev_info(&pdev->dev,"eeprom init finished.\n");
  430.         }
  431.  
  432.         dev_info(&pdev->dev, "loaded ath5k eeprom\n");
  433.  
  434.         return 0;
  435. }
  436.  
  437. static struct of_device_id ath5k_eeprom_ids[] = {
  438.         { .compatible = "ath5k,eeprom" },
  439.         { }
  440. };
  441.  
  442. static struct platform_driver ath5k_eeprom_driver = {
  443.         .driver         = {
  444.                 .name           = "ath5k,eeprom",
  445.                 .owner  = THIS_MODULE,
  446.                 .of_match_table = of_match_ptr(ath5k_eeprom_ids),
  447.         },
  448. };
  449.  
  450. static int __init of_ath5k_eeprom_init(void)
  451. {
  452.         return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe);
  453. }
  454. //#device_initcall(of_ath5k_eeprom_init);
  455. subsys_initcall(of_ath5k_eeprom_init);
RAW Paste Data