Root/target/linux/lantiq/files/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
51static 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
85static 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
113static 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
133extern void __init xway_register_nand(struct mtd_partition *parts, int count);
134
135// end BTHH_USE_NAND
136
137static struct gpio_led
138bthomehubv2b_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
153static struct gpio_keys_button
154bthomehubv2b_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.
182static 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. */
216static struct resource bthhv2b_nor_resource =
217    MEM_RES("nor", LTQ_FLASH_START, 0x80000);
218
219static struct platform_device ltq_nor = {
220    .name = "ltq_nor",
221    .resource = &bthhv2b_nor_resource,
222    .num_resources = 1,
223};
224
225static 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
231static struct physmap_flash_data bthomehubv2b_flash_data = {
232    .nr_parts = ARRAY_SIZE(bthomehubv2b_partitions),
233    .parts = bthomehubv2b_partitions,
234};
235
236
237
238
239static 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
248static struct ltq_eth_data ltq_eth_data = {
249    .mii_mode = PHY_INTERFACE_MODE_MII,
250};
251
252
253
254
255static 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 */
270static 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
283static 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
296static 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
383error_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
394int porta2_hw_revision = -1;
395EXPORT_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
407static 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
512static 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
534MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2BOPENRG,
535    "BTHOMEHUBV2BOPENRG",
536    "BTHOMEHUBV2B - BT Homehub V2.0 Type B with OpenRG image retained",
537    bthomehubv2b_init);
538
539MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2B,
540    "BTHOMEHUBV2B",
541    "BTHOMEHUBV2B - BT Homehub V2.0 Type B",
542    bthomehubv2b_init);
543

Archive Download this file



interactive