Add ath9k eeprom and pci fixup support
[librecmc/librecmc.git] / target / linux / lantiq / patches-3.7 / 0302-wifi-eep.patch
1 Index: linux-3.7.4/arch/mips/lantiq/xway/Makefile
2 ===================================================================
3 --- linux-3.7.4.orig/arch/mips/lantiq/xway/Makefile     2013-01-28 18:08:39.000000000 +0100
4 +++ linux-3.7.4/arch/mips/lantiq/xway/Makefile  2013-01-28 18:10:31.416141818 +0100
5 @@ -1,3 +1,6 @@
6  obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
7  
8 +obj-y += eth_mac.o
9 +obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
10 +
11  obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
12 Index: linux-3.7.4/arch/mips/lantiq/xway/ath_eep.c
13 ===================================================================
14 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
15 +++ linux-3.7.4/arch/mips/lantiq/xway/ath_eep.c 2013-01-28 18:13:43.256146389 +0100
16 @@ -0,0 +1,206 @@
17 +/*
18 + *  Copyright (C) 2011 Luca Olivetti <luca@ventoso.org>
19 + *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
20 + *  Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com>
21 + *  Copyright (C) 2013 Álvaro Fernández Rojas <noltari@gmail.com>
22 + *
23 + *  This program is free software; you can redistribute it and/or modify it
24 + *  under the terms of the GNU General Public License version 2 as published
25 + *  by the Free Software Foundation.
26 + */
27 +
28 +#include <linux/init.h>
29 +#include <linux/module.h>
30 +#include <linux/platform_device.h>
31 +#include <linux/etherdevice.h>
32 +#include <linux/ath5k_platform.h>
33 +#include <linux/ath9k_platform.h>
34 +#include <linux/pci.h>
35 +#include <pci-ath-fixup.h>
36 +
37 +extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
38 +struct ath5k_platform_data ath5k_pdata;
39 +struct ath9k_platform_data ath9k_pdata = {
40 +       .led_pin = -1,
41 +};
42 +static u16 ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
43 +static u8 athxk_eeprom_mac[6];
44 +
45 +static int ath9k_pci_plat_dev_init(struct pci_dev *dev)
46 +{
47 +       dev->dev.platform_data = &ath9k_pdata;
48 +       return 0;
49 +}
50 +
51 +int __init of_ath9k_eeprom_probe(struct platform_device *pdev)
52 +{
53 +       struct device_node *np = pdev->dev.of_node;
54 +       struct resource *eep_res, *mac_res;
55 +       void __iomem *eep, *mac;
56 +       int mac_offset;
57 +       u32 mac_inc = 0, pci_slot = 0;
58 +       int i;
59 +       u16 *eepdata, sum, el;
60 +
61 +       eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
62 +       mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
63 +
64 +       if (!eep_res) {
65 +               dev_err(&pdev->dev, "failed to load eeprom address\n");
66 +               return -ENODEV;
67 +       }
68 +       if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS) {
69 +               dev_err(&pdev->dev, "eeprom has an invalid size\n");
70 +               return -EINVAL;
71 +       }
72 +
73 +       eep = ioremap(eep_res->start, resource_size(eep_res));
74 +       memcpy_fromio(ath9k_pdata.eeprom_data, eep, ATH9K_PLAT_EEP_MAX_WORDS);
75 +
76 +       if (of_find_property(np, "ath,eep-swap", NULL)) {
77 +               ath9k_pdata.endian_check = true;
78 +
79 +               dev_info(&pdev->dev, "endian check enabled.\n");
80 +       }
81 +
82 +       if (of_find_property(np, "ath,eep-csum", NULL)) {
83 +               sum = ath9k_pdata.eeprom_data[0x200>>1];
84 +               el = sum / sizeof(u16) - 2;  /* skip length and (old) checksum */
85 +               eepdata = (u16 *) (&ath9k_pdata.eeprom_data[0x204>>1]); /* after checksum */
86 +               for (i = 0; i < el; i++)
87 +                       sum ^= *eepdata++;
88 +               sum ^= 0xffff;
89 +               ath9k_pdata.eeprom_data[0x202>>1] = sum;
90 +
91 +               dev_info(&pdev->dev, "checksum fixed.\n");
92 +       }
93 +
94 +       if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
95 +               memcpy_fromio(athxk_eeprom_mac, (void*) ath9k_pdata.eeprom_data, 6);
96 +       } else if (mac_res) {
97 +               if (resource_size(mac_res) != 6) {
98 +                       dev_err(&pdev->dev, "mac has an invalid size\n");
99 +                       return -EINVAL;
100 +               }
101 +               mac = ioremap(mac_res->start, resource_size(mac_res));
102 +               memcpy_fromio(athxk_eeprom_mac, mac, 6);
103 +       } else {
104 +               dev_warn(&pdev->dev, "using random mac\n");
105 +               random_ether_addr(athxk_eeprom_mac);
106 +       }
107 +
108 +       if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
109 +               athxk_eeprom_mac[5] += mac_inc;
110 +
111 +       ath9k_pdata.macaddr = athxk_eeprom_mac;
112 +       ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
113 +
114 +       if (!of_property_read_u32(np, "ath,pci-slot", &pci_slot)) {
115 +               ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
116 +
117 +               dev_info(&pdev->dev, "pci slot: %u\n", pci_slot);
118 +       }
119 +
120 +       dev_info(&pdev->dev, "loaded ath9k eeprom\n");
121 +
122 +       return 0;
123 +}
124 +
125 +static struct of_device_id ath9k_eeprom_ids[] = {
126 +       { .compatible = "ath9k,eeprom" },
127 +       { }
128 +};
129 +
130 +static struct platform_driver ath9k_eeprom_driver = {
131 +       .driver         = {
132 +               .name           = "ath9k,eeprom",
133 +               .owner  = THIS_MODULE,
134 +               .of_match_table = of_match_ptr(ath9k_eeprom_ids),
135 +       },
136 +};
137 +
138 +static int __init of_ath9k_eeprom_init(void)
139 +{
140 +       return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
141 +}
142 +arch_initcall(of_ath9k_eeprom_init);
143 +
144 +
145 +static int ath5k_pci_plat_dev_init(struct pci_dev *dev)
146 +{
147 +       dev->dev.platform_data = &ath5k_pdata;
148 +       return 0;
149 +}
150 +
151 +int __init of_ath5k_eeprom_probe(struct platform_device *pdev)
152 +{
153 +       struct device_node *np = pdev->dev.of_node;
154 +       struct resource *eep_res, *mac_res;
155 +       void __iomem *eep, *mac;
156 +       int mac_offset;
157 +       u32 mac_inc = 0;
158 +       int i;
159 +
160 +       eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
161 +       mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
162 +
163 +       if (!eep_res) {
164 +               dev_err(&pdev->dev, "failed to load eeprom address\n");
165 +               return -ENODEV;
166 +       }
167 +       if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS) {
168 +               dev_err(&pdev->dev, "eeprom has an invalid size\n");
169 +               return -EINVAL;
170 +       }
171 +
172 +       eep = ioremap(eep_res->start, resource_size(eep_res));
173 +       memcpy_fromio(ath5k_eeprom_data, eep, ATH5K_PLAT_EEP_MAX_WORDS);
174 +
175 +       if (of_find_property(np, "ath,eep-swap", NULL))
176 +               for (i = 0; i < (ATH5K_PLAT_EEP_MAX_WORDS >> 1); i++)
177 +                               ath5k_eeprom_data[i] = swab16(ath5k_eeprom_data[i]);
178 +
179 +       if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
180 +               memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_eeprom_data, 6);
181 +       } else if (mac_res) {
182 +               if (resource_size(mac_res) != 6) {
183 +                       dev_err(&pdev->dev, "mac has an invalid size\n");
184 +                       return -EINVAL;
185 +               }
186 +               mac = ioremap(mac_res->start, resource_size(mac_res));
187 +               memcpy_fromio(athxk_eeprom_mac, mac, 6);
188 +       } else {
189 +               dev_warn(&pdev->dev, "using random mac\n");
190 +               random_ether_addr(athxk_eeprom_mac);
191 +       }
192 +
193 +       if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
194 +               athxk_eeprom_mac[5] += mac_inc;
195 +
196 +       ath5k_pdata.eeprom_data = ath5k_eeprom_data;
197 +       ath5k_pdata.macaddr = athxk_eeprom_mac;
198 +       ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
199 +
200 +       dev_info(&pdev->dev, "loaded ath5k eeprom\n");
201 +
202 +       return 0;
203 +}
204 +
205 +static struct of_device_id ath5k_eeprom_ids[] = {
206 +       { .compatible = "ath5k,eeprom" },
207 +       { }
208 +};
209 +
210 +static struct platform_driver ath5k_eeprom_driver = {
211 +       .driver         = {
212 +               .name           = "ath5k,eeprom",
213 +               .owner  = THIS_MODULE,
214 +               .of_match_table = of_match_ptr(ath5k_eeprom_ids),
215 +       },
216 +};
217 +
218 +static int __init of_ath5k_eeprom_init(void)
219 +{
220 +       return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe);
221 +}
222 +device_initcall(of_ath5k_eeprom_init);
223 Index: linux-3.7.4/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
224 ===================================================================
225 --- linux-3.7.4.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h        2013-01-28 18:08:38.000000000 +0100
226 +++ linux-3.7.4/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h     2013-01-28 18:10:03.616141155 +0100
227 @@ -90,5 +90,8 @@
228  extern void ltq_pmu_enable(unsigned int module);
229  extern void ltq_pmu_disable(unsigned int module);
230  
231 +/* allow the ethernet driver to load a flash mapped mac addr */
232 +const u8* ltq_get_eth_mac(void);
233 +
234  #endif /* CONFIG_SOC_TYPE_XWAY */
235  #endif /* _LTQ_XWAY_H__ */
236 Index: linux-3.7.4/arch/mips/lantiq/xway/eth_mac.c
237 ===================================================================
238 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
239 +++ linux-3.7.4/arch/mips/lantiq/xway/eth_mac.c 2013-01-28 18:10:03.620141154 +0100
240 @@ -0,0 +1,76 @@
241 +/*
242 + *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
243 + *
244 + *  This program is free software; you can redistribute it and/or modify it
245 + *  under the terms of the GNU General Public License version 2 as published
246 + *  by the Free Software Foundation.
247 + */
248 +
249 +#include <linux/init.h>
250 +#include <linux/module.h>
251 +#include <linux/of_platform.h>
252 +#include <linux/if_ether.h>
253 +
254 +static u8 eth_mac[6];
255 +static int eth_mac_set;
256 +
257 +const u8* ltq_get_eth_mac(void)
258 +{
259 +       return eth_mac;
260 +}
261 +
262 +static int __init setup_ethaddr(char *str)
263 +{
264 +       eth_mac_set = mac_pton(str, eth_mac);
265 +       return !eth_mac_set;
266 +}
267 +__setup("ethaddr=", setup_ethaddr);
268 +
269 +int __init of_eth_mac_probe(struct platform_device *pdev)
270 +{
271 +       struct device_node *np = pdev->dev.of_node;
272 +       struct resource *mac_res;
273 +       void __iomem *mac;
274 +       u32 mac_inc = 0;
275 +
276 +       if (eth_mac_set) {
277 +               dev_err(&pdev->dev, "mac was already set by bootloader\n");
278 +               return -EINVAL;
279 +       }
280 +       mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
281 +
282 +       if (!mac_res) {
283 +               dev_err(&pdev->dev, "failed to load mac\n");
284 +               return -EINVAL;
285 +       }
286 +       if (resource_size(mac_res) != 6) {
287 +               dev_err(&pdev->dev, "mac has an invalid size\n");
288 +               return -EINVAL;
289 +       }
290 +       mac = ioremap(mac_res->start, resource_size(mac_res));
291 +       memcpy_fromio(eth_mac, mac, 6);
292 +
293 +       if (!of_property_read_u32(np, "mac-increment", &mac_inc))
294 +               eth_mac[5] += mac_inc;
295 +
296 +       return 0;
297 +}
298 +
299 +static struct of_device_id eth_mac_ids[] = {
300 +       { .compatible = "lantiq,eth-mac" },
301 +       { /* sentinel */ }
302 +};
303 +
304 +static struct platform_driver eth_mac_driver = {
305 +       .driver         = {
306 +               .name           = "lantiq,eth-mac",
307 +               .owner  = THIS_MODULE,
308 +               .of_match_table = of_match_ptr(eth_mac_ids),
309 +       },
310 +};
311 +
312 +static int __init of_eth_mac_init(void)
313 +{
314 +       return platform_driver_probe(&eth_mac_driver, of_eth_mac_probe);
315 +}
316 +device_initcall(of_eth_mac_init);
317 Index: linux-3.7.4/drivers/net/ethernet/lantiq_etop.c
318 ===================================================================
319 --- linux-3.7.4.orig/drivers/net/ethernet/lantiq_etop.c 2013-01-28 18:08:39.000000000 +0100
320 +++ linux-3.7.4/drivers/net/ethernet/lantiq_etop.c      2013-01-28 18:10:03.620141154 +0100
321 @@ -825,7 +825,8 @@
322  
323         ltq_etop_change_mtu(dev, 1500);
324  
325 -       memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
326 +       if (priv->mac)
327 +               memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
328         if (!is_valid_ether_addr(mac.sa_data)) {
329                 pr_warn("etop: invalid MAC, using random\n");
330                 random_ether_addr(mac.sa_data);
331 @@ -949,7 +950,9 @@
332         priv->tx_irq = irqres[0].start;
333         priv->rx_irq = irqres[1].start;
334         priv->mii_mode = of_get_phy_mode(pdev->dev.of_node);
335 -       priv->mac = of_get_mac_address(pdev->dev.of_node);
336 +       priv->mac = ltq_get_eth_mac();
337 +       if (!priv->mac)
338 +               priv->mac = of_get_mac_address(pdev->dev.of_node);
339  
340         priv->clk_ppe = clk_get(&pdev->dev, NULL);
341         if (IS_ERR(priv->clk_ppe))
342 Index: linux-3.7.4/arch/mips/lantiq/xway/rt_eep.c
343 ===================================================================
344 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
345 +++ linux-3.7.4/arch/mips/lantiq/xway/rt_eep.c  2013-01-28 18:10:03.620141154 +0100
346 @@ -0,0 +1,60 @@
347 +/*
348 + *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
349 + *
350 + *  This program is free software; you can redistribute it and/or modify it
351 + *  under the terms of the GNU General Public License version 2 as published
352 + *  by the Free Software Foundation.
353 + */
354 +
355 +#include <linux/init.h>
356 +#include <linux/module.h>
357 +#include <linux/pci.h>
358 +#include <linux/platform_device.h>
359 +#include <linux/rt2x00_platform.h>
360 +
361 +extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
362 +static struct rt2x00_platform_data rt2x00_pdata;
363 +
364 +static int rt2x00_pci_plat_dev_init(struct pci_dev *dev)
365 +{
366 +       dev->dev.platform_data = &rt2x00_pdata;
367 +       return 0;
368 +}
369 +
370 +int __init of_ralink_eeprom_probe(struct platform_device *pdev)
371 +{
372 +       struct device_node *np = pdev->dev.of_node;
373 +       const char *eeprom;
374 +
375 +       if (of_property_read_string(np, "ralink,eeprom", &eeprom)) {
376 +               dev_err(&pdev->dev, "failed to load eeprom filename\n");
377 +               return 0;
378 +       }
379 +
380 +       rt2x00_pdata.eeprom_file_name = kstrdup(eeprom, GFP_KERNEL);
381 +//     rt2x00_pdata.mac_address = mac;
382 +       ltq_pci_plat_dev_init = rt2x00_pci_plat_dev_init;
383 +
384 +       dev_info(&pdev->dev, "using %s as eeprom\n", eeprom);
385 +
386 +       return 0;
387 +}
388 +
389 +static struct of_device_id ralink_eeprom_ids[] = {
390 +       { .compatible = "ralink,eeprom" },
391 +       { }
392 +};
393 +
394 +static struct platform_driver ralink_eeprom_driver = {
395 +       .driver         = {
396 +               .name           = "ralink,eeprom",
397 +               .owner  = THIS_MODULE,
398 +               .of_match_table = of_match_ptr(ralink_eeprom_ids),
399 +       },
400 +};
401 +
402 +static int __init of_ralink_eeprom_init(void)
403 +{
404 +       return platform_driver_probe(&ralink_eeprom_driver, of_ralink_eeprom_probe);
405 +}
406 +device_initcall(of_ralink_eeprom_init);
407 Index: linux-3.7.4/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
408 ===================================================================
409 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
410 +++ linux-3.7.4/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h       2013-01-28 18:10:03.620141154 +0100
411 @@ -0,0 +1,6 @@
412 +#ifndef _PCI_ATH_FIXUP
413 +#define _PCI_ATH_FIXUP
414 +
415 +void ltq_pci_ath_fixup(unsigned slot, u16 *cal_data) __init;
416 +
417 +#endif /* _PCI_ATH_FIXUP */
418 Index: linux-3.7.4/arch/mips/lantiq/xway/pci-ath-fixup.c
419 ===================================================================
420 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
421 +++ linux-3.7.4/arch/mips/lantiq/xway/pci-ath-fixup.c   2013-01-28 18:10:03.624141153 +0100
422 @@ -0,0 +1,109 @@
423 +/*
424 + *  Atheros AP94 reference board PCI initialization
425 + *
426 + *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
427 + *
428 + *  This program is free software; you can redistribute it and/or modify it
429 + *  under the terms of the GNU General Public License version 2 as published
430 + *  by the Free Software Foundation.
431 + */
432 +
433 +#include <linux/pci.h>
434 +#include <linux/init.h>
435 +#include <linux/delay.h>
436 +#include <lantiq_soc.h>
437 +
438 +#define LTQ_PCI_MEM_BASE               0x18000000
439 +
440 +struct ath_fixup {
441 +       u16             *cal_data;
442 +       unsigned        slot;
443 +};
444 +
445 +static int ath_num_fixups;
446 +static struct ath_fixup ath_fixups[2];
447 +
448 +static void ath_pci_fixup(struct pci_dev *dev)
449 +{
450 +       void __iomem *mem;
451 +       u16 *cal_data = NULL;
452 +       u16 cmd;
453 +       u32 bar0;
454 +       u32 val;
455 +       unsigned i;
456 +
457 +       for (i = 0; i < ath_num_fixups; i++) {
458 +               if (ath_fixups[i].cal_data == NULL)
459 +                       continue;
460 +
461 +               if (ath_fixups[i].slot != PCI_SLOT(dev->devfn))
462 +                       continue;
463 +
464 +               cal_data = ath_fixups[i].cal_data;
465 +               break;
466 +       }
467 +
468 +       if (cal_data == NULL)
469 +               return;
470 +
471 +       if (*cal_data != 0xa55a) {
472 +               pr_err("pci %s: invalid calibration data\n", pci_name(dev));
473 +               return;
474 +       }
475 +
476 +       pr_info("pci %s: fixup device configuration\n", pci_name(dev));
477 +
478 +       mem = ioremap(LTQ_PCI_MEM_BASE, 0x10000);
479 +       if (!mem) {
480 +               pr_err("pci %s: ioremap error\n", pci_name(dev));
481 +               return;
482 +       }
483 +
484 +       pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
485 +       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, LTQ_PCI_MEM_BASE);
486 +       pci_read_config_word(dev, PCI_COMMAND, &cmd);
487 +       cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
488 +       pci_write_config_word(dev, PCI_COMMAND, cmd);
489 +
490 +       /* set pointer to first reg address */
491 +       cal_data += 3;
492 +       while (*cal_data != 0xffff) {
493 +               u32 reg;
494 +               reg = *cal_data++;
495 +               val = *cal_data++;
496 +               val |= (*cal_data++) << 16;
497 +
498 +               ltq_w32(swab32(val), mem + reg);
499 +               udelay(100);
500 +       }
501 +
502 +       pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
503 +       dev->vendor = val & 0xffff;
504 +       dev->device = (val >> 16) & 0xffff;
505 +
506 +       pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
507 +       dev->revision = val & 0xff;
508 +       dev->class = val >> 8; /* upper 3 bytes */
509 +
510 +       pr_info("pci %s: fixup info: [%04x:%04x] revision %02x class %#08x\n", 
511 +               pci_name(dev), dev->vendor, dev->device, dev->revision, dev->class);
512 +
513 +       pci_read_config_word(dev, PCI_COMMAND, &cmd);
514 +       cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
515 +       pci_write_config_word(dev, PCI_COMMAND, cmd);
516 +
517 +       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
518 +
519 +       iounmap(mem);
520 +}
521 +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath_pci_fixup);
522 +
523 +void __init ltq_pci_ath_fixup(unsigned slot, u16 *cal_data)
524 +{
525 +       if (ath_num_fixups >= ARRAY_SIZE(ath_fixups))
526 +               return;
527 +
528 +       ath_fixups[ath_num_fixups].slot = slot;
529 +       ath_fixups[ath_num_fixups].cal_data = cal_data;
530 +       ath_num_fixups++;
531 +}