* [PATCH 5/8] add Texas Instruments AR7 support
@ 2009-06-04 14:19 Florian Fainelli
[not found] ` <200906161428.33571.florian@openwrt.org>
0 siblings, 1 reply; 11+ messages in thread
From: Florian Fainelli @ 2009-06-04 14:19 UTC (permalink / raw)
To: Ralf Baechle, Linux-MIPS
This patch adds support for the Texas Instruments
AR7 System-on-Chip.
Changes from v1:
- simplified mach-ar7/spaces.h
- removed superfluous parenthesis
- use lib/gcd.c
- select VLYNQ
- removed non-8250 UART code, there are only 8250 UARTs in use
Signed-off-by: Matteo Croce <matteo@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Eugene Konev <ejka@imfi.kspu.ru>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c4a84a6..faf0bb9 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -22,6 +22,24 @@ choice
config MACH_ALCHEMY
bool "Alchemy processor based machines"
+config AR7
+ bool "Texas Instruments AR7"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select CEVT_R4K
+ select CSRC_R4K
+ select IRQ_CPU
+ select NO_EXCEPT_FILL
+ select SWAP_IO_SPACE
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_KGDB
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select GENERIC_GPIO
+ select GCD
+ select VLYNQ
+
config BASLER_EXCITE
bool "Basler eXcite smart camera"
select CEVT_R4K
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 52a3509..e22f595 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -173,6 +173,13 @@ libs-y += arch/mips/fw/lib/
#
#
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7) += arch/mips/ar7/
+cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7) += 0xffffffff94100000
+
+#
# Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
#
core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
new file mode 100644
index 0000000..7435e44
--- /dev/null
+++ b/arch/mips/ar7/Makefile
@@ -0,0 +1,10 @@
+
+obj-y := \
+ prom.o \
+ setup.o \
+ memory.o \
+ irq.o \
+ time.o \
+ platform.o \
+ gpio.o \
+ clock.o
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
new file mode 100644
index 0000000..ead7df8
--- /dev/null
+++ b/arch/mips/ar7/clock.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gcd.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define BOOT_PLL_SOURCE_MASK 0x3
+#define CPU_PLL_SOURCE_SHIFT 16
+#define BUS_PLL_SOURCE_SHIFT 14
+#define USB_PLL_SOURCE_SHIFT 18
+#define DSP_PLL_SOURCE_SHIFT 22
+#define BOOT_PLL_SOURCE_AFE 0
+#define BOOT_PLL_SOURCE_BUS 0
+#define BOOT_PLL_SOURCE_REF 1
+#define BOOT_PLL_SOURCE_XTAL 2
+#define BOOT_PLL_SOURCE_CPU 3
+#define BOOT_PLL_BYPASS 0x00000020
+#define BOOT_PLL_ASYNC_MODE 0x02000000
+#define BOOT_PLL_2TO1_MODE 0x00008000
+
+#define TNETD7200_CLOCK_ID_CPU 0
+#define TNETD7200_CLOCK_ID_DSP 1
+#define TNETD7200_CLOCK_ID_USB 2
+
+#define TNETD7200_DEF_CPU_CLK 211000000
+#define TNETD7200_DEF_DSP_CLK 125000000
+#define TNETD7200_DEF_USB_CLK 48000000
+
+struct tnetd7300_clock {
+ u32 ctrl;
+#define PREDIV_MASK 0x001f0000
+#define PREDIV_SHIFT 16
+#define POSTDIV_MASK 0x0000001f
+ u32 unused1[3];
+ u32 pll;
+#define MUL_MASK 0x0000f000
+#define MUL_SHIFT 12
+#define PLL_MODE_MASK 0x00000001
+#define PLL_NDIV 0x00000800
+#define PLL_DIV 0x00000002
+#define PLL_STATUS 0x00000001
+ u32 unused2[3];
+};
+
+struct tnetd7300_clocks {
+ struct tnetd7300_clock bus;
+ struct tnetd7300_clock cpu;
+ struct tnetd7300_clock usb;
+ struct tnetd7300_clock dsp;
+};
+
+struct tnetd7200_clock {
+ u32 ctrl;
+ u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+ u32 mul;
+ u32 prediv;
+ u32 postdiv;
+ u32 postdiv2;
+ u32 unused2[6];
+ u32 cmd;
+ u32 status;
+ u32 cmden;
+ u32 padding[15];
+};
+
+struct tnetd7200_clocks {
+ struct tnetd7200_clock cpu;
+ struct tnetd7200_clock dsp;
+ 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 void approximate(int base, int target, int *prediv,
+ int *postdiv, int *mul)
+{
+ int i, j, k, freq, res = target;
+ for (i = 1; i <= 16; i++)
+ for (j = 1; j <= 32; j++)
+ for (k = 1; k <= 32; k++) {
+ freq = abs(base / j * i / k - target);
+ if (freq < res) {
+ res = freq;
+ *mul = i;
+ *prediv = j;
+ *postdiv = k;
+ }
+ }
+}
+
+static void calculate(int base, int target, int *prediv, int *postdiv,
+ int *mul)
+{
+ int tmp_gcd, tmp_base, tmp_freq;
+
+ for (*prediv = 1; *prediv <= 32; (*prediv)++) {
+ tmp_base = base / *prediv;
+ tmp_gcd = gcd(target, tmp_base);
+ *mul = target / tmp_gcd;
+ *postdiv = tmp_base / tmp_gcd;
+ if ((*mul < 1) || (*mul >= 16))
+ continue;
+ if ((*postdiv > 0) & (*postdiv <= 32))
+ break;
+ }
+
+ if (base / *prediv * *mul / *postdiv != target) {
+ approximate(base, target, prediv, postdiv, mul);
+ tmp_freq = base / *prediv * *mul / *postdiv;
+ printk(KERN_WARNING
+ "Adjusted requested frequency %d to %d\n",
+ target, tmp_freq);
+ }
+
+ printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
+ *prediv, *postdiv, *mul);
+}
+
+static int tnetd7300_dsp_clock(void)
+{
+ u32 didr1, didr2;
+ u8 rev = ar7_chip_rev();
+ didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
+ didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
+ if (didr2 & (1 << 23))
+ return 0;
+ if ((rev >= 0x23) && (rev != 0x57))
+ return 250000000;
+ if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
+ > 4208000)
+ return 250000000;
+ return 0;
+}
+
+static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
+ u32 *bootcr, u32 bus_clock)
+{
+ int product;
+ int base_clock = AR7_REF_CLOCK;
+ u32 ctrl = readl(&clock->ctrl);
+ u32 pll = readl(&clock->pll);
+ int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
+ int postdiv = (ctrl & POSTDIV_MASK) + 1;
+ int divisor = prediv * postdiv;
+ int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
+
+ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+ case BOOT_PLL_SOURCE_BUS:
+ base_clock = bus_clock;
+ break;
+ case BOOT_PLL_SOURCE_REF:
+ base_clock = AR7_REF_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_XTAL:
+ base_clock = AR7_XTAL_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_CPU:
+ base_clock = ar7_cpu_clock;
+ break;
+ }
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base_clock / divisor;
+
+ if ((pll & PLL_MODE_MASK) == 0)
+ return (base_clock >> (mul / 16 + 1)) / divisor;
+
+ if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
+ product = (mul & 1) ?
+ (base_clock * mul) >> 1 :
+ (base_clock * (mul - 1)) >> 2;
+ return product / divisor;
+ }
+
+ if (mul == 16)
+ return base_clock / divisor;
+
+ return base_clock * mul / divisor;
+}
+
+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;
+
+ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+ case BOOT_PLL_SOURCE_BUS:
+ base_clock = ar7_bus_clock;
+ break;
+ case BOOT_PLL_SOURCE_REF:
+ base_clock = AR7_REF_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_XTAL:
+ base_clock = AR7_XTAL_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_CPU:
+ base_clock = ar7_cpu_clock;
+ break;
+ }
+
+ calculate(base_clock, frequency, &prediv, &postdiv, &mul);
+
+ writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
+ mdelay(1);
+ writel(4, &clock->pll);
+ while (readl(&clock->pll) & PLL_STATUS)
+ ;
+ writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
+ mdelay(75);
+}
+
+static void __init tnetd7300_init_clocks(void)
+{
+ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ struct tnetd7300_clocks *clocks =
+ (struct tnetd7300_clocks *)
+ ioremap_nocache(AR7_REGS_POWER + 0x20,
+ sizeof(struct tnetd7300_clocks));
+
+ ar7_bus_clock = 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,
+ &clocks->cpu, bootcr, AR7_AFE_CLOCK);
+ else
+ ar7_cpu_clock = ar7_bus_clock;
+/*
+ tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
+ bootcr, 48000000);
+*/
+ if (ar7_dsp_clock == 250000000)
+ tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
+ bootcr, ar7_dsp_clock);
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock,
+ u32 *bootcr, u32 bus_clock)
+{
+ int divisor = ((readl(&clock->prediv) & 0x1f) + 1) *
+ ((readl(&clock->postdiv) & 0x1f) + 1);
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base / divisor;
+
+ return base * ((readl(&clock->mul) & 0xf) + 1) / divisor;
+}
+
+
+static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
+ int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
+{
+ printk(KERN_INFO
+ "Clocks: base = %d, frequency = %u, prediv = %d, "
+ "postdiv = %d, postdiv2 = %d, mul = %d\n",
+ base, frequency, prediv, postdiv, postdiv2, mul);
+
+ writel(0, &clock->ctrl);
+ writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+ writel((mul - 1) & 0xF, &clock->mul);
+
+ for (mul = 0; mul < 2000; mul++)
+ ; /* nop */
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
+
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
+
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(readl(&clock->ctrl) | 1, &clock->ctrl);
+}
+
+static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
+{
+ if (*bootcr & BOOT_PLL_ASYNC_MODE)
+ /* Async */
+ switch (clock_id) {
+ case TNETD7200_CLOCK_ID_DSP:
+ return AR7_REF_CLOCK;
+ default:
+ return AR7_AFE_CLOCK;
+ }
+ else
+ /* Sync */
+ if (*bootcr & BOOT_PLL_2TO1_MODE)
+ /* 2:1 */
+ switch (clock_id) {
+ case TNETD7200_CLOCK_ID_DSP:
+ return AR7_REF_CLOCK;
+ default:
+ return AR7_AFE_CLOCK;
+ }
+ else
+ /* 1:1 */
+ return AR7_REF_CLOCK;
+}
+
+
+static void __init tnetd7200_init_clocks(void)
+{
+ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ struct tnetd7200_clocks *clocks =
+ (struct tnetd7200_clocks *)
+ ioremap_nocache(AR7_REGS_POWER + 0x80,
+ sizeof(struct tnetd7200_clocks));
+ int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
+ int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
+ int usb_base, usb_mul, usb_prediv, usb_postdiv;
+
+ cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
+ dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
+
+ if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+ printk(KERN_INFO "Clocks: Async 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) / dsp_postdiv;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
+ ar7_bus_clock);
+
+ 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_postdiv;
+ tnetd7200_set_clock(cpu_base, &clocks->cpu,
+ cpu_prediv, cpu_postdiv, -1, cpu_mul,
+ ar7_cpu_clock);
+
+ } else
+ if (*bootcr & BOOT_PLL_2TO1_MODE) {
+ printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
+
+ 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_postdiv;
+ tnetd7200_set_clock(cpu_base, &clocks->cpu,
+ cpu_prediv, cpu_postdiv, -1, cpu_mul,
+ ar7_cpu_clock);
+
+ 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;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+ dsp_mul * 2, ar7_bus_clock);
+ } 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)
+ / dsp_postdiv;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+ dsp_mul * 2, ar7_bus_clock);
+
+ ar7_cpu_clock = ar7_bus_clock;
+ }
+
+ printk(KERN_INFO "Clocks: Setting USB clock\n");
+ usb_base = ar7_bus_clock;
+ 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;
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+void __init ar7_init_clocks(void)
+{
+ switch (ar7_chip_id()) {
+ case AR7_CHIP_7100:
+ tnetd7200_init_clocks();
+ break;
+ case AR7_CHIP_7200:
+ tnetd7200_init_clocks();
+ break;
+ case AR7_CHIP_7300:
+ ar7_dsp_clock = tnetd7300_dsp_clock();
+ tnetd7300_init_clocks();
+ break;
+ default:
+ break;
+ }
+}
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
new file mode 100644
index 0000000..74e14a3
--- /dev/null
+++ b/arch/mips/ar7/gpio.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach-ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX];
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ if (ar7_gpio_list[gpio])
+ return -EBUSY;
+
+ if (label)
+ ar7_gpio_list[gpio] = label;
+ else
+ ar7_gpio_list[gpio] = "busy";
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+ BUG_ON(!ar7_gpio_list[gpio]);
+ ar7_gpio_list[gpio] = NULL;
+}
+EXPORT_SYMBOL(gpio_free);
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
new file mode 100644
index 0000000..fb3756f
--- /dev/null
+++ b/arch/mips/ar7/irq.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define EXCEPT_OFFSET 0x80
+#define PACE_OFFSET 0xA0
+#define CHNLS_OFFSET 0x200
+
+#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10)
+#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8)
+#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */
+#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */
+#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */
+#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */
+#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */
+#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */
+#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */
+#define PIR_OFFSET (0x40)
+#define MSR_OFFSET (0x44)
+#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */
+#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */
+
+#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
+
+#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
+
+static void ar7_unmask_irq(unsigned int irq_nr);
+static void ar7_mask_irq(unsigned int irq_nr);
+static void ar7_ack_irq(unsigned int irq_nr);
+static void ar7_unmask_sec_irq(unsigned int irq_nr);
+static void ar7_mask_sec_irq(unsigned int irq_nr);
+static void ar7_ack_sec_irq(unsigned int irq_nr);
+static void ar7_cascade(void);
+static void ar7_irq_init(int base);
+static int ar7_irq_base;
+
+static struct irq_chip ar7_irq_type = {
+ .name = "AR7",
+ .unmask = ar7_unmask_irq,
+ .mask = ar7_mask_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,
+};
+
+static struct irqaction ar7_cascade_action = {
+ .handler = no_action,
+ .name = "AR7 cascade interrupt"
+};
+
+static void ar7_unmask_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(ESR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_mask_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(ECR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_ack_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(CR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_unmask_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+}
+
+static void ar7_mask_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+}
+
+static void ar7_ack_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+ ar7_irq_init(8);
+}
+
+static void __init ar7_irq_init(int base)
+{
+ int i;
+ /*
+ * Disable interrupts and clear pending
+ */
+ writel(0xffffffff, REG(ECR_OFFSET(0)));
+ writel(0xff, REG(ECR_OFFSET(32)));
+ writel(0xffffffff, REG(SEC_ECR_OFFSET));
+ writel(0xffffffff, REG(CR_OFFSET(0)));
+ writel(0xff, REG(CR_OFFSET(32)));
+ writel(0xffffffff, REG(SEC_CR_OFFSET));
+
+ ar7_irq_base = 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,
+ handle_level_irq);
+ /* Secondary IRQ's */
+ if (i < 32)
+ set_irq_chip_and_handler(base + i + 40,
+ &ar7_sec_irq_type,
+ handle_level_irq);
+ }
+
+ setup_irq(2, &ar7_cascade_action);
+ setup_irq(ar7_irq_base, &ar7_cascade_action);
+ set_c0_status(IE_IRQ0);
+}
+
+static void ar7_cascade(void)
+{
+ u32 status;
+ int i, irq;
+
+ /* Primary IRQ's */
+ irq = readl(REG(PIR_OFFSET)) & 0x3f;
+ if (irq) {
+ do_IRQ(ar7_irq_base + irq);
+ return;
+ }
+
+ /* Secondary IRQ's are cascaded through primary '0' */
+ writel(1, REG(CR_OFFSET(irq)));
+ status = readl(REG(SEC_SR_OFFSET));
+ for (i = 0; i < 32; i++) {
+ if (status & 1) {
+ do_IRQ(ar7_irq_base + i + 40);
+ return;
+ }
+ status >>= 1;
+ }
+
+ spurious_interrupt();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(7);
+ else if (pending & STATUSF_IP2) /* int0 hardware line */
+ ar7_cascade();
+ else
+ spurious_interrupt();
+}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
new file mode 100644
index 0000000..2e7910d
--- /dev/null
+++ b/arch/mips/ar7/memory.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mips-boards/prom.h>
+
+static int __init memsize(void)
+{
+ u32 size = (64 << 20);
+ u32 *addr = (u32 *)KSEG1ADDR(0x14000000 + size - 4);
+ u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+ u32 *tmpaddr = addr;
+
+ while (tmpaddr > kernel_end) {
+ *tmpaddr = (u32)tmpaddr;
+ size >>= 1;
+ tmpaddr -= size >> 2;
+ }
+
+ do {
+ tmpaddr += size >> 2;
+ if (*tmpaddr != (u32)tmpaddr)
+ break;
+ size <<= 1;
+ } while (size < (64 << 20));
+
+ writel(tmpaddr, &addr);
+
+ return size;
+}
+
+void __init prom_meminit(void)
+{
+ unsigned long pages;
+
+ pages = memsize() >> PAGE_SHIFT;
+ add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+ return;
+}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
new file mode 100644
index 0000000..f8fcfb2
--- /dev/null
+++ b/arch/mips/ar7/platform.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/vlynq.h>
+#include <linux/leds.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/prom.h>
+
+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;
+ struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
+ result = gpio_request(pdata->gpio_bit, "vlynq");
+ if (result)
+ goto out;
+
+ ar7_device_reset(pdata->reset_bit);
+
+ result = ar7_gpio_disable(pdata->gpio_bit);
+ if (result)
+ goto out_enabled;
+
+ result = ar7_gpio_enable(pdata->gpio_bit);
+ if (result)
+ goto out_enabled;
+
+ result = gpio_direction_output(pdata->gpio_bit, 0);
+ if (result)
+ goto out_gpio_enabled;
+
+ mdelay(50);
+
+ gpio_set_value(pdata->gpio_bit, 1);
+ mdelay(50);
+
+ return 0;
+
+out_gpio_enabled:
+ ar7_gpio_disable(pdata->gpio_bit);
+out_enabled:
+ ar7_device_disable(pdata->reset_bit);
+ gpio_free(pdata->gpio_bit);
+out:
+ return result;
+}
+
+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[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_MAC0,
+ .end = AR7_REGS_MAC0 + 0x7ff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 27,
+ .end = 27,
+ },
+};
+
+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 resource vlynq_low_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ0,
+ .end = AR7_REGS_VLYNQ0 + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 29,
+ .end = 29,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x04000000,
+ .end = 0x04ffffff,
+ },
+ {
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 80,
+ .end = 111,
+ },
+};
+
+static struct resource vlynq_high_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ1,
+ .end = AR7_REGS_VLYNQ1 + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 33,
+ .end = 33,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
+ },
+ {
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 112,
+ .end = 143,
+ },
+};
+
+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 = 0x034001fff,
+ },
+};
+
+static struct physmap_flash_data physmap_flash_data = {
+ .width = 2,
+};
+
+static struct plat_cpmac_data cpmac_low_data = {
+ .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,
+};
+
+static u64 cpmac_dma_mask = DMA_32BIT_MASK;
+static struct platform_device cpmac_low = {
+ .id = 0,
+ .name = "cpmac",
+ .dev = {
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ .platform_data = &cpmac_low_data,
+ },
+ .resource = cpmac_low_res,
+ .num_resources = ARRAY_SIZE(cpmac_low_res),
+};
+
+static struct platform_device cpmac_high = {
+ .id = 1,
+ .name = "cpmac",
+ .dev = {
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ .platform_data = &cpmac_high_data,
+ },
+ .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 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 gpio_led default_leds[] = {
+ { .name = "status", .gpio = 8, .active_low = 1, },
+};
+
+static struct gpio_led dsl502t_leds[] = {
+ { .name = "status", .gpio = 9, .active_low = 1, },
+ { .name = "ethernet", .gpio = 7, .active_low = 1, },
+ { .name = "usb", .gpio = 12, .active_low = 1, },
+};
+
+static struct gpio_led dg834g_leds[] = {
+ { .name = "ppp", .gpio = 6, .active_low = 1, },
+ { .name = "status", .gpio = 7, .active_low = 1, },
+ { .name = "adsl", .gpio = 8, .active_low = 1, },
+ { .name = "wifi", .gpio = 12, .active_low = 1, },
+ {
+ .name = "power",
+ .gpio = 14,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+};
+
+static struct gpio_led fb_sl_leds[] = {
+ { .name = "1", .gpio = 7, },
+ { .name = "2", .gpio = 13, .active_low = 1, },
+ { .name = "3", .gpio = 10, .active_low = 1, },
+ { .name = "4", .gpio = 12, .active_low = 1, },
+ { .name = "5", .gpio = 9, .active_low = 1, },
+};
+
+static struct gpio_led fb_fon_leds[] = {
+ { .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_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 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 */
+ ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+ ar7_led_data.leds = default_leds;
+
+ /* FIXME: the whole thing is unreliable */
+ prId = prom_getenv("ProductID");
+ usb_prod = prom_getenv("usb_prod");
+
+ /* If we can't get the product id from PROM, use the default LEDs */
+ if (!prId)
+ return;
+
+ if (strstr(prId, "Fritz_Box_FON")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
+ ar7_led_data.leds = fb_fon_leds;
+ } else if (strstr(prId, "Fritz_Box_")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
+ ar7_led_data.leds = fb_sl_leds;
+ } else if ((!strcmp(prId, "AR7RD") || !strcmp(prId, "AR7DB"))
+ && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
+ ar7_led_data.leds = dsl502t_leds;
+ } else if (strstr(prId, "DG834")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
+ ar7_led_data.leds = dg834g_leds;
+ }
+}
+
+static int __init ar7_register_devices(void)
+{
+ int res;
+
+#ifdef CONFIG_SERIAL_8250
+
+ static struct uart_port uart_port[2];
+
+ memset(uart_port, 0, sizeof(struct uart_port) * 2);
+
+ uart_port[0].type = PORT_AR7;
+ 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_MEM;
+ 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]);
+ if (res)
+ return res;
+
+
+ /* Only TNETD73xx have a second serial port */
+ if (ar7_has_second_uart()) {
+ uart_port[1].type = PORT_AR7;
+ 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_MEM;
+ 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]);
+ if (res)
+ return res;
+ }
+
+#endif /* CONFIG_SERIAL_8250 */
+
+ res = platform_device_register(&physmap_flash);
+ if (res)
+ return res;
+
+ ar7_device_disable(vlynq_low_data.reset_bit);
+ res = platform_device_register(&vlynq_low);
+ if (res)
+ return res;
+
+ if (ar7_has_high_vlynq()) {
+ ar7_device_disable(vlynq_high_data.reset_bit);
+ res = platform_device_register(&vlynq_high);
+ if (res)
+ return res;
+ }
+
+ if (ar7_has_high_cpmac()) {
+ cpmac_get_mac(1, cpmac_high_data.dev_addr);
+ res = platform_device_register(&cpmac_high);
+ if (res)
+ return res;
+ } else {
+ cpmac_low_data.phy_mask = 0xffffffff;
+ }
+
+ cpmac_get_mac(0, cpmac_low_data.dev_addr);
+ res = platform_device_register(&cpmac_low);
+ if (res)
+ return res;
+
+ detect_leds();
+ res = platform_device_register(&ar7_gpio_leds);
+ if (res)
+ return res;
+
+ res = platform_device_register(&ar7_udc);
+
+ return res;
+}
+
+
+arch_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
new file mode 100644
index 0000000..ce16385
--- /dev/null
+++ b/arch/mips/ar7/prom.c
@@ -0,0 +1,330 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <asm/bootinfo.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+#define MAX_ENTRY 80
+
+struct env_var {
+ char *name;
+ char *value;
+};
+
+static struct env_var adam2_env[MAX_ENTRY] = { { 0, }, };
+
+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;
+
+ return NULL;
+}
+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] */
+
+ 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';
+ }
+}
+
+struct psbl_rec {
+ u32 psbl_size;
+ u32 env_base;
+ u32 env_size;
+ u32 ffs_base;
+ u32 ffs_size;
+};
+
+static __initdata char psp_env_version[] = "TIENV0.8";
+
+struct psp_env_chunk {
+ u8 num;
+ u8 ctrl;
+ u16 csum;
+ u8 len;
+ char data[11];
+} __attribute__ ((packed));
+
+struct psp_var_map_entry {
+ 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" },
+};
+
+/*
+
+Well-known variable (num is looked up in table above for matching variable name)
+Example: cpufrequency=211968000
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in a single chunk
+Example: NAME=VALUE
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in 2 chunks (len is the number of chunks)
+Example: bootloaderVersion=1.3.7.15
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Data is padded with 0xFF
+
+*/
+
+#define PSP_ENV_SIZE 4096
+
+static char psp_env_data[PSP_ENV_SIZE] = { 0, };
+
+static char * __init lookup_psp_var_map(u8 num)
+{
+ int i;
+
+ for (i = 0; i < sizeof(psp_var_map); i++)
+ if (psp_var_map[i].num == num)
+ return psp_var_map[i].value;
+
+ return NULL;
+}
+
+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;
+ adam2_env[i].value = value;
+ return;
+ } else if (!strcmp(adam2_env[i].name, name)) {
+ adam2_env[i].value = value;
+ return;
+ }
+ }
+}
+
+static int __init parse_psp_env(void *psp_env_base)
+{
+ int i, n;
+ char *name, *value;
+ struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
+
+ memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
+
+ i = 1;
+ n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
+ while (i < n) {
+ if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
+ break;
+ value = chunks[i].data;
+ if (chunks[i].num) {
+ name = lookup_psp_var_map(chunks[i].num);
+ } else {
+ name = value;
+ value += strlen(name) + 1;
+ }
+ if (name)
+ add_adam2_var(name, value);
+ i += chunks[i].len;
+ }
+ return 0;
+}
+
+static void __init ar7_init_env(struct env_var *env)
+{
+ int i;
+ struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
+ void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
+
+ if (strcmp(psp_env, psp_env_version) == 0) {
+ parse_psp_env(psp_env);
+ } else {
+ for (i = 0; i < MAX_ENTRY; i++, env++)
+ if (env->name)
+ add_adam2_var(env->name, env->value);
+ }
+}
+
+static void __init console_config(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char console_string[40];
+ int baud = 0;
+ char parity = '\0', bits = '\0', flow = '\0';
+ char *s, *p;
+
+ if (strstr(prom_getcmdline(), "console="))
+ return;
+
+#ifdef CONFIG_KGDB
+ if (!strstr(prom_getcmdline(), "nokgdb")) {
+ strcat(prom_getcmdline(), " console=kgdb");
+ kgdb_enabled = 1;
+ return;
+ }
+#endif
+
+ s = prom_getenv("modetty0");
+ if (s) {
+ baud = simple_strtoul(s, &p, 10);
+ s = p;
+ if (*s == ',')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s == ',')
+ s++;
+ if (*s)
+ bits = *s++;
+ if (*s == ',')
+ s++;
+ if (*s == 'h')
+ flow = 'r';
+ }
+
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+
+ if (flow == 'r')
+ sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+ parity, bits, flow);
+ else
+ sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
+ bits);
+ strcat(prom_getcmdline(), console_string);
+#endif
+}
+
+void __init prom_init(void)
+{
+ ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
+ ar7_init_env((struct env_var *)fw_arg2);
+ console_config();
+}
+
+#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
+static inline unsigned int serial_in(int offset)
+{
+ return readb((void *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+ writeb(value, (void *)PORT(offset));
+}
+
+char prom_getchar(void)
+{
+ while (!(serial_in(UART_LSR) & UART_LSR_DR))
+ ;
+ return serial_in(UART_RX);
+}
+
+int prom_putchar(char c)
+{
+ while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+ ;
+ serial_out(UART_TX, c);
+ return 1;
+}
+
+/* from adm5120/prom.c */
+void prom_printf(const char *fmt, ...)
+{
+ va_list args;
+ int l;
+ char *p, *buf_end;
+ char buf[1024];
+
+ va_start(args, fmt);
+ l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+ va_end(args);
+
+ buf_end = buf + l;
+
+ for (p = buf; p < buf_end; p++) {
+ /* Crude cr/nl handling is better than none */
+ if (*p == '\n')
+ prom_putchar('\r');
+ prom_putchar(*p);
+ }
+}
+
+#ifdef CONFIG_KGDB
+int putDebugChar(char c)
+{
+ return prom_putchar(c);
+}
+
+char getDebugChar(void)
+{
+ return prom_getchar();
+}
+#endif
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
new file mode 100644
index 0000000..a5bd7e6
--- /dev/null
+++ b/arch/mips/ar7/setup.c
@@ -0,0 +1,107 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+static void ar7_machine_restart(char *command);
+static void ar7_machine_halt(void);
+static void ar7_machine_power_off(void);
+
+static void ar7_machine_restart(char *command)
+{
+ u32 *softres_reg = (u32 *)ioremap(AR7_REGS_RESET +
+ AR7_RESET_SOFTWARE, 1);
+ writel(1, softres_reg);
+}
+
+static void ar7_machine_halt(void)
+{
+ while (1)
+ ;
+}
+
+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();
+}
+
+const char *get_system_type(void)
+{
+ u16 chip_id = ar7_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)";
+ default:
+ return "TI AR7 (Unknown)";
+ }
+}
+
+static int __init ar7_init_console(void)
+{
+ return 0;
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+
+extern void ar7_init_clocks(void);
+
+void __init plat_mem_setup(void)
+{
+ unsigned long io_base;
+
+ _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");
+ set_io_port_base(io_base);
+
+ prom_meminit();
+ ar7_init_clocks();
+
+ ioport_resource.start = 0;
+ ioport_resource.end = ~0;
+ iomem_resource.start = 0;
+ iomem_resource.end = ~0;
+
+ printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
+ get_system_type(),
+ ar7_chip_id(), ar7_chip_rev());
+}
+
+console_initcall(ar7_init_console);
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
new file mode 100644
index 0000000..5f17489
--- /dev/null
+++ b/arch/mips/ar7/time.c
@@ -0,0 +1,28 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/version.h>
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+
+void __init plat_time_init(void)
+{
+ mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
new file mode 100644
index 0000000..d972e09
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/ar7.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AR7_H__
+#define __AR7_H__
+
+#include <linux/delay.h>
+#include <asm/addrspace.h>
+#include <linux/io.h>
+
+#define AR7_REGS_BASE 0x08610000
+
+#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
+#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
+/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
+#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
+#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
+#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
+#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
+#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
+#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
+#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
+#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
+#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
+
+#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
+#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
+#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
+
+#define AR7_RESET_PEREPHERIAL 0x0
+#define AR7_RESET_SOFTWARE 0x4
+#define AR7_RESET_STATUS 0x8
+
+#define AR7_RESET_BIT_CPMAC_LO 17
+#define AR7_RESET_BIT_CPMAC_HI 21
+#define AR7_RESET_BIT_MDIO 22
+#define AR7_RESET_BIT_EPHY 26
+
+/* GPIO control registers */
+#define AR7_GPIO_INPUT 0x0
+#define AR7_GPIO_OUTPUT 0x4
+#define AR7_GPIO_DIR 0x8
+#define AR7_GPIO_ENABLE 0xc
+
+#define AR7_CHIP_7100 0x18
+#define AR7_CHIP_7200 0x2b
+#define AR7_CHIP_7300 0x05
+
+/* Interrupts */
+#define AR7_IRQ_UART0 15
+#define AR7_IRQ_UART1 16
+
+/* Clocks */
+#define AR7_AFE_CLOCK 35328000
+#define AR7_REF_CLOCK 25000000
+#define AR7_XTAL_CLOCK 24000000
+
+struct plat_cpmac_data {
+ int reset_bit;
+ int power_bit;
+ u32 phy_mask;
+ char dev_addr[6];
+};
+
+struct plat_dsl_data {
+ int reset_bit_dsl;
+ int reset_bit_sar;
+};
+
+extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
+
+static inline u16 ar7_chip_id(void)
+{
+ return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
+}
+
+static inline u8 ar7_chip_rev(void)
+{
+ return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
+}
+
+static inline int ar7_cpu_freq(void)
+{
+ return ar7_cpu_clock;
+}
+
+static inline int ar7_bus_freq(void)
+{
+ return ar7_bus_clock;
+}
+
+static inline int ar7_vbus_freq(void)
+{
+ return ar7_bus_clock / 2;
+}
+#define ar7_cpmac_freq ar7_vbus_freq
+
+static inline int ar7_dsp_freq(void)
+{
+ return ar7_dsp_clock;
+}
+
+static inline int ar7_has_high_cpmac(void)
+{
+ u16 chip_id = ar7_chip_id();
+ switch (chip_id) {
+ case AR7_CHIP_7100:
+ case AR7_CHIP_7200:
+ return 0;
+ default:
+ return 1;
+ }
+}
+#define ar7_has_high_vlynq ar7_has_high_cpmac
+#define ar7_has_second_uart ar7_has_high_cpmac
+
+static inline void ar7_device_enable(u32 bit)
+{
+ void *reset_reg =
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ writel(readl(reset_reg) | (1 << bit), reset_reg);
+ mdelay(20);
+}
+
+static inline void ar7_device_disable(u32 bit)
+{
+ void *reset_reg =
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ writel(readl(reset_reg) & ~(1 << bit), reset_reg);
+ mdelay(20);
+}
+
+static inline void ar7_device_reset(u32 bit)
+{
+ ar7_device_disable(bit);
+ ar7_device_enable(bit);
+}
+
+static inline void ar7_device_on(u32 bit)
+{
+ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+ writel(readl(power_reg) | (1 << bit), power_reg);
+ mdelay(20);
+}
+
+static inline void ar7_device_off(u32 bit)
+{
+ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+ writel(readl(power_reg) & ~(1 << bit), power_reg);
+ mdelay(20);
+}
+
+#endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
new file mode 100644
index 0000000..cbe9c4f
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/gpio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AR7_GPIO_H__
+#define __AR7_GPIO_H__
+
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+
+/* Common GPIO layer */
+static inline int gpio_get_value(unsigned gpio)
+{
+ void __iomem *gpio_in =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+ return readl(gpio_in) & (1 << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ void __iomem *gpio_out =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+ unsigned tmp;
+
+ tmp = readl(gpio_out) & ~(1 << gpio);
+ if (value)
+ tmp |= 1 << gpio;
+ writel(tmp, gpio_out);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ void __iomem *gpio_dir =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ void __iomem *gpio_dir =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ gpio_set_value(gpio, value);
+ writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+/* Board specific GPIO functions */
+static inline int ar7_gpio_enable(unsigned gpio)
+{
+ void __iomem *gpio_en =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+ writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+ return 0;
+}
+
+static inline int ar7_gpio_disable(unsigned gpio)
+{
+ void __iomem *gpio_en =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+ writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+ return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
new file mode 100644
index 0000000..39e9757
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/irq.h
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Shamelessly copied from asm-mips/mach-emma2rh/
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_AR7_IRQ_H
+#define __ASM_AR7_IRQ_H
+
+#define NR_IRQS 256
+
+#include_next <irq.h>
+
+#endif /* __ASM_AR7_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
new file mode 100644
index 0000000..55f5939
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/prom.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2006, 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __PROM_H__
+#define __PROM_H__
+
+extern char *prom_getenv(const char *name);
+extern void prom_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+extern void prom_meminit(void);
+
+#endif /* __PROM_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
new file mode 100644
index 0000000..ac28f27
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/spaces.h
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_AR7_SPACES_H
+#define _ASM_AR7_SPACES_H
+
+/*
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
+ */
+#define PAGE_OFFSET 0x94000000UL
+#define PHYS_OFFSET 0x14000000UL
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h
new file mode 100644
index 0000000..f4862b5
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_AR7_WAR_H
+#define __ASM_MIPS_MACH_AR7_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
[not found] ` <200906161428.33571.florian@openwrt.org>
@ 2009-06-23 9:28 ` Florian Fainelli
2009-06-23 18:15 ` Ralf Baechle
0 siblings, 1 reply; 11+ messages in thread
From: Florian Fainelli @ 2009-06-23 9:28 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Linux-MIPS
Le Tuesday 16 June 2009 14:28:32 Florian Fainelli, vous avez écrit :
> Le Thursday 04 June 2009 16:19:24 Florian Fainelli, vous avez écrit :
> > This patch adds support for the Texas Instruments
> > AR7 System-on-Chip.
> >
> > Changes from v1:
> > - simplified mach-ar7/spaces.h
> > - removed superfluous parenthesis
> > - use lib/gcd.c
> > - select VLYNQ
> > - removed non-8250 UART code, there are only 8250 UARTs in use
>
> Here comes an updated version.
> --
And now a new version again.
--
From: Florian Fainelli <florian@openwrt.org>
Subject: Add support for Texas Instruments AR7 System-on-a-Chip
This patch adds support for the Texas Instruments AR7 System-on-a-Chip.
It supports the TNETD7100, 7200 and 7300 versions of the SoC.
Changes from v3:
- added definition for AR7_SDRAM_BASE register
- switch to 32-bits accessors when accessing UART registers
- clean up header inclusion in time and setup files
- added help description below the AR7 config symbol
Changes from v2:
- remove ifdef on CONFIG_SERIAL_8250, we always enable it
- use PORT_16550A instead of PORT_AR7 avoids patching serial subsystem
Changes from v1:
- simplified mach-ar7/spaces.h
- removed superfluous parenthesis
- use lib/gcd.c
- select VLYNQ
- removed non-8250 UART code, there are only 8250 UARTs in use
Signed-off-by: Matteo Croce <matteo@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Eugene Konev <ejka@openwrt.org>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
--
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b29f028..dde11bb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -22,6 +22,27 @@ choice
config MACH_ALCHEMY
bool "Alchemy processor based machines"
+config AR7
+ bool "Texas Instruments AR7"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select CEVT_R4K
+ select CSRC_R4K
+ select IRQ_CPU
+ select NO_EXCEPT_FILL
+ select SWAP_IO_SPACE
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_KGDB
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select GENERIC_GPIO
+ select GCD
+ select VLYNQ
+ help
+ Support for the Texas Instruments AR7 System-on-a-Chip
+ family: TNETD7100, 7200 and 7300.
+
config BASLER_EXCITE
bool "Basler eXcite smart camera"
select CEVT_R4K
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 807572a..861da51 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -173,6 +173,13 @@ libs-y += arch/mips/fw/lib/
#
#
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7) += arch/mips/ar7/
+cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7) += 0xffffffff94100000
+
+#
# Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
#
core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
new file mode 100644
index 0000000..7435e44
--- /dev/null
+++ b/arch/mips/ar7/Makefile
@@ -0,0 +1,10 @@
+
+obj-y := \
+ prom.o \
+ setup.o \
+ memory.o \
+ irq.o \
+ time.o \
+ platform.o \
+ gpio.o \
+ clock.o
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
new file mode 100644
index 0000000..072f848
--- /dev/null
+++ b/arch/mips/ar7/clock.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gcd.h>
+#include <linux/io.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define BOOT_PLL_SOURCE_MASK 0x3
+#define CPU_PLL_SOURCE_SHIFT 16
+#define BUS_PLL_SOURCE_SHIFT 14
+#define USB_PLL_SOURCE_SHIFT 18
+#define DSP_PLL_SOURCE_SHIFT 22
+#define BOOT_PLL_SOURCE_AFE 0
+#define BOOT_PLL_SOURCE_BUS 0
+#define BOOT_PLL_SOURCE_REF 1
+#define BOOT_PLL_SOURCE_XTAL 2
+#define BOOT_PLL_SOURCE_CPU 3
+#define BOOT_PLL_BYPASS 0x00000020
+#define BOOT_PLL_ASYNC_MODE 0x02000000
+#define BOOT_PLL_2TO1_MODE 0x00008000
+
+#define TNETD7200_CLOCK_ID_CPU 0
+#define TNETD7200_CLOCK_ID_DSP 1
+#define TNETD7200_CLOCK_ID_USB 2
+
+#define TNETD7200_DEF_CPU_CLK 211000000
+#define TNETD7200_DEF_DSP_CLK 125000000
+#define TNETD7200_DEF_USB_CLK 48000000
+
+struct tnetd7300_clock {
+ u32 ctrl;
+#define PREDIV_MASK 0x001f0000
+#define PREDIV_SHIFT 16
+#define POSTDIV_MASK 0x0000001f
+ u32 unused1[3];
+ u32 pll;
+#define MUL_MASK 0x0000f000
+#define MUL_SHIFT 12
+#define PLL_MODE_MASK 0x00000001
+#define PLL_NDIV 0x00000800
+#define PLL_DIV 0x00000002
+#define PLL_STATUS 0x00000001
+ u32 unused2[3];
+};
+
+struct tnetd7300_clocks {
+ struct tnetd7300_clock bus;
+ struct tnetd7300_clock cpu;
+ struct tnetd7300_clock usb;
+ struct tnetd7300_clock dsp;
+};
+
+struct tnetd7200_clock {
+ u32 ctrl;
+ u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+ u32 mul;
+ u32 prediv;
+ u32 postdiv;
+ u32 postdiv2;
+ u32 unused2[6];
+ u32 cmd;
+ u32 status;
+ u32 cmden;
+ u32 padding[15];
+};
+
+struct tnetd7200_clocks {
+ struct tnetd7200_clock cpu;
+ struct tnetd7200_clock dsp;
+ 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 void approximate(int base, int target, int *prediv,
+ int *postdiv, int *mul)
+{
+ int i, j, k, freq, res = target;
+ for (i = 1; i <= 16; i++)
+ for (j = 1; j <= 32; j++)
+ for (k = 1; k <= 32; k++) {
+ freq = abs(base / j * i / k - target);
+ if (freq < res) {
+ res = freq;
+ *mul = i;
+ *prediv = j;
+ *postdiv = k;
+ }
+ }
+}
+
+static void calculate(int base, int target, int *prediv, int *postdiv,
+ int *mul)
+{
+ int tmp_gcd, tmp_base, tmp_freq;
+
+ for (*prediv = 1; *prediv <= 32; (*prediv)++) {
+ tmp_base = base / *prediv;
+ tmp_gcd = gcd(target, tmp_base);
+ *mul = target / tmp_gcd;
+ *postdiv = tmp_base / tmp_gcd;
+ if ((*mul < 1) || (*mul >= 16))
+ continue;
+ if ((*postdiv > 0) & (*postdiv <= 32))
+ break;
+ }
+
+ if (base / *prediv * *mul / *postdiv != target) {
+ approximate(base, target, prediv, postdiv, mul);
+ tmp_freq = base / *prediv * *mul / *postdiv;
+ printk(KERN_WARNING
+ "Adjusted requested frequency %d to %d\n",
+ target, tmp_freq);
+ }
+
+ printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
+ *prediv, *postdiv, *mul);
+}
+
+static int tnetd7300_dsp_clock(void)
+{
+ u32 didr1, didr2;
+ u8 rev = ar7_chip_rev();
+ didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
+ didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
+ if (didr2 & (1 << 23))
+ return 0;
+ if ((rev >= 0x23) && (rev != 0x57))
+ return 250000000;
+ if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
+ > 4208000)
+ return 250000000;
+ return 0;
+}
+
+static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
+ u32 *bootcr, u32 bus_clock)
+{
+ int product;
+ int base_clock = AR7_REF_CLOCK;
+ u32 ctrl = readl(&clock->ctrl);
+ u32 pll = readl(&clock->pll);
+ int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
+ int postdiv = (ctrl & POSTDIV_MASK) + 1;
+ int divisor = prediv * postdiv;
+ int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
+
+ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+ case BOOT_PLL_SOURCE_BUS:
+ base_clock = bus_clock;
+ break;
+ case BOOT_PLL_SOURCE_REF:
+ base_clock = AR7_REF_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_XTAL:
+ base_clock = AR7_XTAL_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_CPU:
+ base_clock = ar7_cpu_clock;
+ break;
+ }
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base_clock / divisor;
+
+ if ((pll & PLL_MODE_MASK) == 0)
+ return (base_clock >> (mul / 16 + 1)) / divisor;
+
+ if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
+ product = (mul & 1) ?
+ (base_clock * mul) >> 1 :
+ (base_clock * (mul - 1)) >> 2;
+ return product / divisor;
+ }
+
+ if (mul == 16)
+ return base_clock / divisor;
+
+ return base_clock * mul / divisor;
+}
+
+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;
+
+ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+ case BOOT_PLL_SOURCE_BUS:
+ base_clock = ar7_bus_clock;
+ break;
+ case BOOT_PLL_SOURCE_REF:
+ base_clock = AR7_REF_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_XTAL:
+ base_clock = AR7_XTAL_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_CPU:
+ base_clock = ar7_cpu_clock;
+ break;
+ }
+
+ calculate(base_clock, frequency, &prediv, &postdiv, &mul);
+
+ writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
+ mdelay(1);
+ writel(4, &clock->pll);
+ while (readl(&clock->pll) & PLL_STATUS)
+ ;
+ writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
+ mdelay(75);
+}
+
+static void __init tnetd7300_init_clocks(void)
+{
+ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ struct tnetd7300_clocks *clocks =
+ (struct tnetd7300_clocks *)
+ ioremap_nocache(AR7_REGS_POWER + 0x20,
+ sizeof(struct tnetd7300_clocks));
+
+ ar7_bus_clock = 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,
+ &clocks->cpu, bootcr, AR7_AFE_CLOCK);
+ else
+ ar7_cpu_clock = ar7_bus_clock;
+/*
+ tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
+ bootcr, 48000000);
+*/
+ if (ar7_dsp_clock == 250000000)
+ tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
+ bootcr, ar7_dsp_clock);
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock,
+ u32 *bootcr, u32 bus_clock)
+{
+ int divisor = ((readl(&clock->prediv) & 0x1f) + 1) *
+ ((readl(&clock->postdiv) & 0x1f) + 1);
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base / divisor;
+
+ return base * ((readl(&clock->mul) & 0xf) + 1) / divisor;
+}
+
+
+static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
+ int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
+{
+ printk(KERN_INFO
+ "Clocks: base = %d, frequency = %u, prediv = %d, "
+ "postdiv = %d, postdiv2 = %d, mul = %d\n",
+ base, frequency, prediv, postdiv, postdiv2, mul);
+
+ writel(0, &clock->ctrl);
+ writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+ writel((mul - 1) & 0xF, &clock->mul);
+
+ for (mul = 0; mul < 2000; mul++)
+ ; /* nop */
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
+
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
+
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(readl(&clock->ctrl) | 1, &clock->ctrl);
+}
+
+static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
+{
+ if (*bootcr & BOOT_PLL_ASYNC_MODE)
+ /* Async */
+ switch (clock_id) {
+ case TNETD7200_CLOCK_ID_DSP:
+ return AR7_REF_CLOCK;
+ default:
+ return AR7_AFE_CLOCK;
+ }
+ else
+ /* Sync */
+ if (*bootcr & BOOT_PLL_2TO1_MODE)
+ /* 2:1 */
+ switch (clock_id) {
+ case TNETD7200_CLOCK_ID_DSP:
+ return AR7_REF_CLOCK;
+ default:
+ return AR7_AFE_CLOCK;
+ }
+ else
+ /* 1:1 */
+ return AR7_REF_CLOCK;
+}
+
+
+static void __init tnetd7200_init_clocks(void)
+{
+ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ struct tnetd7200_clocks *clocks =
+ (struct tnetd7200_clocks *)
+ ioremap_nocache(AR7_REGS_POWER + 0x80,
+ sizeof(struct tnetd7200_clocks));
+ int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
+ int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
+ int usb_base, usb_mul, usb_prediv, usb_postdiv;
+
+ cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
+ dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
+
+ if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+ printk(KERN_INFO "Clocks: Async 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) / dsp_postdiv;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
+ ar7_bus_clock);
+
+ 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_postdiv;
+ tnetd7200_set_clock(cpu_base, &clocks->cpu,
+ cpu_prediv, cpu_postdiv, -1, cpu_mul,
+ ar7_cpu_clock);
+
+ } else
+ if (*bootcr & BOOT_PLL_2TO1_MODE) {
+ printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
+
+ 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_postdiv;
+ tnetd7200_set_clock(cpu_base, &clocks->cpu,
+ cpu_prediv, cpu_postdiv, -1, cpu_mul,
+ ar7_cpu_clock);
+
+ 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;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+ dsp_mul * 2, ar7_bus_clock);
+ } 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)
+ / dsp_postdiv;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+ dsp_mul * 2, ar7_bus_clock);
+
+ ar7_cpu_clock = ar7_bus_clock;
+ }
+
+ printk(KERN_INFO "Clocks: Setting USB clock\n");
+ usb_base = ar7_bus_clock;
+ 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;
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+void __init ar7_init_clocks(void)
+{
+ switch (ar7_chip_id()) {
+ case AR7_CHIP_7100:
+ tnetd7200_init_clocks();
+ break;
+ case AR7_CHIP_7200:
+ tnetd7200_init_clocks();
+ break;
+ case AR7_CHIP_7300:
+ ar7_dsp_clock = tnetd7300_dsp_clock();
+ tnetd7300_init_clocks();
+ break;
+ default:
+ break;
+ }
+}
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
new file mode 100644
index 0000000..74e14a3
--- /dev/null
+++ b/arch/mips/ar7/gpio.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach-ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX];
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ if (ar7_gpio_list[gpio])
+ return -EBUSY;
+
+ if (label)
+ ar7_gpio_list[gpio] = label;
+ else
+ ar7_gpio_list[gpio] = "busy";
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+ BUG_ON(!ar7_gpio_list[gpio]);
+ ar7_gpio_list[gpio] = NULL;
+}
+EXPORT_SYMBOL(gpio_free);
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
new file mode 100644
index 0000000..fb3756f
--- /dev/null
+++ b/arch/mips/ar7/irq.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define EXCEPT_OFFSET 0x80
+#define PACE_OFFSET 0xA0
+#define CHNLS_OFFSET 0x200
+
+#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10)
+#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8)
+#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */
+#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */
+#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */
+#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */
+#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */
+#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */
+#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */
+#define PIR_OFFSET (0x40)
+#define MSR_OFFSET (0x44)
+#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */
+#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */
+
+#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
+
+#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
+
+static void ar7_unmask_irq(unsigned int irq_nr);
+static void ar7_mask_irq(unsigned int irq_nr);
+static void ar7_ack_irq(unsigned int irq_nr);
+static void ar7_unmask_sec_irq(unsigned int irq_nr);
+static void ar7_mask_sec_irq(unsigned int irq_nr);
+static void ar7_ack_sec_irq(unsigned int irq_nr);
+static void ar7_cascade(void);
+static void ar7_irq_init(int base);
+static int ar7_irq_base;
+
+static struct irq_chip ar7_irq_type = {
+ .name = "AR7",
+ .unmask = ar7_unmask_irq,
+ .mask = ar7_mask_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,
+};
+
+static struct irqaction ar7_cascade_action = {
+ .handler = no_action,
+ .name = "AR7 cascade interrupt"
+};
+
+static void ar7_unmask_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(ESR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_mask_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(ECR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_ack_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(CR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_unmask_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+}
+
+static void ar7_mask_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+}
+
+static void ar7_ack_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+ ar7_irq_init(8);
+}
+
+static void __init ar7_irq_init(int base)
+{
+ int i;
+ /*
+ * Disable interrupts and clear pending
+ */
+ writel(0xffffffff, REG(ECR_OFFSET(0)));
+ writel(0xff, REG(ECR_OFFSET(32)));
+ writel(0xffffffff, REG(SEC_ECR_OFFSET));
+ writel(0xffffffff, REG(CR_OFFSET(0)));
+ writel(0xff, REG(CR_OFFSET(32)));
+ writel(0xffffffff, REG(SEC_CR_OFFSET));
+
+ ar7_irq_base = 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,
+ handle_level_irq);
+ /* Secondary IRQ's */
+ if (i < 32)
+ set_irq_chip_and_handler(base + i + 40,
+ &ar7_sec_irq_type,
+ handle_level_irq);
+ }
+
+ setup_irq(2, &ar7_cascade_action);
+ setup_irq(ar7_irq_base, &ar7_cascade_action);
+ set_c0_status(IE_IRQ0);
+}
+
+static void ar7_cascade(void)
+{
+ u32 status;
+ int i, irq;
+
+ /* Primary IRQ's */
+ irq = readl(REG(PIR_OFFSET)) & 0x3f;
+ if (irq) {
+ do_IRQ(ar7_irq_base + irq);
+ return;
+ }
+
+ /* Secondary IRQ's are cascaded through primary '0' */
+ writel(1, REG(CR_OFFSET(irq)));
+ status = readl(REG(SEC_SR_OFFSET));
+ for (i = 0; i < 32; i++) {
+ if (status & 1) {
+ do_IRQ(ar7_irq_base + i + 40);
+ return;
+ }
+ status >>= 1;
+ }
+
+ spurious_interrupt();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(7);
+ else if (pending & STATUSF_IP2) /* int0 hardware line */
+ ar7_cascade();
+ else
+ spurious_interrupt();
+}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
new file mode 100644
index 0000000..8c24581
--- /dev/null
+++ b/arch/mips/ar7/memory.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mips-boards/prom.h>
+
+static int __init memsize(void)
+{
+ u32 size = (64 << 20);
+ u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
+ u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+ u32 *tmpaddr = addr;
+
+ while (tmpaddr > kernel_end) {
+ *tmpaddr = (u32)tmpaddr;
+ size >>= 1;
+ tmpaddr -= size >> 2;
+ }
+
+ do {
+ tmpaddr += size >> 2;
+ if (*tmpaddr != (u32)tmpaddr)
+ break;
+ size <<= 1;
+ } while (size < (64 << 20));
+
+ writel(tmpaddr, &addr);
+
+ return size;
+}
+
+void __init prom_meminit(void)
+{
+ unsigned long pages;
+
+ pages = memsize() >> PAGE_SHIFT;
+ add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+ return;
+}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
new file mode 100644
index 0000000..dc48b13
--- /dev/null
+++ b/arch/mips/ar7/platform.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/vlynq.h>
+#include <linux/leds.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/prom.h>
+
+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;
+ struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
+ result = gpio_request(pdata->gpio_bit, "vlynq");
+ if (result)
+ goto out;
+
+ ar7_device_reset(pdata->reset_bit);
+
+ result = ar7_gpio_disable(pdata->gpio_bit);
+ if (result)
+ goto out_enabled;
+
+ result = ar7_gpio_enable(pdata->gpio_bit);
+ if (result)
+ goto out_enabled;
+
+ result = gpio_direction_output(pdata->gpio_bit, 0);
+ if (result)
+ goto out_gpio_enabled;
+
+ mdelay(50);
+
+ gpio_set_value(pdata->gpio_bit, 1);
+ mdelay(50);
+
+ return 0;
+
+out_gpio_enabled:
+ ar7_gpio_disable(pdata->gpio_bit);
+out_enabled:
+ ar7_device_disable(pdata->reset_bit);
+ gpio_free(pdata->gpio_bit);
+out:
+ return result;
+}
+
+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[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_MAC0,
+ .end = AR7_REGS_MAC0 + 0x7ff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 27,
+ .end = 27,
+ },
+};
+
+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 resource vlynq_low_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ0,
+ .end = AR7_REGS_VLYNQ0 + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 29,
+ .end = 29,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x04000000,
+ .end = 0x04ffffff,
+ },
+ {
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 80,
+ .end = 111,
+ },
+};
+
+static struct resource vlynq_high_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ1,
+ .end = AR7_REGS_VLYNQ1 + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 33,
+ .end = 33,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
+ },
+ {
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 112,
+ .end = 143,
+ },
+};
+
+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 = 0x034001fff,
+ },
+};
+
+static struct physmap_flash_data physmap_flash_data = {
+ .width = 2,
+};
+
+static struct plat_cpmac_data cpmac_low_data = {
+ .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,
+};
+
+static u64 cpmac_dma_mask = DMA_32BIT_MASK;
+static struct platform_device cpmac_low = {
+ .id = 0,
+ .name = "cpmac",
+ .dev = {
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ .platform_data = &cpmac_low_data,
+ },
+ .resource = cpmac_low_res,
+ .num_resources = ARRAY_SIZE(cpmac_low_res),
+};
+
+static struct platform_device cpmac_high = {
+ .id = 1,
+ .name = "cpmac",
+ .dev = {
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ .platform_data = &cpmac_high_data,
+ },
+ .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 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 gpio_led default_leds[] = {
+ { .name = "status", .gpio = 8, .active_low = 1, },
+};
+
+static struct gpio_led dsl502t_leds[] = {
+ { .name = "status", .gpio = 9, .active_low = 1, },
+ { .name = "ethernet", .gpio = 7, .active_low = 1, },
+ { .name = "usb", .gpio = 12, .active_low = 1, },
+};
+
+static struct gpio_led dg834g_leds[] = {
+ { .name = "ppp", .gpio = 6, .active_low = 1, },
+ { .name = "status", .gpio = 7, .active_low = 1, },
+ { .name = "adsl", .gpio = 8, .active_low = 1, },
+ { .name = "wifi", .gpio = 12, .active_low = 1, },
+ {
+ .name = "power",
+ .gpio = 14,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+};
+
+static struct gpio_led fb_sl_leds[] = {
+ { .name = "1", .gpio = 7, },
+ { .name = "2", .gpio = 13, .active_low = 1, },
+ { .name = "3", .gpio = 10, .active_low = 1, },
+ { .name = "4", .gpio = 12, .active_low = 1, },
+ { .name = "5", .gpio = 9, .active_low = 1, },
+};
+
+static struct gpio_led fb_fon_leds[] = {
+ { .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_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 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 */
+ ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+ ar7_led_data.leds = default_leds;
+
+ /* FIXME: the whole thing is unreliable */
+ prId = prom_getenv("ProductID");
+ usb_prod = prom_getenv("usb_prod");
+
+ /* If we can't get the product id from PROM, use the default LEDs */
+ if (!prId)
+ return;
+
+ if (strstr(prId, "Fritz_Box_FON")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
+ ar7_led_data.leds = fb_fon_leds;
+ } else if (strstr(prId, "Fritz_Box_")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
+ ar7_led_data.leds = fb_sl_leds;
+ } else if ((!strcmp(prId, "AR7RD") || !strcmp(prId, "AR7DB"))
+ && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
+ ar7_led_data.leds = dsl502t_leds;
+ } else if (strstr(prId, "DG834")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
+ ar7_led_data.leds = dg834g_leds;
+ }
+}
+
+static int __init ar7_register_devices(void)
+{
+ int res;
+ static struct uart_port uart_port[2];
+
+ 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]);
+ 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]);
+ if (res)
+ return res;
+ }
+
+ res = platform_device_register(&physmap_flash);
+ if (res)
+ return res;
+
+ ar7_device_disable(vlynq_low_data.reset_bit);
+ res = platform_device_register(&vlynq_low);
+ if (res)
+ return res;
+
+ if (ar7_has_high_vlynq()) {
+ ar7_device_disable(vlynq_high_data.reset_bit);
+ res = platform_device_register(&vlynq_high);
+ if (res)
+ return res;
+ }
+
+ if (ar7_has_high_cpmac()) {
+ cpmac_get_mac(1, cpmac_high_data.dev_addr);
+ res = platform_device_register(&cpmac_high);
+ if (res)
+ return res;
+ } else {
+ cpmac_low_data.phy_mask = 0xffffffff;
+ }
+
+ cpmac_get_mac(0, cpmac_low_data.dev_addr);
+ res = platform_device_register(&cpmac_low);
+ if (res)
+ return res;
+
+ detect_leds();
+ res = platform_device_register(&ar7_gpio_leds);
+ if (res)
+ return res;
+
+ res = platform_device_register(&ar7_udc);
+
+ return res;
+}
+arch_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
new file mode 100644
index 0000000..9fca789
--- /dev/null
+++ b/arch/mips/ar7/prom.c
@@ -0,0 +1,330 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <asm/bootinfo.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+#define MAX_ENTRY 80
+
+struct env_var {
+ char *name;
+ char *value;
+};
+
+static struct env_var adam2_env[MAX_ENTRY] = { { 0, }, };
+
+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;
+
+ return NULL;
+}
+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] */
+
+ 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';
+ }
+}
+
+struct psbl_rec {
+ u32 psbl_size;
+ u32 env_base;
+ u32 env_size;
+ u32 ffs_base;
+ u32 ffs_size;
+};
+
+static __initdata char psp_env_version[] = "TIENV0.8";
+
+struct psp_env_chunk {
+ u8 num;
+ u8 ctrl;
+ u16 csum;
+ u8 len;
+ char data[11];
+} __attribute__ ((packed));
+
+struct psp_var_map_entry {
+ 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" },
+};
+
+/*
+
+Well-known variable (num is looked up in table above for matching variable name)
+Example: cpufrequency=211968000
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in a single chunk
+Example: NAME=VALUE
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in 2 chunks (len is the number of chunks)
+Example: bootloaderVersion=1.3.7.15
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Data is padded with 0xFF
+
+*/
+
+#define PSP_ENV_SIZE 4096
+
+static char psp_env_data[PSP_ENV_SIZE] = { 0, };
+
+static char * __init lookup_psp_var_map(u8 num)
+{
+ int i;
+
+ for (i = 0; i < sizeof(psp_var_map); i++)
+ if (psp_var_map[i].num == num)
+ return psp_var_map[i].value;
+
+ return NULL;
+}
+
+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;
+ adam2_env[i].value = value;
+ return;
+ } else if (!strcmp(adam2_env[i].name, name)) {
+ adam2_env[i].value = value;
+ return;
+ }
+ }
+}
+
+static int __init parse_psp_env(void *psp_env_base)
+{
+ int i, n;
+ char *name, *value;
+ struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
+
+ memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
+
+ i = 1;
+ n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
+ while (i < n) {
+ if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
+ break;
+ value = chunks[i].data;
+ if (chunks[i].num) {
+ name = lookup_psp_var_map(chunks[i].num);
+ } else {
+ name = value;
+ value += strlen(name) + 1;
+ }
+ if (name)
+ add_adam2_var(name, value);
+ i += chunks[i].len;
+ }
+ return 0;
+}
+
+static void __init ar7_init_env(struct env_var *env)
+{
+ int i;
+ struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
+ void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
+
+ if (strcmp(psp_env, psp_env_version) == 0) {
+ parse_psp_env(psp_env);
+ } else {
+ for (i = 0; i < MAX_ENTRY; i++, env++)
+ if (env->name)
+ add_adam2_var(env->name, env->value);
+ }
+}
+
+static void __init console_config(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char console_string[40];
+ int baud = 0;
+ char parity = '\0', bits = '\0', flow = '\0';
+ char *s, *p;
+
+ if (strstr(prom_getcmdline(), "console="))
+ return;
+
+#ifdef CONFIG_KGDB
+ if (!strstr(prom_getcmdline(), "nokgdb")) {
+ strcat(prom_getcmdline(), " console=kgdb");
+ kgdb_enabled = 1;
+ return;
+ }
+#endif
+
+ s = prom_getenv("modetty0");
+ if (s) {
+ baud = simple_strtoul(s, &p, 10);
+ s = p;
+ if (*s == ',')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s == ',')
+ s++;
+ if (*s)
+ bits = *s++;
+ if (*s == ',')
+ s++;
+ if (*s == 'h')
+ flow = 'r';
+ }
+
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+
+ if (flow == 'r')
+ sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+ parity, bits, flow);
+ else
+ sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
+ bits);
+ strcat(prom_getcmdline(), console_string);
+#endif
+}
+
+void __init prom_init(void)
+{
+ ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
+ ar7_init_env((struct env_var *)fw_arg2);
+ console_config();
+}
+
+#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
+static inline unsigned int serial_in(int offset)
+{
+ return readl((void *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+ writel(value, (void *)PORT(offset));
+}
+
+char prom_getchar(void)
+{
+ while (!(serial_in(UART_LSR) & UART_LSR_DR))
+ ;
+ return serial_in(UART_RX);
+}
+
+int prom_putchar(char c)
+{
+ while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+ ;
+ serial_out(UART_TX, c);
+ return 1;
+}
+
+/* from adm5120/prom.c */
+void prom_printf(const char *fmt, ...)
+{
+ va_list args;
+ int l;
+ char *p, *buf_end;
+ char buf[1024];
+
+ va_start(args, fmt);
+ l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+ va_end(args);
+
+ buf_end = buf + l;
+
+ for (p = buf; p < buf_end; p++) {
+ /* Crude cr/nl handling is better than none */
+ if (*p == '\n')
+ prom_putchar('\r');
+ prom_putchar(*p);
+ }
+}
+
+#ifdef CONFIG_KGDB
+int putDebugChar(char c)
+{
+ return prom_putchar(c);
+}
+
+char getDebugChar(void)
+{
+ return prom_getchar();
+}
+#endif
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
new file mode 100644
index 0000000..de8c937
--- /dev/null
+++ b/arch/mips/ar7/setup.c
@@ -0,0 +1,107 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/time.h>
+
+#include <asm/reboot.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+static void ar7_machine_restart(char *command);
+static void ar7_machine_halt(void);
+static void ar7_machine_power_off(void);
+
+static void ar7_machine_restart(char *command)
+{
+ u32 *softres_reg = (u32 *)ioremap(AR7_REGS_RESET +
+ AR7_RESET_SOFTWARE, 1);
+ writel(1, softres_reg);
+}
+
+static void ar7_machine_halt(void)
+{
+ while (1)
+ ;
+}
+
+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();
+}
+
+const char *get_system_type(void)
+{
+ u16 chip_id = ar7_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)";
+ default:
+ return "TI AR7 (Unknown)";
+ }
+}
+
+static int __init ar7_init_console(void)
+{
+ return 0;
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+
+extern void ar7_init_clocks(void);
+
+void __init plat_mem_setup(void)
+{
+ unsigned long io_base;
+
+ _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");
+ set_io_port_base(io_base);
+
+ prom_meminit();
+ ar7_init_clocks();
+
+ ioport_resource.start = 0;
+ ioport_resource.end = ~0;
+ iomem_resource.start = 0;
+ iomem_resource.end = ~0;
+
+ printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
+ get_system_type(),
+ ar7_chip_id(), ar7_chip_rev());
+}
+
+console_initcall(ar7_init_console);
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
new file mode 100644
index 0000000..a1fba89
--- /dev/null
+++ b/arch/mips/ar7/time.c
@@ -0,0 +1,30 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+
+void __init plat_time_init(void)
+{
+ mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
new file mode 100644
index 0000000..b8686ee
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/ar7.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AR7_H__
+#define __AR7_H__
+
+#include <linux/delay.h>
+#include <asm/addrspace.h>
+#include <linux/io.h>
+
+#define AR7_SDRAM_BASE 0x14000000
+
+#define AR7_REGS_BASE 0x08610000
+
+#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
+#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
+/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
+#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
+#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
+#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
+#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
+#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
+#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
+#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
+#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
+#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
+
+#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
+#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
+#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
+
+#define AR7_RESET_PEREPHERIAL 0x0
+#define AR7_RESET_SOFTWARE 0x4
+#define AR7_RESET_STATUS 0x8
+
+#define AR7_RESET_BIT_CPMAC_LO 17
+#define AR7_RESET_BIT_CPMAC_HI 21
+#define AR7_RESET_BIT_MDIO 22
+#define AR7_RESET_BIT_EPHY 26
+
+/* GPIO control registers */
+#define AR7_GPIO_INPUT 0x0
+#define AR7_GPIO_OUTPUT 0x4
+#define AR7_GPIO_DIR 0x8
+#define AR7_GPIO_ENABLE 0xc
+
+#define AR7_CHIP_7100 0x18
+#define AR7_CHIP_7200 0x2b
+#define AR7_CHIP_7300 0x05
+
+/* Interrupts */
+#define AR7_IRQ_UART0 15
+#define AR7_IRQ_UART1 16
+
+/* Clocks */
+#define AR7_AFE_CLOCK 35328000
+#define AR7_REF_CLOCK 25000000
+#define AR7_XTAL_CLOCK 24000000
+
+struct plat_cpmac_data {
+ int reset_bit;
+ int power_bit;
+ u32 phy_mask;
+ char dev_addr[6];
+};
+
+struct plat_dsl_data {
+ int reset_bit_dsl;
+ int reset_bit_sar;
+};
+
+extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
+
+static inline u16 ar7_chip_id(void)
+{
+ return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
+}
+
+static inline u8 ar7_chip_rev(void)
+{
+ return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
+}
+
+static inline int ar7_cpu_freq(void)
+{
+ return ar7_cpu_clock;
+}
+
+static inline int ar7_bus_freq(void)
+{
+ return ar7_bus_clock;
+}
+
+static inline int ar7_vbus_freq(void)
+{
+ return ar7_bus_clock / 2;
+}
+#define ar7_cpmac_freq ar7_vbus_freq
+
+static inline int ar7_dsp_freq(void)
+{
+ return ar7_dsp_clock;
+}
+
+static inline int ar7_has_high_cpmac(void)
+{
+ u16 chip_id = ar7_chip_id();
+ switch (chip_id) {
+ case AR7_CHIP_7100:
+ case AR7_CHIP_7200:
+ return 0;
+ default:
+ return 1;
+ }
+}
+#define ar7_has_high_vlynq ar7_has_high_cpmac
+#define ar7_has_second_uart ar7_has_high_cpmac
+
+static inline void ar7_device_enable(u32 bit)
+{
+ void *reset_reg =
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ writel(readl(reset_reg) | (1 << bit), reset_reg);
+ mdelay(20);
+}
+
+static inline void ar7_device_disable(u32 bit)
+{
+ void *reset_reg =
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ writel(readl(reset_reg) & ~(1 << bit), reset_reg);
+ mdelay(20);
+}
+
+static inline void ar7_device_reset(u32 bit)
+{
+ ar7_device_disable(bit);
+ ar7_device_enable(bit);
+}
+
+static inline void ar7_device_on(u32 bit)
+{
+ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+ writel(readl(power_reg) | (1 << bit), power_reg);
+ mdelay(20);
+}
+
+static inline void ar7_device_off(u32 bit)
+{
+ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+ writel(readl(power_reg) & ~(1 << bit), power_reg);
+ mdelay(20);
+}
+
+#endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
new file mode 100644
index 0000000..cbe9c4f
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/gpio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AR7_GPIO_H__
+#define __AR7_GPIO_H__
+
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+
+/* Common GPIO layer */
+static inline int gpio_get_value(unsigned gpio)
+{
+ void __iomem *gpio_in =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+ return readl(gpio_in) & (1 << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ void __iomem *gpio_out =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+ unsigned tmp;
+
+ tmp = readl(gpio_out) & ~(1 << gpio);
+ if (value)
+ tmp |= 1 << gpio;
+ writel(tmp, gpio_out);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ void __iomem *gpio_dir =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ void __iomem *gpio_dir =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ gpio_set_value(gpio, value);
+ writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+/* Board specific GPIO functions */
+static inline int ar7_gpio_enable(unsigned gpio)
+{
+ void __iomem *gpio_en =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+ writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+ return 0;
+}
+
+static inline int ar7_gpio_disable(unsigned gpio)
+{
+ void __iomem *gpio_en =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+ writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+ return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
new file mode 100644
index 0000000..39e9757
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/irq.h
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Shamelessly copied from asm-mips/mach-emma2rh/
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_AR7_IRQ_H
+#define __ASM_AR7_IRQ_H
+
+#define NR_IRQS 256
+
+#include_next <irq.h>
+
+#endif /* __ASM_AR7_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
new file mode 100644
index 0000000..55f5939
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/prom.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2006, 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __PROM_H__
+#define __PROM_H__
+
+extern char *prom_getenv(const char *name);
+extern void prom_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+extern void prom_meminit(void);
+
+#endif /* __PROM_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
new file mode 100644
index 0000000..ac28f27
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/spaces.h
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_AR7_SPACES_H
+#define _ASM_AR7_SPACES_H
+
+/*
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
+ */
+#define PAGE_OFFSET 0x94000000UL
+#define PHYS_OFFSET 0x14000000UL
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h
new file mode 100644
index 0000000..f4862b5
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_AR7_WAR_H
+#define __ASM_MIPS_MACH_AR7_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-23 9:28 ` Florian Fainelli
@ 2009-06-23 18:15 ` Ralf Baechle
2009-06-24 9:12 ` Florian Fainelli
0 siblings, 1 reply; 11+ messages in thread
From: Ralf Baechle @ 2009-06-23 18:15 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Linux-MIPS
On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
AR7 time again - the platform pending longest ... Let's see:
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index b29f028..dde11bb 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -22,6 +22,27 @@ choice
> config MACH_ALCHEMY
> bool "Alchemy processor based machines"
>
> +config AR7
> + bool "Texas Instruments AR7"
> + select BOOT_ELF32
> + select DMA_NONCOHERENT
> + select CEVT_R4K
> + select CSRC_R4K
> + select IRQ_CPU
> + select NO_EXCEPT_FILL
> + select SWAP_IO_SPACE
> + select SYS_HAS_CPU_MIPS32_R1
> + select SYS_HAS_EARLY_PRINTK
> + select SYS_SUPPORTS_32BIT_KERNEL
> + select SYS_SUPPORTS_KGDB
> + select SYS_SUPPORTS_LITTLE_ENDIAN
> + select GENERIC_GPIO
> + select GCD
> + select VLYNQ
> + help
> + Support for the Texas Instruments AR7 System-on-a-Chip
> + family: TNETD7100, 7200 and 7300.
> +
> config BASLER_EXCITE
> bool "Basler eXcite smart camera"
> select CEVT_R4K
> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
> index 807572a..861da51 100644
> --- a/arch/mips/Makefile
> +++ b/arch/mips/Makefile
> @@ -173,6 +173,13 @@ libs-y += arch/mips/fw/lib/
> #
>
> #
> +# Texas Instruments AR7
> +#
> +core-$(CONFIG_AR7) += arch/mips/ar7/
> +cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
> +load-$(CONFIG_AR7) += 0xffffffff94100000
> +
> +#
> # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
> #
> core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
> diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
> new file mode 100644
> index 0000000..7435e44
> --- /dev/null
> +++ b/arch/mips/ar7/Makefile
> @@ -0,0 +1,10 @@
> +
> +obj-y := \
> + prom.o \
> + setup.o \
> + memory.o \
> + irq.o \
> + time.o \
> + platform.o \
> + gpio.o \
> + clock.o
> diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
> new file mode 100644
> index 0000000..072f848
> --- /dev/null
> +++ b/arch/mips/ar7/clock.c
> @@ -0,0 +1,447 @@
> +/*
> + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
> + * Copyright (C) 2007 Eugene Konev <ejka@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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/gcd.h>
> +#include <linux/io.h>
> +
> +#include <asm/addrspace.h>
> +#include <asm/mach-ar7/ar7.h>
> +
> +#define BOOT_PLL_SOURCE_MASK 0x3
> +#define CPU_PLL_SOURCE_SHIFT 16
> +#define BUS_PLL_SOURCE_SHIFT 14
> +#define USB_PLL_SOURCE_SHIFT 18
> +#define DSP_PLL_SOURCE_SHIFT 22
> +#define BOOT_PLL_SOURCE_AFE 0
> +#define BOOT_PLL_SOURCE_BUS 0
> +#define BOOT_PLL_SOURCE_REF 1
> +#define BOOT_PLL_SOURCE_XTAL 2
> +#define BOOT_PLL_SOURCE_CPU 3
> +#define BOOT_PLL_BYPASS 0x00000020
> +#define BOOT_PLL_ASYNC_MODE 0x02000000
> +#define BOOT_PLL_2TO1_MODE 0x00008000
> +
> +#define TNETD7200_CLOCK_ID_CPU 0
> +#define TNETD7200_CLOCK_ID_DSP 1
> +#define TNETD7200_CLOCK_ID_USB 2
> +
> +#define TNETD7200_DEF_CPU_CLK 211000000
> +#define TNETD7200_DEF_DSP_CLK 125000000
> +#define TNETD7200_DEF_USB_CLK 48000000
> +
> +struct tnetd7300_clock {
> + u32 ctrl;
> +#define PREDIV_MASK 0x001f0000
> +#define PREDIV_SHIFT 16
> +#define POSTDIV_MASK 0x0000001f
> + u32 unused1[3];
> + u32 pll;
> +#define MUL_MASK 0x0000f000
> +#define MUL_SHIFT 12
> +#define PLL_MODE_MASK 0x00000001
> +#define PLL_NDIV 0x00000800
> +#define PLL_DIV 0x00000002
> +#define PLL_STATUS 0x00000001
> + u32 unused2[3];
> +};
> +
> +struct tnetd7300_clocks {
> + struct tnetd7300_clock bus;
> + struct tnetd7300_clock cpu;
> + struct tnetd7300_clock usb;
> + struct tnetd7300_clock dsp;
> +};
> +
> +struct tnetd7200_clock {
> + u32 ctrl;
> + u32 unused1[3];
> +#define DIVISOR_ENABLE_MASK 0x00008000
> + u32 mul;
> + u32 prediv;
> + u32 postdiv;
> + u32 postdiv2;
> + u32 unused2[6];
> + u32 cmd;
> + u32 status;
> + u32 cmden;
> + u32 padding[15];
> +};
> +
> +struct tnetd7200_clocks {
> + struct tnetd7200_clock cpu;
> + struct tnetd7200_clock dsp;
> + 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 void approximate(int base, int target, int *prediv,
> + int *postdiv, int *mul)
> +{
> + int i, j, k, freq, res = target;
> + for (i = 1; i <= 16; i++)
> + for (j = 1; j <= 32; j++)
> + for (k = 1; k <= 32; k++) {
> + freq = abs(base / j * i / k - target);
> + if (freq < res) {
> + res = freq;
> + *mul = i;
> + *prediv = j;
> + *postdiv = k;
> + }
> + }
> +}
> +
> +static void calculate(int base, int target, int *prediv, int *postdiv,
> + int *mul)
> +{
> + int tmp_gcd, tmp_base, tmp_freq;
> +
> + for (*prediv = 1; *prediv <= 32; (*prediv)++) {
> + tmp_base = base / *prediv;
> + tmp_gcd = gcd(target, tmp_base);
> + *mul = target / tmp_gcd;
> + *postdiv = tmp_base / tmp_gcd;
> + if ((*mul < 1) || (*mul >= 16))
> + continue;
> + if ((*postdiv > 0) & (*postdiv <= 32))
> + break;
> + }
> +
> + if (base / *prediv * *mul / *postdiv != target) {
> + approximate(base, target, prediv, postdiv, mul);
> + tmp_freq = base / *prediv * *mul / *postdiv;
> + printk(KERN_WARNING
> + "Adjusted requested frequency %d to %d\n",
> + target, tmp_freq);
> + }
> +
> + printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
> + *prediv, *postdiv, *mul);
> +}
> +
> +static int tnetd7300_dsp_clock(void)
> +{
> + u32 didr1, didr2;
> + u8 rev = ar7_chip_rev();
> + didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
> + didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
> + if (didr2 & (1 << 23))
> + return 0;
> + if ((rev >= 0x23) && (rev != 0x57))
> + return 250000000;
> + if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
> + > 4208000)
> + return 250000000;
> + return 0;
> +}
> +
> +static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
> + u32 *bootcr, u32 bus_clock)
> +{
> + int product;
> + int base_clock = AR7_REF_CLOCK;
> + u32 ctrl = readl(&clock->ctrl);
> + u32 pll = readl(&clock->pll);
> + int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
> + int postdiv = (ctrl & POSTDIV_MASK) + 1;
> + int divisor = prediv * postdiv;
> + int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
> +
> + switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
> + case BOOT_PLL_SOURCE_BUS:
> + base_clock = bus_clock;
> + break;
> + case BOOT_PLL_SOURCE_REF:
> + base_clock = AR7_REF_CLOCK;
> + break;
> + case BOOT_PLL_SOURCE_XTAL:
> + base_clock = AR7_XTAL_CLOCK;
> + break;
> + case BOOT_PLL_SOURCE_CPU:
> + base_clock = ar7_cpu_clock;
> + break;
> + }
> +
> + if (*bootcr & BOOT_PLL_BYPASS)
> + return base_clock / divisor;
> +
> + if ((pll & PLL_MODE_MASK) == 0)
> + return (base_clock >> (mul / 16 + 1)) / divisor;
> +
> + if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
> + product = (mul & 1) ?
> + (base_clock * mul) >> 1 :
> + (base_clock * (mul - 1)) >> 2;
> + return product / divisor;
> + }
> +
> + if (mul == 16)
> + return base_clock / divisor;
> +
> + return base_clock * mul / divisor;
> +}
> +
> +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;
> +
> + switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
> + case BOOT_PLL_SOURCE_BUS:
> + base_clock = ar7_bus_clock;
> + break;
> + case BOOT_PLL_SOURCE_REF:
> + base_clock = AR7_REF_CLOCK;
> + break;
> + case BOOT_PLL_SOURCE_XTAL:
> + base_clock = AR7_XTAL_CLOCK;
> + break;
> + case BOOT_PLL_SOURCE_CPU:
> + base_clock = ar7_cpu_clock;
> + break;
> + }
> +
> + calculate(base_clock, frequency, &prediv, &postdiv, &mul);
> +
> + writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
> + mdelay(1);
> + writel(4, &clock->pll);
> + while (readl(&clock->pll) & PLL_STATUS)
> + ;
> + writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
> + mdelay(75);
This function is called by a time when BogoMIPS hasn't run yet, so
udelay, mdelay and ndelay won't do the right thing. Since the kernel is
running fine for you this suggests that the delay may not be required or
other initialization code is providing the 75ms.
If you find it is ok to run this function at a later stage as a normal
initcall you may want to consider using msleep() instead of mdelay().
> +}
> +
> +static void __init tnetd7300_init_clocks(void)
> +{
> + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> + struct tnetd7300_clocks *clocks =
> + (struct tnetd7300_clocks *)
> + ioremap_nocache(AR7_REGS_POWER + 0x20,
> + sizeof(struct tnetd7300_clocks));
> +
> + ar7_bus_clock = 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,
> + &clocks->cpu, bootcr, AR7_AFE_CLOCK);
> + else
> + ar7_cpu_clock = ar7_bus_clock;
> +/*
> + tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
> + bootcr, 48000000);
> +*/
> + if (ar7_dsp_clock == 250000000)
> + tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
> + bootcr, ar7_dsp_clock);
> +
> + iounmap(clocks);
> + iounmap(bootcr);
> +}
> +
> +static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock,
> + u32 *bootcr, u32 bus_clock)
> +{
> + int divisor = ((readl(&clock->prediv) & 0x1f) + 1) *
> + ((readl(&clock->postdiv) & 0x1f) + 1);
> +
> + if (*bootcr & BOOT_PLL_BYPASS)
> + return base / divisor;
> +
> + return base * ((readl(&clock->mul) & 0xf) + 1) / divisor;
> +}
> +
> +
> +static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
> + int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
> +{
> + printk(KERN_INFO
> + "Clocks: base = %d, frequency = %u, prediv = %d, "
> + "postdiv = %d, postdiv2 = %d, mul = %d\n",
> + base, frequency, prediv, postdiv, postdiv2, mul);
> +
> + writel(0, &clock->ctrl);
> + writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
> + writel((mul - 1) & 0xF, &clock->mul);
> +
> + for (mul = 0; mul < 2000; mul++)
> + ; /* nop */
> +
> + while (readl(&clock->status) & 0x1)
> + ; /* nop */
> +
> + writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
> +
> + writel(readl(&clock->cmden) | 1, &clock->cmden);
> + writel(readl(&clock->cmd) | 1, &clock->cmd);
> +
> + while (readl(&clock->status) & 0x1)
> + ; /* nop */
> +
> + writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
> +
> + writel(readl(&clock->cmden) | 1, &clock->cmden);
> + writel(readl(&clock->cmd) | 1, &clock->cmd);
> +
> + while (readl(&clock->status) & 0x1)
> + ; /* nop */
> +
> + writel(readl(&clock->ctrl) | 1, &clock->ctrl);
> +}
> +
> +static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
> +{
> + if (*bootcr & BOOT_PLL_ASYNC_MODE)
> + /* Async */
> + switch (clock_id) {
> + case TNETD7200_CLOCK_ID_DSP:
> + return AR7_REF_CLOCK;
> + default:
> + return AR7_AFE_CLOCK;
> + }
> + else
> + /* Sync */
> + if (*bootcr & BOOT_PLL_2TO1_MODE)
> + /* 2:1 */
> + switch (clock_id) {
> + case TNETD7200_CLOCK_ID_DSP:
> + return AR7_REF_CLOCK;
> + default:
> + return AR7_AFE_CLOCK;
> + }
> + else
> + /* 1:1 */
> + return AR7_REF_CLOCK;
> +}
> +
> +
> +static void __init tnetd7200_init_clocks(void)
> +{
> + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> + struct tnetd7200_clocks *clocks =
> + (struct tnetd7200_clocks *)
> + ioremap_nocache(AR7_REGS_POWER + 0x80,
> + sizeof(struct tnetd7200_clocks));
> + int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
> + int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
> + int usb_base, usb_mul, usb_prediv, usb_postdiv;
> +
> + cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
> + dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
> +
> + if (*bootcr & BOOT_PLL_ASYNC_MODE) {
> + printk(KERN_INFO "Clocks: Async 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) / dsp_postdiv;
> + tnetd7200_set_clock(dsp_base, &clocks->dsp,
> + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
> + ar7_bus_clock);
> +
> + 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_postdiv;
> + tnetd7200_set_clock(cpu_base, &clocks->cpu,
> + cpu_prediv, cpu_postdiv, -1, cpu_mul,
> + ar7_cpu_clock);
> +
> + } else
> + if (*bootcr & BOOT_PLL_2TO1_MODE) {
> + printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
> +
> + 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_postdiv;
> + tnetd7200_set_clock(cpu_base, &clocks->cpu,
> + cpu_prediv, cpu_postdiv, -1, cpu_mul,
> + ar7_cpu_clock);
> +
> + 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;
> + tnetd7200_set_clock(dsp_base, &clocks->dsp,
> + dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
> + dsp_mul * 2, ar7_bus_clock);
> + } 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)
> + / dsp_postdiv;
> + tnetd7200_set_clock(dsp_base, &clocks->dsp,
> + dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
> + dsp_mul * 2, ar7_bus_clock);
> +
> + ar7_cpu_clock = ar7_bus_clock;
> + }
> +
> + printk(KERN_INFO "Clocks: Setting USB clock\n");
> + usb_base = ar7_bus_clock;
> + 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;
> +
> + iounmap(clocks);
> + iounmap(bootcr);
> +}
> +
> +void __init ar7_init_clocks(void)
> +{
> + switch (ar7_chip_id()) {
> + case AR7_CHIP_7100:
> + tnetd7200_init_clocks();
> + break;
> + case AR7_CHIP_7200:
> + tnetd7200_init_clocks();
> + break;
> + case AR7_CHIP_7300:
> + ar7_dsp_clock = tnetd7300_dsp_clock();
> + tnetd7300_init_clocks();
> + break;
> + default:
> + break;
> + }
> +}
> diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
> new file mode 100644
> index 0000000..74e14a3
> --- /dev/null
> +++ b/arch/mips/ar7/gpio.c
> @@ -0,0 +1,48 @@
> +/*
> + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
> + * Copyright (C) 2007 Eugene Konev <ejka@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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <linux/module.h>
> +
> +#include <asm/mach-ar7/gpio.h>
> +
> +static const char *ar7_gpio_list[AR7_GPIO_MAX];
> +
> +int gpio_request(unsigned gpio, const char *label)
> +{
> + if (gpio >= AR7_GPIO_MAX)
> + return -EINVAL;
> +
> + if (ar7_gpio_list[gpio])
> + return -EBUSY;
> +
> + if (label)
> + ar7_gpio_list[gpio] = label;
> + else
> + ar7_gpio_list[gpio] = "busy";
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpio_request);
> +
> +void gpio_free(unsigned gpio)
> +{
> + BUG_ON(!ar7_gpio_list[gpio]);
> + ar7_gpio_list[gpio] = NULL;
> +}
> +EXPORT_SYMBOL(gpio_free);
> diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
> new file mode 100644
> index 0000000..fb3756f
> --- /dev/null
> +++ b/arch/mips/ar7/irq.c
> @@ -0,0 +1,184 @@
> +/*
> + * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
> + * Copyright (C) 2006,2007 Eugene Konev <ejka@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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +
> +#include <asm/irq_cpu.h>
> +#include <asm/mipsregs.h>
> +#include <asm/mach-ar7/ar7.h>
> +
> +#define EXCEPT_OFFSET 0x80
> +#define PACE_OFFSET 0xA0
> +#define CHNLS_OFFSET 0x200
> +
> +#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10)
> +#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8)
> +#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */
> +#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */
> +#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */
> +#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */
> +#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */
> +#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */
> +#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */
> +#define PIR_OFFSET (0x40)
> +#define MSR_OFFSET (0x44)
> +#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */
> +#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */
> +
> +#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
> +
> +#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
> +
> +static void ar7_unmask_irq(unsigned int irq_nr);
> +static void ar7_mask_irq(unsigned int irq_nr);
> +static void ar7_ack_irq(unsigned int irq_nr);
> +static void ar7_unmask_sec_irq(unsigned int irq_nr);
> +static void ar7_mask_sec_irq(unsigned int irq_nr);
> +static void ar7_ack_sec_irq(unsigned int irq_nr);
> +static void ar7_cascade(void);
> +static void ar7_irq_init(int base);
> +static int ar7_irq_base;
> +
> +static struct irq_chip ar7_irq_type = {
> + .name = "AR7",
> + .unmask = ar7_unmask_irq,
> + .mask = ar7_mask_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,
> +};
If you move these two structure definitions below the functions they're
refering to, you can get rid of all the prototypes.
> +
> +static struct irqaction ar7_cascade_action = {
> + .handler = no_action,
> + .name = "AR7 cascade interrupt"
> +};
> +
> +static void ar7_unmask_irq(unsigned int irq)
> +{
> + writel(1 << ((irq - ar7_irq_base) % 32),
> + REG(ESR_OFFSET(irq - ar7_irq_base)));
> +}
> +
> +static void ar7_mask_irq(unsigned int irq)
> +{
> + writel(1 << ((irq - ar7_irq_base) % 32),
> + REG(ECR_OFFSET(irq - ar7_irq_base)));
> +}
> +
> +static void ar7_ack_irq(unsigned int irq)
> +{
> + writel(1 << ((irq - ar7_irq_base) % 32),
> + REG(CR_OFFSET(irq - ar7_irq_base)));
> +}
> +
> +static void ar7_unmask_sec_irq(unsigned int irq)
> +{
> + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
> +}
> +
> +static void ar7_mask_sec_irq(unsigned int irq)
> +{
> + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
> +}
> +
> +static void ar7_ack_sec_irq(unsigned int irq)
> +{
> + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
> +}
> +
> +void __init arch_init_irq(void)
> +{
> + mips_cpu_irq_init();
> + ar7_irq_init(8);
> +}
> +
> +static void __init ar7_irq_init(int base)
> +{
> + int i;
> + /*
> + * Disable interrupts and clear pending
> + */
> + writel(0xffffffff, REG(ECR_OFFSET(0)));
> + writel(0xff, REG(ECR_OFFSET(32)));
> + writel(0xffffffff, REG(SEC_ECR_OFFSET));
> + writel(0xffffffff, REG(CR_OFFSET(0)));
> + writel(0xff, REG(CR_OFFSET(32)));
> + writel(0xffffffff, REG(SEC_CR_OFFSET));
> +
> + ar7_irq_base = 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,
> + handle_level_irq);
> + /* Secondary IRQ's */
> + if (i < 32)
> + set_irq_chip_and_handler(base + i + 40,
> + &ar7_sec_irq_type,
> + handle_level_irq);
> + }
> +
> + setup_irq(2, &ar7_cascade_action);
> + setup_irq(ar7_irq_base, &ar7_cascade_action);
> + set_c0_status(IE_IRQ0);
> +}
> +
> +static void ar7_cascade(void)
> +{
> + u32 status;
> + int i, irq;
> +
> + /* Primary IRQ's */
> + irq = readl(REG(PIR_OFFSET)) & 0x3f;
> + if (irq) {
> + do_IRQ(ar7_irq_base + irq);
> + return;
> + }
> +
> + /* Secondary IRQ's are cascaded through primary '0' */
> + writel(1, REG(CR_OFFSET(irq)));
> + status = readl(REG(SEC_SR_OFFSET));
> + for (i = 0; i < 32; i++) {
> + if (status & 1) {
> + do_IRQ(ar7_irq_base + i + 40);
> + return;
> + }
> + status >>= 1;
> + }
> +
> + spurious_interrupt();
> +}
> +
> +asmlinkage void plat_irq_dispatch(void)
> +{
> + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
> + if (pending & STATUSF_IP7) /* cpu timer */
> + do_IRQ(7);
> + else if (pending & STATUSF_IP2) /* int0 hardware line */
> + ar7_cascade();
> + else
> + spurious_interrupt();
> +}
> diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
> new file mode 100644
> index 0000000..8c24581
> --- /dev/null
> +++ b/arch/mips/ar7/memory.c
> @@ -0,0 +1,72 @@
> +/*
> + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
> + * Copyright (C) 2007 Eugene Konev <ejka@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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +#include <linux/bootmem.h>
> +#include <linux/init.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/pfn.h>
> +#include <linux/proc_fs.h>
> +#include <linux/string.h>
> +#include <linux/swap.h>
> +
> +#include <asm/bootinfo.h>
> +#include <asm/page.h>
> +#include <asm/sections.h>
> +
> +#include <asm/mach-ar7/ar7.h>
> +#include <asm/mips-boards/prom.h>
> +
> +static int __init memsize(void)
> +{
> + u32 size = (64 << 20);
> + u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
> + u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
> + u32 *tmpaddr = addr;
> +
> + while (tmpaddr > kernel_end) {
> + *tmpaddr = (u32)tmpaddr;
> + size >>= 1;
> + tmpaddr -= size >> 2;
> + }
> +
> + do {
> + tmpaddr += size >> 2;
> + if (*tmpaddr != (u32)tmpaddr)
> + break;
> + size <<= 1;
> + } while (size < (64 << 20));
> +
> + writel(tmpaddr, &addr);
> +
> + return size;
> +}
> +
> +void __init prom_meminit(void)
> +{
> + unsigned long pages;
> +
> + pages = memsize() >> PAGE_SHIFT;
> + add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
> + BOOT_MEM_RAM);
> +}
> +
> +void __init prom_free_prom_memory(void)
> +{
> + return;
Useless return statement.
> +}
> diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
> new file mode 100644
> index 0000000..dc48b13
> --- /dev/null
> +++ b/arch/mips/ar7/platform.c
> @@ -0,0 +1,486 @@
> +/*
> + * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
> + * Copyright (C) 2006,2007 Eugene Konev <ejka@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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <linux/init.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/platform_device.h>
> +#include <linux/mtd/physmap.h>
> +#include <linux/serial.h>
> +#include <linux/serial_8250.h>
> +#include <linux/ioport.h>
> +#include <linux/io.h>
> +#include <linux/version.h>
> +#include <linux/vlynq.h>
> +#include <linux/leds.h>
> +#include <linux/string.h>
> +#include <linux/etherdevice.h>
> +
> +#include <asm/addrspace.h>
> +#include <asm/mach-ar7/ar7.h>
> +#include <asm/mach-ar7/gpio.h>
> +#include <asm/mach-ar7/prom.h>
> +
> +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;
> + struct plat_vlynq_data *pdata = dev->dev.platform_data;
> +
> + result = gpio_request(pdata->gpio_bit, "vlynq");
> + if (result)
> + goto out;
> +
> + ar7_device_reset(pdata->reset_bit);
> +
> + result = ar7_gpio_disable(pdata->gpio_bit);
> + if (result)
> + goto out_enabled;
> +
> + result = ar7_gpio_enable(pdata->gpio_bit);
> + if (result)
> + goto out_enabled;
> +
> + result = gpio_direction_output(pdata->gpio_bit, 0);
> + if (result)
> + goto out_gpio_enabled;
> +
> + mdelay(50);
Consider using msleep(50).
> +
> + gpio_set_value(pdata->gpio_bit, 1);
> + mdelay(50);
Ditto - consider using msleep(50).
> +
> + return 0;
> +
> +out_gpio_enabled:
> + ar7_gpio_disable(pdata->gpio_bit);
> +out_enabled:
> + ar7_device_disable(pdata->reset_bit);
> + gpio_free(pdata->gpio_bit);
> +out:
> + return result;
> +}
> +
> +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[] = {
> + {
> + .name = "regs",
> + .flags = IORESOURCE_MEM,
> + .start = AR7_REGS_MAC0,
> + .end = AR7_REGS_MAC0 + 0x7ff,
> + },
> + {
> + .name = "irq",
> + .flags = IORESOURCE_IRQ,
> + .start = 27,
> + .end = 27,
> + },
> +};
> +
> +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 resource vlynq_low_res[] = {
> + {
> + .name = "regs",
> + .flags = IORESOURCE_MEM,
> + .start = AR7_REGS_VLYNQ0,
> + .end = AR7_REGS_VLYNQ0 + 0xff,
> + },
> + {
> + .name = "irq",
> + .flags = IORESOURCE_IRQ,
> + .start = 29,
> + .end = 29,
> + },
> + {
> + .name = "mem",
> + .flags = IORESOURCE_MEM,
> + .start = 0x04000000,
> + .end = 0x04ffffff,
> + },
> + {
> + .name = "devirq",
> + .flags = IORESOURCE_IRQ,
> + .start = 80,
> + .end = 111,
> + },
> +};
> +
> +static struct resource vlynq_high_res[] = {
> + {
> + .name = "regs",
> + .flags = IORESOURCE_MEM,
> + .start = AR7_REGS_VLYNQ1,
> + .end = AR7_REGS_VLYNQ1 + 0xff,
> + },
> + {
> + .name = "irq",
> + .flags = IORESOURCE_IRQ,
> + .start = 33,
> + .end = 33,
> + },
> + {
> + .name = "mem",
> + .flags = IORESOURCE_MEM,
> + .start = 0x0c000000,
> + .end = 0x0cffffff,
> + },
> + {
> + .name = "devirq",
> + .flags = IORESOURCE_IRQ,
> + .start = 112,
> + .end = 143,
> + },
> +};
> +
> +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 = 0x034001fff,
> + },
> +};
> +
> +static struct physmap_flash_data physmap_flash_data = {
> + .width = 2,
> +};
> +
> +static struct plat_cpmac_data cpmac_low_data = {
> + .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,
> +};
> +
> +static u64 cpmac_dma_mask = DMA_32BIT_MASK;
> +static struct platform_device cpmac_low = {
> + .id = 0,
> + .name = "cpmac",
> + .dev = {
> + .dma_mask = &cpmac_dma_mask,
> + .coherent_dma_mask = DMA_32BIT_MASK,
> + .platform_data = &cpmac_low_data,
> + },
> + .resource = cpmac_low_res,
> + .num_resources = ARRAY_SIZE(cpmac_low_res),
> +};
> +
> +static struct platform_device cpmac_high = {
> + .id = 1,
> + .name = "cpmac",
> + .dev = {
> + .dma_mask = &cpmac_dma_mask,
> + .coherent_dma_mask = DMA_32BIT_MASK,
> + .platform_data = &cpmac_high_data,
> + },
> + .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 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 gpio_led default_leds[] = {
> + { .name = "status", .gpio = 8, .active_low = 1, },
Please initialize one field per line only - as above for vlynq_high, for
example.
> +};
> +
> +static struct gpio_led dsl502t_leds[] = {
> + { .name = "status", .gpio = 9, .active_low = 1, },
> + { .name = "ethernet", .gpio = 7, .active_low = 1, },
> + { .name = "usb", .gpio = 12, .active_low = 1, },
> +};
> +
> +static struct gpio_led dg834g_leds[] = {
> + { .name = "ppp", .gpio = 6, .active_low = 1, },
> + { .name = "status", .gpio = 7, .active_low = 1, },
> + { .name = "adsl", .gpio = 8, .active_low = 1, },
> + { .name = "wifi", .gpio = 12, .active_low = 1, },
> + {
> + .name = "power",
> + .gpio = 14,
> + .active_low = 1,
> + .default_trigger = "default-on",
> + },
> +};
> +
> +static struct gpio_led fb_sl_leds[] = {
> + { .name = "1", .gpio = 7, },
> + { .name = "2", .gpio = 13, .active_low = 1, },
> + { .name = "3", .gpio = 10, .active_low = 1, },
> + { .name = "4", .gpio = 12, .active_low = 1, },
> + { .name = "5", .gpio = 9, .active_low = 1, },
> +};
> +
> +static struct gpio_led fb_fon_leds[] = {
> + { .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_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 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;
Linux coding style - please don't use CamelStyle names for identifiers.
> +
> + /* Default LEDs */
> + ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
> + ar7_led_data.leds = default_leds;
> +
> + /* FIXME: the whole thing is unreliable */
> + prId = prom_getenv("ProductID");
> + usb_prod = prom_getenv("usb_prod");
> +
> + /* If we can't get the product id from PROM, use the default LEDs */
> + if (!prId)
> + return;
> +
> + if (strstr(prId, "Fritz_Box_FON")) {
> + ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
> + ar7_led_data.leds = fb_fon_leds;
> + } else if (strstr(prId, "Fritz_Box_")) {
> + ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
> + ar7_led_data.leds = fb_sl_leds;
> + } else if ((!strcmp(prId, "AR7RD") || !strcmp(prId, "AR7DB"))
> + && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
> + ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
> + ar7_led_data.leds = dsl502t_leds;
> + } else if (strstr(prId, "DG834")) {
> + ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
> + ar7_led_data.leds = dg834g_leds;
> + }
> +}
> +
> +static int __init ar7_register_devices(void)
> +{
> + int res;
> + static struct uart_port uart_port[2];
> +
> + 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]);
> + 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]);
> + if (res)
> + return res;
> + }
> +
> + res = platform_device_register(&physmap_flash);
> + if (res)
> + return res;
> +
> + ar7_device_disable(vlynq_low_data.reset_bit);
> + res = platform_device_register(&vlynq_low);
> + if (res)
> + return res;
> +
> + if (ar7_has_high_vlynq()) {
> + ar7_device_disable(vlynq_high_data.reset_bit);
> + res = platform_device_register(&vlynq_high);
> + if (res)
> + return res;
> + }
> +
> + if (ar7_has_high_cpmac()) {
> + cpmac_get_mac(1, cpmac_high_data.dev_addr);
> + res = platform_device_register(&cpmac_high);
> + if (res)
> + return res;
> + } else {
> + cpmac_low_data.phy_mask = 0xffffffff;
> + }
> +
> + cpmac_get_mac(0, cpmac_low_data.dev_addr);
> + res = platform_device_register(&cpmac_low);
> + if (res)
> + return res;
> +
> + detect_leds();
> + res = platform_device_register(&ar7_gpio_leds);
> + if (res)
> + return res;
> +
> + res = platform_device_register(&ar7_udc);
> +
> + return res;
> +}
> +arch_initcall(ar7_register_devices);
> diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
> new file mode 100644
> index 0000000..9fca789
> --- /dev/null
> +++ b/arch/mips/ar7/prom.c
> @@ -0,0 +1,330 @@
> +/*
> + * Carsten Langgaard, carstenl@mips.com
> + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
> + *
> + * This program is free software; you can distribute it and/or modify it
> + * under the terms of the GNU General Public License (Version 2) as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
> + *
> + * Putting things on the screen/serial line using YAMONs facilities.
> + */
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/serial_reg.h>
> +#include <linux/spinlock.h>
> +#include <linux/module.h>
> +#include <linux/string.h>
> +#include <linux/io.h>
> +#include <asm/bootinfo.h>
> +
> +#include <asm/mach-ar7/ar7.h>
> +#include <asm/mach-ar7/prom.h>
> +
> +#define MAX_ENTRY 80
> +
> +struct env_var {
> + char *name;
> + char *value;
> +};
> +
> +static struct env_var adam2_env[MAX_ENTRY] = { { 0, }, };
Don't initialize global variables to zero. That just bloats the file.
> +
> +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;
> +
> + return NULL;
> +}
> +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] */
> +
> + 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';
> + }
> +}
> +
> +struct psbl_rec {
> + u32 psbl_size;
> + u32 env_base;
> + u32 env_size;
> + u32 ffs_base;
> + u32 ffs_size;
> +};
> +
> +static __initdata char psp_env_version[] = "TIENV0.8";
> +
> +struct psp_env_chunk {
> + u8 num;
> + u8 ctrl;
> + u16 csum;
> + u8 len;
> + char data[11];
> +} __attribute__ ((packed));
> +
> +struct psp_var_map_entry {
> + 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" },
> +};
> +
> +/*
> +
> +Well-known variable (num is looked up in table above for matching variable name)
> +Example: cpufrequency=211968000
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +
> +Name=Value pair in a single chunk
> +Example: NAME=VALUE
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +
> +Name=Value pair in 2 chunks (len is the number of chunks)
> +Example: bootloaderVersion=1.3.7.15
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
> ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
> +
> +Data is padded with 0xFF
> +
> +*/
> +
> +#define PSP_ENV_SIZE 4096
> +
> +static char psp_env_data[PSP_ENV_SIZE] = { 0, };
> +
> +static char * __init lookup_psp_var_map(u8 num)
> +{
> + int i;
> +
> + for (i = 0; i < sizeof(psp_var_map); i++)
> + if (psp_var_map[i].num == num)
> + return psp_var_map[i].value;
> +
> + return NULL;
> +}
> +
> +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;
> + adam2_env[i].value = value;
> + return;
> + } else if (!strcmp(adam2_env[i].name, name)) {
> + adam2_env[i].value = value;
> + return;
> + }
> + }
> +}
> +
> +static int __init parse_psp_env(void *psp_env_base)
> +{
> + int i, n;
> + char *name, *value;
> + struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
> +
> + memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
> +
> + i = 1;
> + n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
> + while (i < n) {
> + if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
> + break;
> + value = chunks[i].data;
> + if (chunks[i].num) {
> + name = lookup_psp_var_map(chunks[i].num);
> + } else {
> + name = value;
> + value += strlen(name) + 1;
> + }
> + if (name)
> + add_adam2_var(name, value);
> + i += chunks[i].len;
> + }
> + return 0;
> +}
> +
> +static void __init ar7_init_env(struct env_var *env)
> +{
> + int i;
> + struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
> + void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
> +
> + if (strcmp(psp_env, psp_env_version) == 0) {
> + parse_psp_env(psp_env);
> + } else {
> + for (i = 0; i < MAX_ENTRY; i++, env++)
> + if (env->name)
> + add_adam2_var(env->name, env->value);
> + }
> +}
> +
> +static void __init console_config(void)
> +{
> +#ifdef CONFIG_SERIAL_8250_CONSOLE
> + char console_string[40];
> + int baud = 0;
> + char parity = '\0', bits = '\0', flow = '\0';
> + char *s, *p;
> +
> + if (strstr(prom_getcmdline(), "console="))
> + return;
> +
> +#ifdef CONFIG_KGDB
> + if (!strstr(prom_getcmdline(), "nokgdb")) {
> + strcat(prom_getcmdline(), " console=kgdb");
> + kgdb_enabled = 1;
> + return;
> + }
> +#endif
> +
> + s = prom_getenv("modetty0");
> + if (s) {
> + baud = simple_strtoul(s, &p, 10);
> + s = p;
> + if (*s == ',')
> + s++;
> + if (*s)
> + parity = *s++;
> + if (*s == ',')
> + s++;
> + if (*s)
> + bits = *s++;
> + if (*s == ',')
> + s++;
> + if (*s == 'h')
> + flow = 'r';
> + }
> +
> + if (baud == 0)
> + baud = 38400;
> + if (parity != 'n' && parity != 'o' && parity != 'e')
> + parity = 'n';
> + if (bits != '7' && bits != '8')
> + bits = '8';
> +
> + if (flow == 'r')
> + sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
> + parity, bits, flow);
> + else
> + sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
> + bits);
> + strcat(prom_getcmdline(), console_string);
> +#endif
> +}
> +
> +void __init prom_init(void)
> +{
> + ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
> + ar7_init_env((struct env_var *)fw_arg2);
> + console_config();
> +}
> +
> +#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
> +static inline unsigned int serial_in(int offset)
> +{
> + return readl((void *)PORT(offset));
> +}
> +
> +static inline void serial_out(int offset, int value)
> +{
> + writel(value, (void *)PORT(offset));
> +}
> +
> +char prom_getchar(void)
> +{
> + while (!(serial_in(UART_LSR) & UART_LSR_DR))
> + ;
> + return serial_in(UART_RX);
> +}
> +
> +int prom_putchar(char c)
> +{
> + while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
> + ;
> + serial_out(UART_TX, c);
> + return 1;
> +}
> +
> +/* from adm5120/prom.c */
> +void prom_printf(const char *fmt, ...)
As above - I see no users of prom_printf() - and it seems to duplicate
early printk anyway, so can you drop it?
> +{
> + va_list args;
> + int l;
> + char *p, *buf_end;
> + char buf[1024];
> +
> + va_start(args, fmt);
> + l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
> + va_end(args);
> +
> + buf_end = buf + l;
> +
> + for (p = buf; p < buf_end; p++) {
> + /* Crude cr/nl handling is better than none */
> + if (*p == '\n')
> + prom_putchar('\r');
> + prom_putchar(*p);
> + }
> +}
> +
> +#ifdef CONFIG_KGDB
> +int putDebugChar(char c)
> +{
> + return prom_putchar(c);
> +}
> +
> +char getDebugChar(void)
> +{
> + return prom_getchar();
> +}
> +#endif
putDebugChar and getDebugChar are dead code.
> diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
> new file mode 100644
> index 0000000..de8c937
> --- /dev/null
> +++ b/arch/mips/ar7/setup.c
> @@ -0,0 +1,107 @@
> +/*
> + * Carsten Langgaard, carstenl@mips.com
> + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
> + *
> + * This program is free software; you can distribute it and/or modify it
> + * under the terms of the GNU General Public License (Version 2) as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
> + */
> +#include <linux/version.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/pm.h>
> +#include <linux/time.h>
> +
> +#include <asm/reboot.h>
> +#include <asm/mach-ar7/ar7.h>
> +#include <asm/mach-ar7/prom.h>
> +
> +static void ar7_machine_restart(char *command);
> +static void ar7_machine_halt(void);
> +static void ar7_machine_power_off(void);
> +
> +static void ar7_machine_restart(char *command)
> +{
> + u32 *softres_reg = (u32 *)ioremap(AR7_REGS_RESET +
> + AR7_RESET_SOFTWARE, 1);
^^^^^^^
Unnecessary cast.
> + writel(1, softres_reg);
> +}
> +
> +static void ar7_machine_halt(void)
> +{
> + while (1)
> + ;
> +}
> +
> +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();
> +}
> +
> +const char *get_system_type(void)
> +{
> + u16 chip_id = ar7_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)";
> + default:
> + return "TI AR7 (Unknown)";
> + }
> +}
> +
> +static int __init ar7_init_console(void)
> +{
> + return 0;
> +}
> +
> +/*
> + * Initializes basic routines and structures pointers, memory size (as
> + * given by the bios and saves the command line.
> + */
> +
> +extern void ar7_init_clocks(void);
> +
> +void __init plat_mem_setup(void)
> +{
> + unsigned long io_base;
> +
> + _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");
> + set_io_port_base(io_base);
> +
> + prom_meminit();
> + ar7_init_clocks();
> +
> + ioport_resource.start = 0;
> + ioport_resource.end = ~0;
That's looking fishy ... Out of curity, do you have anything that's using
ioports (cat /proc/ioports) on AR7 systems at all? If not then you can
just drop this.
> + iomem_resource.start = 0;
> + iomem_resource.end = ~0;
This iomem_resource initialization is not needed. The same values are
already the default; see kernel/resource.c.
> +
> + printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
> + get_system_type(),
> + ar7_chip_id(), ar7_chip_rev());
> +}
> +
> +console_initcall(ar7_init_console);
> diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
> new file mode 100644
> index 0000000..a1fba89
> --- /dev/null
> +++ b/arch/mips/ar7/time.c
> @@ -0,0 +1,30 @@
> +/*
> + * Carsten Langgaard, carstenl@mips.com
> + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
> + *
> + * This program is free software; you can distribute it and/or modify it
> + * under the terms of the GNU General Public License (Version 2) as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
> + *
> + * Setting up the clock on the MIPS boards.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/time.h>
> +
> +#include <asm/time.h>
> +#include <asm/mach-ar7/ar7.h>
> +
> +void __init plat_time_init(void)
> +{
> + mips_hpt_frequency = ar7_cpu_freq() / 2;
> +}
> diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
> new file mode 100644
> index 0000000..b8686ee
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ar7/ar7.h
> @@ -0,0 +1,172 @@
> +/*
> + * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
> + * Copyright (C) 2006,2007 Eugene Konev <ejka@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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef __AR7_H__
> +#define __AR7_H__
> +
> +#include <linux/delay.h>
> +#include <asm/addrspace.h>
> +#include <linux/io.h>
> +
> +#define AR7_SDRAM_BASE 0x14000000
> +
> +#define AR7_REGS_BASE 0x08610000
> +
> +#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
> +#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
> +/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
> +#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
> +#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
> +#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
> +#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
> +#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
> +#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
> +#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
> +#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
> +#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
> +#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
> +
> +#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
> +#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
> +#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
> +
> +#define AR7_RESET_PEREPHERIAL 0x0
> +#define AR7_RESET_SOFTWARE 0x4
> +#define AR7_RESET_STATUS 0x8
> +
> +#define AR7_RESET_BIT_CPMAC_LO 17
> +#define AR7_RESET_BIT_CPMAC_HI 21
> +#define AR7_RESET_BIT_MDIO 22
> +#define AR7_RESET_BIT_EPHY 26
> +
> +/* GPIO control registers */
> +#define AR7_GPIO_INPUT 0x0
> +#define AR7_GPIO_OUTPUT 0x4
> +#define AR7_GPIO_DIR 0x8
> +#define AR7_GPIO_ENABLE 0xc
> +
> +#define AR7_CHIP_7100 0x18
> +#define AR7_CHIP_7200 0x2b
> +#define AR7_CHIP_7300 0x05
> +
> +/* Interrupts */
> +#define AR7_IRQ_UART0 15
> +#define AR7_IRQ_UART1 16
> +
> +/* Clocks */
> +#define AR7_AFE_CLOCK 35328000
> +#define AR7_REF_CLOCK 25000000
> +#define AR7_XTAL_CLOCK 24000000
> +
> +struct plat_cpmac_data {
> + int reset_bit;
> + int power_bit;
> + u32 phy_mask;
> + char dev_addr[6];
> +};
> +
> +struct plat_dsl_data {
> + int reset_bit_dsl;
> + int reset_bit_sar;
> +};
> +
> +extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
> +
> +static inline u16 ar7_chip_id(void)
> +{
> + return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
> +}
> +
> +static inline u8 ar7_chip_rev(void)
> +{
> + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
> +}
> +
> +static inline int ar7_cpu_freq(void)
> +{
> + return ar7_cpu_clock;
> +}
> +
> +static inline int ar7_bus_freq(void)
> +{
> + return ar7_bus_clock;
> +}
> +
> +static inline int ar7_vbus_freq(void)
> +{
> + return ar7_bus_clock / 2;
> +}
> +#define ar7_cpmac_freq ar7_vbus_freq
> +
> +static inline int ar7_dsp_freq(void)
> +{
> + return ar7_dsp_clock;
> +}
> +
> +static inline int ar7_has_high_cpmac(void)
> +{
> + u16 chip_id = ar7_chip_id();
> + switch (chip_id) {
> + case AR7_CHIP_7100:
> + case AR7_CHIP_7200:
> + return 0;
> + default:
> + return 1;
> + }
> +}
> +#define ar7_has_high_vlynq ar7_has_high_cpmac
> +#define ar7_has_second_uart ar7_has_high_cpmac
> +
> +static inline void ar7_device_enable(u32 bit)
> +{
> + void *reset_reg =
> + (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
> + writel(readl(reset_reg) | (1 << bit), reset_reg);
> + mdelay(20);
Consider using msleep(20).
> +}
> +
> +static inline void ar7_device_disable(u32 bit)
> +{
> + void *reset_reg =
> + (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
> + writel(readl(reset_reg) & ~(1 << bit), reset_reg);
> + mdelay(20);
Ditto - consider using msleep(20).
> +}
> +
> +static inline void ar7_device_reset(u32 bit)
> +{
> + ar7_device_disable(bit);
> + ar7_device_enable(bit);
> +}
> +
> +static inline void ar7_device_on(u32 bit)
> +{
> + void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
> + writel(readl(power_reg) | (1 << bit), power_reg);
> + mdelay(20);
Ditto - consider using msleep(20).
> +}
> +
> +static inline void ar7_device_off(u32 bit)
> +{
> + void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
> + writel(readl(power_reg) & ~(1 << bit), power_reg);
> + mdelay(20);
Ditto - consider using msleep(20).
> +}
> +
> +#endif /* __AR7_H__ */
> diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
> new file mode 100644
> index 0000000..cbe9c4f
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ar7/gpio.h
> @@ -0,0 +1,110 @@
> +/*
> + * Copyright (C) 2007 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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef __AR7_GPIO_H__
> +#define __AR7_GPIO_H__
> +
> +#include <asm/mach-ar7/ar7.h>
> +
> +#define AR7_GPIO_MAX 32
> +
> +extern int gpio_request(unsigned gpio, const char *label);
> +extern void gpio_free(unsigned gpio);
> +
> +/* Common GPIO layer */
> +static inline int gpio_get_value(unsigned gpio)
> +{
> + void __iomem *gpio_in =
> + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
> +
> + return readl(gpio_in) & (1 << gpio);
> +}
> +
> +static inline void gpio_set_value(unsigned gpio, int value)
> +{
> + void __iomem *gpio_out =
> + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
> + unsigned tmp;
> +
> + tmp = readl(gpio_out) & ~(1 << gpio);
> + if (value)
> + tmp |= 1 << gpio;
> + writel(tmp, gpio_out);
> +}
> +
> +static inline int gpio_direction_input(unsigned gpio)
> +{
> + void __iomem *gpio_dir =
> + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
> +
> + if (gpio >= AR7_GPIO_MAX)
> + return -EINVAL;
> +
> + writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
> +
> + return 0;
> +}
> +
> +static inline int gpio_direction_output(unsigned gpio, int value)
> +{
> + void __iomem *gpio_dir =
> + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
> +
> + if (gpio >= AR7_GPIO_MAX)
> + return -EINVAL;
> +
> + gpio_set_value(gpio, value);
> + writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
> +
> + return 0;
> +}
> +
> +static inline int gpio_to_irq(unsigned gpio)
> +{
> + return -EINVAL;
> +}
> +
> +static inline int irq_to_gpio(unsigned irq)
> +{
> + return -EINVAL;
> +}
> +
> +/* Board specific GPIO functions */
> +static inline int ar7_gpio_enable(unsigned gpio)
> +{
> + void __iomem *gpio_en =
> + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
> +
> + writel(readl(gpio_en) | (1 << gpio), gpio_en);
> +
> + return 0;
> +}
> +
> +static inline int ar7_gpio_disable(unsigned gpio)
> +{
> + void __iomem *gpio_en =
> + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
> +
> + writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
> +
> + return 0;
> +}
> +
> +#include <asm-generic/gpio.h>
> +
> +#endif
> diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
> new file mode 100644
> index 0000000..39e9757
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ar7/irq.h
> @@ -0,0 +1,16 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Shamelessly copied from asm-mips/mach-emma2rh/
> + * Copyright (C) 2003 by Ralf Baechle
> + */
> +#ifndef __ASM_AR7_IRQ_H
> +#define __ASM_AR7_IRQ_H
> +
> +#define NR_IRQS 256
> +
> +#include_next <irq.h>
> +
> +#endif /* __ASM_AR7_IRQ_H */
> diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
> new file mode 100644
> index 0000000..55f5939
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ar7/prom.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright (C) 2006, 2007 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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef __PROM_H__
> +#define __PROM_H__
> +
> +extern char *prom_getenv(const char *name);
> +extern void prom_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
I see no users of prom_printf() - and it seems to duplicate early printk
anyway, so can you drop it?
> +extern void prom_meminit(void);
> +
> +#endif /* __PROM_H__ */
> diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
> new file mode 100644
> index 0000000..ac28f27
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ar7/spaces.h
> @@ -0,0 +1,22 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
> + * Copyright (C) 2000, 2002 Maciej W. Rozycki
> + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
> + */
> +#ifndef _ASM_AR7_SPACES_H
> +#define _ASM_AR7_SPACES_H
> +
> +/*
> + * This handles the memory map.
> + * We handle pages at KSEG0 for kernels with 32 bit address space.
> + */
> +#define PAGE_OFFSET 0x94000000UL
> +#define PHYS_OFFSET 0x14000000UL
> +
> +#include <asm/mach-generic/spaces.h>
> +
> +#endif /* __ASM_AR7_SPACES_H */
> diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h
> new file mode 100644
> index 0000000..f4862b5
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-ar7/war.h
> @@ -0,0 +1,25 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
> + */
> +#ifndef __ASM_MIPS_MACH_AR7_WAR_H
> +#define __ASM_MIPS_MACH_AR7_WAR_H
> +
> +#define R4600_V1_INDEX_ICACHEOP_WAR 0
> +#define R4600_V1_HIT_CACHEOP_WAR 0
> +#define R4600_V2_HIT_CACHEOP_WAR 0
> +#define R5432_CP0_INTERRUPT_WAR 0
> +#define BCM1250_M3_WAR 0
> +#define SIBYTE_1956_WAR 0
> +#define MIPS4K_ICACHE_REFILL_WAR 0
> +#define MIPS_CACHE_SYNC_WAR 0
> +#define TX49XX_ICACHE_INDEX_INV_WAR 0
> +#define RM9000_CDEX_SMP_WAR 0
> +#define ICACHE_REFILLS_WORKAROUND_WAR 0
> +#define R10000_LLSC_WAR 0
> +#define MIPS34K_MISSED_ITLB_WAR 0
> +
> +#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
Ralf
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-23 18:15 ` Ralf Baechle
@ 2009-06-24 9:12 ` Florian Fainelli
2009-06-24 10:22 ` Ralf Baechle
2009-06-24 11:28 ` Alexander Clouter
0 siblings, 2 replies; 11+ messages in thread
From: Florian Fainelli @ 2009-06-24 9:12 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Linux-MIPS
Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
> On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
>
> AR7 time again - the platform pending longest ... Let's see:
Thank you very much for your comments Ralf, please find below an updated
version which addresses all of your comments. I hope this time we are going
to make it ;)
--
From: Florian Fainelli <florian@openwrt.org>
Subject: Add support for Texas Instruments AR7 System-on-a-Chip
This patch adds support for the Texas Instruments AR7 System-on-a-Chip.
It supports the TNETD7100, 7200 and 7300 versions of the SoC.
Changes from v4:
- moved clock initialization from plat_mem_setup to arch_initcall
- removed dead kgdb code
- replaced calls to mdelay with msleep
- split gpio leds definitions into single lines
- re-order variables declaration in irq handling code
- removed ioport_resource initialization, there are no users of it
- removed iomem_resource initialization, same is done by the kernel
Changes from v3:
- added definition for AR7_SDRAM_BASE register
- switch to 32-bits accessors when accessing UART registers
- clean up header inclusion in time and setup files
- added help description below the AR7 config symbol
Changes from v2:
- remove ifdef on CONFIG_SERIAL_8250, we always enable it
- use PORT_16550A instead of PORT_AR7 avoids patching serial subsystem
Changes from v1:
- simplified mach-ar7/spaces.h
- removed superfluous parenthesis
- use lib/gcd.c
- select VLYNQ
- removed non-8250 UART code, there are only 8250 UARTs in use
Signed-off-by: Matteo Croce <matteo@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Eugene Konev <ejka@openwrt.org>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
--
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b29f028..ae38038 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -22,6 +22,26 @@ choice
config MACH_ALCHEMY
bool "Alchemy processor based machines"
+config AR7
+ bool "Texas Instruments AR7"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select CEVT_R4K
+ select CSRC_R4K
+ select IRQ_CPU
+ select NO_EXCEPT_FILL
+ select SWAP_IO_SPACE
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select GENERIC_GPIO
+ select GCD
+ select VLYNQ
+ help
+ Support for the Texas Instruments AR7 System-on-a-Chip
+ family: TNETD7100, 7200 and 7300.
+
config BASLER_EXCITE
bool "Basler eXcite smart camera"
select CEVT_R4K
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 807572a..861da51 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -173,6 +173,13 @@ libs-y += arch/mips/fw/lib/
#
#
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7) += arch/mips/ar7/
+cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7) += 0xffffffff94100000
+
+#
# Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
#
core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
new file mode 100644
index 0000000..7435e44
--- /dev/null
+++ b/arch/mips/ar7/Makefile
@@ -0,0 +1,10 @@
+
+obj-y := \
+ prom.o \
+ setup.o \
+ memory.o \
+ irq.o \
+ time.o \
+ platform.o \
+ gpio.o \
+ clock.o
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
new file mode 100644
index 0000000..7ce5f07
--- /dev/null
+++ b/arch/mips/ar7/clock.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gcd.h>
+#include <linux/io.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define BOOT_PLL_SOURCE_MASK 0x3
+#define CPU_PLL_SOURCE_SHIFT 16
+#define BUS_PLL_SOURCE_SHIFT 14
+#define USB_PLL_SOURCE_SHIFT 18
+#define DSP_PLL_SOURCE_SHIFT 22
+#define BOOT_PLL_SOURCE_AFE 0
+#define BOOT_PLL_SOURCE_BUS 0
+#define BOOT_PLL_SOURCE_REF 1
+#define BOOT_PLL_SOURCE_XTAL 2
+#define BOOT_PLL_SOURCE_CPU 3
+#define BOOT_PLL_BYPASS 0x00000020
+#define BOOT_PLL_ASYNC_MODE 0x02000000
+#define BOOT_PLL_2TO1_MODE 0x00008000
+
+#define TNETD7200_CLOCK_ID_CPU 0
+#define TNETD7200_CLOCK_ID_DSP 1
+#define TNETD7200_CLOCK_ID_USB 2
+
+#define TNETD7200_DEF_CPU_CLK 211000000
+#define TNETD7200_DEF_DSP_CLK 125000000
+#define TNETD7200_DEF_USB_CLK 48000000
+
+struct tnetd7300_clock {
+ u32 ctrl;
+#define PREDIV_MASK 0x001f0000
+#define PREDIV_SHIFT 16
+#define POSTDIV_MASK 0x0000001f
+ u32 unused1[3];
+ u32 pll;
+#define MUL_MASK 0x0000f000
+#define MUL_SHIFT 12
+#define PLL_MODE_MASK 0x00000001
+#define PLL_NDIV 0x00000800
+#define PLL_DIV 0x00000002
+#define PLL_STATUS 0x00000001
+ u32 unused2[3];
+};
+
+struct tnetd7300_clocks {
+ struct tnetd7300_clock bus;
+ struct tnetd7300_clock cpu;
+ struct tnetd7300_clock usb;
+ struct tnetd7300_clock dsp;
+};
+
+struct tnetd7200_clock {
+ u32 ctrl;
+ u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+ u32 mul;
+ u32 prediv;
+ u32 postdiv;
+ u32 postdiv2;
+ u32 unused2[6];
+ u32 cmd;
+ u32 status;
+ u32 cmden;
+ u32 padding[15];
+};
+
+struct tnetd7200_clocks {
+ struct tnetd7200_clock cpu;
+ struct tnetd7200_clock dsp;
+ 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 void approximate(int base, int target, int *prediv,
+ int *postdiv, int *mul)
+{
+ int i, j, k, freq, res = target;
+ for (i = 1; i <= 16; i++)
+ for (j = 1; j <= 32; j++)
+ for (k = 1; k <= 32; k++) {
+ freq = abs(base / j * i / k - target);
+ if (freq < res) {
+ res = freq;
+ *mul = i;
+ *prediv = j;
+ *postdiv = k;
+ }
+ }
+}
+
+static void calculate(int base, int target, int *prediv, int *postdiv,
+ int *mul)
+{
+ int tmp_gcd, tmp_base, tmp_freq;
+
+ for (*prediv = 1; *prediv <= 32; (*prediv)++) {
+ tmp_base = base / *prediv;
+ tmp_gcd = gcd(target, tmp_base);
+ *mul = target / tmp_gcd;
+ *postdiv = tmp_base / tmp_gcd;
+ if ((*mul < 1) || (*mul >= 16))
+ continue;
+ if ((*postdiv > 0) & (*postdiv <= 32))
+ break;
+ }
+
+ if (base / *prediv * *mul / *postdiv != target) {
+ approximate(base, target, prediv, postdiv, mul);
+ tmp_freq = base / *prediv * *mul / *postdiv;
+ printk(KERN_WARNING
+ "Adjusted requested frequency %d to %d\n",
+ target, tmp_freq);
+ }
+
+ printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
+ *prediv, *postdiv, *mul);
+}
+
+static int tnetd7300_dsp_clock(void)
+{
+ u32 didr1, didr2;
+ u8 rev = ar7_chip_rev();
+ didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
+ didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
+ if (didr2 & (1 << 23))
+ return 0;
+ if ((rev >= 0x23) && (rev != 0x57))
+ return 250000000;
+ if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
+ > 4208000)
+ return 250000000;
+ return 0;
+}
+
+static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
+ u32 *bootcr, u32 bus_clock)
+{
+ int product;
+ int base_clock = AR7_REF_CLOCK;
+ u32 ctrl = readl(&clock->ctrl);
+ u32 pll = readl(&clock->pll);
+ int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
+ int postdiv = (ctrl & POSTDIV_MASK) + 1;
+ int divisor = prediv * postdiv;
+ int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
+
+ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+ case BOOT_PLL_SOURCE_BUS:
+ base_clock = bus_clock;
+ break;
+ case BOOT_PLL_SOURCE_REF:
+ base_clock = AR7_REF_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_XTAL:
+ base_clock = AR7_XTAL_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_CPU:
+ base_clock = ar7_cpu_clock;
+ break;
+ }
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base_clock / divisor;
+
+ if ((pll & PLL_MODE_MASK) == 0)
+ return (base_clock >> (mul / 16 + 1)) / divisor;
+
+ if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
+ product = (mul & 1) ?
+ (base_clock * mul) >> 1 :
+ (base_clock * (mul - 1)) >> 2;
+ return product / divisor;
+ }
+
+ if (mul == 16)
+ return base_clock / divisor;
+
+ return base_clock * mul / divisor;
+}
+
+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;
+
+ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+ case BOOT_PLL_SOURCE_BUS:
+ base_clock = ar7_bus_clock;
+ break;
+ case BOOT_PLL_SOURCE_REF:
+ base_clock = AR7_REF_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_XTAL:
+ base_clock = AR7_XTAL_CLOCK;
+ break;
+ case BOOT_PLL_SOURCE_CPU:
+ base_clock = ar7_cpu_clock;
+ break;
+ }
+
+ calculate(base_clock, frequency, &prediv, &postdiv, &mul);
+
+ writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
+ msleep(1);
+ writel(4, &clock->pll);
+ while (readl(&clock->pll) & PLL_STATUS)
+ ;
+ writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
+ msleep(75);
+}
+
+static void __init tnetd7300_init_clocks(void)
+{
+ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ struct tnetd7300_clocks *clocks =
+ (struct tnetd7300_clocks *)
+ ioremap_nocache(AR7_REGS_POWER + 0x20,
+ sizeof(struct tnetd7300_clocks));
+
+ ar7_bus_clock = 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,
+ &clocks->cpu, bootcr, AR7_AFE_CLOCK);
+ else
+ ar7_cpu_clock = ar7_bus_clock;
+/*
+ tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
+ bootcr, 48000000);
+*/
+ if (ar7_dsp_clock == 250000000)
+ tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
+ bootcr, ar7_dsp_clock);
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock,
+ u32 *bootcr, u32 bus_clock)
+{
+ int divisor = ((readl(&clock->prediv) & 0x1f) + 1) *
+ ((readl(&clock->postdiv) & 0x1f) + 1);
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base / divisor;
+
+ return base * ((readl(&clock->mul) & 0xf) + 1) / divisor;
+}
+
+
+static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
+ int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
+{
+ printk(KERN_INFO
+ "Clocks: base = %d, frequency = %u, prediv = %d, "
+ "postdiv = %d, postdiv2 = %d, mul = %d\n",
+ base, frequency, prediv, postdiv, postdiv2, mul);
+
+ writel(0, &clock->ctrl);
+ writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+ writel((mul - 1) & 0xF, &clock->mul);
+
+ for (mul = 0; mul < 2000; mul++)
+ ; /* nop */
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
+
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
+
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+ while (readl(&clock->status) & 0x1)
+ ; /* nop */
+
+ writel(readl(&clock->ctrl) | 1, &clock->ctrl);
+}
+
+static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
+{
+ if (*bootcr & BOOT_PLL_ASYNC_MODE)
+ /* Async */
+ switch (clock_id) {
+ case TNETD7200_CLOCK_ID_DSP:
+ return AR7_REF_CLOCK;
+ default:
+ return AR7_AFE_CLOCK;
+ }
+ else
+ /* Sync */
+ if (*bootcr & BOOT_PLL_2TO1_MODE)
+ /* 2:1 */
+ switch (clock_id) {
+ case TNETD7200_CLOCK_ID_DSP:
+ return AR7_REF_CLOCK;
+ default:
+ return AR7_AFE_CLOCK;
+ }
+ else
+ /* 1:1 */
+ return AR7_REF_CLOCK;
+}
+
+
+static void __init tnetd7200_init_clocks(void)
+{
+ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ struct tnetd7200_clocks *clocks =
+ (struct tnetd7200_clocks *)
+ ioremap_nocache(AR7_REGS_POWER + 0x80,
+ sizeof(struct tnetd7200_clocks));
+ int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
+ int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
+ int usb_base, usb_mul, usb_prediv, usb_postdiv;
+
+ cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
+ dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
+
+ if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+ printk(KERN_INFO "Clocks: Async 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) / dsp_postdiv;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
+ ar7_bus_clock);
+
+ 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_postdiv;
+ tnetd7200_set_clock(cpu_base, &clocks->cpu,
+ cpu_prediv, cpu_postdiv, -1, cpu_mul,
+ ar7_cpu_clock);
+
+ } else
+ if (*bootcr & BOOT_PLL_2TO1_MODE) {
+ printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
+
+ 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_postdiv;
+ tnetd7200_set_clock(cpu_base, &clocks->cpu,
+ cpu_prediv, cpu_postdiv, -1, cpu_mul,
+ ar7_cpu_clock);
+
+ 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;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+ dsp_mul * 2, ar7_bus_clock);
+ } 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)
+ / dsp_postdiv;
+ tnetd7200_set_clock(dsp_base, &clocks->dsp,
+ dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+ dsp_mul * 2, ar7_bus_clock);
+
+ ar7_cpu_clock = ar7_bus_clock;
+ }
+
+ printk(KERN_INFO "Clocks: Setting USB clock\n");
+ usb_base = ar7_bus_clock;
+ 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;
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+int __init ar7_init_clocks(void)
+{
+ switch (ar7_chip_id()) {
+ case AR7_CHIP_7100:
+ tnetd7200_init_clocks();
+ break;
+ case AR7_CHIP_7200:
+ tnetd7200_init_clocks();
+ break;
+ case AR7_CHIP_7300:
+ ar7_dsp_clock = tnetd7300_dsp_clock();
+ tnetd7300_init_clocks();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+arch_initcall(ar7_init_clocks);
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
new file mode 100644
index 0000000..74e14a3
--- /dev/null
+++ b/arch/mips/ar7/gpio.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach-ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX];
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ if (ar7_gpio_list[gpio])
+ return -EBUSY;
+
+ if (label)
+ ar7_gpio_list[gpio] = label;
+ else
+ ar7_gpio_list[gpio] = "busy";
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+ BUG_ON(!ar7_gpio_list[gpio]);
+ ar7_gpio_list[gpio] = NULL;
+}
+EXPORT_SYMBOL(gpio_free);
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
new file mode 100644
index 0000000..c781556
--- /dev/null
+++ b/arch/mips/ar7/irq.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define EXCEPT_OFFSET 0x80
+#define PACE_OFFSET 0xA0
+#define CHNLS_OFFSET 0x200
+
+#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10)
+#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8)
+#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */
+#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */
+#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */
+#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */
+#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */
+#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */
+#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */
+#define PIR_OFFSET (0x40)
+#define MSR_OFFSET (0x44)
+#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */
+#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */
+
+#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
+
+#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
+
+static int ar7_irq_base;
+
+static void ar7_unmask_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(ESR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_mask_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(ECR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_ack_irq(unsigned int irq)
+{
+ writel(1 << ((irq - ar7_irq_base) % 32),
+ REG(CR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_unmask_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+}
+
+static void ar7_mask_sec_irq(unsigned int irq)
+{
+ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+}
+
+static void ar7_ack_sec_irq(unsigned int irq)
+{
+ writel(1 << (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
+};
+
+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,
+};
+
+static struct irqaction ar7_cascade_action = {
+ .handler = no_action,
+ .name = "AR7 cascade interrupt"
+};
+
+static void __init ar7_irq_init(int base)
+{
+ int i;
+ /*
+ * Disable interrupts and clear pending
+ */
+ writel(0xffffffff, REG(ECR_OFFSET(0)));
+ writel(0xff, REG(ECR_OFFSET(32)));
+ writel(0xffffffff, REG(SEC_ECR_OFFSET));
+ writel(0xffffffff, REG(CR_OFFSET(0)));
+ writel(0xff, REG(CR_OFFSET(32)));
+ writel(0xffffffff, REG(SEC_CR_OFFSET));
+
+ ar7_irq_base = 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,
+ handle_level_irq);
+ /* Secondary IRQ's */
+ if (i < 32)
+ set_irq_chip_and_handler(base + i + 40,
+ &ar7_sec_irq_type,
+ handle_level_irq);
+ }
+
+ setup_irq(2, &ar7_cascade_action);
+ setup_irq(ar7_irq_base, &ar7_cascade_action);
+ set_c0_status(IE_IRQ0);
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+ ar7_irq_init(8);
+}
+
+static void ar7_cascade(void)
+{
+ u32 status;
+ int i, irq;
+
+ /* Primary IRQ's */
+ irq = readl(REG(PIR_OFFSET)) & 0x3f;
+ if (irq) {
+ do_IRQ(ar7_irq_base + irq);
+ return;
+ }
+
+ /* Secondary IRQ's are cascaded through primary '0' */
+ writel(1, REG(CR_OFFSET(irq)));
+ status = readl(REG(SEC_SR_OFFSET));
+ for (i = 0; i < 32; i++) {
+ if (status & 1) {
+ do_IRQ(ar7_irq_base + i + 40);
+ return;
+ }
+ status >>= 1;
+ }
+
+ spurious_interrupt();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(7);
+ else if (pending & STATUSF_IP2) /* int0 hardware line */
+ ar7_cascade();
+ else
+ spurious_interrupt();
+}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
new file mode 100644
index 0000000..46fed44
--- /dev/null
+++ b/arch/mips/ar7/memory.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mips-boards/prom.h>
+
+static int __init memsize(void)
+{
+ u32 size = (64 << 20);
+ u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
+ u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+ u32 *tmpaddr = addr;
+
+ while (tmpaddr > kernel_end) {
+ *tmpaddr = (u32)tmpaddr;
+ size >>= 1;
+ tmpaddr -= size >> 2;
+ }
+
+ do {
+ tmpaddr += size >> 2;
+ if (*tmpaddr != (u32)tmpaddr)
+ break;
+ size <<= 1;
+ } while (size < (64 << 20));
+
+ writel(tmpaddr, &addr);
+
+ return size;
+}
+
+void __init prom_meminit(void)
+{
+ unsigned long pages;
+
+ pages = memsize() >> PAGE_SHIFT;
+ add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+ /* Nothing to free */
+}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
new file mode 100644
index 0000000..5422449
--- /dev/null
+++ b/arch/mips/ar7/platform.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/vlynq.h>
+#include <linux/leds.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/prom.h>
+
+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;
+ struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
+ result = gpio_request(pdata->gpio_bit, "vlynq");
+ if (result)
+ goto out;
+
+ ar7_device_reset(pdata->reset_bit);
+
+ result = ar7_gpio_disable(pdata->gpio_bit);
+ if (result)
+ goto out_enabled;
+
+ result = ar7_gpio_enable(pdata->gpio_bit);
+ if (result)
+ goto out_enabled;
+
+ result = gpio_direction_output(pdata->gpio_bit, 0);
+ if (result)
+ goto out_gpio_enabled;
+
+ msleep(50);
+
+ gpio_set_value(pdata->gpio_bit, 1);
+ msleep(50);
+
+ return 0;
+
+out_gpio_enabled:
+ ar7_gpio_disable(pdata->gpio_bit);
+out_enabled:
+ ar7_device_disable(pdata->reset_bit);
+ gpio_free(pdata->gpio_bit);
+out:
+ return result;
+}
+
+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[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_MAC0,
+ .end = AR7_REGS_MAC0 + 0x7ff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 27,
+ .end = 27,
+ },
+};
+
+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 resource vlynq_low_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ0,
+ .end = AR7_REGS_VLYNQ0 + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 29,
+ .end = 29,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x04000000,
+ .end = 0x04ffffff,
+ },
+ {
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 80,
+ .end = 111,
+ },
+};
+
+static struct resource vlynq_high_res[] = {
+ {
+ .name = "regs",
+ .flags = IORESOURCE_MEM,
+ .start = AR7_REGS_VLYNQ1,
+ .end = AR7_REGS_VLYNQ1 + 0xff,
+ },
+ {
+ .name = "irq",
+ .flags = IORESOURCE_IRQ,
+ .start = 33,
+ .end = 33,
+ },
+ {
+ .name = "mem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
+ },
+ {
+ .name = "devirq",
+ .flags = IORESOURCE_IRQ,
+ .start = 112,
+ .end = 143,
+ },
+};
+
+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 = 0x034001fff,
+ },
+};
+
+static struct physmap_flash_data physmap_flash_data = {
+ .width = 2,
+};
+
+static struct plat_cpmac_data cpmac_low_data = {
+ .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,
+};
+
+static u64 cpmac_dma_mask = DMA_32BIT_MASK;
+static struct platform_device cpmac_low = {
+ .id = 0,
+ .name = "cpmac",
+ .dev = {
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ .platform_data = &cpmac_low_data,
+ },
+ .resource = cpmac_low_res,
+ .num_resources = ARRAY_SIZE(cpmac_low_res),
+};
+
+static struct platform_device cpmac_high = {
+ .id = 1,
+ .name = "cpmac",
+ .dev = {
+ .dma_mask = &cpmac_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ .platform_data = &cpmac_high_data,
+ },
+ .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 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 gpio_led default_leds[] = {
+ {
+ .name = "status",
+ .gpio = 8,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led dsl502t_leds[] = {
+ {
+ .name = "status",
+ .gpio = 9,
+ .active_low = 1,
+ },
+ {
+ .name = "ethernet",
+ .gpio = 7,
+ .active_low = 1,
+ },
+ {
+ .name = "usb",
+ .gpio = 12,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led dg834g_leds[] = {
+ {
+ .name = "ppp",
+ .gpio = 6,
+ .active_low = 1,
+ },
+ {
+ .name = "status",
+ .gpio = 7,
+ .active_low = 1,
+ },
+ {
+ .name = "adsl",
+ .gpio = 8,
+ .active_low = 1,
+ },
+ {
+ .name = "wifi",
+ .gpio = 12,
+ .active_low = 1,
+ },
+ {
+ .name = "power",
+ .gpio = 14,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+};
+
+static struct gpio_led fb_sl_leds[] = {
+ {
+ .name = "1",
+ .gpio = 7,
+ },
+ {
+ .name = "2",
+ .gpio = 13,
+ .active_low = 1,
+ },
+ {
+ .name = "3",
+ .gpio = 10,
+ .active_low = 1,
+ },
+ {
+ .name = "4",
+ .gpio = 12,
+ .active_low = 1,
+ },
+ {
+ .name = "5",
+ .gpio = 9,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led fb_fon_leds[] = {
+ {
+ .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_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 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 */
+ ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+ ar7_led_data.leds = default_leds;
+
+ /* FIXME: the whole thing is unreliable */
+ prid = prom_getenv("ProductID");
+ usb_prod = prom_getenv("usb_prod");
+
+ /* If we can't get the product id from PROM, use the default LEDs */
+ if (!prid)
+ return;
+
+ if (strstr(prid, "Fritz_Box_FON")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
+ ar7_led_data.leds = fb_fon_leds;
+ } else if (strstr(prid, "Fritz_Box_")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
+ ar7_led_data.leds = fb_sl_leds;
+ } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
+ && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
+ ar7_led_data.leds = dsl502t_leds;
+ } else if (strstr(prid, "DG834")) {
+ ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
+ ar7_led_data.leds = dg834g_leds;
+ }
+}
+
+static int __init ar7_register_devices(void)
+{
+ int res;
+ static struct uart_port uart_port[2];
+
+ 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]);
+ 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]);
+ if (res)
+ return res;
+ }
+
+ res = platform_device_register(&physmap_flash);
+ if (res)
+ return res;
+
+ ar7_device_disable(vlynq_low_data.reset_bit);
+ res = platform_device_register(&vlynq_low);
+ if (res)
+ return res;
+
+ if (ar7_has_high_vlynq()) {
+ ar7_device_disable(vlynq_high_data.reset_bit);
+ res = platform_device_register(&vlynq_high);
+ if (res)
+ return res;
+ }
+
+ if (ar7_has_high_cpmac()) {
+ cpmac_get_mac(1, cpmac_high_data.dev_addr);
+ res = platform_device_register(&cpmac_high);
+ if (res)
+ return res;
+ } else {
+ cpmac_low_data.phy_mask = 0xffffffff;
+ }
+
+ cpmac_get_mac(0, cpmac_low_data.dev_addr);
+ res = platform_device_register(&cpmac_low);
+ if (res)
+ return res;
+
+ detect_leds();
+ res = platform_device_register(&ar7_gpio_leds);
+ if (res)
+ return res;
+
+ res = platform_device_register(&ar7_udc);
+
+ return res;
+}
+arch_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
new file mode 100644
index 0000000..a320bce
--- /dev/null
+++ b/arch/mips/ar7/prom.c
@@ -0,0 +1,297 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <asm/bootinfo.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+#define MAX_ENTRY 80
+
+struct env_var {
+ char *name;
+ char *value;
+};
+
+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;
+
+ return NULL;
+}
+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] */
+
+ 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';
+ }
+}
+
+struct psbl_rec {
+ u32 psbl_size;
+ u32 env_base;
+ u32 env_size;
+ u32 ffs_base;
+ u32 ffs_size;
+};
+
+static __initdata char psp_env_version[] = "TIENV0.8";
+
+struct psp_env_chunk {
+ u8 num;
+ u8 ctrl;
+ u16 csum;
+ u8 len;
+ char data[11];
+} __attribute__ ((packed));
+
+struct psp_var_map_entry {
+ 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" },
+};
+
+/*
+
+Well-known variable (num is looked up in table above for matching variable name)
+Example: cpufrequency=211968000
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in a single chunk
+Example: NAME=VALUE
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in 2 chunks (len is the number of chunks)
+Example: bootloaderVersion=1.3.7.15
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Data is padded with 0xFF
+
+*/
+
+#define PSP_ENV_SIZE 4096
+
+static char psp_env_data[PSP_ENV_SIZE] = { 0, };
+
+static char * __init lookup_psp_var_map(u8 num)
+{
+ int i;
+
+ for (i = 0; i < sizeof(psp_var_map); i++)
+ if (psp_var_map[i].num == num)
+ return psp_var_map[i].value;
+
+ return NULL;
+}
+
+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;
+ adam2_env[i].value = value;
+ return;
+ } else if (!strcmp(adam2_env[i].name, name)) {
+ adam2_env[i].value = value;
+ return;
+ }
+ }
+}
+
+static int __init parse_psp_env(void *psp_env_base)
+{
+ int i, n;
+ char *name, *value;
+ struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
+
+ memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
+
+ i = 1;
+ n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
+ while (i < n) {
+ if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
+ break;
+ value = chunks[i].data;
+ if (chunks[i].num) {
+ name = lookup_psp_var_map(chunks[i].num);
+ } else {
+ name = value;
+ value += strlen(name) + 1;
+ }
+ if (name)
+ add_adam2_var(name, value);
+ i += chunks[i].len;
+ }
+ return 0;
+}
+
+static void __init ar7_init_env(struct env_var *env)
+{
+ int i;
+ struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
+ void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
+
+ if (strcmp(psp_env, psp_env_version) == 0) {
+ parse_psp_env(psp_env);
+ } else {
+ for (i = 0; i < MAX_ENTRY; i++, env++)
+ if (env->name)
+ add_adam2_var(env->name, env->value);
+ }
+}
+
+static void __init console_config(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char console_string[40];
+ int baud = 0;
+ char parity = '\0', bits = '\0', flow = '\0';
+ char *s, *p;
+
+ if (strstr(prom_getcmdline(), "console="))
+ return;
+
+#ifdef CONFIG_KGDB
+ if (!strstr(prom_getcmdline(), "nokgdb")) {
+ strcat(prom_getcmdline(), " console=kgdb");
+ kgdb_enabled = 1;
+ return;
+ }
+#endif
+
+ s = prom_getenv("modetty0");
+ if (s) {
+ baud = simple_strtoul(s, &p, 10);
+ s = p;
+ if (*s == ',')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s == ',')
+ s++;
+ if (*s)
+ bits = *s++;
+ if (*s == ',')
+ s++;
+ if (*s == 'h')
+ flow = 'r';
+ }
+
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+
+ if (flow == 'r')
+ sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+ parity, bits, flow);
+ else
+ sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
+ bits);
+ strcat(prom_getcmdline(), console_string);
+#endif
+}
+
+void __init prom_init(void)
+{
+ ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
+ ar7_init_env((struct env_var *)fw_arg2);
+ console_config();
+}
+
+#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
+static inline unsigned int serial_in(int offset)
+{
+ return readl((void *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+ writel(value, (void *)PORT(offset));
+}
+
+char prom_getchar(void)
+{
+ while (!(serial_in(UART_LSR) & UART_LSR_DR))
+ ;
+ return serial_in(UART_RX);
+}
+
+int prom_putchar(char c)
+{
+ while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+ ;
+ serial_out(UART_TX, c);
+ return 1;
+}
+
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
new file mode 100644
index 0000000..cccb484
--- /dev/null
+++ b/arch/mips/ar7/setup.c
@@ -0,0 +1,98 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/time.h>
+
+#include <asm/reboot.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+static void ar7_machine_restart(char *command);
+static void ar7_machine_halt(void);
+static void ar7_machine_power_off(void);
+
+static void ar7_machine_restart(char *command)
+{
+ u32 *softres_reg = ioremap(AR7_REGS_RESET +
+ AR7_RESET_SOFTWARE, 1);
+ writel(1, softres_reg);
+}
+
+static void ar7_machine_halt(void)
+{
+ while (1)
+ ;
+}
+
+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();
+}
+
+const char *get_system_type(void)
+{
+ u16 chip_id = ar7_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)";
+ default:
+ return "TI AR7 (Unknown)";
+ }
+}
+
+static int __init ar7_init_console(void)
+{
+ return 0;
+}
+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;
+
+ _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");
+ 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());
+}
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
new file mode 100644
index 0000000..a1fba89
--- /dev/null
+++ b/arch/mips/ar7/time.c
@@ -0,0 +1,30 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+
+void __init plat_time_init(void)
+{
+ mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
new file mode 100644
index 0000000..4ebe2c6
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/ar7.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AR7_H__
+#define __AR7_H__
+
+#include <linux/delay.h>
+#include <asm/addrspace.h>
+#include <linux/io.h>
+
+#define AR7_SDRAM_BASE 0x14000000
+
+#define AR7_REGS_BASE 0x08610000
+
+#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
+#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
+/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
+#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
+#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
+#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
+#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
+#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
+#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
+#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
+#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
+#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
+
+#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
+#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
+#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
+
+#define AR7_RESET_PEREPHERIAL 0x0
+#define AR7_RESET_SOFTWARE 0x4
+#define AR7_RESET_STATUS 0x8
+
+#define AR7_RESET_BIT_CPMAC_LO 17
+#define AR7_RESET_BIT_CPMAC_HI 21
+#define AR7_RESET_BIT_MDIO 22
+#define AR7_RESET_BIT_EPHY 26
+
+/* GPIO control registers */
+#define AR7_GPIO_INPUT 0x0
+#define AR7_GPIO_OUTPUT 0x4
+#define AR7_GPIO_DIR 0x8
+#define AR7_GPIO_ENABLE 0xc
+
+#define AR7_CHIP_7100 0x18
+#define AR7_CHIP_7200 0x2b
+#define AR7_CHIP_7300 0x05
+
+/* Interrupts */
+#define AR7_IRQ_UART0 15
+#define AR7_IRQ_UART1 16
+
+/* Clocks */
+#define AR7_AFE_CLOCK 35328000
+#define AR7_REF_CLOCK 25000000
+#define AR7_XTAL_CLOCK 24000000
+
+struct plat_cpmac_data {
+ int reset_bit;
+ int power_bit;
+ u32 phy_mask;
+ char dev_addr[6];
+};
+
+struct plat_dsl_data {
+ int reset_bit_dsl;
+ int reset_bit_sar;
+};
+
+extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
+
+static inline u16 ar7_chip_id(void)
+{
+ return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
+}
+
+static inline u8 ar7_chip_rev(void)
+{
+ return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
+}
+
+static inline int ar7_cpu_freq(void)
+{
+ return ar7_cpu_clock;
+}
+
+static inline int ar7_bus_freq(void)
+{
+ return ar7_bus_clock;
+}
+
+static inline int ar7_vbus_freq(void)
+{
+ return ar7_bus_clock / 2;
+}
+#define ar7_cpmac_freq ar7_vbus_freq
+
+static inline int ar7_dsp_freq(void)
+{
+ return ar7_dsp_clock;
+}
+
+static inline int ar7_has_high_cpmac(void)
+{
+ u16 chip_id = ar7_chip_id();
+ switch (chip_id) {
+ case AR7_CHIP_7100:
+ case AR7_CHIP_7200:
+ return 0;
+ default:
+ return 1;
+ }
+}
+#define ar7_has_high_vlynq ar7_has_high_cpmac
+#define ar7_has_second_uart ar7_has_high_cpmac
+
+static inline void ar7_device_enable(u32 bit)
+{
+ void *reset_reg =
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ writel(readl(reset_reg) | (1 << bit), reset_reg);
+ msleep(20);
+}
+
+static inline void ar7_device_disable(u32 bit)
+{
+ void *reset_reg =
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ writel(readl(reset_reg) & ~(1 << bit), reset_reg);
+ msleep(20);
+}
+
+static inline void ar7_device_reset(u32 bit)
+{
+ ar7_device_disable(bit);
+ ar7_device_enable(bit);
+}
+
+static inline void ar7_device_on(u32 bit)
+{
+ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+ writel(readl(power_reg) | (1 << bit), power_reg);
+ msleep(20);
+}
+
+static inline void ar7_device_off(u32 bit)
+{
+ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+ writel(readl(power_reg) & ~(1 << bit), power_reg);
+ msleep(20);
+}
+
+#endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
new file mode 100644
index 0000000..cbe9c4f
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/gpio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __AR7_GPIO_H__
+#define __AR7_GPIO_H__
+
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+
+/* Common GPIO layer */
+static inline int gpio_get_value(unsigned gpio)
+{
+ void __iomem *gpio_in =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+ return readl(gpio_in) & (1 << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ void __iomem *gpio_out =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+ unsigned tmp;
+
+ tmp = readl(gpio_out) & ~(1 << gpio);
+ if (value)
+ tmp |= 1 << gpio;
+ writel(tmp, gpio_out);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ void __iomem *gpio_dir =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ void __iomem *gpio_dir =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ gpio_set_value(gpio, value);
+ writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+ return 0;
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+/* Board specific GPIO functions */
+static inline int ar7_gpio_enable(unsigned gpio)
+{
+ void __iomem *gpio_en =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+ writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+ return 0;
+}
+
+static inline int ar7_gpio_disable(unsigned gpio)
+{
+ void __iomem *gpio_en =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+ writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+ return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
new file mode 100644
index 0000000..39e9757
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/irq.h
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Shamelessly copied from asm-mips/mach-emma2rh/
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_AR7_IRQ_H
+#define __ASM_AR7_IRQ_H
+
+#define NR_IRQS 256
+
+#include_next <irq.h>
+
+#endif /* __ASM_AR7_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
new file mode 100644
index 0000000..088f61f
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/prom.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006, 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __PROM_H__
+#define __PROM_H__
+
+extern char *prom_getenv(const char *name);
+extern void prom_meminit(void);
+
+#endif /* __PROM_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
new file mode 100644
index 0000000..ac28f27
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/spaces.h
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_AR7_SPACES_H
+#define _ASM_AR7_SPACES_H
+
+/*
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
+ */
+#define PAGE_OFFSET 0x94000000UL
+#define PHYS_OFFSET 0x14000000UL
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h
new file mode 100644
index 0000000..f4862b5
--- /dev/null
+++ b/arch/mips/include/asm/mach-ar7/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_AR7_WAR_H
+#define __ASM_MIPS_MACH_AR7_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 9:12 ` Florian Fainelli
@ 2009-06-24 10:22 ` Ralf Baechle
2009-06-24 12:17 ` Florian Fainelli
2009-06-24 11:28 ` Alexander Clouter
1 sibling, 1 reply; 11+ messages in thread
From: Ralf Baechle @ 2009-06-24 10:22 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Linux-MIPS
On Wed, Jun 24, 2009 at 11:12:57AM +0200, Florian Fainelli wrote:
> Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
> > On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
> >
> > AR7 time again - the platform pending longest ... Let's see:
>
> Thank you very much for your comments Ralf, please find below an updated
> version which addresses all of your comments. I hope this time we are going
> to make it ;)
One final request, could you send me a useful defconfig file? for AR7?
Ralf
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 9:12 ` Florian Fainelli
2009-06-24 10:22 ` Ralf Baechle
@ 2009-06-24 11:28 ` Alexander Clouter
2009-06-24 12:23 ` Ralf Baechle
2009-06-24 17:32 ` Florian Fainelli
1 sibling, 2 replies; 11+ messages in thread
From: Alexander Clouter @ 2009-06-24 11:28 UTC (permalink / raw)
To: linux-mips
Hi,
Florian Fainelli <florian@openwrt.org> wrote:
> Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
>> On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
>>
>> AR7 time again - the platform pending longest ... Let's see:
>
> Thank you very much for your comments Ralf, please find below an updated
> version which addresses all of your comments. I hope this time we are going
> to make it ;)
>
I am hoping someone can have a tackle of the lzma/bzip2 kernel/initramfs
generic compression code myself, but I guess one thing at a time. :) If
you have a simple way for me to produce a LZMA'd image, I'll test it
this on my WAG54Gv2 (I need the image to be less than 700kB).
My comments, for what they are worth, below:
> From: Florian Fainelli <florian@openwrt.org>
> Subject: Add support for Texas Instruments AR7 System-on-a-Chip
>
> This patch adds support for the Texas Instruments AR7 System-on-a-Chip.
> It supports the TNETD7100, 7200 and 7300 versions of the SoC.
>
> Changes from v4:
> [snipped]
>
> Signed-off-by: Matteo Croce <matteo@openwrt.org>
> Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> Signed-off-by: Eugene Konev <ejka@openwrt.org>
> Signed-off-by: Nicolas Thill <nico@openwrt.org>
> Signed-off-by: Florian Fainelli <florian@openwrt.org>
> --
> [snipped]
>
> diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
> new file mode 100644
> index 0000000..7ce5f07
> --- /dev/null
> +++ b/arch/mips/ar7/clock.c
> @@ -0,0 +1,450 @@
> [snipped]
> +static void __init tnetd7300_init_clocks(void)
> +{
> + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> + struct tnetd7300_clocks *clocks =
> + (struct tnetd7300_clocks *)
> + ioremap_nocache(AR7_REGS_POWER + 0x20,
> + sizeof(struct tnetd7300_clocks));
> +
>
Needless cast'ing and also should you not check that NULL is not
returned for both of these ioremap's?
> + ar7_bus_clock = 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,
> + &clocks->cpu, bootcr, AR7_AFE_CLOCK);
> + else
> + ar7_cpu_clock = ar7_bus_clock;
> +/*
> + tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
> + bootcr, 48000000);
> +*/
>
Dead code? Feels that way with what then follows.
> + if (ar7_dsp_clock == 250000000)
> + tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
> + bootcr, ar7_dsp_clock);
> +
> + iounmap(clocks);
> + iounmap(bootcr);
> +}
>
> [snipped]
>
> +static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
> + int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
> +{
> + printk(KERN_INFO
> + "Clocks: base = %d, frequency = %u, prediv = %d, "
> + "postdiv = %d, postdiv2 = %d, mul = %d\n",
> + base, frequency, prediv, postdiv, postdiv2, mul);
> +
> + writel(0, &clock->ctrl);
> + writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
> + writel((mul - 1) & 0xF, &clock->mul);
> +
> + for (mul = 0; mul < 2000; mul++)
> + ; /* nop */
> +
Only for furthering my know how, this because the timing is changing so
you cannot msleep() or whatever? Can we not jump straight into the
while() instead and wait it out? Alternatively start with a:
----
while (!readl(&clock->status) & 0x1)
;
----
and then lead into the following?
> + while (readl(&clock->status) & 0x1)
> + ; /* nop */
> +
> + writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
> +
> + writel(readl(&clock->cmden) | 1, &clock->cmden);
> + writel(readl(&clock->cmd) | 1, &clock->cmd);
> +
> + while (readl(&clock->status) & 0x1)
> + ; /* nop */
> +
> + writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
> +
> + writel(readl(&clock->cmden) | 1, &clock->cmden);
> + writel(readl(&clock->cmd) | 1, &clock->cmd);
> +
> + while (readl(&clock->status) & 0x1)
> + ; /* nop */
> +
> + writel(readl(&clock->ctrl) | 1, &clock->ctrl);
> +}
>
> [snipped]
>
> +static void __init tnetd7200_init_clocks(void)
> +{
> + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> + struct tnetd7200_clocks *clocks =
> + (struct tnetd7200_clocks *)
> + ioremap_nocache(AR7_REGS_POWER + 0x80,
> + sizeof(struct tnetd7200_clocks));
>
casting and NULL checks?
> +int __init ar7_init_clocks(void)
> +{
> + switch (ar7_chip_id()) {
> + case AR7_CHIP_7100:
> + tnetd7200_init_clocks();
> + break;
> + case AR7_CHIP_7200:
> + tnetd7200_init_clocks();
> + break;
>
Change this to the following maybe?
----
switch (ar7_chip_id()) {
case AR7_CHIP_7100:
case AR7_CHIP_7200:
tnetd7200_init_clocks();
break;
----
> + case AR7_CHIP_7300:
> + ar7_dsp_clock = tnetd7300_dsp_clock();
> + tnetd7300_init_clocks();
> + break;
> + default:
> + break;
> + }
> +
> + return 0;
> +}
> +arch_initcall(ar7_init_clocks);
> diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
>
Too late now but gpiolib is rather nice to look into at some stage.
> diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
> [snipped]
> +#include <linux/version.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/pm.h>
> +#include <linux/time.h>
> +
> +#include <asm/reboot.h>
> +#include <asm/mach-ar7/ar7.h>
> +#include <asm/mach-ar7/prom.h>
> +
> +static void ar7_machine_restart(char *command);
> +static void ar7_machine_halt(void);
> +static void ar7_machine_power_off(void);
> +
>
I don't think these are needed as you have the following in the
'correct' order.
> +static void ar7_machine_restart(char *command)
> +{
> + u32 *softres_reg = ioremap(AR7_REGS_RESET +
> + AR7_RESET_SOFTWARE, 1);
> + writel(1, softres_reg);
> +}
> +
> +static void ar7_machine_halt(void)
> +{
> + while (1)
> + ;
> +}
> +
> +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();
> +}
>
> +const char *get_system_type(void)
> +{
> + u16 chip_id = ar7_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)";
> + default:
> + return "TI AR7 (Unknown)";
> + }
> +}
> +
> +static int __init ar7_init_console(void)
> +{
> + return 0;
> +}
> +console_initcall(ar7_init_console);
> +
Does this need to be called?
> +/*
> + * 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;
> +
> + _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");
> + set_io_port_base(io_base);
> +
>
Casting a pointer to a unsigned long...hmmmm.
> + prom_meminit();
> +
> + printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
> + get_system_type(),
> + ar7_chip_id(), ar7_chip_rev());
> +}
> diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
> new file mode 100644
> index 0000000..a1fba89
> --- /dev/null
> +++ b/arch/mips/ar7/time.c
> @@ -0,0 +1,30 @@
> +/*
> + * Carsten Langgaard, carstenl@mips.com
> + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
> + *
> + * This program is free software; you can distribute it and/or modify it
> + * under the terms of the GNU General Public License (Version 2) as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
> + *
> + * Setting up the clock on the MIPS boards.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/time.h>
> +
> +#include <asm/time.h>
> +#include <asm/mach-ar7/ar7.h>
> +
> +void __init plat_time_init(void)
> +{
> + mips_hpt_frequency = ar7_cpu_freq() / 2;
> +}
> diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
> [snipped]
> +#ifndef __AR7_H__
> +#define __AR7_H__
> +
> +#include <linux/delay.h>
> +#include <asm/addrspace.h>
> +#include <linux/io.h>
> +
> +#define AR7_SDRAM_BASE 0x14000000
> +
> +#define AR7_REGS_BASE 0x08610000
> +
> +#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
> +#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
> +/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
> +#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
> +#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
> +#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
> +#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
> +#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
> +#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
> +#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
> +#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
> +#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
> +#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
> +
> +#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
> +#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
> +#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
> +
>
I guess it's style, but I have preferred '(<blah> | <offset>)'. You
might want to add a few more for unlabelled offsets such as
"AR7_REGS_POWER + 0x80" to make things more self documenting?
> [snipped]
> +extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
> +
> +static inline u16 ar7_chip_id(void)
> +{
> + return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
> +}
> +
> +static inline u8 ar7_chip_rev(void)
> +{
> + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
> +}
>
unneeded casting?
> [snipped]
> +
> +static inline int ar7_has_high_cpmac(void)
> +{
> + u16 chip_id = ar7_chip_id();
> + switch (chip_id) {
> + case AR7_CHIP_7100:
> + case AR7_CHIP_7200:
> + return 0;
> + default:
> + return 1;
> + }
> +}
I would probably recommend as a default to return ENXIO or EINVAL maybe?
Then for AR7_CHIP_7300 you return 1, I'm guessing?
I have been slightly tracking the ar7 code for a while and I have to say
it is really looking much nicer now-a-days. Well done! If you ever are
in London, I'll buy you a beer.
Cheers
--
Alexander Clouter
.sigmonster says: Happiness is the greatest good.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 10:22 ` Ralf Baechle
@ 2009-06-24 12:17 ` Florian Fainelli
0 siblings, 0 replies; 11+ messages in thread
From: Florian Fainelli @ 2009-06-24 12:17 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Linux-MIPS
Le Wednesday 24 June 2009 12:22:42 Ralf Baechle, vous avez écrit :
> On Wed, Jun 24, 2009 at 11:12:57AM +0200, Florian Fainelli wrote:
> > Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
> > > On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
> > >
> > > AR7 time again - the platform pending longest ... Let's see:
> >
> > Thank you very much for your comments Ralf, please find below an updated
> > version which addresses all of your comments. I hope this time we are
> > going to make it ;)
>
> One final request, could you send me a useful defconfig file? for AR7?
Of course, here is the defconfig that I used:
--
From: Florian Fainelli <florian@openwrt.org>
Subject: AR7: add defconfig
This patch adds a default configuration for the Texas Instruments
AR7 System-on-a-Chip.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
--
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
new file mode 100644
index 0000000..dad5b67
--- /dev/null
+++ b/arch/mips/configs/ar7_defconfig
@@ -0,0 +1,1182 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Wed Jun 24 14:08:59 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+CONFIG_AR7=y
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_KEXEC=y
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_PROBE_INITRD_HEADER=y
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+CONFIG_TCP_CONG_WESTWOOD=y
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+CONFIG_DEFAULT_WESTWOOD=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="westwood"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_REDIRECT is not set
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_ATM is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+# CONFIG_AX25 is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+CONFIG_CPMAC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AR7_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_SERIAL=y
+CONFIG_SSB_DRIVER_MIPS=y
+CONFIG_SSB_EMBEDDED=y
+CONFIG_SSB_DRIVER_EXTIF=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+CONFIG_VLYNQ=y
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 11:28 ` Alexander Clouter
@ 2009-06-24 12:23 ` Ralf Baechle
2009-06-24 20:18 ` Florian Fainelli
2009-06-24 17:32 ` Florian Fainelli
1 sibling, 1 reply; 11+ messages in thread
From: Ralf Baechle @ 2009-06-24 12:23 UTC (permalink / raw)
To: Alexander Clouter; +Cc: linux-mips
On Wed, Jun 24, 2009 at 12:28:56PM +0100, Alexander Clouter wrote:
> Florian Fainelli <florian@openwrt.org> wrote:
> > Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
> >> On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
> >>
> >> AR7 time again - the platform pending longest ... Let's see:
> >
> > Thank you very much for your comments Ralf, please find below an updated
> > version which addresses all of your comments. I hope this time we are going
> > to make it ;)
> >
> I am hoping someone can have a tackle of the lzma/bzip2 kernel/initramfs
> generic compression code myself, but I guess one thing at a time. :) If
> you have a simple way for me to produce a LZMA'd image, I'll test it
> this on my WAG54Gv2 (I need the image to be less than 700kB).
>
> My comments, for what they are worth, below:
>
> > From: Florian Fainelli <florian@openwrt.org>
> > Subject: Add support for Texas Instruments AR7 System-on-a-Chip
> >
> > This patch adds support for the Texas Instruments AR7 System-on-a-Chip.
> > It supports the TNETD7100, 7200 and 7300 versions of the SoC.
> >
> > Changes from v4:
> > [snipped]
> >
> > Signed-off-by: Matteo Croce <matteo@openwrt.org>
> > Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> > Signed-off-by: Eugene Konev <ejka@openwrt.org>
> > Signed-off-by: Nicolas Thill <nico@openwrt.org>
> > Signed-off-by: Florian Fainelli <florian@openwrt.org>
> > --
> > [snipped]
> >
> > diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
> > new file mode 100644
> > index 0000000..7ce5f07
> > --- /dev/null
> > +++ b/arch/mips/ar7/clock.c
> > @@ -0,0 +1,450 @@
> > [snipped]
> > +static void __init tnetd7300_init_clocks(void)
> > +{
> > + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> > + struct tnetd7300_clocks *clocks =
> > + (struct tnetd7300_clocks *)
> > + ioremap_nocache(AR7_REGS_POWER + 0x20,
> > + sizeof(struct tnetd7300_clocks));
> > +
> >
> Needless cast'ing and also should you not check that NULL is not
> returned for both of these ioremap's?
That's because we "know" it can't ever fail for addresses < 0x20000000.
Downside - sparse will bitch about it.
But yes, the cast indeed is unnecessary.
Ralf
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 11:28 ` Alexander Clouter
2009-06-24 12:23 ` Ralf Baechle
@ 2009-06-24 17:32 ` Florian Fainelli
2009-06-24 21:16 ` Alexander Clouter
1 sibling, 1 reply; 11+ messages in thread
From: Florian Fainelli @ 2009-06-24 17:32 UTC (permalink / raw)
To: Alexander Clouter; +Cc: linux-mips
Hi
Le Wednesday 24 June 2009 13:28:56 Alexander Clouter, vous avez écrit :
> Hi,
>
> Florian Fainelli <florian@openwrt.org> wrote:
> > Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
> >> On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
> >>
> >> AR7 time again - the platform pending longest ... Let's see:
> >
> > Thank you very much for your comments Ralf, please find below an updated
> > version which addresses all of your comments. I hope this time we are
> > going to make it ;)
>
> I am hoping someone can have a tackle of the lzma/bzip2 kernel/initramfs
> generic compression code myself, but I guess one thing at a time. :) If
> you have a simple way for me to produce a LZMA'd image, I'll test it
> this on my WAG54Gv2 (I need the image to be less than 700kB).
>
> My comments, for what they are worth, below:
> > From: Florian Fainelli <florian@openwrt.org>
> > Subject: Add support for Texas Instruments AR7 System-on-a-Chip
> >
> > This patch adds support for the Texas Instruments AR7 System-on-a-Chip.
> > It supports the TNETD7100, 7200 and 7300 versions of the SoC.
> >
> > Changes from v4:
> > [snipped]
> >
> > Signed-off-by: Matteo Croce <matteo@openwrt.org>
> > Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> > Signed-off-by: Eugene Konev <ejka@openwrt.org>
> > Signed-off-by: Nicolas Thill <nico@openwrt.org>
> > Signed-off-by: Florian Fainelli <florian@openwrt.org>
> > --
> > [snipped]
> >
> > diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
> > new file mode 100644
> > index 0000000..7ce5f07
> > --- /dev/null
> > +++ b/arch/mips/ar7/clock.c
> > @@ -0,0 +1,450 @@
> > [snipped]
> > +static void __init tnetd7300_init_clocks(void)
> > +{
> > + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> > + struct tnetd7300_clocks *clocks =
> > + (struct tnetd7300_clocks *)
> > + ioremap_nocache(AR7_REGS_POWER +
> > 0x20, + sizeof(struct
> > tnetd7300_clocks)); +
>
> Needless cast'ing and also should you not check that NULL is not
> returned for both of these ioremap's?
As Ralf explained, ioremap will not fail here.
>
> > + ar7_bus_clock = 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,
> > + &clocks->cpu, bootcr, AR7_AFE_CLOCK);
> > + else
> > + ar7_cpu_clock = ar7_bus_clock;
> > +/*
> > + tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
> > + bootcr, 48000000);
> > +*/
>
> Dead code? Feels that way with what then follows.
Not really, but not used yet since we have not ported the USB HCI driver yet.
>
> > + if (ar7_dsp_clock == 250000000)
> > + tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
> > + bootcr, ar7_dsp_clock);
> > +
> > + iounmap(clocks);
> > + iounmap(bootcr);
> > +}
> >
> > [snipped]
> >
> > +static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
> > + int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
> > +{
> > + printk(KERN_INFO
> > + "Clocks: base = %d, frequency = %u, prediv = %d, "
> > + "postdiv = %d, postdiv2 = %d, mul = %d\n",
> > + base, frequency, prediv, postdiv, postdiv2, mul);
> > +
> > + writel(0, &clock->ctrl);
> > + writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F),
> > &clock->prediv); + writel((mul - 1) & 0xF, &clock->mul);
> > +
> > + for (mul = 0; mul < 2000; mul++)
> > + ; /* nop */
> > +
>
> Only for furthering my know how, this because the timing is changing so
> you cannot msleep() or whatever? Can we not jump straight into the
> while() instead and wait it out? Alternatively start with a:
> ----
> while (!readl(&clock->status) & 0x1)
> ;
> ----
>
> and then lead into the following?
Yes, we can keep busy waiting on the status register, this works too.
>
> > + while (readl(&clock->status) & 0x1)
> > + ; /* nop */
> > +
> > + writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F),
> > &clock->postdiv); +
> > + writel(readl(&clock->cmden) | 1, &clock->cmden);
> > + writel(readl(&clock->cmd) | 1, &clock->cmd);
> > +
> > + while (readl(&clock->status) & 0x1)
> > + ; /* nop */
> > +
> > + writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F),
> > &clock->postdiv2); +
> > + writel(readl(&clock->cmden) | 1, &clock->cmden);
> > + writel(readl(&clock->cmd) | 1, &clock->cmd);
> > +
> > + while (readl(&clock->status) & 0x1)
> > + ; /* nop */
> > +
> > + writel(readl(&clock->ctrl) | 1, &clock->ctrl);
> > +}
> >
> > [snipped]
> >
> > +static void __init tnetd7200_init_clocks(void)
> > +{
> > + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> > + struct tnetd7200_clocks *clocks =
> > + (struct tnetd7200_clocks *)
> > + ioremap_nocache(AR7_REGS_POWER +
> > 0x80, + sizeof(struct
> > tnetd7200_clocks));
>
> casting and NULL checks?
>
> > +int __init ar7_init_clocks(void)
> > +{
> > + switch (ar7_chip_id()) {
> > + case AR7_CHIP_7100:
> > + tnetd7200_init_clocks();
> > + break;
> > + case AR7_CHIP_7200:
> > + tnetd7200_init_clocks();
> > + break;
>
> Change this to the following maybe?
> ----
> switch (ar7_chip_id()) {
> case AR7_CHIP_7100:
> case AR7_CHIP_7200:
> tnetd7200_init_clocks();
> break;
> ----
>
> > + case AR7_CHIP_7300:
> > + ar7_dsp_clock = tnetd7300_dsp_clock();
> > + tnetd7300_init_clocks();
> > + break;
> > + default:
> > + break;
> > + }
> > +
> > + return 0;
> > +}
> > +arch_initcall(ar7_init_clocks);
> >
> > diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
>
> Too late now but gpiolib is rather nice to look into at some stage.
Yes, I will submit that later when AR7 is already included.
>
> > diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
> > [snipped]
> > +#include <linux/version.h>
> > +#include <linux/init.h>
> > +#include <linux/ioport.h>
> > +#include <linux/pm.h>
> > +#include <linux/time.h>
> > +
> > +#include <asm/reboot.h>
> > +#include <asm/mach-ar7/ar7.h>
> > +#include <asm/mach-ar7/prom.h>
> > +
> > +static void ar7_machine_restart(char *command);
> > +static void ar7_machine_halt(void);
> > +static void ar7_machine_power_off(void);
> > +
>
> I don't think these are needed as you have the following in the
> 'correct' order.
Indeed.
>
> > +static void ar7_machine_restart(char *command)
> > +{
> > + u32 *softres_reg = ioremap(AR7_REGS_RESET +
> > + AR7_RESET_SOFTWARE, 1);
> > + writel(1, softres_reg);
> > +}
> > +
> > +static void ar7_machine_halt(void)
> > +{
> > + while (1)
> > + ;
> > +}
> > +
> > +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();
> > +}
> >
> > +const char *get_system_type(void)
> > +{
> > + u16 chip_id = ar7_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)";
> > + default:
> > + return "TI AR7 (Unknown)";
> > + }
> > +}
> > +
> > +static int __init ar7_init_console(void)
> > +{
> > + return 0;
> > +}
> > +console_initcall(ar7_init_console);
> > +
>
> Does this need to be called?
>
> > +/*
> > + * 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;
> > +
> > + _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");
> > + set_io_port_base(io_base);
> > +
>
> Casting a pointer to a unsigned long...hmmmm.
>
> > + prom_meminit();
> > +
> > + printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
> > + get_system_type(),
> > + ar7_chip_id(), ar7_chip_rev());
> > +}
> > diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
> > new file mode 100644
> > index 0000000..a1fba89
> > --- /dev/null
> > +++ b/arch/mips/ar7/time.c
> > @@ -0,0 +1,30 @@
> > +/*
> > + * Carsten Langgaard, carstenl@mips.com
> > + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
> > + *
> > + * This program is free software; you can distribute it and/or modify
> > it + * under the terms of the GNU General Public License (Version 2) as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but
> > WITHOUT + * ANY WARRANTY; without even the implied warranty of
> > MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> > General Public License + * for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > along + * with this program; if not, write to the Free Software
> > Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307,
> > USA.
> > + *
> > + * Setting up the clock on the MIPS boards.
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/time.h>
> > +
> > +#include <asm/time.h>
> > +#include <asm/mach-ar7/ar7.h>
> > +
> > +void __init plat_time_init(void)
> > +{
> > + mips_hpt_frequency = ar7_cpu_freq() / 2;
> > +}
> >
> > diff --git a/arch/mips/include/asm/mach-ar7/ar7.h
> > b/arch/mips/include/asm/mach-ar7/ar7.h [snipped]
> > +#ifndef __AR7_H__
> > +#define __AR7_H__
> > +
> > +#include <linux/delay.h>
> > +#include <asm/addrspace.h>
> > +#include <linux/io.h>
> > +
> > +#define AR7_SDRAM_BASE 0x14000000
> > +
> > +#define AR7_REGS_BASE 0x08610000
> > +
> > +#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000)
> > +#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
> > +/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
> > +#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
> > +#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
> > +#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
> > +#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
> > +#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800)
> > +#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00)
> > +#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00)
> > +#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00)
> > +#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400)
> > +#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800)
> > +
> > +#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00)
> > +#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
> > +#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
> > +
>
> I guess it's style, but I have preferred '(<blah> | <offset>)'. You
> might want to add a few more for unlabelled offsets such as
> "AR7_REGS_POWER + 0x80" to make things more self documenting?
Right, added too.
>
> > [snipped]
> > +extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
> > +
> > +static inline u16 ar7_chip_id(void)
> > +{
> > + return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
> > +}
> > +
> > +static inline u8 ar7_chip_rev(void)
> > +{
> > + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) &
> > 0xff; +}
>
> unneeded casting?
>
> > [snipped]
> > +
> > +static inline int ar7_has_high_cpmac(void)
> > +{
> > + u16 chip_id = ar7_chip_id();
> > + switch (chip_id) {
> > + case AR7_CHIP_7100:
> > + case AR7_CHIP_7200:
> > + return 0;
> > + default:
> > + return 1;
> > + }
> > +}
>
> I would probably recommend as a default to return ENXIO or EINVAL maybe?
> Then for AR7_CHIP_7300 you return 1, I'm guessing?
Yes, thanks.
>
> I have been slightly tracking the ar7 code for a while and I have to say
> it is really looking much nicer now-a-days. Well done! If you ever are
> in London, I'll buy you a beer.
I am in Paris at the moment, but you can also come here ;)
--
Best regards, Florian Fainelli
Email : florian@openwrt.org
http://openwrt.org
-------------------------------
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 12:23 ` Ralf Baechle
@ 2009-06-24 20:18 ` Florian Fainelli
0 siblings, 0 replies; 11+ messages in thread
From: Florian Fainelli @ 2009-06-24 20:18 UTC (permalink / raw)
To: Ralf Baechle; +Cc: Alexander Clouter, linux-mips
Le Wednesday 24 June 2009 14:23:47 Ralf Baechle, vous avez écrit :
> On Wed, Jun 24, 2009 at 12:28:56PM +0100, Alexander Clouter wrote:
> > Florian Fainelli <florian@openwrt.org> wrote:
> > > Le Tuesday 23 June 2009 20:15:09 Ralf Baechle, vous avez écrit :
> > >> On Tue, Jun 23, 2009 at 11:28:27AM +0200, Florian Fainelli wrote:
> > >>
> > >> AR7 time again - the platform pending longest ... Let's see:
> > >
> > > Thank you very much for your comments Ralf, please find below an
> > > updated version which addresses all of your comments. I hope this time
> > > we are going to make it ;)
> >
> > I am hoping someone can have a tackle of the lzma/bzip2 kernel/initramfs
> > generic compression code myself, but I guess one thing at a time. :) If
> > you have a simple way for me to produce a LZMA'd image, I'll test it
> > this on my WAG54Gv2 (I need the image to be less than 700kB).
> >
> > My comments, for what they are worth, below:
> > > From: Florian Fainelli <florian@openwrt.org>
> > > Subject: Add support for Texas Instruments AR7 System-on-a-Chip
> > >
> > > This patch adds support for the Texas Instruments AR7 System-on-a-Chip.
> > > It supports the TNETD7100, 7200 and 7300 versions of the SoC.
> > >
> > > Changes from v4:
> > > [snipped]
> > >
> > > Signed-off-by: Matteo Croce <matteo@openwrt.org>
> > > Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> > > Signed-off-by: Eugene Konev <ejka@openwrt.org>
> > > Signed-off-by: Nicolas Thill <nico@openwrt.org>
> > > Signed-off-by: Florian Fainelli <florian@openwrt.org>
> > > --
> > > [snipped]
> > >
> > > diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
> > > new file mode 100644
> > > index 0000000..7ce5f07
> > > --- /dev/null
> > > +++ b/arch/mips/ar7/clock.c
> > > @@ -0,0 +1,450 @@
> > > [snipped]
> > > +static void __init tnetd7300_init_clocks(void)
> > > +{
> > > + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
> > > + struct tnetd7300_clocks *clocks =
> > > + (struct tnetd7300_clocks *)
> > > + ioremap_nocache(AR7_REGS_POWER
> > > + 0x20, + sizeof(struct
> > > tnetd7300_clocks)); +
> >
> > Needless cast'ing and also should you not check that NULL is not
> > returned for both of these ioremap's?
>
> That's because we "know" it can't ever fail for addresses < 0x20000000.
> Downside - sparse will bitch about it.
>
> But yes, the cast indeed is unnecessary.
Incremental patch on top of the one you already have below.
--
From: Florian Fainelli <florian@openwrt.org>
Subject: clean up AR7 code
This patch cleans up the code and is incremental to version 5
of patch previously sent which adds AR7 support.
- uneeded casts on ioremaps in clock.c
- define AR7_REGS_CLOCKS/UR8_REGS_CLOCKS for consistency
- remove useless nops and use busy-waiting on the pll status register
- remove commented out usb clock setting for TNETD7300
- simplify ar7_init_clocks
- return -ENXIO for unknown chips in ar7_has_high_cpmac
- remove forward declarations of functions in setup.c
Signed-off-by: Florian Fainelli <florian@openwrt.org>
--
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
index 7ce5f07..b8c7c84 100644
--- a/arch/mips/ar7/clock.c
+++ b/arch/mips/ar7/clock.c
@@ -244,8 +244,7 @@ static void __init tnetd7300_init_clocks(void)
{
u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
struct tnetd7300_clocks *clocks =
- (struct tnetd7300_clocks *)
- ioremap_nocache(AR7_REGS_POWER + 0x20,
+ ioremap_nocache(UR8_REGS_CLOCKS,
sizeof(struct tnetd7300_clocks));
ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
@@ -256,10 +255,7 @@ static void __init tnetd7300_init_clocks(void)
&clocks->cpu, bootcr, AR7_AFE_CLOCK);
else
ar7_cpu_clock = ar7_bus_clock;
-/*
- tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
- bootcr, 48000000);
-*/
+
if (ar7_dsp_clock == 250000000)
tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
bootcr, ar7_dsp_clock);
@@ -293,9 +289,6 @@ static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
writel((mul - 1) & 0xF, &clock->mul);
- for (mul = 0; mul < 2000; mul++)
- ; /* nop */
-
while (readl(&clock->status) & 0x1)
; /* nop */
@@ -348,8 +341,7 @@ static void __init tnetd7200_init_clocks(void)
{
u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
struct tnetd7200_clocks *clocks =
- (struct tnetd7200_clocks *)
- ioremap_nocache(AR7_REGS_POWER + 0x80,
+ ioremap_nocache(AR7_REGS_CLOCKS,
sizeof(struct tnetd7200_clocks));
int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
@@ -432,8 +424,6 @@ int __init ar7_init_clocks(void)
{
switch (ar7_chip_id()) {
case AR7_CHIP_7100:
- tnetd7200_init_clocks();
- break;
case AR7_CHIP_7200:
tnetd7200_init_clocks();
break;
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
index cccb484..6ebb5f1 100644
--- a/arch/mips/ar7/setup.c
+++ b/arch/mips/ar7/setup.c
@@ -25,10 +25,6 @@
#include <asm/mach-ar7/ar7.h>
#include <asm/mach-ar7/prom.h>
-static void ar7_machine_restart(char *command);
-static void ar7_machine_halt(void);
-static void ar7_machine_power_off(void);
-
static void ar7_machine_restart(char *command)
{
u32 *softres_reg = ioremap(AR7_REGS_RESET +
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
index 4ebe2c6..de71694 100644
--- a/arch/mips/include/asm/mach-ar7/ar7.h
+++ b/arch/mips/include/asm/mach-ar7/ar7.h
@@ -21,8 +21,10 @@
#define __AR7_H__
#include <linux/delay.h>
-#include <asm/addrspace.h>
#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <asm/addrspace.h>
#define AR7_SDRAM_BASE 0x14000000
@@ -32,6 +34,8 @@
#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900)
/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80)
+#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20)
#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200)
#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
@@ -126,8 +130,10 @@ static inline int ar7_has_high_cpmac(void)
case AR7_CHIP_7100:
case AR7_CHIP_7200:
return 0;
- default:
+ case AR7_CHIP_7300:
return 1;
+ default:
+ return -ENXIO;
}
}
#define ar7_has_high_vlynq ar7_has_high_cpmac
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 5/8] add Texas Instruments AR7 support
2009-06-24 17:32 ` Florian Fainelli
@ 2009-06-24 21:16 ` Alexander Clouter
0 siblings, 0 replies; 11+ messages in thread
From: Alexander Clouter @ 2009-06-24 21:16 UTC (permalink / raw)
To: linux-mips
Hi,
Florian Fainelli <florian@openwrt.org> wrote:
>
> Le Wednesday 24 June 2009 13:28:56 Alexander Clouter, vous avez écrit :
>>
>> Florian Fainelli <florian@openwrt.org> wrote:
>>
>> > +/*
>> > + * 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;
>> > +
>> > + _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");
>> > + set_io_port_base(io_base);
>> > +
>>
>> Casting a pointer to a unsigned long...hmmmm.
>>
arch/mips/sgi-ip32/crime.c:crime_init() has the much nicer feeling:
set_io_port_base((unsigned long) ioremap(AR7_REGS_BASE, 0x100000));
At least this approach hides the pointer to int cast'ing.
>> I have been slightly tracking the ar7 code for a while and I have to say
>> it is really looking much nicer now-a-days. Well done! If you ever are
>> in London, I'll buy you a beer.
>
> I am in Paris at the moment, but you can also come here ;)
>
Noted :)
Cheers
--
Alexander Clouter
.sigmonster says: I'm not proud.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2009-06-24 22:12 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-04 14:19 [PATCH 5/8] add Texas Instruments AR7 support Florian Fainelli
[not found] ` <200906161428.33571.florian@openwrt.org>
2009-06-23 9:28 ` Florian Fainelli
2009-06-23 18:15 ` Ralf Baechle
2009-06-24 9:12 ` Florian Fainelli
2009-06-24 10:22 ` Ralf Baechle
2009-06-24 12:17 ` Florian Fainelli
2009-06-24 11:28 ` Alexander Clouter
2009-06-24 12:23 ` Ralf Baechle
2009-06-24 20:18 ` Florian Fainelli
2009-06-24 17:32 ` Florian Fainelli
2009-06-24 21:16 ` Alexander Clouter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).