[ARM] 3140/1: NSLU2 machine support
authorAlessandro Zummo <azummo-armlinux@towertech.it>
Thu, 10 Nov 2005 14:05:04 +0000 (14:05 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 10 Nov 2005 14:05:04 +0000 (14:05 +0000)
Patch from Alessandro Zummo

This patch adds support for the LinkSys NSLU2 running with
both big and little-endian kernels. The LinkSys NSLU2 is
a cost engineered ARM, XScale 420 based system similar to
the the Intel IXDP425 evaluation board. It uses the
IXP4XX ARCH.

While this patch applies independently of other patches
the resultant kernel requires further patches to successfully
use onboard devices, including the onboard flash. Since these
patches are independent of this one they will be submitted
separately.

A defconfig is not included here because not all of
the required drivers are actually in the kernel.
We intend to provide one as soon as the patches
will be incorporated in mainstream.

This patch is the combined work of nslu2-linux.org

Signed-off-by: John Bowler <jbowler@acm.org>
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/Makefile
arch/arm/mach-ixp4xx/nslu2-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/nslu2-power.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/nslu2-setup.c [new file with mode: 0644]
include/asm-arm/arch-ixp4xx/hardware.h
include/asm-arm/arch-ixp4xx/irqs.h
include/asm-arm/arch-ixp4xx/nslu2.h [new file with mode: 0644]

index 89762a26495c02d1a3abb05a5cfcee69ab0110ee..385285851cb5cd6561f48cdd228201a3ffe94b76 100644 (file)
@@ -8,6 +8,16 @@ menu "Intel IXP4xx Implementation Options"
 
 comment "IXP4xx Platforms"
 
+# This entry is placed on top because otherwise it would have
+# been shown as a submenu.
+config MACH_NSLU2
+       bool
+       prompt "NSLU2" if !(MACH_IXDP465 || MACH_IXDPG425 || ARCH_IXDP425 || ARCH_ADI_COYOTE || ARCH_AVILA || ARCH_IXCDP1100 || ARCH_PRPMC1100 || MACH_GTWX5715)
+       help
+         Say 'Y' here if you want your kernel to support Linksys's
+         NSLU2 NAS device. For more information on this platform,
+         see http://www.nslu2-linux.org
+
 config ARCH_AVILA
        bool "Avila"
        help
index ddecbda4a633ee93f8a19d3c3ed56ab9cbd2275c..7a15629c18d0bd397fdbb09d928133b2c5a28774 100644 (file)
@@ -8,4 +8,5 @@ obj-$(CONFIG_ARCH_IXDP4XX)      += ixdp425-pci.o ixdp425-setup.o
 obj-$(CONFIG_MACH_IXDPG425)    += ixdpg425-pci.o coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)  += coyote-pci.o coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)    += gtwx5715-pci.o gtwx5715-setup.o
