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.
6 * Copyright (C) 2011 Andrej Vlašić
7 * Copyright (C) 2011 Luka Perkov
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>
25 #include <linux/string.h>
26 #include <linux/delay.h>
27 #include <linux/module.h>
30 #include <lantiq_soc.h>
31 #include <lantiq_platform.h>
32 #include <dev-gpio-leds.h>
33 #include <dev-gpio-buttons.h>
35 #include "../machtypes.h"
36 //#include "dev-wifi-ath9k.h"
38 #include "dev-dwc_otg.h"
40 #undef USE_BTHH_GPIO_INIT
42 // this reads certain data from u-boot if it's there
43 #define USE_UBOOT_ENV_DATA
45 #define UBOOT_ENV_OFFSET 0x040000
46 #define UBOOT_ENV_SIZE 0x010000
49 // this is only here for reference
50 // definition of NAND flash area
51 static struct mtd_partition bthomehubv2b_nand_partitions
[] =
82 #ifdef NAND_KEEPOPENRG
83 // this allows both firmwares to co-exist
85 static struct mtd_partition bthomehubv2b_nand_partitions
[] =
103 .name
= "wholeflash",
111 // this gives more jffs2 by overwriting openrg
113 static struct mtd_partition bthomehubv2b_nand_partitions
[] =
126 .name
= "wholeflash",
133 extern void __init
xway_register_nand(struct mtd_partition
*parts
, int count
);
137 static struct gpio_led
138 bthomehubv2b_gpio_leds
[] __initdata
= {
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, },
153 static struct gpio_keys_button
154 bthomehubv2b_gpio_keys
[] __initdata
= {
159 .debounce_interval
= LTQ_KEYS_DEBOUNCE_INTERVAL
,
164 .desc
= "findhandset",
167 .debounce_interval
= LTQ_KEYS_DEBOUNCE_INTERVAL
,
175 .debounce_interval
= LTQ_KEYS_DEBOUNCE_INTERVAL
,
181 // definition of NOR flash area - as per original.
182 static struct mtd_partition bthomehubv2b_partitions
[] =
191 .offset
= UBOOT_ENV_OFFSET
,
192 .size
= UBOOT_ENV_SIZE
,
205 .name
= "rg_conf_factory",
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);
219 static struct platform_device ltq_nor
= {
221 .resource
= &bthhv2b_nor_resource
,
225 static void __init
bthhv2b_register_nor(struct physmap_flash_data
*data
)
227 ltq_nor
.dev
.platform_data
= data
;
228 platform_device_register(<q_nor
);
231 static struct physmap_flash_data bthomehubv2b_flash_data
= {
232 .nr_parts
= ARRAY_SIZE(bthomehubv2b_partitions
),
233 .parts
= bthomehubv2b_partitions
,
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, },
248 static struct ltq_eth_data ltq_eth_data
= {
249 .mii_mode
= PHY_INTERFACE_MODE_MII
,
255 static char __init
*get_uboot_env_var(char *haystack
, int haystack_len
, char *needle
, int needle_len
) {
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
;
266 * bthomehubv2b_parse_hex_* are not uniq. in arm/orion there are also duplicates:
268 * TODO: one day write a patch for this :)
270 static int __init
bthomehubv2b_parse_hex_nibble(char n
) {
271 if (n
>= '0' && n
<= '9')
274 if (n
>= 'A' && n
<= 'F')
277 if (n
>= 'a' && n
<= 'f')
283 static int __init
bthomehubv2b_parse_hex_byte(const char *b
) {
287 hi
= bthomehubv2b_parse_hex_nibble(b
[0]);
288 lo
= bthomehubv2b_parse_hex_nibble(b
[1]);
290 if (hi
< 0 || lo
< 0)
293 return (hi
<< 4) | lo
;
296 static int __init
bthomehubv2b_register_ethernet(void) {
299 char *mac
= "01:02:03:04:05:06";
301 char *boardid
= "BTHHV2B";
304 char *uboot_env_page
;
305 uboot_env_page
= ioremap(LTQ_FLASH_START
+ UBOOT_ENV_OFFSET
, UBOOT_ENV_SIZE
);
309 Data
= get_uboot_env_var(uboot_env_page
, UBOOT_ENV_SIZE
, "\0ethaddr=", 9);
315 Data
= get_uboot_env_var(uboot_env_page
, UBOOT_ENV_SIZE
, "\0boardid=", 9);
322 printk("bthomehubv2b: Failed to get uboot_env_page");
333 /* Sanity check the string we're looking at */
334 for (i
= 0; i
< 5; i
++) {
335 if (*(mac
+ (i
* 3) + 2) != ':') {
340 for (i
= 0; i
< 6; i
++) {
342 byte
= bthomehubv2b_parse_hex_byte(mac
+ (i
* 3));
350 printk("bthomehubv2b: Found ethernet MAC address: ");
352 printk("bthomehubv2b: using default MAC (pls set ethaddr in u-boot): ");
354 for (i
= 0; i
< 6; i
++)
355 printk("%.2x%s", addr
[i
], (i
< 5) ? ":" : ".\n");
357 memcpy(<q_eth_data
.mac
.sa_data
, addr
, 6);
358 ltq_register_etop(<q_eth_data
);
360 //memcpy(&bthomehubv2b_ath5k_eeprom_mac, addr, 6);
361 //bthomehubv2b_ath5k_eeprom_mac[5]++;
364 printk("bthomehubv2b: Board id is %s.", boardid
);
366 printk("bthomehubv2b: Default Board id is %s.", boardid
);
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);
373 printk("bthomehubv2b: Board id is unknown, fix uboot_env data.");
377 // should not unmap while we are using the ram?
379 iounmap(uboot_env_page
);
385 iounmap(uboot_env_page
);
390 #define PORTA2_HW_PASS1 0
391 #define PORTA2_HW_PASS1_SC14480 1
392 #define PORTA2_HW_PASS2 2
394 int porta2_hw_revision
= -1;
395 EXPORT_SYMBOL(porta2_hw_revision
);
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
406 #ifdef USE_BTHH_GPIO_INIT
407 static void bthomehubv2b_board_prom_init(void)
410 unsigned int gpio
= 0;
411 void __iomem
*mem
= ioremap(LTQ_GPIO0_BASE_ADDR
, LTQ_GPIO_SIZE
*2);
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)
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)
426 printk("About to sense board using GPIOs at %8.8X\n", (unsigned int)mem
);
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;
436 *DANUBE_GPIO_P1_OUT
= 0x7008;
437 *DANUBE_GPIO_P1_DIR
= 0xF3AE;
438 *DANUBE_GPIO_P1_ALTSEL0
= 0x83A7;
439 *DANUBE_GPIO_P1_ALTSEL1
= 0x0400;
441 gpio
= (*DANUBE_GPIO_P0_IN
& 0xFFFF) |
442 ((*DANUBE_GPIO_P1_IN
& 0xFFFF) << 16);
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;
451 porta2_hw_revision
= revision
;
452 printk("PORTA2: detected HW revision %d\n", revision
);
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
460 *DANUBE_GPIO_P0_OUT
= 0x0200;
462 * During the manufacturing process a different machine takes over uart0
463 * so set it as input (so it wouldn't drive the line)
465 #define cCONFIG_SHC_BT_MFG_TEST 0
466 *DANUBE_GPIO_P0_DIR
= 0x2671 | (cCONFIG_SHC_BT_MFG_TEST
? 0 : (1 << 12));
468 if (revision
== PORTA2_HW_PASS1_SC14480
|| revision
== PORTA2_HW_PASS2
)
469 *DANUBE_GPIO_P0_ALTSEL0
= 0x7873;
471 *DANUBE_GPIO_P0_ALTSEL0
= 0x3873;
473 *DANUBE_GPIO_P0_ALTSEL1
= 0x0001;
476 //###################################################################################
477 // Register values before patch
478 // P1_ALTSEL0 = 0x83A7
479 // P1_ALTSEL1 = 0x0400
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
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
501 //###################################################################################
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;
512 static void __init
bthomehubv2b_init(void) {
513 #define bthomehubv2b_USB 13
515 // read the board version
516 #ifdef USE_BTHH_GPIO_INIT
517 bthomehubv2b_board_prom_init();
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(<q_pci_data
);
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();
534 MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2BOPENRG
,
535 "BTHOMEHUBV2BOPENRG",
536 "BTHOMEHUBV2B - BT Homehub V2.0 Type B with OpenRG image retained",
539 MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2B
,
541 "BTHOMEHUBV2B - BT Homehub V2.0 Type B",