1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-24 03:30:37 +02:00

[lantiq] adds 3.6 files, patches and config

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34061 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
blogic 2012-11-02 20:07:26 +00:00
parent 1048c7b452
commit 4f2c17075b
35 changed files with 9938 additions and 0 deletions

View File

@ -0,0 +1,154 @@
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_BCMA_POSSIBLE=y
CONFIG_BUILDTIME_EXTABLE_SORT=y
CONFIG_CEVT_R4K=y
CONFIG_CEVT_R4K_LIB=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_MIPS32=y
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
CONFIG_CPU_MIPSR2=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CSRC_R4K=y
CONFIG_CSRC_R4K_LIB=y
# CONFIG_DEBUG_PINCTRL is not set
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DTC=y
# CONFIG_DT_EASY50712 is not set
CONFIG_DT_EASY80920=y
CONFIG_EARLY_PRINTK=y
CONFIG_ETHERNET_PACKET_MANGLE=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_MM_LANTIQ=y
CONFIG_GPIO_STP_XWAY=y
CONFIG_GPIO_SYSFS=y
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_GENERIC_HARDIRQS=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_IRQ_WORK=y
CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=y
CONFIG_HZ=250
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
CONFIG_IMAGE_CMDLINE_HACK=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQ_CPU=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_LANTIQ=y
CONFIG_LANTIQ_ETOP=y
CONFIG_LANTIQ_PHY=y
CONFIG_LANTIQ_WDT=y
CONFIG_LANTIQ_XRX200=y
CONFIG_LEDS_GPIO=y
# CONFIG_MACH_LOONGSON1 is not set
CONFIG_MDIO_BOARDINFO=y
# CONFIG_MDIO_BUS_MUX_GPIO is not set
CONFIG_MIPS=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_MIPS_MACHINE is not set
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_VPE_LOADER is not set
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_LANTIQ=y
CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_DEVICE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OF_PCI=y
CONFIG_OF_PCI_IRQ=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_LANTIQ=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
CONFIG_PINCONF=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_LANTIQ=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PINCTRL_XWAY=y
CONFIG_PINMUX=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_PSB6970_PHY=y
CONFIG_RTL8366RB_PHY=y
CONFIG_RTL8366_SMI=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_LANTIQ=y
# CONFIG_SOC_AMAZON_SE is not set
# CONFIG_SOC_FALCON is not set
CONFIG_SOC_TYPE_XWAY=y
CONFIG_SOC_XWAY=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWCONFIG=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USE_OF=y
CONFIG_XZ_DEC=y
CONFIG_ZONE_DMA_FLAG=0

View File

@ -0,0 +1,34 @@
From 98dbc5764d8b6fa9cabe316fe725281703bf0fc6 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 24 Jul 2012 08:56:41 +0200
Subject: [PATCH] MIPS: lantiq: explicitly enable clkout generation
Previously we relied on the bootloader to have enabled this bit. However some
bootloaders seem to not enable this for us.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4120/
---
arch/mips/lantiq/xway/sysctrl.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index befbb76..8430983 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -187,10 +187,12 @@ static int clkout_enable(struct clk *clk)
for (i = 0; i < 4; i++) {
if (clk->rates[i] == clk->rate) {
int shift = 14 - (2 * clk->module);
+ int enable = 7 - clk->module;
unsigned int val = ltq_cgu_r32(ifccr);
val &= ~(3 << shift);
val |= i << shift;
+ val |= enable;
ltq_cgu_w32(val, ifccr);
return 0;
}
--
1.7.10.4

View File

@ -0,0 +1,195 @@
From 61fa969f27ec58296544bf94d058f3aa704cb8d9 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 11:39:57 +0000
Subject: [PATCH 2/9] MIPS: lantiq: split up IRQ IM ranges
Up to now all our SoCs had the 5 IM ranges in a consecutive order. To accomodate
the SVIP we need to support IM ranges that are scattered inside the register range.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4237/
---
.../include/asm/mach-lantiq/falcon/falcon_irq.h | 2 +
.../mips/include/asm/mach-lantiq/xway/lantiq_irq.h | 2 +
arch/mips/lantiq/irq.c | 60 +++++++++++---------
3 files changed, 36 insertions(+), 28 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
index 318f982..c6b63a4 100644
--- a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
@@ -20,4 +20,6 @@
#define MIPS_CPU_TIMER_IRQ 7
+#define MAX_IM 5
+
#endif /* _FALCON_IRQ__ */
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
index aa0b3b8..5eadfe5 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -21,4 +21,6 @@
#define MIPS_CPU_TIMER_IRQ 7
+#define MAX_IM 5
+
#endif
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 57c1a4e..a2699a70 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -55,8 +55,8 @@
*/
#define LTQ_ICU_EBU_IRQ 22
-#define ltq_icu_w32(x, y) ltq_w32((x), ltq_icu_membase + (y))
-#define ltq_icu_r32(x) ltq_r32(ltq_icu_membase + (x))
+#define ltq_icu_w32(m, x, y) ltq_w32((x), ltq_icu_membase[m] + (y))
+#define ltq_icu_r32(m, x) ltq_r32(ltq_icu_membase[m] + (x))
#define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y))
#define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x))
@@ -82,17 +82,17 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
};
static int exin_avail;
-static void __iomem *ltq_icu_membase;
+static void __iomem *ltq_icu_membase[MAX_IM];
static void __iomem *ltq_eiu_membase;
void ltq_disable_irq(struct irq_data *d)
{
u32 ier = LTQ_ICU_IM0_IER;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
+ int im = offset / INT_NUM_IM_OFFSET;
- ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
- ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier);
+ ltq_icu_w32(im, ltq_icu_r32(im, ier) & ~BIT(offset), ier);
}
void ltq_mask_and_ack_irq(struct irq_data *d)
@@ -100,32 +100,31 @@ void ltq_mask_and_ack_irq(struct irq_data *d)
u32 ier = LTQ_ICU_IM0_IER;
u32 isr = LTQ_ICU_IM0_ISR;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
+ int im = offset / INT_NUM_IM_OFFSET;
- ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
- isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
- ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier);
- ltq_icu_w32(BIT(offset), isr);
+ ltq_icu_w32(im, ltq_icu_r32(im, ier) & ~BIT(offset), ier);
+ ltq_icu_w32(im, BIT(offset), isr);
}
static void ltq_ack_irq(struct irq_data *d)
{
u32 isr = LTQ_ICU_IM0_ISR;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
+ int im = offset / INT_NUM_IM_OFFSET;
- isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
- ltq_icu_w32(BIT(offset), isr);
+ ltq_icu_w32(im, BIT(offset), isr);
}
void ltq_enable_irq(struct irq_data *d)
{
u32 ier = LTQ_ICU_IM0_IER;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
+ int im = offset / INT_NUM_IM_OFFSET;
- ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
- ltq_icu_w32(ltq_icu_r32(ier) | BIT(offset), ier);
+ ltq_icu_w32(im, ltq_icu_r32(im, ier) | BIT(offset), ier);
}
static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
@@ -192,7 +191,7 @@ static void ltq_hw_irqdispatch(int module)
{
u32 irq;
- irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
+ irq = ltq_icu_r32(module, LTQ_ICU_IM0_IOSR);
if (irq == 0)
return;
@@ -275,7 +274,7 @@ asmlinkage void plat_irq_dispatch(void)
do_IRQ(MIPS_CPU_TIMER_IRQ);
goto out;
} else {
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < MAX_IM; i++) {
if (pending & (CAUSEF_IP2 << i)) {
ltq_hw_irqdispatch(i);
goto out;
@@ -318,15 +317,19 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
struct resource res;
int i;
- if (of_address_to_resource(node, 0, &res))
- panic("Failed to get icu memory range");
+ for (i = 0; i < MAX_IM; i++) {
+ if (of_address_to_resource(node, i, &res))
+ panic("Failed to get icu memory range");
- if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
- pr_err("Failed to request icu memory");
+ if (request_mem_region(res.start, resource_size(&res),
+ res.name) < 0)
+ pr_err("Failed to request icu memory");
- ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res));
- if (!ltq_icu_membase)
- panic("Failed to remap icu memory");
+ ltq_icu_membase[i] = ioremap_nocache(res.start,
+ resource_size(&res));
+ if (!ltq_icu_membase[i])
+ panic("Failed to remap icu memory");
+ }
/* the external interrupts are optional and xway only */
eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu");
@@ -351,17 +354,17 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
}
/* turn off all irqs by default */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < MAX_IM; i++) {
/* make sure all irqs are turned off by default */
- ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
+ ltq_icu_w32(i, 0, LTQ_ICU_IM0_IER);
/* clear all possibly pending interrupts */
- ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
+ ltq_icu_w32(i, ~0, LTQ_ICU_IM0_ISR);
}
mips_cpu_irq_init();
- for (i = 2; i <= 6; i++)
- setup_irq(i, &cascade);
+ for (i = 0; i < MAX_IM; i++)
+ setup_irq(i + 2, &cascade);
if (cpu_has_vint) {
pr_info("Setting up vectored interrupts\n");
@@ -373,7 +376,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
set_vi_handler(7, ltq_hw5_irqdispatch);
}
- irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET,
+ irq_domain_add_linear(node,
+ (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
&irq_domain_ops, 0);
#if defined(CONFIG_MIPS_MT_SMP)
--
1.7.10.4

View File

@ -0,0 +1,84 @@
From c2c9c788b91218bccbb9ac31539ffa577fe502bf Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 08:09:20 +0000
Subject: [PATCH 3/9] MIPS: lantiq: timer irq can be different to 7
The SVIP SoC has its timer IRQ on a different IRQ than 7. Fix up the irq
code to be able to handle this.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4229/
---
arch/mips/lantiq/irq.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index a2699a70..0cec43d 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -84,6 +84,7 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
static int exin_avail;
static void __iomem *ltq_icu_membase[MAX_IM];
static void __iomem *ltq_eiu_membase;
+static struct irq_domain *ltq_domain;
void ltq_disable_irq(struct irq_data *d)
{
@@ -219,10 +220,14 @@ DEFINE_HWx_IRQDISPATCH(2)
DEFINE_HWx_IRQDISPATCH(3)
DEFINE_HWx_IRQDISPATCH(4)
+#if MIPS_CPU_TIMER_IRQ == 7
static void ltq_hw5_irqdispatch(void)
{
do_IRQ(MIPS_CPU_TIMER_IRQ);
}
+#else
+DEFINE_HWx_IRQDISPATCH(5)
+#endif
#ifdef CONFIG_MIPS_MT_SMP
void __init arch_init_ipiirq(int irq, struct irqaction *action)
@@ -270,7 +275,7 @@ asmlinkage void plat_irq_dispatch(void)
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
unsigned int i;
- if (pending & CAUSEF_IP7) {
+ if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) {
do_IRQ(MIPS_CPU_TIMER_IRQ);
goto out;
} else {
@@ -376,7 +381,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
set_vi_handler(7, ltq_hw5_irqdispatch);
}
- irq_domain_add_linear(node,
+ ltq_domain = irq_domain_add_linear(node,
(MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
&irq_domain_ops, 0);
@@ -401,12 +406,20 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
/* tell oprofile which irq to use */
cp0_perfcount_irq = LTQ_PERF_IRQ;
+
+ /*
+ * if the timer irq is not one of the mips irqs we need to
+ * create a mapping
+ */
+ if (MIPS_CPU_TIMER_IRQ != 7)
+ irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ);
+
return 0;
}
unsigned int __cpuinit get_c0_compare_int(void)
{
- return CP0_LEGACY_COMPARE_IRQ;
+ return MIPS_CPU_TIMER_IRQ;
}
static struct of_device_id __initdata of_irq_ids[] = {
--
1.7.10.4

View File

@ -0,0 +1,30 @@
From 9c1628b603ee9d2bb220be0400c5dc6950cf012b Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 08:09:21 +0000
Subject: [PATCH 4/9] MIPS: lantiq: dont register irq_chip for the irq cascade
We dont want to register the irq_chip for the MIPS IRQ cascade.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4230/
---
arch/mips/lantiq/irq.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 0cec43d..87f15d6 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -297,6 +297,9 @@ static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
struct irq_chip *chip = &ltq_irq_type;
int i;
+ if (hw < MIPS_CPU_IRQ_CASCADE)
+ return 0;
+
for (i = 0; i < exin_avail; i++)
if (hw == ltq_eiu_irq[i])
chip = &ltq_eiu_type;
--
1.7.10.4

View File

@ -0,0 +1,31 @@
From 70ec9054e7a65c878298666083f7d5b70ccf9032 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 08:09:22 +0000
Subject: [PATCH 5/9] MIPS: lantiq: external irq sources are not loaded
properly
Support for the external interrupt unit was broken when the code was converted
to devicetree support.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4231/
---
arch/mips/lantiq/irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 87f15d6..f36acd1 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -341,7 +341,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
/* the external interrupts are optional and xway only */
eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu");
- if (eiu_node && of_address_to_resource(eiu_node, 0, &res)) {
+ if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
/* find out how many external irq sources we have */
const __be32 *count = of_get_property(node,
"lantiq,count", NULL);
--
1.7.10.4

View File

@ -0,0 +1,39 @@
From f8cd170dabeca90c976e6487ba7a8a7752aae571 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 11:39:56 +0000
Subject: [PATCH 6/9] MIPS: lantiq: adds support for nmi and ejtag bootrom
vectors
Register nmi and ejtag bootrom vectors for FALC-ON SoC.
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4238/
---
arch/mips/lantiq/falcon/prom.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c
index c1d278f..aa94979 100644
--- a/arch/mips/lantiq/falcon/prom.c
+++ b/arch/mips/lantiq/falcon/prom.c
@@ -8,6 +8,8 @@
*/
#include <linux/kernel.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
#include <asm/io.h>
#include <lantiq_soc.h>
@@ -84,4 +86,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
unreachable();
break;
}
+
+ board_nmi_handler_setup = ltq_soc_nmi_setup;
+ board_ejtag_handler_setup = ltq_soc_ejtag_setup;
}
--
1.7.10.4

View File

@ -0,0 +1,30 @@
From 3a6ac5004c7c8b140319439f8b1f3f6d4cbfe67a Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 08:25:41 +0000
Subject: [PATCH 7/9] MIPS: lantiq: falcon clocks were not enabled properly
As a result of a non populated ->bits field inside the clock struct, the clock
domains were never powered on the Falcon. Until now we only used domains that
were also used and powered by the bootloader.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4234/
---
arch/mips/lantiq/falcon/sysctrl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
index ba0123d..2d4ced3 100644
--- a/arch/mips/lantiq/falcon/sysctrl.c
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -171,6 +171,7 @@ static inline void clkdev_add_sys(const char *dev, unsigned int module,
clk->cl.con_id = NULL;
clk->cl.clk = clk;
clk->module = module;
+ clk->bits = bits;
clk->activate = sysctl_activate;
clk->deactivate = sysctl_deactivate;
clk->enable = sysctl_clken;
--
1.7.10.4

View File

@ -0,0 +1,31 @@
From f40e1f9d856ec417468c090c4b56826171daa670 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 08:25:42 +0000
Subject: [PATCH 8/9] MIPS: lantiq: enable pci clk conditional for xrx200 SoC
The xrx200 SoC family has the same PCI clock register layout as the AR9.
Enable the same quirk as for AR9
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4235/
---
arch/mips/lantiq/xway/sysctrl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index befbb76..67c3a91 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -145,7 +145,8 @@ static int pci_enable(struct clk *clk)
{
unsigned int val = ltq_cgu_r32(ifccr);
/* set bus clock speed */
- if (of_machine_is_compatible("lantiq,ar9")) {
+ if (of_machine_is_compatible("lantiq,ar9") ||
+ of_machine_is_compatible("lantiq,vr9")) {
val &= ~0x1f00000;
if (clk->rate == CLOCK_33M)
val |= 0xe00000;
--
1.7.10.4

View File

@ -0,0 +1,246 @@
From 30404aec4d093942ba67ded8e1926cbf4472d4f7 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 16 Aug 2012 11:31:02 +0000
Subject: [PATCH 9/9] MIPS: lantiq: adds support for gptu timers
Lantiq socs have a General Purpose Timer Unit (GPTU). This driver allows us to
initialize the timers. The voice firmware needs these timers as a reference.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4236/
---
arch/mips/lantiq/xway/Makefile | 2 +-
arch/mips/lantiq/xway/gptu.c | 214 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 215 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/lantiq/xway/gptu.c
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index dc3194f..f7053b8 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1 +1 @@
-obj-y := prom.o sysctrl.o clk.o reset.o gpio.o dma.o
+obj-y := prom.o sysctrl.o clk.o reset.o gpio.o dma.o gptu.o
diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c
new file mode 100644
index 0000000..cbb56fc
--- /dev/null
+++ b/arch/mips/lantiq/xway/gptu.c
@@ -0,0 +1,214 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2012 Lantiq GmbH
+ */
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+
+#include <lantiq_soc.h>
+#include "../clk.h"
+
+/* the magic ID byte of the core */
+#define GPTU_MAGIC 0x59
+/* clock control register */
+#define GPTU_CLC 0x00
+/* id register */
+#define GPTU_ID 0x08
+/* interrupt node enable */
+#define GPTU_IRNEN 0xf4
+/* interrupt control register */
+#define GPTU_IRCR 0xf8
+/* interrupt capture register */
+#define GPTU_IRNCR 0xfc
+/* there are 3 identical blocks of 2 timers. calculate register offsets */
+#define GPTU_SHIFT(x) (x % 2 ? 4 : 0)
+#define GPTU_BASE(x) (((x >> 1) * 0x20) + 0x10)
+/* timer control register */
+#define GPTU_CON(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x00)
+/* timer auto reload register */
+#define GPTU_RUN(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x08)
+/* timer manual reload register */
+#define GPTU_RLD(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x10)
+/* timer count register */
+#define GPTU_CNT(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x18)
+
+/* GPTU_CON(x) */
+#define CON_CNT BIT(2)
+#define CON_EDGE_ANY (BIT(7) | BIT(6))
+#define CON_SYNC BIT(8)
+#define CON_CLK_INT BIT(10)
+
+/* GPTU_RUN(x) */
+#define RUN_SEN BIT(0)
+#define RUN_RL BIT(2)
+
+/* set clock to runmode */
+#define CLC_RMC BIT(8)
+/* bring core out of suspend */
+#define CLC_SUSPEND BIT(4)
+/* the disable bit */
+#define CLC_DISABLE BIT(0)
+
+#define gptu_w32(x, y) ltq_w32((x), gptu_membase + (y))
+#define gptu_r32(x) ltq_r32(gptu_membase + (x))
+
+enum gptu_timer {
+ TIMER1A = 0,
+ TIMER1B,
+ TIMER2A,
+ TIMER2B,
+ TIMER3A,
+ TIMER3B
+};
+
+static void __iomem *gptu_membase;
+static struct resource irqres[6];
+
+static irqreturn_t timer_irq_handler(int irq, void *priv)
+{
+ int timer = irq - irqres[0].start;
+ gptu_w32(1 << timer, GPTU_IRNCR);
+ return IRQ_HANDLED;
+}
+
+static void gptu_hwinit(void)
+{
+ gptu_w32(0x00, GPTU_IRNEN);
+ gptu_w32(0xff, GPTU_IRNCR);
+ gptu_w32(CLC_RMC | CLC_SUSPEND, GPTU_CLC);
+}
+
+static void gptu_hwexit(void)
+{
+ gptu_w32(0x00, GPTU_IRNEN);
+ gptu_w32(0xff, GPTU_IRNCR);
+ gptu_w32(CLC_DISABLE, GPTU_CLC);
+}
+
+static int gptu_enable(struct clk *clk)
+{
+ int ret = request_irq(irqres[clk->bits].start, timer_irq_handler,
+ IRQF_TIMER, "gtpu", NULL);
+ if (ret) {
+ pr_err("gptu: failed to request irq\n");
+ return ret;
+ }
+
+ gptu_w32(CON_CNT | CON_EDGE_ANY | CON_SYNC | CON_CLK_INT,
+ GPTU_CON(clk->bits));
+ gptu_w32(1, GPTU_RLD(clk->bits));
+ gptu_w32(gptu_r32(GPTU_IRNEN) | BIT(clk->bits), GPTU_IRNEN);
+ gptu_w32(RUN_SEN | RUN_RL, GPTU_RUN(clk->bits));
+ return 0;
+}
+
+static void gptu_disable(struct clk *clk)
+{
+ gptu_w32(0, GPTU_RUN(clk->bits));
+ gptu_w32(0, GPTU_CON(clk->bits));
+ gptu_w32(0, GPTU_RLD(clk->bits));
+ gptu_w32(gptu_r32(GPTU_IRNEN) & ~BIT(clk->bits), GPTU_IRNEN);
+ free_irq(irqres[clk->bits].start, NULL);
+}
+
+static inline void clkdev_add_gptu(struct device *dev, const char *con,
+ unsigned int timer)
+{
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
+ clk->cl.dev_id = dev_name(dev);
+ clk->cl.con_id = con;
+ clk->cl.clk = clk;
+ clk->enable = gptu_enable;
+ clk->disable = gptu_disable;
+ clk->bits = timer;
+ clkdev_add(&clk->cl);
+}
+
+static int __devinit gptu_probe(struct platform_device *pdev)
+{
+ struct clk *clk;
+ struct resource *res;
+
+ if (of_irq_to_resource_table(pdev->dev.of_node, irqres, 6) != 6) {
+ dev_err(&pdev->dev, "Failed to get IRQ list\n");
+ return -EINVAL;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get resource\n");
+ return -ENOMEM;
+ }
+
+ /* remap gptu register range */
+ gptu_membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!gptu_membase) {
+ dev_err(&pdev->dev, "Failed to remap resource\n");
+ return -ENOMEM;
+ }
+
+ /* enable our clock */
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Failed to get clock\n");
+ return -ENOENT;
+ }
+ clk_enable(clk);
+
+ /* power up the core */
+ gptu_hwinit();
+
+ /* the gptu has a ID register */
+ if (((gptu_r32(GPTU_ID) >> 8) & 0xff) != GPTU_MAGIC) {
+ dev_err(&pdev->dev, "Failed to find magic\n");
+ gptu_hwexit();
+ return -ENAVAIL;
+ }
+
+ /* register the clocks */
+ clkdev_add_gptu(&pdev->dev, "timer1a", TIMER1A);
+ clkdev_add_gptu(&pdev->dev, "timer1b", TIMER1B);
+ clkdev_add_gptu(&pdev->dev, "timer2a", TIMER2A);
+ clkdev_add_gptu(&pdev->dev, "timer2b", TIMER2B);
+ clkdev_add_gptu(&pdev->dev, "timer3a", TIMER3A);
+ clkdev_add_gptu(&pdev->dev, "timer3b", TIMER3B);
+
+ dev_info(&pdev->dev, "gptu: 6 timers loaded\n");
+
+ return 0;
+}
+
+static const struct of_device_id gptu_match[] = {
+ { .compatible = "lantiq,gptu-xway" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dma_match);
+
+static struct platform_driver dma_driver = {
+ .probe = gptu_probe,
+ .driver = {
+ .name = "gptu-xway",
+ .owner = THIS_MODULE,
+ .of_match_table = gptu_match,
+ },
+};
+
+int __init gptu_init(void)
+{
+ int ret = platform_driver_register(&dma_driver);
+
+ if (ret)
+ pr_info("gptu: Error registering platform driver\n");
+ return ret;
+}
+
+arch_initcall(gptu_init);
--
1.7.10.4

View File

@ -0,0 +1,554 @@
From e316cb2b16bbfbe48387b56e7e6b5d32ec686f82 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 May 2012 00:33:56 +0200
Subject: [PATCH 11/15] OF: pinctrl: MIPS: lantiq: adds support for FALCON SoC
Implement support for pinctrl on lantiq/falcon socs. The FALCON has 5 banks
of up to 32 pins.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
.../include/asm/mach-lantiq/falcon/lantiq_soc.h | 4 +
arch/mips/lantiq/Kconfig | 1 +
drivers/pinctrl/Kconfig | 5 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-falcon.c | 468 ++++++++++++++++++++
5 files changed, 479 insertions(+)
create mode 100644 drivers/pinctrl/pinctrl-falcon.c
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
index b385252..fccac35 100644
--- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
@@ -57,6 +57,10 @@ extern __iomem void *ltq_sys1_membase;
#define ltq_sys1_w32_mask(clear, set, reg) \
ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg)
+/* allow the gpio and pinctrl drivers to talk to eachother */
+extern int pinctrl_falcon_get_range_size(int id);
+extern void pinctrl_falcon_add_gpio_range(struct pinctrl_gpio_range *range);
+
/*
* to keep the irq code generic we need to define this to 0 as falcon
* has no EIU/EBU
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 080c013..d84f361 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -20,6 +20,7 @@ config SOC_XWAY
config SOC_FALCON
bool "FALCON"
+ select PINCTRL_FALCON
endchoice
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f77dce0..45d2158 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -65,6 +65,11 @@ config PINCTRL_PXA3xx
bool
select PINMUX
+config PINCTRL_FALCON
+ bool
+ depends on SOC_FALCON
+ depends on PINCTRL_LANTIQ
+
config PINCTRL_MMP2
bool "MMP2 pin controller driver"
depends on ARCH_MMP
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index e19e207..c0566c8 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_IMX51) += pinctrl-imx51.o
obj-$(CONFIG_PINCTRL_IMX53) += pinctrl-imx53.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
+obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
new file mode 100644
index 0000000..ee73059
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -0,0 +1,468 @@
+/*
+ * linux/drivers/pinctrl/pinmux-falcon.c
+ * based on linux/drivers/pinctrl/pinmux-pxa910.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-lantiq.h"
+
+#include <lantiq_soc.h>
+
+/* Multiplexer Control Register */
+#define LTQ_PADC_MUX(x) (x * 0x4)
+/* Pull Up Enable Register */
+#define LTQ_PADC_PUEN 0x80
+/* Pull Down Enable Register */
+#define LTQ_PADC_PDEN 0x84
+/* Slew Rate Control Register */
+#define LTQ_PADC_SRC 0x88
+/* Drive Current Control Register */
+#define LTQ_PADC_DCC 0x8C
+/* Pad Control Availability Register */
+#define LTQ_PADC_AVAIL 0xF0
+
+#define pad_r32(p, reg) ltq_r32(p + reg)
+#define pad_w32(p, val, reg) ltq_w32(val, p + reg)
+#define pad_w32_mask(c, clear, set, reg) \
+ pad_w32(c, (pad_r32(c, reg) & ~(clear)) | (set), reg)
+
+#define pad_getbit(m, r, p) (!!(ltq_r32(m + r) & (1 << p)))
+
+#define PORTS 5
+#define PINS 32
+#define PORT(x) (x / PINS)
+#define PORT_PIN(x) (x % PINS)
+
+#define MFP_FALCON(a, f0, f1, f2, f3) \
+{ \
+ .name = #a, \
+ .pin = a, \
+ .func = { \
+ FALCON_MUX_##f0, \
+ FALCON_MUX_##f1, \
+ FALCON_MUX_##f2, \
+ FALCON_MUX_##f3, \
+ }, \
+}
+
+#define GRP_MUX(a, m, p) \
+{ \
+ .name = a, \
+ .mux = FALCON_MUX_##m, \
+ .pins = p, \
+ .npins = ARRAY_SIZE(p), \
+}
+
+enum falcon_mux {
+ FALCON_MUX_GPIO = 0,
+ FALCON_MUX_RST,
+ FALCON_MUX_NTR,
+ FALCON_MUX_MDIO,
+ FALCON_MUX_LED,
+ FALCON_MUX_SPI,
+ FALCON_MUX_ASC,
+ FALCON_MUX_I2C,
+ FALCON_MUX_HOSTIF,
+ FALCON_MUX_SLIC,
+ FALCON_MUX_JTAG,
+ FALCON_MUX_PCM,
+ FALCON_MUX_MII,
+ FALCON_MUX_PHY,
+ FALCON_MUX_NONE = 0xffff,
+};
+
+static struct pinctrl_pin_desc falcon_pads[PORTS * PINS];
+static int pad_count[PORTS];
+
+static void lantiq_load_pin_desc(struct pinctrl_pin_desc *d, int bank, int len)
+{
+ int base = bank * PINS;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ /* strlen("ioXYZ") + 1 = 6 */
+ char *name = kzalloc(6, GFP_KERNEL);
+ snprintf(name, 6, "io%d", base + i);
+ d[i].number = base + i;
+ d[i].name = name;
+ }
+ pad_count[bank] = len;
+}
+
+static struct ltq_mfp_pin falcon_mfp[] = {
+ /* pin f0 f1 f2 f3 */
+ MFP_FALCON(GPIO0, RST, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO1, GPIO, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO2, GPIO, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO3, GPIO, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO4, NTR, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO5, NTR, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO6, RST, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO7, MDIO, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO8, MDIO, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO9, LED, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO10, LED, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO11, LED, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO12, LED, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO13, LED, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO14, LED, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO32, ASC, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO33, ASC, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO34, SPI, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO35, SPI, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO36, SPI, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO37, SPI, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO38, SPI, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO39, I2C, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO40, I2C, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO41, HOSTIF, GPIO, HOSTIF, JTAG),
+ MFP_FALCON(GPIO42, HOSTIF, GPIO, HOSTIF, NONE),
+ MFP_FALCON(GPIO43, SLIC, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO44, SLIC, GPIO, PCM, ASC),
+ MFP_FALCON(GPIO45, SLIC, GPIO, PCM, ASC),
+ MFP_FALCON(GPIO64, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO65, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO66, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO67, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO68, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO69, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO70, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO71, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO72, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO73, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO74, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO75, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO76, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO77, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO78, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO79, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO80, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO81, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO82, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO83, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO84, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO85, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO86, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO87, MII, GPIO, NONE, NONE),
+ MFP_FALCON(GPIO88, PHY, GPIO, NONE, NONE),
+};
+
+static const unsigned pins_por[] = {GPIO0};
+static const unsigned pins_ntr[] = {GPIO4};
+static const unsigned pins_ntr8k[] = {GPIO5};
+static const unsigned pins_hrst[] = {GPIO6};
+static const unsigned pins_mdio[] = {GPIO7, GPIO8};
+static const unsigned pins_bled[] = {GPIO7, GPIO10, GPIO11,
+ GPIO12, GPIO13, GPIO14};
+static const unsigned pins_asc0[] = {GPIO32, GPIO33};
+static const unsigned pins_spi[] = {GPIO34, GPIO35, GPIO36};
+static const unsigned pins_spi_cs0[] = {GPIO37};
+static const unsigned pins_spi_cs1[] = {GPIO38};
+static const unsigned pins_i2c[] = {GPIO39, GPIO40};
+static const unsigned pins_jtag[] = {GPIO41};
+static const unsigned pins_slic[] = {GPIO43, GPIO44, GPIO45};
+static const unsigned pins_pcm[] = {GPIO44, GPIO45};
+static const unsigned pins_asc1[] = {GPIO44, GPIO45};
+
+static struct ltq_pin_group falcon_grps[] = {
+ GRP_MUX("por", RST, pins_por),
+ GRP_MUX("ntr", NTR, pins_ntr),
+ GRP_MUX("ntr8k", NTR, pins_ntr8k),
+ GRP_MUX("hrst", RST, pins_hrst),
+ GRP_MUX("mdio", MDIO, pins_mdio),
+ GRP_MUX("bootled", LED, pins_bled),
+ GRP_MUX("asc0", ASC, pins_asc0),
+ GRP_MUX("spi", SPI, pins_spi),
+ GRP_MUX("spi cs0", SPI, pins_spi_cs0),
+ GRP_MUX("spi cs1", SPI, pins_spi_cs1),
+ GRP_MUX("i2c", I2C, pins_i2c),
+ GRP_MUX("jtag", JTAG, pins_jtag),
+ GRP_MUX("slic", SLIC, pins_slic),
+ GRP_MUX("pcm", PCM, pins_pcm),
+ GRP_MUX("asc1", ASC, pins_asc1),
+};
+
+static const char * const ltq_rst_grps[] = {"por", "hrst"};
+static const char * const ltq_ntr_grps[] = {"ntr", "ntr8k"};
+static const char * const ltq_mdio_grps[] = {"mdio"};
+static const char * const ltq_bled_grps[] = {"bootled"};
+static const char * const ltq_asc_grps[] = {"asc0", "asc1"};
+static const char * const ltq_spi_grps[] = {"spi", "spi cs0", "spi cs1"};
+static const char * const ltq_i2c_grps[] = {"i2c"};
+static const char * const ltq_jtag_grps[] = {"jtag"};
+static const char * const ltq_slic_grps[] = {"slic"};
+static const char * const ltq_pcm_grps[] = {"pcm"};
+
+static struct ltq_pmx_func falcon_funcs[] = {
+ {"rst", ARRAY_AND_SIZE(ltq_rst_grps)},
+ {"ntr", ARRAY_AND_SIZE(ltq_ntr_grps)},
+ {"mdio", ARRAY_AND_SIZE(ltq_mdio_grps)},
+ {"led", ARRAY_AND_SIZE(ltq_bled_grps)},
+ {"asc", ARRAY_AND_SIZE(ltq_asc_grps)},
+ {"spi", ARRAY_AND_SIZE(ltq_spi_grps)},
+ {"i2c", ARRAY_AND_SIZE(ltq_i2c_grps)},
+ {"jtag", ARRAY_AND_SIZE(ltq_jtag_grps)},
+ {"slic", ARRAY_AND_SIZE(ltq_slic_grps)},
+ {"pcm", ARRAY_AND_SIZE(ltq_pcm_grps)},
+};
+
+
+
+
+/* --------- pinconf related code --------- */
+static int falcon_pinconf_group_get(struct pinctrl_dev *pctrldev,
+ unsigned group, unsigned long *config)
+{
+ return -ENOTSUPP;
+}
+
+static int falcon_pinconf_group_set(struct pinctrl_dev *pctrldev,
+ unsigned group, unsigned long config)
+{
+ return -ENOTSUPP;
+}
+
+static int falcon_pinconf_get(struct pinctrl_dev *pctrldev,
+ unsigned pin, unsigned long *config)
+{
+ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+ enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(*config);
+ void __iomem *mem = info->membase[PORT(pin)];
+
+ switch (param) {
+ case LTQ_PINCONF_PARAM_DRIVE_CURRENT:
+ *config = LTQ_PINCONF_PACK(param,
+ !!pad_getbit(mem, LTQ_PADC_DCC, PORT_PIN(pin)));
+ break;
+
+ case LTQ_PINCONF_PARAM_SLEW_RATE:
+ *config = LTQ_PINCONF_PACK(param,
+ !!pad_getbit(mem, LTQ_PADC_SRC, PORT_PIN(pin)));
+ break;
+
+ case LTQ_PINCONF_PARAM_PULL:
+ if (pad_getbit(mem, LTQ_PADC_PDEN, PORT_PIN(pin)))
+ *config = LTQ_PINCONF_PACK(param, 1);
+ else if (pad_getbit(mem, LTQ_PADC_PUEN, PORT_PIN(pin)))
+ *config = LTQ_PINCONF_PACK(param, 2);
+ else
+ *config = LTQ_PINCONF_PACK(param, 0);
+
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int falcon_pinconf_set(struct pinctrl_dev *pctrldev,
+ unsigned pin, unsigned long config)
+{
+ enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(config);
+ int arg = LTQ_PINCONF_UNPACK_ARG(config);
+ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+ void __iomem *mem = info->membase[PORT(pin)];
+ u32 reg;
+
+ switch (param) {
+ case LTQ_PINCONF_PARAM_DRIVE_CURRENT:
+ reg = LTQ_PADC_DCC;
+ break;
+
+ case LTQ_PINCONF_PARAM_SLEW_RATE:
+ reg = LTQ_PADC_SRC;
+ break;
+
+ case LTQ_PINCONF_PARAM_PULL:
+ if (arg == 1)
+ reg = LTQ_PADC_PDEN;
+ else
+ reg = LTQ_PADC_PUEN;
+ break;
+
+ default:
+ pr_err("%s: Invalid config param %04x\n",
+ pinctrl_dev_get_name(pctrldev), param);
+ return -ENOTSUPP;
+ }
+
+ pad_w32(mem, BIT(PORT_PIN(pin)), reg);
+ if (!(pad_r32(mem, reg) & BIT(PORT_PIN(pin))))
+ return -ENOTSUPP;
+ return 0;
+}
+
+static void falcon_pinconf_dbg_show(struct pinctrl_dev *pctrldev,
+ struct seq_file *s, unsigned offset)
+{
+}
+
+static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev,
+ struct seq_file *s, unsigned selector)
+{
+}
+
+struct pinconf_ops falcon_pinconf_ops = {
+ .pin_config_get = falcon_pinconf_get,
+ .pin_config_set = falcon_pinconf_set,
+ .pin_config_group_get = falcon_pinconf_group_get,
+ .pin_config_group_set = falcon_pinconf_group_set,
+ .pin_config_dbg_show = falcon_pinconf_dbg_show,
+ .pin_config_group_dbg_show = falcon_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc falcon_pctrl_desc = {
+ .owner = THIS_MODULE,
+ .pins = falcon_pads,
+ .confops = &falcon_pinconf_ops,
+};
+
+static inline int falcon_mux_apply(struct pinctrl_dev *pctrldev,
+ int mfp, int mux)
+{
+ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+ int port = PORT(info->mfp[mfp].pin);
+
+ if ((port >= PORTS) || (!info->membase[port]))
+ return -ENODEV;
+
+ pad_w32(info->membase[port], mux,
+ LTQ_PADC_MUX(PORT_PIN(info->mfp[mfp].pin)));
+ return 0;
+}
+
+static const struct ltq_cfg_param falcon_cfg_params[] = {
+ {"lantiq,pull", LTQ_PINCONF_PARAM_PULL},
+ {"lantiq,drive-current", LTQ_PINCONF_PARAM_DRIVE_CURRENT},
+ {"lantiq,slew-rate", LTQ_PINCONF_PARAM_SLEW_RATE},
+};
+
+static struct ltq_pinmux_info falcon_info = {
+ .desc = &falcon_pctrl_desc,
+ .apply_mux = falcon_mux_apply,
+};
+
+
+
+
+/* --------- register the pinctrl layer --------- */
+
+int pinctrl_falcon_get_range_size(int id)
+{
+ u32 avail;
+
+ if ((id >= PORTS) || (!falcon_info.membase[id]))
+ return -EINVAL;
+
+ avail = pad_r32(falcon_info.membase[id], LTQ_PADC_AVAIL);
+
+ return fls(avail);
+}
+
+void pinctrl_falcon_add_gpio_range(struct pinctrl_gpio_range *range)
+{
+ pinctrl_add_gpio_range(falcon_info.pctrl, range);
+}
+
+static int pinctrl_falcon_probe(struct platform_device *pdev)
+{
+ struct device_node *np;
+ int pad_count = 0;
+ int ret = 0;
+
+ /* load and remap the pad resources of the different banks */
+ for_each_compatible_node(np, NULL, "lantiq,pad-falcon") {
+ struct platform_device *ppdev = of_find_device_by_node(np);
+ const __be32 *bank = of_get_property(np, "lantiq,bank", NULL);
+ struct resource res;
+ u32 avail;
+ int pins;
+
+ if (!ppdev) {
+ dev_err(&pdev->dev, "failed to find pad pdev\n");
+ continue;
+ }
+ if (!bank || *bank >= PORTS)
+ continue;
+ if (of_address_to_resource(np, 0, &res))
+ continue;
+ falcon_info.clk[*bank] = clk_get(&ppdev->dev, NULL);
+ if (IS_ERR(falcon_info.clk[*bank])) {
+ dev_err(&ppdev->dev, "failed to get clock\n");
+ return PTR_ERR(falcon_info.clk[*bank]);
+ }
+ falcon_info.membase[*bank] =
+ devm_request_and_ioremap(&pdev->dev, &res);
+ if (!falcon_info.membase[*bank]) {
+ dev_err(&pdev->dev,
+ "Failed to remap memory for bank %d\n",
+ *bank);
+ return -ENOMEM;
+ }
+ avail = pad_r32(falcon_info.membase[*bank],
+ LTQ_PADC_AVAIL);
+ pins = fls(avail);
+ lantiq_load_pin_desc(&falcon_pads[pad_count], *bank, pins);
+ pad_count += pins;
+ clk_enable(falcon_info.clk[*bank]);
+ dev_dbg(&pdev->dev, "found %s with %d pads\n",
+ res.name, pins);
+ }
+ dev_dbg(&pdev->dev, "found a total of %d pads\n", pad_count);
+ falcon_pctrl_desc.name = dev_name(&pdev->dev);
+ falcon_pctrl_desc.npins = pad_count;
+
+ falcon_info.mfp = falcon_mfp;
+ falcon_info.num_mfp = ARRAY_SIZE(falcon_mfp);
+ falcon_info.grps = falcon_grps;
+ falcon_info.num_grps = ARRAY_SIZE(falcon_grps);
+ falcon_info.funcs = falcon_funcs;
+ falcon_info.num_funcs = ARRAY_SIZE(falcon_funcs);
+
+ ret = ltq_pinctrl_register(pdev, &falcon_info);
+ if (!ret)
+ dev_info(&pdev->dev, "Init done\n");
+ return ret;
+}
+
+static const struct of_device_id falcon_match[] = {
+ { .compatible = "lantiq,pinctrl-falcon" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, falcon_match);
+
+static struct platform_driver pinctrl_falcon_driver = {
+ .probe = pinctrl_falcon_probe,
+ .driver = {
+ .name = "pinctrl-falcon",
+ .owner = THIS_MODULE,
+ .of_match_table = falcon_match,
+ },
+};
+
+int __init pinctrl_falcon_init(void)
+{
+ return platform_driver_register(&pinctrl_falcon_driver);
+}
+
+core_initcall_sync(pinctrl_falcon_init);
--
1.7.10.4

View File

@ -0,0 +1,121 @@
From 5c56f76995691cf761f66d6d89a00eea80be660c Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 20 Jul 2012 19:01:00 +0200
Subject: [PATCH 12/15] Document: devicetree: add OF documents for lantiq xway
pinctrl
Signed-off-by: John Crispin <blogic@openwrt.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
.../bindings/pinctrl/lantiq,xway-pinumx.txt | 97 ++++++++++++++++++++
1 file changed, 97 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/lantiq,xway-pinumx.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/lantiq,xway-pinumx.txt b/Documentation/devicetree/bindings/pinctrl/lantiq,xway-pinumx.txt
new file mode 100644
index 0000000..b5469db
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/lantiq,xway-pinumx.txt
@@ -0,0 +1,97 @@
+Lantiq XWAY pinmux controller
+
+Required properties:
+- compatible: "lantiq,pinctrl-xway" or "lantiq,pinctrl-xr9"
+- reg: Should contain the physical address and length of the gpio/pinmux
+ register range
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Lantiq's pin configuration nodes act as a container for an abitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those group(s), and two pin configuration parameters:
+pull-up and open-drain
+
+The name of each subnode is not important as long as it is unique; all subnodes
+should be enumerated and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+We support 2 types of nodes.
+
+Definition of mux function groups:
+
+Required subnode-properties:
+- lantiq,groups : An array of strings. Each string contains the name of a group.
+ Valid values for these names are listed below.
+- lantiq,function: A string containing the name of the function to mux to the
+ group. Valid values for function names are listed below.
+
+Valid values for group and function names:
+
+ mux groups:
+ exin0, exin1, exin2, jtag, ebu a23, ebu a24, ebu a25, ebu clk, ebu cs1,
+ ebu wait, nand ale, nand cs1, nand cle, spi, spi_cs1, spi_cs2, spi_cs3,
+ spi_cs4, spi_cs5, spi_cs6, asc0, asc0 cts rts, stp, nmi , gpt1, gpt2,
+ gpt3, clkout0, clkout1, clkout2, clkout3, gnt1, gnt2, gnt3, req1, req2,
+ req3
+
+ additional mux groups (XR9 only):
+ mdio, nand rdy, nand rd, exin3, exin4, gnt4, req4
+
+ functions:
+ spi, asc, cgu, jtag, exin, stp, gpt, nmi, pci, ebu, mdio
+
+
+
+Definition of pin configurations:
+
+Required subnode-properties:
+- lantiq,pins : An array of strings. Each string contains the name of a pin.
+ Valid values for these names are listed below.
+
+Optional subnode-properties:
+- lantiq,pull: Integer, representing the pull-down/up to apply to the pin.
+ 0: none, 1: down, 2: up.
+- lantiq,open-drain: Boolean, enables open-drain on the defined pin.
+
+Valid values for XWAY pin names:
+ Pinconf pins can be referenced via the names io0-io31.
+
+Valid values for XR9 pin names:
+ Pinconf pins can be referenced via the names io0-io55.
+
+Example:
+ gpio: pinmux@E100B10 {
+ compatible = "lantiq,pinctrl-xway";
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0xE100B10 0xA0>;
+
+ state_default: pinmux {
+ stp {
+ lantiq,groups = "stp";
+ lantiq,function = "stp";
+ };
+ pci {
+ lantiq,groups = "gnt1";
+ lantiq,function = "pci";
+ };
+ conf_out {
+ lantiq,pins = "io4", "io5", "io6"; /* stp */
+ lantiq,open-drain;
+ lantiq,pull = <0>;
+ };
+ };
+ };
+
--
1.7.10.4

View File

@ -0,0 +1,108 @@
From 8e004b47b7645fe8ebe1bb81f75cd8f16650de68 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 22 Jul 2012 09:23:50 +0200
Subject: [PATCH 13/15] Document: devicetree: add OF documents for lantiq
falcon pinctrl
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
.../bindings/pinctrl/lantiq,falcon-pinumx.txt | 83 ++++++++++++++++++++
1 file changed, 83 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/lantiq,falcon-pinumx.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/lantiq,falcon-pinumx.txt b/Documentation/devicetree/bindings/pinctrl/lantiq,falcon-pinumx.txt
new file mode 100644
index 0000000..daa7689
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/lantiq,falcon-pinumx.txt
@@ -0,0 +1,83 @@
+Lantiq FALCON pinmux controller
+
+Required properties:
+- compatible: "lantiq,pinctrl-falcon"
+- reg: Should contain the physical address and length of the gpio/pinmux
+ register range
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Lantiq's pin configuration nodes act as a container for an abitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those group(s), and two pin configuration parameters:
+pull-up and open-drain
+
+The name of each subnode is not important as long as it is unique; all subnodes
+should be enumerated and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+We support 2 types of nodes.
+
+Definition of mux function groups:
+
+Required subnode-properties:
+- lantiq,groups : An array of strings. Each string contains the name of a group.
+ Valid values for these names are listed below.
+- lantiq,function: A string containing the name of the function to mux to the
+ group. Valid values for function names are listed below.
+
+Valid values for group and function names:
+
+ mux groups:
+ por, ntr, ntr8k, hrst, mdio, bootled, asc0, spi, spi cs0, spi cs1, i2c,
+ jtag, slic, pcm, asc1
+
+ functions:
+ rst, ntr, mdio, led, asc, spi, i2c, jtag, slic, pcm
+
+
+Definition of pin configurations:
+
+Required subnode-properties:
+- lantiq,pins : An array of strings. Each string contains the name of a pin.
+ Valid values for these names are listed below.
+
+Optional subnode-properties:
+- lantiq,pull: Integer, representing the pull-down/up to apply to the pin.
+ 0: none, 1: down
+- lantiq,drive-current: Boolean, enables drive-current
+- lantiq,slew-rate: Boolean, enables slew-rate
+
+Example:
+ pinmux0 {
+ compatible = "lantiq,pinctrl-falcon";
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ asc0 {
+ lantiq,groups = "asc0";
+ lantiq,function = "asc";
+ };
+ ntr {
+ lantiq,groups = "ntr8k";
+ lantiq,function = "ntr";
+ };
+ i2c {
+ lantiq,groups = "i2c";
+ lantiq,function = "i2c";
+ };
+ hrst {
+ lantiq,groups = "hrst";
+ lantiq,function = "rst";
+ };
+ };
+ };
--
1.7.10.4

View File

@ -0,0 +1,33 @@
From 6a88a0f762a61f212d4bbcf1ad45369f28014484 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 15 Aug 2012 15:41:50 +0200
Subject: [PATCH 14/15] MIPS: lantiq: make use of __gpio_to_irq
The gpio_chip struct allows us to set a .to_irq callback. Once this is set
we can rely on the generic __gpio_to_irq() function to map gpio->irq allowing
more than one gpio_chip to register an interrupt
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/include/asm/mach-lantiq/gpio.h | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/gpio.h b/arch/mips/include/asm/mach-lantiq/gpio.h
index f79505b..9ba1cae 100644
--- a/arch/mips/include/asm/mach-lantiq/gpio.h
+++ b/arch/mips/include/asm/mach-lantiq/gpio.h
@@ -1,10 +1,7 @@
#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H
#define __ASM_MIPS_MACH_LANTIQ_GPIO_H
-static inline int gpio_to_irq(unsigned int gpio)
-{
- return -1;
-}
+#define gpio_to_irq __gpio_to_irq
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
--
1.7.10.4

View File

@ -0,0 +1,34 @@
From c9e854cf940fbc09846c255895efceb3bc9bf095 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 11 Jul 2012 16:33:43 +0200
Subject: [PATCH 15/15] GPIO: MIPS: lantiq: fix overflow inside stp-xway
driver
The driver was using a 16 bit field for storing the shadow value of the shift
register cascade. This resulted in only the first 2 shift registeres receiving
the correct data. The third shift register would always receive 0x00.
Fix this by using a 32bit field for the shadow value.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-kernel@vger.kernel.org
---
drivers/gpio/gpio-stp-xway.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index e35096b..8bead0b 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -82,7 +82,7 @@ struct xway_stp {
struct gpio_chip gc;
void __iomem *virt;
u32 edge; /* rising or falling edge triggered shift register */
- u16 shadow; /* shadow the shift registers state */
+ u32 shadow; /* shadow the shift registers state */
u8 groups; /* we can drive 1-3 groups of 8bit each */
u8 dsl; /* the 2 LSBs can be driven by the dsl core */
u8 phy1; /* 3 bits can be driven by phy1 */
--
1.7.10.4

View File

@ -0,0 +1,257 @@
From 99f2b107924c07bee0bae7151426495fb815ca6e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 23 Aug 2012 20:28:32 +0200
Subject: [PATCH] mtd: lantiq: Add NAND support on Lantiq XWAY SoC.
The driver uses plat_nand. As the platform_device is loaded from DT, we need
to lookup the node and attach our xway specific "struct platform_nand_data"
to it.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---
drivers/mtd/nand/Kconfig | 8 ++
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/xway_nand.c | 201 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
create mode 100644 drivers/mtd/nand/xway_nand.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7101e8a..ce5cf02 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -580,4 +580,12 @@ config MTD_NAND_FSMC
Enables support for NAND Flash chips on the ST Microelectronics
Flexible Static Memory Controller (FSMC)
+config MTD_NAND_XWAY
+ tristate "Support for NAND on Lantiq XWAY SoC"
+ depends on LANTIQ && SOC_TYPE_XWAY
+ select MTD_NAND_PLATFORM
+ help
+ Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
+ to the External Bus Unit (EBU).
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index ddee818..c4b0ab3 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -53,5 +53,6 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
+obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c
new file mode 100644
index 0000000..3f81dc8
--- /dev/null
+++ b/drivers/mtd/nand/xway_nand.c
@@ -0,0 +1,201 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright © 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/mtd/nand.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+/* nand registers */
+#define EBU_ADDSEL1 0x24
+#define EBU_NAND_CON 0xB0
+#define EBU_NAND_WAIT 0xB4
+#define EBU_NAND_ECC0 0xB8
+#define EBU_NAND_ECC_AC 0xBC
+
+/* nand commands */
+#define NAND_CMD_ALE (1 << 2)
+#define NAND_CMD_CLE (1 << 3)
+#define NAND_CMD_CS (1 << 4)
+#define NAND_WRITE_CMD_RESET 0xff
+#define NAND_WRITE_CMD (NAND_CMD_CS | NAND_CMD_CLE)
+#define NAND_WRITE_ADDR (NAND_CMD_CS | NAND_CMD_ALE)
+#define NAND_WRITE_DATA (NAND_CMD_CS)
+#define NAND_READ_DATA (NAND_CMD_CS)
+#define NAND_WAIT_WR_C (1 << 3)
+#define NAND_WAIT_RD (0x1)
+
+/* we need to tel the ebu which addr we mapped the nand to */
+#define ADDSEL1_MASK(x) (x << 4)
+#define ADDSEL1_REGEN 1
+
+/* we need to tell the EBU that we have nand attached and set it up properly */
+#define BUSCON1_SETUP (1 << 22)
+#define BUSCON1_BCGEN_RES (0x3 << 12)
+#define BUSCON1_WAITWRC2 (2 << 8)
+#define BUSCON1_WAITRDC2 (2 << 6)
+#define BUSCON1_HOLDC1 (1 << 4)
+#define BUSCON1_RECOVC1 (1 << 2)
+#define BUSCON1_CMULT4 1
+
+#define NAND_CON_CE (1 << 20)
+#define NAND_CON_OUT_CS1 (1 << 10)
+#define NAND_CON_IN_CS1 (1 << 8)
+#define NAND_CON_PRE_P (1 << 7)
+#define NAND_CON_WP_P (1 << 6)
+#define NAND_CON_SE_P (1 << 5)
+#define NAND_CON_CS_P (1 << 4)
+#define NAND_CON_CSMUX (1 << 1)
+#define NAND_CON_NANDM 1
+
+static void xway_reset_chip(struct nand_chip *chip)
+{
+ unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W;
+ unsigned long flags;
+
+ nandaddr &= ~NAND_WRITE_ADDR;
+ nandaddr |= NAND_WRITE_CMD;
+
+ /* finish with a reset */
+ spin_lock_irqsave(&ebu_lock, flags);
+ writeb(NAND_WRITE_CMD_RESET, (void __iomem *) nandaddr);
+ while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+ ;
+ spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void xway_select_chip(struct mtd_info *mtd, int chip)
+{
+
+ switch (chip) {
+ case -1:
+ ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON);
+ ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON);
+ break;
+ case 0:
+ ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON);
+ ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
+ unsigned long flags;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ nandaddr &= ~(NAND_WRITE_CMD | NAND_WRITE_ADDR);
+ if (ctrl & NAND_CLE)
+ nandaddr |= NAND_WRITE_CMD;
+ else
+ nandaddr |= NAND_WRITE_ADDR;
+ this->IO_ADDR_W = (void __iomem *) nandaddr;
+ }
+
+ if (cmd != NAND_CMD_NONE) {
+ spin_lock_irqsave(&ebu_lock, flags);
+ writeb(cmd, this->IO_ADDR_W);
+ while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+ ;
+ spin_unlock_irqrestore(&ebu_lock, flags);
+ }
+}
+
+static int xway_dev_ready(struct mtd_info *mtd)
+{
+ return ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD;
+}
+
+static unsigned char xway_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long nandaddr = (unsigned long) this->IO_ADDR_R;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+ ret = ltq_r8((void __iomem *)(nandaddr + NAND_READ_DATA));
+ spin_unlock_irqrestore(&ebu_lock, flags);
+
+ return ret;
+}
+
+static int xway_nand_probe(struct platform_device *pdev)
+{
+ struct nand_chip *this = platform_get_drvdata(pdev);
+ unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
+ const __be32 *cs = of_get_property(pdev->dev.of_node,
+ "lantiq,cs", NULL);
+ u32 cs_flag = 0;
+
+ /* load our CS from the DT. Either we find a valid 1 or default to 0 */
+ if (cs && (*cs == 1))
+ cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1;
+
+ /* setup the EBU to run in NAND mode on our base addr */
+ ltq_ebu_w32(CPHYSADDR(nandaddr)
+ | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1);
+
+ ltq_ebu_w32(BUSCON1_SETUP | BUSCON1_BCGEN_RES | BUSCON1_WAITWRC2
+ | BUSCON1_WAITRDC2 | BUSCON1_HOLDC1 | BUSCON1_RECOVC1
+ | BUSCON1_CMULT4, LTQ_EBU_BUSCON1);
+
+ ltq_ebu_w32(NAND_CON_NANDM | NAND_CON_CSMUX | NAND_CON_CS_P
+ | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P
+ | cs_flag, EBU_NAND_CON);
+
+ /* finish with a reset */
+ xway_reset_chip(this);
+
+ return 0;
+}
+
+/* allow users to override the partition in DT using the cmdline */
+static const char *part_probes[] = { "cmdlinepart", "ofpart", NULL };
+
+static struct platform_nand_data xway_nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_delay = 30,
+ .part_probe_types = part_probes,
+ },
+ .ctrl = {
+ .probe = xway_nand_probe,
+ .cmd_ctrl = xway_cmd_ctrl,
+ .dev_ready = xway_dev_ready,
+ .select_chip = xway_select_chip,
+ .read_byte = xway_read_byte,
+ }
+};
+
+/*
+ * Try to find the node inside the DT. If it is available attach out
+ * platform_nand_data
+ */
+static int __init xway_register_nand(void)
+{
+ struct device_node *node;
+ struct platform_device *pdev;
+
+ node = of_find_compatible_node(NULL, NULL, "lantiq,nand-xway");
+ if (!node)
+ return -ENOENT;
+ pdev = of_find_device_by_node(node);
+ if (!pdev)
+ return -EINVAL;
+ pdev->dev.platform_data = &xway_nand_data;
+ of_node_put(node);
+ return 0;
+}
+
+subsys_initcall(xway_register_nand);
--
1.7.10.4

View File

@ -0,0 +1,71 @@
From b27b8f1bd7d46f1affc9a2bc4142e248411c1afa Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 17:42:48 +0200
Subject: [PATCH 100/113] MIPS: lantiq: external interrupt units not loaded
properly
The code references the wrong device node causing the number of EIU pins to
be wrong.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/irq.c | 2 +-
drivers/pinctrl/pinctrl-xway.c | 15 +++++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index f36acd1..8e55622 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -343,7 +343,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu");
if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
/* find out how many external irq sources we have */
- const __be32 *count = of_get_property(node,
+ const __be32 *count = of_get_property(eiu_node,
"lantiq,count", NULL);
if (count)
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index b9bcaec..ea5e017 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -14,6 +14,7 @@
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/device.h>
@@ -618,6 +619,19 @@ static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
pinctrl_free_gpio(gpio);
}
+static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+ struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+ struct resource res;
+ int i;
+
+ for (i = 0; i < info->num_exin; i++)
+ if (offset == info->exin[i])
+ if (of_irq_to_resource(chip->dev->of_node, i, &res))
+ return res.start;
+ return 0;
+}
+
static struct gpio_chip xway_chip = {
.label = "gpio-xway",
.direction_input = xway_gpio_dir_in,
@@ -626,6 +640,7 @@ static struct gpio_chip xway_chip = {
.set = xway_gpio_set,
.request = xway_gpio_req,
.free = xway_gpio_free,
+ .to_irq = xway_gpio_to_irq,
.base = -1,
};
--
1.7.10.4

View File

@ -0,0 +1,27 @@
From 50b5073dd266721a690323519fb906a56daa09d7 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 1 Nov 2012 20:39:43 +0100
Subject: [PATCH 101/113] MIPS: lantiq: bootsel bits are wrong
---
arch/mips/lantiq/xway/reset.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 22c55f7..a89d1a3 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -34,8 +34,8 @@
/* reset cause */
#define RCU_STAT_SHIFT 26
/* boot selection */
-#define RCU_BOOT_SEL_SHIFT 26
-#define RCU_BOOT_SEL_MASK 0x7
+#define RCU_BOOT_SEL_SHIFT 17
+#define RCU_BOOT_SEL_MASK 0xf
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
--
1.7.10.4

View File

@ -0,0 +1,62 @@
From 671f34ea864ddc353f32272b3a2f7ee62d6f8548 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 1 Nov 2012 20:50:39 +0100
Subject: [PATCH 102/113] MIPS: lantiq: fixes dma irq ack
---
arch/mips/lantiq/xway/dma.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 55d2c4f..a301b3b 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -25,6 +25,7 @@
#include <lantiq_soc.h>
#include <xway_dma.h>
+#define LTQ_DMA_ID 0x08
#define LTQ_DMA_CTRL 0x10
#define LTQ_DMA_CPOLL 0x14
#define LTQ_DMA_CS 0x18
@@ -89,7 +90,7 @@ ltq_dma_ack_irq(struct ltq_dma_channel *ch)
local_irq_save(flags);
ltq_dma_w32(ch->nr, LTQ_DMA_CS);
- ltq_dma_w32(DMA_IRQ_ACK, LTQ_DMA_CIS);
+ ltq_dma_w32(ltq_dma_r32(LTQ_DMA_CIS), LTQ_DMA_CIS);
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(ltq_dma_ack_irq);
@@ -103,6 +104,7 @@ ltq_dma_open(struct ltq_dma_channel *ch)
ltq_dma_w32(ch->nr, LTQ_DMA_CS);
ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL);
ltq_dma_enable_irq(ch);
+ ltq_dma_ack_irq(ch);
local_irq_restore(flag);
}
EXPORT_SYMBOL_GPL(ltq_dma_open);
@@ -214,6 +216,7 @@ ltq_dma_init(struct platform_device *pdev)
{
struct clk *clk;
struct resource *res;
+ unsigned id;
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -243,6 +246,12 @@ ltq_dma_init(struct platform_device *pdev)
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
}
+
+ id = ltq_dma_r32(LTQ_DMA_ID);
+ dev_info(&pdev->dev,
+ "Init done - hw rev: %X, ports: %d, channels: %d\n",
+ id & 0x1f, (id >> 16) & 0xf, id >> 20);
+
dev_info(&pdev->dev, "init done\n");
return 0;
}
--
1.7.10.4

