ARM: shmobile: r8a7740: add DMAEngine support for USB
[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 {
cb76eb81
KM
309 .slave_id = SHDMA_SLAVE_SDHI0_TX,
310 .addr = 0xe6850030,
311 .chcr = CHCR_TX(XMIT_SZ_16BIT),
312 .mid_rid = 0xc1,
313 }, {
314 .slave_id = SHDMA_SLAVE_SDHI0_RX,
315 .addr = 0xe6850030,
316 .chcr = CHCR_RX(XMIT_SZ_16BIT),
317 .mid_rid = 0xc2,
318 }, {
319 .slave_id = SHDMA_SLAVE_SDHI1_TX,
320 .addr = 0xe6860030,
321 .chcr = CHCR_TX(XMIT_SZ_16BIT),
322 .mid_rid = 0xc9,
323 }, {
324 .slave_id = SHDMA_SLAVE_SDHI1_RX,
325 .addr = 0xe6860030,
326 .chcr = CHCR_RX(XMIT_SZ_16BIT),
327 .mid_rid = 0xca,
328 }, {
329 .slave_id = SHDMA_SLAVE_SDHI2_TX,
330 .addr = 0xe6870030,
331 .chcr = CHCR_TX(XMIT_SZ_16BIT),
332 .mid_rid = 0xcd,
333 }, {
334 .slave_id = SHDMA_SLAVE_SDHI2_RX,
335 .addr = 0xe6870030,
336 .chcr = CHCR_RX(XMIT_SZ_16BIT),
337 .mid_rid = 0xce,
338 }, {
643c3307
KM
339 .slave_id = SHDMA_SLAVE_FSIA_TX,
340 .addr = 0xfe1f0024,
341 .chcr = CHCR_TX(XMIT_SZ_32BIT),
342 .mid_rid = 0xb1,
343 }, {
344 .slave_id = SHDMA_SLAVE_FSIA_RX,
345 .addr = 0xfe1f0020,
346 .chcr = CHCR_RX(XMIT_SZ_32BIT),
347 .mid_rid = 0xb2,
348 }, {
349 .slave_id = SHDMA_SLAVE_FSIB_TX,
350 .addr = 0xfe1f0064,
351 .chcr = CHCR_TX(XMIT_SZ_32BIT),
352 .mid_rid = 0xb5,
353 },
354};
355
356#define DMA_CHANNEL(a, b, c) \
357{ \
358 .offset = a, \
359 .dmars = b, \
360 .dmars_bit = c, \
361 .chclr_offset = (0x220 - 0x20) + a \
362}
363
364static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
365 DMA_CHANNEL(0x00, 0, 0),
366 DMA_CHANNEL(0x10, 0, 8),
367 DMA_CHANNEL(0x20, 4, 0),
368 DMA_CHANNEL(0x30, 4, 8),
369 DMA_CHANNEL(0x50, 8, 0),
370 DMA_CHANNEL(0x60, 8, 8),
371};
372
373static const unsigned int ts_shift[] = TS_SHIFT;
374
375static struct sh_dmae_pdata dma_platform_data = {
376 .slave = r8a7740_dmae_slaves,
377 .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves),
378 .channel = r8a7740_dmae_channels,
379 .channel_num = ARRAY_SIZE(r8a7740_dmae_channels),
380 .ts_low_shift = 3,
381 .ts_low_mask = 0x18,
382 .ts_high_shift = (20 - 2),
383 .ts_high_mask = 0x00300000,
384 .ts_shift = ts_shift,
385 .ts_shift_num = ARRAY_SIZE(ts_shift),
386 .dmaor_init = DMAOR_DME,
387 .chclr_present = 1,
388};
389
390/* Resource order important! */
391static struct resource r8a7740_dmae0_resources[] = {
392 {
393 /* Channel registers and DMAOR */
394 .start = 0xfe008020,
395 .end = 0xfe00828f,
396 .flags = IORESOURCE_MEM,
397 },
398 {
399 /* DMARSx */
400 .start = 0xfe009000,
401 .end = 0xfe00900b,
402 .flags = IORESOURCE_MEM,
403 },
404 {
405 .name = "error_irq",
406 .start = evt2irq(0x20c0),
407 .end = evt2irq(0x20c0),
408 .flags = IORESOURCE_IRQ,
409 },
410 {
411 /* IRQ for channels 0-5 */
412 .start = evt2irq(0x2000),
413 .end = evt2irq(0x20a0),
414 .flags = IORESOURCE_IRQ,
415 },
416};
417
418/* Resource order important! */
419static struct resource r8a7740_dmae1_resources[] = {
420 {
421 /* Channel registers and DMAOR */
422 .start = 0xfe018020,
423 .end = 0xfe01828f,
424 .flags = IORESOURCE_MEM,
425 },
426 {
427 /* DMARSx */
428 .start = 0xfe019000,
429 .end = 0xfe01900b,
430 .flags = IORESOURCE_MEM,
431 },
432 {
433 .name = "error_irq",
434 .start = evt2irq(0x21c0),
435 .end = evt2irq(0x21c0),
436 .flags = IORESOURCE_IRQ,
437 },
438 {
439 /* IRQ for channels 0-5 */
440 .start = evt2irq(0x2100),
441 .end = evt2irq(0x21a0),
442 .flags = IORESOURCE_IRQ,
443 },
444};
445
446/* Resource order important! */
447static struct resource r8a7740_dmae2_resources[] = {
448 {
449 /* Channel registers and DMAOR */
450 .start = 0xfe028020,
451 .end = 0xfe02828f,
452 .flags = IORESOURCE_MEM,
453 },
454 {
455 /* DMARSx */
456 .start = 0xfe029000,
457 .end = 0xfe02900b,
458 .flags = IORESOURCE_MEM,
459 },
460 {
461 .name = "error_irq",
462 .start = evt2irq(0x22c0),
463 .end = evt2irq(0x22c0),
464 .flags = IORESOURCE_IRQ,
465 },
466 {
467 /* IRQ for channels 0-5 */
468 .start = evt2irq(0x2200),
469 .end = evt2irq(0x22a0),
470 .flags = IORESOURCE_IRQ,
471 },
472};
473
474static struct platform_device dma0_device = {
475 .name = "sh-dma-engine",
476 .id = 0,
477 .resource = r8a7740_dmae0_resources,
478 .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources),
479 .dev = {
480 .platform_data = &dma_platform_data,
481 },
482};
483
484static struct platform_device dma1_device = {
485 .name = "sh-dma-engine",
486 .id = 1,
487 .resource = r8a7740_dmae1_resources,
488 .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources),
489 .dev = {
490 .platform_data = &dma_platform_data,
491 },
492};
493
494static struct platform_device dma2_device = {
495 .name = "sh-dma-engine",
496 .id = 2,
497 .resource = r8a7740_dmae2_resources,
498 .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources),
499 .dev = {
500 .platform_data = &dma_platform_data,
501 },
502};
503
dbf382e5
KM
504/* USB-DMAC */
505/* Transmit sizes and respective CHCR register values */
506enum {
507 USBTS_XMIT_SZ_8BYTE = 0,
508 USBTS_XMIT_SZ_16BYTE = 1,
509 USBTS_XMIT_SZ_32BYTE = 2,
510};
511
512/* log2(size / 8) - used to calculate number of transfers */
513static const unsigned int dma_usbts_shift[] = {
514 [USBTS_XMIT_SZ_8BYTE] = 3,
515 [USBTS_XMIT_SZ_16BYTE] = 4,
516 [USBTS_XMIT_SZ_32BYTE] = 5,
517};
518
519static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
520 {
521 .offset = 0,
522 }, {
523 .offset = 0x20,
524 },
525};
526
527#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
528
529static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
530 {
531 .slave_id = SHDMA_SLAVE_USBHS_TX,
532 .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
533 }, {
534 .slave_id = SHDMA_SLAVE_USBHS_RX,
535 .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
536 },
537};
538
539static struct sh_dmae_pdata usb_dma_platform_data = {
540 .slave = r8a7740_usb_dma_slaves,
541 .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves),
542 .channel = r8a7740_usb_dma_channels,
543 .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels),
544 .ts_low_shift = 6,
545 .ts_low_mask = 0xc0,
546 .ts_high_shift = 0,
547 .ts_high_mask = 0,
548 .ts_shift = dma_usbts_shift,
549 .ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
550 .dmaor_init = DMAOR_DME,
551 .chcr_offset = 0x14,
552 .chcr_ie_bit = 1 << 5,
553 .dmaor_is_32bit = 1,
554 .needs_tend_set = 1,
555 .no_dmars = 1,
556 .slave_only = 1,
557};
558
559static struct resource r8a7740_usb_dma_resources[] = {
560 {
561 /* Channel registers and DMAOR */
562 .start = 0xe68a0020,
563 .end = 0xe68a0064 - 1,
564 .flags = IORESOURCE_MEM,
565 },
566 {
567 /* VCR/SWR/DMICR */
568 .start = 0xe68a0000,
569 .end = 0xe68a0014 - 1,
570 .flags = IORESOURCE_MEM,
571 },
572 {
573 /* IRQ for channels */
574 .start = evt2irq(0x0a00),
575 .end = evt2irq(0x0a00),
576 .flags = IORESOURCE_IRQ,
577 },
578};
579
580static struct platform_device usb_dma_device = {
581 .name = "sh-dma-engine",
582 .id = 3,
583 .resource = r8a7740_usb_dma_resources,
584 .num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources),
585 .dev = {
586 .platform_data = &usb_dma_platform_data,
587 },
588};
589
6831f3a9
KM
590/* I2C */
591static struct resource i2c0_resources[] = {
592 [0] = {
593 .name = "IIC0",
594 .start = 0xfff20000,
595 .end = 0xfff20425 - 1,
596 .flags = IORESOURCE_MEM,
597 },
598 [1] = {
215d6cc9
KM
599 .start = intcs_evt2irq(0xe00),
600 .end = intcs_evt2irq(0xe60),
6831f3a9
KM
601 .flags = IORESOURCE_IRQ,
602 },
603};
604
605static struct resource i2c1_resources[] = {
606 [0] = {
607 .name = "IIC1",
608 .start = 0xe6c20000,
609 .end = 0xe6c20425 - 1,
610 .flags = IORESOURCE_MEM,
611 },
612 [1] = {
215d6cc9
KM
613 .start = evt2irq(0x780), /* IIC1_ALI1 */
614 .end = evt2irq(0x7e0), /* IIC1_DTEI1 */
6831f3a9
KM
615 .flags = IORESOURCE_IRQ,
616 },
617};
618
619static struct platform_device i2c0_device = {
620 .name = "i2c-sh_mobile",
621 .id = 0,
622 .resource = i2c0_resources,
623 .num_resources = ARRAY_SIZE(i2c0_resources),
624};
625
626static struct platform_device i2c1_device = {
627 .name = "i2c-sh_mobile",
628 .id = 1,
629 .resource = i2c1_resources,
630 .num_resources = ARRAY_SIZE(i2c1_resources),
631};
632
633static struct platform_device *r8a7740_late_devices[] __initdata = {
634 &i2c0_device,
635 &i2c1_device,
643c3307
KM
636 &dma0_device,
637 &dma1_device,
638 &dma2_device,
dbf382e5 639 &usb_dma_device,
6831f3a9
KM
640};
641
d49679e5
KM
642/*
643 * r8a7740 chip has lasting errata on MERAM buffer.
644 * this is work-around for it.
645 * see
646 * "Media RAM (MERAM)" on r8a7740 documentation
647 */
648#define MEBUFCNTR 0xFE950098
649void r8a7740_meram_workaround(void)
650{
651 void __iomem *reg;
652
653 reg = ioremap_nocache(MEBUFCNTR, 4);
654 if (reg) {
655 iowrite32(0x01600164, reg);
656 iounmap(reg);
657 }
658}
659
6831f3a9
KM
660#define ICCR 0x0004
661#define ICSTART 0x0070
662
663#define i2c_read(reg, offset) ioread8(reg + offset)
664#define i2c_write(reg, offset, data) iowrite8(data, reg + offset)
665
666/*
667 * r8a7740 chip has lasting errata on I2C I/O pad reset.
668 * this is work-around for it.
669 */
670static void r8a7740_i2c_workaround(struct platform_device *pdev)
671{
672 struct resource *res;
673 void __iomem *reg;
674
675 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
676 if (unlikely(!res)) {
677 pr_err("r8a7740 i2c workaround fail (cannot find resource)\n");
678 return;
679 }
680
681 reg = ioremap(res->start, resource_size(res));
682 if (unlikely(!reg)) {
683 pr_err("r8a7740 i2c workaround fail (cannot map IO)\n");
684 return;
685 }
686
687 i2c_write(reg, ICCR, i2c_read(reg, ICCR) | 0x80);
688 i2c_read(reg, ICCR); /* dummy read */
689
690 i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
691 i2c_read(reg, ICSTART); /* dummy read */
692
4228716c 693 udelay(10);
6831f3a9
KM
694
695 i2c_write(reg, ICCR, 0x01);
6831f3a9 696 i2c_write(reg, ICSTART, 0x00);
4228716c
KM
697
698 udelay(10);
6831f3a9
KM
699
700 i2c_write(reg, ICCR, 0x10);
4228716c 701 udelay(10);
6831f3a9 702 i2c_write(reg, ICCR, 0x00);
4228716c 703 udelay(10);
6831f3a9 704 i2c_write(reg, ICCR, 0x10);
4228716c 705 udelay(10);
6831f3a9
KM
706
707 iounmap(reg);
708}
709
6c01ba44
KM
710void __init r8a7740_add_standard_devices(void)
711{
6831f3a9
KM
712 /* I2C work-around */
713 r8a7740_i2c_workaround(&i2c0_device);
714 r8a7740_i2c_workaround(&i2c1_device);
715
6c01ba44
KM
716 platform_add_devices(r8a7740_early_devices,
717 ARRAY_SIZE(r8a7740_early_devices));
6831f3a9
KM
718 platform_add_devices(r8a7740_late_devices,
719 ARRAY_SIZE(r8a7740_late_devices));
6c01ba44
KM
720}
721
23e5bc03
MD
722static void __init r8a7740_earlytimer_init(void)
723{
724 r8a7740_clock_init(0);
725 shmobile_earlytimer_init();
726}
727
6c01ba44
KM
728void __init r8a7740_add_early_devices(void)
729{
730 early_platform_add_devices(r8a7740_early_devices,
731 ARRAY_SIZE(r8a7740_early_devices));
d3ab7221
MD
732
733 /* setup early console here as well */
734 shmobile_setup_console();
23e5bc03
MD
735
736 /* override timer setup with soc-specific code */
737 shmobile_timer.init = r8a7740_earlytimer_init;
6c01ba44 738}
This page took 0.089968 seconds and 5 git commands to generate.