EEPROM fix for Astoria/Arcadyan boards.

This patch fixes a problem in some Astoria/Arcadyan routers with Atheros
based wireless. In these boards the flash partition that contains the
MAC and calibration data is not read properly, causing the driver to not
initialize the wireless.

[   13.772000] PCI: Enabling device 0000:00:0e.0 (0000 -> 0002)
[   13.776000] ath5k 0000:00:0e.0: registered as 'phy0'
[   15.024000] ath5k: phy0: unable to init EEPROM
[   15.024000] ath5k: probe of 0000:00:0e.0 failed with error -5

This patch covers both ath5k and ath9k drivers.

Signed off by: David Fernández <papijunkm...@yahoo.com>
Signed off by: Bruno Rodríguez <bruno.rodriguez.1...@gmail.com>
Signed off by: Álvaro Fernández <nolt...@gmail.com>
Tested by: José Vázquez Fernández <ppvazquez...@gmail.com>


Index: target/linux/lantiq/patches-3.10/0203-arv-athx-workaround.patch
===================================================================
--- target/linux/lantiq/patches-3.10/0203-arv-athx-workaround.patch
(revisión: 0)
+++ target/linux/lantiq/patches-3.10/0203-arv-athx-workaround.patch
(revisión: 0)
@@ -0,0 +1,447 @@
+--- a/arch/mips/lantiq/xway/ath_eep.c
++++ b/arch/mips/lantiq/xway/ath_eep.c
+@@ -41,94 +41,182 @@ int __init of_ath9k_eeprom_probe(struct
+ {
+       struct device_node *np = pdev->dev.of_node, *mtd_np;
+       int mac_offset, led_pin;
++      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;
+ 
+-      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;
+-      }
++      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;
+-      }
++              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;
+-      }
++              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;
+-      }
++              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),
++              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;
+-      }
++              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-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_find_property(np, "ath,eep-endian", NULL)) {
+-              ath9k_pdata.endian_check = true;
++              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;
+ 
+-              dev_info(&pdev->dev, "endian check enabled.\n");
+-      }
++              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);
++              }
++              if (!of_property_read_u32(np, "ath,led-pin", &led_pin)) {
++                      ath9k_pdata.led_pin = led_pin;
++
++                      dev_info(&pdev->dev, "using led pin %d.\n", led_pin);
++              }
+ 
+-      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");
+       }
++      else
++      {
++              /* Noltari's patch for ath9k.*/
++
++              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;
++              }
+ 
+-      if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
+-              athxk_eeprom_mac[5] += mac_inc;
++              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]);
++              }
+ 
+-      ath9k_pdata.macaddr = athxk_eeprom_mac;
+-      ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
++              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_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);
+-              if (ath9k_eep_load) {
+-                      struct pci_dev *d = NULL;
+-                      while ((d = pci_get_device(PCI_VENDOR_ID_ATHEROS,
+-                                      PCI_ANY_ID, d)) != NULL)
+-                              pci_fixup_device(pci_fixup_early, d);
++              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,led-pin", &led_pin)) {
+-              ath9k_pdata.led_pin = led_pin;
++              if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
++                      athxk_eeprom_mac[5]+=mac_inc;
+ 
+-              dev_info(&pdev->dev, "using led pin %d.\n", led_pin);
++              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;
+ }
+ 
+@@ -173,69 +261,157 @@ static int ath5k_pci_plat_dev_init(struc
+ 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;
++      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;
+ 
+-      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;
+-      }
++      if (!of_find_property(np,"ath,arv-ath5k-fix",NULL))
++      {
+ 
+-      phandle = be32_to_cpup(list++);
+-      if (!phandle) {
+-              dev_err(&pdev->dev, "failed to find phandle\n");
+-              return -ENODEV;
+-      }
++              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;
++              }
+ 
+-      mtd_np = of_find_node_by_phandle(phandle);
+-      if (!mtd_np) {
+-              dev_err(&pdev->dev, "failed to find mtd node\n");
+-              return -ENODEV;
+-      }
++              phandle = be32_to_cpup(list++);
++              if (!phandle) {
++                      dev_err(&pdev->dev, "failed to find phandle\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;
+-      }
++              mtd_np = of_find_node_by_phandle(phandle);
++              if (!mtd_np) {
++                      dev_err(&pdev->dev, "failed to find mtd node\n");
++                      return -ENODEV;
++              }
+ 
+-      i = mtd_read(the_mtd, be32_to_cpup(list),
++              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;
+-      }
++              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(ath9k_pdata.eeprom_data[i]);
++              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;
+ 
+-      if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
+-              memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data 
+
mac_offset, 6);
++              ath5k_pdata.macaddr = athxk_eeprom_mac;
++              ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
+       } 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");
+-      }
++              /* Noltari's patch for ath5k.*/
+ 
+-      if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
+-              athxk_eeprom_mac[5] += mac_inc;
++              eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++              mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ 
+-      ath5k_pdata.macaddr = athxk_eeprom_mac;
+-      ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
++              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");
+ 
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to