1/*
2 * SH-X3 Prototype Setup
3 *
4 *  Copyright (C) 2007 - 2010  Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License.  See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/platform_device.h>
11#include <linux/init.h>
12#include <linux/serial.h>
13#include <linux/serial_sci.h>
14#include <linux/io.h>
15#include <linux/gpio.h>
16#include <linux/sh_timer.h>
17#include <linux/sh_intc.h>
18#include <cpu/shx3.h>
19#include <asm/mmzone.h>
20
21/*
22 * This intentionally only registers SCIF ports 0, 1, and 3. SCIF 2
23 * INTEVT values overlap with the FPU EXPEVT ones, requiring special
24 * demuxing in the exception dispatch path.
25 *
26 * As this overlap is something that never should have made it in to
27 * silicon in the first place, we just refuse to deal with the port at
28 * all rather than adding infrastructure to hack around it.
29 */
30static struct plat_sci_port scif0_platform_data = {
31	.flags		= UPF_BOOT_AUTOCONF,
32	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
33	.type		= PORT_SCIF,
34};
35
36static struct resource scif0_resources[] = {
37	DEFINE_RES_MEM(0xffc30000, 0x100),
38	DEFINE_RES_IRQ(evt2irq(0x700)),
39	DEFINE_RES_IRQ(evt2irq(0x720)),
40	DEFINE_RES_IRQ(evt2irq(0x760)),
41	DEFINE_RES_IRQ(evt2irq(0x740)),
42};
43
44static struct platform_device scif0_device = {
45	.name		= "sh-sci",
46	.id		= 0,
47	.resource	= scif0_resources,
48	.num_resources	= ARRAY_SIZE(scif0_resources),
49	.dev		= {
50		.platform_data	= &scif0_platform_data,
51	},
52};
53
54static struct plat_sci_port scif1_platform_data = {
55	.flags		= UPF_BOOT_AUTOCONF,
56	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
57	.type		= PORT_SCIF,
58};
59
60static struct resource scif1_resources[] = {
61	DEFINE_RES_MEM(0xffc40000, 0x100),
62	DEFINE_RES_IRQ(evt2irq(0x780)),
63	DEFINE_RES_IRQ(evt2irq(0x7a0)),
64	DEFINE_RES_IRQ(evt2irq(0x7e0)),
65	DEFINE_RES_IRQ(evt2irq(0x7c0)),
66};
67
68static struct platform_device scif1_device = {
69	.name		= "sh-sci",
70	.id		= 1,
71	.resource	= scif1_resources,
72	.num_resources	= ARRAY_SIZE(scif1_resources),
73	.dev		= {
74		.platform_data	= &scif1_platform_data,
75	},
76};
77
78static struct plat_sci_port scif2_platform_data = {
79	.flags		= UPF_BOOT_AUTOCONF,
80	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
81	.type		= PORT_SCIF,
82};
83
84static struct resource scif2_resources[] = {
85	DEFINE_RES_MEM(0xffc60000, 0x100),
86	DEFINE_RES_IRQ(evt2irq(0x880)),
87	DEFINE_RES_IRQ(evt2irq(0x8a0)),
88	DEFINE_RES_IRQ(evt2irq(0x8e0)),
89	DEFINE_RES_IRQ(evt2irq(0x8c0)),
90};
91
92static struct platform_device scif2_device = {
93	.name		= "sh-sci",
94	.id		= 2,
95	.resource	= scif2_resources,
96	.num_resources	= ARRAY_SIZE(scif2_resources),
97	.dev		= {
98		.platform_data	= &scif2_platform_data,
99	},
100};
101
102static struct sh_timer_config tmu0_platform_data = {
103	.channels_mask = 7,
104};
105
106static struct resource tmu0_resources[] = {
107	DEFINE_RES_MEM(0xffc10000, 0x30),
108	DEFINE_RES_IRQ(evt2irq(0x400)),
109	DEFINE_RES_IRQ(evt2irq(0x420)),
110	DEFINE_RES_IRQ(evt2irq(0x440)),
111};
112
113static struct platform_device tmu0_device = {
114	.name		= "sh-tmu",
115	.id		= 0,
116	.dev = {
117		.platform_data	= &tmu0_platform_data,
118	},
119	.resource	= tmu0_resources,
120	.num_resources	= ARRAY_SIZE(tmu0_resources),
121};
122
123static struct sh_timer_config tmu1_platform_data = {
124	.channels_mask = 7,
125};
126
127static struct resource tmu1_resources[] = {
128	DEFINE_RES_MEM(0xffc20000, 0x2c),
129	DEFINE_RES_IRQ(evt2irq(0x460)),
130	DEFINE_RES_IRQ(evt2irq(0x480)),
131	DEFINE_RES_IRQ(evt2irq(0x4a0)),
132};
133
134static struct platform_device tmu1_device = {
135	.name		= "sh-tmu",
136	.id		= 1,
137	.dev = {
138		.platform_data	= &tmu1_platform_data,
139	},
140	.resource	= tmu1_resources,
141	.num_resources	= ARRAY_SIZE(tmu1_resources),
142};
143
144static struct platform_device *shx3_early_devices[] __initdata = {
145	&scif0_device,
146	&scif1_device,
147	&scif2_device,
148	&tmu0_device,
149	&tmu1_device,
150};
151
152static int __init shx3_devices_setup(void)
153{
154	return platform_add_devices(shx3_early_devices,
155				   ARRAY_SIZE(shx3_early_devices));
156}
157arch_initcall(shx3_devices_setup);
158
159void __init plat_early_device_setup(void)
160{
161	early_platform_add_devices(shx3_early_devices,
162				   ARRAY_SIZE(shx3_early_devices));
163}
164
165enum {
166	UNUSED = 0,
167
168	/* interrupt sources */
169	IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
170	IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
171	IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
172	IRL_HHLL, IRL_HHLH, IRL_HHHL,
173	IRQ0, IRQ1, IRQ2, IRQ3,
174	HUDII,
175	TMU0, TMU1, TMU2, TMU3, TMU4, TMU5,
176	PCII0, PCII1, PCII2, PCII3, PCII4,
177	PCII5, PCII6, PCII7, PCII8, PCII9,
178	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
179	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
180	SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
181	SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI,
182	DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3,
183	DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE,
184	DU,
185	DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8, DMAC1_DMINT9,
186	DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE,
187	IIC, VIN0, VIN1, VCORE0, ATAPI,
188	DTU0, DTU1, DTU2, DTU3,
189	FE0, FE1,
190	GPIO0, GPIO1, GPIO2, GPIO3,
191	PAM, IRM,
192	INTICI0, INTICI1, INTICI2, INTICI3,
193	INTICI4, INTICI5, INTICI6, INTICI7,
194
195	/* interrupt groups */
196	IRL, PCII56789, SCIF0, SCIF1, SCIF2, SCIF3,
197	DMAC0, DMAC1,
198};
199
200static struct intc_vect vectors[] __initdata = {
201	INTC_VECT(HUDII, 0x3e0),
202	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
203	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU3, 0x460),
204	INTC_VECT(TMU4, 0x480), INTC_VECT(TMU5, 0x4a0),
205	INTC_VECT(PCII0, 0x500), INTC_VECT(PCII1, 0x520),
206	INTC_VECT(PCII2, 0x540), INTC_VECT(PCII3, 0x560),
207	INTC_VECT(PCII4, 0x580), INTC_VECT(PCII5, 0x5a0),
208	INTC_VECT(PCII6, 0x5c0), INTC_VECT(PCII7, 0x5e0),
209	INTC_VECT(PCII8, 0x600), INTC_VECT(PCII9, 0x620),
210	INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
211	INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
212	INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0),
213	INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0),
214	INTC_VECT(SCIF3_ERI, 0x880), INTC_VECT(SCIF3_RXI, 0x8a0),
215	INTC_VECT(SCIF3_BRI, 0x8c0), INTC_VECT(SCIF3_TXI, 0x8e0),
216	INTC_VECT(DMAC0_DMINT0, 0x900), INTC_VECT(DMAC0_DMINT1, 0x920),
217	INTC_VECT(DMAC0_DMINT2, 0x940), INTC_VECT(DMAC0_DMINT3, 0x960),
218	INTC_VECT(DMAC0_DMINT4, 0x980), INTC_VECT(DMAC0_DMINT5, 0x9a0),
219	INTC_VECT(DMAC0_DMAE, 0x9c0),
220	INTC_VECT(DU, 0x9e0),
221	INTC_VECT(DMAC1_DMINT6, 0xa00), INTC_VECT(DMAC1_DMINT7, 0xa20),
222	INTC_VECT(DMAC1_DMINT8, 0xa40), INTC_VECT(DMAC1_DMINT9, 0xa60),
223	INTC_VECT(DMAC1_DMINT10, 0xa80), INTC_VECT(DMAC1_DMINT11, 0xaa0),
224	INTC_VECT(DMAC1_DMAE, 0xac0),
225	INTC_VECT(IIC, 0xae0),
226	INTC_VECT(VIN0, 0xb00), INTC_VECT(VIN1, 0xb20),
227	INTC_VECT(VCORE0, 0xb00), INTC_VECT(ATAPI, 0xb60),
228	INTC_VECT(DTU0, 0xc00), INTC_VECT(DTU0, 0xc20),
229	INTC_VECT(DTU0, 0xc40),
230	INTC_VECT(DTU1, 0xc60), INTC_VECT(DTU1, 0xc80),
231	INTC_VECT(DTU1, 0xca0),
232	INTC_VECT(DTU2, 0xcc0), INTC_VECT(DTU2, 0xce0),
233	INTC_VECT(DTU2, 0xd00),
234	INTC_VECT(DTU3, 0xd20), INTC_VECT(DTU3, 0xd40),
235	INTC_VECT(DTU3, 0xd60),
236	INTC_VECT(FE0, 0xe00), INTC_VECT(FE1, 0xe20),
237	INTC_VECT(GPIO0, 0xe40), INTC_VECT(GPIO1, 0xe60),
238	INTC_VECT(GPIO2, 0xe80), INTC_VECT(GPIO3, 0xea0),
239	INTC_VECT(PAM, 0xec0), INTC_VECT(IRM, 0xee0),
240	INTC_VECT(INTICI0, 0xf00), INTC_VECT(INTICI1, 0xf20),
241	INTC_VECT(INTICI2, 0xf40), INTC_VECT(INTICI3, 0xf60),
242	INTC_VECT(INTICI4, 0xf80), INTC_VECT(INTICI5, 0xfa0),
243	INTC_VECT(INTICI6, 0xfc0), INTC_VECT(INTICI7, 0xfe0),
244};
245
246static struct intc_group groups[] __initdata = {
247	INTC_GROUP(IRL, IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
248		   IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
249		   IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
250		   IRL_HHLL, IRL_HHLH, IRL_HHHL),
251	INTC_GROUP(PCII56789, PCII5, PCII6, PCII7, PCII8, PCII9),
252	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
253	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
254	INTC_GROUP(SCIF3, SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI),
255	INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
256		   DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
257	INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
258		   DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
259};
260
261#define INT2DISTCR0	0xfe4108a0
262#define INT2DISTCR1	0xfe4108a4
263#define INT2DISTCR2	0xfe4108a8
264
265static struct intc_mask_reg mask_registers[] __initdata = {
266	{ 0xfe410030, 0xfe410050, 32, /* CnINTMSK0 / CnINTMSKCLR0 */
267	  { IRQ0, IRQ1, IRQ2, IRQ3 } },
268	{ 0xfe410040, 0xfe410060, 32, /* CnINTMSK1 / CnINTMSKCLR1 */
269	  { IRL } },
270	{ 0xfe410820, 0xfe410850, 32, /* CnINT2MSK0 / CnINT2MSKCLR0 */
271	  { FE1, FE0, 0, ATAPI, VCORE0, VIN1, VIN0, IIC,
272	    DU, GPIO3, GPIO2, GPIO1, GPIO0, PAM, 0, 0,
273	    0, 0, 0, 0, 0, 0, 0, 0, /* HUDI bits ignored */
274	    0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, },
275	    INTC_SMP_BALANCING(INT2DISTCR0) },
276	{ 0xfe410830, 0xfe410860, 32, /* CnINT2MSK1 / CnINT2MSKCLR1 */
277	  { 0, 0, 0, 0, DTU3, DTU2, DTU1, DTU0, /* IRM bits ignored */
278	    PCII9, PCII8, PCII7, PCII6, PCII5, PCII4, PCII3, PCII2,
279	    PCII1, PCII0, DMAC1_DMAE, DMAC1_DMINT11,
280	    DMAC1_DMINT10, DMAC1_DMINT9, DMAC1_DMINT8, DMAC1_DMINT7,
281	    DMAC1_DMINT6, DMAC0_DMAE, DMAC0_DMINT5, DMAC0_DMINT4,
282	    DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 },
283	    INTC_SMP_BALANCING(INT2DISTCR1) },
284	{ 0xfe410840, 0xfe410870, 32, /* CnINT2MSK2 / CnINT2MSKCLR2 */
285	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286	    SCIF3_TXI, SCIF3_BRI, SCIF3_RXI, SCIF3_ERI,
287	    SCIF2_TXI, SCIF2_BRI, SCIF2_RXI, SCIF2_ERI,
288	    SCIF1_TXI, SCIF1_BRI, SCIF1_RXI, SCIF1_ERI,
289	    SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI },
290	    INTC_SMP_BALANCING(INT2DISTCR2) },
291};
292
293static struct intc_prio_reg prio_registers[] __initdata = {
294	{ 0xfe410010, 0, 32, 4, /* INTPRI */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
295
296	{ 0xfe410800, 0, 32, 4, /* INT2PRI0 */ { 0, HUDII, TMU5, TMU4,
297						 TMU3, TMU2, TMU1, TMU0 } },
298	{ 0xfe410804, 0, 32, 4, /* INT2PRI1 */ { DTU3, DTU2, DTU1, DTU0,
299						 SCIF3, SCIF2,
300						 SCIF1, SCIF0 } },
301	{ 0xfe410808, 0, 32, 4, /* INT2PRI2 */ { DMAC1, DMAC0,
302						 PCII56789, PCII4,
303						 PCII3, PCII2,
304						 PCII1, PCII0 } },
305	{ 0xfe41080c, 0, 32, 4, /* INT2PRI3 */ { FE1, FE0, ATAPI, VCORE0,
306						 VIN1, VIN0, IIC, DU} },
307	{ 0xfe410810, 0, 32, 4, /* INT2PRI4 */ { 0, 0, PAM, GPIO3,
308						 GPIO2, GPIO1, GPIO0, IRM } },
309	{ 0xfe410090, 0xfe4100a0, 32, 4, /* CnICIPRI / CnICIPRICLR */
310	  { INTICI7, INTICI6, INTICI5, INTICI4,
311	    INTICI3, INTICI2, INTICI1, INTICI0 }, INTC_SMP(4, 4) },
312};
313
314static DECLARE_INTC_DESC(intc_desc, "shx3", vectors, groups,
315			 mask_registers, prio_registers, NULL);
316
317/* Support for external interrupt pins in IRQ mode */
318static struct intc_vect vectors_irq[] __initdata = {
319	INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
320	INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
321};
322
323static struct intc_sense_reg sense_registers[] __initdata = {
324	{ 0xfe41001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3 } },
325};
326
327static DECLARE_INTC_DESC(intc_desc_irq, "shx3-irq", vectors_irq, groups,
328			 mask_registers, prio_registers, sense_registers);
329
330/* External interrupt pins in IRL mode */
331static struct intc_vect vectors_irl[] __initdata = {
332	INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220),
333	INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260),
334	INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0),
335	INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0),
336	INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320),
337	INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360),
338	INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0),
339	INTC_VECT(IRL_HHHL, 0x3c0),
340};
341
342static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups,
343			 mask_registers, prio_registers, NULL);
344
345void __init plat_irq_setup_pins(int mode)
346{
347	int ret = 0;
348
349	switch (mode) {
350	case IRQ_MODE_IRQ:
351		ret |= gpio_request(GPIO_FN_IRQ3, intc_desc_irq.name);
352		ret |= gpio_request(GPIO_FN_IRQ2, intc_desc_irq.name);
353		ret |= gpio_request(GPIO_FN_IRQ1, intc_desc_irq.name);
354		ret |= gpio_request(GPIO_FN_IRQ0, intc_desc_irq.name);
355
356		if (unlikely(ret)) {
357			pr_err("Failed to set IRQ mode\n");
358			return;
359		}
360
361		register_intc_controller(&intc_desc_irq);
362		break;
363	case IRQ_MODE_IRL3210:
364		ret |= gpio_request(GPIO_FN_IRL3, intc_desc_irl.name);
365		ret |= gpio_request(GPIO_FN_IRL2, intc_desc_irl.name);
366		ret |= gpio_request(GPIO_FN_IRL1, intc_desc_irl.name);
367		ret |= gpio_request(GPIO_FN_IRL0, intc_desc_irl.name);
368
369		if (unlikely(ret)) {
370			pr_err("Failed to set IRL mode\n");
371			return;
372		}
373
374		register_intc_controller(&intc_desc_irl);
375		break;
376	default:
377		BUG();
378	}
379}
380
381void __init plat_irq_setup(void)
382{
383	register_intc_controller(&intc_desc);
384}
385
386void __init plat_mem_setup(void)
387{
388	unsigned int nid = 1;
389
390	/* Register CPU#0 URAM space as Node 1 */
391	setup_bootmem_node(nid++, 0x145f0000, 0x14610000);	/* CPU0 */
392
393#if 0
394	/* XXX: Not yet.. */
395	setup_bootmem_node(nid++, 0x14df0000, 0x14e10000);	/* CPU1 */
396	setup_bootmem_node(nid++, 0x155f0000, 0x15610000);	/* CPU2 */
397	setup_bootmem_node(nid++, 0x15df0000, 0x15e10000);	/* CPU3 */
398#endif
399
400	setup_bootmem_node(nid++, 0x16000000, 0x16020000);	/* CSM */
401}
402