1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
3  *		http://www.samsung.com
4  *
5  * Copyright 2008 Openmoko, Inc.
6  * Copyright 2008 Simtec Electronics
7  *	Ben Dooks <ben@simtec.co.uk>
8  *	http://armlinux.simtec.co.uk/
9  *
10  * Common Codes for S3C64XX machines
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/interrupt.h>
21 #include <linux/ioport.h>
22 #include <linux/serial_core.h>
23 #include <linux/platform_device.h>
24 #include <linux/io.h>
25 #include <linux/dma-mapping.h>
26 #include <linux/irq.h>
27 #include <linux/gpio.h>
28 
29 #include <asm/mach/arch.h>
30 #include <asm/mach/map.h>
31 #include <asm/hardware/vic.h>
32 
33 #include <mach/map.h>
34 #include <mach/hardware.h>
35 #include <mach/regs-gpio.h>
36 
37 #include <plat/cpu.h>
38 #include <plat/clock.h>
39 #include <plat/devs.h>
40 #include <plat/pm.h>
41 #include <plat/gpio-cfg.h>
42 #include <plat/irq-uart.h>
43 #include <plat/irq-vic-timer.h>
44 #include <plat/regs-irqtype.h>
45 #include <plat/regs-serial.h>
46 #include <plat/watchdog-reset.h>
47 
48 #include "common.h"
49 
50 /* uart registration process */
51 
s3c64xx_init_uarts(struct s3c2410_uartcfg * cfg,int no)52 static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
53 {
54 	s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
55 }
56 
57 /* table of supported CPUs */
58 
59 static const char name_s3c6400[] = "S3C6400";
60 static const char name_s3c6410[] = "S3C6410";
61 
62 static struct cpu_table cpu_ids[] __initdata = {
63 	{
64 		.idcode		= S3C6400_CPU_ID,
65 		.idmask		= S3C64XX_CPU_MASK,
66 		.map_io		= s3c6400_map_io,
67 		.init_clocks	= s3c6400_init_clocks,
68 		.init_uarts	= s3c64xx_init_uarts,
69 		.init		= s3c6400_init,
70 		.name		= name_s3c6400,
71 	}, {
72 		.idcode		= S3C6410_CPU_ID,
73 		.idmask		= S3C64XX_CPU_MASK,
74 		.map_io		= s3c6410_map_io,
75 		.init_clocks	= s3c6410_init_clocks,
76 		.init_uarts	= s3c64xx_init_uarts,
77 		.init		= s3c6410_init,
78 		.name		= name_s3c6410,
79 	},
80 };
81 
82 /* minimal IO mapping */
83 
84 /* see notes on uart map in arch/arm/mach-s3c64xx/include/mach/debug-macro.S */
85 #define UART_OFFS (S3C_PA_UART & 0xfffff)
86 
87 static struct map_desc s3c_iodesc[] __initdata = {
88 	{
89 		.virtual	= (unsigned long)S3C_VA_SYS,
90 		.pfn		= __phys_to_pfn(S3C64XX_PA_SYSCON),
91 		.length		= SZ_4K,
92 		.type		= MT_DEVICE,
93 	}, {
94 		.virtual	= (unsigned long)S3C_VA_MEM,
95 		.pfn		= __phys_to_pfn(S3C64XX_PA_SROM),
96 		.length		= SZ_4K,
97 		.type		= MT_DEVICE,
98 	}, {
99 		.virtual	= (unsigned long)(S3C_VA_UART + UART_OFFS),
100 		.pfn		= __phys_to_pfn(S3C_PA_UART),
101 		.length		= SZ_4K,
102 		.type		= MT_DEVICE,
103 	}, {
104 		.virtual	= (unsigned long)VA_VIC0,
105 		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC0),
106 		.length		= SZ_16K,
107 		.type		= MT_DEVICE,
108 	}, {
109 		.virtual	= (unsigned long)VA_VIC1,
110 		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC1),
111 		.length		= SZ_16K,
112 		.type		= MT_DEVICE,
113 	}, {
114 		.virtual	= (unsigned long)S3C_VA_TIMER,
115 		.pfn		= __phys_to_pfn(S3C_PA_TIMER),
116 		.length		= SZ_16K,
117 		.type		= MT_DEVICE,
118 	}, {
119 		.virtual	= (unsigned long)S3C64XX_VA_GPIO,
120 		.pfn		= __phys_to_pfn(S3C64XX_PA_GPIO),
121 		.length		= SZ_4K,
122 		.type		= MT_DEVICE,
123 	}, {
124 		.virtual	= (unsigned long)S3C64XX_VA_MODEM,
125 		.pfn		= __phys_to_pfn(S3C64XX_PA_MODEM),
126 		.length		= SZ_4K,
127 		.type		= MT_DEVICE,
128 	}, {
129 		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
130 		.pfn		= __phys_to_pfn(S3C64XX_PA_WATCHDOG),
131 		.length		= SZ_4K,
132 		.type		= MT_DEVICE,
133 	}, {
134 		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
135 		.pfn		= __phys_to_pfn(S3C64XX_PA_USB_HSPHY),
136 		.length		= SZ_1K,
137 		.type		= MT_DEVICE,
138 	},
139 };
140 
141 static struct bus_type s3c64xx_subsys = {
142 	.name		= "s3c64xx-core",
143 	.dev_name	= "s3c64xx-core",
144 };
145 
146 static struct device s3c64xx_dev = {
147 	.bus	= &s3c64xx_subsys,
148 };
149 
150 /* read cpu identification code */
151 
s3c64xx_init_io(struct map_desc * mach_desc,int size)152 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
153 {
154 	/* initialise the io descriptors we need for initialisation */
155 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
156 	iotable_init(mach_desc, size);
157 	init_consistent_dma_size(SZ_8M);
158 
159 	/* detect cpu id */
160 	s3c64xx_init_cpu();
161 
162 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
163 }
164 
s3c64xx_dev_init(void)165 static __init int s3c64xx_dev_init(void)
166 {
167 	subsys_system_register(&s3c64xx_subsys, NULL);
168 	return device_register(&s3c64xx_dev);
169 }
170 core_initcall(s3c64xx_dev_init);
171 
172 /*
173  * setup the sources the vic should advertise resume
174  * for, even though it is not doing the wake
175  * (set_irq_wake needs to be valid)
176  */
177 #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
178 #define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) |	\
179 			 1 << (IRQ_PENDN - IRQ_VIC1_BASE) |	\
180 			 1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) |	\
181 			 1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) |	\
182 			 1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))
183 
s3c64xx_init_irq(u32 vic0_valid,u32 vic1_valid)184 void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
185 {
186 	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
187 
188 	/* initialise the pair of VICs */
189 	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
190 	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
191 
192 	/* add the timer sub-irqs */
193 	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
194 }
195 
196 #define eint_offset(irq)	((irq) - IRQ_EINT(0))
197 #define eint_irq_to_bit(irq)	((u32)(1 << eint_offset(irq)))
198 
s3c_irq_eint_mask(struct irq_data * data)199 static inline void s3c_irq_eint_mask(struct irq_data *data)
200 {
201 	u32 mask;
202 
203 	mask = __raw_readl(S3C64XX_EINT0MASK);
204 	mask |= (u32)data->chip_data;
205 	__raw_writel(mask, S3C64XX_EINT0MASK);
206 }
207 
s3c_irq_eint_unmask(struct irq_data * data)208 static void s3c_irq_eint_unmask(struct irq_data *data)
209 {
210 	u32 mask;
211 
212 	mask = __raw_readl(S3C64XX_EINT0MASK);
213 	mask &= ~((u32)data->chip_data);
214 	__raw_writel(mask, S3C64XX_EINT0MASK);
215 }
216 
s3c_irq_eint_ack(struct irq_data * data)217 static inline void s3c_irq_eint_ack(struct irq_data *data)
218 {
219 	__raw_writel((u32)data->chip_data, S3C64XX_EINT0PEND);
220 }
221 
s3c_irq_eint_maskack(struct irq_data * data)222 static void s3c_irq_eint_maskack(struct irq_data *data)
223 {
224 	/* compiler should in-line these */
225 	s3c_irq_eint_mask(data);
226 	s3c_irq_eint_ack(data);
227 }
228 
s3c_irq_eint_set_type(struct irq_data * data,unsigned int type)229 static int s3c_irq_eint_set_type(struct irq_data *data, unsigned int type)
230 {
231 	int offs = eint_offset(data->irq);
232 	int pin, pin_val;
233 	int shift;
234 	u32 ctrl, mask;
235 	u32 newvalue = 0;
236 	void __iomem *reg;
237 
238 	if (offs > 27)
239 		return -EINVAL;
240 
241 	if (offs <= 15)
242 		reg = S3C64XX_EINT0CON0;
243 	else
244 		reg = S3C64XX_EINT0CON1;
245 
246 	switch (type) {
247 	case IRQ_TYPE_NONE:
248 		printk(KERN_WARNING "No edge setting!\n");
249 		break;
250 
251 	case IRQ_TYPE_EDGE_RISING:
252 		newvalue = S3C2410_EXTINT_RISEEDGE;
253 		break;
254 
255 	case IRQ_TYPE_EDGE_FALLING:
256 		newvalue = S3C2410_EXTINT_FALLEDGE;
257 		break;
258 
259 	case IRQ_TYPE_EDGE_BOTH:
260 		newvalue = S3C2410_EXTINT_BOTHEDGE;
261 		break;
262 
263 	case IRQ_TYPE_LEVEL_LOW:
264 		newvalue = S3C2410_EXTINT_LOWLEV;
265 		break;
266 
267 	case IRQ_TYPE_LEVEL_HIGH:
268 		newvalue = S3C2410_EXTINT_HILEV;
269 		break;
270 
271 	default:
272 		printk(KERN_ERR "No such irq type %d", type);
273 		return -1;
274 	}
275 
276 	if (offs <= 15)
277 		shift = (offs / 2) * 4;
278 	else
279 		shift = ((offs - 16) / 2) * 4;
280 	mask = 0x7 << shift;
281 
282 	ctrl = __raw_readl(reg);
283 	ctrl &= ~mask;
284 	ctrl |= newvalue << shift;
285 	__raw_writel(ctrl, reg);
286 
287 	/* set the GPIO pin appropriately */
288 
289 	if (offs < 16) {
290 		pin = S3C64XX_GPN(offs);
291 		pin_val = S3C_GPIO_SFN(2);
292 	} else if (offs < 23) {
293 		pin = S3C64XX_GPL(offs + 8 - 16);
294 		pin_val = S3C_GPIO_SFN(3);
295 	} else {
296 		pin = S3C64XX_GPM(offs - 23);
297 		pin_val = S3C_GPIO_SFN(3);
298 	}
299 
300 	s3c_gpio_cfgpin(pin, pin_val);
301 
302 	return 0;
303 }
304 
305 static struct irq_chip s3c_irq_eint = {
306 	.name		= "s3c-eint",
307 	.irq_mask	= s3c_irq_eint_mask,
308 	.irq_unmask	= s3c_irq_eint_unmask,
309 	.irq_mask_ack	= s3c_irq_eint_maskack,
310 	.irq_ack	= s3c_irq_eint_ack,
311 	.irq_set_type	= s3c_irq_eint_set_type,
312 	.irq_set_wake	= s3c_irqext_wake,
313 };
314 
315 /* s3c_irq_demux_eint
316  *
317  * This function demuxes the IRQ from the group0 external interrupts,
318  * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into
319  * the specific handlers s3c_irq_demux_eintX_Y.
320  */
s3c_irq_demux_eint(unsigned int start,unsigned int end)321 static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
322 {
323 	u32 status = __raw_readl(S3C64XX_EINT0PEND);
324 	u32 mask = __raw_readl(S3C64XX_EINT0MASK);
325 	unsigned int irq;
326 
327 	status &= ~mask;
328 	status >>= start;
329 	status &= (1 << (end - start + 1)) - 1;
330 
331 	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
332 		if (status & 1)
333 			generic_handle_irq(irq);
334 
335 		status >>= 1;
336 	}
337 }
338 
s3c_irq_demux_eint0_3(unsigned int irq,struct irq_desc * desc)339 static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
340 {
341 	s3c_irq_demux_eint(0, 3);
342 }
343 
s3c_irq_demux_eint4_11(unsigned int irq,struct irq_desc * desc)344 static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
345 {
346 	s3c_irq_demux_eint(4, 11);
347 }
348 
s3c_irq_demux_eint12_19(unsigned int irq,struct irq_desc * desc)349 static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
350 {
351 	s3c_irq_demux_eint(12, 19);
352 }
353 
s3c_irq_demux_eint20_27(unsigned int irq,struct irq_desc * desc)354 static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
355 {
356 	s3c_irq_demux_eint(20, 27);
357 }
358 
s3c64xx_init_irq_eint(void)359 static int __init s3c64xx_init_irq_eint(void)
360 {
361 	int irq;
362 
363 	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
364 		irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
365 		irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
366 		set_irq_flags(irq, IRQF_VALID);
367 	}
368 
369 	irq_set_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
370 	irq_set_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
371 	irq_set_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
372 	irq_set_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
373 
374 	return 0;
375 }
376 arch_initcall(s3c64xx_init_irq_eint);
377 
s3c64xx_restart(char mode,const char * cmd)378 void s3c64xx_restart(char mode, const char *cmd)
379 {
380 	if (mode != 's')
381 		arch_wdt_reset();
382 
383 	/* if all else fails, or mode was for soft, jump to 0 */
384 	soft_restart(0);
385 }
386