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