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#include <linux/gpio.h> 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 34#define NSLU2_SDA_PIN 7 35#define NSLU2_SCL_PIN 6 36 37/* NSLU2 Timer */ 38#define NSLU2_FREQ 66000000 39 40/* Buttons */ 41#define NSLU2_PB_GPIO 5 /* power button */ 42#define NSLU2_PO_GPIO 8 /* power off */ 43#define NSLU2_RB_GPIO 12 /* reset button */ 44 45/* Buzzer */ 46#define NSLU2_GPIO_BUZZ 4 47 48/* LEDs */ 49#define NSLU2_LED_RED_GPIO 0 50#define NSLU2_LED_GRN_GPIO 1 51#define NSLU2_LED_DISK1_GPIO 3 52#define NSLU2_LED_DISK2_GPIO 2 53 54static struct flash_platform_data nslu2_flash_data = { 55 .map_name = "cfi_probe", 56 .width = 2, 57}; 58 59static struct resource nslu2_flash_resource = { 60 .flags = IORESOURCE_MEM, 61}; 62 63static struct platform_device nslu2_flash = { 64 .name = "IXP4XX-Flash", 65 .id = 0, 66 .dev.platform_data = &nslu2_flash_data, 67 .num_resources = 1, 68 .resource = &nslu2_flash_resource, 69}; 70 71static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = { 72 .sda_pin = NSLU2_SDA_PIN, 73 .scl_pin = NSLU2_SCL_PIN, 74}; 75 76static struct i2c_board_info __initdata nslu2_i2c_board_info [] = { 77 { 78 I2C_BOARD_INFO("x1205", 0x6f), 79 }, 80}; 81 82static struct gpio_led nslu2_led_pins[] = { 83 { 84 .name = "nslu2:green:ready", 85 .gpio = NSLU2_LED_GRN_GPIO, 86 }, 87 { 88 .name = "nslu2:red:status", 89 .gpio = NSLU2_LED_RED_GPIO, 90 }, 91 { 92 .name = "nslu2:green:disk-1", 93 .gpio = NSLU2_LED_DISK1_GPIO, 94 .active_low = true, 95 }, 96 { 97 .name = "nslu2:green:disk-2", 98 .gpio = NSLU2_LED_DISK2_GPIO, 99 .active_low = true, 100 }, 101}; 102 103static struct gpio_led_platform_data nslu2_led_data = { 104 .num_leds = ARRAY_SIZE(nslu2_led_pins), 105 .leds = nslu2_led_pins, 106}; 107 108static struct platform_device nslu2_leds = { 109 .name = "leds-gpio", 110 .id = -1, 111 .dev.platform_data = &nslu2_led_data, 112}; 113 114static struct platform_device nslu2_i2c_gpio = { 115 .name = "i2c-gpio", 116 .id = 0, 117 .dev = { 118 .platform_data = &nslu2_i2c_gpio_data, 119 }, 120}; 121 122static struct platform_device nslu2_beeper = { 123 .name = "ixp4xx-beeper", 124 .id = NSLU2_GPIO_BUZZ, 125 .num_resources = 0, 126}; 127 128static struct resource nslu2_uart_resources[] = { 129 { 130 .start = IXP4XX_UART1_BASE_PHYS, 131 .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, 132 .flags = IORESOURCE_MEM, 133 }, 134 { 135 .start = IXP4XX_UART2_BASE_PHYS, 136 .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, 137 .flags = IORESOURCE_MEM, 138 } 139}; 140 141static struct plat_serial8250_port nslu2_uart_data[] = { 142 { 143 .mapbase = IXP4XX_UART1_BASE_PHYS, 144 .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, 145 .irq = IRQ_IXP4XX_UART1, 146 .flags = UPF_BOOT_AUTOCONF, 147 .iotype = UPIO_MEM, 148 .regshift = 2, 149 .uartclk = IXP4XX_UART_XTAL, 150 }, 151 { 152 .mapbase = IXP4XX_UART2_BASE_PHYS, 153 .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, 154 .irq = IRQ_IXP4XX_UART2, 155 .flags = UPF_BOOT_AUTOCONF, 156 .iotype = UPIO_MEM, 157 .regshift = 2, 158 .uartclk = IXP4XX_UART_XTAL, 159 }, 160 { } 161}; 162 163static struct platform_device nslu2_uart = { 164 .name = "serial8250", 165 .id = PLAT8250_DEV_PLATFORM, 166 .dev.platform_data = nslu2_uart_data, 167 .num_resources = 2, 168 .resource = nslu2_uart_resources, 169}; 170 171/* Built-in 10/100 Ethernet MAC interfaces */ 172static struct eth_plat_info nslu2_plat_eth[] = { 173 { 174 .phy = 1, 175 .rxq = 3, 176 .txreadyq = 20, 177 } 178}; 179 180static struct platform_device nslu2_eth[] = { 181 { 182 .name = "ixp4xx_eth", 183 .id = IXP4XX_ETH_NPEB, 184 .dev.platform_data = nslu2_plat_eth, 185 } 186}; 187 188static struct platform_device *nslu2_devices[] __initdata = { 189 &nslu2_i2c_gpio, 190 &nslu2_flash, 191 &nslu2_beeper, 192 &nslu2_leds, 193 &nslu2_eth[0], 194}; 195 196static void nslu2_power_off(void) 197{ 198 /* This causes the box to drop the power and go dead. */ 199 200 /* enable the pwr cntl gpio and assert power off */ 201 gpio_direction_output(NSLU2_PO_GPIO, 1); 202} 203 204static irqreturn_t nslu2_power_handler(int irq, void *dev_id) 205{ 206 /* Signal init to do the ctrlaltdel action, this will bypass init if 207 * it hasn't started and do a kernel_restart. 208 */ 209 ctrl_alt_del(); 210 211 return IRQ_HANDLED; 212} 213 214static irqreturn_t nslu2_reset_handler(int irq, void *dev_id) 215{ 216 /* This is the paper-clip reset, it shuts the machine down directly. 217 */ 218 machine_power_off(); 219 220 return IRQ_HANDLED; 221} 222 223static int __init nslu2_gpio_init(void) 224{ 225 if (!machine_is_nslu2()) 226 return 0; 227 228 /* Request the power off GPIO */ 229 return gpio_request(NSLU2_PO_GPIO, "power off"); 230} 231device_initcall(nslu2_gpio_init); 232 233static void __init nslu2_timer_init(void) 234{ 235 /* The xtal on this machine is non-standard. */ 236 ixp4xx_timer_freq = NSLU2_FREQ; 237 238 /* Call standard timer_init function. */ 239 ixp4xx_timer_init(); 240} 241 242static void __init nslu2_init(void) 243{ 244 uint8_t __iomem *f; 245 int i; 246 247 ixp4xx_sys_init(); 248 249 nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); 250 nslu2_flash_resource.end = 251 IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; 252 253 i2c_register_board_info(0, nslu2_i2c_board_info, 254 ARRAY_SIZE(nslu2_i2c_board_info)); 255 256 /* 257 * This is only useful on a modified machine, but it is valuable 258 * to have it first in order to see debug messages, and so that 259 * it does *not* get removed if platform_add_devices fails! 260 */ 261 (void)platform_device_register(&nslu2_uart); 262 263 platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); 264 265 pm_power_off = nslu2_power_off; 266 267 if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler, 268 IRQF_TRIGGER_LOW, "NSLU2 reset button", NULL) < 0) { 269 270 printk(KERN_DEBUG "Reset Button IRQ %d not available\n", 271 gpio_to_irq(NSLU2_RB_GPIO)); 272 } 273 274 if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler, 275 IRQF_TRIGGER_HIGH, "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 .atag_offset = 0x100, 304 .map_io = ixp4xx_map_io, 305 .init_early = ixp4xx_init_early, 306 .init_irq = ixp4xx_init_irq, 307 .init_time = nslu2_timer_init, 308 .init_machine = nslu2_init, 309#if defined(CONFIG_PCI) 310 .dma_zone_size = SZ_64M, 311#endif 312 .restart = ixp4xx_restart, 313MACHINE_END 314