bump kernel to 3.2.12
[openwrt/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);