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