aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/mach-migor/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/mach-migor/setup.c')
-rw-r--r--arch/sh/boards/mach-migor/setup.c225
1 files changed, 100 insertions, 125 deletions
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 0bcbe58b11e9..271dfc260e82 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -1,17 +1,16 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Renesas System Solutions Asia Pte. Ltd - Migo-R 3 * Renesas System Solutions Asia Pte. Ltd - Migo-R
3 * 4 *
4 * Copyright (C) 2008 Magnus Damm 5 * 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 */ 6 */
7#include <linux/clkdev.h>
10#include <linux/init.h> 8#include <linux/init.h>
11#include <linux/platform_device.h> 9#include <linux/platform_device.h>
12#include <linux/interrupt.h> 10#include <linux/interrupt.h>
13#include <linux/input.h> 11#include <linux/input.h>
14#include <linux/input/sh_keysc.h> 12#include <linux/input/sh_keysc.h>
13#include <linux/memblock.h>
15#include <linux/mmc/host.h> 14#include <linux/mmc/host.h>
16#include <linux/mtd/physmap.h> 15#include <linux/mtd/physmap.h>
17#include <linux/mfd/tmio.h> 16#include <linux/mfd/tmio.h>
@@ -23,10 +22,11 @@
23#include <linux/delay.h> 22#include <linux/delay.h>
24#include <linux/clk.h> 23#include <linux/clk.h>
25#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/gpio/machine.h>
26#include <linux/videodev2.h> 26#include <linux/videodev2.h>
27#include <linux/sh_intc.h> 27#include <linux/sh_intc.h>
28#include <video/sh_mobile_lcdc.h> 28#include <video/sh_mobile_lcdc.h>
29#include <media/drv-intf/sh_mobile_ceu.h> 29#include <media/drv-intf/renesas-ceu.h>
30#include <media/i2c/ov772x.h> 30#include <media/i2c/ov772x.h>
31#include <media/soc_camera.h> 31#include <media/soc_camera.h>
32#include <media/i2c/tw9910.h> 32#include <media/i2c/tw9910.h>
@@ -45,6 +45,9 @@
45 * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A) 45 * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A)
46 */ 46 */
47 47
48#define CEU_BUFFER_MEMORY_SIZE (4 << 20)
49static phys_addr_t ceu_dma_membase;
50
48static struct smc91x_platdata smc91x_info = { 51static struct smc91x_platdata smc91x_info = {
49 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, 52 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
50}; 53};
@@ -301,65 +304,24 @@ static struct platform_device migor_lcdc_device = {
301 }, 304 },
302}; 305};
303 306
304static struct clk *camera_clk; 307static struct ceu_platform_data ceu_pdata = {
305static DEFINE_MUTEX(camera_lock); 308 .num_subdevs = 2,
306 309 .subdevs = {
307static void camera_power_on(int is_tw) 310 { /* [0] = ov772x */
308{ 311 .flags = 0,
309 mutex_lock(&camera_lock); 312 .bus_width = 8,
310 313 .bus_shift = 0,
311 /* Use 10 MHz VIO_CKO instead of 24 MHz to work 314 .i2c_adapter_id = 0,
312 * around signal quality issues on Panel Board V2.1. 315 .i2c_address = 0x21,
313 */ 316 },
314 camera_clk = clk_get(NULL, "video_clk"); 317 { /* [1] = tw9910 */
315 clk_set_rate(camera_clk, 10000000); 318 .flags = 0,
316 clk_enable(camera_clk); /* start VIO_CKO */ 319 .bus_width = 8,
317 320 .bus_shift = 0,
318 /* use VIO_RST to take camera out of reset */ 321 .i2c_adapter_id = 0,
319 mdelay(10); 322 .i2c_address = 0x45,
320 if (is_tw) { 323 },
321 gpio_set_value(GPIO_PTT2, 0); 324 },
322 gpio_set_value(GPIO_PTT0, 0);
323 } else {
324 gpio_set_value(GPIO_PTT0, 1);
325 }
326 gpio_set_value(GPIO_PTT3, 0);
327 mdelay(10);
328 gpio_set_value(GPIO_PTT3, 1);
329 mdelay(10); /* wait to let chip come out of reset */
330}
331
332static void camera_power_off(void)
333{
334 clk_disable(camera_clk); /* stop VIO_CKO */
335 clk_put(camera_clk);
336
337 gpio_set_value(GPIO_PTT3, 0);
338 mutex_unlock(&camera_lock);
339}
340
341static int ov7725_power(struct device *dev, int mode)
342{
343 if (mode)
344 camera_power_on(0);
345 else
346 camera_power_off();
347
348 return 0;
349}
350
351static int tw9910_power(struct device *dev, int mode)
352{
353 if (mode)
354 camera_power_on(1);
355 else
356 camera_power_off();
357
358 return 0;
359}
360
361static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
362 .flags = SH_CEU_FLAG_USE_8BIT_BUS,
363}; 325};
364 326
365static struct resource migor_ceu_resources[] = { 327static struct resource migor_ceu_resources[] = {
@@ -373,18 +335,32 @@ static struct resource migor_ceu_resources[] = {
373 .start = evt2irq(0x880), 335 .start = evt2irq(0x880),
374 .flags = IORESOURCE_IRQ, 336 .flags = IORESOURCE_IRQ,
375 }, 337 },
376 [2] = {
377 /* place holder for contiguous memory */
378 },
379}; 338};
380 339
381static struct platform_device migor_ceu_device = { 340static struct platform_device migor_ceu_device = {
382 .name = "sh_mobile_ceu", 341 .name = "renesas-ceu",
383 .id = 0, /* "ceu0" clock */ 342 .id = 0, /* ceu.0 */
384 .num_resources = ARRAY_SIZE(migor_ceu_resources), 343 .num_resources = ARRAY_SIZE(migor_ceu_resources),
385 .resource = migor_ceu_resources, 344 .resource = migor_ceu_resources,
386 .dev = { 345 .dev = {
387 .platform_data = &sh_mobile_ceu_info, 346 .platform_data = &ceu_pdata,
347 },
348};
349
350/* Powerdown/reset gpios for CEU image sensors */
351static struct gpiod_lookup_table ov7725_gpios = {
352 .dev_id = "0-0021",
353 .table = {
354 GPIO_LOOKUP("sh7722_pfc", GPIO_PTT0, "pwdn", GPIO_ACTIVE_HIGH),
355 GPIO_LOOKUP("sh7722_pfc", GPIO_PTT3, "rstb", GPIO_ACTIVE_LOW),
356 },
357};
358
359static struct gpiod_lookup_table tw9910_gpios = {
360 .dev_id = "0-0045",
361 .table = {
362 GPIO_LOOKUP("sh7722_pfc", GPIO_PTT2, "pdn", GPIO_ACTIVE_HIGH),
363 GPIO_LOOKUP("sh7722_pfc", GPIO_PTT3, "rstb", GPIO_ACTIVE_LOW),
388 }, 364 },
389}; 365};
390 366
@@ -423,6 +399,15 @@ static struct platform_device sdhi_cn9_device = {
423 }, 399 },
424}; 400};
425 401
402static struct ov772x_camera_info ov7725_info = {
403 .flags = 0,
404};
405
406static struct tw9910_video_info tw9910_info = {
407 .buswidth = 8,
408 .mpout = TW9910_MPO_FIELD,
409};
410
426static struct i2c_board_info migor_i2c_devices[] = { 411static struct i2c_board_info migor_i2c_devices[] = {
427 { 412 {
428 I2C_BOARD_INFO("rs5c372b", 0x32), 413 I2C_BOARD_INFO("rs5c372b", 0x32),
@@ -434,51 +419,13 @@ static struct i2c_board_info migor_i2c_devices[] = {
434 { 419 {
435 I2C_BOARD_INFO("wm8978", 0x1a), 420 I2C_BOARD_INFO("wm8978", 0x1a),
436 }, 421 },
437};
438
439static struct i2c_board_info migor_i2c_camera[] = {
440 { 422 {
441 I2C_BOARD_INFO("ov772x", 0x21), 423 I2C_BOARD_INFO("ov772x", 0x21),
424 .platform_data = &ov7725_info,
442 }, 425 },
443 { 426 {
444 I2C_BOARD_INFO("tw9910", 0x45), 427 I2C_BOARD_INFO("tw9910", 0x45),
445 }, 428 .platform_data = &tw9910_info,
446};
447
448static struct ov772x_camera_info ov7725_info;
449
450static struct soc_camera_link ov7725_link = {
451 .power = ov7725_power,
452 .board_info = &migor_i2c_camera[0],
453 .i2c_adapter_id = 0,
454 .priv = &ov7725_info,
455};
456
457static struct tw9910_video_info tw9910_info = {
458 .buswidth = SOCAM_DATAWIDTH_8,
459 .mpout = TW9910_MPO_FIELD,
460};
461
462static struct soc_camera_link tw9910_link = {
463 .power = tw9910_power,
464 .board_info = &migor_i2c_camera[1],
465 .i2c_adapter_id = 0,
466 .priv = &tw9910_info,
467};
468
469static struct platform_device migor_camera[] = {
470 {
471 .name = "soc-camera-pdrv",
472 .id = 0,
473 .dev = {
474 .platform_data = &ov7725_link,
475 },
476 }, {
477 .name = "soc-camera-pdrv",
478 .id = 1,
479 .dev = {
480 .platform_data = &tw9910_link,
481 },
482 }, 429 },
483}; 430};
484 431
@@ -486,12 +433,9 @@ static struct platform_device *migor_devices[] __initdata = {
486 &smc91x_eth_device, 433 &smc91x_eth_device,
487 &sh_keysc_device, 434 &sh_keysc_device,
488 &migor_lcdc_device, 435 &migor_lcdc_device,
489 &migor_ceu_device,
490 &migor_nor_flash_device, 436 &migor_nor_flash_device,
491 &migor_nand_flash_device, 437 &migor_nand_flash_device,
492 &sdhi_cn9_device, 438 &sdhi_cn9_device,
493 &migor_camera[0],
494 &migor_camera[1],
495}; 439};
496 440
497extern char migor_sdram_enter_start; 441extern char migor_sdram_enter_start;
@@ -501,6 +445,8 @@ extern char migor_sdram_leave_end;
501 445
502static int __init migor_devices_setup(void) 446static int __init migor_devices_setup(void)
503{ 447{
448 struct clk *video_clk;
449
504 /* register board specific self-refresh code */ 450 /* register board specific self-refresh code */
505 sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF, 451 sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
506 &migor_sdram_enter_start, 452 &migor_sdram_enter_start,
@@ -620,20 +566,8 @@ static int __init migor_devices_setup(void)
620 gpio_request(GPIO_FN_VIO_D9, NULL); 566 gpio_request(GPIO_FN_VIO_D9, NULL);
621 gpio_request(GPIO_FN_VIO_D8, NULL); 567 gpio_request(GPIO_FN_VIO_D8, NULL);
622 568
623 gpio_request(GPIO_PTT3, NULL); /* VIO_RST */
624 gpio_direction_output(GPIO_PTT3, 0);
625 gpio_request(GPIO_PTT2, NULL); /* TV_IN_EN */
626 gpio_direction_output(GPIO_PTT2, 1);
627 gpio_request(GPIO_PTT0, NULL); /* CAM_EN */
628#ifdef CONFIG_SH_MIGOR_RTA_WVGA
629 gpio_direction_output(GPIO_PTT0, 0);
630#else
631 gpio_direction_output(GPIO_PTT0, 1);
632#endif
633 __raw_writew(__raw_readw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */ 569 __raw_writew(__raw_readw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */
634 570
635 platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
636
637 /* SIU: Port B */ 571 /* SIU: Port B */
638 gpio_request(GPIO_FN_SIUBOLR, NULL); 572 gpio_request(GPIO_FN_SIUBOLR, NULL);
639 gpio_request(GPIO_FN_SIUBOBT, NULL); 573 gpio_request(GPIO_FN_SIUBOBT, NULL);
@@ -647,9 +581,36 @@ static int __init migor_devices_setup(void)
647 */ 581 */
648 __raw_writew(__raw_readw(PORT_MSELCRA) | 1, PORT_MSELCRA); 582 __raw_writew(__raw_readw(PORT_MSELCRA) | 1, PORT_MSELCRA);
649 583
584 /*
585 * Use 10 MHz VIO_CKO instead of 24 MHz to work around signal quality
586 * issues on Panel Board V2.1.
587 */
588 video_clk = clk_get(NULL, "video_clk");
589 if (!IS_ERR(video_clk)) {
590 clk_set_rate(video_clk, clk_round_rate(video_clk, 10000000));
591 clk_put(video_clk);
592 }
593
594 /* Add a clock alias for ov7725 xclk source. */
595 clk_add_alias("xclk", "0-0021", "video_clk", NULL);
596
597 /* Register GPIOs for video sources. */
598 gpiod_add_lookup_table(&ov7725_gpios);
599 gpiod_add_lookup_table(&tw9910_gpios);
600
650 i2c_register_board_info(0, migor_i2c_devices, 601 i2c_register_board_info(0, migor_i2c_devices,
651 ARRAY_SIZE(migor_i2c_devices)); 602 ARRAY_SIZE(migor_i2c_devices));
652 603
604 /* Initialize CEU platform device separately to map memory first */
605 device_initialize(&migor_ceu_device.dev);
606 arch_setup_pdev_archdata(&migor_ceu_device);
607 dma_declare_coherent_memory(&migor_ceu_device.dev,
608 ceu_dma_membase, ceu_dma_membase,
609 ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1,
610 DMA_MEMORY_EXCLUSIVE);
611
612 platform_device_add(&migor_ceu_device);
613
653 return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices)); 614 return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
654} 615}
655arch_initcall(migor_devices_setup); 616arch_initcall(migor_devices_setup);
@@ -665,10 +626,24 @@ static int migor_mode_pins(void)
665 return MODE_PIN0 | MODE_PIN1 | MODE_PIN5; 626 return MODE_PIN0 | MODE_PIN1 | MODE_PIN5;
666} 627}
667 628
629/* Reserve a portion of memory for CEU buffers */
630static void __init migor_mv_mem_reserve(void)
631{
632 phys_addr_t phys;
633 phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
634
635 phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
636 memblock_free(phys, size);
637 memblock_remove(phys, size);
638
639 ceu_dma_membase = phys;
640}
641
668/* 642/*
669 * The Machine Vector 643 * The Machine Vector
670 */ 644 */
671static struct sh_machine_vector mv_migor __initmv = { 645static struct sh_machine_vector mv_migor __initmv = {
672 .mv_name = "Migo-R", 646 .mv_name = "Migo-R",
673 .mv_mode_pins = migor_mode_pins, 647 .mv_mode_pins = migor_mode_pins,
648 .mv_mem_reserve = migor_mv_mem_reserve,
674}; 649};