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