blob: dbc30670a27ff36d9b771ad322b03d5a74ca57fc [file] [log] [blame]
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -08001/*
2 * R8A7740 processor support
3 *
4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -080020#include <linux/delay.h>
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080021#include <linux/kernel.h>
22#include <linux/init.h>
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -080023#include <linux/io.h>
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080024#include <linux/platform_device.h>
25#include <linux/serial_sci.h>
26#include <linux/sh_timer.h>
27#include <mach/r8a7740.h>
Magnus Dammd3ab7222012-02-29 21:37:35 +090028#include <mach/common.h>
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080029#include <asm/mach-types.h>
Magnus Dammd3ab7222012-02-29 21:37:35 +090030#include <asm/mach/map.h>
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080031#include <asm/mach/arch.h>
32
Magnus Dammd3ab7222012-02-29 21:37:35 +090033static struct map_desc r8a7740_io_desc[] __initdata = {
34 /*
35 * for CPGA/INTC/PFC
36 * 0xe6000000-0xefffffff -> 0xe6000000-0xefffffff
37 */
38 {
39 .virtual = 0xe6000000,
40 .pfn = __phys_to_pfn(0xe6000000),
41 .length = 160 << 20,
42 .type = MT_DEVICE_NONSHARED
43 },
44#ifdef CONFIG_CACHE_L2X0
45 /*
46 * for l2x0_init()
47 * 0xf0100000-0xf0101000 -> 0xf0002000-0xf0003000
48 */
49 {
50 .virtual = 0xf0002000,
51 .pfn = __phys_to_pfn(0xf0100000),
52 .length = PAGE_SIZE,
53 .type = MT_DEVICE_NONSHARED
54 },
55#endif
56};
57
58void __init r8a7740_map_io(void)
59{
60 iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
61}
62
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080063/* SCIFA0 */
64static struct plat_sci_port scif0_platform_data = {
65 .mapbase = 0xe6c40000,
66 .flags = UPF_BOOT_AUTOCONF,
67 .scscr = SCSCR_RE | SCSCR_TE,
68 .scbrr_algo_id = SCBRR_ALGO_4,
69 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -080070 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c00)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080071};
72
73static struct platform_device scif0_device = {
74 .name = "sh-sci",
75 .id = 0,
76 .dev = {
77 .platform_data = &scif0_platform_data,
78 },
79};
80
81/* SCIFA1 */
82static struct plat_sci_port scif1_platform_data = {
83 .mapbase = 0xe6c50000,
84 .flags = UPF_BOOT_AUTOCONF,
85 .scscr = SCSCR_RE | SCSCR_TE,
86 .scbrr_algo_id = SCBRR_ALGO_4,
87 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -080088 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c20)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -080089};
90
91static struct platform_device scif1_device = {
92 .name = "sh-sci",
93 .id = 1,
94 .dev = {
95 .platform_data = &scif1_platform_data,
96 },
97};
98
99/* SCIFA2 */
100static struct plat_sci_port scif2_platform_data = {
101 .mapbase = 0xe6c60000,
102 .flags = UPF_BOOT_AUTOCONF,
103 .scscr = SCSCR_RE | SCSCR_TE,
104 .scbrr_algo_id = SCBRR_ALGO_4,
105 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800106 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c40)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800107};
108
109static struct platform_device scif2_device = {
110 .name = "sh-sci",
111 .id = 2,
112 .dev = {
113 .platform_data = &scif2_platform_data,
114 },
115};
116
117/* SCIFA3 */
118static struct plat_sci_port scif3_platform_data = {
119 .mapbase = 0xe6c70000,
120 .flags = UPF_BOOT_AUTOCONF,
121 .scscr = SCSCR_RE | SCSCR_TE,
122 .scbrr_algo_id = SCBRR_ALGO_4,
123 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800124 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c60)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800125};
126
127static struct platform_device scif3_device = {
128 .name = "sh-sci",
129 .id = 3,
130 .dev = {
131 .platform_data = &scif3_platform_data,
132 },
133};
134
135/* SCIFA4 */
136static struct plat_sci_port scif4_platform_data = {
137 .mapbase = 0xe6c80000,
138 .flags = UPF_BOOT_AUTOCONF,
139 .scscr = SCSCR_RE | SCSCR_TE,
140 .scbrr_algo_id = SCBRR_ALGO_4,
141 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800142 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d20)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800143};
144
145static struct platform_device scif4_device = {
146 .name = "sh-sci",
147 .id = 4,
148 .dev = {
149 .platform_data = &scif4_platform_data,
150 },
151};
152
153/* SCIFA5 */
154static struct plat_sci_port scif5_platform_data = {
155 .mapbase = 0xe6cb0000,
156 .flags = UPF_BOOT_AUTOCONF,
157 .scscr = SCSCR_RE | SCSCR_TE,
158 .scbrr_algo_id = SCBRR_ALGO_4,
159 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800160 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d40)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800161};
162
163static struct platform_device scif5_device = {
164 .name = "sh-sci",
165 .id = 5,
166 .dev = {
167 .platform_data = &scif5_platform_data,
168 },
169};
170
171/* SCIFA6 */
172static struct plat_sci_port scif6_platform_data = {
173 .mapbase = 0xe6cc0000,
174 .flags = UPF_BOOT_AUTOCONF,
175 .scscr = SCSCR_RE | SCSCR_TE,
176 .scbrr_algo_id = SCBRR_ALGO_4,
177 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800178 .irqs = SCIx_IRQ_MUXED(evt2irq(0x04c0)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800179};
180
181static struct platform_device scif6_device = {
182 .name = "sh-sci",
183 .id = 6,
184 .dev = {
185 .platform_data = &scif6_platform_data,
186 },
187};
188
189/* SCIFA7 */
190static struct plat_sci_port scif7_platform_data = {
191 .mapbase = 0xe6cd0000,
192 .flags = UPF_BOOT_AUTOCONF,
193 .scscr = SCSCR_RE | SCSCR_TE,
194 .scbrr_algo_id = SCBRR_ALGO_4,
195 .type = PORT_SCIFA,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800196 .irqs = SCIx_IRQ_MUXED(evt2irq(0x04e0)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800197};
198
199static struct platform_device scif7_device = {
200 .name = "sh-sci",
201 .id = 7,
202 .dev = {
203 .platform_data = &scif7_platform_data,
204 },
205};
206
207/* SCIFB */
208static struct plat_sci_port scifb_platform_data = {
209 .mapbase = 0xe6c30000,
210 .flags = UPF_BOOT_AUTOCONF,
211 .scscr = SCSCR_RE | SCSCR_TE,
212 .scbrr_algo_id = SCBRR_ALGO_4,
213 .type = PORT_SCIFB,
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800214 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d60)),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800215};
216
217static struct platform_device scifb_device = {
218 .name = "sh-sci",
219 .id = 8,
220 .dev = {
221 .platform_data = &scifb_platform_data,
222 },
223};
224
225/* CMT */
226static struct sh_timer_config cmt10_platform_data = {
227 .name = "CMT10",
228 .channel_offset = 0x10,
229 .timer_bit = 0,
230 .clockevent_rating = 125,
231 .clocksource_rating = 125,
232};
233
234static struct resource cmt10_resources[] = {
235 [0] = {
236 .name = "CMT10",
237 .start = 0xe6138010,
238 .end = 0xe613801b,
239 .flags = IORESOURCE_MEM,
240 },
241 [1] = {
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800242 .start = evt2irq(0x0b00),
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800243 .flags = IORESOURCE_IRQ,
244 },
245};
246
247static struct platform_device cmt10_device = {
248 .name = "sh_cmt",
249 .id = 10,
250 .dev = {
251 .platform_data = &cmt10_platform_data,
252 },
253 .resource = cmt10_resources,
254 .num_resources = ARRAY_SIZE(cmt10_resources),
255};
256
257static struct platform_device *r8a7740_early_devices[] __initdata = {
258 &scif0_device,
259 &scif1_device,
260 &scif2_device,
261 &scif3_device,
262 &scif4_device,
263 &scif5_device,
264 &scif6_device,
265 &scif7_device,
266 &scifb_device,
267 &cmt10_device,
268};
269
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -0800270/* I2C */
271static struct resource i2c0_resources[] = {
272 [0] = {
273 .name = "IIC0",
274 .start = 0xfff20000,
275 .end = 0xfff20425 - 1,
276 .flags = IORESOURCE_MEM,
277 },
278 [1] = {
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800279 .start = intcs_evt2irq(0xe00),
280 .end = intcs_evt2irq(0xe60),
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -0800281 .flags = IORESOURCE_IRQ,
282 },
283};
284
285static struct resource i2c1_resources[] = {
286 [0] = {
287 .name = "IIC1",
288 .start = 0xe6c20000,
289 .end = 0xe6c20425 - 1,
290 .flags = IORESOURCE_MEM,
291 },
292 [1] = {
Kuninori Morimoto215d6cc2011-11-10 18:46:35 -0800293 .start = evt2irq(0x780), /* IIC1_ALI1 */
294 .end = evt2irq(0x7e0), /* IIC1_DTEI1 */
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -0800295 .flags = IORESOURCE_IRQ,
296 },
297};
298
299static struct platform_device i2c0_device = {
300 .name = "i2c-sh_mobile",
301 .id = 0,
302 .resource = i2c0_resources,
303 .num_resources = ARRAY_SIZE(i2c0_resources),
304};
305
306static struct platform_device i2c1_device = {
307 .name = "i2c-sh_mobile",
308 .id = 1,
309 .resource = i2c1_resources,
310 .num_resources = ARRAY_SIZE(i2c1_resources),
311};
312
313static struct platform_device *r8a7740_late_devices[] __initdata = {
314 &i2c0_device,
315 &i2c1_device,
316};
317
318#define ICCR 0x0004
319#define ICSTART 0x0070
320
321#define i2c_read(reg, offset) ioread8(reg + offset)
322#define i2c_write(reg, offset, data) iowrite8(data, reg + offset)
323
324/*
325 * r8a7740 chip has lasting errata on I2C I/O pad reset.
326 * this is work-around for it.
327 */
328static void r8a7740_i2c_workaround(struct platform_device *pdev)
329{
330 struct resource *res;
331 void __iomem *reg;
332
333 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
334 if (unlikely(!res)) {
335 pr_err("r8a7740 i2c workaround fail (cannot find resource)\n");
336 return;
337 }
338
339 reg = ioremap(res->start, resource_size(res));
340 if (unlikely(!reg)) {
341 pr_err("r8a7740 i2c workaround fail (cannot map IO)\n");
342 return;
343 }
344
345 i2c_write(reg, ICCR, i2c_read(reg, ICCR) | 0x80);
346 i2c_read(reg, ICCR); /* dummy read */
347
348 i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
349 i2c_read(reg, ICSTART); /* dummy read */
350
351 mdelay(100);
352
353 i2c_write(reg, ICCR, 0x01);
354 i2c_read(reg, ICCR);
355 i2c_write(reg, ICSTART, 0x00);
356 i2c_read(reg, ICSTART);
357
358 i2c_write(reg, ICCR, 0x10);
359 mdelay(100);
360 i2c_write(reg, ICCR, 0x00);
361 mdelay(100);
362 i2c_write(reg, ICCR, 0x10);
363 mdelay(100);
364
365 iounmap(reg);
366}
367
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800368void __init r8a7740_add_standard_devices(void)
369{
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -0800370 /* I2C work-around */
371 r8a7740_i2c_workaround(&i2c0_device);
372 r8a7740_i2c_workaround(&i2c1_device);
373
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800374 platform_add_devices(r8a7740_early_devices,
375 ARRAY_SIZE(r8a7740_early_devices));
Kuninori Morimoto6831f3a2011-11-10 18:46:23 -0800376 platform_add_devices(r8a7740_late_devices,
377 ARRAY_SIZE(r8a7740_late_devices));
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800378}
379
380void __init r8a7740_add_early_devices(void)
381{
382 early_platform_add_devices(r8a7740_early_devices,
383 ARRAY_SIZE(r8a7740_early_devices));
Magnus Dammd3ab7222012-02-29 21:37:35 +0900384
385 /* setup early console here as well */
386 shmobile_setup_console();
Kuninori Morimoto6c01ba42011-11-10 18:45:52 -0800387}