1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * arch/arm/mach-spear6xx/spear6xx.c
4 *
5 * SPEAr6XX machines common source file
6 *
7 * Copyright (C) 2009 ST Microelectronics
8 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
9 *
10 * Copyright 2012 Stefan Roese <sr@denx.de>
11 */
12
13 #include <linux/amba/pl08x.h>
14 #include <linux/clk.h>
15 #include <linux/err.h>
16 #include <linux/of.h>
17 #include <linux/of_address.h>
18 #include <linux/of_platform.h>
19 #include <linux/amba/pl080.h>
20 #include <asm/mach/arch.h>
21 #include <asm/mach/time.h>
22 #include <asm/mach/map.h>
23 #include "pl080.h"
24 #include "generic.h"
25 #include <mach/spear.h>
26 #include <mach/misc_regs.h>
27
28 /* dmac device registration */
29 static struct pl08x_channel_data spear600_dma_info[] = {
30 {
31 .bus_id = "ssp1_rx",
32 .min_signal = 0,
33 .max_signal = 0,
34 .muxval = 0,
35 .periph_buses = PL08X_AHB1,
36 }, {
37 .bus_id = "ssp1_tx",
38 .min_signal = 1,
39 .max_signal = 1,
40 .muxval = 0,
41 .periph_buses = PL08X_AHB1,
42 }, {
43 .bus_id = "uart0_rx",
44 .min_signal = 2,
45 .max_signal = 2,
46 .muxval = 0,
47 .periph_buses = PL08X_AHB1,
48 }, {
49 .bus_id = "uart0_tx",
50 .min_signal = 3,
51 .max_signal = 3,
52 .muxval = 0,
53 .periph_buses = PL08X_AHB1,
54 }, {
55 .bus_id = "uart1_rx",
56 .min_signal = 4,
57 .max_signal = 4,
58 .muxval = 0,
59 .periph_buses = PL08X_AHB1,
60 }, {
61 .bus_id = "uart1_tx",
62 .min_signal = 5,
63 .max_signal = 5,
64 .muxval = 0,
65 .periph_buses = PL08X_AHB1,
66 }, {
67 .bus_id = "ssp2_rx",
68 .min_signal = 6,
69 .max_signal = 6,
70 .muxval = 0,
71 .periph_buses = PL08X_AHB2,
72 }, {
73 .bus_id = "ssp2_tx",
74 .min_signal = 7,
75 .max_signal = 7,
76 .muxval = 0,
77 .periph_buses = PL08X_AHB2,
78 }, {
79 .bus_id = "ssp0_rx",
80 .min_signal = 8,
81 .max_signal = 8,
82 .muxval = 0,
83 .periph_buses = PL08X_AHB1,
84 }, {
85 .bus_id = "ssp0_tx",
86 .min_signal = 9,
87 .max_signal = 9,
88 .muxval = 0,
89 .periph_buses = PL08X_AHB1,
90 }, {
91 .bus_id = "i2c_rx",
92 .min_signal = 10,
93 .max_signal = 10,
94 .muxval = 0,
95 .periph_buses = PL08X_AHB1,
96 }, {
97 .bus_id = "i2c_tx",
98 .min_signal = 11,
99 .max_signal = 11,
100 .muxval = 0,
101 .periph_buses = PL08X_AHB1,
102 }, {
103 .bus_id = "irda",
104 .min_signal = 12,
105 .max_signal = 12,
106 .muxval = 0,
107 .periph_buses = PL08X_AHB1,
108 }, {
109 .bus_id = "adc",
110 .min_signal = 13,
111 .max_signal = 13,
112 .muxval = 0,
113 .periph_buses = PL08X_AHB2,
114 }, {
115 .bus_id = "to_jpeg",
116 .min_signal = 14,
117 .max_signal = 14,
118 .muxval = 0,
119 .periph_buses = PL08X_AHB1,
120 }, {
121 .bus_id = "from_jpeg",
122 .min_signal = 15,
123 .max_signal = 15,
124 .muxval = 0,
125 .periph_buses = PL08X_AHB1,
126 }, {
127 .bus_id = "ras0_rx",
128 .min_signal = 0,
129 .max_signal = 0,
130 .muxval = 1,
131 .periph_buses = PL08X_AHB1,
132 }, {
133 .bus_id = "ras0_tx",
134 .min_signal = 1,
135 .max_signal = 1,
136 .muxval = 1,
137 .periph_buses = PL08X_AHB1,
138 }, {
139 .bus_id = "ras1_rx",
140 .min_signal = 2,
141 .max_signal = 2,
142 .muxval = 1,
143 .periph_buses = PL08X_AHB1,
144 }, {
145 .bus_id = "ras1_tx",
146 .min_signal = 3,
147 .max_signal = 3,
148 .muxval = 1,
149 .periph_buses = PL08X_AHB1,
150 }, {
151 .bus_id = "ras2_rx",
152 .min_signal = 4,
153 .max_signal = 4,
154 .muxval = 1,
155 .periph_buses = PL08X_AHB1,
156 }, {
157 .bus_id = "ras2_tx",
158 .min_signal = 5,
159 .max_signal = 5,
160 .muxval = 1,
161 .periph_buses = PL08X_AHB1,
162 }, {
163 .bus_id = "ras3_rx",
164 .min_signal = 6,
165 .max_signal = 6,
166 .muxval = 1,
167 .periph_buses = PL08X_AHB1,
168 }, {
169 .bus_id = "ras3_tx",
170 .min_signal = 7,
171 .max_signal = 7,
172 .muxval = 1,
173 .periph_buses = PL08X_AHB1,
174 }, {
175 .bus_id = "ras4_rx",
176 .min_signal = 8,
177 .max_signal = 8,
178 .muxval = 1,
179 .periph_buses = PL08X_AHB1,
180 }, {
181 .bus_id = "ras4_tx",
182 .min_signal = 9,
183 .max_signal = 9,
184 .muxval = 1,
185 .periph_buses = PL08X_AHB1,
186 }, {
187 .bus_id = "ras5_rx",
188 .min_signal = 10,
189 .max_signal = 10,
190 .muxval = 1,
191 .periph_buses = PL08X_AHB1,
192 }, {
193 .bus_id = "ras5_tx",
194 .min_signal = 11,
195 .max_signal = 11,
196 .muxval = 1,
197 .periph_buses = PL08X_AHB1,
198 }, {
199 .bus_id = "ras6_rx",
200 .min_signal = 12,
201 .max_signal = 12,
202 .muxval = 1,
203 .periph_buses = PL08X_AHB1,
204 }, {
205 .bus_id = "ras6_tx",
206 .min_signal = 13,
207 .max_signal = 13,
208 .muxval = 1,
209 .periph_buses = PL08X_AHB1,
210 }, {
211 .bus_id = "ras7_rx",
212 .min_signal = 14,
213 .max_signal = 14,
214 .muxval = 1,
215 .periph_buses = PL08X_AHB1,
216 }, {
217 .bus_id = "ras7_tx",
218 .min_signal = 15,
219 .max_signal = 15,
220 .muxval = 1,
221 .periph_buses = PL08X_AHB1,
222 }, {
223 .bus_id = "ext0_rx",
224 .min_signal = 0,
225 .max_signal = 0,
226 .muxval = 2,
227 .periph_buses = PL08X_AHB2,
228 }, {
229 .bus_id = "ext0_tx",
230 .min_signal = 1,
231 .max_signal = 1,
232 .muxval = 2,
233 .periph_buses = PL08X_AHB2,
234 }, {
235 .bus_id = "ext1_rx",
236 .min_signal = 2,
237 .max_signal = 2,
238 .muxval = 2,
239 .periph_buses = PL08X_AHB2,
240 }, {
241 .bus_id = "ext1_tx",
242 .min_signal = 3,
243 .max_signal = 3,
244 .muxval = 2,
245 .periph_buses = PL08X_AHB2,
246 }, {
247 .bus_id = "ext2_rx",
248 .min_signal = 4,
249 .max_signal = 4,
250 .muxval = 2,
251 .periph_buses = PL08X_AHB2,
252 }, {
253 .bus_id = "ext2_tx",
254 .min_signal = 5,
255 .max_signal = 5,
256 .muxval = 2,
257 .periph_buses = PL08X_AHB2,
258 }, {
259 .bus_id = "ext3_rx",
260 .min_signal = 6,
261 .max_signal = 6,
262 .muxval = 2,
263 .periph_buses = PL08X_AHB2,
264 }, {
265 .bus_id = "ext3_tx",
266 .min_signal = 7,
267 .max_signal = 7,
268 .muxval = 2,
269 .periph_buses = PL08X_AHB2,
270 }, {
271 .bus_id = "ext4_rx",
272 .min_signal = 8,
273 .max_signal = 8,
274 .muxval = 2,
275 .periph_buses = PL08X_AHB2,
276 }, {
277 .bus_id = "ext4_tx",
278 .min_signal = 9,
279 .max_signal = 9,
280 .muxval = 2,
281 .periph_buses = PL08X_AHB2,
282 }, {
283 .bus_id = "ext5_rx",
284 .min_signal = 10,
285 .max_signal = 10,
286 .muxval = 2,
287 .periph_buses = PL08X_AHB2,
288 }, {
289 .bus_id = "ext5_tx",
290 .min_signal = 11,
291 .max_signal = 11,
292 .muxval = 2,
293 .periph_buses = PL08X_AHB2,
294 }, {
295 .bus_id = "ext6_rx",
296 .min_signal = 12,
297 .max_signal = 12,
298 .muxval = 2,
299 .periph_buses = PL08X_AHB2,
300 }, {
301 .bus_id = "ext6_tx",
302 .min_signal = 13,
303 .max_signal = 13,
304 .muxval = 2,
305 .periph_buses = PL08X_AHB2,
306 }, {
307 .bus_id = "ext7_rx",
308 .min_signal = 14,
309 .max_signal = 14,
310 .muxval = 2,
311 .periph_buses = PL08X_AHB2,
312 }, {
313 .bus_id = "ext7_tx",
314 .min_signal = 15,
315 .max_signal = 15,
316 .muxval = 2,
317 .periph_buses = PL08X_AHB2,
318 },
319 };
320
321 static struct pl08x_platform_data spear6xx_pl080_plat_data = {
322 .memcpy_burst_size = PL08X_BURST_SZ_16,
323 .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
324 .memcpy_prot_buff = true,
325 .memcpy_prot_cache = true,
326 .lli_buses = PL08X_AHB1,
327 .mem_buses = PL08X_AHB1,
328 .get_xfer_signal = pl080_get_signal,
329 .put_xfer_signal = pl080_put_signal,
330 .slave_channels = spear600_dma_info,
331 .num_slave_channels = ARRAY_SIZE(spear600_dma_info),
332 };
333
334 /*
335 * Following will create 16MB static virtual/physical mappings
336 * PHYSICAL VIRTUAL
337 * 0xF0000000 0xF0000000
338 * 0xF1000000 0xF1000000
339 * 0xD0000000 0xFD000000
340 * 0xFC000000 0xFC000000
341 */
342 struct map_desc spear6xx_io_desc[] __initdata = {
343 {
344 .virtual = (unsigned long)VA_SPEAR6XX_ML_CPU_BASE,
345 .pfn = __phys_to_pfn(SPEAR_ICM3_ML1_2_BASE),
346 .length = 2 * SZ_16M,
347 .type = MT_DEVICE
348 }, {
349 .virtual = (unsigned long)VA_SPEAR_ICM1_2_BASE,
350 .pfn = __phys_to_pfn(SPEAR_ICM1_2_BASE),
351 .length = SZ_16M,
352 .type = MT_DEVICE
353 }, {
354 .virtual = (unsigned long)VA_SPEAR_ICM3_SMI_CTRL_BASE,
355 .pfn = __phys_to_pfn(SPEAR_ICM3_SMI_CTRL_BASE),
356 .length = SZ_16M,
357 .type = MT_DEVICE
358 },
359 };
360
361 /* This will create static memory mapping for selected devices */
spear6xx_map_io(void)362 void __init spear6xx_map_io(void)
363 {
364 iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
365 }
366
spear6xx_timer_init(void)367 void __init spear6xx_timer_init(void)
368 {
369 char pclk_name[] = "pll3_clk";
370 struct clk *gpt_clk, *pclk;
371
372 spear6xx_clk_init(MISC_BASE);
373
374 /* get the system timer clock */
375 gpt_clk = clk_get_sys("gpt0", NULL);
376 if (IS_ERR(gpt_clk)) {
377 pr_err("%s:couldn't get clk for gpt\n", __func__);
378 BUG();
379 }
380
381 /* get the suitable parent clock for timer*/
382 pclk = clk_get(NULL, pclk_name);
383 if (IS_ERR(pclk)) {
384 pr_err("%s:couldn't get %s as parent for gpt\n",
385 __func__, pclk_name);
386 BUG();
387 }
388
389 clk_set_parent(gpt_clk, pclk);
390 clk_put(gpt_clk);
391 clk_put(pclk);
392
393 spear_setup_of_timer();
394 }
395
396 /* Add auxdata to pass platform data */
397 struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
398 OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
399 &spear6xx_pl080_plat_data),
400 {}
401 };
402
spear600_dt_init(void)403 static void __init spear600_dt_init(void)
404 {
405 of_platform_default_populate(NULL, spear6xx_auxdata_lookup, NULL);
406 }
407
408 static const char *spear600_dt_board_compat[] = {
409 "st,spear600",
410 NULL
411 };
412
413 DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
414 .map_io = spear6xx_map_io,
415 .init_time = spear6xx_timer_init,
416 .init_machine = spear600_dt_init,
417 .restart = spear_restart,
418 .dt_compat = spear600_dt_board_compat,
419 MACHINE_END
420