[lantiq] bump kernel to 3.2.12
[openwrt.git] / target / linux / lantiq / files-3.2 / arch / mips / lantiq / xway / mach-bthomehubv2b.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify it
3  *  under the terms of the GNU General Public License version 2 as published
4  *  by the Free Software Foundation.
5  *
6  *  Copyright (C) 2011 Andrej Vlašić
7  *  Copyright (C) 2011 Luka Perkov
8  *
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/platform_device.h>
14 #include <linux/leds.h>
15 #include <linux/gpio.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/mtd/partitions.h>
18 #include <linux/mtd/physmap.h>
19 #include <linux/input.h>
20 #include <linux/ath5k_platform.h>
21 #include <linux/ath9k_platform.h>
22 #include <linux/pci.h>
23 #include <linux/phy.h>
24 #include <linux/io.h>
25 #include <linux/string.h>
26 #include <linux/delay.h>
27 #include <linux/module.h>
28
29 #include <irq.h>
30 #include <lantiq_soc.h>
31 #include <lantiq_platform.h>
32 #include <dev-gpio-leds.h>
33 #include <dev-gpio-buttons.h>
34
35 #include "../machtypes.h"
36 //#include "dev-wifi-ath9k.h"
37 #include "devices.h"
38 #include "dev-dwc_otg.h"
39
40 #undef USE_BTHH_GPIO_INIT
41
42 // this reads certain data from u-boot if it's there
43 #define USE_UBOOT_ENV_DATA
44
45 #define UBOOT_ENV_OFFSET        0x040000
46 #define UBOOT_ENV_SIZE          0x010000
47
48 #ifdef NAND_ORGLAYOUT
49 // this is only here for reference
50 // definition of NAND flash area
51 static struct mtd_partition bthomehubv2b_nand_partitions[] =
52 {
53         {
54                 .name   = "ART",
55                 .offset = 0x0000000,
56                 .size   = 0x0004000,
57         },
58         {
59                 .name   = "image1",
60                 .offset = 0x0004000,
61                 .size   = 0x0E00000,
62         },
63         {
64                 .name   = "unknown1",
65                 .offset = 0x0E04000,
66                 .size   = 0x00FC000,
67         },
68         {
69                 .name   = "image2",
70                 .offset = 0x0F00000,
71                 .size   = 0x0E00000,
72         },
73         {
74                 .name   = "unknown2",
75                 .offset = 0x1D00000,
76                 .size   = 0x0300000,
77         },
78
79 };
80 #endif
81
82 #ifdef NAND_KEEPOPENRG
83 // this allows both firmwares to co-exist
84
85 static struct mtd_partition bthomehubv2b_nand_partitions[] =
86 {
87         {
88                 .name   = "art",
89                 .offset = 0x0000000,
90                 .size   = 0x0004000,
91         },
92         {
93                 .name   = "Image1",
94                 .offset = 0x0004000,
95                 .size   = 0x0E00000,
96         },
97         {
98                 .name   = "linux",
99                 .offset = 0x0E04000,
100                 .size   = 0x11fC000,
101         },
102         {
103                 .name   = "wholeflash",
104                 .offset = 0x0000000,
105                 .size   = 0x2000000,
106         },
107
108 };
109 #endif
110
111 // this gives more jffs2 by overwriting openrg
112
113 static struct mtd_partition bthomehubv2b_nand_partitions[] =
114 {
115         {
116                 .name   = "art",
117                 .offset = 0x0000000,
118                 .size   = 0x0004000,
119         },
120         {
121                 .name   = "linux",
122                 .offset = 0x0004000,
123                 .size   = 0x1ffC000,
124         },
125         {
126                 .name   = "wholeflash",
127                 .offset = 0x0000000,
128                 .size   = 0x2000000,
129         },
130
131 };
132
133 extern void __init xway_register_nand(struct mtd_partition *parts, int count);
134
135 // end BTHH_USE_NAND
136
137 static struct gpio_led
138 bthomehubv2b_gpio_leds[] __initdata = {
139
140         { .name = "soc:orange:upgrading",       .gpio = 213, },
141         { .name = "soc:orange:phone",           .gpio = 214, },
142         { .name = "soc:blue:phone",             .gpio = 215, },
143         { .name = "soc:orange:wireless",        .gpio = 216, },
144         { .name = "soc:blue:wireless",          .gpio = 217, },
145         { .name = "soc:red:broadband",          .gpio = 218, },
146         { .name = "soc:orange:broadband",       .gpio = 219, },
147         { .name = "soc:blue:broadband",         .gpio = 220, },
148         { .name = "soc:red:power",              .gpio = 221, },
149         { .name = "soc:orange:power",           .gpio = 222, },
150         { .name = "soc:blue:power",             .gpio = 223, },
151 };
152
153 static struct gpio_keys_button
154 bthomehubv2b_gpio_keys[] __initdata = {
155         {
156                 .desc           = "restart",
157                 .type           = EV_KEY,
158                 .code           = BTN_0,
159                 .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
160                 .gpio           = 2,
161                 .active_low     = 1,
162         },
163         {
164                 .desc           = "findhandset",
165                 .type           = EV_KEY,
166                 .code           = BTN_1,
167                 .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
168                 .gpio           = 15,
169                 .active_low     = 1,
170         },
171         {
172                 .desc           = "wps",
173                 .type           = EV_KEY,
174                 .code           = BTN_2,
175                 .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
176                 .gpio           = 22,
177                 .active_low     = 1,
178         },
179 };
180
181 // definition of NOR flash area - as per original.
182 static struct mtd_partition bthomehubv2b_partitions[] =
183 {
184         {
185                 .name   = "uboot",
186                 .offset = 0x000000,
187                 .size   = 0x040000,
188         },
189         {
190                 .name   = "uboot_env",
191                 .offset = UBOOT_ENV_OFFSET,
192                 .size   = UBOOT_ENV_SIZE,
193         },
194         {
195                 .name   = "rg_conf_1",
196                 .offset = 0x050000,
197                 .size   = 0x010000,
198         },
199         {
200                 .name   = "rg_conf_2",
201                 .offset = 0x060000,
202                 .size   = 0x010000,
203         },
204         {
205                 .name   = "rg_conf_factory",
206                 .offset = 0x070000,
207                 .size   = 0x010000,
208         },
209 };
210
211
212 /* nor flash */
213 /* bt homehubv2b has a very small nor flash */
214 /* so make it look for a small one, else we get a lot of alias chips identified - */
215 /* not a bug problem, but fills the logs. */
216 static struct resource bthhv2b_nor_resource =
217         MEM_RES("nor", LTQ_FLASH_START, 0x80000);
218
219 static struct platform_device ltq_nor = {
220         .name           = "ltq_nor",
221         .resource       = &bthhv2b_nor_resource,
222         .num_resources  = 1,
223 };
224
225 static void __init bthhv2b_register_nor(struct physmap_flash_data *data)
226 {
227         ltq_nor.dev.platform_data = data;
228         platform_device_register(&ltq_nor);
229 }
230
231 static struct physmap_flash_data bthomehubv2b_flash_data = {
232         .nr_parts       = ARRAY_SIZE(bthomehubv2b_partitions),
233         .parts          = bthomehubv2b_partitions,
234 };
235
236
237
238
239 static struct ltq_pci_data ltq_pci_data = {
240         .clock  = PCI_CLOCK_INT,
241         .gpio   = PCI_GNT1 | PCI_REQ1,
242         .irq    = { [14] = INT_NUM_IM0_IRL0 + 22, },
243 };
244
245
246
247
248 static struct ltq_eth_data ltq_eth_data = {
249         .mii_mode       = PHY_INTERFACE_MODE_MII,
250 };
251
252
253
254
255 static char __init *get_uboot_env_var(char *haystack, int haystack_len, char *needle, int needle_len) {
256         int i;
257         for (i = 0; i <= haystack_len - needle_len; i++) {
258                 if (memcmp(haystack + i, needle, needle_len) == 0) {
259                         return haystack + i + needle_len;
260                 }
261         }
262         return NULL;
263 }
264
265 /*
266  * bthomehubv2b_parse_hex_* are not uniq. in arm/orion there are also duplicates:
267  * dns323_parse_hex_*
268  * TODO: one day write a patch for this :)
269  */
270 static int __init bthomehubv2b_parse_hex_nibble(char n) {
271         if (n >= '0' && n <= '9')
272                 return n - '0';
273
274         if (n >= 'A' && n <= 'F')
275                 return n - 'A' + 10;
276
277         if (n >= 'a' && n <= 'f')
278                 return n - 'a' + 10;
279
280         return -1;
281 }
282
283 static int __init bthomehubv2b_parse_hex_byte(const char *b) {
284         int hi;
285         int lo;
286
287         hi = bthomehubv2b_parse_hex_nibble(b[0]);
288         lo = bthomehubv2b_parse_hex_nibble(b[1]);
289
290         if (hi < 0 || lo < 0)
291                 return -1;
292
293         return (hi << 4) | lo;
294 }
295
296 static int __init bthomehubv2b_register_ethernet(void) {
297         u_int8_t addr[6];
298         int i;
299         char *mac = "01:02:03:04:05:06";
300         int gotmac = 0;
301         char *boardid = "BTHHV2B";
302         int gotboardid = 0;
303
304         char *uboot_env_page;
305         uboot_env_page = ioremap(LTQ_FLASH_START + UBOOT_ENV_OFFSET, UBOOT_ENV_SIZE);
306         if (uboot_env_page)
307         {
308                 char *Data = NULL;
309                 Data = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0ethaddr=", 9);
310                 if (Data)
311                 {
312                         mac = Data;
313                 }
314
315                 Data = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0boardid=", 9);
316
317                 if (Data)
318                         boardid = Data;
319         }
320         else
321         {
322                 printk("bthomehubv2b: Failed to get uboot_env_page");
323         }
324
325         if (!mac) {
326         goto error_fail;
327         }
328
329         if (!boardid) {
330         goto error_fail;
331         }
332
333         /* Sanity check the string we're looking at */
334         for (i = 0; i < 5; i++) {
335         if (*(mac + (i * 3) + 2) != ':') {
336                 goto error_fail;
337                 }
338         }
339
340         for (i = 0; i < 6; i++) {
341                 int byte;
342                 byte = bthomehubv2b_parse_hex_byte(mac + (i * 3));
343                 if (byte < 0) {
344                         goto error_fail;
345                 }
346                 addr[i] = byte;
347         }
348
349         if (gotmac)
350                 printk("bthomehubv2b: Found ethernet MAC address: ");
351         else
352                 printk("bthomehubv2b: using default MAC (pls set ethaddr in u-boot): ");
353
354         for (i = 0; i < 6; i++)
355                 printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
356
357         memcpy(&ltq_eth_data.mac.sa_data, addr, 6);
358         ltq_register_etop(&ltq_eth_data);
359
360         //memcpy(&bthomehubv2b_ath5k_eeprom_mac, addr, 6);
361         //bthomehubv2b_ath5k_eeprom_mac[5]++;
362
363         if (gotboardid)
364                 printk("bthomehubv2b: Board id is %s.", boardid);
365         else
366                 printk("bthomehubv2b: Default Board id is %s.", boardid);
367
368         if (strncmp(boardid, "BTHHV2B", 7) == 0) {
369                 // read in dev-wifi-ath9k
370                 //memcpy(&bthomehubv2b_ath5k_eeprom_data, sx763_eeprom_data, ATH5K_PLAT_EEP_MAX_WORDS);
371         }
372         else {
373                 printk("bthomehubv2b: Board id is unknown, fix uboot_env data.");
374         }
375
376
377         // should not unmap while we are using the ram?
378         if (uboot_env_page)
379                 iounmap(uboot_env_page);
380
381         return 0;
382
383 error_fail:
384         if (uboot_env_page)
385                 iounmap(uboot_env_page);
386         return -EINVAL;
387 }
388
389
390 #define PORTA2_HW_PASS1 0
391 #define PORTA2_HW_PASS1_SC14480 1
392 #define PORTA2_HW_PASS2 2
393
394 int porta2_hw_revision = -1;
395 EXPORT_SYMBOL(porta2_hw_revision);
396
397 #define LTQ_GPIO_OUT            0x00
398 #define LTQ_GPIO_IN             0x04
399 #define LTQ_GPIO_DIR            0x08
400 #define LTQ_GPIO_ALTSEL0        0x0C
401 #define LTQ_GPIO_ALTSEL1        0x10
402 #define LTQ_GPIO_OD             0x14
403 #define LTQ_GPIO_PUDSEL         0x1C
404 #define LTQ_GPIO_PUDEN          0x20
405
406 #ifdef USE_BTHH_GPIO_INIT
407 static void bthomehubv2b_board_prom_init(void)
408 {
409         int revision = 0;
410         unsigned int gpio = 0;
411         void __iomem *mem = ioremap(LTQ_GPIO0_BASE_ADDR, LTQ_GPIO_SIZE*2);
412
413 #define DANUBE_GPIO_P0_OUT (unsigned short *)(mem + LTQ_GPIO_OUT)
414 #define DANUBE_GPIO_P0_IN (unsigned short *)(mem + LTQ_GPIO_IN)
415 #define DANUBE_GPIO_P0_DIR (unsigned short *)(mem + LTQ_GPIO_DIR)
416 #define DANUBE_GPIO_P0_ALTSEL0 (unsigned short *)(mem + LTQ_GPIO_ALTSEL0)
417 #define DANUBE_GPIO_P0_ALTSEL1 (unsigned short *)(mem + LTQ_GPIO_ALTSEL1)
418
419 #define DANUBE_GPIO_P1_OUT (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_OUT)
420 #define DANUBE_GPIO_P1_IN (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_IN)
421 #define DANUBE_GPIO_P1_DIR (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_DIR)
422 #define DANUBE_GPIO_P1_ALTSEL0 (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_ALTSEL0)
423 #define DANUBE_GPIO_P1_ALTSEL1 (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_ALTSEL1)
424 #define DANUBE_GPIO_P1_OD (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_OD)
425
426         printk("About to sense board using GPIOs at %8.8X\n", (unsigned int)mem);
427
428
429         /* First detect HW revision of the board. For that we need to set the GPIO
430          * lines according to table 7.2.1/7.2.2 in HSI */
431         *DANUBE_GPIO_P0_OUT = 0x0200;
432         *DANUBE_GPIO_P0_DIR = 0x2610;
433         *DANUBE_GPIO_P0_ALTSEL0 = 0x7812;
434         *DANUBE_GPIO_P0_ALTSEL1 = 0x0000;
435
436         *DANUBE_GPIO_P1_OUT = 0x7008;
437         *DANUBE_GPIO_P1_DIR = 0xF3AE;
438         *DANUBE_GPIO_P1_ALTSEL0 = 0x83A7;
439         *DANUBE_GPIO_P1_ALTSEL1 = 0x0400;
440
441         gpio = (*DANUBE_GPIO_P0_IN & 0xFFFF) | 
442                 ((*DANUBE_GPIO_P1_IN & 0xFFFF) << 16);
443
444         revision |= (gpio & (1 << 27)) ? (1 << 0) : 0;
445         revision |= (gpio & (1 << 20)) ? (1 << 1) : 0;
446         revision |= (gpio & (1 << 8)) ? (1 << 2) : 0;
447         revision |= (gpio & (1 << 6)) ? (1 << 3) : 0;
448         revision |= (gpio & (1 << 5)) ? (1 << 4) : 0;
449         revision |= (gpio & (1 << 0)) ? (1 << 5) : 0;
450
451         porta2_hw_revision = revision;
452         printk("PORTA2: detected HW revision %d\n", revision);
453
454         /* Set GPIO lines according to HW revision. */
455         /* !!! Note that we are setting SPI_CS5 (GPIO 9) to be GPIO out with value
456          * of HIGH since the FXO does not use the SPI CS mechanism, it does it
457          * manually by controlling the GPIO line. We need the CS line to be disabled
458          * (HIGH) until needed since it will intefere with other devices on the SPI
459          * bus. */
460         *DANUBE_GPIO_P0_OUT = 0x0200;
461         /*
462          * During the manufacturing process a different machine takes over uart0
463          * so set it as input (so it wouldn't drive the line)
464          */
465 #define cCONFIG_SHC_BT_MFG_TEST 0
466         *DANUBE_GPIO_P0_DIR = 0x2671 | (cCONFIG_SHC_BT_MFG_TEST ? 0 : (1 << 12));
467
468         if (revision == PORTA2_HW_PASS1_SC14480 || revision == PORTA2_HW_PASS2)
469                 *DANUBE_GPIO_P0_ALTSEL0 = 0x7873;
470         else
471                 *DANUBE_GPIO_P0_ALTSEL0 = 0x3873;
472
473         *DANUBE_GPIO_P0_ALTSEL1 = 0x0001;
474
475
476         //###################################################################################    
477         // Register values before patch
478         // P1_ALTSEL0 = 0x83A7
479         // P1_ALTSEL1 = 0x0400
480         // P1_OU        T     = 0x7008
481         // P1_DIR     = 0xF3AE
482         // P1_OD      = 0xE3Fc
483         printk("\nApplying Patch for CPU1 IRQ Issue\n");
484         *DANUBE_GPIO_P1_ALTSEL0 &= ~(1<<12);  // switch P1.12 (GPIO28) to GPIO functionality
485         *DANUBE_GPIO_P1_ALTSEL1 &= ~(1<<12);  // switch P1.12 (GPIO28) to GPIO functionality
486         *DANUBE_GPIO_P1_OUT     &= ~(1<<12);  // set P1.12 (GPIO28) to 0
487         *DANUBE_GPIO_P1_DIR     |= (1<<12);   // configure P1.12 (GPIO28) as output 
488         *DANUBE_GPIO_P1_OD      |= (1<<12);   // activate Push/Pull mode 
489         udelay(100);                          // wait a little bit (100us)
490         *DANUBE_GPIO_P1_OD      &= ~(1<<12);  // switch back from Push/Pull to Open Drain
491         // important: before! setting output to 1 (3,3V) the mode must be switched 
492         // back to Open Drain because the reset pin of the SC14488 is internally 
493         // pulled to 1,8V
494         *DANUBE_GPIO_P1_OUT     |= (1<<12);   // set output P1.12 (GPIO28) to 1
495         // Register values after patch, should be the same as before
496         // P1_ALTSEL0 = 0x83A7
497         // P1_ALTSEL1 = 0x0400
498         // P1_OUT     = 0x7008
499         // P1_DIR     = 0xF3AE
500         // P1_OD      = 0xE3Fc
501         //###################################################################################
502
503
504         *DANUBE_GPIO_P1_OUT = 0x7008;
505         *DANUBE_GPIO_P1_DIR = 0xEBAE | (revision == PORTA2_HW_PASS2 ? 0x1000 : 0);
506         *DANUBE_GPIO_P1_ALTSEL0 = 0x8BA7;
507         *DANUBE_GPIO_P1_ALTSEL1 = 0x0400;
508
509         iounmap(mem);
510 }
511 #endif
512 static void __init bthomehubv2b_init(void) {
513 #define bthomehubv2b_USB                13
514
515         // read the board version
516 #ifdef USE_BTHH_GPIO_INIT
517         bthomehubv2b_board_prom_init();
518 #endif
519
520         // register extra GPPOs used by LEDs as GPO 0x200+
521         ltq_register_gpio_stp();
522         ltq_add_device_gpio_leds(-1, ARRAY_SIZE(bthomehubv2b_gpio_leds), bthomehubv2b_gpio_leds);
523         bthhv2b_register_nor(&bthomehubv2b_flash_data);
524         xway_register_nand(bthomehubv2b_nand_partitions, ARRAY_SIZE(bthomehubv2b_nand_partitions));
525         ltq_register_pci(&ltq_pci_data);
526         ltq_register_tapi();
527         ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(bthomehubv2b_gpio_keys), bthomehubv2b_gpio_keys);
528 //      ltq_register_ath9k();
529         xway_register_dwc(bthomehubv2b_USB);
530         bthomehubv2b_register_ethernet();
531
532 }
533
534 MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2BOPENRG,
535         "BTHOMEHUBV2BOPENRG",
536         "BTHOMEHUBV2B - BT Homehub V2.0 Type B with OpenRG image retained",
537         bthomehubv2b_init);
538
539 MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2B,
540         "BTHOMEHUBV2B",
541         "BTHOMEHUBV2B - BT Homehub V2.0 Type B",
542         bthomehubv2b_init);