Root/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.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/pci.h>
22#include <linux/phy.h>
23#include <linux/io.h>
24#include <linux/string.h>
25
26#include <irq.h>
27#include <lantiq_soc.h>
28#include <lantiq_platform.h>
29#include <dev-gpio-leds.h>
30#include <dev-gpio-buttons.h>
31
32#include "../machtypes.h"
33#include "dev-wifi-ath5k.h"
34#include "devices.h"
35#include "dev-dwc_otg.h"
36
37#include "mach-gigasx76x.h"
38
39#define UBOOT_ENV_OFFSET 0x010000
40#define UBOOT_ENV_SIZE 0x010000
41
42static struct mtd_partition gigasx76x_partitions[] =
43{
44    {
45        .name = "uboot",
46        .offset = 0x000000,
47        .size = 0x010000,
48    },
49    {
50        .name = "uboot_env",
51        .offset = UBOOT_ENV_OFFSET,
52        .size = UBOOT_ENV_SIZE,
53    },
54    {
55        .name = "linux",
56        .offset = 0x020000,
57        .size = 0x7e0000,
58    },
59};
60
61static struct gpio_led
62gigasx76x_gpio_leds[] __initdata = {
63    { .name = "soc:green:voip", .gpio = 216, },
64    { .name = "soc:green:adsl", .gpio = 217, },
65    { .name = "soc:green:usb", .gpio = 218, },
66    { .name = "soc:green:wifi", .gpio = 219, },
67    { .name = "soc:green:phone2", .gpio = 220, },
68    { .name = "soc:green:phone1", .gpio = 221, },
69    { .name = "soc:green:line", .gpio = 222, },
70    { .name = "soc:green:online", .gpio = 223, },
71};
72
73static struct gpio_keys_button
74gigasx76x_gpio_keys[] __initdata = {
75    {
76        .desc = "wps",
77        .type = EV_KEY,
78        .code = KEY_WPS_BUTTON,
79        .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
80        .gpio = 22,
81        .active_low = 1,
82    },
83    {
84        .desc = "reset",
85        .type = EV_KEY,
86        .code = BTN_0,
87        .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
88        .gpio = 14,
89        .active_low = 0,
90    },
91};
92
93static struct physmap_flash_data gigasx76x_flash_data = {
94    .nr_parts = ARRAY_SIZE(gigasx76x_partitions),
95    .parts = gigasx76x_partitions,
96};
97
98static struct ltq_pci_data ltq_pci_data = {
99    .clock = PCI_CLOCK_INT,
100    .gpio = PCI_GNT1 | PCI_REQ1,
101    .irq = { [14] = INT_NUM_IM0_IRL0 + 22, },
102};
103
104static struct ltq_eth_data ltq_eth_data = {
105    .mii_mode = PHY_INTERFACE_MODE_MII,
106};
107
108static char __init *get_uboot_env_var(char *haystack, int haystack_len, char *needle, int needle_len) {
109    int i;
110    for (i = 0; i <= haystack_len - needle_len; i++) {
111        if (memcmp(haystack + i, needle, needle_len) == 0) {
112            return haystack + i + needle_len;
113        }
114    }
115    return NULL;
116}
117
118/*
119 * gigasx76x_parse_hex_* are not uniq. in arm/orion there are also duplicates:
120 * dns323_parse_hex_*
121 * TODO: one day write a patch for this :)
122 */
123static int __init gigasx76x_parse_hex_nibble(char n) {
124    if (n >= '0' && n <= '9')
125        return n - '0';
126
127    if (n >= 'A' && n <= 'F')
128        return n - 'A' + 10;
129
130    if (n >= 'a' && n <= 'f')
131        return n - 'a' + 10;
132
133    return -1;
134}
135
136static int __init gigasx76x_parse_hex_byte(const char *b) {
137    int hi;
138    int lo;
139
140    hi = gigasx76x_parse_hex_nibble(b[0]);
141    lo = gigasx76x_parse_hex_nibble(b[1]);
142
143    if (hi < 0 || lo < 0)
144        return -1;
145
146    return (hi << 4) | lo;
147}
148
149static u16 gigasx76x_ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
150static u8 gigasx76x_ath5k_eeprom_mac[6];
151
152static int __init gigasx76x_register_ethernet(void) {
153    u_int8_t addr[6];
154    int i;
155    char *uboot_env_page;
156    char *mac;
157    char *boardid;
158
159    uboot_env_page = ioremap(LTQ_FLASH_START + UBOOT_ENV_OFFSET, UBOOT_ENV_SIZE);
160    if (!uboot_env_page)
161        return -ENOMEM;
162
163    mac = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0ethaddr=", 9);
164    boardid = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0boardid=", 9);
165
166    if (!mac) {
167    goto error_fail;
168    }
169
170    if (!boardid) {
171    goto error_fail;
172    }
173
174    /* Sanity check the string we're looking at */
175    for (i = 0; i < 5; i++) {
176    if (*(mac + (i * 3) + 2) != ':') {
177        goto error_fail;
178        }
179    }
180
181    for (i = 0; i < 6; i++) {
182        int byte;
183        byte = gigasx76x_parse_hex_byte(mac + (i * 3));
184        if (byte < 0) {
185            goto error_fail;
186        }
187        addr[i] = byte;
188    }
189
190    iounmap(uboot_env_page);
191    printk("GIGASX76X: Found ethernet MAC address: ");
192    for (i = 0; i < 6; i++)
193        printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
194
195    memcpy(&ltq_eth_data.mac.sa_data, addr, 6);
196    ltq_register_etop(&ltq_eth_data);
197
198    memcpy(&gigasx76x_ath5k_eeprom_mac, addr, 6);
199    gigasx76x_ath5k_eeprom_mac[5]++;
200
201    if (strncmp(boardid, "sx763", 5) == 0) {
202        printk("GIGASX76X: Board id is sx763.");
203        memcpy(&gigasx76x_ath5k_eeprom_data, sx763_eeprom_data, ATH5K_PLAT_EEP_MAX_WORDS);
204    } else if (strncmp(boardid, "sx762", 5) == 0) {
205            printk("GIGASX76X: Board id is sx762.");
206            memcpy(&gigasx76x_ath5k_eeprom_data, sx762_eeprom_data, ATH5K_PLAT_EEP_MAX_WORDS);
207    } else {
208        printk("GIGASX76X: Board id is unknown, fix uboot_env data.");
209    }
210
211    return 0;
212
213    error_fail:
214        iounmap(uboot_env_page);
215        return -EINVAL;
216}
217
218static void __init gigasx76x_init(void) {
219#define GIGASX76X_USB 29
220#define GIGASX76X_MADWIFI_ADDR 0xb07f0000
221
222    ltq_register_gpio_stp();
223    ltq_register_nor(&gigasx76x_flash_data);
224    ltq_register_pci(&ltq_pci_data);
225    ltq_register_tapi();
226    ltq_add_device_gpio_leds(-1, ARRAY_SIZE(gigasx76x_gpio_leds), gigasx76x_gpio_leds);
227    ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(gigasx76x_gpio_keys), gigasx76x_gpio_keys);
228    ltq_register_ath5k(gigasx76x_ath5k_eeprom_data, gigasx76x_ath5k_eeprom_mac);
229    xway_register_dwc(GIGASX76X_USB);
230    gigasx76x_register_ethernet();
231}
232
233MIPS_MACHINE(LANTIQ_MACH_GIGASX76X, "GIGASX76X", "GIGASX76X - Gigaset SX761,SX762,SX763", gigasx76x_init);
234

Archive Download this file



interactive