]>
Commit | Line | Data |
---|---|---|
aa44ef4d | 1 | /* |
c15def1c | 2 | * Copyright (C) 2008-2009 ST-Ericsson SA |
aa44ef4d SK |
3 | * |
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2, as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | */ | |
11 | #include <linux/types.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/device.h> | |
14 | #include <linux/amba/bus.h> | |
aa90eb9d | 15 | #include <linux/interrupt.h> |
aa44ef4d SK |
16 | #include <linux/irq.h> |
17 | #include <linux/platform_device.h> | |
cc2c1334 | 18 | #include <linux/io.h> |
3a8e39c9 | 19 | #include <linux/mfd/abx500/ab8500.h> |
661c6af0 | 20 | #include <linux/mfd/dbx500-prcmu.h> |
fa86a764 LJ |
21 | #include <linux/of.h> |
22 | #include <linux/of_platform.h> | |
23 | #include <linux/regulator/machine.h> | |
4040d10a | 24 | #include <linux/random.h> |
aa44ef4d | 25 | |
5caecb44 | 26 | #include <asm/pmu.h> |
aa44ef4d | 27 | #include <asm/mach/map.h> |
b8edf848 | 28 | |
e657bcf6 | 29 | #include "setup.h" |
eba52748 | 30 | #include "irqs.h" |
94bdc0e2 | 31 | |
6f6d6433 | 32 | #include "board-mop500-regulators.h" |
fa86a764 | 33 | #include "board-mop500.h" |
6f6d6433 | 34 | #include "db8500-regs.h" |
7a4f2609 | 35 | #include "id.h" |
fbf1eadf | 36 | |
6f6d6433 LJ |
37 | struct ab8500_platform_data ab8500_platdata = { |
38 | .irq_base = MOP500_AB8500_IRQ_BASE, | |
39 | .regulator = &ab8500_regulator_plat_data, | |
40 | }; | |
41 | ||
42 | struct prcmu_pdata db8500_prcmu_pdata = { | |
43 | .ab_platdata = &ab8500_platdata, | |
44 | .ab_irq = IRQ_DB8500_AB8500, | |
45 | .irq_base = IRQ_PRCMU_BASE, | |
46 | .version_offset = DB8500_PRCMU_FW_VERSION_OFFSET, | |
47 | .legacy_offset = DB8500_PRCMU_LEGACY_OFFSET, | |
48 | }; | |
49 | ||
aa44ef4d | 50 | /* minimum static i/o mapping required to boot U8500 platforms */ |
abf12d71 | 51 | static struct map_desc u8500_uart_io_desc[] __initdata = { |
92389ca8 RV |
52 | __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), |
53 | __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), | |
abf12d71 | 54 | }; |
bc71c096 LW |
55 | /* U8500 and U9540 common io_desc */ |
56 | static struct map_desc u8500_common_io_desc[] __initdata = { | |
215e83d9 LW |
57 | /* SCU base also covers GIC CPU BASE and TWD with its 4K page */ |
58 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), | |
92389ca8 RV |
59 | __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), |
60 | __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), | |
92389ca8 | 61 | __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), |
92389ca8 RV |
62 | __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), |
63 | ||
64 | __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), | |
65 | __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), | |
66 | __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), | |
67 | __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), | |
68 | __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), | |
69 | ||
c9c09572 | 70 | __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), |
94bdc0e2 RV |
71 | __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), |
72 | __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), | |
73 | __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), | |
ee9581d7 MJ |
74 | }; |
75 | ||
76 | /* U8500 IO map specific description */ | |
77 | static struct map_desc u8500_io_desc[] __initdata = { | |
78 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), | |
fcbd458e | 79 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), |
ee9581d7 MJ |
80 | |
81 | }; | |
82 | ||
83 | /* U9540 IO map specific description */ | |
84 | static struct map_desc u9540_io_desc[] __initdata = { | |
85 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K + SZ_8K), | |
86 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K), | |
75a36ee0 RV |
87 | }; |
88 | ||
abf12d71 | 89 | void __init u8500_map_io(void) |
f946738c | 90 | { |
abf12d71 RV |
91 | /* |
92 | * Map the UARTs early so that the DEBUG_LL stuff continues to work. | |
93 | */ | |
94 | iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc)); | |
f946738c | 95 | |
abf12d71 | 96 | ux500_map_io(); |
f946738c | 97 | |
bc71c096 | 98 | iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc)); |
75a36ee0 | 99 | |
e1bbb55d | 100 | if (cpu_is_ux540_family()) |
ee9581d7 MJ |
101 | iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc)); |
102 | else | |
103 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); | |
aa44ef4d SK |
104 | } |
105 | ||
aa90eb9d RV |
106 | /* |
107 | * The PMU IRQ lines of two cores are wired together into a single interrupt. | |
108 | * Bounce the interrupt to the other core if it's not ours. | |
109 | */ | |
110 | static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) | |
111 | { | |
112 | irqreturn_t ret = handler(irq, dev); | |
113 | int other = !smp_processor_id(); | |
114 | ||
115 | if (ret == IRQ_NONE && cpu_online(other)) | |
116 | irq_set_affinity(irq, cpumask_of(other)); | |
117 | ||
118 | /* | |
119 | * We should be able to get away with the amount of IRQ_NONEs we give, | |
120 | * while still having the spurious IRQ detection code kick in if the | |
121 | * interrupt really starts hitting spuriously. | |
122 | */ | |
123 | return ret; | |
124 | } | |
125 | ||
3a8e39c9 | 126 | struct arm_pmu_platdata db8500_pmu_platdata = { |
aa90eb9d RV |
127 | .handle_irq = db8500_pmu_handler, |
128 | }; | |
129 | ||
eda413c2 LJ |
130 | static const char *db8500_read_soc_id(void) |
131 | { | |
132 | void __iomem *uid = __io_address(U8500_BB_UID_BASE); | |
133 | ||
4040d10a LW |
134 | /* Throw these device-specific numbers into the entropy pool */ |
135 | add_device_randomness(uid, 0x14); | |
eda413c2 | 136 | return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x", |
33c8abce | 137 | readl((u32 *)uid+0), |
eda413c2 LJ |
138 | readl((u32 *)uid+1), readl((u32 *)uid+2), |
139 | readl((u32 *)uid+3), readl((u32 *)uid+4)); | |
140 | } | |
141 | ||
142 | static struct device * __init db8500_soc_device_init(void) | |
143 | { | |
144 | const char *soc_id = db8500_read_soc_id(); | |
145 | ||
146 | return ux500_soc_device_init(soc_id); | |
147 | } | |
148 | ||
fa86a764 | 149 | #ifdef CONFIG_MACH_UX500_DT |
fa86a764 LJ |
150 | static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { |
151 | /* Requires call-back bindings. */ | |
152 | OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata), | |
cece5c40 | 153 | /* Requires DMA bindings. */ |
52819730 LW |
154 | OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0", &mop500_sdi0_data), |
155 | OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1", &mop500_sdi1_data), | |
156 | OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2", &mop500_sdi2_data), | |
157 | OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4", &mop500_sdi4_data), | |
acab2f6f LJ |
158 | OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000, |
159 | "ux500-msp-i2s.0", &msp0_platform_data), | |
160 | OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000, | |
161 | "ux500-msp-i2s.1", &msp1_platform_data), | |
162 | OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000, | |
163 | "ux500-msp-i2s.2", &msp2_platform_data), | |
164 | OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000, | |
165 | "ux500-msp-i2s.3", &msp3_platform_data), | |
1b1d2e83 | 166 | /* Requires non-DT:able platform data. */ |
05ec260e LW |
167 | OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", |
168 | &db8500_prcmu_pdata), | |
946cc7dd | 169 | OF_DEV_AUXDATA("stericsson,ux500-cryp", 0xa03cb000, "cryp1", NULL), |
f016d440 | 170 | OF_DEV_AUXDATA("stericsson,ux500-hash", 0xa03c2000, "hash1", NULL), |
ef95f7ff FB |
171 | OF_DEV_AUXDATA("stericsson,snd-soc-mop500", 0, "snd-soc-mop500.0", |
172 | NULL), | |
fa86a764 LJ |
173 | {}, |
174 | }; | |
175 | ||
c21a43b7 | 176 | static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = { |
c21a43b7 LJ |
177 | OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", |
178 | &db8500_prcmu_pdata), | |
179 | {}, | |
180 | }; | |
181 | ||
fa86a764 LJ |
182 | static const struct of_device_id u8500_local_bus_nodes[] = { |
183 | /* only create devices below soc node */ | |
184 | { .compatible = "stericsson,db8500", }, | |
185 | { .compatible = "stericsson,db8500-prcmu", }, | |
186 | { .compatible = "simple-bus"}, | |
187 | { }, | |
188 | }; | |
189 | ||
190 | static void __init u8500_init_machine(void) | |
191 | { | |
1e74043a | 192 | struct device *parent = db8500_soc_device_init(); |
fa86a764 LJ |
193 | |
194 | /* Pinmaps must be in place before devices register */ | |
195 | if (of_machine_is_compatible("st-ericsson,mop500")) | |
196 | mop500_pinmaps_init(); | |
265c3c0a | 197 | else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { |
fa86a764 | 198 | snowball_pinmaps_init(); |
265c3c0a | 199 | } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) |
fa86a764 | 200 | hrefv60_pinmaps_init(); |
58e5b9e3 LJ |
201 | else if (of_machine_is_compatible("st-ericsson,ccu9540")) {} |
202 | /* TODO: Add pinmaps for ccu9540 board. */ | |
fa86a764 | 203 | |
c21a43b7 LJ |
204 | /* automatically probe child nodes of dbx5x0 devices */ |
205 | if (of_machine_is_compatible("st-ericsson,u8540")) | |
206 | of_platform_populate(NULL, u8500_local_bus_nodes, | |
207 | u8540_auxdata_lookup, parent); | |
208 | else | |
209 | of_platform_populate(NULL, u8500_local_bus_nodes, | |
210 | u8500_auxdata_lookup, parent); | |
fa86a764 LJ |
211 | } |
212 | ||
79b40753 LJ |
213 | static const char * stericsson_dt_platform_compat[] = { |
214 | "st-ericsson,u8500", | |
215 | "st-ericsson,u8540", | |
216 | "st-ericsson,u9500", | |
217 | "st-ericsson,u9540", | |
fa86a764 LJ |
218 | NULL, |
219 | }; | |
220 | ||
46c1bf81 | 221 | DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)") |
f44c5fd1 | 222 | .smp = smp_ops(ux500_smp_ops), |
fa86a764 LJ |
223 | .map_io = u8500_map_io, |
224 | .init_irq = ux500_init_irq, | |
225 | /* we re-use nomadik timer here */ | |
6bb27d73 | 226 | .init_time = ux500_timer_init, |
fa86a764 | 227 | .init_machine = u8500_init_machine, |
74a1c9ab | 228 | .init_late = NULL, |
79b40753 | 229 | .dt_compat = stericsson_dt_platform_compat, |
bd93ec50 | 230 | .restart = ux500_restart, |
fa86a764 LJ |
231 | MACHINE_END |
232 | ||
233 | #endif |