diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-10 18:17:52 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-10 18:17:52 -0400 |
commit | 0b019a41553a919965bb02d07d54e3e6c57a796d (patch) | |
tree | 6e329b4159b440d2aac5200a5c07103fe261c096 /arch/arm/mach-shmobile/board-ap4evb.c | |
parent | 5f6878b0d22f9b93f9698f88c335007e2a3c3bbc (diff) | |
parent | 054d5c9238f3c577ad51195c3ee7803613f322cc (diff) |
Merge branches 'master' and 'devel' into for-linus
Conflicts:
arch/arm/Kconfig
arch/arm/mm/Kconfig
Diffstat (limited to 'arch/arm/mach-shmobile/board-ap4evb.c')
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 817 |
1 files changed, 786 insertions, 31 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 1c2ec96ce261..23d472f9525e 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -17,25 +17,45 @@ | |||
17 | * along with this program; if not, write to the Free Software | 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 | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ | 19 | */ |
20 | #include <linux/clk.h> | ||
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/mfd/sh_mobile_sdhi.h> | ||
28 | #include <linux/mmc/host.h> | ||
26 | #include <linux/mtd/mtd.h> | 29 | #include <linux/mtd/mtd.h> |
27 | #include <linux/mtd/partitions.h> | 30 | #include <linux/mtd/partitions.h> |
28 | #include <linux/mtd/physmap.h> | 31 | #include <linux/mtd/physmap.h> |
32 | #include <linux/mmc/host.h> | ||
33 | #include <linux/mmc/sh_mmcif.h> | ||
34 | #include <linux/i2c.h> | ||
35 | #include <linux/i2c/tsc2007.h> | ||
29 | #include <linux/io.h> | 36 | #include <linux/io.h> |
30 | #include <linux/smsc911x.h> | 37 | #include <linux/smsc911x.h> |
38 | #include <linux/sh_intc.h> | ||
39 | #include <linux/sh_clk.h> | ||
31 | #include <linux/gpio.h> | 40 | #include <linux/gpio.h> |
32 | #include <linux/input.h> | 41 | #include <linux/input.h> |
33 | #include <linux/input/sh_keysc.h> | 42 | #include <linux/input/sh_keysc.h> |
43 | #include <linux/usb/r8a66597.h> | ||
44 | |||
45 | #include <sound/sh_fsi.h> | ||
46 | |||
47 | #include <video/sh_mobile_hdmi.h> | ||
48 | #include <video/sh_mobile_lcdc.h> | ||
49 | #include <video/sh_mipi_dsi.h> | ||
50 | |||
34 | #include <mach/common.h> | 51 | #include <mach/common.h> |
52 | #include <mach/irqs.h> | ||
35 | #include <mach/sh7372.h> | 53 | #include <mach/sh7372.h> |
54 | |||
36 | #include <asm/mach-types.h> | 55 | #include <asm/mach-types.h> |
37 | #include <asm/mach/arch.h> | 56 | #include <asm/mach/arch.h> |
38 | #include <asm/mach/map.h> | 57 | #include <asm/mach/map.h> |
58 | #include <asm/mach/time.h> | ||
39 | 59 | ||
40 | /* | 60 | /* |
41 | * Address Interface BusWidth note | 61 | * Address Interface BusWidth note |
@@ -80,12 +100,56 @@ | |||
80 | */ | 100 | */ |
81 | 101 | ||
82 | /* | 102 | /* |
83 | * KEYSC | 103 | * LCD / IRQ / KEYSC / IrDA |
104 | * | ||
105 | * IRQ = IRQ26 (TS), IRQ27 (VIO), IRQ28 (QHD-TouchScreen) | ||
106 | * LCD = 2nd LCDC (WVGA) | ||
84 | * | 107 | * |
85 | * SW43 KEYSC | 108 | * | SW43 | |
86 | * ------------------------- | 109 | * SW3 | ON | OFF | |
87 | * ON enable | 110 | * -------------+-----------------------+---------------+ |
88 | * OFF disable | 111 | * ON | KEY / IrDA | LCD | |
112 | * OFF | KEY / IrDA / IRQ | IRQ | | ||
113 | * | ||
114 | * | ||
115 | * QHD / WVGA display | ||
116 | * | ||
117 | * You can choice display type on menuconfig. | ||
118 | * Then, check above dip-switch. | ||
119 | */ | ||
120 | |||
121 | /* | ||
122 | * USB | ||
123 | * | ||
124 | * J7 : 1-2 MAX3355E VBUS | ||
125 | * 2-3 DC 5.0V | ||
126 | * | ||
127 | * S39: bit2: off | ||
128 | */ | ||
129 | |||
130 | /* | ||
131 | * FSI/FSMI | ||
132 | * | ||
133 | * SW41 : ON : SH-Mobile AP4 Audio Mode | ||
134 | * : OFF : Bluetooth Audio Mode | ||
135 | */ | ||
136 | |||
137 | /* | ||
138 | * MMC0/SDHI1 (CN7) | ||
139 | * | ||
140 | * J22 : select card voltage | ||
141 | * 1-2 pin : 1.8v | ||
142 | * 2-3 pin : 3.3v | ||
143 | * | ||
144 | * SW1 | SW33 | ||
145 | * | bit1 | bit2 | bit3 | bit4 | ||
146 | * ------------+------+------+------+------- | ||
147 | * MMC0 OFF | OFF | ON | ON | X | ||
148 | * SDHI1 OFF | ON | X | OFF | ON | ||
149 | * | ||
150 | * voltage lebel | ||
151 | * CN7 : 1.8v | ||
152 | * CN12: 3.3v | ||
89 | */ | 153 | */ |
90 | 154 | ||
91 | /* MTD */ | 155 | /* MTD */ |
@@ -148,7 +212,7 @@ static struct resource smc911x_resources[] = { | |||
148 | .end = 0x16000000 - 1, | 212 | .end = 0x16000000 - 1, |
149 | .flags = IORESOURCE_MEM, | 213 | .flags = IORESOURCE_MEM, |
150 | }, { | 214 | }, { |
151 | .start = 6, | 215 | .start = evt2irq(0x02c0) /* IRQ6A */, |
152 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, | 216 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, |
153 | }, | 217 | }, |
154 | }; | 218 | }; |
@@ -169,6 +233,180 @@ static struct platform_device smc911x_device = { | |||
169 | }, | 233 | }, |
170 | }; | 234 | }; |
171 | 235 | ||
236 | /* SH_MMCIF */ | ||
237 | static struct resource sh_mmcif_resources[] = { | ||
238 | [0] = { | ||
239 | .name = "SH_MMCIF", | ||
240 | .start = 0xE6BD0000, | ||
241 | .end = 0xE6BD00FF, | ||
242 | .flags = IORESOURCE_MEM, | ||
243 | }, | ||
244 | [1] = { | ||
245 | /* MMC ERR */ | ||
246 | .start = evt2irq(0x1ac0), | ||
247 | .flags = IORESOURCE_IRQ, | ||
248 | }, | ||
249 | [2] = { | ||
250 | /* MMC NOR */ | ||
251 | .start = evt2irq(0x1ae0), | ||
252 | .flags = IORESOURCE_IRQ, | ||
253 | }, | ||
254 | }; | ||
255 | |||
256 | static struct sh_mmcif_plat_data sh_mmcif_plat = { | ||
257 | .sup_pclk = 0, | ||
258 | .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, | ||
259 | .caps = MMC_CAP_4_BIT_DATA | | ||
260 | MMC_CAP_8_BIT_DATA | | ||
261 | MMC_CAP_NEEDS_POLL, | ||
262 | }; | ||
263 | |||
264 | static struct platform_device sh_mmcif_device = { | ||
265 | .name = "sh_mmcif", | ||
266 | .id = 0, | ||
267 | .dev = { | ||
268 | .dma_mask = NULL, | ||
269 | .coherent_dma_mask = 0xffffffff, | ||
270 | .platform_data = &sh_mmcif_plat, | ||
271 | }, | ||
272 | .num_resources = ARRAY_SIZE(sh_mmcif_resources), | ||
273 | .resource = sh_mmcif_resources, | ||
274 | }; | ||
275 | |||
276 | /* SDHI0 */ | ||
277 | static struct sh_mobile_sdhi_info sdhi0_info = { | ||
278 | .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, | ||
279 | .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, | ||
280 | }; | ||
281 | |||
282 | static struct resource sdhi0_resources[] = { | ||
283 | [0] = { | ||
284 | .name = "SDHI0", | ||
285 | .start = 0xe6850000, | ||
286 | .end = 0xe68501ff, | ||
287 | .flags = IORESOURCE_MEM, | ||
288 | }, | ||
289 | [1] = { | ||
290 | .start = evt2irq(0x0e00) /* SDHI0 */, | ||
291 | .flags = IORESOURCE_IRQ, | ||
292 | }, | ||
293 | }; | ||
294 | |||
295 | static struct platform_device sdhi0_device = { | ||
296 | .name = "sh_mobile_sdhi", | ||
297 | .num_resources = ARRAY_SIZE(sdhi0_resources), | ||
298 | .resource = sdhi0_resources, | ||
299 | .id = 0, | ||
300 | .dev = { | ||
301 | .platform_data = &sdhi0_info, | ||
302 | }, | ||
303 | }; | ||
304 | |||
305 | /* SDHI1 */ | ||
306 | static struct sh_mobile_sdhi_info sdhi1_info = { | ||
307 | .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, | ||
308 | .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, | ||
309 | .tmio_ocr_mask = MMC_VDD_165_195, | ||
310 | }; | ||
311 | |||
312 | static struct resource sdhi1_resources[] = { | ||
313 | [0] = { | ||
314 | .name = "SDHI1", | ||
315 | .start = 0xe6860000, | ||
316 | .end = 0xe68601ff, | ||
317 | .flags = IORESOURCE_MEM, | ||
318 | }, | ||
319 | [1] = { | ||
320 | .start = evt2irq(0x0e80), | ||
321 | .flags = IORESOURCE_IRQ, | ||
322 | }, | ||
323 | }; | ||
324 | |||
325 | static struct platform_device sdhi1_device = { | ||
326 | .name = "sh_mobile_sdhi", | ||
327 | .num_resources = ARRAY_SIZE(sdhi1_resources), | ||
328 | .resource = sdhi1_resources, | ||
329 | .id = 1, | ||
330 | .dev = { | ||
331 | .platform_data = &sdhi1_info, | ||
332 | }, | ||
333 | }; | ||
334 | |||
335 | /* USB1 */ | ||
336 | static void usb1_host_port_power(int port, int power) | ||
337 | { | ||
338 | if (!power) /* only power-on supported for now */ | ||
339 | return; | ||
340 | |||
341 | /* set VBOUT/PWEN and EXTLP1 in DVSTCTR */ | ||
342 | __raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008); | ||
343 | } | ||
344 | |||
345 | static struct r8a66597_platdata usb1_host_data = { | ||
346 | .on_chip = 1, | ||
347 | .port_power = usb1_host_port_power, | ||
348 | }; | ||
349 | |||
350 | static struct resource usb1_host_resources[] = { | ||
351 | [0] = { | ||
352 | .name = "USBHS", | ||
353 | .start = 0xE68B0000, | ||
354 | .end = 0xE68B00E6 - 1, | ||
355 | .flags = IORESOURCE_MEM, | ||
356 | }, | ||
357 | [1] = { | ||
358 | .start = evt2irq(0x1ce0) /* USB1_USB1I0 */, | ||
359 | .flags = IORESOURCE_IRQ, | ||
360 | }, | ||
361 | }; | ||
362 | |||
363 | static struct platform_device usb1_host_device = { | ||
364 | .name = "r8a66597_hcd", | ||
365 | .id = 1, | ||
366 | .dev = { | ||
367 | .dma_mask = NULL, /* not use dma */ | ||
368 | .coherent_dma_mask = 0xffffffff, | ||
369 | .platform_data = &usb1_host_data, | ||
370 | }, | ||
371 | .num_resources = ARRAY_SIZE(usb1_host_resources), | ||
372 | .resource = usb1_host_resources, | ||
373 | }; | ||
374 | |||
375 | static struct sh_mobile_lcdc_info lcdc_info = { | ||
376 | .ch[0] = { | ||
377 | .chan = LCDC_CHAN_MAINLCD, | ||
378 | .bpp = 16, | ||
379 | } | ||
380 | }; | ||
381 | |||
382 | static struct resource lcdc_resources[] = { | ||
383 | [0] = { | ||
384 | .name = "LCDC", | ||
385 | .start = 0xfe940000, /* P4-only space */ | ||
386 | .end = 0xfe943fff, | ||
387 | .flags = IORESOURCE_MEM, | ||
388 | }, | ||
389 | [1] = { | ||
390 | .start = intcs_evt2irq(0x580), | ||
391 | .flags = IORESOURCE_IRQ, | ||
392 | }, | ||
393 | }; | ||
394 | |||
395 | static struct platform_device lcdc_device = { | ||
396 | .name = "sh_mobile_lcdc_fb", | ||
397 | .num_resources = ARRAY_SIZE(lcdc_resources), | ||
398 | .resource = lcdc_resources, | ||
399 | .dev = { | ||
400 | .platform_data = &lcdc_info, | ||
401 | .coherent_dma_mask = ~0, | ||
402 | }, | ||
403 | }; | ||
404 | |||
405 | /* | ||
406 | * QHD display | ||
407 | */ | ||
408 | #ifdef CONFIG_AP4EVB_QHD | ||
409 | |||
172 | /* KEYSC (Needs SW43 set to ON) */ | 410 | /* KEYSC (Needs SW43 set to ON) */ |
173 | static struct sh_keysc_info keysc_info = { | 411 | static struct sh_keysc_info keysc_info = { |
174 | .mode = SH_KEYSC_MODE_1, | 412 | .mode = SH_KEYSC_MODE_1, |
@@ -191,7 +429,7 @@ static struct resource keysc_resources[] = { | |||
191 | .flags = IORESOURCE_MEM, | 429 | .flags = IORESOURCE_MEM, |
192 | }, | 430 | }, |
193 | [1] = { | 431 | [1] = { |
194 | .start = 79, | 432 | .start = evt2irq(0x0be0), /* KEYSC_KEY */ |
195 | .flags = IORESOURCE_IRQ, | 433 | .flags = IORESOURCE_IRQ, |
196 | }, | 434 | }, |
197 | }; | 435 | }; |
@@ -206,32 +444,362 @@ static struct platform_device keysc_device = { | |||
206 | }, | 444 | }, |
207 | }; | 445 | }; |
208 | 446 | ||
209 | /* SDHI0 */ | 447 | /* MIPI-DSI */ |
210 | static struct resource sdhi0_resources[] = { | 448 | static struct resource mipidsi0_resources[] = { |
211 | [0] = { | 449 | [0] = { |
212 | .name = "SDHI0", | 450 | .start = 0xffc60000, |
213 | .start = 0xe6850000, | 451 | .end = 0xffc68fff, |
214 | .end = 0xe68501ff, | ||
215 | .flags = IORESOURCE_MEM, | 452 | .flags = IORESOURCE_MEM, |
216 | }, | 453 | }, |
454 | }; | ||
455 | |||
456 | static struct sh_mipi_dsi_info mipidsi0_info = { | ||
457 | .data_format = MIPI_RGB888, | ||
458 | .lcd_chan = &lcdc_info.ch[0], | ||
459 | }; | ||
460 | |||
461 | static struct platform_device mipidsi0_device = { | ||
462 | .name = "sh-mipi-dsi", | ||
463 | .num_resources = ARRAY_SIZE(mipidsi0_resources), | ||
464 | .resource = mipidsi0_resources, | ||
465 | .id = 0, | ||
466 | .dev = { | ||
467 | .platform_data = &mipidsi0_info, | ||
468 | }, | ||
469 | }; | ||
470 | |||
471 | /* This function will disappear when we switch to (runtime) PM */ | ||
472 | static int __init ap4evb_init_display_clk(void) | ||
473 | { | ||
474 | struct clk *lcdc_clk; | ||
475 | struct clk *dsitx_clk; | ||
476 | int ret; | ||
477 | |||
478 | lcdc_clk = clk_get(&lcdc_device.dev, "sh_mobile_lcdc_fb.0"); | ||
479 | if (IS_ERR(lcdc_clk)) | ||
480 | return PTR_ERR(lcdc_clk); | ||
481 | |||
482 | dsitx_clk = clk_get(&mipidsi0_device.dev, "sh-mipi-dsi.0"); | ||
483 | if (IS_ERR(dsitx_clk)) { | ||
484 | ret = PTR_ERR(dsitx_clk); | ||
485 | goto eclkdsitxget; | ||
486 | } | ||
487 | |||
488 | ret = clk_enable(lcdc_clk); | ||
489 | if (ret < 0) | ||
490 | goto eclklcdcon; | ||
491 | |||
492 | ret = clk_enable(dsitx_clk); | ||
493 | if (ret < 0) | ||
494 | goto eclkdsitxon; | ||
495 | |||
496 | return 0; | ||
497 | |||
498 | eclkdsitxon: | ||
499 | clk_disable(lcdc_clk); | ||
500 | eclklcdcon: | ||
501 | clk_put(dsitx_clk); | ||
502 | eclkdsitxget: | ||
503 | clk_put(lcdc_clk); | ||
504 | |||
505 | return ret; | ||
506 | } | ||
507 | device_initcall(ap4evb_init_display_clk); | ||
508 | |||
509 | static struct platform_device *qhd_devices[] __initdata = { | ||
510 | &mipidsi0_device, | ||
511 | &keysc_device, | ||
512 | }; | ||
513 | #endif /* CONFIG_AP4EVB_QHD */ | ||
514 | |||
515 | /* FSI */ | ||
516 | #define IRQ_FSI evt2irq(0x1840) | ||
517 | #define FSIACKCR 0xE6150018 | ||
518 | static void fsiackcr_init(struct clk *clk) | ||
519 | { | ||
520 | u32 status = __raw_readl(clk->enable_reg); | ||
521 | |||
522 | /* use external clock */ | ||
523 | status &= ~0x000000ff; | ||
524 | status |= 0x00000080; | ||
525 | __raw_writel(status, clk->enable_reg); | ||
526 | } | ||
527 | |||
528 | static struct clk_ops fsiackcr_clk_ops = { | ||
529 | .init = fsiackcr_init, | ||
530 | }; | ||
531 | |||
532 | static struct clk fsiackcr_clk = { | ||
533 | .ops = &fsiackcr_clk_ops, | ||
534 | .enable_reg = (void __iomem *)FSIACKCR, | ||
535 | .rate = 0, /* unknown */ | ||
536 | }; | ||
537 | |||
538 | static struct sh_fsi_platform_info fsi_info = { | ||
539 | .porta_flags = SH_FSI_BRS_INV | | ||
540 | SH_FSI_OUT_SLAVE_MODE | | ||
541 | SH_FSI_IN_SLAVE_MODE | | ||
542 | SH_FSI_OFMT(PCM) | | ||
543 | SH_FSI_IFMT(PCM), | ||
544 | }; | ||
545 | |||
546 | static struct resource fsi_resources[] = { | ||
547 | [0] = { | ||
548 | .name = "FSI", | ||
549 | .start = 0xFE3C0000, | ||
550 | .end = 0xFE3C0400 - 1, | ||
551 | .flags = IORESOURCE_MEM, | ||
552 | }, | ||
217 | [1] = { | 553 | [1] = { |
218 | .start = 96, | 554 | .start = IRQ_FSI, |
219 | .flags = IORESOURCE_IRQ, | 555 | .flags = IORESOURCE_IRQ, |
220 | }, | 556 | }, |
221 | }; | 557 | }; |
222 | 558 | ||
223 | static struct platform_device sdhi0_device = { | 559 | static struct platform_device fsi_device = { |
224 | .name = "sh_mobile_sdhi", | 560 | .name = "sh_fsi2", |
225 | .num_resources = ARRAY_SIZE(sdhi0_resources), | 561 | .id = 0, |
226 | .resource = sdhi0_resources, | 562 | .num_resources = ARRAY_SIZE(fsi_resources), |
227 | .id = 0, | 563 | .resource = fsi_resources, |
564 | .dev = { | ||
565 | .platform_data = &fsi_info, | ||
566 | }, | ||
567 | }; | ||
568 | |||
569 | static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = { | ||
570 | .clock_source = LCDC_CLK_EXTERNAL, | ||
571 | .ch[0] = { | ||
572 | .chan = LCDC_CHAN_MAINLCD, | ||
573 | .bpp = 16, | ||
574 | .interface_type = RGB24, | ||
575 | .clock_divider = 1, | ||
576 | .flags = LCDC_FLAGS_DWPOL, | ||
577 | .lcd_cfg = { | ||
578 | .name = "HDMI", | ||
579 | /* So far only 720p is supported */ | ||
580 | .xres = 1280, | ||
581 | .yres = 720, | ||
582 | /* | ||
583 | * If left and right margins are not multiples of 8, | ||
584 | * LDHAJR will be adjusted accordingly by the LCDC | ||
585 | * driver. Until we start using EDID, these values | ||
586 | * might have to be adjusted for different monitors. | ||
587 | */ | ||
588 | .left_margin = 200, | ||
589 | .right_margin = 88, | ||
590 | .hsync_len = 48, | ||
591 | .upper_margin = 20, | ||
592 | .lower_margin = 5, | ||
593 | .vsync_len = 5, | ||
594 | .pixclock = 13468, | ||
595 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
596 | }, | ||
597 | } | ||
598 | }; | ||
599 | |||
600 | static struct resource lcdc1_resources[] = { | ||
601 | [0] = { | ||
602 | .name = "LCDC1", | ||
603 | .start = 0xfe944000, | ||
604 | .end = 0xfe947fff, | ||
605 | .flags = IORESOURCE_MEM, | ||
606 | }, | ||
607 | [1] = { | ||
608 | .start = intcs_evt2irq(0x17a0), | ||
609 | .flags = IORESOURCE_IRQ, | ||
610 | }, | ||
611 | }; | ||
612 | |||
613 | static struct platform_device lcdc1_device = { | ||
614 | .name = "sh_mobile_lcdc_fb", | ||
615 | .num_resources = ARRAY_SIZE(lcdc1_resources), | ||
616 | .resource = lcdc1_resources, | ||
617 | .id = 1, | ||
618 | .dev = { | ||
619 | .platform_data = &sh_mobile_lcdc1_info, | ||
620 | .coherent_dma_mask = ~0, | ||
621 | }, | ||
622 | }; | ||
623 | |||
624 | static struct sh_mobile_hdmi_info hdmi_info = { | ||
625 | .lcd_chan = &sh_mobile_lcdc1_info.ch[0], | ||
626 | .lcd_dev = &lcdc1_device.dev, | ||
627 | }; | ||
628 | |||
629 | static struct resource hdmi_resources[] = { | ||
630 | [0] = { | ||
631 | .name = "HDMI", | ||
632 | .start = 0xe6be0000, | ||
633 | .end = 0xe6be00ff, | ||
634 | .flags = IORESOURCE_MEM, | ||
635 | }, | ||
636 | [1] = { | ||
637 | /* There's also an HDMI interrupt on INTCS @ 0x18e0 */ | ||
638 | .start = evt2irq(0x17e0), | ||
639 | .flags = IORESOURCE_IRQ, | ||
640 | }, | ||
641 | }; | ||
642 | |||
643 | static struct platform_device hdmi_device = { | ||
644 | .name = "sh-mobile-hdmi", | ||
645 | .num_resources = ARRAY_SIZE(hdmi_resources), | ||
646 | .resource = hdmi_resources, | ||
647 | .id = -1, | ||
648 | .dev = { | ||
649 | .platform_data = &hdmi_info, | ||
650 | }, | ||
228 | }; | 651 | }; |
229 | 652 | ||
230 | static struct platform_device *ap4evb_devices[] __initdata = { | 653 | static struct platform_device *ap4evb_devices[] __initdata = { |
231 | &nor_flash_device, | 654 | &nor_flash_device, |
232 | &smc911x_device, | 655 | &smc911x_device, |
233 | &keysc_device, | ||
234 | &sdhi0_device, | 656 | &sdhi0_device, |
657 | &sdhi1_device, | ||
658 | &usb1_host_device, | ||
659 | &fsi_device, | ||
660 | &sh_mmcif_device, | ||
661 | &lcdc1_device, | ||
662 | &lcdc_device, | ||
663 | &hdmi_device, | ||
664 | }; | ||
665 | |||
666 | static int __init hdmi_init_pm_clock(void) | ||
667 | { | ||
668 | struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick"); | ||
669 | int ret; | ||
670 | long rate; | ||
671 | |||
672 | if (IS_ERR(hdmi_ick)) { | ||
673 | ret = PTR_ERR(hdmi_ick); | ||
674 | pr_err("Cannot get HDMI ICK: %d\n", ret); | ||
675 | goto out; | ||
676 | } | ||
677 | |||
678 | ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk); | ||
679 | if (ret < 0) { | ||
680 | pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount); | ||
681 | goto out; | ||
682 | } | ||
683 | |||
684 | pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk)); | ||
685 | |||
686 | rate = clk_round_rate(&pllc2_clk, 594000000); | ||
687 | if (rate < 0) { | ||
688 | pr_err("Cannot get suitable rate: %ld\n", rate); | ||
689 | ret = rate; | ||
690 | goto out; | ||
691 | } | ||
692 | |||
693 | ret = clk_set_rate(&pllc2_clk, rate); | ||
694 | if (ret < 0) { | ||
695 | pr_err("Cannot set rate %ld: %d\n", rate, ret); | ||
696 | goto out; | ||
697 | } | ||
698 | |||
699 | pr_debug("PLLC2 set frequency %lu\n", rate); | ||
700 | |||
701 | ret = clk_set_parent(hdmi_ick, &pllc2_clk); | ||
702 | if (ret < 0) { | ||
703 | pr_err("Cannot set HDMI parent: %d\n", ret); | ||
704 | goto out; | ||
705 | } | ||
706 | |||
707 | out: | ||
708 | if (!IS_ERR(hdmi_ick)) | ||
709 | clk_put(hdmi_ick); | ||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | device_initcall(hdmi_init_pm_clock); | ||
714 | |||
715 | /* | ||
716 | * FIXME !! | ||
717 | * | ||
718 | * gpio_no_direction | ||
719 | * gpio_pull_up | ||
720 | * are quick_hack. | ||
721 | * | ||
722 | * current gpio frame work doesn't have | ||
723 | * the method to control only pull up/down/free. | ||
724 | * this function should be replaced by correct gpio function | ||
725 | */ | ||
726 | static void __init gpio_no_direction(u32 addr) | ||
727 | { | ||
728 | __raw_writeb(0x00, addr); | ||
729 | } | ||
730 | |||
731 | static void __init gpio_pull_up(u32 addr) | ||
732 | { | ||
733 | u8 data = __raw_readb(addr); | ||
734 | |||
735 | data &= 0x0F; | ||
736 | data |= 0xC0; | ||
737 | __raw_writeb(data, addr); | ||
738 | } | ||
739 | |||
740 | /* TouchScreen */ | ||
741 | #define IRQ28 evt2irq(0x3380) /* IRQ28A */ | ||
742 | #define IRQ7 evt2irq(0x02e0) /* IRQ7A */ | ||
743 | static int ts_get_pendown_state(void) | ||
744 | { | ||
745 | int val1, val2; | ||
746 | |||
747 | gpio_free(GPIO_FN_IRQ28_123); | ||
748 | gpio_free(GPIO_FN_IRQ7_40); | ||
749 | |||
750 | gpio_request(GPIO_PORT123, NULL); | ||
751 | gpio_request(GPIO_PORT40, NULL); | ||
752 | |||
753 | gpio_direction_input(GPIO_PORT123); | ||
754 | gpio_direction_input(GPIO_PORT40); | ||
755 | |||
756 | val1 = gpio_get_value(GPIO_PORT123); | ||
757 | val2 = gpio_get_value(GPIO_PORT40); | ||
758 | |||
759 | gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ | ||
760 | gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */ | ||
761 | |||
762 | return val1 ^ val2; | ||
763 | } | ||
764 | |||
765 | #define PORT40CR 0xE6051028 | ||
766 | #define PORT123CR 0xE605007B | ||
767 | static int ts_init(void) | ||
768 | { | ||
769 | gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ | ||
770 | gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */ | ||
771 | |||
772 | gpio_pull_up(PORT40CR); | ||
773 | gpio_pull_up(PORT123CR); | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static struct tsc2007_platform_data tsc2007_info = { | ||
779 | .model = 2007, | ||
780 | .x_plate_ohms = 180, | ||
781 | .get_pendown_state = ts_get_pendown_state, | ||
782 | .init_platform_hw = ts_init, | ||
783 | }; | ||
784 | |||
785 | static struct i2c_board_info tsc_device = { | ||
786 | I2C_BOARD_INFO("tsc2007", 0x48), | ||
787 | .type = "tsc2007", | ||
788 | .platform_data = &tsc2007_info, | ||
789 | /*.irq is selected on ap4evb_init */ | ||
790 | }; | ||
791 | |||
792 | /* I2C */ | ||
793 | static struct i2c_board_info i2c0_devices[] = { | ||
794 | { | ||
795 | I2C_BOARD_INFO("ak4643", 0x13), | ||
796 | }, | ||
797 | }; | ||
798 | |||
799 | static struct i2c_board_info i2c1_devices[] = { | ||
800 | { | ||
801 | I2C_BOARD_INFO("r2025sd", 0x32), | ||
802 | }, | ||
235 | }; | 803 | }; |
236 | 804 | ||
237 | static struct map_desc ap4evb_io_desc[] __initdata = { | 805 | static struct map_desc ap4evb_io_desc[] __initdata = { |
@@ -250,14 +818,18 @@ static void __init ap4evb_map_io(void) | |||
250 | { | 818 | { |
251 | iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); | 819 | iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); |
252 | 820 | ||
253 | /* setup early devices, clocks and console here as well */ | 821 | /* setup early devices and console here as well */ |
254 | sh7372_add_early_devices(); | 822 | sh7372_add_early_devices(); |
255 | sh7367_clock_init(); /* use g3 clocks for now */ | ||
256 | shmobile_setup_console(); | 823 | shmobile_setup_console(); |
257 | } | 824 | } |
258 | 825 | ||
826 | #define GPIO_PORT9CR 0xE6051009 | ||
827 | #define GPIO_PORT10CR 0xE605100A | ||
259 | static void __init ap4evb_init(void) | 828 | static void __init ap4evb_init(void) |
260 | { | 829 | { |
830 | u32 srcr4; | ||
831 | struct clk *clk; | ||
832 | |||
261 | sh7372_pinmux_init(); | 833 | sh7372_pinmux_init(); |
262 | 834 | ||
263 | /* enable SCIFA0 */ | 835 | /* enable SCIFA0 */ |
@@ -296,6 +868,93 @@ static void __init ap4evb_init(void) | |||
296 | gpio_export(GPIO_PORT34, 0); | 868 | gpio_export(GPIO_PORT34, 0); |
297 | gpio_export(GPIO_PORT35, 0); | 869 | gpio_export(GPIO_PORT35, 0); |
298 | 870 | ||
871 | /* SDHI0 */ | ||
872 | gpio_request(GPIO_FN_SDHICD0, NULL); | ||
873 | gpio_request(GPIO_FN_SDHIWP0, NULL); | ||
874 | gpio_request(GPIO_FN_SDHICMD0, NULL); | ||
875 | gpio_request(GPIO_FN_SDHICLK0, NULL); | ||
876 | gpio_request(GPIO_FN_SDHID0_3, NULL); | ||
877 | gpio_request(GPIO_FN_SDHID0_2, NULL); | ||
878 | gpio_request(GPIO_FN_SDHID0_1, NULL); | ||
879 | gpio_request(GPIO_FN_SDHID0_0, NULL); | ||
880 | |||
881 | /* SDHI1 */ | ||
882 | gpio_request(GPIO_FN_SDHICMD1, NULL); | ||
883 | gpio_request(GPIO_FN_SDHICLK1, NULL); | ||
884 | gpio_request(GPIO_FN_SDHID1_3, NULL); | ||
885 | gpio_request(GPIO_FN_SDHID1_2, NULL); | ||
886 | gpio_request(GPIO_FN_SDHID1_1, NULL); | ||
887 | gpio_request(GPIO_FN_SDHID1_0, NULL); | ||
888 | |||
889 | /* MMCIF */ | ||
890 | gpio_request(GPIO_FN_MMCD0_0, NULL); | ||
891 | gpio_request(GPIO_FN_MMCD0_1, NULL); | ||
892 | gpio_request(GPIO_FN_MMCD0_2, NULL); | ||
893 | gpio_request(GPIO_FN_MMCD0_3, NULL); | ||
894 | gpio_request(GPIO_FN_MMCD0_4, NULL); | ||
895 | gpio_request(GPIO_FN_MMCD0_5, NULL); | ||
896 | gpio_request(GPIO_FN_MMCD0_6, NULL); | ||
897 | gpio_request(GPIO_FN_MMCD0_7, NULL); | ||
898 | gpio_request(GPIO_FN_MMCCMD0, NULL); | ||
899 | gpio_request(GPIO_FN_MMCCLK0, NULL); | ||
900 | |||
901 | /* USB enable */ | ||
902 | gpio_request(GPIO_FN_VBUS0_1, NULL); | ||
903 | gpio_request(GPIO_FN_IDIN_1_18, NULL); | ||
904 | gpio_request(GPIO_FN_PWEN_1_115, NULL); | ||
905 | gpio_request(GPIO_FN_OVCN_1_114, NULL); | ||
906 | gpio_request(GPIO_FN_EXTLP_1, NULL); | ||
907 | gpio_request(GPIO_FN_OVCN2_1, NULL); | ||
908 | |||
909 | /* setup USB phy */ | ||
910 | __raw_writew(0x8a0a, 0xE6058130); /* USBCR2 */ | ||
911 | |||
912 | /* enable FSI2 */ | ||
913 | gpio_request(GPIO_FN_FSIAIBT, NULL); | ||
914 | gpio_request(GPIO_FN_FSIAILR, NULL); | ||
915 | gpio_request(GPIO_FN_FSIAISLD, NULL); | ||
916 | gpio_request(GPIO_FN_FSIAOSLD, NULL); | ||
917 | gpio_request(GPIO_PORT161, NULL); | ||
918 | gpio_direction_output(GPIO_PORT161, 0); /* slave */ | ||
919 | |||
920 | gpio_request(GPIO_PORT9, NULL); | ||
921 | gpio_request(GPIO_PORT10, NULL); | ||
922 | gpio_no_direction(GPIO_PORT9CR); /* FSIAOBT needs no direction */ | ||
923 | gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */ | ||
924 | |||
925 | /* set SPU2 clock to 119.6 MHz */ | ||
926 | clk = clk_get(NULL, "spu_clk"); | ||
927 | if (!IS_ERR(clk)) { | ||
928 | clk_set_rate(clk, clk_round_rate(clk, 119600000)); | ||
929 | clk_put(clk); | ||
930 | } | ||
931 | |||
932 | /* change parent of FSI A */ | ||
933 | clk = clk_get(NULL, "fsia_clk"); | ||
934 | if (!IS_ERR(clk)) { | ||
935 | clk_register(&fsiackcr_clk); | ||
936 | clk_set_parent(clk, &fsiackcr_clk); | ||
937 | clk_put(clk); | ||
938 | } | ||
939 | |||
940 | /* | ||
941 | * set irq priority, to avoid sound chopping | ||
942 | * when NFS rootfs is used | ||
943 | * FSI(3) > SMSC911X(2) | ||
944 | */ | ||
945 | intc_set_priority(IRQ_FSI, 3); | ||
946 | |||
947 | i2c_register_board_info(0, i2c0_devices, | ||
948 | ARRAY_SIZE(i2c0_devices)); | ||
949 | |||
950 | i2c_register_board_info(1, i2c1_devices, | ||
951 | ARRAY_SIZE(i2c1_devices)); | ||
952 | |||
953 | #ifdef CONFIG_AP4EVB_QHD | ||
954 | /* | ||
955 | * QHD | ||
956 | */ | ||
957 | |||
299 | /* enable KEYSC */ | 958 | /* enable KEYSC */ |
300 | gpio_request(GPIO_FN_KEYOUT0, NULL); | 959 | gpio_request(GPIO_FN_KEYOUT0, NULL); |
301 | gpio_request(GPIO_FN_KEYOUT1, NULL); | 960 | gpio_request(GPIO_FN_KEYOUT1, NULL); |
@@ -308,26 +967,122 @@ static void __init ap4evb_init(void) | |||
308 | gpio_request(GPIO_FN_KEYIN3_133, NULL); | 967 | gpio_request(GPIO_FN_KEYIN3_133, NULL); |
309 | gpio_request(GPIO_FN_KEYIN4, NULL); | 968 | gpio_request(GPIO_FN_KEYIN4, NULL); |
310 | 969 | ||
311 | /* SDHI0 */ | 970 | /* enable TouchScreen */ |
312 | gpio_request(GPIO_FN_SDHICD0, NULL); | 971 | set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW); |
313 | gpio_request(GPIO_FN_SDHIWP0, NULL); | 972 | |
314 | gpio_request(GPIO_FN_SDHICMD0, NULL); | 973 | tsc_device.irq = IRQ28; |
315 | gpio_request(GPIO_FN_SDHICLK0, NULL); | 974 | i2c_register_board_info(1, &tsc_device, 1); |
316 | gpio_request(GPIO_FN_SDHID0_3, NULL); | 975 | |
317 | gpio_request(GPIO_FN_SDHID0_2, NULL); | 976 | /* LCDC0 */ |
318 | gpio_request(GPIO_FN_SDHID0_1, NULL); | 977 | lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; |
319 | gpio_request(GPIO_FN_SDHID0_0, NULL); | 978 | lcdc_info.ch[0].interface_type = RGB24; |
979 | lcdc_info.ch[0].clock_divider = 1; | ||
980 | lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; | ||
981 | lcdc_info.ch[0].lcd_cfg.name = "R63302(QHD)"; | ||
982 | lcdc_info.ch[0].lcd_cfg.xres = 544; | ||
983 | lcdc_info.ch[0].lcd_cfg.yres = 961; | ||
984 | lcdc_info.ch[0].lcd_cfg.left_margin = 72; | ||
985 | lcdc_info.ch[0].lcd_cfg.right_margin = 600; | ||
986 | lcdc_info.ch[0].lcd_cfg.hsync_len = 16; | ||
987 | lcdc_info.ch[0].lcd_cfg.upper_margin = 8; | ||
988 | lcdc_info.ch[0].lcd_cfg.lower_margin = 8; | ||
989 | lcdc_info.ch[0].lcd_cfg.vsync_len = 2; | ||
990 | lcdc_info.ch[0].lcd_cfg.sync = FB_SYNC_VERT_HIGH_ACT | | ||
991 | FB_SYNC_HOR_HIGH_ACT; | ||
992 | lcdc_info.ch[0].lcd_size_cfg.width = 44; | ||
993 | lcdc_info.ch[0].lcd_size_cfg.height = 79; | ||
994 | |||
995 | platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices)); | ||
996 | |||
997 | #else | ||
998 | /* | ||
999 | * WVGA | ||
1000 | */ | ||
1001 | gpio_request(GPIO_FN_LCDD17, NULL); | ||
1002 | gpio_request(GPIO_FN_LCDD16, NULL); | ||
1003 | gpio_request(GPIO_FN_LCDD15, NULL); | ||
1004 | gpio_request(GPIO_FN_LCDD14, NULL); | ||
1005 | gpio_request(GPIO_FN_LCDD13, NULL); | ||
1006 | gpio_request(GPIO_FN_LCDD12, NULL); | ||
1007 | gpio_request(GPIO_FN_LCDD11, NULL); | ||
1008 | gpio_request(GPIO_FN_LCDD10, NULL); | ||
1009 | gpio_request(GPIO_FN_LCDD9, NULL); | ||
1010 | gpio_request(GPIO_FN_LCDD8, NULL); | ||
1011 | gpio_request(GPIO_FN_LCDD7, NULL); | ||
1012 | gpio_request(GPIO_FN_LCDD6, NULL); | ||
1013 | gpio_request(GPIO_FN_LCDD5, NULL); | ||
1014 | gpio_request(GPIO_FN_LCDD4, NULL); | ||
1015 | gpio_request(GPIO_FN_LCDD3, NULL); | ||
1016 | gpio_request(GPIO_FN_LCDD2, NULL); | ||
1017 | gpio_request(GPIO_FN_LCDD1, NULL); | ||
1018 | gpio_request(GPIO_FN_LCDD0, NULL); | ||
1019 | gpio_request(GPIO_FN_LCDDISP, NULL); | ||
1020 | gpio_request(GPIO_FN_LCDDCK, NULL); | ||
1021 | |||
1022 | gpio_request(GPIO_PORT189, NULL); /* backlight */ | ||
1023 | gpio_direction_output(GPIO_PORT189, 1); | ||
1024 | |||
1025 | gpio_request(GPIO_PORT151, NULL); /* LCDDON */ | ||
1026 | gpio_direction_output(GPIO_PORT151, 1); | ||
1027 | |||
1028 | lcdc_info.clock_source = LCDC_CLK_BUS; | ||
1029 | lcdc_info.ch[0].interface_type = RGB18; | ||
1030 | lcdc_info.ch[0].clock_divider = 2; | ||
1031 | lcdc_info.ch[0].flags = 0; | ||
1032 | lcdc_info.ch[0].lcd_cfg.name = "WVGA Panel"; | ||
1033 | lcdc_info.ch[0].lcd_cfg.xres = 800; | ||
1034 | lcdc_info.ch[0].lcd_cfg.yres = 480; | ||
1035 | lcdc_info.ch[0].lcd_cfg.left_margin = 220; | ||
1036 | lcdc_info.ch[0].lcd_cfg.right_margin = 110; | ||
1037 | lcdc_info.ch[0].lcd_cfg.hsync_len = 70; | ||
1038 | lcdc_info.ch[0].lcd_cfg.upper_margin = 20; | ||
1039 | lcdc_info.ch[0].lcd_cfg.lower_margin = 5; | ||
1040 | lcdc_info.ch[0].lcd_cfg.vsync_len = 5; | ||
1041 | lcdc_info.ch[0].lcd_cfg.sync = 0; | ||
1042 | lcdc_info.ch[0].lcd_size_cfg.width = 152; | ||
1043 | lcdc_info.ch[0].lcd_size_cfg.height = 91; | ||
1044 | |||
1045 | /* enable TouchScreen */ | ||
1046 | set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW); | ||
1047 | |||
1048 | tsc_device.irq = IRQ7; | ||
1049 | i2c_register_board_info(0, &tsc_device, 1); | ||
1050 | #endif /* CONFIG_AP4EVB_QHD */ | ||
320 | 1051 | ||
321 | sh7372_add_standard_devices(); | 1052 | sh7372_add_standard_devices(); |
322 | 1053 | ||
1054 | /* HDMI */ | ||
1055 | gpio_request(GPIO_FN_HDMI_HPD, NULL); | ||
1056 | gpio_request(GPIO_FN_HDMI_CEC, NULL); | ||
1057 | |||
1058 | /* Reset HDMI, must be held at least one EXTALR (32768Hz) period */ | ||
1059 | #define SRCR4 0xe61580bc | ||
1060 | srcr4 = __raw_readl(SRCR4); | ||
1061 | __raw_writel(srcr4 | (1 << 13), SRCR4); | ||
1062 | udelay(50); | ||
1063 | __raw_writel(srcr4 & ~(1 << 13), SRCR4); | ||
1064 | |||
323 | platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); | 1065 | platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); |
324 | } | 1066 | } |
325 | 1067 | ||
1068 | static void __init ap4evb_timer_init(void) | ||
1069 | { | ||
1070 | sh7372_clock_init(); | ||
1071 | shmobile_timer.init(); | ||
1072 | |||
1073 | /* External clock source */ | ||
1074 | clk_set_rate(&dv_clki_clk, 27000000); | ||
1075 | } | ||
1076 | |||
1077 | static struct sys_timer ap4evb_timer = { | ||
1078 | .init = ap4evb_timer_init, | ||
1079 | }; | ||
1080 | |||
326 | MACHINE_START(AP4EVB, "ap4evb") | 1081 | MACHINE_START(AP4EVB, "ap4evb") |
327 | .phys_io = 0xe6000000, | 1082 | .phys_io = 0xe6000000, |
328 | .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc, | 1083 | .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc, |
329 | .map_io = ap4evb_map_io, | 1084 | .map_io = ap4evb_map_io, |
330 | .init_irq = sh7372_init_irq, | 1085 | .init_irq = sh7372_init_irq, |
331 | .init_machine = ap4evb_init, | 1086 | .init_machine = ap4evb_init, |
332 | .timer = &shmobile_timer, | 1087 | .timer = &ap4evb_timer, |
333 | MACHINE_END | 1088 | MACHINE_END |