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