1/* 2 * GPR board platform device registration (Au1550) 3 * 4 * Copyright (C) 2010 Wolfgang Grandegger <wg@denx.de> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include <linux/delay.h> 22#include <linux/init.h> 23#include <linux/interrupt.h> 24#include <linux/kernel.h> 25#include <linux/platform_device.h> 26#include <linux/pm.h> 27#include <linux/mtd/partitions.h> 28#include <linux/mtd/physmap.h> 29#include <linux/leds.h> 30#include <linux/gpio.h> 31#include <linux/i2c.h> 32#include <linux/i2c-gpio.h> 33#include <asm/bootinfo.h> 34#include <asm/idle.h> 35#include <asm/reboot.h> 36#include <asm/mach-au1x00/au1000.h> 37#include <prom.h> 38 39const char *get_system_type(void) 40{ 41 return "GPR"; 42} 43 44void __init prom_init(void) 45{ 46 unsigned char *memsize_str; 47 unsigned long memsize; 48 49 prom_argc = fw_arg0; 50 prom_argv = (char **)fw_arg1; 51 prom_envp = (char **)fw_arg2; 52 53 prom_init_cmdline(); 54 55 memsize_str = prom_getenv("memsize"); 56 if (!memsize_str || kstrtoul(memsize_str, 0, &memsize)) 57 memsize = 0x04000000; 58 add_memory_region(0, memsize, BOOT_MEM_RAM); 59} 60 61void prom_putchar(unsigned char c) 62{ 63 alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c); 64} 65 66static void gpr_reset(char *c) 67{ 68 /* switch System-LED to orange (red# and green# on) */ 69 alchemy_gpio_direction_output(4, 0); 70 alchemy_gpio_direction_output(5, 0); 71 72 /* trigger watchdog to reset board in 200ms */ 73 printk(KERN_EMERG "Triggering watchdog soft reset...\n"); 74 raw_local_irq_disable(); 75 alchemy_gpio_direction_output(1, 0); 76 udelay(1); 77 alchemy_gpio_set_value(1, 1); 78 while (1) 79 cpu_wait(); 80} 81 82static void gpr_power_off(void) 83{ 84 while (1) 85 cpu_wait(); 86} 87 88void __init board_setup(void) 89{ 90 printk(KERN_INFO "Trapeze ITS GPR board\n"); 91 92 pm_power_off = gpr_power_off; 93 _machine_halt = gpr_power_off; 94 _machine_restart = gpr_reset; 95 96 /* Enable UART1/3 */ 97 alchemy_uart_enable(AU1000_UART3_PHYS_ADDR); 98 alchemy_uart_enable(AU1000_UART1_PHYS_ADDR); 99 100 /* Take away Reset of UMTS-card */ 101 alchemy_gpio_direction_output(215, 1); 102} 103 104/* 105 * Watchdog 106 */ 107static struct resource gpr_wdt_resource[] = { 108 [0] = { 109 .start = 1, 110 .end = 1, 111 .name = "gpr-adm6320-wdt", 112 .flags = IORESOURCE_IRQ, 113 } 114}; 115 116static struct platform_device gpr_wdt_device = { 117 .name = "adm6320-wdt", 118 .id = 0, 119 .num_resources = ARRAY_SIZE(gpr_wdt_resource), 120 .resource = gpr_wdt_resource, 121}; 122 123/* 124 * FLASH 125 * 126 * 0x00000000-0x00200000 : "kernel" 127 * 0x00200000-0x00a00000 : "rootfs" 128 * 0x01d00000-0x01f00000 : "config" 129 * 0x01c00000-0x01d00000 : "yamon" 130 * 0x01d00000-0x01d40000 : "yamon env vars" 131 * 0x00000000-0x00a00000 : "kernel+rootfs" 132 */ 133static struct mtd_partition gpr_mtd_partitions[] = { 134 { 135 .name = "kernel", 136 .size = 0x00200000, 137 .offset = 0, 138 }, 139 { 140 .name = "rootfs", 141 .size = 0x00800000, 142 .offset = MTDPART_OFS_APPEND, 143 .mask_flags = MTD_WRITEABLE, 144 }, 145 { 146 .name = "config", 147 .size = 0x00200000, 148 .offset = 0x01d00000, 149 }, 150 { 151 .name = "yamon", 152 .size = 0x00100000, 153 .offset = 0x01c00000, 154 }, 155 { 156 .name = "yamon env vars", 157 .size = 0x00040000, 158 .offset = MTDPART_OFS_APPEND, 159 }, 160 { 161 .name = "kernel+rootfs", 162 .size = 0x00a00000, 163 .offset = 0, 164 }, 165}; 166 167static struct physmap_flash_data gpr_flash_data = { 168 .width = 4, 169 .nr_parts = ARRAY_SIZE(gpr_mtd_partitions), 170 .parts = gpr_mtd_partitions, 171}; 172 173static struct resource gpr_mtd_resource = { 174 .start = 0x1e000000, 175 .end = 0x1fffffff, 176 .flags = IORESOURCE_MEM, 177}; 178 179static struct platform_device gpr_mtd_device = { 180 .name = "physmap-flash", 181 .dev = { 182 .platform_data = &gpr_flash_data, 183 }, 184 .num_resources = 1, 185 .resource = &gpr_mtd_resource, 186}; 187 188/* 189 * LEDs 190 */ 191static struct gpio_led gpr_gpio_leds[] = { 192 { /* green */ 193 .name = "gpr:green", 194 .gpio = 4, 195 .active_low = 1, 196 }, 197 { /* red */ 198 .name = "gpr:red", 199 .gpio = 5, 200 .active_low = 1, 201 } 202}; 203 204static struct gpio_led_platform_data gpr_led_data = { 205 .num_leds = ARRAY_SIZE(gpr_gpio_leds), 206 .leds = gpr_gpio_leds, 207}; 208 209static struct platform_device gpr_led_devices = { 210 .name = "leds-gpio", 211 .id = -1, 212 .dev = { 213 .platform_data = &gpr_led_data, 214 } 215}; 216 217/* 218 * I2C 219 */ 220static struct i2c_gpio_platform_data gpr_i2c_data = { 221 .sda_pin = 209, 222 .sda_is_open_drain = 1, 223 .scl_pin = 210, 224 .scl_is_open_drain = 1, 225 .udelay = 2, /* ~100 kHz */ 226 .timeout = HZ, 227}; 228 229static struct platform_device gpr_i2c_device = { 230 .name = "i2c-gpio", 231 .id = -1, 232 .dev.platform_data = &gpr_i2c_data, 233}; 234 235static struct i2c_board_info gpr_i2c_info[] __initdata = { 236 { 237 I2C_BOARD_INFO("lm83", 0x18), 238 .type = "lm83" 239 } 240}; 241 242 243 244static struct resource alchemy_pci_host_res[] = { 245 [0] = { 246 .start = AU1500_PCI_PHYS_ADDR, 247 .end = AU1500_PCI_PHYS_ADDR + 0xfff, 248 .flags = IORESOURCE_MEM, 249 }, 250}; 251 252static int gpr_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) 253{ 254 if ((slot == 0) && (pin == 1)) 255 return AU1550_PCI_INTA; 256 else if ((slot == 0) && (pin == 2)) 257 return AU1550_PCI_INTB; 258 259 return 0xff; 260} 261 262static struct alchemy_pci_platdata gpr_pci_pd = { 263 .board_map_irq = gpr_map_pci_irq, 264 .pci_cfg_set = PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H | 265 PCI_CONFIG_CH | 266#if defined(__MIPSEB__) 267 PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM, 268#else 269 0, 270#endif 271}; 272 273static struct platform_device gpr_pci_host_dev = { 274 .dev.platform_data = &gpr_pci_pd, 275 .name = "alchemy-pci", 276 .id = 0, 277 .num_resources = ARRAY_SIZE(alchemy_pci_host_res), 278 .resource = alchemy_pci_host_res, 279}; 280 281static struct platform_device *gpr_devices[] __initdata = { 282 &gpr_wdt_device, 283 &gpr_mtd_device, 284 &gpr_i2c_device, 285 &gpr_led_devices, 286}; 287 288static int __init gpr_pci_init(void) 289{ 290 return platform_device_register(&gpr_pci_host_dev); 291} 292/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */ 293arch_initcall(gpr_pci_init); 294 295 296static int __init gpr_dev_init(void) 297{ 298 i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info)); 299 300 return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices)); 301} 302device_initcall(gpr_dev_init); 303