* [PATCH][MIPS][0/6] AR7: AR7 strikes back
@ 2007-10-11 0:48 Matteo Croce
2007-10-11 0:50 ` [PATCH][MIPS][1/6] AR7: core support Matteo Croce
` (6 more replies)
0 siblings, 7 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 0:48 UTC (permalink / raw)
To: linux-mips; +Cc: nico, nbd, florian, openwrt-devel, Andrew Morton
Here are the new patches made against latest 2.6.23 git tree
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH][MIPS][1/6] AR7: core support
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
@ 2007-10-11 0:50 ` Matteo Croce
2007-10-11 0:54 ` [PATCH][MIPS][2/6] AR7: VLYNQ bus Matteo Croce
` (5 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 0:50 UTC (permalink / raw)
To: linux-mips
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Florian Fainelli <florian@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>
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f943736..a207a8b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -16,6 +16,22 @@ choice
prompt "System type"
default SGI_IP22
+config AR7
+ bool "Texas Instruments AR7"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ 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 SYS_SUPPORTS_BIG_ENDIAN
+ select GENERIC_GPIO
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+
config MACH_ALCHEMY
bool "Alchemy processor based machines"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index ebd5d02..905d06a 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -157,6 +157,13 @@ libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/
#
#
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7) += arch/mips/ar7/
+cflags-$(CONFIG_AR7) += -Iinclude/asm-mips/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..ecbcbf0
--- /dev/null
+++ b/arch/mips/ar7/clock.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau, Eugene Konev
+ *
+ * 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 <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/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 {
+ volatile u32 ctrl;
+#define PREDIV_MASK 0x001f0000
+#define PREDIV_SHIFT 16
+#define POSTDIV_MASK 0x0000001f
+ u32 unused1[3];
+ volatile 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];
+} __packed;
+
+struct tnetd7300_clocks {
+ struct tnetd7300_clock bus;
+ struct tnetd7300_clock cpu;
+ struct tnetd7300_clock usb;
+ struct tnetd7300_clock dsp;
+} __packed;
+
+struct tnetd7200_clock {
+ volatile u32 ctrl;
+ u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+ volatile u32 mul;
+ volatile u32 prediv;
+ volatile u32 postdiv;
+ volatile u32 postdiv2;
+ u32 unused2[6];
+ volatile u32 cmd;
+ volatile u32 status;
+ volatile u32 cmden;
+ u32 padding[15];
+} __packed;
+
+struct tnetd7200_clocks {
+ struct tnetd7200_clock cpu;
+ struct tnetd7200_clock dsp;
+ struct tnetd7200_clock usb;
+} __packed;
+
+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 int gcd(int a, int b)
+{
+ int c;
+
+ if (a < b) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ while ((c = (a % b))) {
+ a = b;
+ b = c;
+ }
+ return b;
+}
+
+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 = clock->ctrl;
+ u32 pll = 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)
+{
+ u32 status;
+ 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);
+
+ clock->ctrl = ((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1);
+ mdelay(1);
+ clock->pll = 4;
+ do
+ status = clock->pll;
+ while (status & PLL_STATUS);
+ clock->pll = ((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e;
+ 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 = ((clock->prediv & 0x1f) + 1) *
+ ((clock->postdiv & 0x1f) + 1);
+
+ if (*bootcr & BOOT_PLL_BYPASS)
+ return base / divisor;
+
+ return base * ((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);
+
+ clock->ctrl = 0;
+ clock->prediv = DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F);
+ clock->mul = ((mul - 1) & 0xF);
+
+ for (mul = 0; mul < 2000; mul++) /* nop */;
+
+ while (clock->status & 0x1) /* nop */;
+
+ clock->postdiv = DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F);
+
+ clock->cmden |= 1;
+ clock->cmd |= 1;
+
+ while (clock->status & 0x1) /* nop */;
+
+ clock->postdiv2 = DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F);
+
+ clock->cmden |= 1;
+ clock->cmd |= 1;
+
+ while (clock->status & 0x1) /* nop */;
+
+ clock->ctrl |= 1;
+}
+
+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;
+
+/*
+ Log from Fritz!Box 7170 Annex B:
+
+ CPU revision is: 00018448
+ Clocks: Async mode
+ Clocks: Setting DSP clock
+ Clocks: prediv: 1, postdiv: 1, mul: 5
+ Clocks: base = 25000000, frequency = 125000000, prediv = 1,
+ postdiv = 2, postdiv2 = 1, mul = 10
+ Clocks: Setting CPU clock
+ Adjusted requested frequency 211000000 to 211968000
+ Clocks: prediv: 1, postdiv: 1, mul: 6
+ Clocks: base = 35328000, frequency = 211968000, prediv = 1,
+ postdiv = 1, postdiv2 = -1, mul = 6
+ Clocks: Setting USB clock
+ Adjusted requested frequency 48000000 to 48076920
+ Clocks: prediv: 13, postdiv: 1, mul: 5
+ Clocks: base = 125000000, frequency = 48000000, prediv = 13,
+ postdiv = 1, postdiv2 = -1, mul = 5
+
+ DSL didn't work if you didn't set the postdiv 2:1 postdiv2 combination,
+ driver hung on startup.
+ Haven't tested this on a synchronous board,
+ neither do i know what to do with ar7_dsp_clock
+*/
+
+ 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_CPU_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);
+
+ #warning FIXME
+ ar7_dsp_clock = ar7_cpu_clock;
+
+ iounmap(clocks);
+ iounmap(bootcr);
+}
+
+void __init ar7_init_clocks(void)
+{
+ switch (ar7_chip_id()) {
+ case AR7_CHIP_7100:
+#warning FIXME: Check if the new 7200 clock init works for 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..7ca7dc9
--- /dev/null
+++ b/arch/mips/ar7/gpio.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau, Eugene Konev
+ *
+ * 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/ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX] = { 0, };
+
+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..e9e0b15
--- /dev/null
+++ b/arch/mips/ar7/irq.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2006, 2007 Felix Fietkau, Eugene Konev
+ *
+ * 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/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..65a094c
--- /dev/null
+++ b/arch/mips/ar7/memory.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 OpenWrt.org
+ *
+ * Based on arch/mips/mm/init.c
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * 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);
+ volatile u32 *addr = (u32 *)KSEG1ADDR(0x14000000 + size - 4);
+ u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+
+ while (addr > kernel_end) {
+ *addr = (u32)addr;
+ size >>= 1;
+ addr -= size >> 2;
+ }
+
+ do {
+ addr += size >> 2;
+ if (*addr != (u32)addr)
+ break;
+ size <<= 1;
+ } while (size < (64 << 20));
+
+ 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..5b345a5
--- /dev/null
+++ b/arch/mips/ar7/platform.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2006, 2007 Felix Fietkau, Eugene Konev
+ *
+ * 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/autoconf.h>
+#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>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+#include <linux/leds.h>
+#endif
+
+#include <asm/addrspace.h>
+#include <asm/ar7/ar7.h>
+#include <asm/ar7/gpio.h>
+#include <asm/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;
+
+ if ((result = gpio_request(pdata->gpio_bit, "vlynq")))
+ goto out;
+
+ ar7_device_reset(pdata->reset_bit);
+
+ if ((result = ar7_gpio_disable(pdata->gpio_bit)))
+ goto out_enabled;
+
+ if ((result = ar7_gpio_enable(pdata->gpio_bit)))
+ goto out_enabled;
+
+ if ((result = gpio_direction_output(pdata->gpio_bit, 0)))
+ 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),
+};
+
+
+/* This is proper way to define uart ports, but they are then detected
+ * as xscale and, obviously, don't work...
+ */
+#if !defined(CONFIG_SERIAL_8250)
+
+static struct plat_serial8250_port uart0_data = {
+ .mapbase = AR7_REGS_UART0,
+ .irq = AR7_IRQ_UART0,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+};
+
+static struct plat_serial8250_port uart1_data = {
+ .mapbase = UR8_REGS_UART1,
+ .irq = AR7_IRQ_UART1,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+};
+
+static struct plat_serial8250_port uart_data[] = {
+ uart0_data,
+ uart1_data,
+ { .flags = 0 }
+};
+
+static struct plat_serial8250_port uart_data_single[] = {
+ uart0_data,
+ { .flags = 0 }
+};
+
+static struct platform_device uart = {
+ .id = 0,
+ .name = "serial8250",
+ .dev.platform_data = uart_data_single
+};
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+static struct gpio_led default_leds[] = {
+ { .name = "status", .gpio = 8, .active_low = 1, },
+};
+
+static struct gpio_led fb_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,
+ }
+};
+#endif
+
+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[] = "00:00:00:12:34:56", *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)
+ mac = default_mac;
+ for (i = 0; i < 6; i++)
+ dev_addr[i] = (char2hex(mac[i * 3]) << 4) +
+ char2hex(mac[i * 3 + 1]);
+}
+
+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;
+ }
+
+#else /* !CONFIG_SERIAL_8250 */
+
+ uart_data[0].uartclk = ar7_bus_freq() / 2;
+ uart_data[1].uartclk = uart_data[0].uartclk;
+
+ /* Only TNETD73xx have a second serial port */
+ if (ar7_has_second_uart())
+ uart.dev.platform_data = uart_data;
+
+ res = platform_device_register(&uart);
+ if (res)
+ return res;
+
+#endif /* CONFIG_SERIAL_8250 */
+
+ res = platform_device_register(&physmap_flash);
+ if (res)
+ return res;
+
+ res = platform_device_register(&vlynq_low);
+ if (res)
+ return res;
+
+ ar7_device_disable(vlynq_low_data.reset_bit);
+ 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;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+#warning FIXME: add model detection
+ ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+ ar7_led_data.leds = default_leds;
+ res = platform_device_register(&ar7_gpio_leds);
+#endif
+ 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..65fe0c0
--- /dev/null
+++ b/arch/mips/ar7/prom.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2006, 2007 OpenWrt.org
+ *
+ * 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/gdb-stub.h>
+
+#include <asm/ar7/ar7.h>
+#include <asm/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(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
+
+ if ((s = prom_getenv("modetty0"))) {
+ 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(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..793f37c
--- /dev/null
+++ b/arch/mips/ar7/setup.c
@@ -0,0 +1,106 @@
+/*
+ * 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/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+
+#include <asm/mips-boards/prom.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/ar7/ar7.h>
+
+extern void ar7_time_init(void);
+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;
+ board_time_init = ar7_time_init;
+ 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..4be2895
--- /dev/null
+++ b/arch/mips/ar7/time.c
@@ -0,0 +1,32 @@
+/*
+ * 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 <asm/time.h>
+#include <asm/ar7/ar7.h>
+
+void __init ar7_time_init(void)
+{
+ mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+ setup_irq(7, irq);
+}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 632bce1..3795c06 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1076,9 +1076,22 @@ void *set_except_vector(int n, void *addr)
exception_handlers[n] = handler;
if (n == 0 && cpu_has_divec) {
- *(u32 *)(ebase + 0x200) = 0x08000000 |
- (0x03ffffff & (handler >> 2));
- flush_icache_range(ebase + 0x200, ebase + 0x204);
+ if ((handler ^ (ebase + 4)) & 0xfc000000) {
+ /* lui k0, 0x0000 */
+ *(u32 *)(ebase + 0x200) = 0x3c1a0000 | (handler >> 16);
+ /* ori k0, 0x0000 */
+ *(u32 *)(ebase + 0x204) =
+ 0x375a0000 | (handler & 0xffff);
+ /* jr k0 */
+ *(u32 *)(ebase + 0x208) = 0x03400008;
+ /* nop */
+ *(u32 *)(ebase + 0x20C) = 0x00000000;
+ flush_icache_range(ebase + 0x200, ebase + 0x210);
+ } else {
+ *(volatile u32 *)(ebase + 0x200) =
+ 0x08000000 | (0x03ffffff & (handler >> 2));
+ flush_icache_range(ebase + 0x200, ebase + 0x204);
+ }
}
return (void *)old_handler;
}
diff --git a/include/asm-mips/ar7/ar7.h b/include/asm-mips/ar7/ar7.h
new file mode 100644
index 0000000..4f90eb1
--- /dev/null
+++ b/include/asm-mips/ar7/ar7.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2006, 2007 Felix Fietkau, Eugene Konev
+ *
+ * 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/include/asm-mips/ar7/gpio.h b/include/asm-mips/ar7/gpio.h
new file mode 100644
index 0000000..4fe9496
--- /dev/null
+++ b/include/asm-mips/ar7/gpio.h
@@ -0,0 +1,121 @@
+/*
+ * 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/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);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ return ((readl(gpio_in) & (1 << gpio)) != 0);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ void __iomem *gpio_out =
+ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+ volatile unsigned tmp;
+
+ if (gpio >= AR7_GPIO_MAX)
+ return;
+
+ 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);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ 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);
+
+ if (gpio >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+ return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/include/asm-mips/ar7/irq.h b/include/asm-mips/ar7/irq.h
new file mode 100644
index 0000000..39e9757
--- /dev/null
+++ b/include/asm-mips/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/include/asm-mips/ar7/prom.h b/include/asm-mips/ar7/prom.h
new file mode 100644
index 0000000..62d7d5c
--- /dev/null
+++ b/include/asm-mips/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(char *name);
+extern void prom_printf(char *fmt, ...);
+
+#endif /* __PROM_H__ */
diff --git a/include/asm-mips/ar7/spaces.h b/include/asm-mips/ar7/spaces.h
new file mode 100644
index 0000000..f4d1237
--- /dev/null
+++ b/include/asm-mips/ar7/spaces.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+
+#define CAC_BASE 0x80000000
+#define IO_BASE 0xa0000000
+#define UNCAC_BASE 0xa0000000
+#define MAP_BASE 0xc0000000
+
+/*
+ * 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
+
+/*
+ * Memory above this physical address will be considered highmem.
+ */
+#ifndef HIGHMEM_START
+#define HIGHMEM_START 0x40000000UL
+#endif
+
+#endif /* __ASM_AR7_SPACES_H */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index d2ea983..8fda483 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -184,8 +184,10 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
-#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
+#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \
+ PHYS_OFFSET)
+#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \
+ PHYS_OFFSET)
#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH][MIPS][2/6] AR7: VLYNQ bus
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
2007-10-11 0:50 ` [PATCH][MIPS][1/6] AR7: core support Matteo Croce
@ 2007-10-11 0:54 ` Matteo Croce
2007-10-11 0:55 ` [PATCH][MIPS][3/6] AR7: mtd partition map Matteo Croce
` (4 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 0:54 UTC (permalink / raw)
To: linux-mips; +Cc: Eugene Konev, Andrew Morton
Support for the Texas Instrument VLYNQ interconnect bus
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Eugene Konev <ejka@imfi.kspu.ru>
diff --git a/drivers/vlynq/Kconfig b/drivers/vlynq/Kconfig
new file mode 100644
index 0000000..2c8ffe0
--- /dev/null
+++ b/drivers/vlynq/Kconfig
@@ -0,0 +1,13 @@
+menu "TI VLYNQ"
+
+config VLYNQ
+ bool "TI VLYNQ bus support"
+ depends on AR7 && EXPERIMENTAL
+ help
+ Support for the TI VLYNQ bus
+
+ The module will be called vlynq
+
+ If unsure, say N
+
+endmenu
diff --git a/drivers/vlynq/Makefile b/drivers/vlynq/Makefile
new file mode 100644
index 0000000..b3f6114
--- /dev/null
+++ b/drivers/vlynq/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for kernel vlynq drivers
+#
+
+obj-$(CONFIG_VLYNQ) += vlynq.o
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c
new file mode 100644
index 0000000..0dd6c18
--- /dev/null
+++ b/drivers/vlynq/vlynq.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (C) 2006, 2007 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/kernel.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/io.h>
+
+#include <linux/vlynq.h>
+
+#define VLYNQ_CTRL_PM_ENABLE 0x80000000
+#define VLYNQ_CTRL_CLOCK_INT 0x00008000
+#define VLYNQ_CTRL_CLOCK_DIV(x) (((x) & 7) << 16)
+#define VLYNQ_CTRL_INT_LOCAL 0x00004000
+#define VLYNQ_CTRL_INT_ENABLE 0x00002000
+#define VLYNQ_CTRL_INT_VECTOR(x) (((x) & 0x1f) << 8)
+#define VLYNQ_CTRL_INT2CFG 0x00000080
+#define VLYNQ_CTRL_RESET 0x00000001
+
+#define VLYNQ_INT_OFFSET 0x00000014
+#define VLYNQ_REMOTE_OFFSET 0x00000080
+
+#define VLYNQ_STATUS_LINK 0x00000001
+#define VLYNQ_STATUS_LERROR 0x00000080
+#define VLYNQ_STATUS_RERROR 0x00000100
+
+#define VINT_ENABLE 0x00000100
+#define VINT_TYPE_EDGE 0x00000080
+#define VINT_LEVEL_LOW 0x00000040
+#define VINT_VECTOR(x) ((x) & 0x1f)
+#define VINT_OFFSET(irq) (8 * ((irq) % 4))
+
+#define VLYNQ_AUTONEGO_V2 0x00010000
+
+struct vlynq_regs {
+ u32 revision;
+ u32 control;
+ u32 status;
+ u32 int_prio;
+ u32 int_status;
+ u32 int_pending;
+ u32 int_ptr;
+ u32 tx_offset;
+ struct vlynq_mapping rx_mapping[4];
+ u32 chip;
+ u32 autonego;
+ u32 unused[6];
+ u32 int_device[8];
+} __attribute__ ((packed));
+
+#define vlynq_reg_read(reg) readl(&(reg))
+#define vlynq_reg_write(reg, val) writel(val, &(reg))
+
+static int __vlynq_enable_device(struct vlynq_device *dev);
+
+#ifdef VLYNQ_DEBUG
+static void vlynq_dump_regs(struct vlynq_device *dev)
+{
+ int i;
+ printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n",
+ dev->local, dev->remote);
+ for (i = 0; i < 32; i++) {
+ printk(KERN_DEBUG "VLYNQ: local %d: %08x\n",
+ i + 1, ((u32 *)dev->local)[i]);
+ printk(KERN_DEBUG "VLYNQ: remote %d: %08x\n",
+ i + 1, ((u32 *)dev->remote)[i]);
+ }
+}
+
+static void vlynq_dump_mem(u32 *base, int count)
+{
+ int i;
+ for (i = 0; i < (count + 3) / 4; i++) {
+ if (i % 4 == 0) printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4);
+ printk(KERN_DEBUG " 0x%08x", *(base + i));
+ }
+ printk(KERN_DEBUG "\n");
+}
+#endif
+
+int vlynq_linked(struct vlynq_device *dev)
+{
+ int i;
+
+ for (i = 0; i < 100; i++)
+ if (vlynq_reg_read(dev->local->status) & VLYNQ_STATUS_LINK)
+ return 1;
+ else
+ cpu_relax();
+
+ return 0;
+}
+
+static void vlynq_irq_unmask(unsigned int irq)
+{
+ u32 val;
+ struct vlynq_device *dev = get_irq_chip_data(irq);
+ int virq;
+
+ BUG_ON(!dev);
+ virq = irq - dev->irq_start;
+ val = vlynq_reg_read(dev->remote->int_device[virq >> 2]);
+ val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq);
+ vlynq_reg_write(dev->remote->int_device[virq >> 2], val);
+}
+
+static void vlynq_irq_mask(unsigned int irq)
+{
+ u32 val;
+ struct vlynq_device *dev = get_irq_chip_data(irq);
+ int virq;
+
+ BUG_ON(!dev);
+ virq = irq - dev->irq_start;
+ val = vlynq_reg_read(dev->remote->int_device[virq >> 2]);
+ val &= ~(VINT_ENABLE << VINT_OFFSET(virq));
+ vlynq_reg_write(dev->remote->int_device[virq >> 2], val);
+}
+
+static int vlynq_irq_type(unsigned int irq, unsigned int flow_type)
+{
+ u32 val;
+ struct vlynq_device *dev = get_irq_chip_data(irq);
+ int virq;
+
+ BUG_ON(!dev);
+ virq = irq - dev->irq_start;
+ val = vlynq_reg_read(dev->remote->int_device[virq >> 2]);
+ switch (flow_type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_EDGE_BOTH:
+ val |= VINT_TYPE_EDGE << VINT_OFFSET(virq);
+ val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq));
+ val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq));
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq));
+ val |= VINT_LEVEL_LOW << VINT_OFFSET(virq);
+ break;
+ default:
+ return -EINVAL;
+ }
+ vlynq_reg_write(dev->remote->int_device[virq >> 2], val);
+ return 0;
+}
+
+static void vlynq_local_ack(unsigned int irq)
+{
+ struct vlynq_device *dev = get_irq_chip_data(irq);
+ u32 status = vlynq_reg_read(dev->local->status);
+ if (printk_ratelimit())
+ printk(KERN_DEBUG "%s: local status: 0x%08x\n",
+ dev->dev.bus_id, status);
+ vlynq_reg_write(dev->local->status, status);
+}
+
+static void vlynq_remote_ack(unsigned int irq)
+{
+ struct vlynq_device *dev = get_irq_chip_data(irq);
+ u32 status = vlynq_reg_read(dev->remote->status);
+ if (printk_ratelimit())
+ printk(KERN_DEBUG "%s: remote status: 0x%08x\n",
+ dev->dev.bus_id, status);
+ vlynq_reg_write(dev->remote->status, status);
+}
+
+static irqreturn_t vlynq_irq(int irq, void *dev_id)
+{
+ struct vlynq_device *dev = dev_id;
+ u32 status;
+ int virq = 0;
+
+ status = vlynq_reg_read(dev->local->int_status);
+ vlynq_reg_write(dev->local->int_status, status);
+
+ if (unlikely(!status))
+ spurious_interrupt();
+
+ while (status) {
+ if (status & 1)
+ do_IRQ(dev->irq_start + virq);
+ status >>= 1;
+ virq++;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irq_chip vlynq_irq_chip = {
+ .name = "vlynq",
+ .unmask = vlynq_irq_unmask,
+ .mask = vlynq_irq_mask,
+ .set_type = vlynq_irq_type,
+};
+
+static struct irq_chip vlynq_local_chip = {
+ .name = "vlynq local error",
+ .unmask = vlynq_irq_unmask,
+ .mask = vlynq_irq_mask,
+ .ack = vlynq_local_ack,
+};
+
+static struct irq_chip vlynq_remote_chip = {
+ .name = "vlynq local error",
+ .unmask = vlynq_irq_unmask,
+ .mask = vlynq_irq_mask,
+ .ack = vlynq_remote_ack,
+};
+
+static int vlynq_setup_irq(struct vlynq_device *dev)
+{
+ u32 val;
+ int i, virq;
+
+ if (dev->local_irq == dev->remote_irq) {
+ printk(KERN_ERR
+ "%s: local vlynq irq should be different from remote\n",
+ dev->dev.bus_id);
+ return -EINVAL;
+ }
+
+ /* Clear local and remote error bits */
+ vlynq_reg_write(dev->local->status, vlynq_reg_read(dev->local->status));
+ vlynq_reg_write(dev->remote->status,
+ vlynq_reg_read(dev->remote->status));
+
+ /* Now setup interrupts */
+ val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq);
+ val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL |
+ VLYNQ_CTRL_INT2CFG;
+ val |= vlynq_reg_read(dev->local->control);
+ vlynq_reg_write(dev->local->int_ptr, VLYNQ_INT_OFFSET);
+ vlynq_reg_write(dev->local->control, val);
+
+ val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq);
+ val |= VLYNQ_CTRL_INT_ENABLE;
+ val |= vlynq_reg_read(dev->remote->control);
+ vlynq_reg_write(dev->remote->int_ptr, VLYNQ_INT_OFFSET);
+ vlynq_reg_write(dev->remote->control, val);
+
+ for (i = dev->irq_start; i <= dev->irq_end; i++) {
+ virq = i - dev->irq_start;
+ if (virq == dev->local_irq) {
+ set_irq_chip_and_handler(i, &vlynq_local_chip,
+ handle_level_irq);
+ set_irq_chip_data(i, dev);
+ } else if (virq == dev->remote_irq) {
+ set_irq_chip_and_handler(i, &vlynq_remote_chip,
+ handle_level_irq);
+ set_irq_chip_data(i, dev);
+ } else {
+ set_irq_chip_and_handler(i, &vlynq_irq_chip,
+ handle_simple_irq);
+ set_irq_chip_data(i, dev);
+ vlynq_reg_write(dev->remote->int_device[virq >> 2], 0);
+ }
+ }
+
+ if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) {
+ printk(KERN_ERR "%s: request_irq failed\n", dev->dev.bus_id);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static void vlynq_device_release(struct device *dev)
+{
+ struct vlynq_device *vdev = to_vlynq_device(dev);
+ kfree(vdev);
+}
+
+static int vlynq_device_match(struct device *dev,
+ struct device_driver *drv)
+{
+ struct vlynq_device *vdev = to_vlynq_device(dev);
+ struct vlynq_driver *vdrv = to_vlynq_driver(drv);
+ struct plat_vlynq_ops *ops = dev->platform_data;
+ struct vlynq_device_id *ids = vdrv->id_table;
+ u32 id = 0;
+ int result;
+
+ while (ids->id) {
+ vdev->divisor = ids->divisor;
+ result = __vlynq_enable_device(vdev);
+ if (result == 0) {
+ id = vlynq_reg_read(vdev->remote->chip);
+ ops->off(vdev);
+ if (ids->id == id) {
+ vlynq_set_drvdata(vdev, ids);
+ return 1;
+ }
+ }
+ ids++;
+ }
+ return 0;
+}
+
+static int vlynq_device_probe(struct device *dev)
+{
+ struct vlynq_device *vdev = to_vlynq_device(dev);
+ struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
+ struct vlynq_device_id *id = vlynq_get_drvdata(vdev);
+ int result = -ENODEV;
+
+ get_device(dev);
+ if (drv && drv->probe)
+ result = drv->probe(vdev, id);
+ if (result)
+ put_device(dev);
+ return result;
+}
+
+static int vlynq_device_remove(struct device *dev)
+{
+ struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
+ if (drv && drv->remove)
+ drv->remove(to_vlynq_device(dev));
+ put_device(dev);
+ return 0;
+}
+
+int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner)
+{
+ driver->driver.name = driver->name;
+ driver->driver.bus = &vlynq_bus_type;
+ return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL(__vlynq_register_driver);
+
+void vlynq_unregister_driver(struct vlynq_driver *driver)
+{
+ driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL(vlynq_unregister_driver);
+
+static int __vlynq_enable_device(struct vlynq_device *dev)
+{
+ int i, result;
+ struct plat_vlynq_ops *ops = dev->dev.platform_data;
+
+ result = ops->on(dev);
+ if (result)
+ return result;
+
+ switch (dev->divisor) {
+ case vlynq_div_auto:
+ /* Only try locally supplied clock, others cause problems */
+ vlynq_reg_write(dev->remote->control, 0);
+ for (i = vlynq_ldiv1; i <= vlynq_ldiv8; i++) {
+ vlynq_reg_write(dev->local->control,
+ VLYNQ_CTRL_CLOCK_INT |
+ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1));
+ if (vlynq_linked(dev)) {
+ printk(KERN_DEBUG
+ "%s: using local clock divisor %d\n",
+ dev->dev.bus_id, i - vlynq_ldiv1 + 1);
+ dev->divisor = i;
+ return 0;
+ }
+ }
+ case vlynq_ldiv1: case vlynq_ldiv2: case vlynq_ldiv3: case vlynq_ldiv4:
+ case vlynq_ldiv5: case vlynq_ldiv6: case vlynq_ldiv7: case vlynq_ldiv8:
+ vlynq_reg_write(dev->remote->control, 0);
+ vlynq_reg_write(dev->local->control,
+ VLYNQ_CTRL_CLOCK_INT |
+ VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
+ vlynq_ldiv1));
+ if (vlynq_linked(dev)) {
+ printk(KERN_DEBUG
+ "%s: using local clock divisor %d\n",
+ dev->dev.bus_id, dev->divisor - vlynq_ldiv1 + 1);
+ return 0;
+ }
+ break;
+ case vlynq_rdiv1: case vlynq_rdiv2: case vlynq_rdiv3: case vlynq_rdiv4:
+ case vlynq_rdiv5: case vlynq_rdiv6: case vlynq_rdiv7: case vlynq_rdiv8:
+ vlynq_reg_write(dev->local->control, 0);
+ vlynq_reg_write(dev->remote->control,
+ VLYNQ_CTRL_CLOCK_INT |
+ VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
+ vlynq_rdiv1));
+ if (vlynq_linked(dev)) {
+ printk(KERN_DEBUG
+ "%s: using remote clock divisor %d\n",
+ dev->dev.bus_id, dev->divisor - vlynq_rdiv1 + 1);
+ return 0;
+ }
+ break;
+ case vlynq_div_external:
+ vlynq_reg_write(dev->local->control, 0);
+ vlynq_reg_write(dev->remote->control, 0);
+ if (vlynq_linked(dev)) {
+ printk(KERN_DEBUG "%s: using external clock\n",
+ dev->dev.bus_id);
+ return 0;
+ }
+ break;
+ }
+
+ ops->off(dev);
+ return -ENODEV;
+}
+
+int vlynq_enable_device(struct vlynq_device *dev)
+{
+ struct plat_vlynq_ops *ops = dev->dev.platform_data;
+ int result = -ENODEV;
+
+ result = __vlynq_enable_device(dev);
+ if (result)
+ return result;
+
+ result = vlynq_setup_irq(dev);
+ if (result)
+ ops->off(dev);
+
+ dev->enabled = !result;
+ return result;
+}
+EXPORT_SYMBOL(vlynq_enable_device);
+
+
+void vlynq_disable_device(struct vlynq_device *dev)
+{
+ struct plat_vlynq_ops *ops = dev->dev.platform_data;
+
+ dev->enabled = 0;
+ free_irq(dev->irq, dev);
+ ops->off(dev);
+}
+EXPORT_SYMBOL(vlynq_disable_device);
+
+int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset,
+ struct vlynq_mapping *mapping)
+{
+ int i;
+
+ if (!dev->enabled)
+ return -ENXIO;
+
+ vlynq_reg_write(dev->local->tx_offset, tx_offset);
+ for (i = 0; i < 4; i++) {
+ vlynq_reg_write(dev->local->rx_mapping[i].offset,
+ mapping[i].offset);
+ vlynq_reg_write(dev->local->rx_mapping[i].size,
+ mapping[i].size);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(vlynq_set_local_mapping);
+
+int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset,
+ struct vlynq_mapping *mapping)
+{
+ int i;
+
+ if (!dev->enabled)
+ return -ENXIO;
+
+ vlynq_reg_write(dev->remote->tx_offset, tx_offset);
+ for (i = 0; i < 4; i++) {
+ vlynq_reg_write(dev->remote->rx_mapping[i].offset,
+ mapping[i].offset);
+ vlynq_reg_write(dev->remote->rx_mapping[i].size,
+ mapping[i].size);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(vlynq_set_remote_mapping);
+
+int vlynq_set_local_irq(struct vlynq_device *dev, int virq)
+{
+ int irq = dev->irq_start + virq;
+ if (dev->enabled)
+ return -EBUSY;
+
+ if ((irq < dev->irq_start) || (irq > dev->irq_end))
+ return -EINVAL;
+
+ if (virq == dev->remote_irq)
+ return -EINVAL;
+
+ dev->local_irq = virq;
+
+ return 0;
+}
+EXPORT_SYMBOL(vlynq_set_local_irq);
+
+int vlynq_set_remote_irq(struct vlynq_device *dev, int virq)
+{
+ int irq = dev->irq_start + virq;
+ if (dev->enabled)
+ return -EBUSY;
+
+ if ((irq < dev->irq_start) || (irq > dev->irq_end))
+ return -EINVAL;
+
+ if (virq == dev->local_irq)
+ return -EINVAL;
+
+ dev->remote_irq = virq;
+
+ return 0;
+}
+EXPORT_SYMBOL(vlynq_set_remote_irq);
+
+static int vlynq_probe(struct platform_device *pdev)
+{
+ struct vlynq_device *dev;
+ struct resource *regs_res, *mem_res, *irq_res;
+ int len, result;
+
+ regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ if (!regs_res)
+ return -ENODEV;
+
+ mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
+ if (!mem_res)
+ return -ENODEV;
+
+ irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "devirq");
+ if (!irq_res)
+ return -ENODEV;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ printk(KERN_ERR
+ "vlynq: failed to allocate device structure\n");
+ return -ENOMEM;
+ }
+
+ dev->id = pdev->id;
+ dev->dev.bus = &vlynq_bus_type;
+ dev->dev.parent = &pdev->dev;
+ snprintf(dev->dev.bus_id, BUS_ID_SIZE, "vlynq%d", dev->id);
+ dev->dev.bus_id[BUS_ID_SIZE - 1] = 0;
+ dev->dev.platform_data = pdev->dev.platform_data;
+ dev->dev.release = vlynq_device_release;
+
+ dev->regs_start = regs_res->start;
+ dev->regs_end = regs_res->end;
+ dev->mem_start = mem_res->start;
+ dev->mem_end = mem_res->end;
+
+ len = regs_res->end - regs_res->start;
+ if (!request_mem_region(regs_res->start, len, dev->dev.bus_id)) {
+ printk(KERN_ERR "%s: Can't request vlynq registers\n",
+ dev->dev.bus_id);
+ result = -ENXIO;
+ goto fail_request;
+ }
+
+ dev->local = ioremap(regs_res->start, len);
+ if (!dev->local) {
+ printk(KERN_ERR "%s: Can't remap vlynq registers\n",
+ dev->dev.bus_id);
+ result = -ENXIO;
+ goto fail_remap;
+ }
+
+ dev->remote = (struct vlynq_regs *)((void *)dev->local +
+ VLYNQ_REMOTE_OFFSET);
+
+ dev->irq = platform_get_irq_byname(pdev, "irq");
+ dev->irq_start = irq_res->start;
+ dev->irq_end = irq_res->end;
+ dev->local_irq = dev->irq_end - dev->irq_start;
+ dev->remote_irq = dev->local_irq - 1;
+
+ if (device_register(&dev->dev))
+ goto fail_register;
+ platform_set_drvdata(pdev, dev);
+
+ printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n",
+ dev->dev.bus_id, (void *)dev->regs_start, dev->irq,
+ (void *)dev->mem_start);
+
+ return 0;
+
+fail_register:
+ iounmap(dev->local);
+fail_remap:
+fail_request:
+ release_mem_region(regs_res->start, len);
+ kfree(dev);
+ return result;
+}
+
+static int vlynq_remove(struct platform_device *pdev)
+{
+ struct vlynq_device *dev = platform_get_drvdata(pdev);
+
+ device_unregister(&dev->dev);
+ iounmap(dev->local);
+ release_mem_region(dev->regs_start, dev->regs_end - dev->regs_start);
+
+ kfree(dev);
+
+ return 0;
+}
+
+static struct platform_driver vlynq_driver = {
+ .driver.name = "vlynq",
+ .probe = vlynq_probe,
+ .remove = __devexit_p(vlynq_remove),
+};
+
+struct bus_type vlynq_bus_type = {
+ .name = "vlynq",
+ .match = vlynq_device_match,
+ .probe = vlynq_device_probe,
+ .remove = vlynq_device_remove,
+};
+EXPORT_SYMBOL(vlynq_bus_type);
+
+static int __devinit vlynq_init(void)
+{
+ int res = 0;
+
+ res = bus_register(&vlynq_bus_type);
+ if (res)
+ goto fail_bus;
+
+ res = platform_driver_register(&vlynq_driver);
+ if (res)
+ goto fail_platform;
+
+ return 0;
+
+fail_platform:
+ bus_unregister(&vlynq_bus_type);
+fail_bus:
+ return res;
+}
+
+static void __devexit vlynq_exit(void)
+{
+ platform_driver_unregister(&vlynq_driver);
+ bus_unregister(&vlynq_bus_type);
+}
+
+module_init(vlynq_init);
+module_exit(vlynq_exit);
diff --git a/include/linux/vlynq.h b/include/linux/vlynq.h
new file mode 100644
index 0000000..b3f2474
--- /dev/null
+++ b/include/linux/vlynq.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2006, 2007 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 __VLYNQ_H__
+#define __VLYNQ_H__
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#define VLYNQ_NUM_IRQS 32
+
+struct vlynq_mapping {
+ u32 size;
+ u32 offset;
+};
+
+enum vlynq_divisor {
+ vlynq_div_auto = 0,
+ vlynq_ldiv1,
+ vlynq_ldiv2,
+ vlynq_ldiv3,
+ vlynq_ldiv4,
+ vlynq_ldiv5,
+ vlynq_ldiv6,
+ vlynq_ldiv7,
+ vlynq_ldiv8,
+ vlynq_rdiv1,
+ vlynq_rdiv2,
+ vlynq_rdiv3,
+ vlynq_rdiv4,
+ vlynq_rdiv5,
+ vlynq_rdiv6,
+ vlynq_rdiv7,
+ vlynq_rdiv8,
+ vlynq_div_external
+};
+
+struct vlynq_device_id {
+ u32 id;
+ enum vlynq_divisor divisor;
+ unsigned long driver_data;
+};
+
+struct vlynq_regs;
+struct vlynq_device {
+ u32 id;
+ int local_irq;
+ int remote_irq;
+ enum vlynq_divisor divisor;
+ u32 regs_start, regs_end;
+ u32 mem_start, mem_end;
+ u32 irq_start, irq_end;
+ int irq;
+ int enabled;
+ struct vlynq_regs *local;
+ struct vlynq_regs *remote;
+ struct device dev;
+};
+
+struct vlynq_driver {
+ char *name;
+ struct vlynq_device_id *id_table;
+ int (*probe)(struct vlynq_device *dev, struct vlynq_device_id *id);
+ void (*remove)(struct vlynq_device *dev);
+ struct device_driver driver;
+};
+
+struct plat_vlynq_ops {
+ int (*on)(struct vlynq_device *dev);
+ void (*off)(struct vlynq_device *dev);
+};
+
+static inline struct vlynq_driver *to_vlynq_driver(struct device_driver *drv)
+{
+ return container_of(drv, struct vlynq_driver, driver);
+}
+
+static inline struct vlynq_device *to_vlynq_device(struct device *device)
+{
+ return container_of(device, struct vlynq_device, dev);
+}
+
+extern struct bus_type vlynq_bus_type;
+
+extern int __vlynq_register_driver(struct vlynq_driver *driver,
+ struct module *owner);
+
+static inline int vlynq_register_driver(struct vlynq_driver *driver)
+{
+ return __vlynq_register_driver(driver, THIS_MODULE);
+}
+
+static inline void *vlynq_get_drvdata(struct vlynq_device *dev)
+{
+ return dev_get_drvdata(&dev->dev);
+}
+
+static inline void vlynq_set_drvdata(struct vlynq_device *dev, void *data)
+{
+ dev_set_drvdata(&dev->dev, data);
+}
+
+static inline u32 vlynq_mem_start(struct vlynq_device *dev)
+{
+ return dev->mem_start;
+}
+
+static inline u32 vlynq_mem_end(struct vlynq_device *dev)
+{
+ return dev->mem_end;
+}
+
+static inline u32 vlynq_mem_len(struct vlynq_device *dev)
+{
+ return dev->mem_end - dev->mem_start + 1;
+}
+
+static inline int vlynq_virq_to_irq(struct vlynq_device *dev, int virq)
+{
+ int irq = dev->irq_start + virq;
+ if ((irq < dev->irq_start) || (irq > dev->irq_end))
+ return -EINVAL;
+
+ return irq;
+}
+
+static inline int vlynq_irq_to_virq(struct vlynq_device *dev, int irq)
+{
+ if ((irq < dev->irq_start) || (irq > dev->irq_end))
+ return -EINVAL;
+
+ return irq - dev->irq_start;
+}
+
+extern void vlynq_unregister_driver(struct vlynq_driver *driver);
+extern int vlynq_enable_device(struct vlynq_device *dev);
+extern void vlynq_disable_device(struct vlynq_device *dev);
+extern int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset,
+ struct vlynq_mapping *mapping);
+extern int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset,
+ struct vlynq_mapping *mapping);
+extern int vlynq_set_local_irq(struct vlynq_device *dev, int virq);
+extern int vlynq_set_remote_irq(struct vlynq_device *dev, int virq);
+
+#endif /* __VLYNQ_H__ */
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH][MIPS][3/6] AR7: mtd partition map
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
2007-10-11 0:50 ` [PATCH][MIPS][1/6] AR7: core support Matteo Croce
2007-10-11 0:54 ` [PATCH][MIPS][2/6] AR7: VLYNQ bus Matteo Croce
@ 2007-10-11 0:55 ` Matteo Croce
2007-10-11 0:57 ` [PATCH][MIPS][4/6] AR7: gpio char device Matteo Croce
` (3 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 0:55 UTC (permalink / raw)
To: linux-mips; +Cc: Felix Fietkau, Eugene Konev, dwmw2, linux-mtd, Andrew Morton
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Eugene Konev <ejka@imfi.kspu.ru>
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index fbec8cd..c1b2508 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -150,6 +150,12 @@ config MTD_AFS_PARTS
for your particular device. It won't happen automatically. The
'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
+config MTD_AR7_PARTS
+ tristate "TI AR7 partitioning support"
+ depends on MTD_PARTITIONS
+ ---help---
+ TI AR7 partitioning support
+
comment "User Modules And Translation Layers"
config MTD_CHAR
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 6d958a4..8451c64 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
+obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
# 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
new file mode 100644
index 0000000..3d160d4
--- /dev/null
+++ b/drivers/mtd/ar7part.c
@@ -0,0 +1,146 @@
+/*
+ * 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
+ *
+ * TI AR7 flash partition table.
+ * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/bootmem.h>
+#include <linux/magic.h>
+
+#define AR7_PARTS 4
+#define ROOT_OFFSET 0xe0000
+
+#define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42)
+#define LOADER_MAGIC2 le32_to_cpu(0xfeed1281)
+
+struct ar7_bin_rec {
+ unsigned int checksum;
+ unsigned int length;
+ unsigned int address;
+};
+
+static struct mtd_partition ar7_parts[AR7_PARTS];
+
+static int create_mtd_partitions(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ unsigned long origin)
+{
+ struct ar7_bin_rec header;
+ unsigned int offset, len;
+ unsigned int pre_size = master->erasesize, post_size = 0;
+ unsigned int root_offset = ROOT_OFFSET;
+
+ int retries = 10;
+
+ ar7_parts[0].name = "loader";
+ ar7_parts[0].offset = 0;
+ ar7_parts[0].size = master->erasesize;
+ ar7_parts[0].mask_flags = MTD_WRITEABLE;
+
+ ar7_parts[1].name = "config";
+ ar7_parts[1].offset = 0;
+ ar7_parts[1].size = master->erasesize;
+ ar7_parts[1].mask_flags = 0;
+
+ do { /* Try 10 blocks starting from master->erasesize */
+ offset = pre_size;
+ master->read(master, offset,
+ sizeof(header), &len, (u8 *)&header);
+ if (!strncmp((char *)&header, "TIENV0.8", 8))
+ ar7_parts[1].offset = pre_size;
+ if (header.checksum == LOADER_MAGIC1)
+ break;
+ if (header.checksum == LOADER_MAGIC2)
+ break;
+ pre_size += master->erasesize;
+ } while (retries--);
+
+ pre_size = offset;
+
+ if (!ar7_parts[1].offset) {
+ ar7_parts[1].offset = master->size - master->erasesize;
+ post_size = master->erasesize;
+ }
+
+ switch (header.checksum) {
+ case LOADER_MAGIC1:
+ while (header.length) {
+ offset += sizeof(header) + header.length;
+ master->read(master, offset, sizeof(header),
+ &len, (u8 *)&header);
+ }
+ root_offset = offset + sizeof(header) + 4;
+ break;
+ case LOADER_MAGIC2:
+ while (header.length) {
+ offset += sizeof(header) + header.length;
+ master->read(master, offset, sizeof(header),
+ &len, (u8 *)&header);
+ }
+ root_offset = offset + sizeof(header) + 4 + 0xff;
+ root_offset &= ~(u32)0xff;
+ break;
+ default:
+ printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
+ break;
+ }
+
+ master->read(master, root_offset,
+ sizeof(header), &len, (u8 *)&header);
+ if (header.checksum != SQUASHFS_MAGIC) {
+ root_offset += master->erasesize - 1;
+ root_offset &= ~(master->erasesize - 1);
+ }
+
+ ar7_parts[2].name = "linux";
+ ar7_parts[2].offset = pre_size;
+ ar7_parts[2].size = master->size - pre_size - post_size;
+ ar7_parts[2].mask_flags = 0;
+
+ ar7_parts[3].name = "rootfs";
+ ar7_parts[3].offset = root_offset;
+ ar7_parts[3].size = master->size - root_offset - post_size;
+ ar7_parts[3].mask_flags = 0;
+
+ *pparts = ar7_parts;
+ return AR7_PARTS;
+}
+
+static struct mtd_part_parser ar7_parser = {
+ .owner = THIS_MODULE,
+ .parse_fn = create_mtd_partitions,
+ .name = "ar7part",
+};
+
+static int __init ar7_parser_init(void)
+{
+ return register_mtd_parser(&ar7_parser);
+}
+
+module_init(ar7_parser_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR( "Felix Fietkau <nbd@openwrt.org>, "
+ "Eugene Konev <ejka@openwrt.org>");
+MODULE_DESCRIPTION("MTD partitioning for TI AR7");
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH][MIPS][4/6] AR7: gpio char device
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
` (2 preceding siblings ...)
2007-10-11 0:55 ` [PATCH][MIPS][3/6] AR7: mtd partition map Matteo Croce
@ 2007-10-11 0:57 ` Matteo Croce
2007-10-11 0:59 ` [PATCH][MIPS][5/6] AR7: serial hack Matteo Croce
` (2 subsequent siblings)
6 siblings, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 0:57 UTC (permalink / raw)
To: linux-mips; +Cc: Nicolas Thill, Andrew Morton
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index b391776..b98aedf 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -928,6 +928,15 @@ config MWAVE
To compile this driver as a module, choose M here: the
module will be called mwave.
+config AR7_GPIO
+ tristate "TI AR7 GPIO Support"
+ depends on AR7
+ help
+ Give userspace access to the GPIO pins on the Texas Instruments AR7
+ processors.
+
+ If compiled as a module, it will be called ar7_gpio.
+
config SCx200_GPIO
tristate "NatSemi SCx200 GPIO Support"
depends on SCx200
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c78ff26..3d7c2af 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_COBALT_LCD) += lcd.o
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
+obj-$(CONFIG_AR7_GPIO) += ar7_gpio.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
diff --git a/drivers/char/ar7_gpio.c b/drivers/char/ar7_gpio.c
new file mode 100644
index 0000000..16460cd
--- /dev/null
+++ b/drivers/char/ar7_gpio.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2007 Nicolas Thill <nico@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/device.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <gpio.h>
+
+#define DRVNAME "ar7_gpio"
+#define LONGNAME "TI AR7 GPIOs Driver"
+
+MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+
+static int ar7_gpio_major;
+
+static ssize_t ar7_gpio_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ int pin = iminor(file->f_dentry->d_inode);
+ size_t i;
+
+ for (i = 0; i < len; ++i) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ switch (c) {
+ case '0':
+ gpio_set_value(pin, 0);
+ break;
+ case '1':
+ gpio_set_value(pin, 1);
+ break;
+ case 'd':
+ case 'D':
+ ar7_gpio_disable(pin);
+ break;
+ case 'e':
+ case 'E':
+ ar7_gpio_enable(pin);
+ break;
+ case 'i':
+ case 'I':
+ case '<':
+ gpio_direction_input(pin);
+ break;
+ case 'o':
+ case 'O':
+ case '>':
+ gpio_direction_output(pin, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return len;
+}
+
+static ssize_t ar7_gpio_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ int pin = iminor(file->f_dentry->d_inode);
+ int value;
+
+ value = gpio_get_value(pin);
+ if (put_user(value ? '1' : '0', buf))
+ return -EFAULT;
+
+ return 1;
+}
+
+static int ar7_gpio_open(struct inode *inode, struct file *file)
+{
+ int m = iminor(inode);
+
+ if (m >= AR7_GPIO_MAX)
+ return -EINVAL;
+
+ return nonseekable_open(inode, file);
+}
+
+static int ar7_gpio_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static const struct file_operations ar7_gpio_fops = {
+ .owner = THIS_MODULE,
+ .write = ar7_gpio_write,
+ .read = ar7_gpio_read,
+ .open = ar7_gpio_open,
+ .release = ar7_gpio_release,
+ .llseek = no_llseek,
+};
+
+static struct platform_device *ar7_gpio_device;
+
+static int __init ar7_gpio_init(void)
+{
+ int rc;
+
+ ar7_gpio_device = platform_device_alloc(DRVNAME, -1);
+ if (!ar7_gpio_device)
+ return -ENOMEM;
+
+ rc = platform_device_add(ar7_gpio_device);
+ if (rc < 0)
+ goto out_put;
+
+ rc = register_chrdev(ar7_gpio_major, DRVNAME, &ar7_gpio_fops);
+ if (rc < 0)
+ goto out_put;
+
+ ar7_gpio_major = rc;
+
+ rc = 0;
+
+ goto out;
+
+out_put:
+ platform_device_put(ar7_gpio_device);
+out:
+ return rc;
+}
+
+static void __exit ar7_gpio_exit(void)
+{
+ unregister_chrdev(ar7_gpio_major, DRVNAME);
+ platform_device_unregister(ar7_gpio_device);
+}
+
+module_init(ar7_gpio_init);
+module_exit(ar7_gpio_exit);
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH][MIPS][5/6] AR7: serial hack
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
` (3 preceding siblings ...)
2007-10-11 0:57 ` [PATCH][MIPS][4/6] AR7: gpio char device Matteo Croce
@ 2007-10-11 0:59 ` Matteo Croce
2007-10-11 1:01 ` [PATCH][MIPS][6/6] AR7: leds driver Matteo Croce
2007-10-18 8:22 ` [PATCH][MIPS][0/6] AR7: AR7 strikes back Florian Fainelli
6 siblings, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 0:59 UTC (permalink / raw)
To: linux-mips
Cc: Florian Fainelli, Felix Fietkau, Nicolas Thill, linux-serial,
Andrew Morton
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index f94109c..94253b7 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -267,6 +267,13 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
+ [PORT_AR7] = {
+ .name = "TI-AR7",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
};
#if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -2453,7 +2460,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
+#ifdef CONFIG_AR7
+ wait_for_xmitr(up, BOTH_EMPTY);
+#else
wait_for_xmitr(up, UART_LSR_THRE);
+#endif
serial_out(up, UART_TX, ch);
}
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index e811a61..cf71de9 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -135,6 +135,10 @@ struct rs_multiport_struct {
* the interrupt line _up_ instead of down, so if we register the IRQ
* while the UART is in that state, we die in an IRQ storm. */
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
+#elif defined(CONFIG_AR7)
+/* This is how it is set up by bootloader... */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1 \
+ | UART_MCR_RTS | UART_MCR_DTR)
#else
#define ALPHA_KLUDGE_MCR 0
#endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 09d17b0..8ad2c3b 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -40,6 +40,7 @@
#define PORT_NS16550A 14
#define PORT_XSCALE 15
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
+#define PORT_AR7 16
#define PORT_MAX_8250 16 /* max port ID */
/*
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][6/6] AR7: leds driver
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
` (4 preceding siblings ...)
2007-10-11 0:59 ` [PATCH][MIPS][5/6] AR7: serial hack Matteo Croce
@ 2007-10-11 1:01 ` Matteo Croce
2007-10-18 8:22 ` [PATCH][MIPS][0/6] AR7: AR7 strikes back Florian Fainelli
6 siblings, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2007-10-11 1:01 UTC (permalink / raw)
To: linux-mips
Cc: Eugene Konev, netdev, davem, kuznet, pekkas, jmorris, yoshfuji,
kaber, Andrew Morton, Jeff Garzik
The new led driver, uses leds-gpio now
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
diff --git a/drivers/leds/leds-ar7.c b/drivers/leds/leds-ar7.c
new file mode 100644
index 0000000..72b958a
--- /dev/null
+++ b/drivers/leds/leds-ar7.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 Nicolas Thill <nico@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/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <gpio.h>
+
+#define DRVNAME "ar7-leds"
+#define LONGNAME "TI AR7 LEDs driver"
+#define AR7_GPIO_BIT_STATUS_LED 8
+
+MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+
+static void ar7_status_led_set(struct led_classdev *pled,
+ enum led_brightness value)
+{
+ gpio_set_value(AR7_GPIO_BIT_STATUS_LED, value ? 0 : 1);
+}
+
+static struct led_classdev ar7_status_led = {
+ .name = "ar7:status",
+ .brightness_set = ar7_status_led_set,
+};
+
+#ifdef CONFIG_PM
+static int ar7_leds_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ led_classdev_suspend(&ar7_status_led);
+ return 0;
+}
+
+static int ar7_leds_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&ar7_status_led);
+ return 0;
+}
+#else /* CONFIG_PM */
+#define ar7_leds_suspend NULL
+#define ar7_leds_resume NULL
+#endif /* CONFIG_PM */
+
+static int ar7_leds_probe(struct platform_device *pdev)
+{
+ int rc;
+
+ rc = led_classdev_register(&pdev->dev, &ar7_status_led);
+ if (rc < 0)
+ goto out;
+
+ ar7_gpio_enable(AR7_GPIO_BIT_STATUS_LED);
+ gpio_direction_output(AR7_GPIO_BIT_STATUS_LED, 0);
+
+out:
+ return rc;
+}
+
+static int ar7_leds_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&ar7_status_led);
+
+ return 0;
+}
+
+static struct platform_device *ar7_leds_device;
+
+static struct platform_driver ar7_leds_driver = {
+ .probe = ar7_leds_probe,
+ .remove = ar7_leds_remove,
+ .suspend = ar7_leds_suspend,
+ .resume = ar7_leds_resume,
+ .driver = {
+ .name = DRVNAME,
+ },
+};
+
+static int __init ar7_leds_init(void)
+{
+ int rc;
+
+ ar7_leds_device = platform_device_alloc(DRVNAME, -1);
+ if (!ar7_leds_device)
+ return -ENOMEM;
+
+ rc = platform_device_add(ar7_leds_device);
+ if (rc < 0)
+ goto out_put;
+
+ rc = platform_driver_register(&ar7_leds_driver);
+ if (rc < 0)
+ goto out_put;
+
+ goto out;
+
+out_put:
+ platform_device_put(ar7_leds_device);
+out:
+ return rc;
+}
+
+static void __exit ar7_leds_exit(void)
+{
+ platform_driver_unregister(&ar7_leds_driver);
+ platform_device_unregister(ar7_leds_device);
+}
+
+module_init(ar7_leds_init);
+module_exit(ar7_leds_exit);
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][0/6] AR7: AR7 strikes back
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
` (5 preceding siblings ...)
2007-10-11 1:01 ` [PATCH][MIPS][6/6] AR7: leds driver Matteo Croce
@ 2007-10-18 8:22 ` Florian Fainelli
6 siblings, 0 replies; 34+ messages in thread
From: Florian Fainelli @ 2007-10-18 8:22 UTC (permalink / raw)
To: Matteo Croce; +Cc: linux-mips, nico, nbd, openwrt-devel, Andrew Morton
Hi all,
Jeff Garzik merged the AR7 ethernet driver and Wim Van Sebroeck merged the
watchdog driver.
Is there anything that needs some cleanup for a linux-mips inclusion ?
On Thursday 11 October 2007 02:48:32 Matteo Croce wrote:
> Here are the new patches made against latest 2.6.23 git tree
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH][MIPS][5/6]: AR7: serial hack
2007-12-27 18:19 [PATCH][MIPS][0/6]: AR7 refresh Matteo Croce
@ 2007-12-27 18:27 ` Matteo Croce
2007-12-28 12:13 ` Sergei Shtylyov
0 siblings, 1 reply; 34+ messages in thread
From: Matteo Croce @ 2007-12-27 18:27 UTC (permalink / raw)
To: linux-mips
Cc: Florian Fainelli, Felix Fietkau, Nicolas Thill, linux-serial,
Andrew Morton
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index f94109c..94253b7 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -267,6 +267,13 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
+ [PORT_AR7] = {
+ .name = "TI-AR7",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
};
#if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -2453,7 +2460,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
+#ifdef CONFIG_AR7
+ wait_for_xmitr(up, BOTH_EMPTY);
+#else
wait_for_xmitr(up, UART_LSR_THRE);
+#endif
serial_out(up, UART_TX, ch);
}
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index e811a61..cf71de9 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -135,6 +135,10 @@ struct rs_multiport_struct {
* the interrupt line _up_ instead of down, so if we register the IRQ
* while the UART is in that state, we die in an IRQ storm. */
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
+#elif defined(CONFIG_AR7)
+/* This is how it is set up by bootloader... */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1 \
+ | UART_MCR_RTS | UART_MCR_DTR)
#else
#define ALPHA_KLUDGE_MCR 0
#endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 9963f81..10af5a2 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -40,6 +40,7 @@
#define PORT_NS16550A 14
#define PORT_XSCALE 15
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
+#define PORT_AR7 16
#define PORT_MAX_8250 16 /* max port ID */
/*
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2007-12-27 18:27 ` [PATCH][MIPS][5/6]: AR7: serial hack Matteo Croce
@ 2007-12-28 12:13 ` Sergei Shtylyov
0 siblings, 0 replies; 34+ messages in thread
From: Sergei Shtylyov @ 2007-12-28 12:13 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Matteo Croce wrote:
> Signed-off-by: Matteo Croce <technoboy85@gmail.com>
> Signed-off-by: Florian Fainelli <florian@openwrt.org>
> Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> Signed-off-by: Nicolas Thill <nico@openwrt.org>
> diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
> index f94109c..94253b7 100644
> --- a/drivers/serial/8250.c
> +++ b/drivers/serial/8250.c
[...]
> @@ -2453,7 +2460,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
> {
> struct uart_8250_port *up = (struct uart_8250_port *)port;
>
> +#ifdef CONFIG_AR7
No board specific #ifdef's here please. You should use the driver's bug
mechanism for this.
> + wait_for_xmitr(up, BOTH_EMPTY);
> +#else
> wait_for_xmitr(up, UART_LSR_THRE);
> +#endif
> serial_out(up, UART_TX, ch);
> }
>
> diff --git a/include/linux/serialP.h b/include/linux/serialP.h
> index e811a61..cf71de9 100644
> --- a/include/linux/serialP.h
> +++ b/include/linux/serialP.h
> @@ -135,6 +135,10 @@ struct rs_multiport_struct {
> * the interrupt line _up_ instead of down, so if we register the IRQ
> * while the UART is in that state, we die in an IRQ storm. */
> #define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
> +#elif defined(CONFIG_AR7)
> +/* This is how it is set up by bootloader... */
> +#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1 \
> + | UART_MCR_RTS | UART_MCR_DTR)
I don't think you should load the driver with forced RTS and DTR.
> #else
> #define ALPHA_KLUDGE_MCR 0
> #endif
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 9963f81..10af5a2 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -40,6 +40,7 @@
> #define PORT_NS16550A 14
> #define PORT_XSCALE 15
> #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
> +#define PORT_AR7 16
Obviously, this should have been 16. :-)
WBR, Sergei
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-12 1:21 [PATCH][MIPS][0/6]: AR7 final Matteo Croce
@ 2008-03-12 1:30 ` Matteo Croce
2008-03-12 9:31 ` Thomas Bogendoerfer
2008-03-12 11:16 ` Alan Cox
0 siblings, 2 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-12 1:30 UTC (permalink / raw)
To: linux-mips
Cc: Florian Fainelli, Felix Fietkau, Nicolas Thill, linux-serial,
Andrew Morton
Ugly but we need it
Signed-off-by: Matteo Croce <technoboy85@gmail.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Nicolas Thill <nico@openwrt.org>
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 77f7a7f..a3a271d 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -267,6 +267,13 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
+ [PORT_AR7] = {
+ .name = "TI-AR7",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
};
#if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -2455,7 +2462,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
+#ifdef CONFIG_AR7
+ wait_for_xmitr(up, BOTH_EMPTY);
+#else
wait_for_xmitr(up, UART_LSR_THRE);
+#endif
serial_out(up, UART_TX, ch);
}
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index e811a61..cf71de9 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -135,6 +135,10 @@ struct rs_multiport_struct {
* the interrupt line _up_ instead of down, so if we register the IRQ
* while the UART is in that state, we die in an IRQ storm. */
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
+#elif defined(CONFIG_AR7)
+/* This is how it is set up by bootloader... */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1 \
+ | UART_MCR_RTS | UART_MCR_DTR)
#else
#define ALPHA_KLUDGE_MCR 0
#endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 289942f..869b6df 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -40,6 +40,7 @@
#define PORT_NS16550A 14
#define PORT_XSCALE 15
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
+#define PORT_AR7 16
#define PORT_MAX_8250 16 /* max port ID */
/*
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-12 1:30 ` [PATCH][MIPS][5/6]: AR7: serial hack Matteo Croce
@ 2008-03-12 9:31 ` Thomas Bogendoerfer
2008-03-13 0:38 ` Matteo Croce
2008-03-12 11:16 ` Alan Cox
1 sibling, 1 reply; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-12 9:31 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
On Wed, Mar 12, 2008 at 02:30:06AM +0100, Matteo Croce wrote:
> Ugly but we need it
why ? I'm running AR7 uarts just like all other 16550.
> #if defined (CONFIG_SERIAL_8250_AU1X00)
> @@ -2455,7 +2462,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
> {
> struct uart_8250_port *up = (struct uart_8250_port *)port;
>
> +#ifdef CONFIG_AR7
> + wait_for_xmitr(up, BOTH_EMPTY);
> +#else
> wait_for_xmitr(up, UART_LSR_THRE);
> +#endif
> serial_out(up, UART_TX, ch);
> }
this doesn't make sense. Why don't you check for the port type and
decide, if you need to use the AR7 way or the normal way. This will
for example break 16550 uarts connected via PCI on UR8 devices.
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 289942f..869b6df 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -40,6 +40,7 @@
> #define PORT_NS16550A 14
> #define PORT_XSCALE 15
> #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
> +#define PORT_AR7 16
this doesn't look correct.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-12 1:30 ` [PATCH][MIPS][5/6]: AR7: serial hack Matteo Croce
2008-03-12 9:31 ` Thomas Bogendoerfer
@ 2008-03-12 11:16 ` Alan Cox
2008-03-13 0:31 ` Matteo Croce
1 sibling, 1 reply; 34+ messages in thread
From: Alan Cox @ 2008-03-12 11:16 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
On Wed, 12 Mar 2008 02:30:06 +0100
Matteo Croce <technoboy85@gmail.com> wrote:
> Ugly but we need it
Too ugly - NAK
However please send an explanation of the problem and lets find a nicer
way to do it or bury it in arch code.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-12 11:16 ` Alan Cox
@ 2008-03-13 0:31 ` Matteo Croce
2008-03-13 9:01 ` Thomas Bogendoerfer
0 siblings, 1 reply; 34+ messages in thread
From: Matteo Croce @ 2008-03-13 0:31 UTC (permalink / raw)
To: Alan Cox
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Il Wednesday 12 March 2008 12:16:29 Alan Cox ha scritto:
> On Wed, 12 Mar 2008 02:30:06 +0100
> Matteo Croce <technoboy85@gmail.com> wrote:
>
> > Ugly but we need it
>
> Too ugly - NAK
>
> However please send an explanation of the problem and lets find a nicer
> way to do it or bury it in arch code.
>
>
This is my problem:
ffi_cmdset_000: DDisabling erae-ssuspend-progrm ddue to code bokeenness.
cmdlinparrt partition arssing not avaiabll
RedBoo ppartition parsngg not availabl
NET: Rgiistered protocl family 1
NET: Regsteered protocol ammily 10
IPv6 overIPPv4 tunnelingdriiver
NET: Regsteered protocolfammily 17
FS:: Mounted roo (ssquashfs filessttem) readonly.
Freeing nuused kernel meorry: 120k freed
I'll try to find a nicer way to fix it
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-12 9:31 ` Thomas Bogendoerfer
@ 2008-03-13 0:38 ` Matteo Croce
2008-03-13 8:45 ` Thomas Bogendoerfer
0 siblings, 1 reply; 34+ messages in thread
From: Matteo Croce @ 2008-03-13 0:38 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Il Wednesday 12 March 2008 10:31:46 Thomas Bogendoerfer ha scritto:
> > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> > index 289942f..869b6df 100644
> > --- a/include/linux/serial_core.h
> > +++ b/include/linux/serial_core.h
> > @@ -40,6 +40,7 @@
> > #define PORT_NS16550A 14
> > #define PORT_XSCALE 15
> > #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
> > +#define PORT_AR7 16
>
> this doesn't look correct.
>
> Thomas.
>
Isn't it 16?
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-13 0:38 ` Matteo Croce
@ 2008-03-13 8:45 ` Thomas Bogendoerfer
2008-03-14 15:46 ` Matteo Croce
0 siblings, 1 reply; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-13 8:45 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
On Thu, Mar 13, 2008 at 01:38:55AM +0100, Matteo Croce wrote:
> Il Wednesday 12 March 2008 10:31:46 Thomas Bogendoerfer ha scritto:
> > > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> > > index 289942f..869b6df 100644
> > > --- a/include/linux/serial_core.h
> > > +++ b/include/linux/serial_core.h
> > > @@ -40,6 +40,7 @@
> > > #define PORT_NS16550A 14
> > > #define PORT_XSCALE 15
> > > #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
> > > +#define PORT_AR7 16
> >
> > this doesn't look correct.
> >
> > Thomas.
> >
>
> Isn't it 16?
PORT_RM9000 is 16, how could PORT_AR7 be 16 as well ? And the 16 for
PORT_RM9000 is correct in my counting.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-13 0:31 ` Matteo Croce
@ 2008-03-13 9:01 ` Thomas Bogendoerfer
2008-03-16 15:27 ` Matteo Croce
2008-03-16 15:49 ` Matteo Croce
0 siblings, 2 replies; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-13 9:01 UTC (permalink / raw)
To: Matteo Croce
Cc: Alan Cox, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
On Thu, Mar 13, 2008 at 01:31:54AM +0100, Matteo Croce wrote:
> Il Wednesday 12 March 2008 12:16:29 Alan Cox ha scritto:
> > On Wed, 12 Mar 2008 02:30:06 +0100
> > Matteo Croce <technoboy85@gmail.com> wrote:
> >
> > > Ugly but we need it
> >
> > Too ugly - NAK
> >
> > However please send an explanation of the problem and lets find a nicer
> > way to do it or bury it in arch code.
> >
> >
>
> This is my problem:
>
> ffi_cmdset_000: DDisabling erae-ssuspend-progrm ddue to code bokeenness.
> cmdlinparrt partition arssing not avaiabll
> RedBoo ppartition parsngg not availabl
> NET: Rgiistered protocl family 1
> NET: Regsteered protocol ammily 10
> IPv6 overIPPv4 tunnelingdriiver
> NET: Regsteered protocolfammily 17
> FS:: Mounted roo (ssquashfs filessttem) readonly.
> Freeing nuused kernel meorry: 120k freed
>
> I'll try to find a nicer way to fix it
don't use AFE mode and treat it like a normal 16550 (PORT_16550A). You
could also try to use UPIO_MEM32. That's how my console driver
(different OS) works for AR7 without the hack to wait for LSR_TEMP and
LSR_THRE.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-13 8:45 ` Thomas Bogendoerfer
@ 2008-03-14 15:46 ` Matteo Croce
2008-03-15 10:40 ` Thomas Bogendoerfer
2008-03-15 11:38 ` Alan Cox
0 siblings, 2 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-14 15:46 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Il Thursday 13 March 2008 09:45:26 Thomas Bogendoerfer ha scritto:
> On Thu, Mar 13, 2008 at 01:38:55AM +0100, Matteo Croce wrote:
> > Il Wednesday 12 March 2008 10:31:46 Thomas Bogendoerfer ha scritto:
> > > > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> > > > index 289942f..869b6df 100644
> > > > --- a/include/linux/serial_core.h
> > > > +++ b/include/linux/serial_core.h
> > > > @@ -40,6 +40,7 @@
> > > > #define PORT_NS16550A 14
> > > > #define PORT_XSCALE 15
> > > > #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
> > > > +#define PORT_AR7 16
> > >
> > > this doesn't look correct.
> > >
> > > Thomas.
> > >
> >
> > Isn't it 16?
>
> PORT_RM9000 is 16, how could PORT_AR7 be 16 as well ? And the 16 for
> PORT_RM9000 is correct in my counting.
>
> Thomas.
>
This is a bit better
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 77f7a7f..a3a271d 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -267,6 +267,13 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
+ [PORT_AR7] = {
+ .name = "TI-AR7",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
};
#if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -2455,7 +2462,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
+#ifdef CONFIG_AR7
+ wait_for_xmitr(up, BOTH_EMPTY);
+#else
wait_for_xmitr(up, UART_LSR_THRE);
+#endif
serial_out(up, UART_TX, ch);
}
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 289942f..15e76c8 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -40,7 +40,8 @@
#define PORT_NS16550A 14
#define PORT_XSCALE 15
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
-#define PORT_MAX_8250 16 /* max port ID */
+#define PORT_AR7 17
+#define PORT_MAX_8250 17 /* max port ID */
/*
* ARM specific type numbers. These are not currently guaranteed
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-14 15:46 ` Matteo Croce
@ 2008-03-15 10:40 ` Thomas Bogendoerfer
2008-03-16 15:45 ` Matteo Croce
2008-03-15 11:38 ` Alan Cox
1 sibling, 1 reply; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-15 10:40 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
On Fri, Mar 14, 2008 at 04:46:09PM +0100, Matteo Croce wrote:
> This is a bit better
is it possible to try without the serial changes first ?
Use
uart_port[0].type = PORT_16550A;
in arch/mips/ar7/platform.c.
Does it work ?
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-14 15:46 ` Matteo Croce
2008-03-15 10:40 ` Thomas Bogendoerfer
@ 2008-03-15 11:38 ` Alan Cox
1 sibling, 0 replies; 34+ messages in thread
From: Alan Cox @ 2008-03-15 11:38 UTC (permalink / raw)
To: Matteo Croce
Cc: Thomas Bogendoerfer, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
> This is a bit better
NAK - especially as there has been a specific response about how to do
this without ifdef hacks in core code.
Alan
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-13 9:01 ` Thomas Bogendoerfer
@ 2008-03-16 15:27 ` Matteo Croce
2008-03-16 15:49 ` Matteo Croce
1 sibling, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-16 15:27 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Alan Cox, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
Il Thursday 13 March 2008 10:01:09 Thomas Bogendoerfer ha scritto:
> On Thu, Mar 13, 2008 at 01:31:54AM +0100, Matteo Croce wrote:
> > Il Wednesday 12 March 2008 12:16:29 Alan Cox ha scritto:
> > > On Wed, 12 Mar 2008 02:30:06 +0100
> > > Matteo Croce <technoboy85@gmail.com> wrote:
> > >
> > > > Ugly but we need it
> > >
> > > Too ugly - NAK
> > >
> > > However please send an explanation of the problem and lets find a nicer
> > > way to do it or bury it in arch code.
> > >
> > >
> >
> > This is my problem:
> >
> > ffi_cmdset_000: DDisabling erae-ssuspend-progrm ddue to code bokeenness.
> > cmdlinparrt partition arssing not avaiabll
> > RedBoo ppartition parsngg not availabl
> > NET: Rgiistered protocl family 1
> > NET: Regsteered protocol ammily 10
> > IPv6 overIPPv4 tunnelingdriiver
> > NET: Regsteered protocolfammily 17
> > FS:: Mounted roo (ssquashfs filessttem) readonly.
> > Freeing nuused kernel meorry: 120k freed
> >
> > I'll try to find a nicer way to fix it
>
> don't use AFE mode and treat it like a normal 16550 (PORT_16550A). You
> could also try to use UPIO_MEM32. That's how my console driver
> (different OS) works for AR7 without the hack to wait for LSR_TEMP and
> LSR_THRE.
>
> Thomas.
>
What about the .fcr field? PORT_16550A uses UART_FCR_R_TRIG_10 while AR7 uses UART_FCR_R_TRIG_00
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-15 10:40 ` Thomas Bogendoerfer
@ 2008-03-16 15:45 ` Matteo Croce
2008-03-18 13:30 ` Thomas Bogendoerfer
2008-03-21 1:55 ` Thomas Bogendoerfer
0 siblings, 2 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-16 15:45 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Il Saturday 15 March 2008 11:40:09 Thomas Bogendoerfer ha scritto:
> On Fri, Mar 14, 2008 at 04:46:09PM +0100, Matteo Croce wrote:
> > This is a bit better
>
> is it possible to try without the serial changes first ?
>
> Use
>
> uart_port[0].type = PORT_16550A;
>
> in arch/mips/ar7/platform.c.
>
> Does it work ?
>
> Thomas.
>
Tried I get teh usual broken serial output:
IP6 oover IPv4 tuneliing driver
NET: eggistered protooll family 17
VFS: Monteed root (squahfss filesystem)reaadonly.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-13 9:01 ` Thomas Bogendoerfer
2008-03-16 15:27 ` Matteo Croce
@ 2008-03-16 15:49 ` Matteo Croce
1 sibling, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-16 15:49 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Alan Cox, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
Il Thursday 13 March 2008 10:01:09 Thomas Bogendoerfer ha scritto:
> On Thu, Mar 13, 2008 at 01:31:54AM +0100, Matteo Croce wrote:
> > Il Wednesday 12 March 2008 12:16:29 Alan Cox ha scritto:
> > > On Wed, 12 Mar 2008 02:30:06 +0100
> > > Matteo Croce <technoboy85@gmail.com> wrote:
> > >
> > > > Ugly but we need it
> > >
> > > Too ugly - NAK
> > >
> > > However please send an explanation of the problem and lets find a nicer
> > > way to do it or bury it in arch code.
> > >
> > >
> >
> > This is my problem:
> >
> > ffi_cmdset_000: DDisabling erae-ssuspend-progrm ddue to code bokeenness.
> > cmdlinparrt partition arssing not avaiabll
> > RedBoo ppartition parsngg not availabl
> > NET: Rgiistered protocl family 1
> > NET: Regsteered protocol ammily 10
> > IPv6 overIPPv4 tunnelingdriiver
> > NET: Regsteered protocolfammily 17
> > FS:: Mounted roo (ssquashfs filessttem) readonly.
> > Freeing nuused kernel meorry: 120k freed
> >
> > I'll try to find a nicer way to fix it
>
> don't use AFE mode and treat it like a normal 16550 (PORT_16550A). You
> could also try to use UPIO_MEM32. That's how my console driver
> (different OS) works for AR7 without the hack to wait for LSR_TEMP and
> LSR_THRE.
>
> Thomas.
>
What do you mean by don't using AFE? Just removing UART_CAP_AFE from the .fcr field?
I've tried but it doesn't work.
I tried also UPIO_MEM32 instead of UPIO_MEM (with PORT_AR7) but it doesn't works
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-16 15:45 ` Matteo Croce
@ 2008-03-18 13:30 ` Thomas Bogendoerfer
2008-03-18 13:43 ` Sergei Shtylyov
2008-03-18 14:01 ` Alan Cox
2008-03-21 1:55 ` Thomas Bogendoerfer
1 sibling, 2 replies; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-18 13:30 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
On Sun, Mar 16, 2008 at 04:45:06PM +0100, Matteo Croce wrote:
> Il Saturday 15 March 2008 11:40:09 Thomas Bogendoerfer ha scritto:
> > On Fri, Mar 14, 2008 at 04:46:09PM +0100, Matteo Croce wrote:
> > > This is a bit better
> >
> > is it possible to try without the serial changes first ?
> >
> > Use
> >
> > uart_port[0].type = PORT_16550A;
> >
> > in arch/mips/ar7/platform.c.
> >
> > Does it work ?
> >
>
> Tried I get teh usual broken serial output:
I just checked the latest AR7/UR8 source, I have, and they don't need
special hacks. This is a 2.6.10 based tree. At that time there was
no serial8250_console_putchar(), console output was done via
serial8250_console_write() without any helper. Before writing to
the UART_TX, wait_for_xmitr() is called. And this wait_for_xmitr() does
check for BOTH_EMPTY.
Is there a good reason, why we don't check for BOTH_EMPTY in
serial8250_console_putchar() ? To match the 2.6.10 behaviour we
would need that and this would fix the AR7 case without any
special handling.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-18 13:30 ` Thomas Bogendoerfer
@ 2008-03-18 13:43 ` Sergei Shtylyov
2008-03-18 13:49 ` Sergei Shtylyov
2008-03-18 14:01 ` Alan Cox
1 sibling, 1 reply; 34+ messages in thread
From: Sergei Shtylyov @ 2008-03-18 13:43 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Matteo Croce, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
Hello.
Thomas Bogendoerfer wrote:
>>Il Saturday 15 March 2008 11:40:09 Thomas Bogendoerfer ha scritto:
>>>On Fri, Mar 14, 2008 at 04:46:09PM +0100, Matteo Croce wrote:
>>>>This is a bit better
>>>is it possible to try without the serial changes first ?
>>>Use
>>> uart_port[0].type = PORT_16550A;
>>>in arch/mips/ar7/platform.c.
>>>Does it work ?
>>Tried I get teh usual broken serial output:
> I just checked the latest AR7/UR8 source, I have, and they don't need
> special hacks. This is a 2.6.10 based tree. At that time there was
> no serial8250_console_putchar(), console output was done via
> serial8250_console_write() without any helper. Before writing to
> the UART_TX, wait_for_xmitr() is called. And this wait_for_xmitr() does
> check for BOTH_EMPTY.
> Is there a good reason, why we don't check for BOTH_EMPTY in
> serial8250_console_putchar() ?
I guess transmission will be slower if you check both THRE and TSRE
conditions.
> To match the 2.6.10 behaviour we
> would need that and this would fix the AR7 case without any
> special handling.
AR7 case seems to be the case of bad hardware, and so require special
handling...
> Thomas.
WBR, Sergei
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-18 13:43 ` Sergei Shtylyov
@ 2008-03-18 13:49 ` Sergei Shtylyov
0 siblings, 0 replies; 34+ messages in thread
From: Sergei Shtylyov @ 2008-03-18 13:49 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Matteo Croce, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
Hi, I wrote:
>>>>> This is a bit better
>>>> is it possible to try without the serial changes first ?
>>>> Use
>>>> uart_port[0].type = PORT_16550A;
>>>> in arch/mips/ar7/platform.c.
>>>> Does it work ?
>>> Tried I get teh usual broken serial output:
>> I just checked the latest AR7/UR8 source, I have, and they don't need
>> special hacks. This is a 2.6.10 based tree. At that time there was
>> no serial8250_console_putchar(), console output was done via
>> serial8250_console_write() without any helper. Before writing to the
>> UART_TX, wait_for_xmitr() is called. And this wait_for_xmitr() does
>> check for BOTH_EMPTY.
>> Is there a good reason, why we don't check for BOTH_EMPTY in
>> serial8250_console_putchar() ?
> I guess transmission will be slower if you check both THRE and TSRE
> conditions.
... and since TX FIFO is in use, it must be even worse since you're only
able to load TX FIFO in the short time slots while TX shift register is empty
-- quite possibly that this condition will turn to virtually no TX FIFO as
these slots my be to short. BTW, does turning off TX FIFO help?
WBR, Sergei
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-18 13:30 ` Thomas Bogendoerfer
2008-03-18 13:43 ` Sergei Shtylyov
@ 2008-03-18 14:01 ` Alan Cox
2008-03-18 14:01 ` Alan Cox
2008-03-18 15:28 ` Thomas Bogendoerfer
1 sibling, 2 replies; 34+ messages in thread
From: Alan Cox @ 2008-03-18 14:01 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Matteo Croce, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
> Is there a good reason, why we don't check for BOTH_EMPTY in
> serial8250_console_putchar() ? To match the 2.6.10 behaviour we
A very good one - we have at least 1 byte of FIFO and the serial-ethernet
magic console devices also use that fifo emptying entirely to deduce when
to send a new packet.
> would need that and this would fix the AR7 case without any
> special handling.
If the AR7 is an 8250 why does it need special handling? and indeed why
does serial work on it except for console - or does that fail too.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-18 14:01 ` Alan Cox
@ 2008-03-18 14:01 ` Alan Cox
2008-03-18 15:28 ` Thomas Bogendoerfer
1 sibling, 0 replies; 34+ messages in thread
From: Alan Cox @ 2008-03-18 14:01 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Matteo Croce, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
> Is there a good reason, why we don't check for BOTH_EMPTY in
> serial8250_console_putchar() ? To match the 2.6.10 behaviour we
A very good one - we have at least 1 byte of FIFO and the serial-ethernet
magic console devices also use that fifo emptying entirely to deduce when
to send a new packet.
> would need that and this would fix the AR7 case without any
> special handling.
If the AR7 is an 8250 why does it need special handling? and indeed why
does serial work on it except for console - or does that fail too.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-18 14:01 ` Alan Cox
2008-03-18 14:01 ` Alan Cox
@ 2008-03-18 15:28 ` Thomas Bogendoerfer
1 sibling, 0 replies; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-18 15:28 UTC (permalink / raw)
To: Alan Cox
Cc: Matteo Croce, linux-mips, Florian Fainelli, Felix Fietkau,
Nicolas Thill, linux-serial, Andrew Morton
On Tue, Mar 18, 2008 at 02:01:33PM +0000, Alan Cox wrote:
> > Is there a good reason, why we don't check for BOTH_EMPTY in
> > serial8250_console_putchar() ? To match the 2.6.10 behaviour we
>
> A very good one - we have at least 1 byte of FIFO and the serial-ethernet
> magic console devices also use that fifo emptying entirely to deduce when
> to send a new packet.
ok, now I understand.
> > would need that and this would fix the AR7 case without any
> > special handling.
>
> If the AR7 is an 8250 why does it need special handling? and indeed why
> does serial work on it except for console - or does that fail too.
well TI calls it a 16550A and I still wonder about the reported
problems. Looks like I need to dig a little bit deeper...
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [PATCH][MIPS][5/6]: AR7: serial hack
@ 2008-03-18 15:40 Nico Coesel
2008-03-18 15:40 ` Nico Coesel
0 siblings, 1 reply; 34+ messages in thread
From: Nico Coesel @ 2008-03-18 15:40 UTC (permalink / raw)
To: linux-mips
Hello all,
I didn't follow the entire discussion, but I might have similar problems
on the AU1100 SoC. The AU1100 also has 16550 style serial ports. The
serial console doesn't work even though I specify console=/dev/ttyS0 on
the kernel command line. Once a getty is started, the serial port is
active and working fine.
Nico
> -----Oorspronkelijk bericht-----
> Van: linux-mips-bounce@linux-mips.org
> [mailto:linux-mips-bounce@linux-mips.org] Namens Alan Cox
> Verzonden: dinsdag 18 maart 2008 15:02
> Aan: Thomas Bogendoerfer
> CC: Matteo Croce; linux-mips@linux-mips.org; Florian
> Fainelli; Felix Fietkau; Nicolas Thill;
> linux-serial@vger.kernel.org; Andrew Morton
> Onderwerp: Re: [PATCH][MIPS][5/6]: AR7: serial hack
>
> > Is there a good reason, why we don't check for BOTH_EMPTY in
> > serial8250_console_putchar() ? To match the 2.6.10 behaviour we
>
> A very good one - we have at least 1 byte of FIFO and the
> serial-ethernet magic console devices also use that fifo
> emptying entirely to deduce when to send a new packet.
>
> > would need that and this would fix the AR7 case without any special
> > handling.
>
> If the AR7 is an 8250 why does it need special handling? and
> indeed why does serial work on it except for console - or
> does that fail too.
>
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-18 15:40 Nico Coesel
@ 2008-03-18 15:40 ` Nico Coesel
0 siblings, 0 replies; 34+ messages in thread
From: Nico Coesel @ 2008-03-18 15:40 UTC (permalink / raw)
To: linux-mips
Hello all,
I didn't follow the entire discussion, but I might have similar problems
on the AU1100 SoC. The AU1100 also has 16550 style serial ports. The
serial console doesn't work even though I specify console=/dev/ttyS0 on
the kernel command line. Once a getty is started, the serial port is
active and working fine.
Nico
> -----Oorspronkelijk bericht-----
> Van: linux-mips-bounce@linux-mips.org
> [mailto:linux-mips-bounce@linux-mips.org] Namens Alan Cox
> Verzonden: dinsdag 18 maart 2008 15:02
> Aan: Thomas Bogendoerfer
> CC: Matteo Croce; linux-mips@linux-mips.org; Florian
> Fainelli; Felix Fietkau; Nicolas Thill;
> linux-serial@vger.kernel.org; Andrew Morton
> Onderwerp: Re: [PATCH][MIPS][5/6]: AR7: serial hack
>
> > Is there a good reason, why we don't check for BOTH_EMPTY in
> > serial8250_console_putchar() ? To match the 2.6.10 behaviour we
>
> A very good one - we have at least 1 byte of FIFO and the
> serial-ethernet magic console devices also use that fifo
> emptying entirely to deduce when to send a new packet.
>
> > would need that and this would fix the AR7 case without any special
> > handling.
>
> If the AR7 is an 8250 why does it need special handling? and
> indeed why does serial work on it except for console - or
> does that fail too.
>
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-16 15:45 ` Matteo Croce
2008-03-18 13:30 ` Thomas Bogendoerfer
@ 2008-03-21 1:55 ` Thomas Bogendoerfer
2008-03-27 21:14 ` Matteo Croce
2008-03-27 21:17 ` Matteo Croce
1 sibling, 2 replies; 34+ messages in thread
From: Thomas Bogendoerfer @ 2008-03-21 1:55 UTC (permalink / raw)
To: Matteo Croce
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
On Sun, Mar 16, 2008 at 04:45:06PM +0100, Matteo Croce wrote:
> Tried I get teh usual broken serial output:
>
> IP6 oover IPv4 tuneliing driver
> NET: eggistered protooll family 17
> VFS: Monteed root (squahfss filesystem)reaadonly.
Linux version 2.6.25-rc6-00000-g151de9e-dirty (tsbogend@solo.franken.de)
(gcc version 3.3.3 (Debian 20040320)) #29 Fri Mar 21 02:40:21 CET 2008
console [early0] enabled
CPU revision is: 00018448 (MIPS 4KEc)
TI AR7 (Unknown), ID: 0x5700, Revision: 0x00
Determined physical RAM map:
memory: 02000000 @ 14000000 (usable)
Zone PFN ranges:
Normal 81920 -> 90112
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 81920 -> 90112
Built 1 zonelists in Zone order, mobility grouping on. Total pages:
8128
Kernel command line: console=ttyS0,115200
Primary instruction cache 16kB, VIPT, 4-way, linesize 16 bytes.
Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 16 bytes
Synthesized clear page handler (26 instructions).
Synthesized copy page handler (46 instructions).
PID hash table entries: 128 (order: 7, 512 bytes)
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 29700k/32768k available (2075k kernel code, 3068k reserved, 466k
data, 136k init, 0k highmem)
Mount-cache hash table entries: 512
net_namespace: 152 bytes
NET: Registered protocol family 16
SCSI subsystem initialized
NET: Registered protocol family 2
Time: MIPS clocksource has been installed.
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing
disabled
serial8250: ttyS0 at MMIO 0x8610e03 (irq = 15) is a 16550A
console handover: boot [early0] -> real [ttyS0]
serial8250: ttyS1 at MMIO 0x8610f03 (irq = 16) is a 16550A
loop: module loaded
Fixed MDIO Bus: probed
ar7_wdt: failed to unlock WDT disable reg
ar7_wdt: failed to unlock WDT prescale reg
ar7_wdt: failed to unlock WDT change reg
ar7_wdt: timer margin 59 seconds (prescale 65535, change 57180, freq
62500000)
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
Root-NFS: No NFS server available, giving up.
VFS: Unable to mount root fs via NFS, trying floppy.
List of all partitions:
No filesystem could mount root, tried:
Kernel panic - not syncing: VFS: Unable to mount root fs on
unknown-block(2,0)
Rebooting in 3 seconds..
I don't see any problems with using PORT_16550A. What I'm still
wondering how your kernel could work at all, since there is a
missing case for setting up the TLB refill handler. Something like
the patch below.
And most of the AR7 device driver code will not work for big endian.
The log above is from a big endian AR7 system, where I needed
to disable CPMAC to get it booting that far.
Thomas.
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 3a93d4c..382738c 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -307,6 +307,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
case CPU_R12000:
case CPU_R14000:
case CPU_4KC:
+ case CPU_4KEC:
case CPU_SB1:
case CPU_SB1A:
case CPU_4KSC:
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-21 1:55 ` Thomas Bogendoerfer
@ 2008-03-27 21:14 ` Matteo Croce
2008-03-27 21:17 ` Matteo Croce
1 sibling, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-27 21:14 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Il Friday 21 March 2008 02:55:40 Thomas Bogendoerfer ha scritto:
> On Sun, Mar 16, 2008 at 04:45:06PM +0100, Matteo Croce wrote:
> > Tried I get teh usual broken serial output:
> >
> > IP6 oover IPv4 tuneliing driver
> > NET: eggistered protooll family 17
> > VFS: Monteed root (squahfss filesystem)reaadonly.
>
> Linux version 2.6.25-rc6-00000-g151de9e-dirty (tsbogend@solo.franken.de)
> (gcc version 3.3.3 (Debian 20040320)) #29 Fri Mar 21 02:40:21 CET 2008
> console [early0] enabled
> CPU revision is: 00018448 (MIPS 4KEc)
> TI AR7 (Unknown), ID: 0x5700, Revision: 0x00
> Determined physical RAM map:
> memory: 02000000 @ 14000000 (usable)
> Zone PFN ranges:
> Normal 81920 -> 90112
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
> 0: 81920 -> 90112
> Built 1 zonelists in Zone order, mobility grouping on. Total pages:
> 8128
> Kernel command line: console=ttyS0,115200
> Primary instruction cache 16kB, VIPT, 4-way, linesize 16 bytes.
> Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 16 bytes
> Synthesized clear page handler (26 instructions).
> Synthesized copy page handler (46 instructions).
> PID hash table entries: 128 (order: 7, 512 bytes)
> Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
> Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
> Memory: 29700k/32768k available (2075k kernel code, 3068k reserved, 466k
> data, 136k init, 0k highmem)
> Mount-cache hash table entries: 512
> net_namespace: 152 bytes
> NET: Registered protocol family 16
> SCSI subsystem initialized
> NET: Registered protocol family 2
> Time: MIPS clocksource has been installed.
> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
> TCP established hash table entries: 1024 (order: 1, 8192 bytes)
> TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
> TCP: Hash tables configured (established 1024 bind 1024)
> TCP reno registered
> io scheduler noop registered
> io scheduler anticipatory registered (default)
> io scheduler deadline registered
> Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing
> disabled
> serial8250: ttyS0 at MMIO 0x8610e03 (irq = 15) is a 16550A
> console handover: boot [early0] -> real [ttyS0]
> serial8250: ttyS1 at MMIO 0x8610f03 (irq = 16) is a 16550A
> loop: module loaded
> Fixed MDIO Bus: probed
> ar7_wdt: failed to unlock WDT disable reg
> ar7_wdt: failed to unlock WDT prescale reg
> ar7_wdt: failed to unlock WDT change reg
> ar7_wdt: timer margin 59 seconds (prescale 65535, change 57180, freq
> 62500000)
> TCP cubic registered
> NET: Registered protocol family 1
> NET: Registered protocol family 17
> RPC: Registered udp transport module.
> RPC: Registered tcp transport module.
> Root-NFS: No NFS server available, giving up.
> VFS: Unable to mount root fs via NFS, trying floppy.
> List of all partitions:
> No filesystem could mount root, tried:
> Kernel panic - not syncing: VFS: Unable to mount root fs on
> unknown-block(2,0)
> Rebooting in 3 seconds..
>
> I don't see any problems with using PORT_16550A. What I'm still
> wondering how your kernel could work at all, since there is a
> missing case for setting up the TLB refill handler. Something like
> the patch below.
>
> And most of the AR7 device driver code will not work for big endian.
> The log above is from a big endian AR7 system, where I needed
> to disable CPMAC to get it booting that far.
>
> Thomas.
>
>
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 3a93d4c..382738c 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -307,6 +307,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
> case CPU_R12000:
> case CPU_R14000:
> case CPU_4KC:
> + case CPU_4KEC:
> case CPU_SB1:
> case CPU_SB1A:
> case CPU_4KSC:
>
>
Actually we use this for 2.6.24:
Index: linux-2.6.24/arch/mips/mm/tlbex.c
===================================================================
--- linux-2.6.24/arch/mips/mm/tlbex.c 2007-10-10 04:31:38.000000000 +0800
+++ linux-2.6.24/arch/mips/mm/tlbex.c 2007-10-10 13:52:34.000000000 +0800
@@ -902,7 +902,6 @@
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
- case CPU_4KC:
case CPU_SB1:
case CPU_SB1A:
case CPU_4KSC:
@@ -933,6 +932,7 @@
tlbw(p);
break;
+ case CPU_4KC:
case CPU_4KEC:
case CPU_24K:
case CPU_34K:
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH][MIPS][5/6]: AR7: serial hack
2008-03-21 1:55 ` Thomas Bogendoerfer
2008-03-27 21:14 ` Matteo Croce
@ 2008-03-27 21:17 ` Matteo Croce
1 sibling, 0 replies; 34+ messages in thread
From: Matteo Croce @ 2008-03-27 21:17 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: linux-mips, Florian Fainelli, Felix Fietkau, Nicolas Thill,
linux-serial, Andrew Morton
Il Friday 21 March 2008 02:55:40 Thomas Bogendoerfer ha scritto:
> On Sun, Mar 16, 2008 at 04:45:06PM +0100, Matteo Croce wrote:
> > Tried I get teh usual broken serial output:
> >
> > IP6 oover IPv4 tuneliing driver
> > NET: eggistered protooll family 17
> > VFS: Monteed root (squahfss filesystem)reaadonly.
>
> Linux version 2.6.25-rc6-00000-g151de9e-dirty (tsbogend@solo.franken.de)
> (gcc version 3.3.3 (Debian 20040320)) #29 Fri Mar 21 02:40:21 CET 2008
> console [early0] enabled
> CPU revision is: 00018448 (MIPS 4KEc)
> TI AR7 (Unknown), ID: 0x5700, Revision: 0x00
> Determined physical RAM map:
> memory: 02000000 @ 14000000 (usable)
> Zone PFN ranges:
> Normal 81920 -> 90112
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
> 0: 81920 -> 90112
> Built 1 zonelists in Zone order, mobility grouping on. Total pages:
> 8128
> Kernel command line: console=ttyS0,115200
> Primary instruction cache 16kB, VIPT, 4-way, linesize 16 bytes.
> Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 16 bytes
> Synthesized clear page handler (26 instructions).
> Synthesized copy page handler (46 instructions).
> PID hash table entries: 128 (order: 7, 512 bytes)
> Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
> Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
> Memory: 29700k/32768k available (2075k kernel code, 3068k reserved, 466k
> data, 136k init, 0k highmem)
> Mount-cache hash table entries: 512
> net_namespace: 152 bytes
> NET: Registered protocol family 16
> SCSI subsystem initialized
> NET: Registered protocol family 2
> Time: MIPS clocksource has been installed.
> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
> TCP established hash table entries: 1024 (order: 1, 8192 bytes)
> TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
> TCP: Hash tables configured (established 1024 bind 1024)
> TCP reno registered
> io scheduler noop registered
> io scheduler anticipatory registered (default)
> io scheduler deadline registered
> Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing
> disabled
> serial8250: ttyS0 at MMIO 0x8610e03 (irq = 15) is a 16550A
> console handover: boot [early0] -> real [ttyS0]
> serial8250: ttyS1 at MMIO 0x8610f03 (irq = 16) is a 16550A
> loop: module loaded
> Fixed MDIO Bus: probed
> ar7_wdt: failed to unlock WDT disable reg
> ar7_wdt: failed to unlock WDT prescale reg
> ar7_wdt: failed to unlock WDT change reg
> ar7_wdt: timer margin 59 seconds (prescale 65535, change 57180, freq
> 62500000)
> TCP cubic registered
> NET: Registered protocol family 1
> NET: Registered protocol family 17
> RPC: Registered udp transport module.
> RPC: Registered tcp transport module.
> Root-NFS: No NFS server available, giving up.
> VFS: Unable to mount root fs via NFS, trying floppy.
> List of all partitions:
> No filesystem could mount root, tried:
> Kernel panic - not syncing: VFS: Unable to mount root fs on
> unknown-block(2,0)
> Rebooting in 3 seconds..
>
> I don't see any problems with using PORT_16550A. What I'm still
> wondering how your kernel could work at all, since there is a
> missing case for setting up the TLB refill handler. Something like
> the patch below.
>
> And most of the AR7 device driver code will not work for big endian.
> The log above is from a big endian AR7 system, where I needed
> to disable CPMAC to get it booting that far.
>
> Thomas.
>
>
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 3a93d4c..382738c 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -307,6 +307,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
> case CPU_R12000:
> case CPU_R14000:
> case CPU_4KC:
> + case CPU_4KEC:
> case CPU_SB1:
> case CPU_SB1A:
> case CPU_4KSC:
>
>
Actually we use this for 2.6.24:
Index: linux-2.6.24/arch/mips/mm/tlbex.c
===================================================================
--- linux-2.6.24/arch/mips/mm/tlbex.c 2007-10-10 04:31:38.000000000 +0800
+++ linux-2.6.24/arch/mips/mm/tlbex.c 2007-10-10 13:52:34.000000000 +0800
@@ -902,7 +902,6 @@
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
- case CPU_4KC:
case CPU_SB1:
case CPU_SB1A:
case CPU_4KSC:
@@ -933,6 +932,7 @@
tlbw(p);
break;
+ case CPU_4KC:
case CPU_4KEC:
case CPU_24K:
case CPU_34K:
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2008-03-27 21:17 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-11 0:48 [PATCH][MIPS][0/6] AR7: AR7 strikes back Matteo Croce
2007-10-11 0:50 ` [PATCH][MIPS][1/6] AR7: core support Matteo Croce
2007-10-11 0:54 ` [PATCH][MIPS][2/6] AR7: VLYNQ bus Matteo Croce
2007-10-11 0:55 ` [PATCH][MIPS][3/6] AR7: mtd partition map Matteo Croce
2007-10-11 0:57 ` [PATCH][MIPS][4/6] AR7: gpio char device Matteo Croce
2007-10-11 0:59 ` [PATCH][MIPS][5/6] AR7: serial hack Matteo Croce
2007-10-11 1:01 ` [PATCH][MIPS][6/6] AR7: leds driver Matteo Croce
2007-10-18 8:22 ` [PATCH][MIPS][0/6] AR7: AR7 strikes back Florian Fainelli
-- strict thread matches above, loose matches on Subject: below --
2007-12-27 18:19 [PATCH][MIPS][0/6]: AR7 refresh Matteo Croce
2007-12-27 18:27 ` [PATCH][MIPS][5/6]: AR7: serial hack Matteo Croce
2007-12-28 12:13 ` Sergei Shtylyov
2008-03-12 1:21 [PATCH][MIPS][0/6]: AR7 final Matteo Croce
2008-03-12 1:30 ` [PATCH][MIPS][5/6]: AR7: serial hack Matteo Croce
2008-03-12 9:31 ` Thomas Bogendoerfer
2008-03-13 0:38 ` Matteo Croce
2008-03-13 8:45 ` Thomas Bogendoerfer
2008-03-14 15:46 ` Matteo Croce
2008-03-15 10:40 ` Thomas Bogendoerfer
2008-03-16 15:45 ` Matteo Croce
2008-03-18 13:30 ` Thomas Bogendoerfer
2008-03-18 13:43 ` Sergei Shtylyov
2008-03-18 13:49 ` Sergei Shtylyov
2008-03-18 14:01 ` Alan Cox
2008-03-18 14:01 ` Alan Cox
2008-03-18 15:28 ` Thomas Bogendoerfer
2008-03-21 1:55 ` Thomas Bogendoerfer
2008-03-27 21:14 ` Matteo Croce
2008-03-27 21:17 ` Matteo Croce
2008-03-15 11:38 ` Alan Cox
2008-03-12 11:16 ` Alan Cox
2008-03-13 0:31 ` Matteo Croce
2008-03-13 9:01 ` Thomas Bogendoerfer
2008-03-16 15:27 ` Matteo Croce
2008-03-16 15:49 ` Matteo Croce
2008-03-18 15:40 Nico Coesel
2008-03-18 15:40 ` Nico Coesel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox