2 * Renesas System Solutions Asia Pte. Ltd - Migo-R
4 * Copyright (C) 2008 Magnus Damm
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
10 #include <linux/init.h>
11 #include <linux/platform_device.h>
12 #include <linux/interrupt.h>
13 #include <linux/input.h>
14 #include <linux/mtd/physmap.h>
15 #include <linux/mtd/nand.h>
16 #include <linux/i2c.h>
17 #include <linux/smc91x.h>
18 #include <linux/delay.h>
19 #include <linux/clk.h>
20 #include <media/soc_camera_platform.h>
21 #include <media/sh_mobile_ceu.h>
22 #include <asm/clock.h>
23 #include <asm/machvec.h>
25 #include <asm/sh_keysc.h>
26 #include <asm/sh_mobile_lcdc.h>
27 #include <asm/migor.h>
29 /* Address IRQ Size Bus Description
30 * 0x00000000 64MB 16 NOR Flash (SP29PL256N)
31 * 0x0c000000 64MB 64 SDRAM (2xK4M563233G)
32 * 0x10000000 IRQ0 16 Ethernet (SMC91C111)
33 * 0x14000000 IRQ4 16 USB 2.0 Host Controller (M66596)
34 * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A)
37 static struct smc91x_platdata smc91x_info = {
38 .flags = SMC91X_USE_16BIT,
41 static struct resource smc91x_eth_resources[] = {
46 .flags = IORESOURCE_MEM,
49 .start = 32, /* IRQ0 */
50 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
54 static struct platform_device smc91x_eth_device = {
56 .num_resources = ARRAY_SIZE(smc91x_eth_resources),
57 .resource = smc91x_eth_resources,
59 .platform_data = &smc91x_info,
63 static struct sh_keysc_info sh_keysc_info = {
64 .mode = SH_KEYSC_MODE_2, /* KEYOUT0->4, KEYIN1->5 */
68 0, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER,
69 0, KEY_F, KEY_C, KEY_D, KEY_H, KEY_1,
70 0, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
71 0, KEY_7, KEY_8, KEY_9, KEY_S, KEY_0,
72 0, KEY_P, KEY_STOP, KEY_REWIND, KEY_PLAY, KEY_FASTFORWARD,
76 static struct resource sh_keysc_resources[] = {
80 .flags = IORESOURCE_MEM,
84 .flags = IORESOURCE_IRQ,
88 static struct platform_device sh_keysc_device = {
90 .num_resources = ARRAY_SIZE(sh_keysc_resources),
91 .resource = sh_keysc_resources,
93 .platform_data = &sh_keysc_info,
97 static struct mtd_partition migor_nor_flash_partitions[] =
102 .size = (1 * 1024 * 1024),
103 .mask_flags = MTD_WRITEABLE, /* Read-only */
107 .offset = MTDPART_OFS_APPEND,
108 .size = (15 * 1024 * 1024),
112 .offset = MTDPART_OFS_APPEND,
113 .size = MTDPART_SIZ_FULL,
117 static struct physmap_flash_data migor_nor_flash_data = {
119 .parts = migor_nor_flash_partitions,
120 .nr_parts = ARRAY_SIZE(migor_nor_flash_partitions),
123 static struct resource migor_nor_flash_resources[] = {
128 .flags = IORESOURCE_MEM,
132 static struct platform_device migor_nor_flash_device = {
133 .name = "physmap-flash",
134 .resource = migor_nor_flash_resources,
135 .num_resources = ARRAY_SIZE(migor_nor_flash_resources),
137 .platform_data = &migor_nor_flash_data,
141 static struct mtd_partition migor_nand_flash_partitions[] = {
145 .size = 512 * 1024 * 1024,
149 .offset = MTDPART_OFS_APPEND,
150 .size = 512 * 1024 * 1024,
154 static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
157 struct nand_chip *chip = mtd->priv;
159 if (cmd == NAND_CMD_NONE)
163 writeb(cmd, chip->IO_ADDR_W + 0x00400000);
164 else if (ctrl & NAND_ALE)
165 writeb(cmd, chip->IO_ADDR_W + 0x00800000);
167 writeb(cmd, chip->IO_ADDR_W);
170 static int migor_nand_flash_ready(struct mtd_info *mtd)
172 return ctrl_inb(PORT_PADR) & 0x02; /* PTA1 */
175 struct platform_nand_data migor_nand_flash_data = {
178 .partitions = migor_nand_flash_partitions,
179 .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions),
181 .part_probe_types = (const char *[]) { "cmdlinepart", NULL },
184 .dev_ready = migor_nand_flash_ready,
185 .cmd_ctrl = migor_nand_flash_cmd_ctl,
189 static struct resource migor_nand_flash_resources[] = {
191 .name = "NAND Flash",
194 .flags = IORESOURCE_MEM,
198 static struct platform_device migor_nand_flash_device = {
200 .resource = migor_nand_flash_resources,
201 .num_resources = ARRAY_SIZE(migor_nand_flash_resources),
203 .platform_data = &migor_nand_flash_data,
207 static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
208 #ifdef CONFIG_SH_MIGOR_RTA_WVGA
209 .clock_source = LCDC_CLK_BUS,
211 .chan = LCDC_CHAN_MAINLCD,
213 .interface_type = RGB16,
229 #ifdef CONFIG_SH_MIGOR_QVGA
230 .clock_source = LCDC_CLK_PERIPHERAL,
232 .chan = LCDC_CHAN_MAINLCD,
234 .interface_type = SYS16A,
246 .sync = FB_SYNC_HOR_HIGH_ACT,
249 .setup_sys = migor_lcd_qvga_setup,
252 .ldmt2r = 0x06000a09,
253 .ldmt3r = 0x180e3418,
259 static struct resource migor_lcdc_resources[] = {
262 .start = 0xfe940000, /* P4-only space */
264 .flags = IORESOURCE_MEM,
268 static struct platform_device migor_lcdc_device = {
269 .name = "sh_mobile_lcdc_fb",
270 .num_resources = ARRAY_SIZE(migor_lcdc_resources),
271 .resource = migor_lcdc_resources,
273 .platform_data = &sh_mobile_lcdc_info,
277 static struct clk *camera_clk;
279 static void camera_power_on(void)
283 camera_clk = clk_get(NULL, "video_clk");
284 clk_set_rate(camera_clk, 24000000);
285 clk_enable(camera_clk); /* start VIO_CKO */
288 value = ctrl_inb(PORT_PTDR);
290 #ifndef CONFIG_SH_MIGOR_RTA_WVGA
293 ctrl_outb(value, PORT_PTDR);
296 ctrl_outb(value | 8, PORT_PTDR);
299 static void camera_power_off(void)
301 clk_disable(camera_clk); /* stop VIO_CKO */
304 ctrl_outb(ctrl_inb(PORT_PTDR) & ~0x08, PORT_PTDR);
307 static unsigned char camera_ov772x_magic[] =
309 0x09, 0x01, 0x0c, 0x10, 0x0d, 0x41, 0x0e, 0x01,
310 0x12, 0x00, 0x13, 0x8F, 0x14, 0x4A, 0x15, 0x00,
311 0x16, 0x00, 0x17, 0x23, 0x18, 0xa0, 0x19, 0x07,
312 0x1a, 0xf0, 0x1b, 0x40, 0x1f, 0x00, 0x20, 0x10,
313 0x22, 0xff, 0x23, 0x01, 0x28, 0x00, 0x29, 0xa0,
314 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0xf0, 0x2d, 0x00,
315 0x2e, 0x00, 0x30, 0x80, 0x31, 0x60, 0x32, 0x00,
316 0x33, 0x00, 0x34, 0x00, 0x3d, 0x80, 0x3e, 0xe2,
317 0x3f, 0x1f, 0x42, 0x80, 0x43, 0x80, 0x44, 0x80,
318 0x45, 0x80, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
319 0x49, 0x50, 0x4a, 0x30, 0x4b, 0x50, 0x4c, 0x50,
320 0x4d, 0x00, 0x4e, 0xef, 0x4f, 0x10, 0x50, 0x60,
321 0x51, 0x00, 0x52, 0x00, 0x53, 0x24, 0x54, 0x7a,
322 0x55, 0xfc, 0x62, 0xff, 0x63, 0xf0, 0x64, 0x1f,
323 0x65, 0x00, 0x66, 0x10, 0x67, 0x00, 0x68, 0x00,
324 0x69, 0x5c, 0x6a, 0x11, 0x6b, 0xa2, 0x6c, 0x01,
325 0x6d, 0x50, 0x6e, 0x80, 0x6f, 0x80, 0x70, 0x0f,
326 0x71, 0x00, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x0f,
327 0x75, 0xff, 0x78, 0x10, 0x79, 0x70, 0x7a, 0x70,
328 0x7b, 0xf0, 0x7c, 0xf0, 0x7d, 0xf0, 0x7e, 0x0e,
329 0x7f, 0x1a, 0x80, 0x31, 0x81, 0x5a, 0x82, 0x69,
330 0x83, 0x75, 0x84, 0x7e, 0x85, 0x88, 0x86, 0x8f,
331 0x87, 0x96, 0x88, 0xa3, 0x89, 0xaf, 0x8a, 0xc4,
332 0x8b, 0xd7, 0x8c, 0xe8, 0x8d, 0x20, 0x8e, 0x00,
333 0x8f, 0x00, 0x90, 0x08, 0x91, 0x10, 0x92, 0x1f,
334 0x93, 0x01, 0x94, 0x2c, 0x95, 0x24, 0x96, 0x08,
335 0x97, 0x14, 0x98, 0x24, 0x99, 0x38, 0x9a, 0x9e,
336 0x9b, 0x00, 0x9c, 0x40, 0x9e, 0x11, 0x9f, 0x02,
337 0xa0, 0x00, 0xa1, 0x40, 0xa2, 0x40, 0xa3, 0x06,
338 0xa4, 0x00, 0xa6, 0x00, 0xa7, 0x40, 0xa8, 0x40,
339 0xa9, 0x80, 0xaa, 0x80, 0xab, 0x06, 0xac, 0xff,
340 0x12, 0x06, 0x64, 0x3f, 0x12, 0x46, 0x17, 0x3f,
341 0x18, 0x50, 0x19, 0x03, 0x1a, 0x78, 0x29, 0x50,
345 static int ov772x_set_capture(struct soc_camera_platform_info *info,
348 struct i2c_adapter *a = i2c_get_adapter(0);
354 return 0; /* camera_power_off() is enough */
356 for (i = 0; i < ARRAY_SIZE(camera_ov772x_magic); i += 2) {
364 buf[0] = camera_ov772x_magic[i];
365 buf[1] = camera_ov772x_magic[i + 1];
367 ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1);
373 static struct soc_camera_platform_info ov772x_info = {
375 .format_name = "RGB565",
378 .pixelformat = V4L2_PIX_FMT_RGB565,
379 .colorspace = V4L2_COLORSPACE_SRGB,
383 .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
384 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
385 .set_capture = ov772x_set_capture,
388 static struct platform_device migor_camera_device = {
389 .name = "soc_camera_platform",
391 .platform_data = &ov772x_info,
395 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
396 .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
397 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
398 .enable_camera = camera_power_on,
399 .disable_camera = camera_power_off,
402 static struct resource migor_ceu_resources[] = {
407 .flags = IORESOURCE_MEM,
411 .flags = IORESOURCE_IRQ,
414 /* place holder for contiguous memory */
418 static struct platform_device migor_ceu_device = {
419 .name = "sh_mobile_ceu",
420 .num_resources = ARRAY_SIZE(migor_ceu_resources),
421 .resource = migor_ceu_resources,
423 .platform_data = &sh_mobile_ceu_info,
427 static struct platform_device *migor_devices[] __initdata = {
432 &migor_camera_device,
433 &migor_nor_flash_device,
434 &migor_nand_flash_device,
437 static struct i2c_board_info migor_i2c_devices[] = {
439 I2C_BOARD_INFO("rs5c372b", 0x32),
442 I2C_BOARD_INFO("migor_ts", 0x51),
443 .irq = 38, /* IRQ6 */
447 static int __init migor_devices_setup(void)
449 clk_always_enable("mstp214"); /* KEYSC */
450 clk_always_enable("mstp200"); /* LCDC */
451 clk_always_enable("mstp203"); /* CEU */
453 platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
455 i2c_register_board_info(0, migor_i2c_devices,
456 ARRAY_SIZE(migor_i2c_devices));
458 return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
460 __initcall(migor_devices_setup);
462 static void __init migor_setup(char **cmdline_p)
464 /* SMC91C111 - Enable IRQ0 */
465 ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR);
468 ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR);
469 ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR);
470 ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
471 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
472 ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
475 ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
476 ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
479 /* Touch Panel - Enable IRQ6 */
480 ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
481 ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
482 ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
484 #ifdef CONFIG_SH_MIGOR_RTA_WVGA
485 /* LCDC - WVGA - Enable RGB Interface signals */
486 ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
487 ctrl_outw(0x0000, PORT_PHCR);
488 ctrl_outw(0x0000, PORT_PLCR);
489 ctrl_outw(0x0000, PORT_PMCR);
490 ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR);
491 ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD);
492 ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB);
493 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
495 #ifdef CONFIG_SH_MIGOR_QVGA
496 /* LCDC - QVGA - Enable SYS Interface signals */
497 ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
498 ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR);
499 ctrl_outw(0x0000, PORT_PLCR);
500 ctrl_outw(0x0000, PORT_PMCR);
501 ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR);
502 ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD);
503 ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB);
504 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
508 ctrl_outw((ctrl_inw(PORT_PTCR) & ~0x03c3) | 0x0051, PORT_PTCR);
509 ctrl_outw(ctrl_inw(PORT_PUCR) & ~0x03ff, PORT_PUCR);
510 ctrl_outw(ctrl_inw(PORT_PVCR) & ~0x03ff, PORT_PVCR);
511 ctrl_outw(ctrl_inw(PORT_PWCR) & ~0x3c00, PORT_PWCR);
512 ctrl_outw(ctrl_inw(PORT_PSELC) | 0x0001, PORT_PSELC);
513 ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x2000, PORT_PSELD);
514 ctrl_outw(ctrl_inw(PORT_PSELE) | 0x000f, PORT_PSELE);
515 ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2200, PORT_MSELCRB);
516 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x0a00, PORT_HIZCRA);
517 ctrl_outw(ctrl_inw(PORT_HIZCRB) & ~0x0003, PORT_HIZCRB);
520 static struct sh_machine_vector mv_migor __initmv = {
522 .mv_setup = migor_setup,