ARM: shmobile: r8a7740: add DMAEngine support for FSI
[deliverable/linux.git] / arch / arm / mach-shmobile / setup-r8a7740.c
CommitLineData
6c01ba44
KM
1/*
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 */
6831f3a9 20#include <linux/delay.h>
3841e6f5 21#include <linux/dma-mapping.h>
6c01ba44
KM
22#include <linux/kernel.h>
23#include <linux/init.h>
6831f3a9 24#include <linux/io.h>
6c01ba44
KM
25#include <linux/platform_device.h>
26#include <linux/serial_sci.h>
643c3307 27#include <linux/sh_dma.h>
6c01ba44 28#include <linux/sh_timer.h>
643c3307 29#include <linux/dma-mapping.h>
6c01ba44 30#include <mach/r8a7740.h>
d3ab7221 31#include <mach/common.h>
250a2723 32#include <mach/irqs.h>
6c01ba44 33#include <asm/mach-types.h>
d3ab7221 34#include <asm/mach/map.h>
6c01ba44 35#include <asm/mach/arch.h>
23e5bc03 36#include <asm/mach/time.h>
6c01ba44 37
d3ab7221
MD
38static struct map_desc r8a7740_io_desc[] __initdata = {
39 /*
40 * for CPGA/INTC/PFC
41 * 0xe6000000-0xefffffff -> 0xe6000000-0xefffffff
42 */
43 {
44 .virtual = 0xe6000000,
45 .pfn = __phys_to_pfn(0xe6000000),
46 .length = 160 << 20,
47 .type = MT_DEVICE_NONSHARED
48 },
49#ifdef CONFIG_CACHE_L2X0
50 /*
51 * for l2x0_init()
52 * 0xf0100000-0xf0101000 -> 0xf0002000-0xf0003000
53 */
54 {
55 .virtual = 0xf0002000,
56 .pfn = __phys_to_pfn(0xf0100000),
57 .length = PAGE_SIZE,
58 .type = MT_DEVICE_NONSHARED
59 },
60#endif
61};
62
63void __init r8a7740_map_io(void)
64{
65 iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
3841e6f5
KM
66
67 /*
68 * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
69 * enough to allocate the frame buffer memory.
70 */
71 init_consistent_dma_size(12 << 20);
d3ab7221
MD
72}
73
6c01ba44
KM
74/* SCIFA0 */
75static struct plat_sci_port scif0_platform_data = {
76 .mapbase = 0xe6c40000,
77 .flags = UPF_BOOT_AUTOCONF,
78 .scscr = SCSCR_RE | SCSCR_TE,
79 .scbrr_algo_id = SCBRR_ALGO_4,
80 .type = PORT_SCIFA,
215d6cc9 81 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c00)),
6c01ba44
KM
82};
83
84static struct platform_device scif0_device = {
85 .name = "sh-sci",
86 .id = 0,
87 .dev = {
88 .platform_data = &scif0_platform_data,
89 },
90};
91
92/* SCIFA1 */
93static struct plat_sci_port scif1_platform_data = {
94 .mapbase = 0xe6c50000,
95 .flags = UPF_BOOT_AUTOCONF,
96 .scscr = SCSCR_RE | SCSCR_TE,
97 .scbrr_algo_id = SCBRR_ALGO_4,
98 .type = PORT_SCIFA,
215d6cc9 99 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c20)),
6c01ba44
KM
100};
101
102static struct platform_device scif1_device = {
103 .name = "sh-sci",
104 .id = 1,
105 .dev = {
106 .platform_data = &scif1_platform_data,
107 },
108};
109
110/* SCIFA2 */
111static struct plat_sci_port scif2_platform_data = {
112 .mapbase = 0xe6c60000,
113 .flags = UPF_BOOT_AUTOCONF,
114 .scscr = SCSCR_RE | SCSCR_TE,
115 .scbrr_algo_id = SCBRR_ALGO_4,
116 .type = PORT_SCIFA,
215d6cc9 117 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c40)),
6c01ba44
KM
118};
119
120static struct platform_device scif2_device = {
121 .name = "sh-sci",
122 .id = 2,
123 .dev = {
124 .platform_data = &scif2_platform_data,
125 },
126};
127
128/* SCIFA3 */
129static struct plat_sci_port scif3_platform_data = {
130 .mapbase = 0xe6c70000,
131 .flags = UPF_BOOT_AUTOCONF,
132 .scscr = SCSCR_RE | SCSCR_TE,
133 .scbrr_algo_id = SCBRR_ALGO_4,
134 .type = PORT_SCIFA,
215d6cc9 135 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c60)),
6c01ba44
KM
136};
137
138static struct platform_device scif3_device = {
139 .name = "sh-sci",
140 .id = 3,
141 .dev = {
142 .platform_data = &scif3_platform_data,
143 },
144};
145
146/* SCIFA4 */
147static struct plat_sci_port scif4_platform_data = {
148 .mapbase = 0xe6c80000,
149 .flags = UPF_BOOT_AUTOCONF,
150 .scscr = SCSCR_RE | SCSCR_TE,
151 .scbrr_algo_id = SCBRR_ALGO_4,
152 .type = PORT_SCIFA,
215d6cc9 153 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d20)),
6c01ba44
KM
154};
155
156static struct platform_device scif4_device = {
157 .name = "sh-sci",
158 .id = 4,
159 .dev = {
160 .platform_data = &scif4_platform_data,
161 },
162};
163
164/* SCIFA5 */
165static struct plat_sci_port scif5_platform_data = {
166 .mapbase = 0xe6cb0000,
167 .flags = UPF_BOOT_AUTOCONF,
168 .scscr = SCSCR_RE | SCSCR_TE,
169 .scbrr_algo_id = SCBRR_ALGO_4,
170 .type = PORT_SCIFA,
215d6cc9 171 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d40)),
6c01ba44
KM
172};
173
174static struct platform_device scif5_device = {
175 .name = "sh-sci",
176 .id = 5,
177 .dev = {
178 .platform_data = &scif5_platform_data,
179 },
180};
181
182/* SCIFA6 */
183static struct plat_sci_port scif6_platform_data = {
184 .mapbase = 0xe6cc0000,
185 .flags = UPF_BOOT_AUTOCONF,
186 .scscr = SCSCR_RE | SCSCR_TE,
187 .scbrr_algo_id = SCBRR_ALGO_4,
188 .type = PORT_SCIFA,
215d6cc9 189 .irqs = SCIx_IRQ_MUXED(evt2irq(0x04c0)),
6c01ba44
KM
190};
191
192static struct platform_device scif6_device = {
193 .name = "sh-sci",
194 .id = 6,
195 .dev = {
196 .platform_data = &scif6_platform_data,
197 },
198};
199
200/* SCIFA7 */
201static struct plat_sci_port scif7_platform_data = {
202 .mapbase = 0xe6cd0000,
203 .flags = UPF_BOOT_AUTOCONF,
204 .scscr = SCSCR_RE | SCSCR_TE,
205 .scbrr_algo_id = SCBRR_ALGO_4,
206 .type = PORT_SCIFA,
215d6cc9 207 .irqs = SCIx_IRQ_MUXED(evt2irq(0x04e0)),
6c01ba44
KM
208};
209
210static struct platform_device scif7_device = {
211 .name = "sh-sci",
212 .id = 7,
213 .dev = {
214 .platform_data = &scif7_platform_data,
215 },
216};
217
218/* SCIFB */
219static struct plat_sci_port scifb_platform_data = {
220 .mapbase = 0xe6c30000,
221 .flags = UPF_BOOT_AUTOCONF,
222 .scscr = SCSCR_RE | SCSCR_TE,
223 .scbrr_algo_id = SCBRR_ALGO_4,
224 .type = PORT_SCIFB,
215d6cc9 225 .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d60)),
6c01ba44
KM
226};
227
228static struct platform_device scifb_device = {
229 .name = "sh-sci",
230 .id = 8,
231 .dev = {
232 .platform_data = &scifb_platform_data,
233 },
234};
235
236/* CMT */
237static struct sh_timer_config cmt10_platform_data = {
238 .name = "CMT10",
239 .channel_offset = 0x10,
240 .timer_bit = 0,
241 .clockevent_rating = 125,
242 .clocksource_rating = 125,
243};
244
245static struct resource cmt10_resources[] = {
246 [0] = {
247 .name = "CMT10",
248 .start = 0xe6138010,
249 .end = 0xe613801b,
250 .flags = IORESOURCE_MEM,
251 },
252 [1] = {
215d6cc9 253 .start = evt2irq(0x0b00),
6c01ba44
KM
254 .flags = IORESOURCE_IRQ,
255 },
256};
257
258static struct platform_device cmt10_device = {
259 .name = "sh_cmt",
260 .id = 10,
261 .dev = {
262 .platform_data = &cmt10_platform_data,
263 },
264 .resource = cmt10_resources,
265 .num_resources = ARRAY_SIZE(cmt10_resources),
266};
267
268static struct platform_device *r8a7740_early_devices[] __initdata = {
269 &scif0_device,
270 &scif1_device,
271 &scif2_device,
272 &scif3_device,
273 &scif4_device,
274 &scif5_device,
275 &scif6_device,
276 &scif7_device,
277 &scifb_device,
278 &cmt10_device,
279};
280
643c3307
KM
281/* DMA */
282enum {
283 XMIT_SZ_8BIT = 0,
284 XMIT_SZ_16BIT = 1,
285 XMIT_SZ_32BIT = 2,
286 XMIT_SZ_64BIT = 7,
287 XMIT_SZ_128BIT = 3,
288 XMIT_SZ_256BIT = 4,
289 XMIT_SZ_512BIT = 5,
290};
291
292/* log2(size / 8) - used to calculate number of transfers */
293#define TS_SHIFT { \
294 [XMIT_SZ_8BIT] = 0, \
295 [XMIT_SZ_16BIT] = 1, \
296 [XMIT_SZ_32BIT] = 2, \
297 [XMIT_SZ_64BIT] = 3, \
298 [XMIT_SZ_128BIT] = 4, \
299 [XMIT_SZ_256BIT] = 5, \
300 [XMIT_SZ_512BIT] = 6, \
301}
302
303#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2)))
304#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
305#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
306
307static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
308 {
309 .slave_id = SHDMA_SLAVE_FSIA_TX,
310 .addr = 0xfe1f0024,
311 .chcr = CHCR_TX(XMIT_SZ_32BIT),
312 .mid_rid = 0xb1,
313 }, {
314 .slave_id = SHDMA_SLAVE_FSIA_RX,
315 .addr = 0xfe1f0020,
316 .chcr = CHCR_RX(XMIT_SZ_32BIT),
317 .mid_rid = 0xb2,
318 }, {
319 .slave_id = SHDMA_SLAVE_FSIB_TX,
320 .addr = 0xfe1f0064,
321 .chcr = CHCR_TX(XMIT_SZ_32BIT),
322 .mid_rid = 0xb5,
323 },
324};
325
326#define DMA_CHANNEL(a, b, c) \
327{ \
328 .offset = a, \
329 .dmars = b, \
330 .dmars_bit = c, \
331 .chclr_offset = (0x220 - 0x20) + a \
332}
333
334static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
335 DMA_CHANNEL(0x00, 0, 0),
336 DMA_CHANNEL(0x10, 0, 8),
337 DMA_CHANNEL(0x20, 4, 0),
338 DMA_CHANNEL(0x30, 4, 8),
339 DMA_CHANNEL(0x50, 8, 0),
340 DMA_CHANNEL(0x60, 8, 8),
341};
342
343static const unsigned int ts_shift[] = TS_SHIFT;
344
345static struct sh_dmae_pdata dma_platform_data = {
346 .slave = r8a7740_dmae_slaves,
347 .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves),
348 .channel = r8a7740_dmae_channels,
349 .channel_num = ARRAY_SIZE(r8a7740_dmae_channels),
350 .ts_low_shift = 3,
351 .ts_low_mask = 0x18,
352 .ts_high_shift = (20 - 2),
353 .ts_high_mask = 0x00300000,
354 .ts_shift = ts_shift,
355 .ts_shift_num = ARRAY_SIZE(ts_shift),
356 .dmaor_init = DMAOR_DME,
357 .chclr_present = 1,
358};
359
360/* Resource order important! */
361static struct resource r8a7740_dmae0_resources[] = {
362 {
363 /* Channel registers and DMAOR */
364 .start = 0xfe008020,
365 .end = 0xfe00828f,
366 .flags = IORESOURCE_MEM,
367 },
368 {
369 /* DMARSx */
370 .start = 0xfe009000,
371 .end = 0xfe00900b,
372 .flags = IORESOURCE_MEM,
373 },
374 {
375 .name = "error_irq",
376 .start = evt2irq(0x20c0),
377 .end = evt2irq(0x20c0),
378 .flags = IORESOURCE_IRQ,
379 },
380 {
381 /* IRQ for channels 0-5 */
382 .start = evt2irq(0x2000),
383 .end = evt2irq(0x20a0),
384 .flags = IORESOURCE_IRQ,
385 },
386};
387
388/* Resource order important! */
389static struct resource r8a7740_dmae1_resources[] = {
390 {
391 /* Channel registers and DMAOR */
392 .start = 0xfe018020,
393 .end = 0xfe01828f,
394 .flags = IORESOURCE_MEM,
395 },
396 {
397 /* DMARSx */
398 .start = 0xfe019000,
399 .end = 0xfe01900b,
400 .flags = IORESOURCE_MEM,
401 },
402 {
403 .name = "error_irq",
404 .start = evt2irq(0x21c0),
405 .end = evt2irq(0x21c0),
406 .flags = IORESOURCE_IRQ,
407 },
408 {
409 /* IRQ for channels 0-5 */
410 .start = evt2irq(0x2100),
411 .end = evt2irq(0x21a0),
412 .flags = IORESOURCE_IRQ,
413 },
414};
415
416/* Resource order important! */
417static struct resource r8a7740_dmae2_resources[] = {
418 {
419 /* Channel registers and DMAOR */
420 .start = 0xfe028020,
421 .end = 0xfe02828f,
422 .flags = IORESOURCE_MEM,
423 },
424 {
425 /* DMARSx */
426 .start = 0xfe029000,
427 .end = 0xfe02900b,
428 .flags = IORESOURCE_MEM,
429 },
430 {
431 .name = "error_irq",
432 .start = evt2irq(0x22c0),
433 .end = evt2irq(0x22c0),
434 .flags = IORESOURCE_IRQ,
435 },
436 {
437 /* IRQ for channels 0-5 */
438 .start = evt2irq(0x2200),
439 .end = evt2irq(0x22a0),
440 .flags = IORESOURCE_IRQ,
441 },
442};
443
444static struct platform_device dma0_device = {
445 .name = "sh-dma-engine",
446 .id = 0,
447 .resource = r8a7740_dmae0_resources,
448 .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources),
449 .dev = {
450 .platform_data = &dma_platform_data,
451 },
452};
453
454static struct platform_device dma1_device = {
455 .name = "sh-dma-engine",
456 .id = 1,
457 .resource = r8a7740_dmae1_resources,
458 .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources),
459 .dev = {
460 .platform_data = &dma_platform_data,
461 },
462};
463
464static struct platform_device dma2_device = {
465 .name = "sh-dma-engine",
466 .id = 2,
467 .resource = r8a7740_dmae2_resources,
468 .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources),
469 .dev = {
470 .platform_data = &dma_platform_data,
471 },
472};
473
6831f3a9
KM
474/* I2C */
475static struct resource i2c0_resources[] = {
476 [0] = {
477 .name = "IIC0",
478 .start = 0xfff20000,
479 .end = 0xfff20425 - 1,
480 .flags = IORESOURCE_MEM,
481 },
482 [1] = {
215d6cc9
KM
483 .start = intcs_evt2irq(0xe00),
484 .end = intcs_evt2irq(0xe60),
6831f3a9
KM
485 .flags = IORESOURCE_IRQ,
486 },
487};
488
489static struct resource i2c1_resources[] = {
490 [0] = {
491 .name = "IIC1",
492 .start = 0xe6c20000,
493 .end = 0xe6c20425 - 1,
494 .flags = IORESOURCE_MEM,
495 },
496 [1] = {
215d6cc9
KM
497 .start = evt2irq(0x780), /* IIC1_ALI1 */
498 .end = evt2irq(0x7e0), /* IIC1_DTEI1 */
6831f3a9
KM
499 .flags = IORESOURCE_IRQ,
500 },
501};
502
503static struct platform_device i2c0_device = {
504 .name = "i2c-sh_mobile",
505 .id = 0,
506 .resource = i2c0_resources,
507 .num_resources = ARRAY_SIZE(i2c0_resources),
508};
509
510static struct platform_device i2c1_device = {
511 .name = "i2c-sh_mobile",
512 .id = 1,
513 .resource = i2c1_resources,
514 .num_resources = ARRAY_SIZE(i2c1_resources),
515};
516
517static struct platform_device *r8a7740_late_devices[] __initdata = {
518 &i2c0_device,
519 &i2c1_device,
643c3307
KM
520 &dma0_device,
521 &dma1_device,
522 &dma2_device,
6831f3a9
KM
523};
524
d49679e5
KM
525/*
526 * r8a7740 chip has lasting errata on MERAM buffer.
527 * this is work-around for it.
528 * see
529 * "Media RAM (MERAM)" on r8a7740 documentation
530 */
531#define MEBUFCNTR 0xFE950098
532void r8a7740_meram_workaround(void)
533{
534 void __iomem *reg;
535
536 reg = ioremap_nocache(MEBUFCNTR, 4);
537 if (reg) {
538 iowrite32(0x01600164, reg);
539 iounmap(reg);
540 }
541}
542
6831f3a9
KM
543#define ICCR 0x0004
544#define ICSTART 0x0070
545
546#define i2c_read(reg, offset) ioread8(reg + offset)
547#define i2c_write(reg, offset, data) iowrite8(data, reg + offset)
548
549/*
550 * r8a7740 chip has lasting errata on I2C I/O pad reset.
551 * this is work-around for it.
552 */
553static void r8a7740_i2c_workaround(struct platform_device *pdev)
554{
555 struct resource *res;
556 void __iomem *reg;
557
558 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
559 if (unlikely(!res)) {
560 pr_err("r8a7740 i2c workaround fail (cannot find resource)\n");
561 return;
562 }
563
564 reg = ioremap(res->start, resource_size(res));
565 if (unlikely(!reg)) {
566 pr_err("r8a7740 i2c workaround fail (cannot map IO)\n");
567 return;
568 }
569
570 i2c_write(reg, ICCR, i2c_read(reg, ICCR) | 0x80);
571 i2c_read(reg, ICCR); /* dummy read */
572
573 i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
574 i2c_read(reg, ICSTART); /* dummy read */
575
4228716c 576 udelay(10);
6831f3a9
KM
577
578 i2c_write(reg, ICCR, 0x01);
6831f3a9 579 i2c_write(reg, ICSTART, 0x00);
4228716c
KM
580
581 udelay(10);
6831f3a9
KM
582
583 i2c_write(reg, ICCR, 0x10);
4228716c 584 udelay(10);
6831f3a9 585 i2c_write(reg, ICCR, 0x00);
4228716c 586 udelay(10);
6831f3a9 587 i2c_write(reg, ICCR, 0x10);
4228716c 588 udelay(10);
6831f3a9
KM
589
590 iounmap(reg);
591}
592
6c01ba44
KM
593void __init r8a7740_add_standard_devices(void)
594{
6831f3a9
KM
595 /* I2C work-around */
596 r8a7740_i2c_workaround(&i2c0_device);
597 r8a7740_i2c_workaround(&i2c1_device);
598
6c01ba44
KM
599 platform_add_devices(r8a7740_early_devices,
600 ARRAY_SIZE(r8a7740_early_devices));
6831f3a9
KM
601 platform_add_devices(r8a7740_late_devices,
602 ARRAY_SIZE(r8a7740_late_devices));
6c01ba44
KM
603}
604
23e5bc03
MD
605static void __init r8a7740_earlytimer_init(void)
606{
607 r8a7740_clock_init(0);
608 shmobile_earlytimer_init();
609}
610
6c01ba44
KM
611void __init r8a7740_add_early_devices(void)
612{
613 early_platform_add_devices(r8a7740_early_devices,
614 ARRAY_SIZE(r8a7740_early_devices));
d3ab7221
MD
615
616 /* setup early console here as well */
617 shmobile_setup_console();
23e5bc03
MD
618
619 /* override timer setup with soc-specific code */
620 shmobile_timer.init = r8a7740_earlytimer_init;
6c01ba44 621}
This page took 0.07346 seconds and 5 git commands to generate.