Root/target/linux/adm8668/files/arch/mips/adm8668/platform.c

1/*
2 * Infineon/ADMTek 8668 (WildPass) platform devices support
3 *
4 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
5 * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/platform_data/tulip.h>
16#include <linux/usb/ehci_pdriver.h>
17#include <linux/mtd/physmap.h>
18#include <linux/mtd/partitions.h>
19#include <linux/pci.h>
20#include <linux/slab.h>
21#include <linux/ioport.h>
22#include <linux/amba/bus.h>
23#include <linux/amba/serial.h>
24
25#include <asm/reboot.h>
26#include <asm/time.h>
27#include <asm/addrspace.h>
28#include <asm/bootinfo.h>
29#include <asm/io.h>
30#include <adm8668.h>
31
32#define ADM8868_UBOOT_ENV 0x20000
33#define ADM8868_UBOOT_WAN_MAC 0x5ac
34#define ADM8868_UBOOT_LAN_MAC 0x404
35
36static void adm8668_uart_set_mctrl(struct amba_device *dev,
37                    void __iomem *base,
38                    unsigned int mcrtl)
39{
40}
41
42static struct amba_pl010_data adm8668_uart0_data = {
43    .set_mctrl = adm8668_uart_set_mctrl,
44};
45
46static struct amba_device adm8668_uart0_device = {
47    .dev = {
48        .init_name = "apb:uart0",
49        .platform_data = &adm8668_uart0_data,
50    },
51    .res = {
52        .start = ADM8668_UART0_BASE,
53        .end = ADM8668_UART0_BASE + 0xF,
54        .flags = IORESOURCE_MEM,
55    },
56    .irq = {
57        ADM8668_UART0_IRQ,
58        -1
59    },
60    .periphid = 0x0041010,
61};
62
63static struct resource eth0_resources[] = {
64    {
65        .start = ADM8668_LAN_BASE,
66        .end = ADM8668_LAN_BASE + 256,
67        .flags = IORESOURCE_MEM,
68    },
69    {
70        .start = ADM8668_LAN_IRQ,
71        .flags = IORESOURCE_IRQ,
72    },
73};
74
75static struct tulip_platform_data eth0_pdata = {
76    .chip_id = ADM8668,
77};
78
79static struct platform_device adm8668_eth0_device = {
80    .name = "tulip",
81    .id = 0,
82    .resource = eth0_resources,
83    .num_resources = ARRAY_SIZE(eth0_resources),
84    .dev.platform_data = &eth0_pdata,
85};
86
87static struct resource eth1_resources[] = {
88    {
89        .start = ADM8668_WAN_BASE,
90        .end = ADM8668_WAN_BASE + 256,
91        .flags = IORESOURCE_MEM,
92    },
93    {
94        .start = ADM8668_WAN_IRQ,
95        .flags = IORESOURCE_IRQ,
96    },
97};
98
99static struct tulip_platform_data eth1_pdata = {
100    .chip_id = ADM8668,
101};
102
103static struct platform_device adm8668_eth1_device = {
104    .name = "tulip",
105    .id = 1,
106    .resource = eth1_resources,
107    .num_resources = ARRAY_SIZE(eth1_resources),
108    .dev.platform_data = &eth1_pdata,
109};
110
111static const char *nor_probe_types[] = { "adm8668part", NULL };
112
113static struct physmap_flash_data nor_flash_data = {
114    .width = 2,
115    .part_probe_types = nor_probe_types,
116};
117
118static struct resource nor_resources[] = {
119    {
120        .start = ADM8668_SMEM1_BASE,
121        .end = ADM8668_SMEM1_BASE + 0x800000 - 1,
122        .flags = IORESOURCE_MEM,
123    },
124};
125
126static struct platform_device adm8668_nor_device = {
127    .name = "physmap-flash",
128    .id = -1,
129    .resource = nor_resources,
130    .num_resources = ARRAY_SIZE(nor_resources),
131    .dev.platform_data = &nor_flash_data,
132};
133
134static struct resource usb_resources[] = {
135    {
136        .start = ADM8668_USB_BASE,
137        .end = ADM8668_USB_BASE + 0x1FFFFF,
138        .flags = IORESOURCE_MEM,
139    },
140    {
141        .start = ADM8668_USB_IRQ,
142        .end = ADM8668_USB_IRQ,
143        .flags = IORESOURCE_IRQ,
144    },
145};
146
147static struct usb_ehci_pdata usb_pdata = {
148    .caps_offset = 0x100,
149    .has_tt = 1,
150    .port_power_off = 1,
151};
152
153static struct platform_device adm8668_usb_device = {
154    .name = "ehci-platform",
155    .id = -1,
156    .resource = usb_resources,
157    .num_resources = ARRAY_SIZE(usb_resources),
158    .dev.platform_data = &usb_pdata,
159};
160
161static struct platform_device *adm8668_devs[] = {
162    &adm8668_eth0_device,
163    &adm8668_eth1_device,
164    &adm8668_nor_device,
165    &adm8668_usb_device,
166};
167
168static void adm8668_fetch_mac(int unit)
169{
170    u8 *mac;
171    u32 offset;
172    struct tulip_platform_data *pdata;
173
174    switch (unit) {
175    case -1:
176    case 0:
177        offset = ADM8868_UBOOT_LAN_MAC;
178        pdata = &eth0_pdata;
179        break;
180    case 1:
181        offset = ADM8868_UBOOT_WAN_MAC;
182        pdata = &eth1_pdata;
183        break;
184    default:
185        pr_err("unsupported ethernet unit: %d\n", unit);
186        return;
187    }
188
189    mac = (u8 *)(KSEG1ADDR(ADM8668_SMEM1_BASE) + ADM8868_UBOOT_ENV + offset);
190
191    memcpy(pdata->mac, mac, sizeof(pdata->mac));
192}
193
194static void adm8668_ehci_workaround(void)
195{
196    u32 chipid;
197
198    chipid = ADM8668_CONFIG_REG(ADM8668_CR0);
199    ADM8668_CONFIG_REG(ADM8668_CR66) = 0x0C1600D9;
200
201    if (chipid == 0x86880001)
202        return;
203
204    ADM8668_CONFIG_REG(ADM8668_CR66) &= ~(3 << 20);
205    ADM8668_CONFIG_REG(ADM8668_CR66) |= (1 << 20);
206    pr_info("ADM8668: applied USB workaround\n");
207}
208
209
210int __devinit adm8668_devs_register(void)
211{
212    int ret;
213
214    ret = amba_device_register(&adm8668_uart0_device, &iomem_resource);
215    if (ret)
216        panic("failed to register AMBA UART");
217
218    adm8668_fetch_mac(0);
219    adm8668_fetch_mac(1);
220    adm8668_ehci_workaround();
221
222    return platform_add_devices(adm8668_devs, ARRAY_SIZE(adm8668_devs));
223}
224arch_initcall(adm8668_devs_register);
225

Archive Download this file



interactive