1 /* 2 * Renesas System Solutions Asia Pte. Ltd - Migo-R 3 * 4 * Copyright (C) 2008 Magnus Damm 5 * 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 8 * for more details. 9 */ 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> 24 #include <asm/io.h> 25 #include <asm/sh_keysc.h> 26 #include <asm/sh_mobile_lcdc.h> 27 #include <asm/migor.h> 28 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) 35 */ 36 37 static struct smc91x_platdata smc91x_info = { 38 .flags = SMC91X_USE_16BIT, 39 }; 40 41 static struct resource smc91x_eth_resources[] = { 42 [0] = { 43 .name = "SMC91C111" , 44 .start = 0x10000300, 45 .end = 0x1000030f, 46 .flags = IORESOURCE_MEM, 47 }, 48 [1] = { 49 .start = 32, /* IRQ0 */ 50 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, 51 }, 52 }; 53 54 static struct platform_device smc91x_eth_device = { 55 .name = "smc91x", 56 .num_resources = ARRAY_SIZE(smc91x_eth_resources), 57 .resource = smc91x_eth_resources, 58 .dev = { 59 .platform_data = &smc91x_info, 60 }, 61 }; 62 63 static struct sh_keysc_info sh_keysc_info = { 64 .mode = SH_KEYSC_MODE_2, /* KEYOUT0->4, KEYIN1->5 */ 65 .scan_timing = 3, 66 .delay = 5, 67 .keycodes = { 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, 73 }, 74 }; 75 76 static struct resource sh_keysc_resources[] = { 77 [0] = { 78 .start = 0x044b0000, 79 .end = 0x044b000f, 80 .flags = IORESOURCE_MEM, 81 }, 82 [1] = { 83 .start = 79, 84 .flags = IORESOURCE_IRQ, 85 }, 86 }; 87 88 static struct platform_device sh_keysc_device = { 89 .name = "sh_keysc", 90 .num_resources = ARRAY_SIZE(sh_keysc_resources), 91 .resource = sh_keysc_resources, 92 .dev = { 93 .platform_data = &sh_keysc_info, 94 }, 95 }; 96 97 static struct mtd_partition migor_nor_flash_partitions[] = 98 { 99 { 100 .name = "uboot", 101 .offset = 0, 102 .size = (1 * 1024 * 1024), 103 .mask_flags = MTD_WRITEABLE, /* Read-only */ 104 }, 105 { 106 .name = "rootfs", 107 .offset = MTDPART_OFS_APPEND, 108 .size = (15 * 1024 * 1024), 109 }, 110 { 111 .name = "other", 112 .offset = MTDPART_OFS_APPEND, 113 .size = MTDPART_SIZ_FULL, 114 }, 115 }; 116 117 static struct physmap_flash_data migor_nor_flash_data = { 118 .width = 2, 119 .parts = migor_nor_flash_partitions, 120 .nr_parts = ARRAY_SIZE(migor_nor_flash_partitions), 121 }; 122 123 static struct resource migor_nor_flash_resources[] = { 124 [0] = { 125 .name = "NOR Flash", 126 .start = 0x00000000, 127 .end = 0x03ffffff, 128 .flags = IORESOURCE_MEM, 129 } 130 }; 131 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), 136 .dev = { 137 .platform_data = &migor_nor_flash_data, 138 }, 139 }; 140 141 static struct mtd_partition migor_nand_flash_partitions[] = { 142 { 143 .name = "nanddata1", 144 .offset = 0x0, 145 .size = 512 * 1024 * 1024, 146 }, 147 { 148 .name = "nanddata2", 149 .offset = MTDPART_OFS_APPEND, 150 .size = 512 * 1024 * 1024, 151 }, 152 }; 153 154 static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd, 155 unsigned int ctrl) 156 { 157 struct nand_chip *chip = mtd->priv; 158 159 if (cmd == NAND_CMD_NONE) 160 return; 161 162 if (ctrl & NAND_CLE) 163 writeb(cmd, chip->IO_ADDR_W + 0x00400000); 164 else if (ctrl & NAND_ALE) 165 writeb(cmd, chip->IO_ADDR_W + 0x00800000); 166 else 167 writeb(cmd, chip->IO_ADDR_W); 168 } 169 170 static int migor_nand_flash_ready(struct mtd_info *mtd) 171 { 172 return ctrl_inb(PORT_PADR) & 0x02; /* PTA1 */ 173 } 174 175 struct platform_nand_data migor_nand_flash_data = { 176 .chip = { 177 .nr_chips = 1, 178 .partitions = migor_nand_flash_partitions, 179 .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions), 180 .chip_delay = 20, 181 .part_probe_types = (const char *[]) { "cmdlinepart", NULL }, 182 }, 183 .ctrl = { 184 .dev_ready = migor_nand_flash_ready, 185 .cmd_ctrl = migor_nand_flash_cmd_ctl, 186 }, 187 }; 188 189 static struct resource migor_nand_flash_resources[] = { 190 [0] = { 191 .name = "NAND Flash", 192 .start = 0x18000000, 193 .end = 0x18ffffff, 194 .flags = IORESOURCE_MEM, 195 }, 196 }; 197 198 static struct platform_device migor_nand_flash_device = { 199 .name = "gen_nand", 200 .resource = migor_nand_flash_resources, 201 .num_resources = ARRAY_SIZE(migor_nand_flash_resources), 202 .dev = { 203 .platform_data = &migor_nand_flash_data, 204 } 205 }; 206 207 static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { 208 #ifdef CONFIG_SH_MIGOR_RTA_WVGA 209 .clock_source = LCDC_CLK_BUS, 210 .ch[0] = { 211 .chan = LCDC_CHAN_MAINLCD, 212 .bpp = 16, 213 .interface_type = RGB16, 214 .clock_divider = 2, 215 .lcd_cfg = { 216 .name = "LB070WV1", 217 .xres = 800, 218 .yres = 480, 219 .left_margin = 64, 220 .right_margin = 16, 221 .hsync_len = 120, 222 .upper_margin = 1, 223 .lower_margin = 17, 224 .vsync_len = 2, 225 .sync = 0, 226 }, 227 } 228 #endif 229 #ifdef CONFIG_SH_MIGOR_QVGA 230 .clock_source = LCDC_CLK_PERIPHERAL, 231 .ch[0] = { 232 .chan = LCDC_CHAN_MAINLCD, 233 .bpp = 16, 234 .interface_type = SYS16A, 235 .clock_divider = 10, 236 .lcd_cfg = { 237 .name = "PH240320T", 238 .xres = 320, 239 .yres = 240, 240 .left_margin = 0, 241 .right_margin = 16, 242 .hsync_len = 8, 243 .upper_margin = 1, 244 .lower_margin = 17, 245 .vsync_len = 2, 246 .sync = FB_SYNC_HOR_HIGH_ACT, 247 }, 248 .board_cfg = { 249 .setup_sys = migor_lcd_qvga_setup, 250 }, 251 .sys_bus_cfg = { 252 .ldmt2r = 0x06000a09, 253 .ldmt3r = 0x180e3418, 254 }, 255 } 256 #endif 257 }; 258 259 static struct resource migor_lcdc_resources[] = { 260 [0] = { 261 .name = "LCDC", 262 .start = 0xfe940000, /* P4-only space */ 263 .end = 0xfe941fff, 264 .flags = IORESOURCE_MEM, 265 }, 266 }; 267 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, 272 .dev = { 273 .platform_data = &sh_mobile_lcdc_info, 274 }, 275 }; 276 277 static struct clk *camera_clk; 278 279 static void camera_power_on(void) 280 { 281 unsigned char value; 282 283 camera_clk = clk_get(NULL, "video_clk"); 284 clk_set_rate(camera_clk, 24000000); 285 clk_enable(camera_clk); /* start VIO_CKO */ 286 287 mdelay(10); 288 value = ctrl_inb(PORT_PTDR); 289 value &= ~0x09; 290 #ifndef CONFIG_SH_MIGOR_RTA_WVGA 291 value |= 0x01; 292 #endif 293 ctrl_outb(value, PORT_PTDR); 294 mdelay(10); 295 296 ctrl_outb(value | 8, PORT_PTDR); 297 } 298 299 static void camera_power_off(void) 300 { 301 clk_disable(camera_clk); /* stop VIO_CKO */ 302 clk_put(camera_clk); 303 304 ctrl_outb(ctrl_inb(PORT_PTDR) & ~0x08, PORT_PTDR); 305 } 306 307 #ifdef CONFIG_I2C 308 static unsigned char camera_ov772x_magic[] = 309 { 310 0x09, 0x01, 0x0c, 0x10, 0x0d, 0x41, 0x0e, 0x01, 311 0x12, 0x00, 0x13, 0x8F, 0x14, 0x4A, 0x15, 0x00, 312 0x16, 0x00, 0x17, 0x23, 0x18, 0xa0, 0x19, 0x07, 313 0x1a, 0xf0, 0x1b, 0x40, 0x1f, 0x00, 0x20, 0x10, 314 0x22, 0xff, 0x23, 0x01, 0x28, 0x00, 0x29, 0xa0, 315 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0xf0, 0x2d, 0x00, 316 0x2e, 0x00, 0x30, 0x80, 0x31, 0x60, 0x32, 0x00, 317 0x33, 0x00, 0x34, 0x00, 0x3d, 0x80, 0x3e, 0xe2, 318 0x3f, 0x1f, 0x42, 0x80, 0x43, 0x80, 0x44, 0x80, 319 0x45, 0x80, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 320 0x49, 0x50, 0x4a, 0x30, 0x4b, 0x50, 0x4c, 0x50, 321 0x4d, 0x00, 0x4e, 0xef, 0x4f, 0x10, 0x50, 0x60, 322 0x51, 0x00, 0x52, 0x00, 0x53, 0x24, 0x54, 0x7a, 323 0x55, 0xfc, 0x62, 0xff, 0x63, 0xf0, 0x64, 0x1f, 324 0x65, 0x00, 0x66, 0x10, 0x67, 0x00, 0x68, 0x00, 325 0x69, 0x5c, 0x6a, 0x11, 0x6b, 0xa2, 0x6c, 0x01, 326 0x6d, 0x50, 0x6e, 0x80, 0x6f, 0x80, 0x70, 0x0f, 327 0x71, 0x00, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x0f, 328 0x75, 0xff, 0x78, 0x10, 0x79, 0x70, 0x7a, 0x70, 329 0x7b, 0xf0, 0x7c, 0xf0, 0x7d, 0xf0, 0x7e, 0x0e, 330 0x7f, 0x1a, 0x80, 0x31, 0x81, 0x5a, 0x82, 0x69, 331 0x83, 0x75, 0x84, 0x7e, 0x85, 0x88, 0x86, 0x8f, 332 0x87, 0x96, 0x88, 0xa3, 0x89, 0xaf, 0x8a, 0xc4, 333 0x8b, 0xd7, 0x8c, 0xe8, 0x8d, 0x20, 0x8e, 0x00, 334 0x8f, 0x00, 0x90, 0x08, 0x91, 0x10, 0x92, 0x1f, 335 0x93, 0x01, 0x94, 0x2c, 0x95, 0x24, 0x96, 0x08, 336 0x97, 0x14, 0x98, 0x24, 0x99, 0x38, 0x9a, 0x9e, 337 0x9b, 0x00, 0x9c, 0x40, 0x9e, 0x11, 0x9f, 0x02, 338 0xa0, 0x00, 0xa1, 0x40, 0xa2, 0x40, 0xa3, 0x06, 339 0xa4, 0x00, 0xa6, 0x00, 0xa7, 0x40, 0xa8, 0x40, 340 0xa9, 0x80, 0xaa, 0x80, 0xab, 0x06, 0xac, 0xff, 341 0x12, 0x06, 0x64, 0x3f, 0x12, 0x46, 0x17, 0x3f, 342 0x18, 0x50, 0x19, 0x03, 0x1a, 0x78, 0x29, 0x50, 343 0x2c, 0x78, 344 }; 345 346 static int ov772x_set_capture(struct soc_camera_platform_info *info, 347 int enable) 348 { 349 struct i2c_adapter *a = i2c_get_adapter(0); 350 struct i2c_msg msg; 351 int ret = 0; 352 int i; 353 354 if (!enable) 355 return 0; /* camera_power_off() is enough */ 356 357 for (i = 0; i < ARRAY_SIZE(camera_ov772x_magic); i += 2) { 358 u_int8_t buf[8]; 359 360 msg.addr = 0x21; 361 msg.buf = buf; 362 msg.len = 2; 363 msg.flags = 0; 364 365 buf[0] = camera_ov772x_magic[i]; 366 buf[1] = camera_ov772x_magic[i + 1]; 367 368 ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1); 369 } 370 371 return ret; 372 } 373 374 static struct soc_camera_platform_info ov772x_info = { 375 .iface = 0, 376 .format_name = "RGB565", 377 .format_depth = 16, 378 .format = { 379 .pixelformat = V4L2_PIX_FMT_RGB565, 380 .colorspace = V4L2_COLORSPACE_SRGB, 381 .width = 320, 382 .height = 240, 383 }, 384 .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | 385 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, 386 .set_capture = ov772x_set_capture, 387 }; 388 389 static struct platform_device migor_camera_device = { 390 .name = "soc_camera_platform", 391 .dev = { 392 .platform_data = &ov772x_info, 393 }, 394 }; 395 #endif /* CONFIG_I2C */ 396 397 static struct sh_mobile_ceu_info sh_mobile_ceu_info = { 398 .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \ 399 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH, 400 .enable_camera = camera_power_on, 401 .disable_camera = camera_power_off, 402 }; 403 404 static struct resource migor_ceu_resources[] = { 405 [0] = { 406 .name = "CEU", 407 .start = 0xfe910000, 408 .end = 0xfe91009f, 409 .flags = IORESOURCE_MEM, 410 }, 411 [1] = { 412 .start = 52, 413 .flags = IORESOURCE_IRQ, 414 }, 415 [2] = { 416 /* place holder for contiguous memory */ 417 }, 418 }; 419 420 static struct platform_device migor_ceu_device = { 421 .name = "sh_mobile_ceu", 422 .num_resources = ARRAY_SIZE(migor_ceu_resources), 423 .resource = migor_ceu_resources, 424 .dev = { 425 .platform_data = &sh_mobile_ceu_info, 426 }, 427 }; 428 429 static struct platform_device *migor_devices[] __initdata = { 430 &smc91x_eth_device, 431 &sh_keysc_device, 432 &migor_lcdc_device, 433 &migor_ceu_device, 434 #ifdef CONFIG_I2C 435 &migor_camera_device, 436 #endif 437 &migor_nor_flash_device, 438 &migor_nand_flash_device, 439 }; 440 441 static struct i2c_board_info migor_i2c_devices[] = { 442 { 443 I2C_BOARD_INFO("rs5c372b", 0x32), 444 }, 445 { 446 I2C_BOARD_INFO("migor_ts", 0x51), 447 .irq = 38, /* IRQ6 */ 448 }, 449 }; 450 451 static int __init migor_devices_setup(void) 452 { 453 clk_always_enable("mstp214"); /* KEYSC */ 454 clk_always_enable("mstp200"); /* LCDC */ 455 clk_always_enable("mstp203"); /* CEU */ 456 457 platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20); 458 459 i2c_register_board_info(0, migor_i2c_devices, 460 ARRAY_SIZE(migor_i2c_devices)); 461 462 return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices)); 463 } 464 __initcall(migor_devices_setup); 465 466 static void __init migor_setup(char **cmdline_p) 467 { 468 /* SMC91C111 - Enable IRQ0 */ 469 ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR); 470 471 /* KEYSC */ 472 ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR); 473 ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR); 474 ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA); 475 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA); 476 ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC); 477 478 /* NAND Flash */ 479 ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR); 480 ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200, 481 BSC_CS6ABCR); 482 483 /* Touch Panel - Enable IRQ6 */ 484 ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR); 485 ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA); 486 ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC); 487 488 #ifdef CONFIG_SH_MIGOR_RTA_WVGA 489 /* LCDC - WVGA - Enable RGB Interface signals */ 490 ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR); 491 ctrl_outw(0x0000, PORT_PHCR); 492 ctrl_outw(0x0000, PORT_PLCR); 493 ctrl_outw(0x0000, PORT_PMCR); 494 ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR); 495 ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD); 496 ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB); 497 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA); 498 #endif 499 #ifdef CONFIG_SH_MIGOR_QVGA 500 /* LCDC - QVGA - Enable SYS Interface signals */ 501 ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR); 502 ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR); 503 ctrl_outw(0x0000, PORT_PLCR); 504 ctrl_outw(0x0000, PORT_PMCR); 505 ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR); 506 ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD); 507 ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB); 508 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA); 509 #endif 510 511 /* CEU */ 512 ctrl_outw((ctrl_inw(PORT_PTCR) & ~0x03c3) | 0x0051, PORT_PTCR); 513 ctrl_outw(ctrl_inw(PORT_PUCR) & ~0x03ff, PORT_PUCR); 514 ctrl_outw(ctrl_inw(PORT_PVCR) & ~0x03ff, PORT_PVCR); 515 ctrl_outw(ctrl_inw(PORT_PWCR) & ~0x3c00, PORT_PWCR); 516 ctrl_outw(ctrl_inw(PORT_PSELC) | 0x0001, PORT_PSELC); 517 ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x2000, PORT_PSELD); 518 ctrl_outw(ctrl_inw(PORT_PSELE) | 0x000f, PORT_PSELE); 519 ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2200, PORT_MSELCRB); 520 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x0a00, PORT_HIZCRA); 521 ctrl_outw(ctrl_inw(PORT_HIZCRB) & ~0x0003, PORT_HIZCRB); 522 } 523 524 static struct sh_machine_vector mv_migor __initmv = { 525 .mv_name = "Migo-R", 526 .mv_setup = migor_setup, 527 }; 528