162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Renesas Technology Sales RTS7751R2D Support.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2002 - 2006 Atom Create Engineering Co., Ltd.
662306a36Sopenharmony_ci * Copyright (C) 2004 - 2007 Paul Mundt
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/init.h>
962306a36Sopenharmony_ci#include <linux/platform_device.h>
1062306a36Sopenharmony_ci#include <linux/mtd/mtd.h>
1162306a36Sopenharmony_ci#include <linux/mtd/partitions.h>
1262306a36Sopenharmony_ci#include <linux/mtd/physmap.h>
1362306a36Sopenharmony_ci#include <linux/ata_platform.h>
1462306a36Sopenharmony_ci#include <linux/sm501.h>
1562306a36Sopenharmony_ci#include <linux/sm501-regs.h>
1662306a36Sopenharmony_ci#include <linux/pm.h>
1762306a36Sopenharmony_ci#include <linux/fb.h>
1862306a36Sopenharmony_ci#include <linux/spi/spi.h>
1962306a36Sopenharmony_ci#include <linux/spi/spi_bitbang.h>
2062306a36Sopenharmony_ci#include <asm/machvec.h>
2162306a36Sopenharmony_ci#include <mach/r2d.h>
2262306a36Sopenharmony_ci#include <asm/io.h>
2362306a36Sopenharmony_ci#include <asm/io_trapped.h>
2462306a36Sopenharmony_ci#include <asm/spi.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic struct resource cf_ide_resources[] = {
2762306a36Sopenharmony_ci	[0] = {
2862306a36Sopenharmony_ci		.start	= PA_AREA5_IO + 0x1000,
2962306a36Sopenharmony_ci		.end	= PA_AREA5_IO + 0x1000 + 0x10 - 0x2,
3062306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
3162306a36Sopenharmony_ci	},
3262306a36Sopenharmony_ci	[1] = {
3362306a36Sopenharmony_ci		.start	= PA_AREA5_IO + 0x80c,
3462306a36Sopenharmony_ci		.end	= PA_AREA5_IO + 0x80c,
3562306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
3662306a36Sopenharmony_ci	},
3762306a36Sopenharmony_ci#ifndef CONFIG_RTS7751R2D_1 /* For R2D-1 polling is preferred */
3862306a36Sopenharmony_ci	[2] = {
3962306a36Sopenharmony_ci		.start	= IRQ_CF_IDE,
4062306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
4162306a36Sopenharmony_ci	},
4262306a36Sopenharmony_ci#endif
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic struct pata_platform_info pata_info = {
4662306a36Sopenharmony_ci	.ioport_shift	= 1,
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic struct platform_device cf_ide_device  = {
5062306a36Sopenharmony_ci	.name		= "pata_platform",
5162306a36Sopenharmony_ci	.id		= -1,
5262306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(cf_ide_resources),
5362306a36Sopenharmony_ci	.resource	= cf_ide_resources,
5462306a36Sopenharmony_ci	.dev	= {
5562306a36Sopenharmony_ci		.platform_data	= &pata_info,
5662306a36Sopenharmony_ci	},
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic struct spi_board_info spi_bus[] = {
6062306a36Sopenharmony_ci	{
6162306a36Sopenharmony_ci		.modalias	= "rtc-r9701",
6262306a36Sopenharmony_ci		.max_speed_hz	= 1000000,
6362306a36Sopenharmony_ci		.mode		= SPI_MODE_3,
6462306a36Sopenharmony_ci	},
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic void r2d_chip_select(struct sh_spi_info *spi, int cs, int state)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	BUG_ON(cs != 0);  /* Single Epson RTC-9701JE attached on CS0 */
7062306a36Sopenharmony_ci	__raw_writew(state == BITBANG_CS_ACTIVE, PA_RTCCE);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic struct sh_spi_info spi_info = {
7462306a36Sopenharmony_ci	.num_chipselect = 1,
7562306a36Sopenharmony_ci	.chip_select = r2d_chip_select,
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic struct resource spi_sh_sci_resources[] = {
7962306a36Sopenharmony_ci	{
8062306a36Sopenharmony_ci		.start	= 0xffe00000,
8162306a36Sopenharmony_ci		.end	= 0xffe0001f,
8262306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
8362306a36Sopenharmony_ci	},
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic struct platform_device spi_sh_sci_device  = {
8762306a36Sopenharmony_ci	.name		= "spi_sh_sci",
8862306a36Sopenharmony_ci	.id		= -1,
8962306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(spi_sh_sci_resources),
9062306a36Sopenharmony_ci	.resource	= spi_sh_sci_resources,
9162306a36Sopenharmony_ci	.dev	= {
9262306a36Sopenharmony_ci		.platform_data	= &spi_info,
9362306a36Sopenharmony_ci	},
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic struct resource heartbeat_resources[] = {
9762306a36Sopenharmony_ci	[0] = {
9862306a36Sopenharmony_ci		.start	= PA_OUTPORT,
9962306a36Sopenharmony_ci		.end	= PA_OUTPORT,
10062306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
10162306a36Sopenharmony_ci	},
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic struct platform_device heartbeat_device = {
10562306a36Sopenharmony_ci	.name		= "heartbeat",
10662306a36Sopenharmony_ci	.id		= -1,
10762306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(heartbeat_resources),
10862306a36Sopenharmony_ci	.resource	= heartbeat_resources,
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic struct resource sm501_resources[] = {
11262306a36Sopenharmony_ci	[0]	= {
11362306a36Sopenharmony_ci		.start	= 0x10000000,
11462306a36Sopenharmony_ci		.end	= 0x13e00000 - 1,
11562306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
11662306a36Sopenharmony_ci	},
11762306a36Sopenharmony_ci	[1]	= {
11862306a36Sopenharmony_ci		.start	= 0x13e00000,
11962306a36Sopenharmony_ci		.end	= 0x13ffffff,
12062306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
12162306a36Sopenharmony_ci	},
12262306a36Sopenharmony_ci	[2]	= {
12362306a36Sopenharmony_ci		.start	= IRQ_VOYAGER,
12462306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
12562306a36Sopenharmony_ci	},
12662306a36Sopenharmony_ci};
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic struct fb_videomode sm501_default_mode = {
12962306a36Sopenharmony_ci	.pixclock	= 35714,
13062306a36Sopenharmony_ci	.xres		= 640,
13162306a36Sopenharmony_ci	.yres		= 480,
13262306a36Sopenharmony_ci	.left_margin	= 105,
13362306a36Sopenharmony_ci	.right_margin	= 50,
13462306a36Sopenharmony_ci	.upper_margin	= 35,
13562306a36Sopenharmony_ci	.lower_margin	= 0,
13662306a36Sopenharmony_ci	.hsync_len	= 96,
13762306a36Sopenharmony_ci	.vsync_len	= 2,
13862306a36Sopenharmony_ci	.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
13962306a36Sopenharmony_ci};
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic struct sm501_platdata_fbsub sm501_pdata_fbsub_pnl = {
14262306a36Sopenharmony_ci	.def_bpp	= 16,
14362306a36Sopenharmony_ci	.def_mode	= &sm501_default_mode,
14462306a36Sopenharmony_ci	.flags		= SM501FB_FLAG_USE_INIT_MODE |
14562306a36Sopenharmony_ci			  SM501FB_FLAG_USE_HWCURSOR |
14662306a36Sopenharmony_ci			  SM501FB_FLAG_USE_HWACCEL |
14762306a36Sopenharmony_ci			  SM501FB_FLAG_DISABLE_AT_EXIT,
14862306a36Sopenharmony_ci};
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic struct sm501_platdata_fbsub sm501_pdata_fbsub_crt = {
15162306a36Sopenharmony_ci	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
15262306a36Sopenharmony_ci			   SM501FB_FLAG_USE_HWCURSOR |
15362306a36Sopenharmony_ci			   SM501FB_FLAG_USE_HWACCEL |
15462306a36Sopenharmony_ci			   SM501FB_FLAG_DISABLE_AT_EXIT),
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci};
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic struct sm501_platdata_fb sm501_fb_pdata = {
15962306a36Sopenharmony_ci	.fb_route	= SM501_FB_OWN,
16062306a36Sopenharmony_ci	.fb_crt		= &sm501_pdata_fbsub_crt,
16162306a36Sopenharmony_ci	.fb_pnl		= &sm501_pdata_fbsub_pnl,
16262306a36Sopenharmony_ci	.flags		= SM501_FBPD_SWAP_FB_ENDIAN,
16362306a36Sopenharmony_ci};
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic struct sm501_initdata sm501_initdata = {
16662306a36Sopenharmony_ci	.devices	= SM501_USE_USB_HOST | SM501_USE_UART0,
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic struct sm501_platdata sm501_platform_data = {
17062306a36Sopenharmony_ci	.init		= &sm501_initdata,
17162306a36Sopenharmony_ci	.fb		= &sm501_fb_pdata,
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic struct platform_device sm501_device = {
17562306a36Sopenharmony_ci	.name		= "sm501",
17662306a36Sopenharmony_ci	.id		= -1,
17762306a36Sopenharmony_ci	.dev		= {
17862306a36Sopenharmony_ci		.platform_data	= &sm501_platform_data,
17962306a36Sopenharmony_ci	},
18062306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(sm501_resources),
18162306a36Sopenharmony_ci	.resource	= sm501_resources,
18262306a36Sopenharmony_ci};
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic struct mtd_partition r2d_partitions[] = {
18562306a36Sopenharmony_ci	{
18662306a36Sopenharmony_ci		.name		= "U-Boot",
18762306a36Sopenharmony_ci		.offset		= 0x00000000,
18862306a36Sopenharmony_ci		.size		= 0x00040000,
18962306a36Sopenharmony_ci		.mask_flags	= MTD_WRITEABLE,
19062306a36Sopenharmony_ci	}, {
19162306a36Sopenharmony_ci		.name		= "Environment",
19262306a36Sopenharmony_ci		.offset		= MTDPART_OFS_NXTBLK,
19362306a36Sopenharmony_ci		.size		= 0x00040000,
19462306a36Sopenharmony_ci		.mask_flags	= MTD_WRITEABLE,
19562306a36Sopenharmony_ci	}, {
19662306a36Sopenharmony_ci		.name		= "Kernel",
19762306a36Sopenharmony_ci		.offset		= MTDPART_OFS_NXTBLK,
19862306a36Sopenharmony_ci		.size		= 0x001c0000,
19962306a36Sopenharmony_ci	}, {
20062306a36Sopenharmony_ci		.name		= "Flash_FS",
20162306a36Sopenharmony_ci		.offset		= MTDPART_OFS_NXTBLK,
20262306a36Sopenharmony_ci		.size		= MTDPART_SIZ_FULL,
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic struct physmap_flash_data flash_data = {
20762306a36Sopenharmony_ci	.width		= 2,
20862306a36Sopenharmony_ci	.nr_parts	= ARRAY_SIZE(r2d_partitions),
20962306a36Sopenharmony_ci	.parts		= r2d_partitions,
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic struct resource flash_resource = {
21362306a36Sopenharmony_ci	.start		= 0x00000000,
21462306a36Sopenharmony_ci	.end		= 0x02000000,
21562306a36Sopenharmony_ci	.flags		= IORESOURCE_MEM,
21662306a36Sopenharmony_ci};
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic struct platform_device flash_device = {
21962306a36Sopenharmony_ci	.name		= "physmap-flash",
22062306a36Sopenharmony_ci	.id		= -1,
22162306a36Sopenharmony_ci	.resource	= &flash_resource,
22262306a36Sopenharmony_ci	.num_resources	= 1,
22362306a36Sopenharmony_ci	.dev		= {
22462306a36Sopenharmony_ci		.platform_data = &flash_data,
22562306a36Sopenharmony_ci	},
22662306a36Sopenharmony_ci};
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic struct platform_device *rts7751r2d_devices[] __initdata = {
22962306a36Sopenharmony_ci	&sm501_device,
23062306a36Sopenharmony_ci	&heartbeat_device,
23162306a36Sopenharmony_ci	&spi_sh_sci_device,
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci/*
23562306a36Sopenharmony_ci * The CF is connected with a 16-bit bus where 8-bit operations are
23662306a36Sopenharmony_ci * unsupported. The linux ata driver is however using 8-bit operations, so
23762306a36Sopenharmony_ci * insert a trapped io filter to convert 8-bit operations into 16-bit.
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_cistatic struct trapped_io cf_trapped_io = {
24062306a36Sopenharmony_ci	.resource		= cf_ide_resources,
24162306a36Sopenharmony_ci	.num_resources		= 2,
24262306a36Sopenharmony_ci	.minimum_bus_width	= 16,
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic int __init rts7751r2d_devices_setup(void)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	if (register_trapped_io(&cf_trapped_io) == 0)
24862306a36Sopenharmony_ci		platform_device_register(&cf_ide_device);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if (mach_is_r2d_plus())
25162306a36Sopenharmony_ci		platform_device_register(&flash_device);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return platform_add_devices(rts7751r2d_devices,
25662306a36Sopenharmony_ci				    ARRAY_SIZE(rts7751r2d_devices));
25762306a36Sopenharmony_ci}
25862306a36Sopenharmony_cidevice_initcall(rts7751r2d_devices_setup);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic void rts7751r2d_power_off(void)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	__raw_writew(0x0001, PA_POWOFF);
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci/*
26662306a36Sopenharmony_ci * Initialize the board
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_cistatic void __init rts7751r2d_setup(char **cmdline_p)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	void __iomem *sm501_reg;
27162306a36Sopenharmony_ci	u16 ver = __raw_readw(PA_VERREG);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	printk(KERN_INFO "FPGA version:%d (revision:%d)\n",
27662306a36Sopenharmony_ci					(ver >> 4) & 0xf, ver & 0xf);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	__raw_writew(0x0000, PA_OUTPORT);
27962306a36Sopenharmony_ci	pm_power_off = rts7751r2d_power_off;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* sm501 dram configuration:
28262306a36Sopenharmony_ci	 * ColSizeX = 11 - External Memory Column Size: 256 words.
28362306a36Sopenharmony_ci	 * APX = 1 - External Memory Active to Pre-Charge Delay: 7 clocks.
28462306a36Sopenharmony_ci	 * RstX = 1 - External Memory Reset: Normal.
28562306a36Sopenharmony_ci	 * Rfsh = 1 - Local Memory Refresh to Command Delay: 12 clocks.
28662306a36Sopenharmony_ci	 * BwC =  1 - Local Memory Block Write Cycle Time: 2 clocks.
28762306a36Sopenharmony_ci	 * BwP =  1 - Local Memory Block Write to Pre-Charge Delay: 1 clock.
28862306a36Sopenharmony_ci	 * AP = 1 - Internal Memory Active to Pre-Charge Delay: 7 clocks.
28962306a36Sopenharmony_ci	 * Rst = 1 - Internal Memory Reset: Normal.
29062306a36Sopenharmony_ci	 * RA = 1 - Internal Memory Remain in Active State: Do not remain.
29162306a36Sopenharmony_ci	 */
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	sm501_reg = (void __iomem *)0xb3e00000 + SM501_DRAM_CONTROL;
29462306a36Sopenharmony_ci	writel(readl(sm501_reg) | 0x00f107c0, sm501_reg);
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci/*
29862306a36Sopenharmony_ci * The Machine Vector
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_cistatic struct sh_machine_vector mv_rts7751r2d __initmv = {
30162306a36Sopenharmony_ci	.mv_name		= "RTS7751R2D",
30262306a36Sopenharmony_ci	.mv_setup		= rts7751r2d_setup,
30362306a36Sopenharmony_ci	.mv_init_irq		= init_rts7751r2d_IRQ,
30462306a36Sopenharmony_ci	.mv_irq_demux		= rts7751r2d_irq_demux,
30562306a36Sopenharmony_ci};
306