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