+obj-$(CONFIG_MACH_NSLU2)       += nslu2-pci.o nslu2-setup.o nslu2-power.o
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c
new file mode 100644 (file)
index 0000000..a575f2e
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/mach-ixp4xx/nslu2-pci.c
+ *
+ * NSLU2 board-level PCI initialization
+ *
+ * based on ixdp425-pci.c:
+ *     Copyright (C) 2002 Intel Corporation.
+ *     Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: http://www.nslu2-linux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+void __init nslu2_pci_preinit(void)
+{
+       set_irq_type(IRQ_NSLU2_PCI_INTA, IRQT_LOW);
+       set_irq_type(IRQ_NSLU2_PCI_INTB, IRQT_LOW);
+       set_irq_type(IRQ_NSLU2_PCI_INTC, IRQT_LOW);
+
+       gpio_line_isr_clear(NSLU2_PCI_INTA_PIN);
+       gpio_line_isr_clear(NSLU2_PCI_INTB_PIN);
+       gpio_line_isr_clear(NSLU2_PCI_INTC_PIN);
+
+       /* INTD is not configured as GPIO is used
+        * for the power input button.
+        */
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init nslu2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       static int pci_irq_table[NSLU2_PCI_IRQ_LINES] = {
+               IRQ_NSLU2_PCI_INTA,
+               IRQ_NSLU2_PCI_INTB,
+               IRQ_NSLU2_PCI_INTC,
+       };
+
+       int irq = -1;
+
+       if (slot >= 1 && slot <= NSLU2_PCI_MAX_DEV &&
+               pin >= 1 && pin <= NSLU2_PCI_IRQ_LINES) {
+                       irq = pci_irq_table[(slot + pin - 2) % NSLU2_PCI_IRQ_LINES];
+       }
+
+       return irq;
+}
+
+struct hw_pci __initdata nslu2_pci = {
+       .nr_controllers = 1,
+       .preinit        = nslu2_pci_preinit,
+       .swizzle        = pci_std_swizzle,
+       .setup          = ixp4xx_setup,
+       .scan           = ixp4xx_scan_bus,
+       .map_irq        = nslu2_map_irq,
+};
+
+int __init nslu2_pci_init(void) /* monkey see, monkey do */
+{
+       if (machine_is_nslu2())
+               pci_common_init(&nslu2_pci);
+
+       return 0;
+}
+
+subsys_initcall(nslu2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
new file mode 100644 (file)
index 0000000..18fbc8c
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * arch/arm/mach-ixp4xx/nslu2-power.c
+ *
+ * NSLU2 Power/Reset driver
+ *
+ * Copyright (C) 2005 Tower Technologies
+ *
+ * based on nslu2-io.c
+ *  Copyright (C) 2004 Karen Spearel
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach-types.h>
+
+extern void ctrl_alt_del(void);
+
+static irqreturn_t nslu2_power_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /* Signal init to do the ctrlaltdel action, this will bypass init if
+        * it hasn't started and do a kernel_restart.
+        */
+       ctrl_alt_del();
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t nslu2_reset_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /* This is the paper-clip reset, it shuts the machine down directly.
+        */
+       machine_power_off();
+
+       return IRQ_HANDLED;
+}
+
+static int __init nslu2_power_init(void)
+{
+       if (!(machine_is_nslu2()))
+               return 0;
+
+       *IXP4XX_GPIO_GPISR = 0x20400000;        /* read the 2 irqs to clr */
+
+       set_irq_type(NSLU2_RB_IRQ, IRQT_LOW);
+       set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH);
+
+       gpio_line_isr_clear(NSLU2_RB_GPIO);
+       gpio_line_isr_clear(NSLU2_PB_GPIO);
+
+       if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler,
+               SA_INTERRUPT, "NSLU2 reset button", NULL) < 0) {
+
+               printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+                       NSLU2_RB_IRQ);
+
+               return -EIO;
+       }
+
+       if (request_irq(NSLU2_PB_IRQ, &nslu2_power_handler,
+               SA_INTERRUPT, "NSLU2 power button", NULL) < 0) {
+
+               printk(KERN_DEBUG "Power Button IRQ %d not available\n",
+                       NSLU2_PB_IRQ);
+
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void __exit nslu2_power_exit(void)
+{
+       free_irq(NSLU2_RB_IRQ, NULL);
+       free_irq(NSLU2_PB_IRQ, NULL);
+}
+
+module_init(nslu2_power_init);
+module_exit(nslu2_power_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("NSLU2 Power/Reset driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
new file mode 100644 (file)
index 0000000..289e94c
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * arch/arm/mach-ixp4xx/nslu2-setup.c
+ *
+ * NSLU2 board-setup
+ *
+ * based ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Author: Mark Rakes <mrakes at mac.com>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * Fixed missing init_time in MACHINE_START kas11 10/22/04
+ * Changed to conform to new style __init ixdp425 kas11 10/22/04
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data nslu2_flash_data = {
+       .map_name               = "cfi_probe",
+       .width                  = 2,
+};
+
+static struct resource nslu2_flash_resource = {
+       .start                  = NSLU2_FLASH_BASE,
+       .end                    = NSLU2_FLASH_BASE + NSLU2_FLASH_SIZE,
+       .flags                  = IORESOURCE_MEM,
+};
+
+static struct platform_device nslu2_flash = {
+       .name                   = "IXP4XX-Flash",
+       .id                     = 0,
+       .dev.platform_data      = &nslu2_flash_data,
+       .num_resources          = 1,
+       .resource               = &nslu2_flash_resource,
+};
+
+static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = {
+       .sda_pin                = NSLU2_SDA_PIN,
+       .scl_pin                = NSLU2_SCL_PIN,
+};
+
+static struct platform_device nslu2_i2c_controller = {
+       .name                   = "IXP4XX-I2C",
+       .id                     = 0,
+       .dev.platform_data      = &nslu2_i2c_gpio_pins,
+       .num_resources          = 0,
+};
+
+static struct resource nslu2_uart_resources[] = {
+       {
+               .start          = IXP4XX_UART1_BASE_PHYS,
+               .end            = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = IXP4XX_UART2_BASE_PHYS,
+               .end            = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+               .flags          = IORESOURCE_MEM,
+       }
+};
+
+static struct plat_serial8250_port nslu2_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART1_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART1,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { }
+};
+
+static struct platform_device nslu2_uart = {
+       .name                   = "serial8250",
+       .id                     = PLAT8250_DEV_PLATFORM,
+       .dev.platform_data      = nslu2_uart_data,
+       .num_resources          = 2,
+       .resource               = nslu2_uart_resources,
+};
+
+static struct platform_device *nslu2_devices[] __initdata = {
+       &nslu2_i2c_controller,
+       &nslu2_flash,
+       &nslu2_uart,
+};
+
+static void nslu2_power_off(void)
+{
+       /* This causes the box to drop the power and go dead. */
+
+       /* enable the pwr cntl gpio */
+       gpio_line_config(NSLU2_PO_GPIO, IXP4XX_GPIO_OUT);
+
+       /* do the deed */
+       gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
+}
+
+static void __init nslu2_init(void)
+{
+       ixp4xx_sys_init();
+
+       pm_power_off = nslu2_power_off;
+
+       platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
+}
+
+MACHINE_START(NSLU2, "Linksys NSLU2")
+       /* Maintainer: www.nslu2-linux.org */
+       .phys_ram       = PHYS_OFFSET,
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
+       .boot_params    = 0x00000100,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .init_machine   = nslu2_init,
+MACHINE_END
index 55d85eea8c1afb2ba7c6da3601f0bd0f7d2ad6ce..cfb413c845f76334bca5b1a8be4c57976351eb18 100644 (file)
@@ -44,5 +44,6 @@ extern unsigned int processor_id;
 #include "ixdp425.h"
 #include "coyote.h"
 #include "prpmc1100.h"
+#include "nslu2.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
index ca808281c7f989aefe011a065fcfae5a81eb8334..2cf4930372bca1ad7e5880b376386d2d7a9628c3 100644 (file)
 #define        IRQ_COYOTE_PCI_SLOT1    IRQ_IXP4XX_GPIO11
 #define        IRQ_COYOTE_IDE          IRQ_IXP4XX_GPIO5
 
+/*
+ * NSLU2 board IRQs
+ */
+#define        IRQ_NSLU2_PCI_INTA      IRQ_IXP4XX_GPIO11
+#define        IRQ_NSLU2_PCI_INTB      IRQ_IXP4XX_GPIO10
+#define        IRQ_NSLU2_PCI_INTC      IRQ_IXP4XX_GPIO9
+
 #endif
diff --git a/include/asm-arm/arch-ixp4xx/nslu2.h b/include/asm-arm/arch-ixp4xx/nslu2.h
new file mode 100644 (file)
index 0000000..b8b347a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * include/asm-arm/arch-ixp4xx/nslu2.h
+ *
+ * NSLU2 platform specific definitions
+ *
+ * Author: Mark Rakes <mrakes AT mac.com>
+ * Maintainers: http://www.nslu2-linux.org
+ *
+ * based on ixdp425.h:
+ *     Copyright 2004 (c) MontaVista, Software, Inc.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
+#define NSLU2_FLASH_BASE       IXP4XX_EXP_BUS_CS0_BASE_PHYS
+#define NSLU2_FLASH_SIZE       IXP4XX_EXP_BUS_CSX_REGION_SIZE
+
+#define NSLU2_SDA_PIN          7
+#define NSLU2_SCL_PIN          6
+
+/*
+ * NSLU2 PCI IRQs
+ */
+#define NSLU2_PCI_MAX_DEV      3
+#define NSLU2_PCI_IRQ_LINES    3
+
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define NSLU2_PCI_INTA_PIN     11
+#define NSLU2_PCI_INTB_PIN     10
+#define NSLU2_PCI_INTC_PIN     9
+#define NSLU2_PCI_INTD_PIN     8
+
+
+/* NSLU2 Timer */
+#define NSLU2_FREQ 66000000
+#define NSLU2_CLOCK_TICK_RATE (((NSLU2_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ)
+#define NSLU2_CLOCK_TICKS_PER_USEC ((NSLU2_CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
+
+/* GPIO */
+
+#define NSLU2_GPIO0            0
+#define NSLU2_GPIO1            1
+#define NSLU2_GPIO2            2
+#define NSLU2_GPIO3            3
+#define NSLU2_GPIO4            4
+#define NSLU2_GPIO5            5
+#define NSLU2_GPIO6            6
+#define NSLU2_GPIO7            7
+#define NSLU2_GPIO8            8
+#define NSLU2_GPIO9            9
+#define NSLU2_GPIO10           10
+#define NSLU2_GPIO11           11
+#define NSLU2_GPIO12           12
+#define NSLU2_GPIO13           13
+#define NSLU2_GPIO14           14
+#define NSLU2_GPIO15           15
+
+/* Buttons */
+
+#define NSLU2_PB_GPIO          NSLU2_GPIO5
+#define NSLU2_PO_GPIO          NSLU2_GPIO8     /* power off */
+#define NSLU2_RB_GPIO          NSLU2_GPIO12
+
+#define NSLU2_PB_IRQ           IRQ_IXP4XX_GPIO5
+#define NSLU2_RB_IRQ           IRQ_IXP4XX_GPIO12
+
+#define NSLU2_PB_BM            (1L << NSLU2_PB_GPIO)
+#define NSLU2_PO_BM            (1L << NSLU2_PO_GPIO)
+#define NSLU2_RB_BM            (1L << NSLU2_RB_GPIO)
+
+/* Buzzer */
+
+#define NSLU2_GPIO_BUZZ                4
+#define NSLU2_BZ_BM            (1L << NSLU2_GPIO_BUZZ)
+/* LEDs */
+
+#define NSLU2_LED_RED          NSLU2_GPIO0
+#define NSLU2_LED_GRN          NSLU2_GPIO1
+
+#define NSLU2_LED_RED_BM       (1L << NSLU2_LED_RED)
+#define NSLU2_LED_GRN_BM       (1L << NSLU2_LED_GRN)
+
+#define NSLU2_LED_DISK1                NSLU2_GPIO2
+#define NSLU2_LED_DISK2                NSLU2_GPIO3
+
+#define NSLU2_LED_DISK1_BM     (1L << NSLU2_GPIO2)
+#define NSLU2_LED_DISK2_BM     (1L << NSLU2_GPIO3)
+
+