adm8668: revert changeset 34554
[openwrt/svn-archive/archive.git] / target / linux / adm8668 / files / 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 .port_power_off = 1,
125 };
126
127 static struct platform_device adm8668_usb_device = {
128 .name = "ehci-platform",
129 .id = -1,
130 .resource = usb_resources,
131 .num_resources = ARRAY_SIZE(usb_resources),
132 .dev.platform_data = &usb_pdata,
133 };
134
135 static struct platform_device *adm8668_devs[] = {
136 &adm8668_eth0_device,
137 &adm8668_eth1_device,
138 &adm8668_usb_device,
139 };
140
141 static void adm8668_fetch_mac(int unit)
142 {
143 u8 *mac;
144 u32 offset;
145 struct tulip_platform_data *pdata;
146
147 switch (unit) {
148 case -1:
149 case 0:
150 offset = ADM8868_UBOOT_LAN_MAC;
151 pdata = &eth0_pdata;
152 break;
153 case 1:
154 offset = ADM8868_UBOOT_WAN_MAC;
155 pdata = &eth1_pdata;
156 break;
157 default:
158 pr_err("unsupported ethernet unit: %d\n", unit);
159 return;
160 }
161
162 mac = (u8 *)(KSEG1ADDR(ADM8668_SMEM1_BASE) + ADM8868_UBOOT_ENV + offset);
163
164 memcpy(pdata->mac, mac, sizeof(pdata->mac));
165 }
166
167 static void adm8668_ehci_workaround(void)
168 {
169 u32 chipid;
170
171 chipid = ADM8668_CONFIG_REG(ADM8668_CR0);
172 ADM8668_CONFIG_REG(ADM8668_CR66) = 0x0C1600D9;
173
174 if (chipid == 0x86880001)
175 return;
176
177 ADM8668_CONFIG_REG(ADM8668_CR66) &= ~(3 << 20);
178 ADM8668_CONFIG_REG(ADM8668_CR66) |= (1 << 20);
179 pr_info("ADM8668: applied USB workaround\n");
180 }
181
182
183 int __devinit adm8668_devs_register(void)
184 {
185 int ret;
186
187 ret = amba_device_register(&adm8668_uart0_device, &iomem_resource);
188 if (ret)
189 panic("failed to register AMBA UART");
190
191 adm8668_fetch_mac(0);
192 adm8668_fetch_mac(1);
193 adm8668_ehci_workaround();
194
195 return platform_add_devices(adm8668_devs, ARRAY_SIZE(adm8668_devs));
196 }
197 arch_initcall(adm8668_devs_register);