aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-orion5x
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-orion5x')
-rw-r--r--arch/arm/mach-orion5x/Makefile2
-rw-r--r--arch/arm/mach-orion5x/common.c1
-rw-r--r--arch/arm/mach-orion5x/common.h7
-rw-r--r--arch/arm/mach-orion5x/dns323-setup.c174
-rw-r--r--arch/arm/mach-orion5x/gpio.c231
-rw-r--r--arch/arm/mach-orion5x/include/mach/dma.h1
-rw-r--r--arch/arm/mach-orion5x/include/mach/gpio.h29
-rw-r--r--arch/arm/mach-orion5x/include/mach/io.h7
-rw-r--r--arch/arm/mach-orion5x/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-orion5x/include/mach/memory.h4
-rw-r--r--arch/arm/mach-orion5x/include/mach/orion5x.h9
-rw-r--r--arch/arm/mach-orion5x/irq.c183
-rw-r--r--arch/arm/mach-orion5x/mpp.c6
13 files changed, 197 insertions, 461 deletions
diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
index 3d4a1bc1235..edc38e2c856 100644
--- a/arch/arm/mach-orion5x/Makefile
+++ b/arch/arm/mach-orion5x/Makefile
@@ -1,4 +1,4 @@
-obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o
+obj-y += common.o addr-map.o pci.o irq.o mpp.o
obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 437065c25c9..0a623379789 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -72,6 +72,7 @@ void __init orion5x_map_io(void)
****************************************************************************/
static struct orion_ehci_data orion5x_ehci_data = {
.dram = &orion5x_mbus_dram_info,
+ .phy_version = EHCI_PHY_ORION,
};
static u64 ehci_dmamask = 0xffffffffUL;
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index a000c7c6ee9..798b9a5e3da 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -51,13 +51,6 @@ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
-/*
- * Valid GPIO pins according to MPP setup, used by machine-setup.
- * (/mach-orion/gpio.c).
- */
-void orion5x_gpio_set_valid(unsigned pin, int valid);
-void gpio_display(void); /* debug */
-
struct machine_desc;
struct meminfo;
struct tag;
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 3e66098340a..0722d6510df 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -21,6 +21,7 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/i2c.h>
+#include <linux/ata_platform.h>
#include <asm/mach-types.h>
#include <asm/gpio.h>
#include <asm/mach/arch.h>
@@ -64,9 +65,21 @@ static struct hw_pci dns323_pci __initdata = {
.map_irq = dns323_pci_map_irq,
};
+static int __init dns323_dev_id(void)
+{
+ u32 dev, rev;
+
+ orion5x_pcie_id(&dev, &rev);
+
+ return dev;
+}
+
static int __init dns323_pci_init(void)
{
- if (machine_is_dns323())
+ /* The 5182 doesn't really use it's PCI bus, and initialising PCI
+ * gets in the way of initialising the SATA controller.
+ */
+ if (machine_is_dns323() && dns323_dev_id() != MV88F5182_DEV_ID)
pci_common_init(&dns323_pci);
return 0;
@@ -75,14 +88,6 @@ static int __init dns323_pci_init(void)
subsys_initcall(dns323_pci_init);
/****************************************************************************
- * Ethernet
- */
-
-static struct mv643xx_eth_platform_data dns323_eth_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-/****************************************************************************
* 8MiB NOR flash (Spansion S29GL064M90TFIR4)
*
* Layout as used by D-Link:
@@ -143,6 +148,90 @@ static struct platform_device dns323_nor_flash = {
};
/****************************************************************************
+ * Ethernet
+ */
+
+static struct mv643xx_eth_platform_data dns323_eth_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these
+ * functions be kept somewhere?
+ */
+static int __init dns323_parse_hex_nibble(char n)
+{
+ if (n >= '0' && n <= '9')
+ return n - '0';
+
+ if (n >= 'A' && n <= 'F')
+ return n - 'A' + 10;
+
+ if (n >= 'a' && n <= 'f')
+ return n - 'a' + 10;
+
+ return -1;
+}
+
+static int __init dns323_parse_hex_byte(const char *b)
+{
+ int hi;
+ int lo;
+
+ hi = dns323_parse_hex_nibble(b[0]);
+ lo = dns323_parse_hex_nibble(b[1]);
+
+ if (hi < 0 || lo < 0)
+ return -1;
+
+ return (hi << 4) | lo;
+}
+
+static int __init dns323_read_mac_addr(void)
+{
+ u_int8_t addr[6];
+ int i;
+ char *mac_page;
+
+ /* MAC address is stored as a regular ol' string in /dev/mtdblock4
+ * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80).
+ */
+ mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024);
+ if (!mac_page)
+ return -ENOMEM;
+
+ /* Sanity check the string we're looking at */
+ for (i = 0; i < 5; i++) {
+ if (*(mac_page + (i * 3) + 2) != ':') {
+ goto error_fail;
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ int byte;
+
+ byte = dns323_parse_hex_byte(mac_page + (i * 3));
+ if (byte < 0) {
+ goto error_fail;
+ }
+
+ addr[i] = byte;
+ }
+
+ iounmap(mac_page);
+ printk("DNS323: Found ethernet MAC address: ");
+ for (i = 0; i < 6; i++)
+ printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
+
+ memcpy(dns323_eth_data.mac_addr, addr, 6);
+
+ return 0;
+
+error_fail:
+ iounmap(mac_page);
+ return -EINVAL;
+}
+
+/****************************************************************************
* GPIO LEDs (simple - doesn't use hardware blinking support)
*/
@@ -207,10 +296,17 @@ static struct platform_device dns323_button_device = {
},
};
+/*****************************************************************************
+ * SATA
+ */
+static struct mv_sata_platform_data dns323_sata_data = {
+ .n_ports = 2,
+};
+
/****************************************************************************
* General Setup
*/
-static struct orion5x_mpp_mode dns323_mpp_modes[] __initdata = {
+static struct orion5x_mpp_mode dns323_mv88f5181_mpp_modes[] __initdata = {
{ 0, MPP_PCIE_RST_OUTn },
{ 1, MPP_GPIO }, /* right amber LED (sata ch0) */
{ 2, MPP_GPIO }, /* left amber LED (sata ch1) */
@@ -234,6 +330,30 @@ static struct orion5x_mpp_mode dns323_mpp_modes[] __initdata = {
{ -1 },
};
+static struct orion5x_mpp_mode dns323_mv88f5182_mpp_modes[] __initdata = {
+ { 0, MPP_UNUSED },
+ { 1, MPP_GPIO }, /* right amber LED (sata ch0) */
+ { 2, MPP_GPIO }, /* left amber LED (sata ch1) */
+ { 3, MPP_UNUSED },
+ { 4, MPP_GPIO }, /* power button LED */
+ { 5, MPP_GPIO }, /* power button LED */
+ { 6, MPP_GPIO }, /* GMT G751-2f overtemp */
+ { 7, MPP_GPIO }, /* M41T80 nIRQ/OUT/SQW */
+ { 8, MPP_GPIO }, /* triggers power off */
+ { 9, MPP_GPIO }, /* power button switch */
+ { 10, MPP_GPIO }, /* reset button switch */
+ { 11, MPP_UNUSED },
+ { 12, MPP_SATA_LED },
+ { 13, MPP_SATA_LED },
+ { 14, MPP_SATA_LED },
+ { 15, MPP_SATA_LED },
+ { 16, MPP_UNUSED },
+ { 17, MPP_UNUSED },
+ { 18, MPP_UNUSED },
+ { 19, MPP_UNUSED },
+ { -1 },
+};
+
/*
* On the DNS-323 the following devices are attached via I2C:
*
@@ -264,16 +384,15 @@ static void __init dns323_init(void)
/* Setup basic Orion functions. Need to be called early. */
orion5x_init();
- orion5x_mpp_conf(dns323_mpp_modes);
- writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */
-
- /*
- * Configure peripherals.
+ /* Just to be tricky, the 5182 has a completely different
+ * set of MPP modes to the 5181.
*/
- orion5x_ehci0_init();
- orion5x_eth_init(&dns323_eth_data);
- orion5x_i2c_init();
- orion5x_uart0_init();
+ if (dns323_dev_id() == MV88F5182_DEV_ID)
+ orion5x_mpp_conf(dns323_mv88f5182_mpp_modes);
+ else {
+ orion5x_mpp_conf(dns323_mv88f5181_mpp_modes);
+ writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */
+ }
/* setup flash mapping
* CS3 holds a 8 MB Spansion S29GL064M90TFIR4
@@ -288,6 +407,23 @@ static void __init dns323_init(void)
i2c_register_board_info(0, dns323_i2c_devices,
ARRAY_SIZE(dns323_i2c_devices));
+ /*
+ * Configure peripherals.
+ */
+ if (dns323_read_mac_addr() < 0)
+ printk("DNS323: Failed to read MAC address\n");
+
+ orion5x_ehci0_init();
+ orion5x_eth_init(&dns323_eth_data);
+ orion5x_i2c_init();
+ orion5x_uart0_init();
+
+ /* The 5182 has it's SATA controller on-chip, and needs it's own little
+ * init routine.
+ */
+ if (dns323_dev_id() == MV88F5182_DEV_ID)
+ orion5x_sata_init(&dns323_sata_data);
+
/* register dns323 specific power-off method */
if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
diff --git a/arch/arm/mach-orion5x/gpio.c b/arch/arm/mach-orion5x/gpio.c
deleted file mode 100644
index f99d08811e5..00000000000
--- a/arch/arm/mach-orion5x/gpio.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * arch/arm/mach-orion5x/gpio.c
- *
- * GPIO functions for Marvell Orion System On Chip
- *
- * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <asm/gpio.h>
-#include <mach/orion5x.h>
-#include "common.h"
-
-static DEFINE_SPINLOCK(gpio_lock);
-static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
-static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
-
-void __init orion5x_gpio_set_valid(unsigned pin, int valid)
-{
- if (valid)
- __set_bit(pin, gpio_valid);
- else
- __clear_bit(pin, gpio_valid);
-}
-
-/*
- * GENERIC_GPIO primitives
- */
-int gpio_direction_input(unsigned pin)
-{
- unsigned long flags;
-
- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
- return -EINVAL;
- }
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- /*
- * Some callers might have not used the gpio_request(),
- * so flag this pin as requested now.
- */
- if (!gpio_label[pin])
- gpio_label[pin] = "?";
-
- orion5x_setbits(GPIO_IO_CONF, 1 << pin);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned pin, int value)
-{
- unsigned long flags;
- int mask;
-
- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
- return -EINVAL;
- }
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- /*
- * Some callers might have not used the gpio_request(),
- * so flag this pin as requested now.
- */
- if (!gpio_label[pin])
- gpio_label[pin] = "?";
-
- mask = 1 << pin;
- orion5x_clrbits(GPIO_BLINK_EN, mask);
- if (value)
- orion5x_setbits(GPIO_OUT, mask);
- else
- orion5x_clrbits(GPIO_OUT, mask);
- orion5x_clrbits(GPIO_IO_CONF, mask);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-int gpio_get_value(unsigned pin)
-{
- int val, mask = 1 << pin;
-
- if (readl(GPIO_IO_CONF) & mask)
- val = readl(GPIO_DATA_IN) ^ readl(GPIO_IN_POL);
- else
- val = readl(GPIO_OUT);
-
- return val & mask;
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned pin, int value)
-{
- unsigned long flags;
- int mask = 1 << pin;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- orion5x_clrbits(GPIO_BLINK_EN, mask);
- if (value)
- orion5x_setbits(GPIO_OUT, mask);
- else
- orion5x_clrbits(GPIO_OUT, mask);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-}
-EXPORT_SYMBOL(gpio_set_value);
-
-void orion5x_gpio_set_blink(unsigned pin, int blink)
-{
- unsigned long flags;
- int mask = 1 << pin;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- orion5x_clrbits(GPIO_OUT, mask);
- if (blink)
- orion5x_setbits(GPIO_BLINK_EN, mask);
- else
- orion5x_clrbits(GPIO_BLINK_EN, mask);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-}
-EXPORT_SYMBOL(orion5x_gpio_set_blink);
-
-int gpio_request(unsigned pin, const char *label)
-{
- int ret = 0;
- unsigned long flags;
-
- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
- return -EINVAL;
- }
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- if (gpio_label[pin]) {
- pr_debug("%s: GPIO %d already used as %s\n",
- __func__, pin, gpio_label[pin]);
- ret = -EBUSY;
- } else
- gpio_label[pin] = label ? label : "?";
-
- spin_unlock_irqrestore(&gpio_lock, flags);
- return ret;
-}
-EXPORT_SYMBOL(gpio_request);
-
-void gpio_free(unsigned pin)
-{
- might_sleep();
-
- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
- return;
- }
-
- if (!gpio_label[pin])
- pr_warning("%s: GPIO %d already freed\n", __func__, pin);
- else
- gpio_label[pin] = NULL;
-}
-EXPORT_SYMBOL(gpio_free);
-
-/* Debug helper */
-void gpio_display(void)
-{
- int i;
-
- for (i = 0; i < GPIO_MAX; i++) {
- printk(KERN_DEBUG "Pin-%d: ", i);
-
- if (!test_bit(i, gpio_valid)) {
- printk("non-GPIO\n");
- } else if (!gpio_label[i]) {
- printk("GPIO, free\n");
- } else {
- printk("GPIO, used by %s, ", gpio_label[i]);
- if (readl(GPIO_IO_CONF) & (1 << i)) {
- printk("input, active %s, level %s, edge %s\n",
- ((readl(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
- ((readl(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
- ((readl(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
- } else {
- printk("output, val=%d\n", (readl(GPIO_OUT) >> i) & 1);
- }
- }
- }
-
- printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
- MPP_0_7_CTRL, readl(MPP_0_7_CTRL));
- printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
- MPP_8_15_CTRL, readl(MPP_8_15_CTRL));
- printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
- MPP_16_19_CTRL, readl(MPP_16_19_CTRL));
- printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
- MPP_DEV_CTRL, readl(MPP_DEV_CTRL));
- printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
- GPIO_OUT, readl(GPIO_OUT));
- printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
- GPIO_IO_CONF, readl(GPIO_IO_CONF));
- printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
- GPIO_BLINK_EN, readl(GPIO_BLINK_EN));
- printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
- GPIO_IN_POL, readl(GPIO_IN_POL));
- printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
- GPIO_DATA_IN, readl(GPIO_DATA_IN));
- printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
- GPIO_LEVEL_MASK, readl(GPIO_LEVEL_MASK));
- printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
- GPIO_EDGE_CAUSE, readl(GPIO_EDGE_CAUSE));
- printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
- GPIO_EDGE_MASK, readl(GPIO_EDGE_MASK));
-}
diff --git a/arch/arm/mach-orion5x/include/mach/dma.h b/arch/arm/mach-orion5x/include/mach/dma.h
deleted file mode 100644
index 40a8c178f10..00000000000
--- a/arch/arm/mach-orion5x/include/mach/dma.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-orion5x/include/mach/gpio.h b/arch/arm/mach-orion5x/include/mach/gpio.h
index 65dc136a86f..d8182e87ac1 100644
--- a/arch/arm/mach-orion5x/include/mach/gpio.h
+++ b/arch/arm/mach-orion5x/include/mach/gpio.h
@@ -2,18 +2,26 @@
* arch/arm/mach-orion5x/include/mach/gpio.h
*
* This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
+ * License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-extern int gpio_request(unsigned pin, const char *label);
-extern void gpio_free(unsigned pin);
-extern int gpio_direction_input(unsigned pin);
-extern int gpio_direction_output(unsigned pin, int value);
-extern int gpio_get_value(unsigned pin);
-extern void gpio_set_value(unsigned pin, int value);
-extern void orion5x_gpio_set_blink(unsigned pin, int blink);
-extern void gpio_display(void); /* debug */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <mach/irqs.h>
+#include <plat/gpio.h>
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+#define GPIO_MAX 32
+#define GPIO_OUT(pin) ORION5X_DEV_BUS_REG(0x100)
+#define GPIO_IO_CONF(pin) ORION5X_DEV_BUS_REG(0x104)
+#define GPIO_BLINK_EN(pin) ORION5X_DEV_BUS_REG(0x108)
+#define GPIO_IN_POL(pin) ORION5X_DEV_BUS_REG(0x10c)
+#define GPIO_DATA_IN(pin) ORION5X_DEV_BUS_REG(0x110)
+#define GPIO_EDGE_CAUSE(pin) ORION5X_DEV_BUS_REG(0x114)
+#define GPIO_EDGE_MASK(pin) ORION5X_DEV_BUS_REG(0x118)
+#define GPIO_LEVEL_MASK(pin) ORION5X_DEV_BUS_REG(0x11c)
static inline int gpio_to_irq(int pin)
{
@@ -25,4 +33,5 @@ static inline int irq_to_gpio(int irq)
return irq - IRQ_ORION5X_GPIO_START;
}
-#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+#endif
diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h
index f24b2513f7f..c47b033bd99 100644
--- a/arch/arm/mach-orion5x/include/mach/io.h
+++ b/arch/arm/mach-orion5x/include/mach/io.h
@@ -38,14 +38,9 @@ __arch_iounmap(void __iomem *addr)
__iounmap(addr);
}
-static inline void __iomem *__io(unsigned long addr)
-{
- return (void __iomem *)addr;
-}
-
#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m)
#define __arch_iounmap(a) __arch_iounmap(a)
-#define __io(a) __io(a)
+#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
diff --git a/arch/arm/mach-orion5x/include/mach/irqs.h b/arch/arm/mach-orion5x/include/mach/irqs.h
index d5b0fbf6b96..a6fa9d8f12d 100644
--- a/arch/arm/mach-orion5x/include/mach/irqs.h
+++ b/arch/arm/mach-orion5x/include/mach/irqs.h
@@ -13,8 +13,6 @@
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H
-#include "orion5x.h" /* need GPIO_MAX */
-
/*
* Orion Main Interrupt Controller
*/
@@ -54,7 +52,7 @@
* Orion General Purpose Pins
*/
#define IRQ_ORION5X_GPIO_START 32
-#define NR_GPIO_IRQS GPIO_MAX
+#define NR_GPIO_IRQS 32
#define NR_IRQS (IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS)
diff --git a/arch/arm/mach-orion5x/include/mach/memory.h b/arch/arm/mach-orion5x/include/mach/memory.h
index 54dd76b013f..52a2955d0f8 100644
--- a/arch/arm/mach-orion5x/include/mach/memory.h
+++ b/arch/arm/mach-orion5x/include/mach/memory.h
@@ -9,8 +9,4 @@
#define PHYS_OFFSET UL(0x00000000)
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt(x) __phys_to_virt(x)
-
-
#endif
diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h
index 9f5ce1ce584..67bda31406d 100644
--- a/arch/arm/mach-orion5x/include/mach/orion5x.h
+++ b/arch/arm/mach-orion5x/include/mach/orion5x.h
@@ -134,14 +134,6 @@
#define MPP_16_19_CTRL ORION5X_DEV_BUS_REG(0x050)
#define MPP_DEV_CTRL ORION5X_DEV_BUS_REG(0x008)
#define MPP_RESET_SAMPLE ORION5X_DEV_BUS_REG(0x010)
-#define GPIO_OUT ORION5X_DEV_BUS_REG(0x100)
-#define GPIO_IO_CONF ORION5X_DEV_BUS_REG(0x104)
-#define GPIO_BLINK_EN ORION5X_DEV_BUS_REG(0x108)
-#define GPIO_IN_POL ORION5X_DEV_BUS_REG(0x10c)
-#define GPIO_DATA_IN ORION5X_DEV_BUS_REG(0x110)
-#define GPIO_EDGE_CAUSE ORION5X_DEV_BUS_REG(0x114)
-#define GPIO_EDGE_MASK ORION5X_DEV_BUS_REG(0x118)
-#define GPIO_LEVEL_MASK ORION5X_DEV_BUS_REG(0x11c)
#define DEV_BANK_0_PARAM ORION5X_DEV_BUS_REG(0x45c)
#define DEV_BANK_1_PARAM ORION5X_DEV_BUS_REG(0x460)
#define DEV_BANK_2_PARAM ORION5X_DEV_BUS_REG(0x464)
@@ -149,7 +141,6 @@
#define DEV_BUS_CTRL ORION5X_DEV_BUS_REG(0x4c0)
#define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0)
#define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4)
-#define GPIO_MAX 32
/***************************************************************************
* Orion CPU Bridge Registers
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index 632a36f5cf1..0caae43301e 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -19,193 +19,38 @@
#include <plat/irq.h>
#include "common.h"
-/*****************************************************************************
- * Orion GPIO IRQ
- *
- * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
- * value of the line or the opposite value.
- *
- * Level IRQ handlers: DATA_IN is used directly as cause register.
- * Interrupt are masked by LEVEL_MASK registers.
- * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
- * Interrupt are masked by EDGE_MASK registers.
- * Both-edge handlers: Similar to regular Edge handlers, but also swaps
- * the polarity to catch the next line transaction.
- * This is a race condition that might not perfectly
- * work on some use cases.
- *
- * Every eight GPIO lines are grouped (OR'ed) before going up to main
- * cause register.
- *
- * EDGE cause mask
- * data-in /--------| |-----| |----\
- * -----| |----- ---- to main cause reg
- * X \----------------| |----/
- * polarity LEVEL mask
- *
- ****************************************************************************/
-static void orion5x_gpio_irq_ack(u32 irq)
-{
- int pin = irq_to_gpio(irq);
- if (irq_desc[irq].status & IRQ_LEVEL)
- /*
- * Mask bit for level interrupt
- */
- orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
- else
- /*
- * Clear casue bit for egde interrupt
- */
- orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
-}
-
-static void orion5x_gpio_irq_mask(u32 irq)
-{
- int pin = irq_to_gpio(irq);
- if (irq_desc[irq].status & IRQ_LEVEL)
- orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
- else
- orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
-}
-
-static void orion5x_gpio_irq_unmask(u32 irq)
+static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
- int pin = irq_to_gpio(irq);
- if (irq_desc[irq].status & IRQ_LEVEL)
- orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
- else
- orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
-}
-
-static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
-{
- int pin = irq_to_gpio(irq);
- struct irq_desc *desc;
-
- if ((readl(GPIO_IO_CONF) & (1 << pin)) == 0) {
- printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
- "(irq %d, pin %d).\n", irq, pin);
- return -EINVAL;
- }
-
- desc = irq_desc + irq;
-
- switch (type) {
- case IRQ_TYPE_LEVEL_HIGH:
- desc->handle_irq = handle_level_irq;
- desc->status |= IRQ_LEVEL;
- orion5x_clrbits(GPIO_IN_POL, (1 << pin));
- break;
- case IRQ_TYPE_LEVEL_LOW:
- desc->handle_irq = handle_level_irq;
- desc->status |= IRQ_LEVEL;
- orion5x_setbits(GPIO_IN_POL, (1 << pin));
- break;
- case IRQ_TYPE_EDGE_RISING:
- desc->handle_irq = handle_edge_irq;
- desc->status &= ~IRQ_LEVEL;
- orion5x_clrbits(GPIO_IN_POL, (1 << pin));
- break;
- case IRQ_TYPE_EDGE_FALLING:
- desc->handle_irq = handle_edge_irq;
- desc->status &= ~IRQ_LEVEL;
- orion5x_setbits(GPIO_IN_POL, (1 << pin));
- break;
- case IRQ_TYPE_EDGE_BOTH:
- desc->handle_irq = handle_edge_irq;
- desc->status &= ~IRQ_LEVEL;
- /*
- * set initial polarity based on current input level
- */
- if ((readl(GPIO_IN_POL) ^ readl(GPIO_DATA_IN))
- & (1 << pin))
- orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
- else
- orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
-
- break;
- default:
- printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
- return -EINVAL;
- }
-
- desc->status &= ~IRQ_TYPE_SENSE_MASK;
- desc->status |= type & IRQ_TYPE_SENSE_MASK;
-
- return 0;
-}
-
-static struct irq_chip orion5x_gpio_irq_chip = {
- .name = "Orion-IRQ-GPIO",
- .ack = orion5x_gpio_irq_ack,
- .mask = orion5x_gpio_irq_mask,
- .unmask = orion5x_gpio_irq_unmask,
- .set_type = orion5x_gpio_set_irq_type,
-};
-
-static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- u32 cause, offs, pin;
-
BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
- offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
- cause = (readl(GPIO_DATA_IN) & readl(GPIO_LEVEL_MASK)) |
- (readl(GPIO_EDGE_CAUSE) & readl(GPIO_EDGE_MASK));
- for (pin = offs; pin < offs + 8; pin++) {
- if (cause & (1 << pin)) {
- irq = gpio_to_irq(pin);
- desc = irq_desc + irq;
- if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
- /* Swap polarity (race with GPIO line) */
- u32 polarity = readl(GPIO_IN_POL);
- polarity ^= 1 << pin;
- writel(polarity, GPIO_IN_POL);
- }
- generic_handle_irq(irq);
- }
- }
+ orion_gpio_irq_handler((irq - IRQ_ORION5X_GPIO_0_7) << 3);
}
-static void __init orion5x_init_gpio_irq(void)
+void __init orion5x_init_irq(void)
{
int i;
- struct irq_desc *desc;
+
+ orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
/*
* Mask and clear GPIO IRQ interrupts
*/
- writel(0x0, GPIO_LEVEL_MASK);
- writel(0x0, GPIO_EDGE_MASK);
- writel(0x0, GPIO_EDGE_CAUSE);
+ writel(0x0, GPIO_LEVEL_MASK(0));
+ writel(0x0, GPIO_EDGE_MASK(0));
+ writel(0x0, GPIO_EDGE_CAUSE(0));
/*
* Register chained level handlers for GPIO IRQs by default.
* User can use set_type() if he wants to use edge types handlers.
*/
for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
- set_irq_chip(i, &orion5x_gpio_irq_chip);
+ set_irq_chip(i, &orion_gpio_irq_level_chip);
set_irq_handler(i, handle_level_irq);
- desc = irq_desc + i;
- desc->status |= IRQ_LEVEL;
+ irq_desc[i].status |= IRQ_LEVEL;
set_irq_flags(i, IRQF_VALID);
}
- set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
- set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
- set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
- set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
-}
-
-/*****************************************************************************
- * Orion Main IRQ
- ****************************************************************************/
-static void __init orion5x_init_main_irq(void)
-{
- orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
-}
-
-void __init orion5x_init_irq(void)
-{
- orion5x_init_main_irq();
- orion5x_init_gpio_irq();
+ set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
+ set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
+ set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
+ set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
}
diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c
index 640ea2a3fc6..e23a3f91d6c 100644
--- a/arch/arm/mach-orion5x/mpp.c
+++ b/arch/arm/mach-orion5x/mpp.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/mbus.h>
#include <linux/io.h>
+#include <asm/gpio.h>
#include <mach/hardware.h>
#include "common.h"
#include "mpp.h"
@@ -152,7 +153,10 @@ void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode)
*reg &= ~(0xf << shift);
*reg |= (num_type & 0xf) << shift;
- orion5x_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
+ if (mode->type == MPP_UNUSED && (mode->mpp < 16 || is_5182()))
+ orion_gpio_set_unused(mode->mpp);
+
+ orion_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
mode++;
}