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