1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Renesas - AP-325RXA
4 * (Compatible with Algo System ., LTD. - AP-320A)
5 *
6 * Copyright (C) 2008 Renesas Solutions Corp.
7 * Author : Yusuke Goda <goda.yuske@renesas.com>
8 */
9
10#include <asm/clock.h>
11#include <asm/io.h>
12#include <asm/suspend.h>
13
14#include <cpu/sh7723.h>
15
16#include <linux/dma-map-ops.h>
17#include <linux/clkdev.h>
18#include <linux/delay.h>
19#include <linux/device.h>
20#include <linux/gpio.h>
21#include <linux/gpio/consumer.h>
22#include <linux/gpio/machine.h>
23#include <linux/i2c.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/memblock.h>
27#include <linux/mfd/tmio.h>
28#include <linux/mmc/host.h>
29#include <linux/mtd/physmap.h>
30#include <linux/mtd/sh_flctl.h>
31#include <linux/platform_device.h>
32#include <linux/regulator/fixed.h>
33#include <linux/regulator/machine.h>
34#include <linux/sh_intc.h>
35#include <linux/smsc911x.h>
36#include <linux/videodev2.h>
37
38#include <media/drv-intf/renesas-ceu.h>
39#include <media/i2c/ov772x.h>
40
41#include <video/sh_mobile_lcdc.h>
42
43#define CEU_BUFFER_MEMORY_SIZE (4 << 20)
44static phys_addr_t ceu_dma_membase;
45
46/* Dummy supplies, where voltage doesn't matter */
47static struct regulator_consumer_supply dummy_supplies[] = {
48 REGULATOR_SUPPLY("vddvario", "smsc911x"),
49 REGULATOR_SUPPLY("vdd33a", "smsc911x"),
50};
51
52static struct smsc911x_platform_config smsc911x_config = {
53 .phy_interface = PHY_INTERFACE_MODE_MII,
54 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
55 .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
56 .flags = SMSC911X_USE_32BIT,
57};
58
59static struct resource smsc9118_resources[] = {
60 [0] = {
61 .start = 0xb6080000,
62 .end = 0xb60fffff,
63 .flags = IORESOURCE_MEM,
64 },
65 [1] = {
66 .start = evt2irq(0x660),
67 .end = evt2irq(0x660),
68 .flags = IORESOURCE_IRQ,
69 }
70};
71
72static struct platform_device smsc9118_device = {
73 .name = "smsc911x",
74 .id = -1,
75 .num_resources = ARRAY_SIZE(smsc9118_resources),
76 .resource = smsc9118_resources,
77 .dev = {
78 .platform_data = &smsc911x_config,
79 },
80};
81
82/*
83 * AP320 and AP325RXA has CPLD data in NOR Flash(0xA80000-0xABFFFF).
84 * If this area erased, this board can not boot.
85 */
86static struct mtd_partition ap325rxa_nor_flash_partitions[] = {
87 {
88 .name = "uboot",
89 .offset = 0,
90 .size = (1 * 1024 * 1024),
91 .mask_flags = MTD_WRITEABLE, /* Read-only */
92 }, {
93 .name = "kernel",
94 .offset = MTDPART_OFS_APPEND,
95 .size = (2 * 1024 * 1024),
96 }, {
97 .name = "free-area0",
98 .offset = MTDPART_OFS_APPEND,
99 .size = ((7 * 1024 * 1024) + (512 * 1024)),
100 }, {
101 .name = "CPLD-Data",
102 .offset = MTDPART_OFS_APPEND,
103 .mask_flags = MTD_WRITEABLE, /* Read-only */
104 .size = (1024 * 128 * 2),
105 }, {
106 .name = "free-area1",
107 .offset = MTDPART_OFS_APPEND,
108 .size = MTDPART_SIZ_FULL,
109 },
110};
111
112static struct physmap_flash_data ap325rxa_nor_flash_data = {
113 .width = 2,
114 .parts = ap325rxa_nor_flash_partitions,
115 .nr_parts = ARRAY_SIZE(ap325rxa_nor_flash_partitions),
116};
117
118static struct resource ap325rxa_nor_flash_resources[] = {
119 [0] = {
120 .name = "NOR Flash",
121 .start = 0x00000000,
122 .end = 0x00ffffff,
123 .flags = IORESOURCE_MEM,
124 }
125};
126
127static struct platform_device ap325rxa_nor_flash_device = {
128 .name = "physmap-flash",
129 .resource = ap325rxa_nor_flash_resources,
130 .num_resources = ARRAY_SIZE(ap325rxa_nor_flash_resources),
131 .dev = {
132 .platform_data = &ap325rxa_nor_flash_data,
133 },
134};
135
136static struct mtd_partition nand_partition_info[] = {
137 {
138 .name = "nand_data",
139 .offset = 0,
140 .size = MTDPART_SIZ_FULL,
141 },
142};
143
144static struct resource nand_flash_resources[] = {
145 [0] = {
146 .start = 0xa4530000,
147 .end = 0xa45300ff,
148 .flags = IORESOURCE_MEM,
149 }
150};
151
152static struct sh_flctl_platform_data nand_flash_data = {
153 .parts = nand_partition_info,
154 .nr_parts = ARRAY_SIZE(nand_partition_info),
155 .flcmncr_val = FCKSEL_E | TYPESEL_SET | NANWF_E,
156 .has_hwecc = 1,
157};
158
159static struct platform_device nand_flash_device = {
160 .name = "sh_flctl",
161 .resource = nand_flash_resources,
162 .num_resources = ARRAY_SIZE(nand_flash_resources),
163 .dev = {
164 .platform_data = &nand_flash_data,
165 },
166};
167
168#define FPGA_LCDREG 0xB4100180
169#define FPGA_BKLREG 0xB4100212
170#define FPGA_LCDREG_VAL 0x0018
171#define PORT_MSELCRB 0xA4050182
172#define PORT_HIZCRC 0xA405015C
173#define PORT_DRVCRA 0xA405018A
174#define PORT_DRVCRB 0xA405018C
175
176static int ap320_wvga_set_brightness(int brightness)
177{
178 if (brightness) {
179 gpio_set_value(gpio: GPIO_PTS3, value: 0);
180 __raw_writew(val: 0x100, FPGA_BKLREG);
181 } else {
182 __raw_writew(val: 0, FPGA_BKLREG);
183 gpio_set_value(gpio: GPIO_PTS3, value: 1);
184 }
185
186 return 0;
187}
188
189static void ap320_wvga_power_on(void)
190{
191 msleep(msecs: 100);
192
193 /* ASD AP-320/325 LCD ON */
194 __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
195}
196
197static void ap320_wvga_power_off(void)
198{
199 /* ASD AP-320/325 LCD OFF */
200 __raw_writew(val: 0, FPGA_LCDREG);
201}
202
203static const struct fb_videomode ap325rxa_lcdc_modes[] = {
204 {
205 .name = "LB070WV1",
206 .xres = 800,
207 .yres = 480,
208 .left_margin = 32,
209 .right_margin = 160,
210 .hsync_len = 8,
211 .upper_margin = 63,
212 .lower_margin = 80,
213 .vsync_len = 1,
214 .sync = 0, /* hsync and vsync are active low */
215 },
216};
217
218static struct sh_mobile_lcdc_info lcdc_info = {
219 .clock_source = LCDC_CLK_EXTERNAL,
220 .ch[0] = {
221 .chan = LCDC_CHAN_MAINLCD,
222 .fourcc = V4L2_PIX_FMT_RGB565,
223 .interface_type = RGB18,
224 .clock_divider = 1,
225 .lcd_modes = ap325rxa_lcdc_modes,
226 .num_modes = ARRAY_SIZE(ap325rxa_lcdc_modes),
227 .panel_cfg = {
228 .width = 152, /* 7.0 inch */
229 .height = 91,
230 .display_on = ap320_wvga_power_on,
231 .display_off = ap320_wvga_power_off,
232 },
233 .bl_info = {
234 .name = "sh_mobile_lcdc_bl",
235 .max_brightness = 1,
236 .set_brightness = ap320_wvga_set_brightness,
237 },
238 }
239};
240
241static struct resource lcdc_resources[] = {
242 [0] = {
243 .name = "LCDC",
244 .start = 0xfe940000, /* P4-only space */
245 .end = 0xfe942fff,
246 .flags = IORESOURCE_MEM,
247 },
248 [1] = {
249 .start = evt2irq(0x580),
250 .flags = IORESOURCE_IRQ,
251 },
252};
253
254static struct platform_device lcdc_device = {
255 .name = "sh_mobile_lcdc_fb",
256 .num_resources = ARRAY_SIZE(lcdc_resources),
257 .resource = lcdc_resources,
258 .dev = {
259 .platform_data = &lcdc_info,
260 },
261};
262
263/* Powerdown/reset gpios for CEU image sensors */
264static struct gpiod_lookup_table ov7725_gpios = {
265 .dev_id = "0-0021",
266 .table = {
267 GPIO_LOOKUP("sh7723_pfc", GPIO_PTZ5, "reset", GPIO_ACTIVE_LOW),
268 },
269};
270
271static struct ceu_platform_data ceu0_pdata = {
272 .num_subdevs = 1,
273 .subdevs = {
274 { /* [0] = ov7725 */
275 .flags = 0,
276 .bus_width = 8,
277 .bus_shift = 0,
278 .i2c_adapter_id = 0,
279 .i2c_address = 0x21,
280 },
281 },
282};
283
284static struct resource ceu_resources[] = {
285 [0] = {
286 .name = "CEU",
287 .start = 0xfe910000,
288 .end = 0xfe91009f,
289 .flags = IORESOURCE_MEM,
290 },
291 [1] = {
292 .start = evt2irq(0x880),
293 .flags = IORESOURCE_IRQ,
294 },
295};
296
297static struct platform_device ap325rxa_ceu_device = {
298 .name = "renesas-ceu",
299 .id = 0, /* "ceu.0" clock */
300 .num_resources = ARRAY_SIZE(ceu_resources),
301 .resource = ceu_resources,
302 .dev = {
303 .platform_data = &ceu0_pdata,
304 },
305};
306
307/* Fixed 3.3V regulators to be used by SDHI0, SDHI1 */
308static struct regulator_consumer_supply fixed3v3_power_consumers[] =
309{
310 REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
311 REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
312 REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
313 REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
314};
315
316static struct resource sdhi0_cn3_resources[] = {
317 [0] = {
318 .name = "SDHI0",
319 .start = 0x04ce0000,
320 .end = 0x04ce00ff,
321 .flags = IORESOURCE_MEM,
322 },
323 [1] = {
324 .start = evt2irq(0xe80),
325 .flags = IORESOURCE_IRQ,
326 },
327};
328
329static struct tmio_mmc_data sdhi0_cn3_data = {
330 .capabilities = MMC_CAP_SDIO_IRQ,
331};
332
333static struct platform_device sdhi0_cn3_device = {
334 .name = "sh_mobile_sdhi",
335 .id = 0, /* "sdhi0" clock */
336 .num_resources = ARRAY_SIZE(sdhi0_cn3_resources),
337 .resource = sdhi0_cn3_resources,
338 .dev = {
339 .platform_data = &sdhi0_cn3_data,
340 },
341};
342
343static struct resource sdhi1_cn7_resources[] = {
344 [0] = {
345 .name = "SDHI1",
346 .start = 0x04cf0000,
347 .end = 0x04cf00ff,
348 .flags = IORESOURCE_MEM,
349 },
350 [1] = {
351 .start = evt2irq(0x4e0),
352 .flags = IORESOURCE_IRQ,
353 },
354};
355
356static struct tmio_mmc_data sdhi1_cn7_data = {
357 .capabilities = MMC_CAP_SDIO_IRQ,
358};
359
360static struct platform_device sdhi1_cn7_device = {
361 .name = "sh_mobile_sdhi",
362 .id = 1, /* "sdhi1" clock */
363 .num_resources = ARRAY_SIZE(sdhi1_cn7_resources),
364 .resource = sdhi1_cn7_resources,
365 .dev = {
366 .platform_data = &sdhi1_cn7_data,
367 },
368};
369
370static struct ov772x_camera_info ov7725_info = {
371 .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
372 .edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0),
373};
374
375static struct i2c_board_info ap325rxa_i2c_devices[] __initdata = {
376 {
377 I2C_BOARD_INFO("pcf8563", 0x51),
378 },
379 {
380 I2C_BOARD_INFO("ov772x", 0x21),
381 .platform_data = &ov7725_info,
382 },
383};
384
385static struct platform_device *ap325rxa_devices[] __initdata = {
386 &smsc9118_device,
387 &ap325rxa_nor_flash_device,
388 &lcdc_device,
389 &nand_flash_device,
390 &sdhi0_cn3_device,
391 &sdhi1_cn7_device,
392};
393
394extern char ap325rxa_sdram_enter_start;
395extern char ap325rxa_sdram_enter_end;
396extern char ap325rxa_sdram_leave_start;
397extern char ap325rxa_sdram_leave_end;
398
399static int __init ap325rxa_devices_setup(void)
400{
401 /* register board specific self-refresh code */
402 sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
403 &ap325rxa_sdram_enter_start,
404 &ap325rxa_sdram_enter_end,
405 &ap325rxa_sdram_leave_start,
406 &ap325rxa_sdram_leave_end);
407
408 regulator_register_always_on(id: 0, name: "fixed-3.3V", supplies: fixed3v3_power_consumers,
409 ARRAY_SIZE(fixed3v3_power_consumers), uv: 3300000);
410 regulator_register_fixed(1, dummy_supplies, ARRAY_SIZE(dummy_supplies));
411
412 /* LD3 and LD4 LEDs */
413 gpio_request(gpio: GPIO_PTX5, NULL); /* RUN */
414 gpio_direction_output(gpio: GPIO_PTX5, value: 1);
415 gpiod_export(desc: gpio_to_desc(gpio: GPIO_PTX5), direction_may_change: 0);
416
417 gpio_request(gpio: GPIO_PTX4, NULL); /* INDICATOR */
418 gpio_direction_output(gpio: GPIO_PTX4, value: 0);
419 gpiod_export(desc: gpio_to_desc(gpio: GPIO_PTX4), direction_may_change: 0);
420
421 /* SW1 input */
422 gpio_request(gpio: GPIO_PTF7, NULL); /* MODE */
423 gpio_direction_input(gpio: GPIO_PTF7);
424 gpiod_export(desc: gpio_to_desc(gpio: GPIO_PTF7), direction_may_change: 0);
425
426 /* LCDC */
427 gpio_request(gpio: GPIO_FN_LCDD15, NULL);
428 gpio_request(gpio: GPIO_FN_LCDD14, NULL);
429 gpio_request(gpio: GPIO_FN_LCDD13, NULL);
430 gpio_request(gpio: GPIO_FN_LCDD12, NULL);
431 gpio_request(gpio: GPIO_FN_LCDD11, NULL);
432 gpio_request(gpio: GPIO_FN_LCDD10, NULL);
433 gpio_request(gpio: GPIO_FN_LCDD9, NULL);
434 gpio_request(gpio: GPIO_FN_LCDD8, NULL);
435 gpio_request(gpio: GPIO_FN_LCDD7, NULL);
436 gpio_request(gpio: GPIO_FN_LCDD6, NULL);
437 gpio_request(gpio: GPIO_FN_LCDD5, NULL);
438 gpio_request(gpio: GPIO_FN_LCDD4, NULL);
439 gpio_request(gpio: GPIO_FN_LCDD3, NULL);
440 gpio_request(gpio: GPIO_FN_LCDD2, NULL);
441 gpio_request(gpio: GPIO_FN_LCDD1, NULL);
442 gpio_request(gpio: GPIO_FN_LCDD0, NULL);
443 gpio_request(gpio: GPIO_FN_LCDLCLK_PTR, NULL);
444 gpio_request(gpio: GPIO_FN_LCDDCK, NULL);
445 gpio_request(gpio: GPIO_FN_LCDVEPWC, NULL);
446 gpio_request(gpio: GPIO_FN_LCDVCPWC, NULL);
447 gpio_request(gpio: GPIO_FN_LCDVSYN, NULL);
448 gpio_request(gpio: GPIO_FN_LCDHSYN, NULL);
449 gpio_request(gpio: GPIO_FN_LCDDISP, NULL);
450 gpio_request(gpio: GPIO_FN_LCDDON, NULL);
451
452 /* LCD backlight */
453 gpio_request(gpio: GPIO_PTS3, NULL);
454 gpio_direction_output(gpio: GPIO_PTS3, value: 1);
455
456 /* CEU */
457 gpio_request(gpio: GPIO_FN_VIO_CLK2, NULL);
458 gpio_request(gpio: GPIO_FN_VIO_VD2, NULL);
459 gpio_request(GPIO_FN_VIO_HD2, NULL);
460 gpio_request(GPIO_FN_VIO_FLD, NULL);
461 gpio_request(GPIO_FN_VIO_CKO, NULL);
462 gpio_request(GPIO_FN_VIO_D15, NULL);
463 gpio_request(GPIO_FN_VIO_D14, NULL);
464 gpio_request(GPIO_FN_VIO_D13, NULL);
465 gpio_request(GPIO_FN_VIO_D12, NULL);
466 gpio_request(GPIO_FN_VIO_D11, NULL);
467 gpio_request(GPIO_FN_VIO_D10, NULL);
468 gpio_request(GPIO_FN_VIO_D9, NULL);
469 gpio_request(GPIO_FN_VIO_D8, NULL);
470
471 gpio_request(GPIO_PTZ7, NULL);
472 gpio_direction_output(GPIO_PTZ7, 0); /* OE_CAM */
473 gpio_request(GPIO_PTZ6, NULL);
474 gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
475 gpio_request(GPIO_PTZ5, NULL);
476 gpio_direction_output(GPIO_PTZ5, 0); /* RST_CAM */
477 gpio_request(GPIO_PTZ4, NULL);
478 gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
479
480 __raw_writew(__raw_readw(PORT_MSELCRB) & ~0x0001, PORT_MSELCRB);
481
482 /* FLCTL */
483 gpio_request(GPIO_FN_FCE, NULL);
484 gpio_request(GPIO_FN_NAF7, NULL);
485 gpio_request(GPIO_FN_NAF6, NULL);
486 gpio_request(GPIO_FN_NAF5, NULL);
487 gpio_request(GPIO_FN_NAF4, NULL);
488 gpio_request(GPIO_FN_NAF3, NULL);
489 gpio_request(GPIO_FN_NAF2, NULL);
490 gpio_request(GPIO_FN_NAF1, NULL);
491 gpio_request(GPIO_FN_NAF0, NULL);
492 gpio_request(GPIO_FN_FCDE, NULL);
493 gpio_request(GPIO_FN_FOE, NULL);
494 gpio_request(GPIO_FN_FSC, NULL);
495 gpio_request(GPIO_FN_FWE, NULL);
496 gpio_request(GPIO_FN_FRB, NULL);
497
498 __raw_writew(val: 0, PORT_HIZCRC);
499 __raw_writew(val: 0xFFFF, PORT_DRVCRA);
500 __raw_writew(val: 0xFFFF, PORT_DRVCRB);
501
502 /* SDHI0 - CN3 - SD CARD */
503 gpio_request(GPIO_FN_SDHI0CD_PTD, NULL);
504 gpio_request(GPIO_FN_SDHI0WP_PTD, NULL);
505 gpio_request(GPIO_FN_SDHI0D3_PTD, NULL);
506 gpio_request(GPIO_FN_SDHI0D2_PTD, NULL);
507 gpio_request(GPIO_FN_SDHI0D1_PTD, NULL);
508 gpio_request(GPIO_FN_SDHI0D0_PTD, NULL);
509 gpio_request(GPIO_FN_SDHI0CMD_PTD, NULL);
510 gpio_request(GPIO_FN_SDHI0CLK_PTD, NULL);
511
512 /* SDHI1 - CN7 - MICRO SD CARD */
513 gpio_request(GPIO_FN_SDHI1CD, NULL);
514 gpio_request(GPIO_FN_SDHI1D3, NULL);
515 gpio_request(GPIO_FN_SDHI1D2, NULL);
516 gpio_request(GPIO_FN_SDHI1D1, NULL);
517 gpio_request(GPIO_FN_SDHI1D0, NULL);
518 gpio_request(GPIO_FN_SDHI1CMD, NULL);
519 gpio_request(GPIO_FN_SDHI1CLK, NULL);
520
521 /* Add a clock alias for ov7725 xclk source. */
522 clk_add_alias(NULL, "0-0021", "video_clk", NULL);
523
524 /* Register RSTB gpio for ov7725 camera sensor. */
525 gpiod_add_lookup_table(table: &ov7725_gpios);
526
527 i2c_register_board_info(busnum: 0, info: ap325rxa_i2c_devices,
528 ARRAY_SIZE(ap325rxa_i2c_devices));
529
530 /* Initialize CEU platform device separately to map memory first */
531 device_initialize(dev: &ap325rxa_ceu_device.dev);
532 dma_declare_coherent_memory(dev: &ap325rxa_ceu_device.dev,
533 phys_addr: ceu_dma_membase, device_addr: ceu_dma_membase,
534 CEU_BUFFER_MEMORY_SIZE);
535
536 platform_device_add(pdev: &ap325rxa_ceu_device);
537
538 return platform_add_devices(ap325rxa_devices,
539 ARRAY_SIZE(ap325rxa_devices));
540}
541arch_initcall(ap325rxa_devices_setup);
542
543/* Return the board specific boot mode pin configuration */
544static int ap325rxa_mode_pins(void)
545{
546 /* MD0=0, MD1=0, MD2=0: Clock Mode 0
547 * MD3=0: 16-bit Area0 Bus Width
548 * MD5=1: Little Endian
549 * TSTMD=1, MD8=1: Test Mode Disabled
550 */
551 return MODE_PIN5 | MODE_PIN8;
552}
553
554/* Reserve a portion of memory for CEU buffers */
555static void __init ap325rxa_mv_mem_reserve(void)
556{
557 phys_addr_t phys;
558 phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
559
560 phys = memblock_phys_alloc(size, PAGE_SIZE);
561 if (!phys)
562 panic(fmt: "Failed to allocate CEU memory\n");
563
564 memblock_phys_free(base: phys, size);
565 memblock_remove(base: phys, size);
566
567 ceu_dma_membase = phys;
568}
569
570static struct sh_machine_vector mv_ap325rxa __initmv = {
571 .mv_name = "AP-325RXA",
572 .mv_mode_pins = ap325rxa_mode_pins,
573 .mv_mem_reserve = ap325rxa_mv_mem_reserve,
574};
575

source code of linux/arch/sh/boards/mach-ap325rxa/setup.c