View File

@ -0,0 +1,36 @@
From 176aad2b97d2e7d623ef07ee9b68b71c7db8cce4 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 1 Nov 2012 20:50:52 +0100
Subject: [PATCH 103/113] MIPS: lantiq: prom code invalidated devicetree
memory
---
arch/mips/lantiq/prom.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 6cfd611..9f9e875 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -87,9 +87,6 @@ void __init device_tree_init(void)
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
unflatten_device_tree();
-
- /* free the space reserved for the dt blob */
- free_bootmem(base, size);
}
void __init prom_init(void)
@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
sizeof(of_ids[0].compatible));
strncpy(of_ids[1].compatible, "simple-bus",
sizeof(of_ids[1].compatible));
- return of_platform_bus_probe(NULL, of_ids, NULL);
+ return of_platform_populate(NULL, of_ids, NULL, NULL);
}
arch_initcall(plat_of_setup);
--
1.7.10.4

View File

@ -0,0 +1,60 @@
From 8fc2eacbe332fbf6bfd09425fb141bb47d843a78 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 09:32:46 +0200
Subject: [PATCH 104/113] MIPS: lantiq: xway: split ltq_reset_once into 2
subfunctions
We need to call the reset functions from within the phy reset code and dont
want to duplicate the access code for the reset registers.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 +++
arch/mips/lantiq/xway/reset.c | 14 ++++++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 6a2df70..6b9f5be 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -87,5 +87,8 @@ extern __iomem void *ltq_cgu_membase;
extern void ltq_pmu_enable(unsigned int module);
extern void ltq_pmu_disable(unsigned int module);
+/* allow drivers to reset clock domains and ip cores */
+void ltq_reset_once(unsigned int module, ulong u);
+
#endif /* CONFIG_SOC_TYPE_XWAY */
#endif /* _LTQ_XWAY_H__ */
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index a89d1a3..1b77f82 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -55,12 +55,22 @@ unsigned char ltq_boot_select(void)
return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
}
+static void ltq_reset_enter(unsigned int module)
+{
+ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
+}
+
+static void ltq_reset_leave(unsigned int module)
+{
+ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
+}
+
/* reset a io domain for u micro seconds */
void ltq_reset_once(unsigned int module, ulong u)
{
- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
+ ltq_reset_enter(RCU_RST_REQ);
udelay(u);
- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
+ ltq_reset_leave(RCU_RST_REQ);
}
static void ltq_machine_restart(char *command)
--
1.7.10.4

