aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/ar7
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/ar7')
-rw-r--r--arch/mips/ar7/Makefile1
-rw-r--r--arch/mips/ar7/Platform6
-rw-r--r--arch/mips/ar7/clock.c118
-rw-r--r--arch/mips/ar7/gpio.c328
-rw-r--r--arch/mips/ar7/irq.c50
-rw-r--r--arch/mips/ar7/memory.c4
-rw-r--r--arch/mips/ar7/platform.c789
-rw-r--r--arch/mips/ar7/prom.c86
-rw-r--r--arch/mips/ar7/setup.c32
-rw-r--r--arch/mips/ar7/time.c15
10 files changed, 960 insertions, 469 deletions
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
index 26bc5da1899..7435e44b396 100644
--- a/arch/mips/ar7/Makefile
+++ b/arch/mips/ar7/Makefile
@@ -8,4 +8,3 @@ obj-y := \
platform.o \
gpio.o \
clock.o
-EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/ar7/Platform b/arch/mips/ar7/Platform
new file mode 100644
index 00000000000..21f9102d533
--- /dev/null
+++ b/arch/mips/ar7/Platform
@@ -0,0 +1,6 @@
+#
+# Texas Instruments AR7
+#
+platform-$(CONFIG_AR7) += ar7/
+cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7) += 0xffffffff94100000
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
index cc65c8eb391..2460f9d23f1 100644
--- a/arch/mips/ar7/clock.c
+++ b/arch/mips/ar7/clock.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +25,8 @@
#include <linux/delay.h>
#include <linux/gcd.h>
#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/addrspace.h>
#include <asm/mach-ar7/ar7.h>
@@ -94,12 +97,16 @@ struct tnetd7200_clocks {
struct tnetd7200_clock usb;
};
-int ar7_cpu_clock = 150000000;
-EXPORT_SYMBOL(ar7_cpu_clock);
-int ar7_bus_clock = 125000000;
-EXPORT_SYMBOL(ar7_bus_clock);
-int ar7_dsp_clock;
-EXPORT_SYMBOL(ar7_dsp_clock);
+static struct clk bus_clk = {
+ .rate = 125000000,
+};
+
+static struct clk cpu_clk = {
+ .rate = 150000000,
+};
+
+static struct clk dsp_clk;
+static struct clk vbus_clk;
static void approximate(int base, int target, int *prediv,
int *postdiv, int *mul)
@@ -185,7 +192,7 @@ static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
base_clock = AR7_XTAL_CLOCK;
break;
case BOOT_PLL_SOURCE_CPU:
- base_clock = ar7_cpu_clock;
+ base_clock = cpu_clk.rate;
break;
}
@@ -212,11 +219,11 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
u32 *bootcr, u32 frequency)
{
int prediv, postdiv, mul;
- int base_clock = ar7_bus_clock;
+ int base_clock = bus_clk.rate;
switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
case BOOT_PLL_SOURCE_BUS:
- base_clock = ar7_bus_clock;
+ base_clock = bus_clk.rate;
break;
case BOOT_PLL_SOURCE_REF:
base_clock = AR7_REF_CLOCK;
@@ -225,19 +232,19 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
base_clock = AR7_XTAL_CLOCK;
break;
case BOOT_PLL_SOURCE_CPU:
- base_clock = ar7_cpu_clock;
+ base_clock = cpu_clk.rate;
break;
}
calculate(base_clock, frequency, &prediv, &postdiv, &mul);
writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
- msleep(1);
+ mdelay(1);
writel(4, &clock->pll);
while (readl(&clock->pll) & PLL_STATUS)
;
writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
- msleep(75);
+ mdelay(75);
}
static void __init tnetd7300_init_clocks(void)
@@ -247,18 +254,18 @@ static void __init tnetd7300_init_clocks(void)
ioremap_nocache(UR8_REGS_CLOCKS,
sizeof(struct tnetd7300_clocks));
- ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
+ bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
&clocks->bus, bootcr, AR7_AFE_CLOCK);
if (*bootcr & BOOT_PLL_ASYNC_MODE)
- ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
+ cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
&clocks->cpu, bootcr, AR7_AFE_CLOCK);
else
- ar7_cpu_clock = ar7_bus_clock;
+ cpu_clk.rate = bus_clk.rate;
- if (ar7_dsp_clock == 250000000)
+ if (dsp_clk.rate == 250000000)
tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
- bootcr, ar7_dsp_clock);
+ bootcr, dsp_clk.rate);
iounmap(clocks);
iounmap(bootcr);
@@ -343,20 +350,20 @@ static void __init tnetd7200_init_clocks(void)
printk(KERN_INFO "Clocks: Setting DSP clock\n");
calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
&dsp_prediv, &dsp_postdiv, &dsp_mul);
- ar7_bus_clock =
+ bus_clk.rate =
((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
tnetd7200_set_clock(dsp_base, &clocks->dsp,
dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
- ar7_bus_clock);
+ bus_clk.rate);
printk(KERN_INFO "Clocks: Setting CPU clock\n");
calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
&cpu_postdiv, &cpu_mul);
- ar7_cpu_clock =
+ cpu_clk.rate =
((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
tnetd7200_set_clock(cpu_base, &clocks->cpu,
cpu_prediv, cpu_postdiv, -1, cpu_mul,
- ar7_cpu_clock);
+ cpu_clk.rate);
} else
if (*bootcr & BOOT_PLL_2TO1_MODE) {
@@ -365,49 +372,91 @@ static void __init tnetd7200_init_clocks(void)
printk(KERN_INFO "Clocks: Setting CPU clock\n");
calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
&cpu_postdiv, &cpu_mul);
- ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul)
+ cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
/ cpu_postdiv;
tnetd7200_set_clock(cpu_base, &clocks->cpu,
cpu_prediv, cpu_postdiv, -1, cpu_mul,
- ar7_cpu_clock);
+ cpu_clk.rate);
printk(KERN_INFO "Clocks: Setting DSP clock\n");
calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
&dsp_postdiv, &dsp_mul);
- ar7_bus_clock = ar7_cpu_clock / 2;
+ bus_clk.rate = cpu_clk.rate / 2;
tnetd7200_set_clock(dsp_base, &clocks->dsp,
dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
- dsp_mul * 2, ar7_bus_clock);
+ dsp_mul * 2, bus_clk.rate);
} else {
printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
printk(KERN_INFO "Clocks: Setting DSP clock\n");
calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
&dsp_postdiv, &dsp_mul);
- ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul)
+ bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
/ dsp_postdiv;
tnetd7200_set_clock(dsp_base, &clocks->dsp,
dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
- dsp_mul * 2, ar7_bus_clock);
+ dsp_mul * 2, bus_clk.rate);
- ar7_cpu_clock = ar7_bus_clock;
+ cpu_clk.rate = bus_clk.rate;
}
printk(KERN_INFO "Clocks: Setting USB clock\n");
- usb_base = ar7_bus_clock;
+ usb_base = bus_clk.rate;
calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
&usb_postdiv, &usb_mul);
tnetd7200_set_clock(usb_base, &clocks->usb,
usb_prediv, usb_postdiv, -1, usb_mul,
TNETD7200_DEF_USB_CLK);
- ar7_dsp_clock = ar7_cpu_clock;
+ dsp_clk.rate = cpu_clk.rate;
iounmap(clocks);
iounmap(bootcr);
}
-int __init ar7_init_clocks(void)
+/*
+ * Linux clock API
+ */
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ if (!strcmp(id, "bus"))
+ return &bus_clk;
+ /* cpmac and vbus share the same rate */
+ if (!strcmp(id, "cpmac"))
+ return &vbus_clk;
+ if (!strcmp(id, "cpu"))
+ return &cpu_clk;
+ if (!strcmp(id, "dsp"))
+ return &dsp_clk;
+ if (!strcmp(id, "vbus"))
+ return &vbus_clk;
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+void __init ar7_init_clocks(void)
{
switch (ar7_chip_id()) {
case AR7_CHIP_7100:
@@ -415,13 +464,12 @@ int __init ar7_init_clocks(void)
tnetd7200_init_clocks();
break;
case AR7_CHIP_7300:
- ar7_dsp_clock = tnetd7300_dsp_clock();
+ dsp_clk.rate = tnetd7300_dsp_clock();
tnetd7300_init_clocks();
break;
default:
break;
}
-
- return 0;
+ /* adjust vbus clock rate */
+ vbus_clk.rate = bus_clk.rate / 2;
}
-arch_initcall(ar7_init_clocks);
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
index 74e14a3dbf4..d8dbd8f0c1d 100644
--- a/arch/mips/ar7/gpio.c
+++ b/arch/mips/ar7/gpio.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ * Copyright (C) 2009-2010 Florian Fainelli <florian@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,31 +19,330 @@
*/
#include <linux/module.h>
+#include <linux/gpio.h>
#include <asm/mach-ar7/gpio.h>
-static const char *ar7_gpio_list[AR7_GPIO_MAX];
+struct ar7_gpio_chip {
+ void __iomem *regs;
+ struct gpio_chip chip;
+};
-int gpio_request(unsigned gpio, const char *label)
+static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
- if (gpio >= AR7_GPIO_MAX)
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
+
+ return readl(gpio_in) & (1 << gpio);
+}
+
+static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_in0 = gpch->regs + TITAN_GPIO_INPUT_0;
+ void __iomem *gpio_in1 = gpch->regs + TITAN_GPIO_INPUT_1;
+
+ return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f));
+}
+
+static void ar7_gpio_set_value(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
+ unsigned tmp;
+
+ tmp = readl(gpio_out) & ~(1 << gpio);
+ if (value)
+ tmp |= 1 << gpio;
+ writel(tmp, gpio_out);
+}
+
+static void titan_gpio_set_value(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_out0 = gpch->regs + TITAN_GPIO_OUTPUT_0;
+ void __iomem *gpio_out1 = gpch->regs + TITAN_GPIO_OUTPUT_1;
+ unsigned tmp;
+
+ tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f));
+ if (value)
+ tmp |= 1 << (gpio & 0x1f);
+ writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0);
+}
+
+static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
+
+ writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static int titan_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
+ void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
+
+ if (gpio >= TITAN_GPIO_MAX)
return -EINVAL;
- if (ar7_gpio_list[gpio])
- return -EBUSY;
+ writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)),
+ gpio >> 5 ? gpio_dir1 : gpio_dir0);
+ return 0;
+}
+
+static int ar7_gpio_direction_output(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
+
+ ar7_gpio_set_value(chip, gpio, value);
+ writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static int titan_gpio_direction_output(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct ar7_gpio_chip *gpch =
+ container_of(chip, struct ar7_gpio_chip, chip);
+ void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
+ void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
+
+ if (gpio >= TITAN_GPIO_MAX)
+ return -EINVAL;
- if (label)
- ar7_gpio_list[gpio] = label;
- else
- ar7_gpio_list[gpio] = "busy";
+ titan_gpio_set_value(chip, gpio, value);
+ writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 <<
+ (gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0);
return 0;
}
-EXPORT_SYMBOL(gpio_request);
-void gpio_free(unsigned gpio)
+static struct ar7_gpio_chip ar7_gpio_chip = {
+ .chip = {
+ .label = "ar7-gpio",
+ .direction_input = ar7_gpio_direction_input,
+ .direction_output = ar7_gpio_direction_output,
+ .set = ar7_gpio_set_value,
+ .get = ar7_gpio_get_value,
+ .base = 0,
+ .ngpio = AR7_GPIO_MAX,
+ }
+};
+
+static struct ar7_gpio_chip titan_gpio_chip = {
+ .chip = {
+ .label = "titan-gpio",
+ .direction_input = titan_gpio_direction_input,
+ .direction_output = titan_gpio_direction_output,
+ .set = titan_gpio_set_value,
+ .get = titan_gpio_get_value,
+ .base = 0,
+ .ngpio = TITAN_GPIO_MAX,
+ }
+};
+
+static inline int ar7_gpio_enable_ar7(unsigned gpio)
{
- BUG_ON(!ar7_gpio_list[gpio]);
- ar7_gpio_list[gpio] = NULL;
+ void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
+
+ writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+ return 0;
+}
+
+static inline int ar7_gpio_enable_titan(unsigned gpio)
+{
+ void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
+ void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
+
+ writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)),
+ gpio >> 5 ? gpio_en1 : gpio_en0);
+
+ return 0;
+}
+
+int ar7_gpio_enable(unsigned gpio)
+{
+ return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) :
+ ar7_gpio_enable_ar7(gpio);
+}
+EXPORT_SYMBOL(ar7_gpio_enable);
+
+static inline int ar7_gpio_disable_ar7(unsigned gpio)
+{
+ void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
+
+ writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+ return 0;
+}
+
+static inline int ar7_gpio_disable_titan(unsigned gpio)
+{
+ void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
+ void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
+
+ writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)),
+ gpio >> 5 ? gpio_en1 : gpio_en0);
+
+ return 0;
+}
+
+int ar7_gpio_disable(unsigned gpio)
+{
+ return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) :
+ ar7_gpio_disable_ar7(gpio);
+}
+EXPORT_SYMBOL(ar7_gpio_disable);
+
+struct titan_gpio_cfg {
+ u32 reg;
+ u32 shift;
+ u32 func;
+};
+
+static const struct titan_gpio_cfg titan_gpio_table[] = {
+ /* reg, start bit, mux value */
+ {4, 24, 1},
+ {4, 26, 1},
+ {4, 28, 1},
+ {4, 30, 1},
+ {5, 6, 1},
+ {5, 8, 1},
+ {5, 10, 1},
+ {5, 12, 1},
+ {7, 14, 3},
+ {7, 16, 3},
+ {7, 18, 3},
+ {7, 20, 3},
+ {7, 22, 3},
+ {7, 26, 3},
+ {7, 28, 3},
+ {7, 30, 3},
+ {8, 0, 3},
+ {8, 2, 3},
+ {8, 4, 3},
+ {8, 10, 3},
+ {8, 14, 3},
+ {8, 16, 3},
+ {8, 18, 3},
+ {8, 20, 3},
+ {9, 8, 3},
+ {9, 10, 3},
+ {9, 12, 3},
+ {9, 14, 3},
+ {9, 18, 3},
+ {9, 20, 3},
+ {9, 24, 3},
+ {9, 26, 3},
+ {9, 28, 3},
+ {9, 30, 3},
+ {10, 0, 3},
+ {10, 2, 3},
+ {10, 8, 3},
+ {10, 10, 3},
+ {10, 12, 3},
+ {10, 14, 3},
+ {13, 12, 3},
+ {13, 14, 3},
+ {13, 16, 3},
+ {13, 18, 3},
+ {13, 24, 3},
+ {13, 26, 3},
+ {13, 28, 3},
+ {13, 30, 3},
+ {14, 2, 3},
+ {14, 6, 3},
+ {14, 8, 3},
+ {14, 12, 3}
+};
+
+static int titan_gpio_pinsel(unsigned gpio)
+{
+ struct titan_gpio_cfg gpio_cfg;
+ u32 mux_status, pin_sel_reg, tmp;
+ void __iomem *pin_sel = (void __iomem *)KSEG1ADDR(AR7_REGS_PINSEL);
+
+ if (gpio >= ARRAY_SIZE(titan_gpio_table))
+ return -EINVAL;
+
+ gpio_cfg = titan_gpio_table[gpio];
+ pin_sel_reg = gpio_cfg.reg - 1;
+
+ mux_status = (readl(pin_sel + pin_sel_reg) >> gpio_cfg.shift) & 0x3;
+
+ /* Check the mux status */
+ if (!((mux_status == 0) || (mux_status == gpio_cfg.func)))
+ return 0;
+
+ /* Set the pin sel value */
+ tmp = readl(pin_sel + pin_sel_reg);
+ tmp |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift);
+ writel(tmp, pin_sel + pin_sel_reg);
+
+ return 0;
+}
+
+/* Perform minimal Titan GPIO configuration */
+static void titan_gpio_init(void)
+{
+ unsigned i;
+
+ for (i = 44; i < 48; i++) {
+ titan_gpio_pinsel(i);
+ ar7_gpio_enable_titan(i);
+ titan_gpio_direction_input(&titan_gpio_chip.chip, i);
+ }
+}
+
+int __init ar7_gpio_init(void)
+{
+ int ret;
+ struct ar7_gpio_chip *gpch;
+ unsigned size;
+
+ if (!ar7_is_titan()) {
+ gpch = &ar7_gpio_chip;
+ size = 0x10;
+ } else {
+ gpch = &titan_gpio_chip;
+ size = 0x1f;
+ }
+
+ gpch->regs = ioremap_nocache(AR7_REGS_GPIO, size);
+ if (!gpch->regs) {
+ printk(KERN_ERR "%s: failed to ioremap regs\n",
+ gpch->chip.label);
+ return -ENOMEM;
+ }
+
+ ret = gpiochip_add(&gpch->chip);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to add gpiochip\n",
+ gpch->chip.label);
+ return ret;
+ }
+ printk(KERN_INFO "%s: registered %d GPIOs\n",
+ gpch->chip.label, gpch->chip.ngpio);
+
+ if (ar7_is_titan())
+ titan_gpio_init();
+
+ return ret;
}
-EXPORT_SYMBOL(gpio_free);
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
index c781556c44e..88c4babfdb5 100644
--- a/arch/mips/ar7/irq.c
+++ b/arch/mips/ar7/irq.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
@@ -48,56 +49,57 @@
static int ar7_irq_base;
-static void ar7_unmask_irq(unsigned int irq)
+static void ar7_unmask_irq(struct irq_data *d)
{
- writel(1 << ((irq - ar7_irq_base) % 32),
- REG(ESR_OFFSET(irq - ar7_irq_base)));
+ writel(1 << ((d->irq - ar7_irq_base) % 32),
+ REG(ESR_OFFSET(d->irq - ar7_irq_base)));
}
-static void ar7_mask_irq(unsigned int irq)
+static void ar7_mask_irq(struct irq_data *d)
{
- writel(1 << ((irq - ar7_irq_base) % 32),
- REG(ECR_OFFSET(irq - ar7_irq_base)));
+ writel(1 << ((d->irq - ar7_irq_base) % 32),
+ REG(ECR_OFFSET(d->irq - ar7_irq_base)));
}
-static void ar7_ack_irq(unsigned int irq)
+static void ar7_ack_irq(struct irq_data *d)
{
- writel(1 << ((irq - ar7_irq_base) % 32),
- REG(CR_OFFSET(irq - ar7_irq_base)));
+ writel(1 << ((d->irq - ar7_irq_base) % 32),
+ REG(CR_OFFSET(d->irq - ar7_irq_base)));
}
-static void ar7_unmask_sec_irq(unsigned int irq)
+static void ar7_unmask_sec_irq(struct irq_data *d)
{
- writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+ writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
}
-static void ar7_mask_sec_irq(unsigned int irq)
+static void ar7_mask_sec_irq(struct irq_data *d)
{
- writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+ writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
}
-static void ar7_ack_sec_irq(unsigned int irq)
+static void ar7_ack_sec_irq(struct irq_data *d)
{
- writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+ writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
}
static struct irq_chip ar7_irq_type = {
.name = "AR7",
- .unmask = ar7_unmask_irq,
- .mask = ar7_mask_irq,
- .ack = ar7_ack_irq
+ .irq_unmask = ar7_unmask_irq,
+ .irq_mask = ar7_mask_irq,
+ .irq_ack = ar7_ack_irq
};
static struct irq_chip ar7_sec_irq_type = {
.name = "AR7",
- .unmask = ar7_unmask_sec_irq,
- .mask = ar7_mask_sec_irq,
- .ack = ar7_ack_sec_irq,
+ .irq_unmask = ar7_unmask_sec_irq,
+ .irq_mask = ar7_mask_sec_irq,
+ .irq_ack = ar7_ack_sec_irq,
};
static struct irqaction ar7_cascade_action = {
.handler = no_action,
- .name = "AR7 cascade interrupt"
+ .name = "AR7 cascade interrupt",
+ .flags = IRQF_NO_THREAD,
};
static void __init ar7_irq_init(int base)
@@ -118,11 +120,11 @@ static void __init ar7_irq_init(int base)
for (i = 0; i < 40; i++) {
writel(i, REG(CHNL_OFFSET(i)));
/* Primary IRQ's */
- set_irq_chip_and_handler(base + i, &ar7_irq_type,
+ irq_set_chip_and_handler(base + i, &ar7_irq_type,
handle_level_irq);
/* Secondary IRQ's */
if (i < 32)
- set_irq_chip_and_handler(base + i + 40,
+ irq_set_chip_and_handler(base + i + 40,
&ar7_sec_irq_type,
handle_level_irq);
}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
index 696c723dc6d..92dfa481205 100644
--- a/arch/mips/ar7/memory.c
+++ b/arch/mips/ar7/memory.c
@@ -30,7 +30,6 @@
#include <asm/sections.h>
#include <asm/mach-ar7/ar7.h>
-#include <asm/mips-boards/prom.h>
static int __init memsize(void)
{
@@ -62,8 +61,7 @@ void __init prom_meminit(void)
unsigned long pages;
pages = memsize() >> PAGE_SHIFT;
- add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
- BOOT_MEM_RAM);
+ add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT, BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index f70a10a8cc9..7e2356fd5fd 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -34,45 +34,50 @@
#include <linux/etherdevice.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
#include <asm/addrspace.h>
#include <asm/mach-ar7/ar7.h>
#include <asm/mach-ar7/gpio.h>
#include <asm/mach-ar7/prom.h>
+/*****************************************************************************
+ * VLYNQ Bus
+ ****************************************************************************/
struct plat_vlynq_data {
struct plat_vlynq_ops ops;
int gpio_bit;
int reset_bit;
};
-
static int vlynq_on(struct vlynq_device *dev)
{
- int result;
+ int ret;
struct plat_vlynq_data *pdata = dev->dev.platform_data;
- result = gpio_request(pdata->gpio_bit, "vlynq");
- if (result)
+ ret = gpio_request(pdata->gpio_bit, "vlynq");
+ if (ret)
goto out;
ar7_device_reset(pdata->reset_bit);
- result = ar7_gpio_disable(pdata->gpio_bit);
- if (result)
+ ret = ar7_gpio_disable(pdata->gpio_bit);
+ if (ret)
goto out_enabled;
- result = ar7_gpio_enable(pdata->gpio_bit);
- if (result)
+ ret = ar7_gpio_enable(pdata->gpio_bit);
+ if (ret)
goto out_enabled;
- result = gpio_direction_output(pdata->gpio_bit, 0);
- if (result)
+ ret = gpio_direction_output(pdata->gpio_bit, 0);
+ if (ret)
goto out_gpio_enabled;
msleep(50);
gpio_set_value(pdata->gpio_bit, 1);
+
msleep(50);
return 0;
@@ -83,320 +88,414 @@ out_enabled:
ar7_device_disable(pdata->reset_bit);
gpio_free(pdata->gpio_bit);
out:
- return result;
+ return ret;
}
static void vlynq_off(struct vlynq_device *dev)
{
struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
ar7_gpio_disable(pdata->gpio_bit);
gpio_free(pdata->gpio_bit);
ar7_device_disable(pdata->reset_bit);
}
-static struct resource physmap_flash_resource = {
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x10000000,
- .end = 0x107fffff,
-};
-
-static struct resource cpmac_low_res[] = {
+static struct resource vlynq_low_res[] = {
{
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_MAC0,
- .end = AR7_REGS_MAC0 + 0x7ff,
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ0,
+ .end = AR7_REGS_VLYNQ0 + 0xff,
},
{
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 27,
- .end = 27,
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 29,
+ .end = 29,
},
-};
-
-static struct resource cpmac_high_res[] = {
{
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_MAC1,
- .end = AR7_REGS_MAC1 + 0x7ff,
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x04000000,
+ .end = 0x04ffffff,
},
{
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 41,
- .end = 41,
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 80,
+ .end = 111,
},
};
-static struct resource vlynq_low_res[] = {
+static struct resource vlynq_high_res[] = {
{
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_VLYNQ0,
- .end = AR7_REGS_VLYNQ0 + 0xff,
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ1,
+ .end = AR7_REGS_VLYNQ1 + 0xff,
},
{
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 29,
- .end = 29,
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 33,
+ .end = 33,
},
{
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x04000000,
- .end = 0x04ffffff,
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
},
{
- .name = "devirq",
- .flags = IORESOURCE_IRQ,
- .start = 80,
- .end = 111,
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 112,
+ .end = 143,
},
};
-static struct resource vlynq_high_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_VLYNQ1,
- .end = AR7_REGS_VLYNQ1 + 0xff,
+static struct plat_vlynq_data vlynq_low_data = {
+ .ops = {
+ .on = vlynq_on,
+ .off = vlynq_off,
},
- {
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 33,
- .end = 33,
+ .reset_bit = 20,
+ .gpio_bit = 18,
+};
+
+static struct plat_vlynq_data vlynq_high_data = {
+ .ops = {
+ .on = vlynq_on,
+ .off = vlynq_off,
},
- {
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x0c000000,
- .end = 0x0cffffff,
+ .reset_bit = 16,
+ .gpio_bit = 19,
+};
+
+static struct platform_device vlynq_low = {
+ .id = 0,
+ .name = "vlynq",
+ .dev = {
+ .platform_data = &vlynq_low_data,
},
- {
- .name = "devirq",
- .flags = IORESOURCE_IRQ,
- .start = 112,
- .end = 143,
+ .resource = vlynq_low_res,
+ .num_resources = ARRAY_SIZE(vlynq_low_res),
+};
+
+static struct platform_device vlynq_high = {
+ .id = 1,
+ .name = "vlynq",
+ .dev = {
+ .platform_data = &vlynq_high_data,
},
+ .resource = vlynq_high_res,
+ .num_resources = ARRAY_SIZE(vlynq_high_res),
};
-static struct resource usb_res[] = {
- {
- .name = "regs",
- .flags = IORESOURCE_MEM,
- .start = AR7_REGS_USB,
- .end = AR7_REGS_USB + 0xff,
+/*****************************************************************************
+ * Flash
+ ****************************************************************************/
+static struct resource physmap_flash_resource = {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x10000000,
+ .end = 0x107fffff,
+};
+
+static const char *ar7_probe_types[] = { "ar7part", NULL };
+
+static struct physmap_flash_data physmap_flash_data = {
+ .width = 2,
+ .part_probe_types = ar7_probe_types,
+};
+
+static struct platform_device physmap_flash = {
+ .name = "physmap-flash",
+ .dev = {
+ .platform_data = &physmap_flash_data,
},
+ .resource = &physmap_flash_resource,
+ .num_resources = 1,
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+static struct resource cpmac_low_res[] = {
{
- .name = "irq",
- .flags = IORESOURCE_IRQ,
- .start = 32,
- .end = 32,
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_MAC0,
+ .end = AR7_REGS_MAC0 + 0x7ff,
},
{
- .name = "mem",
- .flags = IORESOURCE_MEM,
- .start = 0x03400000,
- .end = 0x03401fff,
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 27,
+ .end = 27,
},
};
-static struct physmap_flash_data physmap_flash_data = {
- .width = 2,
+static struct resource cpmac_high_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_MAC1,
+ .end = AR7_REGS_MAC1 + 0x7ff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 41,
+ .end = 41,
+ },
};
static struct fixed_phy_status fixed_phy_status __initdata = {
- .link = 1,
- .speed = 100,
- .duplex = 1,
+ .link = 1,
+ .speed = 100,
+ .duplex = 1,
};
static struct plat_cpmac_data cpmac_low_data = {
- .reset_bit = 17,
- .power_bit = 20,
- .phy_mask = 0x80000000,
+ .reset_bit = 17,
+ .power_bit = 20,
+ .phy_mask = 0x80000000,
};
static struct plat_cpmac_data cpmac_high_data = {
- .reset_bit = 21,
- .power_bit = 22,
- .phy_mask = 0x7fffffff,
-};
-
-static struct plat_vlynq_data vlynq_low_data = {
- .ops.on = vlynq_on,
- .ops.off = vlynq_off,
- .reset_bit = 20,
- .gpio_bit = 18,
-};
-
-static struct plat_vlynq_data vlynq_high_data = {
- .ops.on = vlynq_on,
- .ops.off = vlynq_off,
- .reset_bit = 16,
- .gpio_bit = 19,
-};
-
-static struct platform_device physmap_flash = {
- .id = 0,
- .name = "physmap-flash",
- .dev.platform_data = &physmap_flash_data,
- .resource = &physmap_flash_resource,
- .num_resources = 1,
+ .reset_bit = 21,
+ .power_bit = 22,
+ .phy_mask = 0x7fffffff,
};
static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
+
static struct platform_device cpmac_low = {
- .id = 0,
- .name = "cpmac",
+ .id = 0,
+ .name = "cpmac",
.dev = {
- .dma_mask = &cpmac_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &cpmac_low_data,
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &cpmac_low_data,
},
- .resource = cpmac_low_res,
- .num_resources = ARRAY_SIZE(cpmac_low_res),
+ .resource = cpmac_low_res,
+ .num_resources = ARRAY_SIZE(cpmac_low_res),
};
static struct platform_device cpmac_high = {
- .id = 1,
- .name = "cpmac",
+ .id = 1,
+ .name = "cpmac",
.dev = {
- .dma_mask = &cpmac_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &cpmac_high_data,
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &cpmac_high_data,
},
- .resource = cpmac_high_res,
- .num_resources = ARRAY_SIZE(cpmac_high_res),
+ .resource = cpmac_high_res,
+ .num_resources = ARRAY_SIZE(cpmac_high_res),
};
-static struct platform_device vlynq_low = {
- .id = 0,
- .name = "vlynq",
- .dev.platform_data = &vlynq_low_data,
- .resource = vlynq_low_res,
- .num_resources = ARRAY_SIZE(vlynq_low_res),
-};
+static void __init cpmac_get_mac(int instance, unsigned char *dev_addr)
+{
+ char name[5], *mac;
-static struct platform_device vlynq_high = {
- .id = 1,
- .name = "vlynq",
- .dev.platform_data = &vlynq_high_data,
- .resource = vlynq_high_res,
- .num_resources = ARRAY_SIZE(vlynq_high_res),
+ sprintf(name, "mac%c", 'a' + instance);
+ mac = prom_getenv(name);
+ if (!mac && instance) {
+ sprintf(name, "mac%c", 'a');
+ mac = prom_getenv(name);
+ }
+
+ if (mac) {
+ if (sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &dev_addr[0], &dev_addr[1],
+ &dev_addr[2], &dev_addr[3],
+ &dev_addr[4], &dev_addr[5]) != 6) {
+ pr_warning("cannot parse mac address, "
+ "using random address\n");
+ eth_random_addr(dev_addr);
+ }
+ } else
+ eth_random_addr(dev_addr);
+}
+
+/*****************************************************************************
+ * USB
+ ****************************************************************************/
+static struct resource usb_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_USB,
+ .end = AR7_REGS_USB + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 32,
+ .end = 32,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x03400000,
+ .end = 0x03401fff,
+ },
};
+static struct platform_device ar7_udc = {
+ .name = "ar7_udc",
+ .resource = usb_res,
+ .num_resources = ARRAY_SIZE(usb_res),
+};
+/*****************************************************************************
+ * LEDs
+ ****************************************************************************/
static struct gpio_led default_leds[] = {
{
- .name = "status",
- .gpio = 8,
- .active_low = 1,
+ .name = "status",
+ .gpio = 8,
+ .active_low = 1,
},
};
+static struct gpio_led titan_leds[] = {
+ { .name = "status", .gpio = 8, .active_low = 1, },
+ { .name = "wifi", .gpio = 13, .active_low = 1, },
+};
+
static struct gpio_led dsl502t_leds[] = {
{
- .name = "status",
- .gpio = 9,
- .active_low = 1,
+ .name = "status",
+ .gpio = 9,
+ .active_low = 1,
},
{
- .name = "ethernet",
- .gpio = 7,
- .active_low = 1,
+ .name = "ethernet",
+ .gpio = 7,
+ .active_low = 1,
},
{
- .name = "usb",
- .gpio = 12,
- .active_low = 1,
+ .name = "usb",
+ .gpio = 12,
+ .active_low = 1,
},
};
static struct gpio_led dg834g_leds[] = {
{
- .name = "ppp",
- .gpio = 6,
- .active_low = 1,
+ .name = "ppp",
+ .gpio = 6,
+ .active_low = 1,
},
{
- .name = "status",
- .gpio = 7,
- .active_low = 1,
+ .name = "status",
+ .gpio = 7,
+ .active_low = 1,
},
{
- .name = "adsl",
- .gpio = 8,
- .active_low = 1,
+ .name = "adsl",
+ .gpio = 8,
+ .active_low = 1,
},
{
- .name = "wifi",
- .gpio = 12,
- .active_low = 1,
+ .name = "wifi",
+ .gpio = 12,
+ .active_low = 1,
},
{
- .name = "power",
- .gpio = 14,
- .active_low = 1,
- .default_trigger = "default-on",
+ .name = "power",
+ .gpio = 14,
+ .active_low = 1,
+ .default_trigger = "default-on",
},
};
static struct gpio_led fb_sl_leds[] = {
{
- .name = "1",
- .gpio = 7,
+ .name = "1",
+ .gpio = 7,
},
{
- .name = "2",
- .gpio = 13,
- .active_low = 1,
+ .name = "2",
+ .gpio = 13,
+ .active_low = 1,
},
{
- .name = "3",
- .gpio = 10,
- .active_low = 1,
+ .name = "3",
+ .gpio = 10,
+ .active_low = 1,
},
{
- .name = "4",
- .gpio = 12,
- .active_low = 1,
+ .name = "4",
+ .gpio = 12,
+ .active_low = 1,
},
{
- .name = "5",
- .gpio = 9,
- .active_low = 1,
+ .name = "5",
+ .gpio = 9,
+ .active_low = 1,
},
};
static struct gpio_led fb_fon_leds[] = {
{
- .name = "1",
- .gpio = 8,
+ .name = "1",
+ .gpio = 8,
+ },
+ {
+ .name = "2",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+ .name = "3",
+ .gpio = 5,
+ },
+ {
+ .name = "4",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+ .name = "5",
+ .gpio = 11,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led gt701_leds[] = {
+ {
+ .name = "inet:green",
+ .gpio = 13,
+ .active_low = 1,
+ },
+ {
+ .name = "usb",
+ .gpio = 12,
+ .active_low = 1,
},
{
- .name = "2",
- .gpio = 3,
- .active_low = 1,
+ .name = "inet:red",
+ .gpio = 9,
+ .active_low = 1,
},
{
- .name = "3",
- .gpio = 5,
+ .name = "power:red",
+ .gpio = 7,
+ .active_low = 1,
},
{
- .name = "4",
- .gpio = 4,
- .active_low = 1,
+ .name = "power:green",
+ .gpio = 8,
+ .active_low = 1,
+ .default_trigger = "default-on",
},
{
- .name = "5",
- .gpio = 11,
- .active_low = 1,
+ .name = "ethernet",
+ .gpio = 10,
+ .active_low = 1,
},
};
@@ -404,74 +503,16 @@ static struct gpio_led_platform_data ar7_led_data;
static struct platform_device ar7_gpio_leds = {
.name = "leds-gpio",
- .id = -1,
.dev = {
.platform_data = &ar7_led_data,
}
};
-static struct platform_device ar7_udc = {
- .id = -1,
- .name = "ar7_udc",
- .resource = usb_res,
- .num_resources = ARRAY_SIZE(usb_res),
-};
-
-static struct resource ar7_wdt_res = {
- .name = "regs",
- .start = -1, /* Filled at runtime */
- .end = -1, /* Filled at runtime */
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ar7_wdt = {
- .id = -1,
- .name = "ar7_wdt",
- .resource = &ar7_wdt_res,
- .num_resources = 1,
-};
-
-static inline unsigned char char2hex(char h)
-{
- switch (h) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- return h - '0';
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- return h - 'A' + 10;
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- return h - 'a' + 10;
- default:
- return 0;
- }
-}
-
-static void cpmac_get_mac(int instance, unsigned char *dev_addr)
-{
- int i;
- char name[5], default_mac[ETH_ALEN], *mac;
-
- mac = NULL;
- sprintf(name, "mac%c", 'a' + instance);
- mac = prom_getenv(name);
- if (!mac) {
- sprintf(name, "mac%c", 'a');
- mac = prom_getenv(name);
- }
- if (!mac) {
- random_ether_addr(default_mac);
- mac = default_mac;
- }
- for (i = 0; i < 6; i++)
- dev_addr[i] = (char2hex(mac[i * 3]) << 4) +
- char2hex(mac[i * 3 + 1]);
-}
-
static void __init detect_leds(void)
{
char *prid, *usb_prod;
- /* Default LEDs */
+ /* Default LEDs */
ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
ar7_led_data.leds = default_leds;
@@ -496,114 +537,198 @@ static void __init detect_leds(void)
} else if (strstr(prid, "DG834")) {
ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
ar7_led_data.leds = dg834g_leds;
+ } else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(titan_leds);
+ ar7_led_data.leds = titan_leds;
+ } else if (strstr(prid, "GT701")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds);
+ ar7_led_data.leds = gt701_leds;
}
}
-static int __init ar7_register_devices(void)
+/*****************************************************************************
+ * Watchdog
+ ****************************************************************************/
+static struct resource ar7_wdt_res = {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = -1, /* Filled at runtime */
+ .end = -1, /* Filled at runtime */
+};
+
+static struct platform_device ar7_wdt = {
+ .name = "ar7_wdt",
+ .resource = &ar7_wdt_res,
+ .num_resources = 1,
+};
+
+/*****************************************************************************
+ * Init
+ ****************************************************************************/
+static int __init ar7_register_uarts(void)
{
- u16 chip_id;
- int res;
- u32 *bootcr, val;
#ifdef CONFIG_SERIAL_8250
- static struct uart_port uart_port[2] __initdata;
-
- memset(uart_port, 0, sizeof(struct uart_port) * 2);
-
- uart_port[0].type = PORT_16550A;
- uart_port[0].line = 0;
- uart_port[0].irq = AR7_IRQ_UART0;
- uart_port[0].uartclk = ar7_bus_freq() / 2;
- uart_port[0].iotype = UPIO_MEM32;
- uart_port[0].mapbase = AR7_REGS_UART0;
- uart_port[0].membase = ioremap(uart_port[0].mapbase, 256);
- uart_port[0].regshift = 2;
- res = early_serial_setup(&uart_port[0]);
+ static struct uart_port uart_port __initdata;
+ struct clk *bus_clk;
+ int res;
+
+ memset(&uart_port, 0, sizeof(struct uart_port));
+
+ bus_clk = clk_get(NULL, "bus");
+ if (IS_ERR(bus_clk))
+ panic("unable to get bus clk");
+
+ uart_port.type = PORT_AR7;
+ uart_port.uartclk = clk_get_rate(bus_clk) / 2;
+ uart_port.iotype = UPIO_MEM32;
+ uart_port.regshift = 2;
+
+ uart_port.line = 0;
+ uart_port.irq = AR7_IRQ_UART0;
+ uart_port.mapbase = AR7_REGS_UART0;
+ uart_port.membase = ioremap(uart_port.mapbase, 256);
+
+ res = early_serial_setup(&uart_port);
if (res)
return res;
-
/* Only TNETD73xx have a second serial port */
if (ar7_has_second_uart()) {
- uart_port[1].type = PORT_16550A;
- uart_port[1].line = 1;
- uart_port[1].irq = AR7_IRQ_UART1;
- uart_port[1].uartclk = ar7_bus_freq() / 2;
- uart_port[1].iotype = UPIO_MEM32;
- uart_port[1].mapbase = UR8_REGS_UART1;
- uart_port[1].membase = ioremap(uart_port[1].mapbase, 256);
- uart_port[1].regshift = 2;
- res = early_serial_setup(&uart_port[1]);
+ uart_port.line = 1;
+ uart_port.irq = AR7_IRQ_UART1;
+ uart_port.mapbase = UR8_REGS_UART1;
+ uart_port.membase = ioremap(uart_port.mapbase, 256);
+
+ res = early_serial_setup(&uart_port);
if (res)
return res;
}
-#endif /* CONFIG_SERIAL_8250 */
+#endif
+
+ return 0;
+}
+
+static void __init titan_fixup_devices(void)
+{
+ /* Set vlynq0 data */
+ vlynq_low_data.reset_bit = 15;
+ vlynq_low_data.gpio_bit = 14;
+
+ /* Set vlynq1 data */
+ vlynq_high_data.reset_bit = 16;
+ vlynq_high_data.gpio_bit = 7;
+
+ /* Set vlynq0 resources */
+ vlynq_low_res[0].start = TITAN_REGS_VLYNQ0;
+ vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff;
+ vlynq_low_res[1].start = 33;
+ vlynq_low_res[1].end = 33;
+ vlynq_low_res[2].start = 0x0c000000;
+ vlynq_low_res[2].end = 0x0fffffff;
+ vlynq_low_res[3].start = 80;
+ vlynq_low_res[3].end = 111;
+
+ /* Set vlynq1 resources */
+ vlynq_high_res[0].start = TITAN_REGS_VLYNQ1;
+ vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff;
+ vlynq_high_res[1].start = 34;
+ vlynq_high_res[1].end = 34;
+ vlynq_high_res[2].start = 0x40000000;
+ vlynq_high_res[2].end = 0x43ffffff;
+ vlynq_high_res[3].start = 112;
+ vlynq_high_res[3].end = 143;
+
+ /* Set cpmac0 data */
+ cpmac_low_data.phy_mask = 0x40000000;
+
+ /* Set cpmac1 data */
+ cpmac_high_data.phy_mask = 0x80000000;
+
+ /* Set cpmac0 resources */
+ cpmac_low_res[0].start = TITAN_REGS_MAC0;
+ cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff;
+
+ /* Set cpmac1 resources */
+ cpmac_high_res[0].start = TITAN_REGS_MAC1;
+ cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff;
+}
+
+static int __init ar7_register_devices(void)
+{
+ void __iomem *bootcr;
+ u32 val;
+ int res;
+
+ res = ar7_register_uarts();
+ if (res)
+ pr_err("unable to setup uart(s): %d\n", res);
+
res = platform_device_register(&physmap_flash);
if (res)
- return res;
+ pr_warning("unable to register physmap-flash: %d\n", res);
+
+ if (ar7_is_titan())
+ titan_fixup_devices();
ar7_device_disable(vlynq_low_data.reset_bit);
res = platform_device_register(&vlynq_low);
if (res)
- return res;
+ pr_warning("unable to register vlynq-low: %d\n", res);
if (ar7_has_high_vlynq()) {
ar7_device_disable(vlynq_high_data.reset_bit);
res = platform_device_register(&vlynq_high);
if (res)
- return res;
+ pr_warning("unable to register vlynq-high: %d\n", res);
}
if (ar7_has_high_cpmac()) {
res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
- if (res && res != -ENODEV)
- return res;
- cpmac_get_mac(1, cpmac_high_data.dev_addr);
- res = platform_device_register(&cpmac_high);
- if (res)
- return res;
- } else {
+ if (!res) {
+ cpmac_get_mac(1, cpmac_high_data.dev_addr);
+
+ res = platform_device_register(&cpmac_high);
+ if (res)
+ pr_warning("unable to register cpmac-high: %d\n", res);
+ } else
+ pr_warning("unable to add cpmac-high phy: %d\n", res);
+ } else
cpmac_low_data.phy_mask = 0xffffffff;
- }
res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
- if (res && res != -ENODEV)
- return res;
-
- cpmac_get_mac(0, cpmac_low_data.dev_addr);
- res = platform_device_register(&cpmac_low);
- if (res)
- return res;
+ if (!res) {
+ cpmac_get_mac(0, cpmac_low_data.dev_addr);
+ res = platform_device_register(&cpmac_low);
+ if (res)
+ pr_warning("unable to register cpmac-low: %d\n", res);
+ } else
+ pr_warning("unable to add cpmac-low phy: %d\n", res);
detect_leds();
res = platform_device_register(&ar7_gpio_leds);
if (res)
- return res;
+ pr_warning("unable to register leds: %d\n", res);
res = platform_device_register(&ar7_udc);
+ if (res)
+ pr_warning("unable to register usb slave: %d\n", res);
- chip_id = ar7_chip_id();
- switch (chip_id) {
- case AR7_CHIP_7100:
- case AR7_CHIP_7200:
- ar7_wdt_res.start = AR7_REGS_WDT;
- break;
- case AR7_CHIP_7300:
- ar7_wdt_res.start = UR8_REGS_WDT;
- break;
- default:
- break;
- }
-
- ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
-
- bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
- val = *bootcr;
+ /* Register watchdog only if enabled in hardware */
+ bootcr = ioremap_nocache(AR7_REGS_DCL, 4);
+ val = readl(bootcr);
iounmap(bootcr);
+ if (val & AR7_WDT_HW_ENA) {
+ if (ar7_has_high_vlynq())
+ ar7_wdt_res.start = UR8_REGS_WDT;
+ else
+ ar7_wdt_res.start = AR7_REGS_WDT;
- /* Register watchdog only if enabled in hardware */
- if (val & AR7_WDT_HW_ENA)
+ ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
res = platform_device_register(&ar7_wdt);
+ if (res)
+ pr_warning("unable to register watchdog: %d\n", res);
+ }
- return res;
+ return 0;
}
-arch_initcall(ar7_register_devices);
+device_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
index c1fdd368281..a23adc49d50 100644
--- a/arch/mips/ar7/prom.c
+++ b/arch/mips/ar7/prom.c
@@ -32,8 +32,8 @@
#define MAX_ENTRY 80
struct env_var {
- char *name;
- char *value;
+ char *name;
+ char *value;
};
static struct env_var adam2_env[MAX_ENTRY];
@@ -41,6 +41,7 @@ static struct env_var adam2_env[MAX_ENTRY];
char *prom_getenv(const char *name)
{
int i;
+
for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
if (!strcmp(name, adam2_env[i].name))
return adam2_env[i].value;
@@ -49,65 +50,50 @@ char *prom_getenv(const char *name)
}
EXPORT_SYMBOL(prom_getenv);
-char * __init prom_getcmdline(void)
-{
- return &(arcs_cmdline[0]);
-}
-
static void __init ar7_init_cmdline(int argc, char *argv[])
{
- char *cp;
- int actr;
-
- actr = 1; /* Always ignore argv[0] */
+ int i;
- cp = &(arcs_cmdline[0]);
- while (actr < argc) {
- strcpy(cp, argv[actr]);
- cp += strlen(argv[actr]);
- *cp++ = ' ';
- actr++;
- }
- if (cp != &(arcs_cmdline[0])) {
- /* get rid of trailing space */
- --cp;
- *cp = '\0';
+ for (i = 1; i < argc; i++) {
+ strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE);
+ if (i < (argc - 1))
+ strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
}
}
struct psbl_rec {
- u32 psbl_size;
- u32 env_base;
- u32 env_size;
- u32 ffs_base;
- u32 ffs_size;
+ u32 psbl_size;
+ u32 env_base;
+ u32 env_size;
+ u32 ffs_base;
+ u32 ffs_size;
};
-static __initdata char psp_env_version[] = "TIENV0.8";
+static const char psp_env_version[] __initconst = "TIENV0.8";
struct psp_env_chunk {
- u8 num;
- u8 ctrl;
- u16 csum;
- u8 len;
- char data[11];
-} __attribute__ ((packed));
+ u8 num;
+ u8 ctrl;
+ u16 csum;
+ u8 len;
+ char data[11];
+} __packed;
struct psp_var_map_entry {
- u8 num;
- char *value;
+ u8 num;
+ char *value;
};
-static struct psp_var_map_entry psp_var_map[] = {
- { 1, "cpufrequency" },
- { 2, "memsize" },
- { 3, "flashsize" },
- { 4, "modetty0" },
- { 5, "modetty1" },
- { 8, "maca" },
- { 9, "macb" },
- { 28, "sysfrequency" },
- { 38, "mipsfrequency" },
+static const struct psp_var_map_entry psp_var_map[] = {
+ { 1, "cpufrequency" },
+ { 2, "memsize" },
+ { 3, "flashsize" },
+ { 4, "modetty0" },
+ { 5, "modetty1" },
+ { 8, "maca" },
+ { 9, "macb" },
+ { 28, "sysfrequency" },
+ { 38, "mipsfrequency" },
};
/*
@@ -154,6 +140,7 @@ static char * __init lookup_psp_var_map(u8 num)
static void __init add_adam2_var(char *name, char *value)
{
int i;
+
for (i = 0; i < MAX_ENTRY; i++) {
if (!adam2_env[i].name) {
adam2_env[i].name = name;
@@ -216,7 +203,7 @@ static void __init console_config(void)
char parity = '\0', bits = '\0', flow = '\0';
char *s, *p;
- if (strstr(prom_getcmdline(), "console="))
+ if (strstr(arcs_cmdline, "console="))
return;
s = prom_getenv("modetty0");
@@ -250,7 +237,7 @@ static void __init console_config(void)
else
sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
bits);
- strcat(prom_getcmdline(), console_string);
+ strlcat(arcs_cmdline, console_string, COMMAND_LINE_SIZE);
#endif
}
@@ -259,6 +246,8 @@ void __init prom_init(void)
ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
ar7_init_env((struct env_var *)fw_arg2);
console_config();
+
+ ar7_gpio_init();
}
#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
@@ -279,4 +268,3 @@ int prom_putchar(char c)
serial_out(UART_TX, c);
return 1;
}
-
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
index 39f6b5b9646..820b7a313d9 100644
--- a/arch/mips/ar7/setup.c
+++ b/arch/mips/ar7/setup.c
@@ -23,11 +23,12 @@
#include <asm/reboot.h>
#include <asm/mach-ar7/ar7.h>
#include <asm/mach-ar7/prom.h>
+#include <asm/mach-ar7/gpio.h>
static void ar7_machine_restart(char *command)
{
- u32 *softres_reg = ioremap(AR7_REGS_RESET +
- AR7_RESET_SOFTWARE, 1);
+ u32 *softres_reg = ioremap(AR7_REGS_RESET + AR7_RESET_SOFTWARE, 1);
+
writel(1, softres_reg);
}
@@ -41,6 +42,7 @@ static void ar7_machine_power_off(void)
{
u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1);
u32 power_state = readl(power_reg) | (3 << 30);
+
writel(power_state, power_reg);
ar7_machine_halt();
}
@@ -48,15 +50,28 @@ static void ar7_machine_power_off(void)
const char *get_system_type(void)
{
u16 chip_id = ar7_chip_id();
+ u16 titan_variant_id = titan_chip_id();
+
switch (chip_id) {
- case AR7_CHIP_7300:
- return "TI AR7 (TNETD7300)";
case AR7_CHIP_7100:
return "TI AR7 (TNETD7100)";
case AR7_CHIP_7200:
return "TI AR7 (TNETD7200)";
+ case AR7_CHIP_7300:
+ return "TI AR7 (TNETD7300)";
+ case AR7_CHIP_TITAN:
+ switch (titan_variant_id) {
+ case TITAN_CHIP_1050:
+ return "TI AR7 (TNETV1050)";
+ case TITAN_CHIP_1055:
+ return "TI AR7 (TNETV1055)";
+ case TITAN_CHIP_1056:
+ return "TI AR7 (TNETV1056)";
+ case TITAN_CHIP_1060:
+ return "TI AR7 (TNETV1060)";
+ }
default:
- return "TI AR7 (Unknown)";
+ return "TI AR7 (unknown)";
}
}
@@ -70,7 +85,6 @@ console_initcall(ar7_init_console);
* Initializes basic routines and structures pointers, memory size (as
* given by the bios and saves the command line.
*/
-
void __init plat_mem_setup(void)
{
unsigned long io_base;
@@ -78,16 +92,14 @@ void __init plat_mem_setup(void)
_machine_restart = ar7_machine_restart;
_machine_halt = ar7_machine_halt;
pm_power_off = ar7_machine_power_off;
- panic_timeout = 3;
io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
if (!io_base)
- panic("Can't remap IO base!\n");
+ panic("Can't remap IO base!");
set_io_port_base(io_base);
prom_meminit();
printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
- get_system_type(),
- ar7_chip_id(), ar7_chip_rev());
+ get_system_type(), ar7_chip_id(), ar7_chip_rev());
}
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
index a1fba894daa..22c93213b23 100644
--- a/arch/mips/ar7/time.c
+++ b/arch/mips/ar7/time.c
@@ -20,11 +20,24 @@
#include <linux/init.h>
#include <linux/time.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/time.h>
#include <asm/mach-ar7/ar7.h>
void __init plat_time_init(void)
{
- mips_hpt_frequency = ar7_cpu_freq() / 2;
+ struct clk *cpu_clk;
+
+ /* Initialize ar7 clocks so the CPU clock frequency is correct */
+ ar7_init_clocks();
+
+ cpu_clk = clk_get(NULL, "cpu");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_ERR "unable to get cpu clock\n");
+ return;
+ }
+
+ mips_hpt_frequency = clk_get_rate(cpu_clk) / 2;
}