1/* 2 * arch/arm/mach-ixp4xx/nslu2-setup.c 3 * 4 * NSLU2 board-setup 5 * 6 * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au> 7 * 8 * based on ixdp425-setup.c: 9 * Copyright (C) 2003-2004 MontaVista Software, Inc. 10 * based on nslu2-power.c: 11 * Copyright (C) 2005 Tower Technologies 12 * 13 * Author: Mark Rakes <mrakes at mac.com> 14 * Author: Rod Whitby <rod@whitby.id.au> 15 * Author: Alessandro Zummo <a.zummo@towertech.it> 16 * Maintainers: http://www.nslu2-linux.org/ 17 * 18 */ 19 20#include <linux/if_ether.h> 21#include <linux/irq.h> 22#include <linux/serial.h> 23#include <linux/serial_8250.h> 24#include <linux/leds.h> 25#include <linux/reboot.h> 26#include <linux/i2c.h> 27#include <linux/i2c-gpio.h> 28#include <linux/io.h> 29#include <asm/mach-types.h> 30#include <asm/mach/arch.h> 31#include <asm/mach/flash.h> 32#include <asm/mach/time.h> 33#include <asm/gpio.h> 34 35#define NSLU2_SDA_PIN 7 36#define NSLU2_SCL_PIN 6 37 38/* NSLU2 Timer */ 39#define NSLU2_FREQ 66000000 40 41/* Buttons */ 42#define NSLU2_PB_GPIO 5 /* power button */ 43#define NSLU2_PO_GPIO 8 /* power off */ 44#define NSLU2_RB_GPIO 12 /* reset button */ 45 46/* Buzzer */ 47#define NSLU2_GPIO_BUZZ 4 48 49/* LEDs */ 50#define NSLU2_LED_RED_GPIO 0 51#define NSLU2_LED_GRN_GPIO 1 52#define NSLU2_LED_DISK1_GPIO 3 53#define NSLU2_LED_DISK2_GPIO 2 54 55static struct flash_platform_data nslu2_flash_data = { 56 .map_name = "cfi_probe", 57 .width = 2, 58}; 59 60static struct resource nslu2_flash_resource = { 61 .flags = IORESOURCE_MEM, 62}; 63 64static struct platform_device nslu2_flash = { 65 .name = "IXP4XX-Flash", 66 .id = 0, 67 .dev.platform_data = &nslu2_flash_data, 68 .num_resources = 1, 69 .resource = &nslu2_flash_resource, 70}; 71 72static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = { 73 .sda_pin = NSLU2_SDA_PIN, 74 .scl_pin = NSLU2_SCL_PIN, 75}; 76 77static struct i2c_board_info __initdata nslu2_i2c_board_info [] = { 78 { 79 I2C_BOARD_INFO("x1205", 0x6f), 80 }, 81}; 82 83static struct gpio_led nslu2_led_pins[] = { 84 { 85 .name = "nslu2:green:ready", 86 .gpio = NSLU2_LED_GRN_GPIO, 87 }, 88 { 89 .name = "nslu2:red:status", 90 .gpio = NSLU2_LED_RED_GPIO, 91 }, 92 { 93 .name = "nslu2:green:disk-1", 94 .gpio = NSLU2_LED_DISK1_GPIO, 95 .active_low = true, 96 }, 97 { 98 .name = "nslu2:green:disk-2", 99 .gpio = NSLU2_LED_DISK2_GPIO, 100 .active_low = true, 101 }, 102}; 103 104static struct gpio_led_platform_data nslu2_led_data = { 105 .num_leds = ARRAY_SIZE(nslu2_led_pins), 106 .leds = nslu2_led_pins, 107}; 108 109static struct platform_device nslu2_leds = { 110 .name = "leds-gpio", 111 .id = -1, 112 .dev.platform_data = &nslu2_led_data, 113}; 114 115static struct platform_device nslu2_i2c_gpio = { 116 .name = "i2c-gpio", 117 .id = 0, 118 .dev = { 119 .platform_data = &nslu2_i2c_gpio_data, 120 }, 121}; 122 123static struct platform_device nslu2_beeper = { 124 .name = "ixp4xx-beeper", 125 .id = NSLU2_GPIO_BUZZ, 126 .num_resources = 0, 127}; 128 129static struct resource nslu2_uart_resources[] = { 130 { 131 .start = IXP4XX_UART1_BASE_PHYS, 132 .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, 133 .flags = IORESOURCE_MEM, 134 }, 135 { 136 .start = IXP4XX_UART2_BASE_PHYS, 137 .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, 138 .flags = IORESOURCE_MEM, 139 } 140}; 141 142static struct plat_serial8250_port nslu2_uart_data[] = { 143 { 144 .mapbase = IXP4XX_UART1_BASE_PHYS, 145 .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, 146 .irq = IRQ_IXP4XX_UART1, 147 .flags = UPF_BOOT_AUTOCONF, 148 .iotype = UPIO_MEM, 149 .regshift = 2, 150 .uartclk = IXP4XX_UART_XTAL, 151 }, 152 { 153 .mapbase = IXP4XX_UART2_BASE_PHYS, 154 .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, 155 .irq = IRQ_IXP4XX_UART2, 156 .flags = UPF_BOOT_AUTOCONF, 157 .iotype = UPIO_MEM, 158 .regshift = 2, 159 .uartclk = IXP4XX_UART_XTAL, 160 }, 161 { } 162}; 163 164static struct platform_device nslu2_uart = { 165 .name = "serial8250", 166 .id = PLAT8250_DEV_PLATFORM, 167 .dev.platform_data = nslu2_uart_data, 168 .num_resources = 2, 169 .resource = nslu2_uart_resources, 170}; 171 172/* Built-in 10/100 Ethernet MAC interfaces */ 173static struct eth_plat_info nslu2_plat_eth[] = { 174 { 175 .phy = 1, 176 .rxq = 3, 177 .txreadyq = 20, 178 } 179}; 180 181static struct platform_device nslu2_eth[] = { 182 { 183 .name = "ixp4xx_eth", 184 .id = IXP4XX_ETH_NPEB, 185 .dev.platform_data = nslu2_plat_eth, 186 } 187}; 188 189static struct platform_device *nslu2_devices[] __initdata = { 190 &nslu2_i2c_gpio, 191 &nslu2_flash, 192 &nslu2_beeper, 193 &nslu2_leds, 194 &nslu2_eth[0], 195}; 196 197static void nslu2_power_off(void) 198{ 199 /* This causes the box to drop the power and go dead. */ 200 201 /* enable the pwr cntl gpio */ 202 gpio_line_config(NSLU2_PO_GPIO, IXP4XX_GPIO_OUT); 203 204 /* do the deed */ 205 gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH); 206} 207 208static irqreturn_t nslu2_power_handler(int irq, void *dev_id) 209{ 210 /* Signal init to do the ctrlaltdel action, this will bypass init if 211 * it hasn't started and do a kernel_restart. 212 */ 213 ctrl_alt_del(); 214 215 return IRQ_HANDLED; 216} 217 218static irqreturn_t nslu2_reset_handler(int irq, void *dev_id) 219{ 220 /* This is the paper-clip reset, it shuts the machine down directly. 221 */ 222 machine_power_off(); 223 224 return IRQ_HANDLED; 225} 226 227static void __init nslu2_timer_init(void) 228{ 229 /* The xtal on this machine is non-standard. */ 230 ixp4xx_timer_freq = NSLU2_FREQ; 231 232 /* Call standard timer_init function. */ 233 ixp4xx_timer_init(); 234} 235 236static struct sys_timer nslu2_timer = { 237 .init = nslu2_timer_init, 238}; 239 240static void __init nslu2_init(void) 241{ 242 uint8_t __iomem *f; 243 int i; 244 245 ixp4xx_sys_init(); 246 247 nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); 248 nslu2_flash_resource.end = 249 IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; 250 251 i2c_register_board_info(0, nslu2_i2c_board_info, 252 ARRAY_SIZE(nslu2_i2c_board_info)); 253 254 /* 255 * This is only useful on a modified machine, but it is valuable 256 * to have it first in order to see debug messages, and so that 257 * it does *not* get removed if platform_add_devices fails! 258 */ 259 (void)platform_device_register(&nslu2_uart); 260 261 platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); 262 263 pm_power_off = nslu2_power_off; 264 265 if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler, 266 IRQF_DISABLED | IRQF_TRIGGER_LOW, 267 "NSLU2 reset button", NULL) < 0) { 268 269 printk(KERN_DEBUG "Reset Button IRQ %d not available\n", 270 gpio_to_irq(NSLU2_RB_GPIO)); 271 } 272 273 if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler, 274 IRQF_DISABLED | IRQF_TRIGGER_HIGH, 275 "NSLU2 power button", NULL) < 0) { 276 277 printk(KERN_DEBUG "Power Button IRQ %d not available\n", 278 gpio_to_irq(NSLU2_PB_GPIO)); 279 } 280 281 /* 282 * Map in a portion of the flash and read the MAC address. 283 * Since it is stored in BE in the flash itself, we need to 284 * byteswap it if we're in LE mode. 285 */ 286 f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x40000); 287 if (f) { 288 for (i = 0; i < 6; i++) 289#ifdef __ARMEB__ 290 nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + i); 291#else 292 nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + (i^3)); 293#endif 294 iounmap(f); 295 } 296 printk(KERN_INFO "NSLU2: Using MAC address %pM for port 0\n", 297 nslu2_plat_eth[0].hwaddr); 298 299} 300 301MACHINE_START(NSLU2, "Linksys NSLU2") 302 /* Maintainer: www.nslu2-linux.org */ 303 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 304 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, 305 .boot_params = 0x00000100, 306 .map_io = ixp4xx_map_io, 307 .init_irq = ixp4xx_init_irq, 308 .timer = &nslu2_timer, 309 .init_machine = nslu2_init, 310MACHINE_END 311