Merge branch 'x86/cleanups' into x86/trampoline
[deliverable/linux.git] / arch / arm / mach-vexpress / v2m.c
1 /*
2 * Versatile Express V2M Motherboard Support
3 */
4 #include <linux/device.h>
5 #include <linux/amba/bus.h>
6 #include <linux/amba/mmci.h>
7 #include <linux/io.h>
8 #include <linux/init.h>
9 #include <linux/platform_device.h>
10 #include <linux/smsc911x.h>
11 #include <linux/spinlock.h>
12 #include <linux/sysdev.h>
13 #include <linux/usb/isp1760.h>
14
15 #include <asm/clkdev.h>
16 #include <asm/sizes.h>
17 #include <asm/mach/flash.h>
18 #include <asm/mach/map.h>
19 #include <asm/mach/time.h>
20 #include <asm/hardware/arm_timer.h>
21
22 #include <mach/clkdev.h>
23 #include <mach/motherboard.h>
24
25 #include <plat/timer-sp.h>
26
27 #include "core.h"
28
29 #define V2M_PA_CS0 0x40000000
30 #define V2M_PA_CS1 0x44000000
31 #define V2M_PA_CS2 0x48000000
32 #define V2M_PA_CS3 0x4c000000
33 #define V2M_PA_CS7 0x10000000
34
35 static struct map_desc v2m_io_desc[] __initdata = {
36 {
37 .virtual = __MMIO_P2V(V2M_PA_CS7),
38 .pfn = __phys_to_pfn(V2M_PA_CS7),
39 .length = SZ_128K,
40 .type = MT_DEVICE,
41 },
42 };
43
44 void __init v2m_map_io(struct map_desc *tile, size_t num)
45 {
46 iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
47 iotable_init(tile, num);
48 }
49
50
51 static void __init v2m_timer_init(void)
52 {
53 writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
54 writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
55
56 sp804_clocksource_init(MMIO_P2V(V2M_TIMER1));
57 sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0);
58 }
59
60 struct sys_timer v2m_timer = {
61 .init = v2m_timer_init,
62 };
63
64
65 static DEFINE_SPINLOCK(v2m_cfg_lock);
66
67 int v2m_cfg_write(u32 devfn, u32 data)
68 {
69 /* Configuration interface broken? */
70 u32 val;
71
72 printk("%s: writing %08x to %08x\n", __func__, data, devfn);
73
74 devfn |= SYS_CFG_START | SYS_CFG_WRITE;
75
76 spin_lock(&v2m_cfg_lock);
77 val = readl(MMIO_P2V(V2M_SYS_CFGSTAT));
78 writel(val & ~SYS_CFG_COMPLETE, MMIO_P2V(V2M_SYS_CFGSTAT));
79
80 writel(data, MMIO_P2V(V2M_SYS_CFGDATA));
81 writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL));
82
83 do {
84 val = readl(MMIO_P2V(V2M_SYS_CFGSTAT));
85 } while (val == 0);
86 spin_unlock(&v2m_cfg_lock);
87
88 return !!(val & SYS_CFG_ERR);
89 }
90
91 int v2m_cfg_read(u32 devfn, u32 *data)
92 {
93 u32 val;
94
95 devfn |= SYS_CFG_START;
96
97 spin_lock(&v2m_cfg_lock);
98 writel(0, MMIO_P2V(V2M_SYS_CFGSTAT));
99 writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL));
100
101 mb();
102
103 do {
104 cpu_relax();
105 val = readl(MMIO_P2V(V2M_SYS_CFGSTAT));
106 } while (val == 0);
107
108 *data = readl(MMIO_P2V(V2M_SYS_CFGDATA));
109 spin_unlock(&v2m_cfg_lock);
110
111 return !!(val & SYS_CFG_ERR);
112 }
113
114
115 static struct resource v2m_pcie_i2c_resource = {
116 .start = V2M_SERIAL_BUS_PCI,
117 .end = V2M_SERIAL_BUS_PCI + SZ_4K - 1,
118 .flags = IORESOURCE_MEM,
119 };
120
121 static struct platform_device v2m_pcie_i2c_device = {
122 .name = "versatile-i2c",
123 .id = 0,
124 .num_resources = 1,
125 .resource = &v2m_pcie_i2c_resource,
126 };
127
128 static struct resource v2m_ddc_i2c_resource = {
129 .start = V2M_SERIAL_BUS_DVI,
130 .end = V2M_SERIAL_BUS_DVI + SZ_4K - 1,
131 .flags = IORESOURCE_MEM,
132 };
133
134 static struct platform_device v2m_ddc_i2c_device = {
135 .name = "versatile-i2c",
136 .id = 1,
137 .num_resources = 1,
138 .resource = &v2m_ddc_i2c_resource,
139 };
140
141 static struct resource v2m_eth_resources[] = {
142 {
143 .start = V2M_LAN9118,
144 .end = V2M_LAN9118 + SZ_64K - 1,
145 .flags = IORESOURCE_MEM,
146 }, {
147 .start = IRQ_V2M_LAN9118,
148 .end = IRQ_V2M_LAN9118,
149 .flags = IORESOURCE_IRQ,
150 },
151 };
152
153 static struct smsc911x_platform_config v2m_eth_config = {
154 .flags = SMSC911X_USE_32BIT,
155 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
156 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
157 .phy_interface = PHY_INTERFACE_MODE_MII,
158 };
159
160 static struct platform_device v2m_eth_device = {
161 .name = "smsc911x",
162 .id = -1,
163 .resource = v2m_eth_resources,
164 .num_resources = ARRAY_SIZE(v2m_eth_resources),
165 .dev.platform_data = &v2m_eth_config,
166 };
167
168 static struct resource v2m_usb_resources[] = {
169 {
170 .start = V2M_ISP1761,
171 .end = V2M_ISP1761 + SZ_128K - 1,
172 .flags = IORESOURCE_MEM,
173 }, {
174 .start = IRQ_V2M_ISP1761,
175 .end = IRQ_V2M_ISP1761,
176 .flags = IORESOURCE_IRQ,
177 },
178 };
179
180 static struct isp1760_platform_data v2m_usb_config = {
181 .is_isp1761 = true,
182 .bus_width_16 = false,
183 .port1_otg = true,
184 .analog_oc = false,
185 .dack_polarity_high = false,
186 .dreq_polarity_high = false,
187 };
188
189 static struct platform_device v2m_usb_device = {
190 .name = "isp1760",
191 .id = -1,
192 .resource = v2m_usb_resources,
193 .num_resources = ARRAY_SIZE(v2m_usb_resources),
194 .dev.platform_data = &v2m_usb_config,
195 };
196
197 static int v2m_flash_init(void)
198 {
199 writel(0, MMIO_P2V(V2M_SYS_FLASH));
200 return 0;
201 }
202
203 static void v2m_flash_exit(void)
204 {
205 writel(0, MMIO_P2V(V2M_SYS_FLASH));
206 }
207
208 static void v2m_flash_set_vpp(int on)
209 {
210 writel(on != 0, MMIO_P2V(V2M_SYS_FLASH));
211 }
212
213 static struct flash_platform_data v2m_flash_data = {
214 .map_name = "cfi_probe",
215 .width = 4,
216 .init = v2m_flash_init,
217 .exit = v2m_flash_exit,
218 .set_vpp = v2m_flash_set_vpp,
219 };
220
221 static struct resource v2m_flash_resources[] = {
222 {
223 .start = V2M_NOR0,
224 .end = V2M_NOR0 + SZ_64M - 1,
225 .flags = IORESOURCE_MEM,
226 }, {
227 .start = V2M_NOR1,
228 .end = V2M_NOR1 + SZ_64M - 1,
229 .flags = IORESOURCE_MEM,
230 },
231 };
232
233 static struct platform_device v2m_flash_device = {
234 .name = "armflash",
235 .id = -1,
236 .resource = v2m_flash_resources,
237 .num_resources = ARRAY_SIZE(v2m_flash_resources),
238 .dev.platform_data = &v2m_flash_data,
239 };
240
241
242 static unsigned int v2m_mmci_status(struct device *dev)
243 {
244 return readl(MMIO_P2V(V2M_SYS_MCI)) & (1 << 0);
245 }
246
247 static struct mmci_platform_data v2m_mmci_data = {
248 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
249 .status = v2m_mmci_status,
250 };
251
252 static AMBA_DEVICE(aaci, "mb:aaci", V2M_AACI, NULL);
253 static AMBA_DEVICE(mmci, "mb:mmci", V2M_MMCI, &v2m_mmci_data);
254 static AMBA_DEVICE(kmi0, "mb:kmi0", V2M_KMI0, NULL);
255 static AMBA_DEVICE(kmi1, "mb:kmi1", V2M_KMI1, NULL);
256 static AMBA_DEVICE(uart0, "mb:uart0", V2M_UART0, NULL);
257 static AMBA_DEVICE(uart1, "mb:uart1", V2M_UART1, NULL);
258 static AMBA_DEVICE(uart2, "mb:uart2", V2M_UART2, NULL);
259 static AMBA_DEVICE(uart3, "mb:uart3", V2M_UART3, NULL);
260 static AMBA_DEVICE(wdt, "mb:wdt", V2M_WDT, NULL);
261 static AMBA_DEVICE(rtc, "mb:rtc", V2M_RTC, NULL);
262
263 static struct amba_device *v2m_amba_devs[] __initdata = {
264 &aaci_device,
265 &mmci_device,
266 &kmi0_device,
267 &kmi1_device,
268 &uart0_device,
269 &uart1_device,
270 &uart2_device,
271 &uart3_device,
272 &wdt_device,
273 &rtc_device,
274 };
275
276
277 static long v2m_osc_round(struct clk *clk, unsigned long rate)
278 {
279 return rate;
280 }
281
282 static int v2m_osc1_set(struct clk *clk, unsigned long rate)
283 {
284 return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate);
285 }
286
287 static const struct clk_ops osc1_clk_ops = {
288 .round = v2m_osc_round,
289 .set = v2m_osc1_set,
290 };
291
292 static struct clk osc1_clk = {
293 .ops = &osc1_clk_ops,
294 .rate = 24000000,
295 };
296
297 static struct clk osc2_clk = {
298 .rate = 24000000,
299 };
300
301 static struct clk dummy_apb_pclk;
302
303 static struct clk_lookup v2m_lookups[] = {
304 { /* AMBA bus clock */
305 .con_id = "apb_pclk",
306 .clk = &dummy_apb_pclk,
307 }, { /* UART0 */
308 .dev_id = "mb:uart0",
309 .clk = &osc2_clk,
310 }, { /* UART1 */
311 .dev_id = "mb:uart1",
312 .clk = &osc2_clk,
313 }, { /* UART2 */
314 .dev_id = "mb:uart2",
315 .clk = &osc2_clk,
316 }, { /* UART3 */
317 .dev_id = "mb:uart3",
318 .clk = &osc2_clk,
319 }, { /* KMI0 */
320 .dev_id = "mb:kmi0",
321 .clk = &osc2_clk,
322 }, { /* KMI1 */
323 .dev_id = "mb:kmi1",
324 .clk = &osc2_clk,
325 }, { /* MMC0 */
326 .dev_id = "mb:mmci",
327 .clk = &osc2_clk,
328 }, { /* CLCD */
329 .dev_id = "mb:clcd",
330 .clk = &osc1_clk,
331 },
332 };
333
334 static void v2m_power_off(void)
335 {
336 if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
337 printk(KERN_EMERG "Unable to shutdown\n");
338 }
339
340 static void v2m_restart(char str, const char *cmd)
341 {
342 if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
343 printk(KERN_EMERG "Unable to reboot\n");
344 }
345
346 static int __init v2m_init(void)
347 {
348 int i;
349
350 clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
351
352 platform_device_register(&v2m_pcie_i2c_device);
353 platform_device_register(&v2m_ddc_i2c_device);
354 platform_device_register(&v2m_flash_device);
355 platform_device_register(&v2m_eth_device);
356 platform_device_register(&v2m_usb_device);
357
358 for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
359 amba_device_register(v2m_amba_devs[i], &iomem_resource);
360
361 pm_power_off = v2m_power_off;
362 arm_pm_restart = v2m_restart;
363
364 return 0;
365 }
366 arch_initcall(v2m_init);
This page took 0.03965 seconds and 6 git commands to generate.