aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-vexpress/v2m.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-02-11 16:44:53 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-05-02 04:35:38 -0400
commitceade897f31b8bb66f378cc35859fcfd0d46aaa2 (patch)
tree44f6fffb4f93ec6247b468e4009e414b4124f585 /arch/arm/mach-vexpress/v2m.c
parent9bf5b2ef673237e0e43161c56f70ac8bf24e43f9 (diff)
ARM: Add Versatile Express support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-vexpress/v2m.c')
-rw-r--r--arch/arm/mach-vexpress/v2m.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
new file mode 100644
index 000000000000..d250711b8c7a
--- /dev/null
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -0,0 +1,361 @@
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
35static 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
44void __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
51static void 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
60struct sys_timer v2m_timer = {
61 .init = v2m_timer_init,
62};
63
64
65static DEFINE_SPINLOCK(v2m_cfg_lock);
66
67int 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
91int 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
115static 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
121static 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
128static 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
134static 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
141static 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
153static 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
160static 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
168static 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
180static 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
189static 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
197static int v2m_flash_init(void)
198{
199 writel(0, MMIO_P2V(V2M_SYS_FLASH));
200 return 0;
201}
202
203static void v2m_flash_exit(void)
204{
205 writel(0, MMIO_P2V(V2M_SYS_FLASH));
206}
207
208static void v2m_flash_set_vpp(int on)
209{
210 writel(on != 0, MMIO_P2V(V2M_SYS_FLASH));
211}
212
213static 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
221static 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
233static 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
242static unsigned int v2m_mmci_status(struct device *dev)
243{
244 return !(readl(MMIO_P2V(V2M_SYS_MCI)) & (1 << 0));
245}
246
247static 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
252static AMBA_DEVICE(aaci, "mb:aaci", V2M_AACI, NULL);
253static AMBA_DEVICE(mmci, "mb:mmci", V2M_MMCI, &v2m_mmci_data);
254static AMBA_DEVICE(kmi0, "mb:kmi0", V2M_KMI0, NULL);
255static AMBA_DEVICE(kmi1, "mb:kmi1", V2M_KMI1, NULL);
256static AMBA_DEVICE(uart0, "mb:uart0", V2M_UART0, NULL);
257static AMBA_DEVICE(uart1, "mb:uart1", V2M_UART1, NULL);
258static AMBA_DEVICE(uart2, "mb:uart2", V2M_UART2, NULL);
259static AMBA_DEVICE(uart3, "mb:uart3", V2M_UART3, NULL);
260static AMBA_DEVICE(wdt, "mb:wdt", V2M_WDT, NULL);
261static AMBA_DEVICE(rtc, "mb:rtc", V2M_RTC, NULL);
262
263static 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
277static long v2m_osc_round(struct clk *clk, unsigned long rate)
278{
279 return rate;
280}
281
282static 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
287static const struct clk_ops osc1_clk_ops = {
288 .round = v2m_osc_round,
289 .set = v2m_osc1_set,
290};
291
292static struct clk osc1_clk = {
293 .ops = &osc1_clk_ops,
294 .rate = 24000000,
295};
296
297static struct clk osc2_clk = {
298 .rate = 24000000,
299};
300
301static struct clk_lookup v2m_lookups[] = {
302 { /* UART0 */
303 .dev_id = "mb:uart0",
304 .clk = &osc2_clk,
305 }, { /* UART1 */
306 .dev_id = "mb:uart1",
307 .clk = &osc2_clk,
308 }, { /* UART2 */
309 .dev_id = "mb:uart2",
310 .clk = &osc2_clk,
311 }, { /* UART3 */
312 .dev_id = "mb:uart3",
313 .clk = &osc2_clk,
314 }, { /* KMI0 */
315 .dev_id = "mb:kmi0",
316 .clk = &osc2_clk,
317 }, { /* KMI1 */
318 .dev_id = "mb:kmi1",
319 .clk = &osc2_clk,
320 }, { /* MMC0 */
321 .dev_id = "mb:mmci",
322 .clk = &osc2_clk,
323 }, { /* CLCD */
324 .dev_id = "mb:clcd",
325 .clk = &osc1_clk,
326 },
327};
328
329static void v2m_power_off(void)
330{
331 if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
332 printk(KERN_EMERG "Unable to shutdown\n");
333}
334
335static void v2m_restart(char str, const char *cmd)
336{
337 if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
338 printk(KERN_EMERG "Unable to reboot\n");
339}
340
341static int __init v2m_init(void)
342{
343 int i;
344
345 clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
346
347 platform_device_register(&v2m_pcie_i2c_device);
348 platform_device_register(&v2m_ddc_i2c_device);
349 platform_device_register(&v2m_flash_device);
350 platform_device_register(&v2m_eth_device);
351 platform_device_register(&v2m_usb_device);
352
353 for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
354 amba_device_register(v2m_amba_devs[i], &iomem_resource);
355
356 pm_power_off = v2m_power_off;
357 arm_pm_restart = v2m_restart;
358
359 return 0;
360}
361arch_initcall(v2m_init);