View File

@ -0,0 +1,210 @@
From 4ed46c23c7257e15a419eb3176375601b312c157 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 09:47:09 +0200
Subject: [PATCH 105/113] MIPS: lantiq: xway: adds reset code for 11G PHYs
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/a | 42 +++++++++++++
arch/mips/b | 36 +++++++++++
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 +
arch/mips/lantiq/xway/reset.c | 63 +++++++++++++++++++-
4 files changed, 142 insertions(+), 2 deletions(-)
create mode 100644 arch/mips/a
create mode 100644 arch/mips/b
diff --git a/arch/mips/a b/arch/mips/a
new file mode 100644
index 0000000..31e61f8
--- /dev/null
+++ b/arch/mips/a
@@ -0,0 +1,42 @@
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 6a2df70..056df1a 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -87,5 +87,8 @@ extern __iomem void *ltq_cgu_membase;
+ extern void ltq_pmu_enable(unsigned int module);
+ extern void ltq_pmu_disable(unsigned int module);
+
++/* allow drivers to reset clock domains and ip cores */
++void ltq_reset_once(unsigned int module, ulong u);
++
+ #endif /* CONFIG_SOC_TYPE_XWAY */
+ #endif /* _LTQ_XWAY_H__ */
+diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
+index 22c55f7..c2a7e65 100644
+--- a/arch/mips/lantiq/xway/reset.c
++++ b/arch/mips/lantiq/xway/reset.c
+@@ -55,13 +62,23 @@ unsigned char ltq_boot_select(void)
+ return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
+ }
+
++static void ltq_reset_enter(unsigned int module)
++{
++ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
++}
++
++static void ltq_reset_leave(unsigned int module)
++{
++ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
++}
++
+ /* reset a io domain for u micro seconds */
+ void ltq_reset_once(unsigned int module, ulong u)
+ {
+- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
++ ltq_reset_enter(RCU_RST_REQ);
+ udelay(u);
+- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
++ ltq_reset_leave(RCU_RST_REQ);
+ }
+
+ static void ltq_machine_restart(char *command)
diff --git a/arch/mips/b b/arch/mips/b
new file mode 100644
index 0000000..c6a0323
--- /dev/null
+++ b/arch/mips/b
@@ -0,0 +1,36 @@
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 6a2df70..056df1a 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -87,8 +87,11 @@ extern __iomem void *ltq_cgu_membase;
+ extern void ltq_pmu_enable(unsigned int module);
+ extern void ltq_pmu_disable(unsigned int module);
+
++/* allow booting xrx200 phys */
++int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
++
+ #endif /* CONFIG_SOC_TYPE_XWAY */
+ #endif /* _LTQ_XWAY_H__ */
+diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
+index 22c55f7..c2a7e65 100644
+--- a/arch/mips/lantiq/xway/reset.c
++++ b/arch/mips/lantiq/xway/reset.c
+@@ -26,11 +26,18 @@
+
+ /* reset request register */
+ #define RCU_RST_REQ 0x0010
++
++#define VR9_RCU_GFS_ADD0 0x0020
++#define VR9_RCU_GFS_ADD1 0x0068
++
+ /* reset status register */
+ #define RCU_RST_STAT 0x0014
+
+ /* reboot bit */
++#define VR9_RCU_RD_GPHY0 BIT(31)
+ #define RCU_RD_SRST BIT(30)
++#define VR9_RCU_RD_GPHY1 BIT(29)
++
+ /* reset cause */
+ #define RCU_STAT_SHIFT 26
+ /* boot selection */
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 6b9f5be..056df1a 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -90,5 +90,8 @@ extern void ltq_pmu_disable(unsigned int module);
/* allow drivers to reset clock domains and ip cores */
void ltq_reset_once(unsigned int module, ulong u);
+/* allow booting xrx200 phys */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
+
#endif /* CONFIG_SOC_TYPE_XWAY */
#endif /* _LTQ_XWAY_H__ */
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 1b77f82..56293cf 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -28,9 +28,15 @@
#define RCU_RST_REQ 0x0010
/* reset status register */
#define RCU_RST_STAT 0x0014
+/* vr9 gphy registers */
+#define VR9_RCU_GFS_ADD0 0x0020
+#define VR9_RCU_GFS_ADD1 0x0068
/* reboot bit */
+#define VR9_RCU_RD_GPHY0 BIT(31)
#define RCU_RD_SRST BIT(30)
+#define VR9_RCU_RD_GPHY1 BIT(29)
+
/* reset cause */
#define RCU_STAT_SHIFT 26
/* boot selection */
@@ -65,13 +71,66 @@ static void ltq_reset_leave(unsigned int module)
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
}
+/* reset / boot a gphy */
+static struct ltq_xrx200_gphy_reset {
+ u32 rd;
+ u32 addr;
+} xrx200_gphy[] = {
+ {VR9_RCU_RD_GPHY0, VR9_RCU_GFS_ADD0},
+ {VR9_RCU_RD_GPHY1, VR9_RCU_GFS_ADD1},
+};
+
+/* reset and boot a gphy. these phys only exist on xrx200 SoC */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
+{
+ if (id > 1) {
+ dev_err(dev, "%u is an invalid gphy id\n", id);
+ return -EINVAL;
+ }
+ dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
+
+ ltq_reset_enter(xrx200_gphy[id].rd);
+ ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
+ ltq_reset_leave(xrx200_gphy[id].rd);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(xrx200_gphy_boot);
+
/* reset a io domain for u micro seconds */
void ltq_reset_once(unsigned int module, ulong u)
{
- ltq_reset_enter(RCU_RST_REQ);
+ ltq_reset_enter(module);
udelay(u);
- ltq_reset_leave(RCU_RST_REQ);
+ ltq_reset_leave(module);
+}
+
+int ifx_rcu_rst(unsigned int reset_domain_id, unsigned int module_id)
+{
+ ltq_reset_once(BIT(module_id), 20);
+ return 0;
+}
+EXPORT_SYMBOL(ifx_rcu_rst);
+
+unsigned int ifx_rcu_rst_req_read(void)
+{
+ unsigned int ret;
+
+ ret = ltq_rcu_r32(RCU_RST_REQ);
+
+ return ret;
+}
+EXPORT_SYMBOL(ifx_rcu_rst_req_read);
+
+void ifx_rcu_rst_req_write(unsigned int value, unsigned int mask)
+{
+ unsigned int ret;
+
+ ret = ltq_rcu_r32(RCU_RST_REQ);
+ ret &= ~mask;
+ ret |= value & mask;
+ ltq_rcu_w32(ret, RCU_RST_REQ);
}
+EXPORT_SYMBOL(ifx_rcu_rst_req_write);
static void ltq_machine_restart(char *command)
{
--
1.7.10.4

View File

@ -0,0 +1,607 @@
From b2ea96b934fcf665b4c0cc844416a7a2618e198e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 09:52:50 +0200
Subject: [PATCH 106/113] MIPS: lantiq: xway: adds PHY11G platform code
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/xway/Makefile | 2 +-
arch/mips/lantiq/xway/vr9_switch_regs.h | 425 +++++++++++++++++++++++++++++++
arch/mips/lantiq/xway/xway_phy_fw.c | 146 +++++++++++
3 files changed, 572 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/lantiq/xway/vr9_switch_regs.h
create mode 100644 arch/mips/lantiq/xway/xway_phy_fw.c
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 70a58c7..1998b7c 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1 +1 @@
-obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
+obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o xway_phy_fw.o
diff --git a/arch/mips/lantiq/xway/vr9_switch_regs.h b/arch/mips/lantiq/xway/vr9_switch_regs.h
new file mode 100644
index 0000000..339e4c1
--- /dev/null
+++ b/arch/mips/lantiq/xway/vr9_switch_regs.h
@@ -0,0 +1,425 @@
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+ */
+
+#ifndef __VR9_SWITCH_REGS_H__
+#define __VR9_SWITCH_REGS_H__
+
+/* Switch core registers */
+struct vr9_switch_core_regs {
+ __be32 swres;
+ /* TODO: implement registers */
+ __be32 rsvd0[0x3f];
+};
+
+/* Switch buffer management registers */
+struct vr9_switch_bm_regs {
+ struct bm_core {
+ __be32 ram_val3; /* RAM value 3 */
+ __be32 ram_val2; /* RAM value 2 */
+ __be32 ram_val1; /* RAM value 1 */
+ __be32 ram_val0; /* RAM value 0 */
+ __be32 ram_addr; /* RAM address */
+ __be32 ram_ctrl; /* RAM access control */
+ __be32 fsqm_gctrl; /* Free segment queue global control */
+ __be32 cons_sel; /* Number of consumed segments */
+ __be32 cons_pkt; /* Number of consumed packet pointers */
+ __be32 gctrl; /* Global control */
+ __be32 queue_gctrl; /* Queue manager global control */
+ /* TODO: implement registers */
+ __be32 rsvd0[0x35];
+ } core;
+
+ struct bm_port {
+ __be32 pcfg; /* Port config */
+ __be32 rmon_ctrl; /* RMON control */
+ } port[13];
+
+ __be32 rsvd0[0x66];
+
+ struct bm_queue {
+ __be32 rsvd0;
+ __be32 pqm_rs; /* Packet queue manager rate shape assignment */
+ } queue[32];
+
+ struct bm_shaper {
+ __be32 ctrl; /* Rate shaper control */
+ __be32 cbs; /* Rate shaper committed burst size */
+ __be32 ibs; /* Rate shaper instantaneous burst size */
+ __be32 cir_ext; /* Rate shaper rate exponent */
+ __be32 cir_mant; /* Rate shaper rate mantissa */
+ } shaper[16];
+
+ __be32 rsvd1[0x2a8];
+};
+
+/* Switch parser and classification engine registers */
+struct vr9_switch_pce_regs {
+ struct pce_core {
+ __be32 tbl_key[16]; /* Table key data */
+ __be32 tbl_mask; /* Table mask */
+ __be32 tbl_val[5]; /* Table value */
+ __be32 tbl_addr; /* Table entry address */
+ __be32 tbl_ctrl; /* Table access control */
+ __be32 tbl_stat; /* Table general status */
+ __be32 age_0; /* Aging counter config 0 */
+ __be32 age_1; /* Aging counter config 1 */
+ __be32 pmap_1; /* Port map (monitoring) */
+ __be32 pmap_2; /* Port map (multicast) */
+ __be32 pmap_3; /* Port map (unknown unicast) */
+ __be32 gctrl_0; /* Global control 0 */
+ __be32 gctrl_1; /* Global control 1 */
+ __be32 tcm_gctrl; /* Three-color marker global control */
+ __be32 igmp_ctrl; /* IGMP control */
+ __be32 igmp_drpm; /* IGMP default router port map */
+ __be32 igmp_age_0; /* IGMP aging 0 */
+ __be32 igmp_age_1; /* IGMP aging 1 */
+ __be32 igmp_stat; /* IGMP status */
+ __be32 wol_gctrl; /* Wake-on-LAN control */
+ __be32 wol_da_0; /* Wake-on-LAN destination address 0 */
+ __be32 wol_da_1; /* Wake-on-LAN destination address 1 */
+ __be32 wol_da_2; /* Wake-on-LAN destination address 2 */
+ __be32 wol_pw_0; /* Wake-on-LAN password 0 */
+ __be32 wol_pw_1; /* Wake-on-LAN password 1 */
+ __be32 wol_pw_2; /* Wake-on-LAN password 2 */
+ __be32 ier_0; /* PCE global interrupt enable 0 */
+ __be32 ier_1; /* PCE global interrupt enable 1 */
+ __be32 isr_0; /* PCE global interrupt status 0 */
+ __be32 isr_1; /* PCE global interrupt status 1 */
+ __be32 parser_stat; /* Parser status */
+ __be32 rsvd0[0x6];
+ } core;
+
+ __be32 rsvd0[0x10];
+
+ struct pce_port {
+ __be32 pctrl_0; /* Port control 0 */
+ __be32 pctrl_1; /* Port control 1 */
+ __be32 pctrl_2; /* Port control 2 */
+ __be32 pctrl_3; /* Port control 3 */
+ __be32 wol_ctrl; /* Wake-on-LAN control */
+ __be32 vlan_ctrl; /* VLAN control */
+ __be32 def_pvid; /* Default port VID */
+ __be32 pstat; /* Port status */
+ __be32 pier; /* Interrupt enable */
+ __be32 pisr; /* Interrupt status */
+ } port[13];
+
+ __be32 rsvd1[0x7e];
+
+ struct pce_meter {
+ /* TODO: implement registers */
+ __be32 rsvd0[0x7];
+ } meter[8];
+
+ __be32 rsvd2[0x308];
+};
+
+static inline unsigned int to_pce_tbl_key_id(unsigned int id)
+{
+ return 15 - id;
+}
+
+static inline unsigned int to_pce_tbl_value_id(unsigned int id)
+{
+ return 4 - id;
+}
+
+/* Switch ethernet MAC registers */
+struct vr9_switch_mac_regs {
+ struct mac_core {
+ __be32 test; /* MAC test */
+ __be32 pfad_cfg; /* Pause frame source address config */
+ __be32 pfsa_0; /* Pause frame source address 0 */
+ __be32 pfsa_1; /* Pause frame source address 1 */
+ __be32 pfsa_2; /* Pause frame source address 2 */
+ __be32 flen; /* Frame length */
+ __be32 vlan_etype_0; /* VLAN ethertype 0 */
+ __be32 vlan_etype_1; /* VLAN ethertype 1 */
+ __be32 ier; /* Interrupt enable */
+ __be32 isr; /* Interrupt status */
+ __be32 rsvd0[0x36];
+ } core;
+
+ struct mac_port {
+ __be32 pstat; /* Port status */
+ __be32 pisr; /* Interrupt status */
+ __be32 pier; /* Interrupt enable */
+ __be32 ctrl_0; /* Control 0 */
+ __be32 ctrl_1; /* Control 1 */
+ __be32 ctrl_2; /* Control 2 */
+ __be32 ctrl_3; /* Control 3 */
+ __be32 ctrl_4; /* Control 4 */
+ __be32 ctrl_5; /* Control 5 */
+ __be32 rsvd0[0x2];
+ __be32 testen; /* Test enable */
+ } port[13];
+
+ __be32 rsvd0[0xa4];
+};
+
+/* Switch Fetch DMA registers */
+struct vr9_switch_fdma_regs {
+ struct fdma_core {
+ __be32 ctrl; /* FDMA control */
+ __be32 stetype; /* Special tag ethertype control */
+ __be32 vtetype; /* VLAN tag ethertype control */
+ __be32 stat; /* FDMA status */
+ __be32 ier; /* FDMA interrupt enable */
+ __be32 isr; /* FDMA interrupt status */
+ } core;
+
+ __be32 rsvd0[0x3a];
+
+ struct fdma_port {
+ __be32 pctrl; /* Port control */
+ __be32 prio; /* Port priority */
+ __be32 pstat_0; /* Port status 0 */
+ __be32 pstat_1; /* Port status 1 */
+ __be32 tstamp_0; /* Egress time stamp 0 */
+ __be32 tstamp_1; /* Egress time stamp 1 */
+ } port[13];
+
+ __be32 rsvd1[0x72];
+};
+
+/* Switch Store DMA registers */
+struct vr9_switch_sdma_regs {
+ struct sdma_core {
+ __be32 ctrl; /* SDMA Control */
+ __be32 fcthr_1; /* Flow control threshold 1 */
+ __be32 rsvd0;
+ __be32 fcthr_3; /* Flow control threshold 3 */
+ __be32 fcthr_4; /* Flow control threshold 4 */
+ __be32 fcthr_5; /* Flow control threshold 5 */
+ __be32 fcthr_6; /* Flow control threshold 6 */
+ __be32 fcthr_7; /* Flow control threshold 7 */
+ __be32 stat_0; /* SDMA status 0 */
+ __be32 stat_1; /* SDMA status 1 */
+ __be32 stat_2; /* SDMA status 2 */
+ __be32 ier; /* SDMA interrupt enable */
+ __be32 isr; /* SDMA interrupt status */
+ } core;
+
+ __be32 rsvd0[0x73];
+
+ struct sdma_port {
+ __be32 pctrl; /* Port control */
+ __be32 prio; /* Port priority */
+ __be32 pstat_0; /* Port status 0 */
+ __be32 pstat_1; /* Port status 1 */
+ __be32 tstamp_0; /* Ingress time stamp 0 */
+ __be32 tstamp_1; /* Ingress time stamp 1 */
+ } port[13];
+
+ __be32 rsvd1[0x32];
+};
+
+/* Switch MDIO control and status registers */
+struct vr9_switch_mdio_regs {
+ __be32 glob_ctrl; /* Global control 0 */
+ __be32 rsvd0[7];
+ __be32 mdio_ctrl; /* MDIO control */
+ __be32 mdio_read; /* MDIO read data */
+ __be32 mdio_write; /* MDIO write data */
+ __be32 mdc_cfg_0; /* MDC clock configuration 0 */
+ __be32 mdc_cfg_1; /* MDC clock configuration 1 */
+ __be32 rsvd1[0x3];
+ __be32 phy_addr[6]; /* PHY address port 5..0 */
+ __be32 mdio_stat[6]; /* MDIO PHY polling status port 0..5 */
+ __be32 aneg_eee[6]; /* EEE auto-neg overrides port 0..5 */
+ __be32 rsvd2[0x14];
+};
+
+static inline unsigned int to_mdio_phyaddr_id(unsigned int id)
+{
+ return 5 - id;
+}
+
+/* Switch xMII control registers */
+struct vr9_switch_mii_regs {
+ __be32 mii_cfg0; /* xMII port 0 configuration */
+ __be32 pcdu0; /* Port 0 clock delay configuration */
+ __be32 mii_cfg1; /* xMII port 1 configuration */
+ __be32 pcdu1; /* Port 1 clock delay configuration */
+ __be32 rsvd0[0x6];
+ __be32 mii_cfg5; /* xMII port 5 configuration */
+ __be32 pcdu5; /* Port 5 clock delay configuration */
+ __be32 rsvd1[0x14];
+ __be32 rxb_ctl_0; /* Port 0 receive buffer control */
+ __be32 rxb_ctl_1; /* Port 1 receive buffer control */
+ __be32 rxb_ctl_5; /* Port 5 receive buffer control */
+ __be32 rsvd2[0x28];
+ __be32 dbg_ctl; /* Debug control */
+};
+
+/* Switch Pseudo-MAC registers */
+struct vr9_switch_pmac_regs {
+ __be32 hd_ctl; /* PMAC header control */
+ __be32 tl; /* PMAC type/length */
+ __be32 sa1; /* PMAC source address 1 */
+ __be32 sa2; /* PMAC source address 2 */
+ __be32 sa3; /* PMAC source address 3 */
+ __be32 da1; /* PMAC destination address 1 */
+ __be32 da2; /* PMAC destination address 2 */
+ __be32 da3; /* PMAC destination address 3 */
+ __be32 vlan; /* PMAC VLAN */
+ __be32 rx_ipg; /* PMAC interpacket gap in RX direction */
+ __be32 st_etype; /* PMAC special tag ethertype */
+ __be32 ewan; /* PMAC ethernet WAN group */
+ __be32 ctl; /* PMAC control */
+ __be32 rsvd0[0x2];
+};
+
+struct vr9_switch_regs {
+ struct vr9_switch_core_regs core;
+ struct vr9_switch_bm_regs bm;
+ struct vr9_switch_pce_regs pce;
+ struct vr9_switch_mac_regs mac;
+ struct vr9_switch_fdma_regs fdma;
+ struct vr9_switch_sdma_regs sdma;
+ struct vr9_switch_mdio_regs mdio;
+ struct vr9_switch_mii_regs mii;
+ struct vr9_switch_pmac_regs pmac;
+};
+
+#define VR9_SWITCH_REG_OFFSET(reg) (4 * (reg))
+
+#define BUILD_CHECK_VR9_REG(name, offset) \
+ BUILD_BUG_ON(offsetof(struct vr9_switch_regs, name) != (4 * offset))
+
+static inline void build_check_vr9_registers(void)
+{
+ BUILD_CHECK_VR9_REG(core, 0x0);
+ BUILD_CHECK_VR9_REG(bm.core, 0x40);
+ BUILD_CHECK_VR9_REG(bm.core.queue_gctrl, 0x4a);
+ BUILD_CHECK_VR9_REG(bm.port[0], 0x80);
+ BUILD_CHECK_VR9_REG(bm.queue, 0x100);
+ BUILD_CHECK_VR9_REG(bm.shaper, 0x140);
+ BUILD_CHECK_VR9_REG(pce.core, 0x438);
+ BUILD_CHECK_VR9_REG(pce.core.tbl_ctrl, 0x44f);
+ BUILD_CHECK_VR9_REG(pce.core.parser_stat, 0x469);
+ BUILD_CHECK_VR9_REG(pce.port[0], 0x480);
+ BUILD_CHECK_VR9_REG(pce.meter[0], 0x580);
+ BUILD_CHECK_VR9_REG(mac.core, 0x8c0);
+ BUILD_CHECK_VR9_REG(mac.port[0].pstat, 0x900);
+ BUILD_CHECK_VR9_REG(mac.port[0].ctrl_0, 0x903);
+ BUILD_CHECK_VR9_REG(mac.port[1].pstat, 0x90c);
+ BUILD_CHECK_VR9_REG(mac.port[1].ctrl_0, 0x90f);
+ BUILD_CHECK_VR9_REG(mac.port[2].pstat, 0x918);
+ BUILD_CHECK_VR9_REG(mac.port[2].ctrl_0, 0x91b);
+ BUILD_CHECK_VR9_REG(fdma.core, 0xa40);
+ BUILD_CHECK_VR9_REG(fdma.port[0], 0xa80);
+ BUILD_CHECK_VR9_REG(sdma.core, 0xb40);
+ BUILD_CHECK_VR9_REG(sdma.port[0], 0xbc0);
+ BUILD_CHECK_VR9_REG(mdio, 0xc40);
+ BUILD_CHECK_VR9_REG(mii, (0xc40 + 0x36));
+ BUILD_CHECK_VR9_REG(pmac, (0xc40 + 0x82));
+}
+
+#define MAC_CTRL0_BM BIT(12)
+#define MAC_CTRL0_APADEN BIT(11)
+#define MAC_CTRL0_VPAD2EN BIT(10)
+#define MAC_CTRL0_VPADEN BIT(9)
+#define MAC_CTRL0_PADEN BIT(8)
+#define MAC_CTRL0_FCS BIT(7)
+#define MAC_CTRL0_FCON_SHIFT 4
+#define MAC_CTRL0_FCON_AUTO (0x0 << MAC_CTRL0_FCON_SHIFT)
+#define MAC_CTRL0_FCON_RX (0x1 << MAC_CTRL0_FCON_SHIFT)
+#define MAC_CTRL0_FCON_TX (0x2 << MAC_CTRL0_FCON_SHIFT)
+#define MAC_CTRL0_FCON_RXTX (0x3 << MAC_CTRL0_FCON_SHIFT)
+#define MAC_CTRL0_FCON_NONE (0x4 << MAC_CTRL0_FCON_SHIFT)
+#define MAC_CTRL0_FDUP_SHIFT 2
+#define MAC_CTRL0_FDUP_AUTO (0x0 << MAC_CTRL0_FDUP_SHIFT)
+#define MAC_CTRL0_FDUP_EN (0x1 << MAC_CTRL0_FDUP_SHIFT)
+#define MAC_CTRL0_FDUP_DIS (0x3 << MAC_CTRL0_FDUP_SHIFT)
+#define MAC_CTRL0_GMII_AUTO 0x0
+#define MAC_CTRL0_GMII_MII 0x1
+#define MAC_CTRL0_GMII_GMII 0x2
+#define MAC_CTRL0_GMII_GMII_2G 0x3
+
+#define MAC_CTRL1_DEFERMODE BIT(15)
+#define MAC_CTRL1_SHORTPRE BIT(8)
+
+#define MAC_CTRL2_MLEN BIT(3)
+#define MAC_CTRL2_LCHKL BIT(2)
+#define MAC_CTRL2_LCHKS_DIS 0x0
+#define MAC_CTRL2_LCHKS_UNTAG 0x1
+#define MAC_CTRL2_LCHKS_TAG 0x2
+
+#define PHY_ADDR_LNKST_SHIFT 13
+#define PHY_ADDR_LNKST_AUTO (0x0 << PHY_ADDR_LNKST_SHIFT)
+#define PHY_ADDR_LNKST_UP (0x1 << PHY_ADDR_LNKST_SHIFT)
+#define PHY_ADDR_LNKST_DOWN (0x2 << PHY_ADDR_LNKST_SHIFT)
+#define PHY_ADDR_SPEED_SHIFT 11
+#define PHY_ADDR_SPEED_M10 (0x0 << PHY_ADDR_SPEED_SHIFT)
+#define PHY_ADDR_SPEED_M100 (0x1 << PHY_ADDR_SPEED_SHIFT)
+#define PHY_ADDR_SPEED_G1 (0x2 << PHY_ADDR_SPEED_SHIFT)
+#define PHY_ADDR_SPEED_AUTO (0x3 << PHY_ADDR_SPEED_SHIFT)
+#define PHY_ADDR_FDUP_SHIFT 9
+#define PHY_ADDR_FDUP_AUTO (0x0 << PHY_ADDR_FDUP_SHIFT)
+#define PHY_ADDR_FDUP_EN (0x1 << PHY_ADDR_FDUP_SHIFT)
+#define PHY_ADDR_FDUP_DIS (0x3 << PHY_ADDR_FDUP_SHIFT)
+#define PHY_ADDR_FCONTX_SHIFT 7
+#define PHY_ADDR_FCONTX_AUTO (0x0 << PHY_ADDR_FCONTX_SHIFT)
+#define PHY_ADDR_FCONTX_EN (0x1 << PHY_ADDR_FCONTX_SHIFT)
+#define PHY_ADDR_FCONTX_DIS (0x3 << PHY_ADDR_FCONTX_SHIFT)
+#define PHY_ADDR_FCONRX_SHIFT 5
+#define PHY_ADDR_FCONRX_AUTO (0x0 << PHY_ADDR_FCONRX_SHIFT)
+#define PHY_ADDR_FCONRX_EN (0x1 << PHY_ADDR_FCONRX_SHIFT)
+#define PHY_ADDR_FCONRX_DIS (0x3 << PHY_ADDR_FCONRX_SHIFT)
+
+#define MII_CFG_RES BIT(15)
+#define MII_CFG_EN BIT(14)
+#define MII_CFG_LDCLKDIS BIT(12)
+#define MII_CFG_MIIRATE_SHIFT 4
+#define MII_CFG_MIIRATE_MASK (0x7 << MII_CFG_MIIRATE_SHIFT)
+#define MII_CFG_MIIRATE_M2P5 (0x0 << MII_CFG_MIIRATE_SHIFT)
+#define MII_CFG_MIIRATE_M25 (0x1 << MII_CFG_MIIRATE_SHIFT)
+#define MII_CFG_MIIRATE_M125 (0x2 << MII_CFG_MIIRATE_SHIFT)
+#define MII_CFG_MIIRATE_M50 (0x3 << MII_CFG_MIIRATE_SHIFT)
+#define MII_CFG_MIIRATE_AUTO (0x4 << MII_CFG_MIIRATE_SHIFT)
+#define MII_CFG_MIIMODE_MASK 0xf
+#define MII_CFG_MIIMODE_MIIP 0x0
+#define MII_CFG_MIIMODE_MIIM 0x1
+#define MII_CFG_MIIMODE_RMIIP 0x2
+#define MII_CFG_MIIMODE_RMIIM 0x3
+#define MII_CFG_MIIMODE_RGMII 0x4
+
+#define PMAC_HD_CTL_FC BIT(10)
+#define PMAC_HD_CTL_RST BIT(8)
+#define PMAC_HD_CTL_AST BIT(7)
+#define PMAC_HD_CTL_RXSH BIT(6)
+#define PMAC_HD_CTL_RC BIT(4)
+#define PMAC_HD_CTL_AS BIT(3)
+#define PMAC_HD_CTL_AC BIT(2)
+
+#define PCE_PCTRL_0_IGSTEN BIT(11)
+
+#define FDMA_PCTRL_STEN BIT(1)
+#define FDMA_PCTRL_EN BIT(0)
+
+#define SDMA_PCTRL_EN BIT(0)
+
+#define MDIO_CTRL_MBUSY BIT(12)
+#define MDIO_CTRL_OP_READ BIT(11)
+#define MDIO_CTRL_OP_WRITE BIT(10)
+#define MDIO_CTRL_PHYAD_SHIFT 5
+#define MDIO_CTRL_PHYAD_MASK (0x1f << MDIO_CTRL_PHYAD_SHIFT)
+#define MDIO_CTRL_REGAD_MASK 0x1f
+
+#endif /* __VR9_SWITCH_REGS_H__ */
diff --git a/arch/mips/lantiq/xway/xway_phy_fw.c b/arch/mips/lantiq/xway/xway_phy_fw.c
new file mode 100644
index 0000000..97a6d22
--- /dev/null
+++ b/arch/mips/lantiq/xway/xway_phy_fw.c
@@ -0,0 +1,146 @@
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/mm.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/ihex.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+
+#include <asm/checksum.h>
+
+#include <lantiq_soc.h>
+
+#include "vr9_switch_regs.h"
+
+#define XWAY_GPHY_FW_ALIGN (16 * 1024)
+#define XWAY_GPHY_FW_NAME_SIZE 32
+
+struct xway_gphy_core {
+ struct device *dev;
+ char fw_name[XWAY_GPHY_FW_NAME_SIZE];
+ dma_addr_t dev_addr;
+ void *fw_addr;
+ size_t fw_size;
+};
+
+static int xway_gphy_load(struct platform_device *pdev, struct xway_gphy_core *gphy)
+{
+ const struct firmware *fw;
+ dma_addr_t dev_addr;
+ void *fw_addr;
+ int err;
+ size_t size;
+ const char *fw_name;
+
+ err = of_property_read_string(pdev->dev.of_node, "firmware", &fw_name);
+ if (err) {
+ dev_err(&pdev->dev, "failed to load firmware filename\n");
+ return err;
+ }
+
+ if (strlen(fw_name) >= sizeof(gphy->fw_name)) {
+ dev_err(&pdev->dev, "firmware filename too long\n");
+ return ENAMETOOLONG;
+ }
+
+ strncpy(gphy->fw_name, fw_name, sizeof(gphy->fw_name));
+
+ dev_info(&pdev->dev, "requesting %s\n", gphy->fw_name);
+ err = request_firmware(&fw, gphy->fw_name, &pdev->dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to load firmware: %s\n", gphy->fw_name);
+ return err;
+ }
+
+ /*
+ * GPHY cores need the firmware code in a persistent and contiguous
+ * memory area with a 16 kB boundary aligned start address
+ */
+ size = fw->size + XWAY_GPHY_FW_ALIGN;
+ fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
+ if (!fw_addr) {
+ dev_err(&pdev->dev, "failed to alloc firmware memory\n");
+ goto err_release;
+ }
+
+ fw_addr = PTR_ALIGN(fw_addr, XWAY_GPHY_FW_ALIGN);
+ dev_addr = ALIGN(dev_addr, XWAY_GPHY_FW_ALIGN);
+
+ memcpy(fw_addr, fw->data, fw->size);
+ release_firmware(fw);
+
+ gphy->dev = &pdev->dev;
+ gphy->dev_addr = dev_addr;
+ gphy->fw_addr = fw_addr;
+ gphy->fw_size = size;
+
+ return 0;
+
+err_release:
+ release_firmware(fw);
+
+ return err;
+}
+
+static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
+{
+ struct xway_gphy_core gphy;
+ struct property *pp;
+ unsigned char *phyids;
+ int i, ret;
+
+ ret = xway_gphy_load(pdev, &gphy);
+ if (ret)
+ return ret;
+ pp = of_find_property(pdev->dev.of_node, "phys", NULL);
+ if (!pp)
+ return -ENOENT;
+ phyids = pp->value;
+ for (i = 0; i < pp->length && !ret; i++)
+ ret = xrx200_gphy_boot(&pdev->dev, phyids[i], gphy.dev_addr);
+ if (!ret)
+ mdelay(100);
+ return ret;
+}
+
+static const struct of_device_id xway_phy_match[] = {
+ { .compatible = "lantiq,phy-xrx200" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xway_phy_match);
+
+static struct platform_driver xway_phy_driver = {
+ .probe = xway_phy_fw_probe,
+ .driver = {
+ .name = "phy-xrx200",
+ .owner = THIS_MODULE,
+ .of_match_table = xway_phy_match,
+ },
+};
+
+module_platform_driver(xway_phy_driver);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
+MODULE_LICENSE("GPL");
+
--
1.7.10.4

View File

@ -0,0 +1,28 @@
From 00b0721cce51988b6dda27b21afb0e09c620bc21 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sat, 27 Oct 2012 09:14:17 +0200
Subject: [PATCH 107/113] MIPS: lantiq: add xrx200 ethernet clock
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/xway/sysctrl.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 2917b56..3925e66 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
+ clkdev_add_pmu("1e108000.eth", NULL, 0,
+ PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
+ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
+ PMU_PPE_QSB | PMU_PPE_TOP);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
ltq_ar9_fpi_hz());
--
1.7.10.4

View File

@ -0,0 +1,47 @@
From 5967e3171d56b7c433587aa418b87ae7fea02f28 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 10:25:39 +0200
Subject: [PATCH 109/113] MTD: lantiq: xway: fix NAND reset timeout handling
Fixes a possible deadlock in the code that resets the NAND flash.
http://lists.infradead.org/pipermail/linux-mtd/2012-September/044240.html
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/mtd/nand/xway_nand.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c
index 3f81dc8..4731300 100644
--- a/drivers/mtd/nand/xway_nand.c
+++ b/drivers/mtd/nand/xway_nand.c
@@ -58,15 +58,23 @@ static void xway_reset_chip(struct nand_chip *chip)
{
unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W;
unsigned long flags;
+ unsigned long timeout;
nandaddr &= ~NAND_WRITE_ADDR;
nandaddr |= NAND_WRITE_CMD;
/* finish with a reset */
+ timeout = jiffies + msecs_to_jiffies(200);
+
spin_lock_irqsave(&ebu_lock, flags);
+
writeb(NAND_WRITE_CMD_RESET, (void __iomem *) nandaddr);
- while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
- ;
+ do {
+ if ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+ break;
+ cond_resched();
+ } while (!time_after_eq(jiffies, timeout));
+
spin_unlock_irqrestore(&ebu_lock, flags);
}
--
1.7.10.4

View File

@ -0,0 +1,228 @@
From 2fa550e1ca132377ee4910eaaf331a257190b75e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 09:28:30 +0200
Subject: [PATCH 110/113] NET: PHY: adds driver for lantiq PHY11G
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/net/phy/Kconfig | 5 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/lantiq.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 184 insertions(+)
create mode 100644 drivers/net/phy/lantiq.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 983bbf4..a7ff1d2 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -102,6 +102,11 @@ config MICREL_PHY
---help---
Supports the KSZ9021, VSC8201, KS8001 PHYs.
+config LANTIQ_PHY
+ tristate "Driver for Lantiq PHYs"
+ ---help---
+ Supports the 11G and 22E PHYs.
+
config FIXED_PHY
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB=y
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 426674d..3aa92bf 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
+obj-$(CONFIG_LANTIQ_PHY) += lantiq.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_AMD_PHY) += amd.o
diff --git a/drivers/net/phy/lantiq.c b/drivers/net/phy/lantiq.c
new file mode 100644
index 0000000..ba4d7b7
--- /dev/null
+++ b/drivers/net/phy/lantiq.c
@@ -0,0 +1,178 @@
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define MII_MMDCTRL 0x0d
+#define MII_MMDDATA 0x0e
+
+#define MII_VR9_11G_IMASK 0x19 /* interrupt mask */
+#define MII_VR9_11G_ISTAT 0x1a /* interrupt status */
+
+#define INT_VR9_11G_WOL BIT(15) /* Wake-On-LAN */
+#define INT_VR9_11G_ANE BIT(11) /* Auto-Neg error */
+#define INT_VR9_11G_ANC BIT(10) /* Auto-Neg complete */
+#define INT_VR9_11G_ADSC BIT(5) /* Link auto-downspeed detect */
+#define INT_VR9_11G_DXMC BIT(2) /* Duplex mode change */
+#define INT_VR9_11G_LSPC BIT(1) /* Link speed change */
+#define INT_VR9_11G_LSTC BIT(0) /* Link state change */
+#define INT_VR9_11G_MASK (INT_VR9_11G_LSTC | INT_VR9_11G_ADSC)
+
+#define ADVERTISED_MPD BIT(10) /* Multi-port device */
+
+#define MMD_DEVAD 0x1f
+#define MMD_ACTYPE_SHIFT 14
+#define MMD_ACTYPE_ADDRESS (0 << MMD_ACTYPE_SHIFT)
+#define MMD_ACTYPE_DATA (1 << MMD_ACTYPE_SHIFT)
+#define MMD_ACTYPE_DATA_PI (2 << MMD_ACTYPE_SHIFT)
+#define MMD_ACTYPE_DATA_PIWR (3 << MMD_ACTYPE_SHIFT)
+
+static __maybe_unused int vr9_gphy_mmd_read(struct phy_device *phydev,
+ u16 regnum)
+{
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
+ phy_write(phydev, MII_MMDDATA, regnum);
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
+
+ return phy_read(phydev, MII_MMDDATA);
+}
+
+static __maybe_unused int vr9_gphy_mmd_write(struct phy_device *phydev,
+ u16 regnum, u16 val)
+{
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
+ phy_write(phydev, MII_MMDDATA, regnum);
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
+ phy_write(phydev, MII_MMDDATA, val);
+
+ return 0;
+}
+
+static int vr9_gphy_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ dev_dbg(&phydev->dev, "%s\n", __func__);
+
+ /* Mask all interrupts */
+ err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
+ if (err)
+ return err;
+
+ /* Clear all pending interrupts */
+ phy_read(phydev, MII_VR9_11G_ISTAT);
+
+ return 0;
+}
+
+static int vr9_gphy_config_aneg(struct phy_device *phydev)
+{
+ int reg, err;
+
+ /* Advertise as multi-port device */
+ reg = phy_read(phydev, MII_CTRL1000);
+ reg |= ADVERTISED_MPD;
+ err = phy_write(phydev, MII_CTRL1000, reg);
+ if (err)
+ return err;
+
+ return genphy_config_aneg(phydev);
+}
+
+static int vr9_gphy_ack_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ /*
+ * Possible IRQ numbers:
+ * - IM3_IRL18 for GPHY0
+ * - IM3_IRL17 for GPHY1
+ *
+ * Due to a silicon bug IRQ lines are not really independent from
+ * each other. Sometimes the two lines are driven at the same time
+ * if only one GPHY core raises the interrupt.
+ */
+
+ reg = phy_read(phydev, MII_VR9_11G_ISTAT);
+
+ return (reg < 0) ? reg : 0;
+}
+
+static int vr9_gphy_did_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ reg = phy_read(phydev, MII_VR9_11G_ISTAT);
+
+ return reg > 0;
+}
+
+static int vr9_gphy_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_VR9_11G_IMASK, INT_VR9_11G_MASK);
+ else
+ err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
+
+ return err;
+}
+
+/* TODO: add vr9_gphy_22f_driver and drivers for external Lantiq PEF7071 PHYs */
+static struct phy_driver vr9_gphy_11g_driver = {
+ .phy_id = 0xd565a408,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Lantiq XWAY VR9 GPHY 11G",
+ .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
+ .flags = 0, /*PHY_HAS_INTERRUPT,*/
+ .config_init = vr9_gphy_config_init,
+ .config_aneg = vr9_gphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = vr9_gphy_ack_interrupt,
+ .did_interrupt = vr9_gphy_did_interrupt,
+ .config_intr = vr9_gphy_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static int __init ltq_phy_init(void)
+{
+ int err;
+
+ err = phy_driver_register(&vr9_gphy_11g_driver);
+ if (err)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ return err;
+}
+
+static void __exit ltq_phy_exit(void)
+{
+ phy_driver_unregister(&vr9_gphy_11g_driver);
+}
+
+module_init(ltq_phy_init);
+module_exit(ltq_phy_exit);
+
+MODULE_DESCRIPTION("Lantiq PHY drivers");
+MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
+MODULE_LICENSE("GPL");
--
1.7.10.4

View File

@ -0,0 +1,807 @@
From 6db31b14d4998f480349dd5f1ef83dc68a1fab0c Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 24 Oct 2012 19:50:30 +0200
Subject: [PATCH 111/113] NET: MIPS: lantiq: update etop driver for devicetree
---
drivers/net/ethernet/lantiq_etop.c | 470 +++++++++++++++++++++++++-----------
1 file changed, 333 insertions(+), 137 deletions(-)
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 003c5bc..dc5457a 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -12,7 +12,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2011-12 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
@@ -36,6 +36,10 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/of_net.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
#include <asm/checksum.h>
@@ -71,25 +75,56 @@
#define ETOP_MII_REVERSE 0xe
#define ETOP_PLEN_UNDER 0x40
#define ETOP_CGEN 0x800
-
-/* use 2 static channels for TX/RX */
-#define LTQ_ETOP_TX_CHANNEL 1
-#define LTQ_ETOP_RX_CHANNEL 6
-#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
-#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
-
+#define ETOP_CFG_MII0 0x01
+
+#define LTQ_GBIT_MDIO_CTL 0xCC
+#define LTQ_GBIT_MDIO_DATA 0xd0
+#define LTQ_GBIT_GCTL0 0x68
+#define LTQ_GBIT_PMAC_HD_CTL 0x8c
+#define LTQ_GBIT_P0_CTL 0x4
+#define LTQ_GBIT_PMAC_RX_IPG 0xa8
+
+#define PMAC_HD_CTL_AS (1 << 19)
+#define PMAC_HD_CTL_RXSH (1 << 22)
+
+/* Switch Enable (0=disable, 1=enable) */
+#define GCTL0_SE 0x80000000
+/* Disable MDIO auto polling (0=disable, 1=enable) */
+#define PX_CTL_DMDIO 0x00400000
+
+/* register information for the gbit's MDIO bus */
+#define MDIO_XR9_REQUEST 0x00008000
+#define MDIO_XR9_READ 0x00000800
+#define MDIO_XR9_WRITE 0x00000400
+#define MDIO_XR9_REG_MASK 0x1f
+#define MDIO_XR9_ADDR_MASK 0x1f
+#define MDIO_XR9_RD_MASK 0xffff
+#define MDIO_XR9_REG_OFFSET 0
+#define MDIO_XR9_ADDR_OFFSET 5
+#define MDIO_XR9_WR_OFFSET 16
+
+#define LTQ_DMA_ETOP ((of_machine_is_compatible("lantiq,ase")) ? \
+ (INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0))
+
+/* the newer xway socks have a embedded 3/7 port gbit multiplexer */
#define ltq_etop_r32(x) ltq_r32(ltq_etop_membase + (x))
#define ltq_etop_w32(x, y) ltq_w32(x, ltq_etop_membase + (y))
#define ltq_etop_w32_mask(x, y, z) \
ltq_w32_mask(x, y, ltq_etop_membase + (z))
-#define DRV_VERSION "1.0"
+#define ltq_gbit_r32(x) ltq_r32(ltq_gbit_membase + (x))
+#define ltq_gbit_w32(x, y) ltq_w32(x, ltq_gbit_membase + (y))
+#define ltq_gbit_w32_mask(x, y, z) \
+ ltq_w32_mask(x, y, ltq_gbit_membase + (z))
+
+#define DRV_VERSION "1.2"
static void __iomem *ltq_etop_membase;
+static void __iomem *ltq_gbit_membase;
struct ltq_etop_chan {
- int idx;
int tx_free;
+ int irq;
struct net_device *netdev;
struct napi_struct napi;
struct ltq_dma_channel dma;
@@ -99,22 +134,35 @@ struct ltq_etop_chan {
struct ltq_etop_priv {
struct net_device *netdev;
struct platform_device *pdev;
- struct ltq_eth_data *pldata;
struct resource *res;
struct mii_bus *mii_bus;
struct phy_device *phydev;
- struct ltq_etop_chan ch[MAX_DMA_CHAN];
- int tx_free[MAX_DMA_CHAN >> 1];
+ struct ltq_etop_chan txch;
+ struct ltq_etop_chan rxch;
+
+ int tx_irq;
+ int rx_irq;
+
+ const void *mac;
+ int mii_mode;
spinlock_t lock;
+
+ struct clk *clk_ppe;
+ struct clk *clk_switch;
+ struct clk *clk_ephy;
+ struct clk *clk_ephycgu;
};
+static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr,
+ int phy_reg, u16 phy_data);
+
static int
ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
{
- ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN);
+ ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
if (!ch->skb[ch->dma.desc])
return -ENOMEM;
ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
@@ -149,8 +197,11 @@ ltq_etop_hw_receive(struct ltq_etop_chan *ch)
spin_unlock_irqrestore(&priv->lock, flags);
skb_put(skb, len);
+ skb->dev = ch->netdev;
skb->protocol = eth_type_trans(skb, ch->netdev);
netif_receive_skb(skb);
+ ch->netdev->stats.rx_packets++;
+ ch->netdev->stats.rx_bytes += len;
}
static int
@@ -158,8 +209,10 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
{
struct ltq_etop_chan *ch = container_of(napi,
struct ltq_etop_chan, napi);
+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
int rx = 0;
int complete = 0;
+ unsigned long flags;
while ((rx < budget) && !complete) {
struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
@@ -173,7 +226,9 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
}
if (complete || !rx) {
napi_complete(&ch->napi);
+ spin_lock_irqsave(&priv->lock, flags);
ltq_dma_ack_irq(&ch->dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return rx;
}
@@ -185,12 +240,14 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
container_of(napi, struct ltq_etop_chan, napi);
struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
struct netdev_queue *txq =
- netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
+ netdev_get_tx_queue(ch->netdev, ch->dma.nr >> 1);
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
while ((ch->dma.desc_base[ch->tx_free].ctl &
(LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ ch->netdev->stats.tx_packets++;
+ ch->netdev->stats.tx_bytes += ch->skb[ch->tx_free]->len;
dev_kfree_skb_any(ch->skb[ch->tx_free]);
ch->skb[ch->tx_free] = NULL;
memset(&ch->dma.desc_base[ch->tx_free], 0,
@@ -203,7 +260,9 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
if (netif_tx_queue_stopped(txq))
netif_tx_start_queue(txq);
napi_complete(&ch->napi);
+ spin_lock_irqsave(&priv->lock, flags);
ltq_dma_ack_irq(&ch->dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
return 1;
}
@@ -211,9 +270,10 @@ static irqreturn_t
ltq_etop_dma_irq(int irq, void *_priv)
{
struct ltq_etop_priv *priv = _priv;
- int ch = irq - LTQ_DMA_CH0_INT;
-
- napi_schedule(&priv->ch[ch].napi);
+ if (irq == priv->txch.dma.irq)
+ napi_schedule(&priv->txch.napi);
+ else
+ napi_schedule(&priv->rxch.napi);
return IRQ_HANDLED;
}
@@ -225,7 +285,7 @@ ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
ltq_dma_free(&ch->dma);
if (ch->dma.irq)
free_irq(ch->dma.irq, priv);
- if (IS_RX(ch->idx)) {
+ if (ch == &priv->txch) {
int desc;
for (desc = 0; desc < LTQ_DESC_NUM; desc++)
dev_kfree_skb_any(ch->skb[ch->dma.desc]);
@@ -236,23 +296,55 @@ static void
ltq_etop_hw_exit(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
- ltq_pmu_disable(PMU_PPE);
- for (i = 0; i < MAX_DMA_CHAN; i++)
- if (IS_TX(i) || IS_RX(i))
- ltq_etop_free_channel(dev, &priv->ch[i]);
+ clk_disable(priv->clk_ppe);
+
+ if (of_machine_is_compatible("lantiq,ar9"))
+ clk_disable(priv->clk_switch);
+
+ if (of_machine_is_compatible("lantiq,ase")) {
+ clk_disable(priv->clk_ephy);
+ clk_disable(priv->clk_ephycgu);
+ }
+
+ ltq_etop_free_channel(dev, &priv->txch);
+ ltq_etop_free_channel(dev, &priv->rxch);
+}
+
+static void
+ltq_etop_gbit_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ clk_enable(priv->clk_switch);
+
+ ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
+ /** Disable MDIO auto polling mode */
+ ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL);
+ /* set 1522 packet size */
+ ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0);
+ /* disable pmac & dmac headers */
+ ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0,
+ LTQ_GBIT_PMAC_HD_CTL);
+ /* Due to traffic halt when burst length 8,
+ replace default IPG value with 0x3B */
+ ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG);
}
static int
ltq_etop_hw_init(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
- ltq_pmu_enable(PMU_PPE);
+ clk_enable(priv->clk_ppe);
- switch (priv->pldata->mii_mode) {
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ ltq_etop_gbit_init(dev);
+ /* force the etops link to the gbit to MII */
+ priv->mii_mode = PHY_INTERFACE_MODE_MII;
+ }
+
+ switch (priv->mii_mode) {
case PHY_INTERFACE_MODE_RMII:
ltq_etop_w32_mask(ETOP_MII_MASK,
ETOP_MII_REVERSE, LTQ_ETOP_CFG);
@@ -264,39 +356,68 @@ ltq_etop_hw_init(struct net_device *dev)
break;
default:
+ if (of_machine_is_compatible("lantiq,ase")) {
+ clk_enable(priv->clk_ephy);
+ /* disable external MII */
+ ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG);
+ /* enable clock for internal PHY */
+ clk_enable(priv->clk_ephycgu);
+ /* we need to write this magic to the internal phy to
+ make it work */
+ ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
+ pr_info("Selected EPHY mode\n");
+ break;
+ }
netdev_err(dev, "unknown mii mode %d\n",
- priv->pldata->mii_mode);
+ priv->mii_mode);
return -ENOTSUPP;
}
/* enable crc generation */
ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG);
+ return 0;
+}
+
+static int
+ltq_etop_dma_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int tx = priv->tx_irq - LTQ_DMA_ETOP;
+ int rx = priv->rx_irq - LTQ_DMA_ETOP;
+ int err;
+
ltq_dma_init_port(DMA_PORT_ETOP);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- int irq = LTQ_DMA_CH0_INT + i;
- struct ltq_etop_chan *ch = &priv->ch[i];
-
- ch->idx = ch->dma.nr = i;
-
- if (IS_TX(i)) {
- ltq_dma_alloc_tx(&ch->dma);
- request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
- "etop_tx", priv);
- } else if (IS_RX(i)) {
- ltq_dma_alloc_rx(&ch->dma);
- for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
- ch->dma.desc++)
- if (ltq_etop_alloc_skb(ch))
- return -ENOMEM;
- ch->dma.desc = 0;
- request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
- "etop_rx", priv);
+ priv->txch.dma.nr = tx;
+ ltq_dma_alloc_tx(&priv->txch.dma);
+ err = request_irq(priv->tx_irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "eth_tx", priv);
+ if (err) {
+ netdev_err(dev, "failed to allocate tx irq\n");
+ goto err_out;
+ }
+ priv->txch.dma.irq = priv->tx_irq;
+
+ priv->rxch.dma.nr = rx;
+ ltq_dma_alloc_rx(&priv->rxch.dma);
+ for (priv->rxch.dma.desc = 0; priv->rxch.dma.desc < LTQ_DESC_NUM;
+ priv->rxch.dma.desc++) {
+ if (ltq_etop_alloc_skb(&priv->rxch)) {
+ netdev_err(dev, "failed to allocate skbs\n");
+ err = -ENOMEM;
+ goto err_out;
}
- ch->dma.irq = irq;
}
- return 0;
+ priv->rxch.dma.desc = 0;
+ err = request_irq(priv->rx_irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "eth_rx", priv);
+ if (err)
+ netdev_err(dev, "failed to allocate rx irq\n");
+ else
+ priv->rxch.dma.irq = priv->rx_irq;
+err_out:
+ return err;
}
static void
@@ -312,7 +433,10 @@ ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- return phy_ethtool_gset(priv->phydev, cmd);
+ if (priv->phydev)
+ return phy_ethtool_gset(priv->phydev, cmd);
+ else
+ return 0;
}
static int
@@ -320,7 +444,10 @@ ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- return phy_ethtool_sset(priv->phydev, cmd);
+ if (priv->phydev)
+ return phy_ethtool_sset(priv->phydev, cmd);
+ else
+ return 0;
}
static int
@@ -328,7 +455,10 @@ ltq_etop_nway_reset(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- return phy_start_aneg(priv->phydev);
+ if (priv->phydev)
+ return phy_start_aneg(priv->phydev);
+ else
+ return 0;
}
static const struct ethtool_ops ltq_etop_ethtool_ops = {
@@ -339,6 +469,39 @@ static const struct ethtool_ops ltq_etop_ethtool_ops = {
};
static int
+ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr,
+ int phy_reg, u16 phy_data)
+{
+ u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE |
+ (phy_data << MDIO_XR9_WR_OFFSET) |
+ ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
+ ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
+
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ return 0;
+}
+
+static int
+ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+ u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ |
+ ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
+ ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
+
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK;
+ return val;
+}
+
+static int
ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
{
u32 val = MDIO_REQUEST |
@@ -379,14 +542,11 @@ ltq_etop_mdio_probe(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
struct phy_device *phydev = NULL;
- int phy_addr;
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- if (priv->mii_bus->phy_map[phy_addr]) {
- phydev = priv->mii_bus->phy_map[phy_addr];
- break;
- }
- }
+ if (of_machine_is_compatible("lantiq,ase"))
+ phydev = priv->mii_bus->phy_map[8];
+ else
+ phydev = priv->mii_bus->phy_map[0];
if (!phydev) {
netdev_err(dev, "no PHY found\n");
@@ -394,7 +554,7 @@ ltq_etop_mdio_probe(struct net_device *dev)
}
phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
- 0, priv->pldata->mii_mode);
+ 0, priv->mii_mode);
if (IS_ERR(phydev)) {
netdev_err(dev, "Could not attach to PHY\n");
@@ -408,6 +568,9 @@ ltq_etop_mdio_probe(struct net_device *dev)
| SUPPORTED_Autoneg
| SUPPORTED_MII
| SUPPORTED_TP);
+ if (of_machine_is_compatible("lantiq,ar9"))
+ phydev->supported &= SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full;
phydev->advertising = phydev->supported;
priv->phydev = phydev;
@@ -433,8 +596,13 @@ ltq_etop_mdio_init(struct net_device *dev)
}
priv->mii_bus->priv = dev;
- priv->mii_bus->read = ltq_etop_mdio_rd;
- priv->mii_bus->write = ltq_etop_mdio_wr;
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ priv->mii_bus->read = ltq_etop_mdio_rd_xr9;
+ priv->mii_bus->write = ltq_etop_mdio_wr_xr9;
+ } else {
+ priv->mii_bus->read = ltq_etop_mdio_rd;
+ priv->mii_bus->write = ltq_etop_mdio_wr;
+ }
priv->mii_bus->name = "ltq_mii";
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
priv->pdev->name, priv->pdev->id);
@@ -483,17 +651,19 @@ static int
ltq_etop_open(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
+ unsigned long flags;
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- struct ltq_etop_chan *ch = &priv->ch[i];
+ napi_enable(&priv->txch.napi);
+ napi_enable(&priv->rxch.napi);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_dma_open(&priv->txch.dma);
+ ltq_dma_open(&priv->rxch.dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (priv->phydev)
+ phy_start(priv->phydev);
- if (!IS_TX(i) && (!IS_RX(i)))
- continue;
- ltq_dma_open(&ch->dma);
- napi_enable(&ch->napi);
- }
- phy_start(priv->phydev);
netif_tx_start_all_queues(dev);
return 0;
}
@@ -502,18 +672,19 @@ static int
ltq_etop_stop(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
+ unsigned long flags;
netif_tx_stop_all_queues(dev);
- phy_stop(priv->phydev);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- struct ltq_etop_chan *ch = &priv->ch[i];
+ if (priv->phydev)
+ phy_stop(priv->phydev);
+ napi_disable(&priv->txch.napi);
+ napi_disable(&priv->rxch.napi);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_dma_close(&priv->txch.dma);
+ ltq_dma_close(&priv->rxch.dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
- if (!IS_RX(i) && !IS_TX(i))
- continue;
- napi_disable(&ch->napi);
- ltq_dma_close(&ch->dma);
- }
return 0;
}
@@ -523,16 +694,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
int queue = skb_get_queue_mapping(skb);
struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
struct ltq_etop_priv *priv = netdev_priv(dev);
- struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
- struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
- int len;
+ struct ltq_dma_desc *desc =
+ &priv->txch.dma.desc_base[priv->txch.dma.desc];
unsigned long flags;
u32 byte_offset;
+ int len;
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
- dev_kfree_skb_any(skb);
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) ||
+ priv->txch.skb[priv->txch.dma.desc]) {
netdev_err(dev, "tx ring full\n");
netif_tx_stop_queue(txq);
return NETDEV_TX_BUSY;
@@ -540,7 +711,7 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
/* dma needs to start on a 16 byte aligned address */
byte_offset = CPHYSADDR(skb->data) % 16;
- ch->skb[ch->dma.desc] = skb;
+ priv->txch.skb[priv->txch.dma.desc] = skb;
dev->trans_start = jiffies;
@@ -550,11 +721,11 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
wmb();
desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
- ch->dma.desc++;
- ch->dma.desc %= LTQ_DESC_NUM;
+ priv->txch.dma.desc++;
+ priv->txch.dma.desc %= LTQ_DESC_NUM;
spin_unlock_irqrestore(&priv->lock, flags);
- if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
+ if (priv->txch.dma.desc_base[priv->txch.dma.desc].ctl & LTQ_DMA_OWN)
netif_tx_stop_queue(txq);
return NETDEV_TX_OK;
@@ -633,34 +804,32 @@ ltq_etop_init(struct net_device *dev)
struct ltq_etop_priv *priv = netdev_priv(dev);
struct sockaddr mac;
int err;
- bool random_mac = false;
ether_setup(dev);
dev->watchdog_timeo = 10 * HZ;
err = ltq_etop_hw_init(dev);
if (err)
goto err_hw;
+ err = ltq_etop_dma_init(dev);
+ if (err)
+ goto err_hw;
+
ltq_etop_change_mtu(dev, 1500);
- memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
+ memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
if (!is_valid_ether_addr(mac.sa_data)) {
pr_warn("etop: invalid MAC, using random\n");
- eth_random_addr(mac.sa_data);
- random_mac = true;
+ random_ether_addr(mac.sa_data);
}
err = ltq_etop_set_mac_address(dev, &mac);
if (err)
goto err_netdev;
-
- /* Set addr_assign_type here, ltq_etop_set_mac_address would reset it. */
- if (random_mac)
- dev->addr_assign_type |= NET_ADDR_RANDOM;
-
ltq_etop_set_multicast_list(dev);
- err = ltq_etop_mdio_init(dev);
- if (err)
- goto err_netdev;
+ if (!ltq_etop_mdio_init(dev))
+ dev->ethtool_ops = &ltq_etop_ethtool_ops;
+ else
+ pr_warn("etop: mdio probe failed\n");;
return 0;
err_netdev:
@@ -680,6 +849,9 @@ ltq_etop_tx_timeout(struct net_device *dev)
err = ltq_etop_hw_init(dev);
if (err)
goto err_hw;
+ err = ltq_etop_dma_init(dev);
+ if (err)
+ goto err_hw;
dev->trans_start = jiffies;
netif_wake_queue(dev);
return;
@@ -703,14 +875,19 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
.ndo_tx_timeout = ltq_etop_tx_timeout,
};
-static int __init
+static int __devinit
ltq_etop_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct ltq_etop_priv *priv;
- struct resource *res;
+ struct resource *res, *gbit_res, irqres[2];
int err;
- int i;
+
+ err = of_irq_to_resource_table(pdev->dev.of_node, irqres, 2);
+ if (err != 2) {
+ dev_err(&pdev->dev, "failed to get etop irqs\n");
+ return -EINVAL;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -736,30 +913,58 @@ ltq_etop_probe(struct platform_device *pdev)
goto err_out;
}
- dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
- if (!dev) {
- err = -ENOMEM;
- goto err_out;
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!gbit_res) {
+ dev_err(&pdev->dev, "failed to get gbit resource\n");
+ err = -ENOENT;
+ goto err_out;
+ }
+ ltq_gbit_membase = devm_ioremap_nocache(&pdev->dev,
+ gbit_res->start, resource_size(gbit_res));
+ if (!ltq_gbit_membase) {
+ dev_err(&pdev->dev, "failed to remap gigabit switch %d\n",
+ pdev->id);
+ err = -ENOMEM;
+ goto err_out;
+ }
}
+
+ dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
strcpy(dev->name, "eth%d");
dev->netdev_ops = &ltq_eth_netdev_ops;
- dev->ethtool_ops = &ltq_etop_ethtool_ops;
priv = netdev_priv(dev);
priv->res = res;
priv->pdev = pdev;
- priv->pldata = dev_get_platdata(&pdev->dev);
priv->netdev = dev;
+ priv->tx_irq = irqres[0].start;
+ priv->rx_irq = irqres[1].start;
+ priv->mii_mode = of_get_phy_mode(pdev->dev.of_node);
+ priv->mac = of_get_mac_address(pdev->dev.of_node);
+
+ priv->clk_ppe = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk_ppe))
+ return PTR_ERR(priv->clk_ppe);
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ priv->clk_switch = clk_get(&pdev->dev, "switch");
+ if (IS_ERR(priv->clk_switch))
+ return PTR_ERR(priv->clk_switch);
+ }
+ if (of_machine_is_compatible("lantiq,ase")) {
+ priv->clk_ephy = clk_get(&pdev->dev, "ephy");
+ if (IS_ERR(priv->clk_ephy))
+ return PTR_ERR(priv->clk_ephy);
+ priv->clk_ephycgu = clk_get(&pdev->dev, "ephycgu");
+ if (IS_ERR(priv->clk_ephycgu))
+ return PTR_ERR(priv->clk_ephycgu);
+ }
+
spin_lock_init(&priv->lock);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- if (IS_TX(i))
- netif_napi_add(dev, &priv->ch[i].napi,
- ltq_etop_poll_tx, 8);
- else if (IS_RX(i))
- netif_napi_add(dev, &priv->ch[i].napi,
- ltq_etop_poll_rx, 32);
- priv->ch[i].netdev = dev;
- }
+ netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8);
+ netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32);
+ priv->txch.netdev = dev;
+ priv->rxch.netdev = dev;
err = register_netdev(dev);
if (err)
@@ -788,32 +993,23 @@ ltq_etop_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id ltq_etop_match[] = {
+ { .compatible = "lantiq,etop-xway" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ltq_etop_match);
+
static struct platform_driver ltq_mii_driver = {
+ .probe = ltq_etop_probe,
.remove = __devexit_p(ltq_etop_remove),
.driver = {
.name = "ltq_etop",
.owner = THIS_MODULE,
+ .of_match_table = ltq_etop_match,
},
};
-int __init
-init_ltq_etop(void)
-{
- int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
-
- if (ret)
- pr_err("ltq_etop: Error registering platform driver!");
- return ret;
-}
-
-static void __exit
-exit_ltq_etop(void)
-{
- platform_driver_unregister(&ltq_mii_driver);
-}
-
-module_init(init_ltq_etop);
-module_exit(exit_ltq_etop);
+module_platform_driver(ltq_mii_driver);
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("Lantiq SoC ETOP");
--
1.7.10.4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,539 @@
From b072ba5c8e730b6d6e828cbc7caf99f669667831 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 12:22:10 +0200
Subject: [PATCH 113/113] EASY80920 dts file
---
arch/mips/lantiq/Kconfig | 4 +
arch/mips/lantiq/dts/Makefile | 1 +
arch/mips/lantiq/dts/easy80920.dts | 369 ++++++++++++++++++++++++++++++++++++
arch/mips/lantiq/dts/vr9.dtsi | 116 ++++++++++++
4 files changed, 490 insertions(+)
create mode 100644 arch/mips/lantiq/dts/easy80920.dts
create mode 100644 arch/mips/lantiq/dts/vr9.dtsi
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index d84f361..c9d0984 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -30,6 +30,10 @@ choice
config DT_EASY50712
bool "Easy50712"
depends on SOC_XWAY
+
+config DT_EASY80920
+ bool "Easy80920"
+ depends on SOC_XWAY
endchoice
config PCI_LANTIQ
diff --git a/arch/mips/lantiq/dts/Makefile b/arch/mips/lantiq/dts/Makefile
index 674fca4..0876c97 100644
--- a/arch/mips/lantiq/dts/Makefile
+++ b/arch/mips/lantiq/dts/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o
+obj-$(CONFIG_DT_EASY80920) := easy80920.dtb.o
$(obj)/%.dtb: $(obj)/%.dts
$(call if_changed,dtc)
diff --git a/arch/mips/lantiq/dts/easy80920.dts b/arch/mips/lantiq/dts/easy80920.dts
new file mode 100644
index 0000000..703e768
--- /dev/null
+++ b/arch/mips/lantiq/dts/easy80920.dts
@@ -0,0 +1,369 @@
+/dts-v1/;
+
+
+/include/ "vr9.dtsi"
+
+/ {
+ chosen {
+ bootargs = "console=ttyLTQ0,115200 init=/etc/preinit";
+ };
+
+ memory@0 {
+ reg = <0x0 0x4000000>;
+ };
+
+ fpi@10000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "lantiq,fpi", "simple-bus";
+ ranges = <0x0 0x10000000 0xEEFFFFF>;
+ reg = <0x10000000 0xEF00000>;
+
+ localbus@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "lantiq,localbus", "simple-bus";
+
+ ranges = <0 0 0x0 0x3ffffff>;
+ nor-boot@0 {
+ compatible = "lantiq,nor";
+ bank-width = <2>;
+ reg = <0 0x0 0x2000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x00000 0x10000>;
+ };
+
+ partition@10000 {
+ label = "uboot_env";
+ reg = <0x10000 0x10000>;
+ };
+
+ partition@20000 {
+ label = "linux";
+ reg = <0x20000 0x7e0000>;
+ };
+ };
+
+ /*ranges = <0 0 0x4000000 0x3ffffff>;
+ nand-parts@0 {
+ compatible = "gen_nand", "lantiq,nand-xway";
+ lantiq,cs = <1>;
+ bank-width = <2>;
+ reg = <0 0x0 0x2000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x00000 0x40000>;
+ };
+
+ partition@10000 {
+ label = "uboot_env";
+ reg = <0x40000 0x40000>;
+ };
+
+ partition@20000 {
+ label = "linux";
+ reg = <0x80000 0x3f80000>;
+ };
+ };*/
+ };
+
+ sflash@E100800 {
+ compatible = "lantiq,sflash";
+ reg = <0xE100800 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x00000 0x10000>;
+ };
+
+ partition@10000 {
+ label = "uboot_env";
+ reg = <0x10000 0x10000>;
+ };
+
+ partition@20000 {
+ label = "linux";
+ reg = <0x20000 0x1d0000>;
+ };
+ };
+
+ gpio: pinmux@E100B10 {
+ compatible = "lantiq,pinctrl-xr9";
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ interrupt-parent = <&icu0>;
+ interrupts = <166 135 66 40 41 42 38>;
+
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0xE100B10 0xA0>;
+
+ state_default: pinmux {
+ stp {
+ lantiq,groups = "stp";
+ lantiq,function = "stp";
+ };
+ /*spi {
+ lantiq,groups = "spi", "spi_cs4";
+ lantiq,function = "spi";
+ };*/
+ nand {
+ lantiq,groups = "nand cle", "nand ale",
+ "nand rd", "nand rdy";
+ lantiq,function = "ebu";
+ };
+ mdio {
+ lantiq,groups = "mdio";
+ lantiq,function = "mdio";
+ };
+ pci {
+ lantiq,groups = "gnt1", "req1";
+ lantiq,function = "pci";
+ };
+ exin {
+ lantiq,groups = "exin3";
+ lantiq,function = "exin";
+ };
+ conf_out {
+ lantiq,pins = "io24", "io13", "io49", /* nand cle, ale and rd */
+ "io4", "io5", "io6", /* stp */
+ "io17", "io18", /* spi dout & clk */
+ "io21", /* pci-rst */
+ "io38"; /* pcie-rst */
+ lantiq,open-drain;
+ lantiq,pull = <0>;
+ };
+ conf_in {
+ lantiq,pins = "io39", /* exin3 */
+ "io48"; /* nand rdy */
+ lantiq,pull = <2>;
+ };
+ };
+ };
+
+ eth@0xE108000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "lantiq,xrx200-net";
+ reg = < 0xE108000 0x3000 /* switch */
+ 0xE10B100 0x70 /* mdio */
+ 0xE10B1D8 0x30 /* mii */
+ 0xE10B308 0x30 /* pmac */
+ >;
+ interrupt-parent = <&icu0>;
+ interrupts = <73 72>;
+
+ lan: interface@0 {
+ compatible = "lantiq,xrx200-pdi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ mac-address = [ 00 11 22 33 44 55 ];
+
+ ethernet@0 {
+ compatible = "lantiq,xrx200-pdi-port";
+ reg = <0>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy0>;
+ };
+ ethernet@1 {
+ compatible = "lantiq,xrx200-pdi-port";
+ reg = <1>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy1>;
+ };
+ ethernet@2 {
+ compatible = "lantiq,xrx200-pdi-port";
+ reg = <2>;
+ phy-mode = "gmii";
+ phy-handle = <&phy11>;
+ };
+ ethernet@4 {
+ compatible = "lantiq,xrx200-pdi-port";
+ reg = <4>;
+ phynmode0 = "gmii";
+ phy-handle = <&phy13>;
+ };
+ };
+
+ wan: interface@1 {
+ compatible = "lantiq,xrx200-pdi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ mac-address = [ 00 11 22 33 44 56 ];
+
+ ethernet@5 {
+ compatible = "lantiq,xrx200-pdi-port";
+ reg = <5>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy5>;
+ };
+ };
+
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "lantiq,xrx200-mdio";
+ phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22";
+ lantiq,c45-reg-init = <1 0 0 0>;
+ };
+ phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22";
+ lantiq,c45-reg-init = <1 0 0 0>;
+ };
+ phy5: ethernet-phy@5 {
+ reg = <0x5>;
+ compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22";
+ lantiq,c45-reg-init = <1 0 0 0>;
+ };
+ phy11: ethernet-phy@11 {
+ reg = <0x11>;
+ compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22";
+ lantiq,c45-reg-init = <1 0 0 0>;
+ };
+ phy13: ethernet-phy@13 {
+ reg = <0x13>;
+ compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22";
+ lantiq,c45-reg-init = <1 0 0 0>;
+ };
+ };
+ };
+
+ stp: stp@E100BB0 {
+ compatible = "lantiq,gpio-stp-xway";
+ reg = <0xE100BB0 0x40>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ lantiq,shadow = <0xffff>;
+ lantiq,groups = <0x7>;
+ lantiq,dsl = <0x3>;
+ lantiq,phy1 = <0x7>;
+ lantiq,phy2 = <0x7>;
+ /* lantiq,rising; */
+ };
+
+ pci@E105400 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ compatible = "lantiq,pci-xway";
+ bus-range = <0x0 0x0>;
+ ranges = <0x2000000 0 0x8000000 0x8000000 0 0x2000000 /* pci memory */
+ 0x1000000 0 0x00000000 0xAE00000 0 0x200000>; /* io space */
+ reg = <0x7000000 0x8000 /* config space */
+ 0xE105400 0x400>; /* pci bridge */
+ lantiq,bus-clock = <33333333>;
+ /*lantiq,external-clock;*/
+ lantiq,delay-hi = <0>; /* 0ns delay */
+ lantiq,delay-lo = <0>; /* 0.0ns delay */
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x7000 0 0 1 &icu0 29 1 // slot 14, irq 29
+ >;
+ gpios-reset = <&gpio 21 0>;
+ req-mask = <0x1>; /* GNT1 */
+ };
+ };
+
+ ifxhcd {
+ compatible = "lantiq,ifxhcd";
+ interrupt-parent = <&icu0>;
+ interrupts = <62 91>;
+ };
+
+ gphy-xrx200 {
+ compatible = "lantiq,phy-xrx200";
+ firmware = "lantiq/vr9_phy11g_a2x.bin";
+ phys = [ 00 01 ];
+ };
+
+ gpio-keys-polled {
+ compatible = "gpio-keys-polled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ poll-interval = <100>;
+ reset {
+ label = "Reset";
+ gpios = <&gpio 7 0>;
+ linux,code = <0x100>;
+ };
+ paging {
+ label = "paging";
+ gpios = <&gpio 11 1>;
+ linux,code = <0x100>;
+ };
+ };
+
+/* gpio-keys {
+ compatible = "gpio-keys";
+ wps {
+ gpios = <&gpio 39 0>;
+ linux,code = <0x100>;
+ };
+ };*/
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ led0 {
+ label = "led0";
+ gpios = <&stp 9 0>;
+ default-state = "on";
+ };
+ warning {
+ label = "warning";
+ gpios = <&stp 22 0>;
+ default-state = "on";
+ };
+ fxs1 {
+ label = "fxs1";
+ gpios = <&stp 21 0>;
+ default-state = "on";
+ };
+ fxs2 {
+ label = "fxs2";
+ gpios = <&stp 20 0>;
+ default-state = "on";
+ };
+ fxo {
+ label = "fxo";
+ gpios = <&stp 19 0>;
+ default-state = "on";
+ };
+ usb1 {
+ label = "usb1";
+ gpios = <&stp 18 0>;
+ default-state = "on";
+ };
+ usb2 {
+ label = "usb2";
+ gpios = <&stp 15 0>;
+ default-state = "on";
+ };
+ sd {
+ label = "sd";
+ gpios = <&stp 14 0>;
+ default-state = "on";
+ };
+ wps {
+ label = "wps";
+ gpios = <&stp 12 0>;
+ default-state = "on";
+ };
+ };
+};
diff --git a/arch/mips/lantiq/dts/vr9.dtsi b/arch/mips/lantiq/dts/vr9.dtsi
new file mode 100644
index 0000000..d3adb58
--- /dev/null
+++ b/arch/mips/lantiq/dts/vr9.dtsi
@@ -0,0 +1,116 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "lantiq,xway", "lantiq,vr9";
+
+ cpus {
+ cpu@0 {
+ compatible = "mips,mips34Kc";
+ };
+ };
+
+ biu@1F800000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "lantiq,biu", "simple-bus";
+ reg = <0x1F800000 0x800000>;
+ ranges = <0x0 0x1F800000 0x7FFFFF>;
+
+ icu0: icu@80200 {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "lantiq,icu";
+ reg = <0x80200 0x28
+ 0x80228 0x28
+ 0x80250 0x28
+ 0x80278 0x28
+ 0x802a0 0x28>;
+ };
+
+ watchdog@803F0 {
+ compatible = "lantiq,wdt";
+ reg = <0x803F0 0x10>;
+ };
+ };
+
+ sram@1F000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "lantiq,sram";
+ reg = <0x1F000000 0x800000>;
+ ranges = <0x0 0x1F000000 0x7FFFFF>;
+
+ eiu0: eiu@101000 {
+ compatible = "lantiq,eiu";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0x101000 0x1000>;
+ lantiq,count = <6>;
+ };
+
+ pmu0: pmu@102000 {
+ compatible = "lantiq,pmu-xway";
+ reg = <0x102000 0x1000>;
+ };
+
+ cgu0: cgu@103000 {
+ compatible = "lantiq,cgu-xway";
+ reg = <0x103000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ rcu0: rcu@203000 {
+ compatible = "lantiq,rcu-xway";
+ reg = <0x203000 0x1000>;
+ /* irq for thermal sensor */
+ interrupt-parent = <&icu0>;
+ interrupts = <115>;
+ };
+ };
+
+ fpi@10000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "lantiq,fpi", "simple-bus";
+ ranges = <0x0 0x10000000 0xEEFFFFF>;
+ reg = <0x10000000 0xEF00000>;
+
+ gptu@E100A00 {
+ compatible = "lantiq,gptu-xway";
+ reg = <0xE100A00 0x100>;
+ interrupt-parent = <&icu0>;
+ interrupts = <126 127 128 129 130 131>;
+ };
+
+ asc1: serial@E100C00 {
+ compatible = "lantiq,asc";
+ reg = <0xE100C00 0x400>;
+ interrupt-parent = <&icu0>;
+ interrupts = <112 113 114>;
+ };
+
+ dma0: dma@E104100 {
+ compatible = "lantiq,dma-xway";
+ reg = <0xE104100 0x800>;
+ };
+
+ ebu0: ebu@E105300 {
+ compatible = "lantiq,ebu-xway";
+ reg = <0xE105300 0x100>;
+ };
+
+ pci0: pci@E105400 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ compatible = "lantiq,pci-xway";
+ bus-range = <0x0 0x0>;
+ ranges = <0x2000000 0 0x8000000 0x8000000 0 0x2000000 /* pci memory */
+ 0x1000000 0 0x00000000 0xAE00000 0 0x200000>; /* io space */
+ reg = <0x7000000 0x8000 /* config space */
+ 0xE105400 0x400>; /* pci bridge */
+ };
+
+ };
+};
--
1.7.10.4