xref: /OK3568_Linux_fs/kernel/arch/mips/alchemy/board-gpr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * GPR board platform device registration (Au1550)
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2010 Wolfgang Grandegger <wg@denx.de>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/delay.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/platform_device.h>
13*4882a593Smuzhiyun #include <linux/pm.h>
14*4882a593Smuzhiyun #include <linux/mtd/partitions.h>
15*4882a593Smuzhiyun #include <linux/mtd/physmap.h>
16*4882a593Smuzhiyun #include <linux/leds.h>
17*4882a593Smuzhiyun #include <linux/gpio.h>
18*4882a593Smuzhiyun #include <linux/i2c.h>
19*4882a593Smuzhiyun #include <linux/platform_data/i2c-gpio.h>
20*4882a593Smuzhiyun #include <linux/gpio/machine.h>
21*4882a593Smuzhiyun #include <asm/bootinfo.h>
22*4882a593Smuzhiyun #include <asm/idle.h>
23*4882a593Smuzhiyun #include <asm/reboot.h>
24*4882a593Smuzhiyun #include <asm/setup.h>
25*4882a593Smuzhiyun #include <asm/mach-au1x00/au1000.h>
26*4882a593Smuzhiyun #include <asm/mach-au1x00/gpio-au1000.h>
27*4882a593Smuzhiyun #include <prom.h>
28*4882a593Smuzhiyun 
get_system_type(void)29*4882a593Smuzhiyun const char *get_system_type(void)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	return "GPR";
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
prom_putchar(char c)34*4882a593Smuzhiyun void prom_putchar(char c)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
gpr_reset(char * c)39*4882a593Smuzhiyun static void gpr_reset(char *c)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	/* switch System-LED to orange (red# and green# on) */
42*4882a593Smuzhiyun 	alchemy_gpio_direction_output(4, 0);
43*4882a593Smuzhiyun 	alchemy_gpio_direction_output(5, 0);
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	/* trigger watchdog to reset board in 200ms */
46*4882a593Smuzhiyun 	printk(KERN_EMERG "Triggering watchdog soft reset...\n");
47*4882a593Smuzhiyun 	raw_local_irq_disable();
48*4882a593Smuzhiyun 	alchemy_gpio_direction_output(1, 0);
49*4882a593Smuzhiyun 	udelay(1);
50*4882a593Smuzhiyun 	alchemy_gpio_set_value(1, 1);
51*4882a593Smuzhiyun 	while (1)
52*4882a593Smuzhiyun 		cpu_wait();
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
gpr_power_off(void)55*4882a593Smuzhiyun static void gpr_power_off(void)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	while (1)
58*4882a593Smuzhiyun 		cpu_wait();
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
board_setup(void)61*4882a593Smuzhiyun void __init board_setup(void)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	printk(KERN_INFO "Trapeze ITS GPR board\n");
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	pm_power_off = gpr_power_off;
66*4882a593Smuzhiyun 	_machine_halt = gpr_power_off;
67*4882a593Smuzhiyun 	_machine_restart = gpr_reset;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	/* Enable UART1/3 */
70*4882a593Smuzhiyun 	alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
71*4882a593Smuzhiyun 	alchemy_uart_enable(AU1000_UART1_PHYS_ADDR);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/* Take away Reset of UMTS-card */
74*4882a593Smuzhiyun 	alchemy_gpio_direction_output(215, 1);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun  * Watchdog
79*4882a593Smuzhiyun  */
80*4882a593Smuzhiyun static struct resource gpr_wdt_resource[] = {
81*4882a593Smuzhiyun 	[0] = {
82*4882a593Smuzhiyun 		.start	= 1,
83*4882a593Smuzhiyun 		.end	= 1,
84*4882a593Smuzhiyun 		.name	= "gpr-adm6320-wdt",
85*4882a593Smuzhiyun 		.flags	= IORESOURCE_IRQ,
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun static struct platform_device gpr_wdt_device = {
90*4882a593Smuzhiyun 	.name = "adm6320-wdt",
91*4882a593Smuzhiyun 	.id = 0,
92*4882a593Smuzhiyun 	.num_resources = ARRAY_SIZE(gpr_wdt_resource),
93*4882a593Smuzhiyun 	.resource = gpr_wdt_resource,
94*4882a593Smuzhiyun };
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun /*
97*4882a593Smuzhiyun  * FLASH
98*4882a593Smuzhiyun  *
99*4882a593Smuzhiyun  * 0x00000000-0x00200000 : "kernel"
100*4882a593Smuzhiyun  * 0x00200000-0x00a00000 : "rootfs"
101*4882a593Smuzhiyun  * 0x01d00000-0x01f00000 : "config"
102*4882a593Smuzhiyun  * 0x01c00000-0x01d00000 : "yamon"
103*4882a593Smuzhiyun  * 0x01d00000-0x01d40000 : "yamon env vars"
104*4882a593Smuzhiyun  * 0x00000000-0x00a00000 : "kernel+rootfs"
105*4882a593Smuzhiyun  */
106*4882a593Smuzhiyun static struct mtd_partition gpr_mtd_partitions[] = {
107*4882a593Smuzhiyun 	{
108*4882a593Smuzhiyun 		.name	= "kernel",
109*4882a593Smuzhiyun 		.size	= 0x00200000,
110*4882a593Smuzhiyun 		.offset = 0,
111*4882a593Smuzhiyun 	},
112*4882a593Smuzhiyun 	{
113*4882a593Smuzhiyun 		.name	= "rootfs",
114*4882a593Smuzhiyun 		.size	= 0x00800000,
115*4882a593Smuzhiyun 		.offset = MTDPART_OFS_APPEND,
116*4882a593Smuzhiyun 		.mask_flags = MTD_WRITEABLE,
117*4882a593Smuzhiyun 	},
118*4882a593Smuzhiyun 	{
119*4882a593Smuzhiyun 		.name	= "config",
120*4882a593Smuzhiyun 		.size	= 0x00200000,
121*4882a593Smuzhiyun 		.offset = 0x01d00000,
122*4882a593Smuzhiyun 	},
123*4882a593Smuzhiyun 	{
124*4882a593Smuzhiyun 		.name	= "yamon",
125*4882a593Smuzhiyun 		.size	= 0x00100000,
126*4882a593Smuzhiyun 		.offset = 0x01c00000,
127*4882a593Smuzhiyun 	},
128*4882a593Smuzhiyun 	{
129*4882a593Smuzhiyun 		.name	= "yamon env vars",
130*4882a593Smuzhiyun 		.size	= 0x00040000,
131*4882a593Smuzhiyun 		.offset = MTDPART_OFS_APPEND,
132*4882a593Smuzhiyun 	},
133*4882a593Smuzhiyun 	{
134*4882a593Smuzhiyun 		.name	= "kernel+rootfs",
135*4882a593Smuzhiyun 		.size	= 0x00a00000,
136*4882a593Smuzhiyun 		.offset = 0,
137*4882a593Smuzhiyun 	},
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun static struct physmap_flash_data gpr_flash_data = {
141*4882a593Smuzhiyun 	.width		= 4,
142*4882a593Smuzhiyun 	.nr_parts	= ARRAY_SIZE(gpr_mtd_partitions),
143*4882a593Smuzhiyun 	.parts		= gpr_mtd_partitions,
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun static struct resource gpr_mtd_resource = {
147*4882a593Smuzhiyun 	.start	= 0x1e000000,
148*4882a593Smuzhiyun 	.end	= 0x1fffffff,
149*4882a593Smuzhiyun 	.flags	= IORESOURCE_MEM,
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static struct platform_device gpr_mtd_device = {
153*4882a593Smuzhiyun 	.name		= "physmap-flash",
154*4882a593Smuzhiyun 	.dev		= {
155*4882a593Smuzhiyun 		.platform_data	= &gpr_flash_data,
156*4882a593Smuzhiyun 	},
157*4882a593Smuzhiyun 	.num_resources	= 1,
158*4882a593Smuzhiyun 	.resource	= &gpr_mtd_resource,
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun  * LEDs
163*4882a593Smuzhiyun  */
164*4882a593Smuzhiyun static const struct gpio_led gpr_gpio_leds[] = {
165*4882a593Smuzhiyun 	{	/* green */
166*4882a593Smuzhiyun 		.name			= "gpr:green",
167*4882a593Smuzhiyun 		.gpio			= 4,
168*4882a593Smuzhiyun 		.active_low		= 1,
169*4882a593Smuzhiyun 	},
170*4882a593Smuzhiyun 	{	/* red */
171*4882a593Smuzhiyun 		.name			= "gpr:red",
172*4882a593Smuzhiyun 		.gpio			= 5,
173*4882a593Smuzhiyun 		.active_low		= 1,
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun };
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static struct gpio_led_platform_data gpr_led_data = {
178*4882a593Smuzhiyun 	.num_leds = ARRAY_SIZE(gpr_gpio_leds),
179*4882a593Smuzhiyun 	.leds = gpr_gpio_leds,
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun static struct platform_device gpr_led_devices = {
183*4882a593Smuzhiyun 	.name = "leds-gpio",
184*4882a593Smuzhiyun 	.id = -1,
185*4882a593Smuzhiyun 	.dev = {
186*4882a593Smuzhiyun 		.platform_data = &gpr_led_data,
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun  * I2C
192*4882a593Smuzhiyun  */
193*4882a593Smuzhiyun static struct gpiod_lookup_table gpr_i2c_gpiod_table = {
194*4882a593Smuzhiyun 	.dev_id = "i2c-gpio",
195*4882a593Smuzhiyun 	.table = {
196*4882a593Smuzhiyun 		/*
197*4882a593Smuzhiyun 		 * This should be on "GPIO2" which has base at 200 so
198*4882a593Smuzhiyun 		 * the global numbers 209 and 210 should correspond to
199*4882a593Smuzhiyun 		 * local offsets 9 and 10.
200*4882a593Smuzhiyun 		 */
201*4882a593Smuzhiyun 		GPIO_LOOKUP_IDX("alchemy-gpio2", 9, NULL, 0,
202*4882a593Smuzhiyun 				GPIO_ACTIVE_HIGH),
203*4882a593Smuzhiyun 		GPIO_LOOKUP_IDX("alchemy-gpio2", 10, NULL, 1,
204*4882a593Smuzhiyun 				GPIO_ACTIVE_HIGH),
205*4882a593Smuzhiyun 	},
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun static struct i2c_gpio_platform_data gpr_i2c_data = {
209*4882a593Smuzhiyun 	/*
210*4882a593Smuzhiyun 	 * The open drain mode is hardwired somewhere or an electrical
211*4882a593Smuzhiyun 	 * property of the alchemy GPIO controller.
212*4882a593Smuzhiyun 	 */
213*4882a593Smuzhiyun 	.sda_is_open_drain	= 1,
214*4882a593Smuzhiyun 	.scl_is_open_drain	= 1,
215*4882a593Smuzhiyun 	.udelay			= 2,		/* ~100 kHz */
216*4882a593Smuzhiyun 	.timeout		= HZ,
217*4882a593Smuzhiyun };
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun static struct platform_device gpr_i2c_device = {
220*4882a593Smuzhiyun 	.name			= "i2c-gpio",
221*4882a593Smuzhiyun 	.id			= -1,
222*4882a593Smuzhiyun 	.dev.platform_data	= &gpr_i2c_data,
223*4882a593Smuzhiyun };
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun static struct i2c_board_info gpr_i2c_info[] __initdata = {
226*4882a593Smuzhiyun 	{
227*4882a593Smuzhiyun 		I2C_BOARD_INFO("lm83", 0x18),
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun };
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun static struct resource alchemy_pci_host_res[] = {
234*4882a593Smuzhiyun 	[0] = {
235*4882a593Smuzhiyun 		.start	= AU1500_PCI_PHYS_ADDR,
236*4882a593Smuzhiyun 		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
237*4882a593Smuzhiyun 		.flags	= IORESOURCE_MEM,
238*4882a593Smuzhiyun 	},
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun 
gpr_map_pci_irq(const struct pci_dev * d,u8 slot,u8 pin)241*4882a593Smuzhiyun static int gpr_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	if ((slot == 0) && (pin == 1))
244*4882a593Smuzhiyun 		return AU1550_PCI_INTA;
245*4882a593Smuzhiyun 	else if ((slot == 0) && (pin == 2))
246*4882a593Smuzhiyun 		return AU1550_PCI_INTB;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	return 0xff;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun static struct alchemy_pci_platdata gpr_pci_pd = {
252*4882a593Smuzhiyun 	.board_map_irq	= gpr_map_pci_irq,
253*4882a593Smuzhiyun 	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
254*4882a593Smuzhiyun 			  PCI_CONFIG_CH |
255*4882a593Smuzhiyun #if defined(__MIPSEB__)
256*4882a593Smuzhiyun 			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
257*4882a593Smuzhiyun #else
258*4882a593Smuzhiyun 			  0,
259*4882a593Smuzhiyun #endif
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun static struct platform_device gpr_pci_host_dev = {
263*4882a593Smuzhiyun 	.dev.platform_data = &gpr_pci_pd,
264*4882a593Smuzhiyun 	.name		= "alchemy-pci",
265*4882a593Smuzhiyun 	.id		= 0,
266*4882a593Smuzhiyun 	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
267*4882a593Smuzhiyun 	.resource	= alchemy_pci_host_res,
268*4882a593Smuzhiyun };
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun static struct platform_device *gpr_devices[] __initdata = {
271*4882a593Smuzhiyun 	&gpr_wdt_device,
272*4882a593Smuzhiyun 	&gpr_mtd_device,
273*4882a593Smuzhiyun 	&gpr_i2c_device,
274*4882a593Smuzhiyun 	&gpr_led_devices,
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun 
gpr_pci_init(void)277*4882a593Smuzhiyun static int __init gpr_pci_init(void)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	return platform_device_register(&gpr_pci_host_dev);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun /* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
282*4882a593Smuzhiyun arch_initcall(gpr_pci_init);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 
gpr_dev_init(void)285*4882a593Smuzhiyun static int __init gpr_dev_init(void)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	gpiod_add_lookup_table(&gpr_i2c_gpiod_table);
288*4882a593Smuzhiyun 	i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices));
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun device_initcall(gpr_dev_init);
293