All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/14] MIPS: lantiq: drop mips_machine support
@ 2012-05-04 12:18 John Crispin
       [not found] ` <1336133919-26525-1-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
                   ` (10 more replies)
  0 siblings, 11 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin

Before we are able to add OF support, we really want to drop all the bloat
needed to register all the platform devices.

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/Kconfig                      |    1 -
 arch/mips/lantiq/Kconfig               |    2 -
 arch/mips/lantiq/Makefile              |    2 +-
 arch/mips/lantiq/devices.c             |  120 --------------------------------
 arch/mips/lantiq/devices.h             |   23 ------
 arch/mips/lantiq/machtypes.h           |   20 -----
 arch/mips/lantiq/prom.h                |    1 -
 arch/mips/lantiq/setup.c               |   23 ------
 arch/mips/lantiq/xway/Kconfig          |   23 ------
 arch/mips/lantiq/xway/Makefile         |    9 +--
 arch/mips/lantiq/xway/devices.c        |  119 -------------------------------
 arch/mips/lantiq/xway/devices.h        |   20 -----
 arch/mips/lantiq/xway/mach-easy50601.c |   57 ---------------
 arch/mips/lantiq/xway/mach-easy50712.c |   74 --------------------
 arch/mips/lantiq/xway/setup-ase.c      |   19 -----
 arch/mips/lantiq/xway/setup-xway.c     |   20 -----
 16 files changed, 4 insertions(+), 529 deletions(-)
 delete mode 100644 arch/mips/lantiq/devices.c
 delete mode 100644 arch/mips/lantiq/devices.h
 delete mode 100644 arch/mips/lantiq/machtypes.h
 delete mode 100644 arch/mips/lantiq/xway/Kconfig
 delete mode 100644 arch/mips/lantiq/xway/devices.c
 delete mode 100644 arch/mips/lantiq/xway/devices.h
 delete mode 100644 arch/mips/lantiq/xway/mach-easy50601.c
 delete mode 100644 arch/mips/lantiq/xway/mach-easy50712.c
 delete mode 100644 arch/mips/lantiq/xway/setup-ase.c
 delete mode 100644 arch/mips/lantiq/xway/setup-xway.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ce30e2f..7c85562 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -229,7 +229,6 @@ config LANTIQ
 	select SWAP_IO_SPACE
 	select BOOT_RAW
 	select HAVE_CLK
-	select MIPS_MACHINE
 
 config LASAT
 	bool "LASAT Networks platforms"
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 3fccf21..2780461 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -18,6 +18,4 @@ config SOC_XWAY
 	select HW_HAS_PCI
 endchoice
 
-source "arch/mips/lantiq/xway/Kconfig"
-
 endif
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index e5dae0e..a268391 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -4,7 +4,7 @@
 # under the terms of the GNU General Public License version 2 as published
 # by the Free Software Foundation.
 
-obj-y := irq.o setup.o clk.o prom.o devices.o
+obj-y := irq.o setup.o clk.o prom.o
 
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
deleted file mode 100644
index de1cb2b..0000000
--- a/arch/mips/lantiq/devices.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/reboot.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/etherdevice.h>
-#include <linux/time.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-
-#include <lantiq_soc.h>
-
-#include "devices.h"
-
-/* nor flash */
-static struct resource ltq_nor_resource = {
-	.name	= "nor",
-	.start	= LTQ_FLASH_START,
-	.end	= LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
-static struct platform_device ltq_nor = {
-	.name		= "ltq_nor",
-	.resource	= &ltq_nor_resource,
-	.num_resources	= 1,
-};
-
-void __init ltq_register_nor(struct physmap_flash_data *data)
-{
-	ltq_nor.dev.platform_data = data;
-	platform_device_register(&ltq_nor);
-}
-
-/* watchdog */
-static struct resource ltq_wdt_resource = {
-	.name	= "watchdog",
-	.start  = LTQ_WDT_BASE_ADDR,
-	.end    = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
-void __init ltq_register_wdt(void)
-{
-	platform_device_register_simple("ltq_wdt", 0, &ltq_wdt_resource, 1);
-}
-
-/* asc ports */
-static struct resource ltq_asc0_resources[] = {
-	{
-		.name	= "asc0",
-		.start  = LTQ_ASC0_BASE_ADDR,
-		.end    = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	IRQ_RES(tx, LTQ_ASC_TIR(0)),
-	IRQ_RES(rx, LTQ_ASC_RIR(0)),
-	IRQ_RES(err, LTQ_ASC_EIR(0)),
-};
-
-static struct resource ltq_asc1_resources[] = {
-	{
-		.name	= "asc1",
-		.start  = LTQ_ASC1_BASE_ADDR,
-		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	IRQ_RES(tx, LTQ_ASC_TIR(1)),
-	IRQ_RES(rx, LTQ_ASC_RIR(1)),
-	IRQ_RES(err, LTQ_ASC_EIR(1)),
-};
-
-void __init ltq_register_asc(int port)
-{
-	switch (port) {
-	case 0:
-		platform_device_register_simple("ltq_asc", 0,
-			ltq_asc0_resources, ARRAY_SIZE(ltq_asc0_resources));
-		break;
-	case 1:
-		platform_device_register_simple("ltq_asc", 1,
-			ltq_asc1_resources, ARRAY_SIZE(ltq_asc1_resources));
-		break;
-	default:
-		break;
-	}
-}
-
-#ifdef CONFIG_PCI
-/* pci */
-static struct platform_device ltq_pci = {
-	.name		= "ltq_pci",
-	.num_resources	= 0,
-};
-
-void __init ltq_register_pci(struct ltq_pci_data *data)
-{
-	ltq_pci.dev.platform_data = data;
-	platform_device_register(&ltq_pci);
-}
-#else
-void __init ltq_register_pci(struct ltq_pci_data *data)
-{
-	pr_err("kernel is compiled without PCI support\n");
-}
-#endif
diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
deleted file mode 100644
index 2947bb1..0000000
--- a/arch/mips/lantiq/devices.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#ifndef _LTQ_DEVICES_H__
-#define _LTQ_DEVICES_H__
-
-#include <lantiq_platform.h>
-#include <linux/mtd/physmap.h>
-
-#define IRQ_RES(resname, irq) \
-	{.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
-
-extern void ltq_register_nor(struct physmap_flash_data *data);
-extern void ltq_register_wdt(void);
-extern void ltq_register_asc(int port);
-extern void ltq_register_pci(struct ltq_pci_data *data);
-
-#endif
diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
deleted file mode 100644
index 7e01b8c..0000000
--- a/arch/mips/lantiq/machtypes.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#ifndef _LANTIQ_MACH_H__
-#define _LANTIQ_MACH_H__
-
-#include <asm/mips_machine.h>
-
-enum lantiq_mach_type {
-	LTQ_MACH_GENERIC = 0,
-	LTQ_MACH_EASY50712,	/* Danube evaluation board */
-	LTQ_MACH_EASY50601,	/* Amazon SE evaluation board */
-};
-
-#endif
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
index 90070a5..f7c2a79 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -24,7 +24,6 @@ struct ltq_soc_info {
 };
 
 extern void ltq_soc_detect(struct ltq_soc_info *i);
-extern void ltq_soc_setup(void);
 extern void ltq_soc_init(void);
 
 #endif
diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
index 1ff6c9d..f1c605a 100644
--- a/arch/mips/lantiq/setup.c
+++ b/arch/mips/lantiq/setup.c
@@ -14,8 +14,6 @@
 
 #include <lantiq_soc.h>
 
-#include "machtypes.h"
-#include "devices.h"
 #include "prom.h"
 
 void __init plat_mem_setup(void)
@@ -43,24 +41,3 @@ void __init plat_mem_setup(void)
 	memsize *= 1024 * 1024;
 	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
 }
-
-static int __init
-lantiq_setup(void)
-{
-	ltq_soc_setup();
-	mips_machine_setup();
-	return 0;
-}
-
-arch_initcall(lantiq_setup);
-
-static void __init
-lantiq_generic_init(void)
-{
-	/* Nothing to do */
-}
-
-MIPS_MACHINE(LTQ_MACH_GENERIC,
-	     "Generic",
-	     "Generic Lantiq based board",
-	     lantiq_generic_init);
diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
deleted file mode 100644
index 2b857de..0000000
--- a/arch/mips/lantiq/xway/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-if SOC_XWAY
-
-menu "MIPS Machine"
-
-config LANTIQ_MACH_EASY50712
-	bool "Easy50712 - Danube"
-	default y
-
-endmenu
-
-endif
-
-if SOC_AMAZON_SE
-
-menu "MIPS Machine"
-
-config LANTIQ_MACH_EASY50601
-	bool "Easy50601 - Amazon SE"
-	default y
-
-endmenu
-
-endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 42d5fda..7a6c30f 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,7 +1,4 @@
-obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
+obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o dma.o
 
-obj-$(CONFIG_SOC_XWAY) += clk-xway.o setup-xway.o
-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o setup-ase.o
-
-obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
-obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+obj-$(CONFIG_SOC_XWAY) += clk-xway.o
+obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
deleted file mode 100644
index d614aa7..0000000
--- a/arch/mips/lantiq/xway/devices.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/mtd/physmap.h>
-#include <linux/kernel.h>
-#include <linux/reboot.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/etherdevice.h>
-#include <linux/time.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-
-#include <lantiq_soc.h>
-#include <lantiq_irq.h>
-#include <lantiq_platform.h>
-
-#include "devices.h"
-
-/* gpio */
-static struct resource ltq_gpio_resource[] = {
-	{
-		.name	= "gpio0",
-		.start  = LTQ_GPIO0_BASE_ADDR,
-		.end    = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.name	= "gpio1",
-		.start  = LTQ_GPIO1_BASE_ADDR,
-		.end    = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.name	= "gpio2",
-		.start  = LTQ_GPIO2_BASE_ADDR,
-		.end    = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}
-};
-
-void __init ltq_register_gpio(void)
-{
-	platform_device_register_simple("ltq_gpio", 0,
-		&ltq_gpio_resource[0], 1);
-	platform_device_register_simple("ltq_gpio", 1,
-		&ltq_gpio_resource[1], 1);
-
-	/* AR9 and VR9 have an extra gpio block */
-	if (ltq_is_ar9() || ltq_is_vr9()) {
-		platform_device_register_simple("ltq_gpio", 2,
-			&ltq_gpio_resource[2], 1);
-	}
-}
-
-/* serial to parallel conversion */
-static struct resource ltq_stp_resource = {
-	.name   = "stp",
-	.start  = LTQ_STP_BASE_ADDR,
-	.end    = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
-void __init ltq_register_gpio_stp(void)
-{
-	platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
-}
-
-/* asc ports - amazon se has its own serial mapping */
-static struct resource ltq_ase_asc_resources[] = {
-	{
-		.name	= "asc0",
-		.start  = LTQ_ASC1_BASE_ADDR,
-		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	IRQ_RES(tx, LTQ_ASC_ASE_TIR),
-	IRQ_RES(rx, LTQ_ASC_ASE_RIR),
-	IRQ_RES(err, LTQ_ASC_ASE_EIR),
-};
-
-void __init ltq_register_ase_asc(void)
-{
-	platform_device_register_simple("ltq_asc", 0,
-		ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
-}
-
-/* ethernet */
-static struct resource ltq_etop_resources = {
-	.name	= "etop",
-	.start	= LTQ_ETOP_BASE_ADDR,
-	.end	= LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct platform_device ltq_etop = {
-	.name		= "ltq_etop",
-	.resource	= &ltq_etop_resources,
-	.num_resources	= 1,
-};
-
-void __init
-ltq_register_etop(struct ltq_eth_data *eth)
-{
-	if (eth) {
-		ltq_etop.dev.platform_data = eth;
-		platform_device_register(&ltq_etop);
-	}
-}
diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
deleted file mode 100644
index e904934..0000000
--- a/arch/mips/lantiq/xway/devices.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#ifndef _LTQ_DEVICES_XWAY_H__
-#define _LTQ_DEVICES_XWAY_H__
-
-#include "../devices.h"
-#include <linux/phy.h>
-
-extern void ltq_register_gpio(void);
-extern void ltq_register_gpio_stp(void);
-extern void ltq_register_ase_asc(void);
-extern void ltq_register_etop(struct ltq_eth_data *eth);
-
-#endif
diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
deleted file mode 100644
index d5aaf63..0000000
--- a/arch/mips/lantiq/xway/mach-easy50601.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/input.h>
-
-#include <lantiq.h>
-
-#include "../machtypes.h"
-#include "devices.h"
-
-static struct mtd_partition easy50601_partitions[] = {
-	{
-		.name	= "uboot",
-		.offset	= 0x0,
-		.size	= 0x10000,
-	},
-	{
-		.name	= "uboot_env",
-		.offset	= 0x10000,
-		.size	= 0x10000,
-	},
-	{
-		.name	= "linux",
-		.offset	= 0x20000,
-		.size	= 0xE0000,
-	},
-	{
-		.name	= "rootfs",
-		.offset	= 0x100000,
-		.size	= 0x300000,
-	},
-};
-
-static struct physmap_flash_data easy50601_flash_data = {
-	.nr_parts	= ARRAY_SIZE(easy50601_partitions),
-	.parts		= easy50601_partitions,
-};
-
-static void __init easy50601_init(void)
-{
-	ltq_register_nor(&easy50601_flash_data);
-}
-
-MIPS_MACHINE(LTQ_MACH_EASY50601,
-			"EASY50601",
-			"EASY50601 Eval Board",
-			easy50601_init);
diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
deleted file mode 100644
index ea5027b..0000000
--- a/arch/mips/lantiq/xway/mach-easy50712.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/input.h>
-#include <linux/phy.h>
-
-#include <lantiq_soc.h>
-#include <irq.h>
-
-#include "../machtypes.h"
-#include "devices.h"
-
-static struct mtd_partition easy50712_partitions[] = {
-	{
-		.name	= "uboot",
-		.offset	= 0x0,
-		.size	= 0x10000,
-	},
-	{
-		.name	= "uboot_env",
-		.offset	= 0x10000,
-		.size	= 0x10000,
-	},
-	{
-		.name	= "linux",
-		.offset	= 0x20000,
-		.size	= 0xe0000,
-	},
-	{
-		.name	= "rootfs",
-		.offset	= 0x100000,
-		.size	= 0x300000,
-	},
-};
-
-static struct physmap_flash_data easy50712_flash_data = {
-	.nr_parts	= ARRAY_SIZE(easy50712_partitions),
-	.parts		= easy50712_partitions,
-};
-
-static struct ltq_pci_data ltq_pci_data = {
-	.clock	= PCI_CLOCK_INT,
-	.gpio	= PCI_GNT1 | PCI_REQ1,
-	.irq	= {
-		[14] = INT_NUM_IM0_IRL0 + 22,
-	},
-};
-
-static struct ltq_eth_data ltq_eth_data = {
-	.mii_mode = PHY_INTERFACE_MODE_MII,
-};
-
-static void __init easy50712_init(void)
-{
-	ltq_register_gpio_stp();
-	ltq_register_nor(&easy50712_flash_data);
-	ltq_register_pci(&ltq_pci_data);
-	ltq_register_etop(&ltq_eth_data);
-}
-
-MIPS_MACHINE(LTQ_MACH_EASY50712,
-	     "EASY50712",
-	     "EASY50712 Eval Board",
-	      easy50712_init);
diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
deleted file mode 100644
index f6f3267..0000000
--- a/arch/mips/lantiq/xway/setup-ase.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  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) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-#include "devices.h"
-
-void __init ltq_soc_setup(void)
-{
-	ltq_register_ase_asc();
-	ltq_register_gpio();
-	ltq_register_wdt();
-}
diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
deleted file mode 100644
index c292f64..0000000
--- a/arch/mips/lantiq/xway/setup-xway.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  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) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-#include "devices.h"
-
-void __init ltq_soc_setup(void)
-{
-	ltq_register_asc(0);
-	ltq_register_asc(1);
-	ltq_register_gpio();
-	ltq_register_wdt();
-}
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 02/14] OF: MIPS: lantiq: implement OF support
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
@ 2012-05-04 12:18     ` John Crispin
  2012-05-04 12:18 ` [PATCH 05/14] MIPS: lantiq: implement support for clkdev api John Crispin
                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

Activate USE_OF, add a sample DTS file and convert the core soc code to OF.

Signed-off-by: John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/Kconfig                  |    1 +
 arch/mips/lantiq/Kconfig           |    9 +++
 arch/mips/lantiq/Makefile          |    4 +-
 arch/mips/lantiq/dts/Makefile      |    4 +
 arch/mips/lantiq/dts/danube.dtsi   |  105 +++++++++++++++++++++++++++++++++
 arch/mips/lantiq/dts/easy50712.dts |  113 ++++++++++++++++++++++++++++++++++++
 arch/mips/lantiq/prom.c            |   57 ++++++++++++++----
 arch/mips/lantiq/prom.h            |    2 +
 arch/mips/lantiq/setup.c           |   43 --------------
 arch/mips/lantiq/xway/ebu.c        |    4 -
 arch/mips/lantiq/xway/reset.c      |   29 ++++-----
 11 files changed, 294 insertions(+), 77 deletions(-)
 create mode 100644 arch/mips/lantiq/dts/Makefile
 create mode 100644 arch/mips/lantiq/dts/danube.dtsi
 create mode 100644 arch/mips/lantiq/dts/easy50712.dts
 delete mode 100644 arch/mips/lantiq/setup.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 7c85562..fbb5639 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -229,6 +229,7 @@ config LANTIQ
 	select SWAP_IO_SPACE
 	select BOOT_RAW
 	select HAVE_CLK
+	select USE_OF
 
 config LASAT
 	bool "LASAT Networks platforms"
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 2780461..9485fe5 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -18,4 +18,13 @@ config SOC_XWAY
 	select HW_HAS_PCI
 endchoice
 
+
+choice
+	prompt "Devicetree"
+
+config DT_EASY50712
+	bool "Easy50712"
+	depends on SOC_XWAY
+endchoice
+
 endif
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index a268391..16f1c75 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -4,7 +4,9 @@
 # under the terms of the GNU General Public License version 2 as published
 # by the Free Software Foundation.
 
-obj-y := irq.o setup.o clk.o prom.o
+obj-y := irq.o clk.o prom.o
+
+obj-y += dts/
 
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 
diff --git a/arch/mips/lantiq/dts/Makefile b/arch/mips/lantiq/dts/Makefile
new file mode 100644
index 0000000..674fca4
--- /dev/null
+++ b/arch/mips/lantiq/dts/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o
+
+$(obj)/%.dtb: $(obj)/%.dts
+	$(call if_changed,dtc)
diff --git a/arch/mips/lantiq/dts/danube.dtsi b/arch/mips/lantiq/dts/danube.dtsi
new file mode 100644
index 0000000..3a4520f
--- /dev/null
+++ b/arch/mips/lantiq/dts/danube.dtsi
@@ -0,0 +1,105 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "lantiq,xway", "lantiq,danube";
+
+	cpus {
+		cpu@0 {
+			compatible = "mips,mips24Kc";
+		};
+	};
+
+	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 0x120>;
+		};
+
+		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 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupt-parent;
+			compatible = "lantiq,eiu-xway";
+			reg = <0x101000 0x1000>;
+		};
+
+		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>;
+		};
+	};
+
+	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>;
+		};
+
+		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 */
+		};
+	};
+};
diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts
new file mode 100644
index 0000000..68c1731
--- /dev/null
+++ b/arch/mips/lantiq/dts/easy50712.dts
@@ -0,0 +1,113 @@
+/dts-v1/;
+
+/include/ "danube.dtsi"
+
+/ {
+	chosen {
+		bootargs = "console=ttyLTQ0,115200 init=/etc/preinit";
+	};
+
+	memory@0 {
+		reg = <0x0 0x2000000>;
+	};
+
+	fpi@10000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		localbus@0 {
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x0 0x3ffffff /* addrsel0 */
+				1 0 0x4000000 0x4000010>; /* addsel1 */
+			compatible = "lantiq,localbus", "simple-bus";
+
+			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>; /* 64 KB */
+				};
+
+				partition@10000 {
+					label = "uboot_env";
+					reg = <0x10000 0x10000>; /* 64 KB */
+				};
+
+				partition@20000 {
+					label = "linux";
+					reg = <0x20000 0x3d0000>;
+				};
+
+				partition@400000 {
+					label = "rootfs";
+					reg = <0x400000 0x400000>;
+				};
+			};
+		};
+
+		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";
+				};
+				exin {
+					lantiq,groups = "exin1";
+					lantiq,function = "exin";
+				};
+				pci {
+					lantiq,groups = "gnt1";
+					lantiq,function = "pci";
+				};
+				conf_out {
+					lantiq,pins = "io4", "io5", "io6"; /* stp */
+					lantiq,open-drain;
+					lantiq,pull = <0>;
+				};
+			};
+		};
+
+		etop@E180000 {
+			compatible = "lantiq,etop-xway";
+			reg = <0xE180000 0x40000>;
+			interrupt-parent = <&icu0>;
+			interrupts = <73 78>;
+			phy-mode = "rmii";
+			mac-address = [ 00 11 22 33 44 55 ];
+		};
+
+		stp0: stp@E100BB0 {
+			#gpio-cells = <2>;
+			compatible = "lantiq,gpio-stp-xway";
+			gpio-controller;
+			reg = <0xE100BB0 0x40>;
+
+			lantiq,shadow = <0xfff>;
+			lantiq,groups = <0x3>;
+		};
+
+		pci@E105400 {
+			lantiq,bus-clock = <33333333>;
+			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 */
+		};
+
+	};
+};
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index cd56892..413ed53 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -8,6 +8,7 @@
 
 #include <linux/export.h>
 #include <linux/clk.h>
+#include <linux/of_platform.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 
@@ -16,13 +17,15 @@
 #include "prom.h"
 #include "clk.h"
 
-static struct ltq_soc_info soc_info;
+/* access to the ebu needs to be locked between different drivers */
+DEFINE_SPINLOCK(ebu_lock);
+EXPORT_SYMBOL_GPL(ebu_lock);
 
-unsigned int ltq_get_cpu_ver(void)
-{
-	return soc_info.rev;
-}
-EXPORT_SYMBOL(ltq_get_cpu_ver);
+/*
+ * this struct is filled by the soc specific detection code and holds
+ * information about the specific soc type, revision and name
+ */
+static struct ltq_soc_info soc_info;
 
 unsigned int ltq_get_soc_type(void)
 {
@@ -57,16 +60,28 @@ static void __init prom_init_cmdline(void)
 	}
 }
 
-void __init prom_init(void)
+void __init plat_mem_setup(void)
 {
-	struct clk *clk;
+	ioport_resource.start = IOPORT_RESOURCE_START;
+	ioport_resource.end = IOPORT_RESOURCE_END;
+	iomem_resource.start = IOMEM_RESOURCE_START;
+	iomem_resource.end = IOMEM_RESOURCE_END;
+
+	set_io_port_base((unsigned long) KSEG1);
+
+	/*
+	 * Load the builtin devicetree. This causes the chosen node to be
+	 * parsed resulting in our memory appearing
+	 */
+	__dt_setup_arch(&__dtb_start);
+}
 
+void __init prom_init(void)
+{
+	/* call the soc specific detetcion code and get it to fill soc_info */
 	ltq_soc_detect(&soc_info);
-	clk_init();
-	clk = clk_get(0, "cpu");
-	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
-		soc_info.name, soc_info.rev);
-	clk_put(clk);
+	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
+		soc_info.name, soc_info.rev_type);
 	soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
 	pr_info("SoC: %s\n", soc_info.sys_type);
 	prom_init_cmdline();
@@ -76,3 +91,19 @@ void __init prom_init(void)
 		panic("failed to register_vsmp_smp_ops()");
 #endif
 }
+
+int __init plat_of_setup(void)
+{
+	static struct of_device_id of_ids[3];
+
+	if (!of_have_populated_dt())
+		panic("device tree not present");
+
+	strncpy(of_ids[0].compatible, soc_info.compatible,
+		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);
+}
+
+arch_initcall(plat_of_setup);
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
index f7c2a79..a3fa1a2 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -26,4 +26,6 @@ struct ltq_soc_info {
 extern void ltq_soc_detect(struct ltq_soc_info *i);
 extern void ltq_soc_init(void);
 
+extern struct boot_param_header __dtb_start;
+
 #endif
diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
deleted file mode 100644
index f1c605a..0000000
--- a/arch/mips/lantiq/setup.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <asm/bootinfo.h>
-
-#include <lantiq_soc.h>
-
-#include "prom.h"
-
-void __init plat_mem_setup(void)
-{
-	/* assume 16M as default incase uboot fails to pass proper ramsize */
-	unsigned long memsize = 16;
-	char **envp = (char **) KSEG1ADDR(fw_arg2);
-
-	ioport_resource.start = IOPORT_RESOURCE_START;
-	ioport_resource.end = IOPORT_RESOURCE_END;
-	iomem_resource.start = IOMEM_RESOURCE_START;
-	iomem_resource.end = IOMEM_RESOURCE_END;
-
-	set_io_port_base((unsigned long) KSEG1);
-
-	while (*envp) {
-		char *e = (char *)KSEG1ADDR(*envp);
-		if (!strncmp(e, "memsize=", 8)) {
-			e += 8;
-			if (strict_strtoul(e, 0, &memsize))
-				pr_warn("bad memsize specified\n");
-		}
-		envp++;
-	}
-	memsize *= 1024 * 1024;
-	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
index 862e3e8..419b47b 100644
--- a/arch/mips/lantiq/xway/ebu.c
+++ b/arch/mips/lantiq/xway/ebu.c
@@ -14,10 +14,6 @@
 
 #include <lantiq_soc.h>
 
-/* all access to the ebu must be locked */
-DEFINE_SPINLOCK(ebu_lock);
-EXPORT_SYMBOL_GPL(ebu_lock);
-
 static struct resource ltq_ebu_resource = {
 	.name	= "ebu",
 	.start	= LTQ_EBU_BASE_ADDR,
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 3327211..22c55f7 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -37,13 +37,6 @@
 #define RCU_BOOT_SEL_SHIFT	26
 #define RCU_BOOT_SEL_MASK	0x7
 
-static struct resource ltq_rcu_resource = {
-	.name   = "rcu",
-	.start  = LTQ_RCU_BASE_ADDR,
-	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
 
@@ -91,17 +84,21 @@ static void ltq_machine_power_off(void)
 
 static int __init mips_reboot_setup(void)
 {
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
-		panic("Failed to insert rcu memory");
+	struct resource res;
+	struct device_node *np =
+		of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+
+	/* check if all the reset register range is available */
+	if (!np)
+		panic("Failed to load reset resources from devicetree");
+
+	if (of_address_to_resource(np, 0, &res))
+		panic("Failed to get rcu memory range");
 
-	if (request_mem_region(ltq_rcu_resource.start,
-			resource_size(&ltq_rcu_resource), "rcu") < 0)
-		panic("Failed to request rcu memory");
+	if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
+		pr_err("Failed to request rcu memory");
 
-	/* remap rcu register range */
-	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
-				resource_size(&ltq_rcu_resource));
+	ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
 	if (!ltq_rcu_membase)
 		panic("Failed to remap core memory");
 
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 02/14] OF: MIPS: lantiq: implement OF support
@ 2012-05-04 12:18     ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, devicetree-discuss

Activate USE_OF, add a sample DTS file and convert the core soc code to OF.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: devicetree-discuss@lists.ozlabs.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/Kconfig                  |    1 +
 arch/mips/lantiq/Kconfig           |    9 +++
 arch/mips/lantiq/Makefile          |    4 +-
 arch/mips/lantiq/dts/Makefile      |    4 +
 arch/mips/lantiq/dts/danube.dtsi   |  105 +++++++++++++++++++++++++++++++++
 arch/mips/lantiq/dts/easy50712.dts |  113 ++++++++++++++++++++++++++++++++++++
 arch/mips/lantiq/prom.c            |   57 ++++++++++++++----
 arch/mips/lantiq/prom.h            |    2 +
 arch/mips/lantiq/setup.c           |   43 --------------
 arch/mips/lantiq/xway/ebu.c        |    4 -
 arch/mips/lantiq/xway/reset.c      |   29 ++++-----
 11 files changed, 294 insertions(+), 77 deletions(-)
 create mode 100644 arch/mips/lantiq/dts/Makefile
 create mode 100644 arch/mips/lantiq/dts/danube.dtsi
 create mode 100644 arch/mips/lantiq/dts/easy50712.dts
 delete mode 100644 arch/mips/lantiq/setup.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 7c85562..fbb5639 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -229,6 +229,7 @@ config LANTIQ
 	select SWAP_IO_SPACE
 	select BOOT_RAW
 	select HAVE_CLK
+	select USE_OF
 
 config LASAT
 	bool "LASAT Networks platforms"
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 2780461..9485fe5 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -18,4 +18,13 @@ config SOC_XWAY
 	select HW_HAS_PCI
 endchoice
 
+
+choice
+	prompt "Devicetree"
+
+config DT_EASY50712
+	bool "Easy50712"
+	depends on SOC_XWAY
+endchoice
+
 endif
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index a268391..16f1c75 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -4,7 +4,9 @@
 # under the terms of the GNU General Public License version 2 as published
 # by the Free Software Foundation.
 
-obj-y := irq.o setup.o clk.o prom.o
+obj-y := irq.o clk.o prom.o
+
+obj-y += dts/
 
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 
diff --git a/arch/mips/lantiq/dts/Makefile b/arch/mips/lantiq/dts/Makefile
new file mode 100644
index 0000000..674fca4
--- /dev/null
+++ b/arch/mips/lantiq/dts/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o
+
+$(obj)/%.dtb: $(obj)/%.dts
+	$(call if_changed,dtc)
diff --git a/arch/mips/lantiq/dts/danube.dtsi b/arch/mips/lantiq/dts/danube.dtsi
new file mode 100644
index 0000000..3a4520f
--- /dev/null
+++ b/arch/mips/lantiq/dts/danube.dtsi
@@ -0,0 +1,105 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "lantiq,xway", "lantiq,danube";
+
+	cpus {
+		cpu@0 {
+			compatible = "mips,mips24Kc";
+		};
+	};
+
+	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 0x120>;
+		};
+
+		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 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupt-parent;
+			compatible = "lantiq,eiu-xway";
+			reg = <0x101000 0x1000>;
+		};
+
+		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>;
+		};
+	};
+
+	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>;
+		};
+
+		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 */
+		};
+	};
+};
diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts
new file mode 100644
index 0000000..68c1731
--- /dev/null
+++ b/arch/mips/lantiq/dts/easy50712.dts
@@ -0,0 +1,113 @@
+/dts-v1/;
+
+/include/ "danube.dtsi"
+
+/ {
+	chosen {
+		bootargs = "console=ttyLTQ0,115200 init=/etc/preinit";
+	};
+
+	memory@0 {
+		reg = <0x0 0x2000000>;
+	};
+
+	fpi@10000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		localbus@0 {
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x0 0x3ffffff /* addrsel0 */
+				1 0 0x4000000 0x4000010>; /* addsel1 */
+			compatible = "lantiq,localbus", "simple-bus";
+
+			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>; /* 64 KB */
+				};
+
+				partition@10000 {
+					label = "uboot_env";
+					reg = <0x10000 0x10000>; /* 64 KB */
+				};
+
+				partition@20000 {
+					label = "linux";
+					reg = <0x20000 0x3d0000>;
+				};
+
+				partition@400000 {
+					label = "rootfs";
+					reg = <0x400000 0x400000>;
+				};
+			};
+		};
+
+		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";
+				};
+				exin {
+					lantiq,groups = "exin1";
+					lantiq,function = "exin";
+				};
+				pci {
+					lantiq,groups = "gnt1";
+					lantiq,function = "pci";
+				};
+				conf_out {
+					lantiq,pins = "io4", "io5", "io6"; /* stp */
+					lantiq,open-drain;
+					lantiq,pull = <0>;
+				};
+			};
+		};
+
+		etop@E180000 {
+			compatible = "lantiq,etop-xway";
+			reg = <0xE180000 0x40000>;
+			interrupt-parent = <&icu0>;
+			interrupts = <73 78>;
+			phy-mode = "rmii";
+			mac-address = [ 00 11 22 33 44 55 ];
+		};
+
+		stp0: stp@E100BB0 {
+			#gpio-cells = <2>;
+			compatible = "lantiq,gpio-stp-xway";
+			gpio-controller;
+			reg = <0xE100BB0 0x40>;
+
+			lantiq,shadow = <0xfff>;
+			lantiq,groups = <0x3>;
+		};
+
+		pci@E105400 {
+			lantiq,bus-clock = <33333333>;
+			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 */
+		};
+
+	};
+};
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index cd56892..413ed53 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -8,6 +8,7 @@
 
 #include <linux/export.h>
 #include <linux/clk.h>
+#include <linux/of_platform.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 
@@ -16,13 +17,15 @@
 #include "prom.h"
 #include "clk.h"
 
-static struct ltq_soc_info soc_info;
+/* access to the ebu needs to be locked between different drivers */
+DEFINE_SPINLOCK(ebu_lock);
+EXPORT_SYMBOL_GPL(ebu_lock);
 
-unsigned int ltq_get_cpu_ver(void)
-{
-	return soc_info.rev;
-}
-EXPORT_SYMBOL(ltq_get_cpu_ver);
+/*
+ * this struct is filled by the soc specific detection code and holds
+ * information about the specific soc type, revision and name
+ */
+static struct ltq_soc_info soc_info;
 
 unsigned int ltq_get_soc_type(void)
 {
@@ -57,16 +60,28 @@ static void __init prom_init_cmdline(void)
 	}
 }
 
-void __init prom_init(void)
+void __init plat_mem_setup(void)
 {
-	struct clk *clk;
+	ioport_resource.start = IOPORT_RESOURCE_START;
+	ioport_resource.end = IOPORT_RESOURCE_END;
+	iomem_resource.start = IOMEM_RESOURCE_START;
+	iomem_resource.end = IOMEM_RESOURCE_END;
+
+	set_io_port_base((unsigned long) KSEG1);
+
+	/*
+	 * Load the builtin devicetree. This causes the chosen node to be
+	 * parsed resulting in our memory appearing
+	 */
+	__dt_setup_arch(&__dtb_start);
+}
 
+void __init prom_init(void)
+{
+	/* call the soc specific detetcion code and get it to fill soc_info */
 	ltq_soc_detect(&soc_info);
-	clk_init();
-	clk = clk_get(0, "cpu");
-	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
-		soc_info.name, soc_info.rev);
-	clk_put(clk);
+	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
+		soc_info.name, soc_info.rev_type);
 	soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
 	pr_info("SoC: %s\n", soc_info.sys_type);
 	prom_init_cmdline();
@@ -76,3 +91,19 @@ void __init prom_init(void)
 		panic("failed to register_vsmp_smp_ops()");
 #endif
 }
+
+int __init plat_of_setup(void)
+{
+	static struct of_device_id of_ids[3];
+
+	if (!of_have_populated_dt())
+		panic("device tree not present");
+
+	strncpy(of_ids[0].compatible, soc_info.compatible,
+		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);
+}
+
+arch_initcall(plat_of_setup);
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
index f7c2a79..a3fa1a2 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -26,4 +26,6 @@ struct ltq_soc_info {
 extern void ltq_soc_detect(struct ltq_soc_info *i);
 extern void ltq_soc_init(void);
 
+extern struct boot_param_header __dtb_start;
+
 #endif
diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
deleted file mode 100644
index f1c605a..0000000
--- a/arch/mips/lantiq/setup.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <asm/bootinfo.h>
-
-#include <lantiq_soc.h>
-
-#include "prom.h"
-
-void __init plat_mem_setup(void)
-{
-	/* assume 16M as default incase uboot fails to pass proper ramsize */
-	unsigned long memsize = 16;
-	char **envp = (char **) KSEG1ADDR(fw_arg2);
-
-	ioport_resource.start = IOPORT_RESOURCE_START;
-	ioport_resource.end = IOPORT_RESOURCE_END;
-	iomem_resource.start = IOMEM_RESOURCE_START;
-	iomem_resource.end = IOMEM_RESOURCE_END;
-
-	set_io_port_base((unsigned long) KSEG1);
-
-	while (*envp) {
-		char *e = (char *)KSEG1ADDR(*envp);
-		if (!strncmp(e, "memsize=", 8)) {
-			e += 8;
-			if (strict_strtoul(e, 0, &memsize))
-				pr_warn("bad memsize specified\n");
-		}
-		envp++;
-	}
-	memsize *= 1024 * 1024;
-	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
index 862e3e8..419b47b 100644
--- a/arch/mips/lantiq/xway/ebu.c
+++ b/arch/mips/lantiq/xway/ebu.c
@@ -14,10 +14,6 @@
 
 #include <lantiq_soc.h>
 
-/* all access to the ebu must be locked */
-DEFINE_SPINLOCK(ebu_lock);
-EXPORT_SYMBOL_GPL(ebu_lock);
-
 static struct resource ltq_ebu_resource = {
 	.name	= "ebu",
 	.start	= LTQ_EBU_BASE_ADDR,
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 3327211..22c55f7 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -37,13 +37,6 @@
 #define RCU_BOOT_SEL_SHIFT	26
 #define RCU_BOOT_SEL_MASK	0x7
 
-static struct resource ltq_rcu_resource = {
-	.name   = "rcu",
-	.start  = LTQ_RCU_BASE_ADDR,
-	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
 
@@ -91,17 +84,21 @@ static void ltq_machine_power_off(void)
 
 static int __init mips_reboot_setup(void)
 {
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
-		panic("Failed to insert rcu memory");
+	struct resource res;
+	struct device_node *np =
+		of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+
+	/* check if all the reset register range is available */
+	if (!np)
+		panic("Failed to load reset resources from devicetree");
+
+	if (of_address_to_resource(np, 0, &res))
+		panic("Failed to get rcu memory range");
 
-	if (request_mem_region(ltq_rcu_resource.start,
-			resource_size(&ltq_rcu_resource), "rcu") < 0)
-		panic("Failed to request rcu memory");
+	if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
+		pr_err("Failed to request rcu memory");
 
-	/* remap rcu register range */
-	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
-				resource_size(&ltq_rcu_resource));
+	ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
 	if (!ltq_rcu_membase)
 		panic("Failed to remap core memory");
 
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
@ 2012-05-04 12:18     ` John Crispin
  2012-05-04 12:18 ` [PATCH 05/14] MIPS: lantiq: implement support for clkdev api John Crispin
                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

Add support for irq_domain on lantiq socs. The conversion is straight forward
as the ICU found inside the socs allows the usage of irq_domain_add_linear.

Signed-off-by: John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/lantiq/irq.c |  120 +++++++++++++++++++++++++++---------------------
 1 files changed, 68 insertions(+), 52 deletions(-)

diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index d227be1..170e6cb 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -9,6 +9,11 @@
 
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/irqdomain.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/irq_cpu.h>
@@ -16,7 +21,7 @@
 #include <lantiq_soc.h>
 #include <irq.h>
 
-/* register definitions */
+/* register definitions - internal irqs */
 #define LTQ_ICU_IM0_ISR		0x0000
 #define LTQ_ICU_IM0_IER		0x0008
 #define LTQ_ICU_IM0_IOSR	0x0010
@@ -25,6 +30,7 @@
 #define LTQ_ICU_IM1_ISR		0x0028
 #define LTQ_ICU_OFFSET		(LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
 
+/* register definitions - external irqs */
 #define LTQ_EIU_EXIN_C		0x0000
 #define LTQ_EIU_EXIN_INIC	0x0004
 #define LTQ_EIU_EXIN_INEN	0x000C
@@ -37,13 +43,13 @@
 #define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1)
 #define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2)
 #define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30)
-
 #define MAX_EIU			6
 
 /* the performance counter */
 #define LTQ_PERF_IRQ		(INT_NUM_IM4_IRL0 + 31)
 
-/* irqs generated by device attached to the EBU need to be acked in
+/*
+ * irqs generated by devices attached to the EBU need to be acked in
  * a special manner
  */
 #define LTQ_ICU_EBU_IRQ		22
@@ -71,20 +77,6 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
 	LTQ_EIU_IR5,
 };
 
-static struct resource ltq_icu_resource = {
-	.name	= "icu",
-	.start	= LTQ_ICU_BASE_ADDR,
-	.end	= LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct resource ltq_eiu_resource = {
-	.name	= "eiu",
-	.start	= LTQ_EIU_BASE_ADDR,
-	.end	= LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
 static void __iomem *ltq_icu_membase;
 static void __iomem *ltq_eiu_membase;
 
@@ -199,14 +191,15 @@ static void ltq_hw_irqdispatch(int module)
 	if (irq == 0)
 		return;
 
-	/* silicon bug causes only the msb set to 1 to be valid. all
+	/*
+	 * silicon bug causes only the msb set to 1 to be valid. all
 	 * other bits might be bogus
 	 */
 	irq = __fls(irq);
 	do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
 
 	/* if this is a EBU irq, we need to ack it or get a deadlock */
-	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
+	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
 		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
 			LTQ_EBU_PCC_ISTAT);
 }
@@ -290,38 +283,62 @@ out:
 	return;
 }
 
+static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+	if (((irq == LTQ_EIU_IR0) || (irq == LTQ_EIU_IR1) ||
+			(irq == LTQ_EIU_IR2)) && ltq_eiu_membase)
+		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
+	/* EIU3-5 only exist on ar9 and vr9 */
+	else if (((irq == LTQ_EIU_IR3) || (irq == LTQ_EIU_IR4) ||
+			(irq == LTQ_EIU_IR5)) &&
+			(of_machine_is_compatible("lantiq,ar9") ||
+				of_machine_is_compatible("lantiq,vr9")) &&
+			ltq_eiu_membase)
+		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
+	else
+		irq_set_chip_and_handler(irq, &ltq_irq_type, handle_level_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops irq_domain_ops = {
+	.xlate = irq_domain_xlate_onetwocell,
+	.map = icu_map,
+};
+
 static struct irqaction cascade = {
 	.handler = no_action,
 	.name = "cascade",
 };
 
-void __init arch_init_irq(void)
+int __init icu_of_init(struct device_node *node, struct device_node *parent)
 {
+	struct device_node *eiu_node;
+	struct resource res;
 	int i;
 
-	if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
-		panic("Failed to insert icu memory");
+	if (of_address_to_resource(node, 0, &res))
+		panic("Failed to get icu memory range");
 
-	if (request_mem_region(ltq_icu_resource.start,
-			resource_size(&ltq_icu_resource), "icu") < 0)
-		panic("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(ltq_icu_resource.start,
-				resource_size(&ltq_icu_resource));
+	ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res));
 	if (!ltq_icu_membase)
 		panic("Failed to remap icu memory");
 
-	if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
-		panic("Failed to insert eiu memory");
-
-	if (request_mem_region(ltq_eiu_resource.start,
-			resource_size(&ltq_eiu_resource), "eiu") < 0)
-		panic("Failed to request eiu memory");
-
-	ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
-				resource_size(&ltq_eiu_resource));
-	if (!ltq_eiu_membase)
-		panic("Failed to remap eiu memory");
+	/* 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 (request_mem_region(res.start, resource_size(&res),
+							res.name) < 0)
+			pr_err("Failed to request eiu memory");
+
+		ltq_eiu_membase = ioremap_nocache(res.start,
+							resource_size(&res));
+		if (!ltq_eiu_membase)
+			panic("Failed to remap eiu memory");
+	}
 
 	/* turn off all irqs by default */
 	for (i = 0; i < 5; i++) {
@@ -346,20 +363,8 @@ void __init arch_init_irq(void)
 		set_vi_handler(7, ltq_hw5_irqdispatch);
 	}
 
-	for (i = INT_NUM_IRQ0;
-		i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
-		if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
-			(i == LTQ_EIU_IR2))
-			irq_set_chip_and_handler(i, &ltq_eiu_type,
-				handle_level_irq);
-		/* EIU3-5 only exist on ar9 and vr9 */
-		else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
-			(i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
-			irq_set_chip_and_handler(i, &ltq_eiu_type,
-				handle_level_irq);
-		else
-			irq_set_chip_and_handler(i, &ltq_irq_type,
-				handle_level_irq);
+	irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET,
+		&irq_domain_ops, 0);
 
 #if defined(CONFIG_MIPS_MT_SMP)
 	if (cpu_has_vint) {
@@ -382,9 +387,20 @@ void __init arch_init_irq(void)
 
 	/* tell oprofile which irq to use */
 	cp0_perfcount_irq = LTQ_PERF_IRQ;
+	return 0;
 }
 
 unsigned int __cpuinit get_c0_compare_int(void)
 {
 	return CP0_LEGACY_COMPARE_IRQ;
 }
+
+static struct of_device_id __initdata of_irq_ids[] = {
+	{ .compatible = "lantiq,icu", .data = icu_of_init },
+	{},
+};
+
+void __init arch_init_irq(void)
+{
+	of_irq_init(of_irq_ids);
+}
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support
@ 2012-05-04 12:18     ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, devicetree-discuss

Add support for irq_domain on lantiq socs. The conversion is straight forward
as the ICU found inside the socs allows the usage of irq_domain_add_linear.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: devicetree-discuss@lists.ozlabs.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/lantiq/irq.c |  120 +++++++++++++++++++++++++++---------------------
 1 files changed, 68 insertions(+), 52 deletions(-)

diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index d227be1..170e6cb 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -9,6 +9,11 @@
 
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/irqdomain.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/irq_cpu.h>
@@ -16,7 +21,7 @@
 #include <lantiq_soc.h>
 #include <irq.h>
 
-/* register definitions */
+/* register definitions - internal irqs */
 #define LTQ_ICU_IM0_ISR		0x0000
 #define LTQ_ICU_IM0_IER		0x0008
 #define LTQ_ICU_IM0_IOSR	0x0010
@@ -25,6 +30,7 @@
 #define LTQ_ICU_IM1_ISR		0x0028
 #define LTQ_ICU_OFFSET		(LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
 
+/* register definitions - external irqs */
 #define LTQ_EIU_EXIN_C		0x0000
 #define LTQ_EIU_EXIN_INIC	0x0004
 #define LTQ_EIU_EXIN_INEN	0x000C
@@ -37,13 +43,13 @@
 #define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1)
 #define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2)
 #define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30)
-
 #define MAX_EIU			6
 
 /* the performance counter */
 #define LTQ_PERF_IRQ		(INT_NUM_IM4_IRL0 + 31)
 
-/* irqs generated by device attached to the EBU need to be acked in
+/*
+ * irqs generated by devices attached to the EBU need to be acked in
  * a special manner
  */
 #define LTQ_ICU_EBU_IRQ		22
@@ -71,20 +77,6 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
 	LTQ_EIU_IR5,
 };
 
-static struct resource ltq_icu_resource = {
-	.name	= "icu",
-	.start	= LTQ_ICU_BASE_ADDR,
-	.end	= LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct resource ltq_eiu_resource = {
-	.name	= "eiu",
-	.start	= LTQ_EIU_BASE_ADDR,
-	.end	= LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
 static void __iomem *ltq_icu_membase;
 static void __iomem *ltq_eiu_membase;
 
@@ -199,14 +191,15 @@ static void ltq_hw_irqdispatch(int module)
 	if (irq == 0)
 		return;
 
-	/* silicon bug causes only the msb set to 1 to be valid. all
+	/*
+	 * silicon bug causes only the msb set to 1 to be valid. all
 	 * other bits might be bogus
 	 */
 	irq = __fls(irq);
 	do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
 
 	/* if this is a EBU irq, we need to ack it or get a deadlock */
-	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
+	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
 		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
 			LTQ_EBU_PCC_ISTAT);
 }
@@ -290,38 +283,62 @@ out:
 	return;
 }
 
+static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+	if (((irq == LTQ_EIU_IR0) || (irq == LTQ_EIU_IR1) ||
+			(irq == LTQ_EIU_IR2)) && ltq_eiu_membase)
+		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
+	/* EIU3-5 only exist on ar9 and vr9 */
+	else if (((irq == LTQ_EIU_IR3) || (irq == LTQ_EIU_IR4) ||
+			(irq == LTQ_EIU_IR5)) &&
+			(of_machine_is_compatible("lantiq,ar9") ||
+				of_machine_is_compatible("lantiq,vr9")) &&
+			ltq_eiu_membase)
+		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
+	else
+		irq_set_chip_and_handler(irq, &ltq_irq_type, handle_level_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops irq_domain_ops = {
+	.xlate = irq_domain_xlate_onetwocell,
+	.map = icu_map,
+};
+
 static struct irqaction cascade = {
 	.handler = no_action,
 	.name = "cascade",
 };
 
-void __init arch_init_irq(void)
+int __init icu_of_init(struct device_node *node, struct device_node *parent)
 {
+	struct device_node *eiu_node;
+	struct resource res;
 	int i;
 
-	if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
-		panic("Failed to insert icu memory");
+	if (of_address_to_resource(node, 0, &res))
+		panic("Failed to get icu memory range");
 
-	if (request_mem_region(ltq_icu_resource.start,
-			resource_size(&ltq_icu_resource), "icu") < 0)
-		panic("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(ltq_icu_resource.start,
-				resource_size(&ltq_icu_resource));
+	ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res));
 	if (!ltq_icu_membase)
 		panic("Failed to remap icu memory");
 
-	if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
-		panic("Failed to insert eiu memory");
-
-	if (request_mem_region(ltq_eiu_resource.start,
-			resource_size(&ltq_eiu_resource), "eiu") < 0)
-		panic("Failed to request eiu memory");
-
-	ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
-				resource_size(&ltq_eiu_resource));
-	if (!ltq_eiu_membase)
-		panic("Failed to remap eiu memory");
+	/* 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 (request_mem_region(res.start, resource_size(&res),
+							res.name) < 0)
+			pr_err("Failed to request eiu memory");
+
+		ltq_eiu_membase = ioremap_nocache(res.start,
+							resource_size(&res));
+		if (!ltq_eiu_membase)
+			panic("Failed to remap eiu memory");
+	}
 
 	/* turn off all irqs by default */
 	for (i = 0; i < 5; i++) {
@@ -346,20 +363,8 @@ void __init arch_init_irq(void)
 		set_vi_handler(7, ltq_hw5_irqdispatch);
 	}
 
-	for (i = INT_NUM_IRQ0;
-		i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
-		if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
-			(i == LTQ_EIU_IR2))
-			irq_set_chip_and_handler(i, &ltq_eiu_type,
-				handle_level_irq);
-		/* EIU3-5 only exist on ar9 and vr9 */
-		else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
-			(i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
-			irq_set_chip_and_handler(i, &ltq_eiu_type,
-				handle_level_irq);
-		else
-			irq_set_chip_and_handler(i, &ltq_irq_type,
-				handle_level_irq);
+	irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET,
+		&irq_domain_ops, 0);
 
 #if defined(CONFIG_MIPS_MT_SMP)
 	if (cpu_has_vint) {
@@ -382,9 +387,20 @@ void __init arch_init_irq(void)
 
 	/* tell oprofile which irq to use */
 	cp0_perfcount_irq = LTQ_PERF_IRQ;
+	return 0;
 }
 
 unsigned int __cpuinit get_c0_compare_int(void)
 {
 	return CP0_LEGACY_COMPARE_IRQ;
 }
+
+static struct of_device_id __initdata of_irq_ids[] = {
+	{ .compatible = "lantiq,icu", .data = icu_of_init },
+	{},
+};
+
+void __init arch_init_irq(void)
+{
+	of_irq_init(of_irq_ids);
+}
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
@ 2012-05-04 12:18     ` John Crispin
  2012-05-04 12:18 ` [PATCH 05/14] MIPS: lantiq: implement support for clkdev api John Crispin
                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

Implement support for pinctrl on lantiq/xway socs. The IO core found on these
socs has the registers for pinctrl, pinconf and gpio mixed up in the same
register range. As the gpio_chip handling is only a few lines, the driver also
implements the gpio functionality. This obseletes the old gpio driver that was
located in the arch/ folder.

Signed-off-by: John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/Kconfig                                  |    1 +
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    2 -
 arch/mips/lantiq/Kconfig                           |    1 +
 arch/mips/lantiq/xway/Makefile                     |    2 +-
 arch/mips/lantiq/xway/gpio.c                       |  195 ------
 arch/mips/lantiq/xway/gpio_stp.c                   |    5 -
 arch/mips/pci/pci-lantiq.c                         |   44 +--
 drivers/pinctrl/Kconfig                            |    9 +
 drivers/pinctrl/Makefile                           |    2 +
 drivers/pinctrl/pinctrl-lantiq.c                   |  308 +++++++++
 drivers/pinctrl/pinctrl-lantiq.h                   |  184 +++++
 drivers/pinctrl/pinctrl-xway.c                     |  702 ++++++++++++++++++++
 12 files changed, 1209 insertions(+), 246 deletions(-)
 delete mode 100644 arch/mips/lantiq/xway/gpio.c
 create mode 100644 drivers/pinctrl/pinctrl-lantiq.c
 create mode 100644 drivers/pinctrl/pinctrl-lantiq.h
 create mode 100644 drivers/pinctrl/pinctrl-xway.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fbb5639..00a0482 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -216,6 +216,7 @@ config MACH_JZ4740
 config LANTIQ
 	bool "Lantiq based platforms"
 	select DMA_NONCOHERENT
+	select PINCTRL
 	select IRQ_CPU
 	select CEVT_R4K
 	select CSRC_R4K
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 15eb4dc..150c7be 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -153,8 +153,6 @@
 #define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
 /* request a non-gpio and set the PIO config */
-extern int  ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name);
 extern void ltq_pmu_enable(unsigned int module);
 extern void ltq_pmu_disable(unsigned int module);
 
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 9485fe5..b86d942 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -2,6 +2,7 @@ if LANTIQ
 
 config SOC_TYPE_XWAY
 	bool
+	select PINCTRL_XWAY
 	default n
 
 choice
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 7a6c30f..323b574 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
-obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o dma.o
+obj-y := prom.o pmu.o ebu.o reset.o gpio_stp.o gpio_ebu.o dma.o
 
 obj-$(CONFIG_SOC_XWAY) += clk-xway.o
 obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
deleted file mode 100644
index c429a5b..0000000
--- a/arch/mips/lantiq/xway/gpio.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <lantiq_soc.h>
-
-#define LTQ_GPIO_OUT		0x00
-#define LTQ_GPIO_IN		0x04
-#define LTQ_GPIO_DIR		0x08
-#define LTQ_GPIO_ALTSEL0	0x0C
-#define LTQ_GPIO_ALTSEL1	0x10
-#define LTQ_GPIO_OD		0x14
-
-#define PINS_PER_PORT		16
-#define MAX_PORTS		3
-
-#define ltq_gpio_getbit(m, r, p)	(!!(ltq_r32(m + r) & (1 << p)))
-#define ltq_gpio_setbit(m, r, p)	ltq_w32_mask(0, (1 << p), m + r)
-#define ltq_gpio_clearbit(m, r, p)	ltq_w32_mask((1 << p), 0, m + r)
-
-struct ltq_gpio {
-	void __iomem *membase;
-	struct gpio_chip chip;
-};
-
-static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
-
-int gpio_to_irq(unsigned int gpio)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_to_irq);
-
-int irq_to_gpio(unsigned int gpio)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL(irq_to_gpio);
-
-int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name)
-{
-	int id = 0;
-
-	if (pin >= (MAX_PORTS * PINS_PER_PORT))
-		return -EINVAL;
-	if (gpio_request(pin, name)) {
-		pr_err("failed to setup lantiq gpio: %s\n", name);
-		return -EBUSY;
-	}
-	if (dir)
-		gpio_direction_output(pin, 1);
-	else
-		gpio_direction_input(pin);
-	while (pin >= PINS_PER_PORT) {
-		pin -= PINS_PER_PORT;
-		id++;
-	}
-	if (alt0)
-		ltq_gpio_setbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL0, pin);
-	else
-		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL0, pin);
-	if (alt1)
-		ltq_gpio_setbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL1, pin);
-	else
-		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL1, pin);
-	return 0;
-}
-EXPORT_SYMBOL(ltq_gpio_request);
-
-static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	if (value)
-		ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
-	else
-		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
-}
-
-static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset);
-}
-
-static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
-
-	return 0;
-}
-
-static int ltq_gpio_direction_output(struct gpio_chip *chip,
-	unsigned int offset, int value)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
-	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
-	ltq_gpio_set(chip, offset, value);
-
-	return 0;
-}
-
-static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
-	return 0;
-}
-
-static int ltq_gpio_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-
-	if (pdev->id >= MAX_PORTS) {
-		dev_err(&pdev->dev, "invalid gpio port %d\n",
-			pdev->id);
-		return -EINVAL;
-	}
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
-			pdev->id);
-		return -ENOENT;
-	}
-	res = devm_request_mem_region(&pdev->dev, res->start,
-		resource_size(res), dev_name(&pdev->dev));
-	if (!res) {
-		dev_err(&pdev->dev,
-			"failed to request memory for gpio port %d\n",
-			pdev->id);
-		return -EBUSY;
-	}
-	ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev,
-		res->start, resource_size(res));
-	if (!ltq_gpio_port[pdev->id].membase) {
-		dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n",
-			pdev->id);
-		return -ENOMEM;
-	}
-	ltq_gpio_port[pdev->id].chip.label = "ltq_gpio";
-	ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input;
-	ltq_gpio_port[pdev->id].chip.direction_output =
-		ltq_gpio_direction_output;
-	ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get;
-	ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
-	ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
-	ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
-	ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
-	platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
-	return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
-}
-
-static struct platform_driver
-ltq_gpio_driver = {
-	.probe = ltq_gpio_probe,
-	.driver = {
-		.name = "ltq_gpio",
-		.owner = THIS_MODULE,
-	},
-};
-
-int __init ltq_gpio_init(void)
-{
-	int ret = platform_driver_register(&ltq_gpio_driver);
-
-	if (ret)
-		pr_info("ltq_gpio : Error registering platform driver!");
-	return ret;
-}
-
-postcore_initcall(ltq_gpio_init);
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
index fd07d87..4f4bd61 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -78,11 +78,6 @@ static struct gpio_chip ltq_stp_chip = {
 
 static int ltq_stp_hw_init(void)
 {
-	/* the 3 pins used to control the external stp */
-	ltq_gpio_request(4, 1, 0, 1, "stp-st");
-	ltq_gpio_request(5, 1, 0, 1, "stp-d");
-	ltq_gpio_request(6, 1, 0, 1, "stp-sh");
-
 	/* sane defaults */
 	ltq_stp_w32(0, LTQ_STP_AR);
 	ltq_stp_w32(0, LTQ_STP_CPU0);
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
index 70fdf2c..3418178 100644
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -68,32 +68,6 @@
 #define ltq_pci_cfg_w32(x, y)	ltq_w32((x), ltq_pci_mapped_cfg + (y))
 #define ltq_pci_cfg_r32(x)	ltq_r32(ltq_pci_mapped_cfg + (x))
 
-struct ltq_pci_gpio_map {
-	int pin;
-	int alt0;
-	int alt1;
-	int dir;
-	char *name;
-};
-
-/* the pci core can make use of the following gpios */
-static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
-	{ 0, 1, 0, 0, "pci-exin0" },
-	{ 1, 1, 0, 0, "pci-exin1" },
-	{ 2, 1, 0, 0, "pci-exin2" },
-	{ 39, 1, 0, 0, "pci-exin3" },
-	{ 10, 1, 0, 0, "pci-exin4" },
-	{ 9, 1, 0, 0, "pci-exin5" },
-	{ 30, 1, 0, 1, "pci-gnt1" },
-	{ 23, 1, 0, 1, "pci-gnt2" },
-	{ 19, 1, 0, 1, "pci-gnt3" },
-	{ 38, 1, 0, 1, "pci-gnt4" },
-	{ 29, 1, 0, 0, "pci-req1" },
-	{ 31, 1, 0, 0, "pci-req2" },
-	{ 3, 1, 0, 0, "pci-req3" },
-	{ 37, 1, 0, 0, "pci-req4" },
-};
-
 __iomem void *ltq_pci_mapped_cfg;
 static __iomem void *ltq_pci_membase;
 
@@ -151,22 +125,6 @@ static u32 ltq_calc_bar11mask(void)
 	return bar11mask;
 }
 
-static void ltq_pci_setup_gpio(int gpio)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
-		if (gpio & (1 << i)) {
-			ltq_gpio_request(ltq_pci_gpio_map[i].pin,
-				ltq_pci_gpio_map[i].alt0,
-				ltq_pci_gpio_map[i].alt1,
-				ltq_pci_gpio_map[i].dir,
-				ltq_pci_gpio_map[i].name);
-		}
-	}
-	ltq_gpio_request(21, 0, 0, 1, "pci-reset");
-	ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
-}
-
 static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
 {
 	u32 temp_buffer;
@@ -192,7 +150,7 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
 	}
 
 	/* setup pci clock and gpis used by pci */
-	ltq_pci_setup_gpio(conf->gpio);
+	gpio_request(21, "pci-reset");
 
 	/* enable auto-switching between PCI and EBU */
 	ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f73a5ea..a19bac96 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
 	bool
 	select PINMUX
 
+config PINCTRL_LANTIQ
+	bool
+	select PINMUX
+	select PINCONF
+
 config PINCTRL_MMP2
 	bool "MMP2 pin controller driver"
 	depends on ARCH_MMP
@@ -83,6 +88,10 @@ config PINCTRL_COH901
 	  COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
 	  ports of 8 GPIO pins each.
 
+config PINCTRL_XWAY
+	bool
+	select PINCTRL_LANTIQ
+
 endmenu
 
 endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 8e3c95a..15bf5a3 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -19,3 +19,5 @@ obj-$(CONFIG_PINCTRL_TEGRA20)	+= pinctrl-tegra20.o
 obj-$(CONFIG_PINCTRL_TEGRA30)	+= pinctrl-tegra30.o
 obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
+obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
+obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
new file mode 100644
index 0000000..f2e28a5
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -0,0 +1,308 @@
+/*
+ *  linux/drivers/pinctrl/pinctrl-lantiq.c
+ *  based on linux/drivers/pinctrl/pinctrl-pxa3xx.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
+ *  publishhed by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "core.h"
+
+#include "pinctrl-lantiq.h"
+
+static int ltq_get_group_count(struct pinctrl_dev *pctrldev)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	return info->num_grps;
+}
+
+static const char *ltq_get_group_name(struct pinctrl_dev *pctrldev,
+					 unsigned selector)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	if (selector >= info->num_grps)
+		return NULL;
+	return info->grps[selector].name;
+}
+
+static int ltq_get_group_pins(struct pinctrl_dev *pctrldev,
+				 unsigned selector,
+				 const unsigned **pins,
+				 unsigned *num_pins)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	if (selector >= info->num_grps)
+		return -EINVAL;
+	*pins = info->grps[selector].pins;
+	*num_pins = info->grps[selector].npins;
+	return 0;
+}
+
+void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+	int i;
+
+	for (i = 0; i < num_maps; i++)
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+			kfree(map[i].data.configs.configs);
+	kfree(map);
+}
+
+static void ltq_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s,
+					unsigned offset)
+{
+	seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+				struct device_node *np,
+				struct pinctrl_map **map)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+	unsigned long configs[3];
+	unsigned num_configs = 0;
+	struct property *prop;
+	const char *group, *pin;
+	const char *function;
+	int ret, i;
+
+	ret = of_property_read_string(np, "lantiq,function", &function);
+	if (!ret) {
+		of_property_for_each_string(np, "lantiq,groups", prop, group) {
+			(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
+			(*map)->name = function;
+			(*map)->data.mux.group = group;
+			(*map)->data.mux.function = function;
+			(*map)++;
+		}
+		if (of_find_property(np, "lantiq,pins", NULL))
+			dev_err(pctldev->dev,
+				"%s mixes pins and groups settings\n",
+				np->name);
+		return 0;
+	}
+
+	for (i = 0; i < info->num_params; i++) {
+		u32 val;
+		int ret = of_property_read_u32(np,
+				info->params[i].property, &val);
+		if (!ret)
+			configs[num_configs++] =
+				LTQ_PINCONF_PACK(info->params[i].param,
+				val);
+	}
+
+	if (!num_configs)
+		return -EINVAL;
+
+	of_property_for_each_string(np, "lantiq,pins", prop, pin) {
+		(*map)->data.configs.configs = kmemdup(configs,
+					num_configs * sizeof(unsigned long),
+					GFP_KERNEL);
+		(*map)->type = PIN_MAP_TYPE_CONFIGS_PIN;
+		(*map)->name = pin;
+		(*map)->data.configs.group_or_pin = pin;
+		(*map)->data.configs.num_configs = num_configs;
+		(*map)++;
+	}
+	return 0;
+}
+
+static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
+{
+	int ret;
+
+	ret = of_property_count_strings(np, "lantiq,groups");
+	if (ret < 0)
+		ret = of_property_count_strings(np, "lantiq,pins");
+	return ret;
+}
+
+int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+				struct device_node *np_config,
+				struct pinctrl_map **map,
+				unsigned *num_maps)
+{
+	struct pinctrl_map *tmp;
+	struct device_node *np;
+	int ret;
+
+	*num_maps = 0;
+	for_each_child_of_node(np_config, np)
+		*num_maps += ltq_pinctrl_dt_subnode_size(np);
+	*map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
+	tmp = *map;
+
+	for_each_child_of_node(np_config, np) {
+		ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
+		if (ret < 0) {
+			ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static struct pinctrl_ops ltq_pctrl_ops = {
+	.get_groups_count	= ltq_get_group_count,
+	.get_group_name		= ltq_get_group_name,
+	.get_group_pins		= ltq_get_group_pins,
+	.pin_dbg_show		= ltq_pinctrl_pin_dbg_show,
+	.dt_node_to_map		= ltq_pinctrl_dt_node_to_map,
+	.dt_free_map		= ltq_pinctrl_dt_free_map,
+};
+
+static int ltq_pmx_func_count(struct pinctrl_dev *pctrldev)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+	return info->num_funcs;
+}
+
+static const char *ltq_pmx_func_name(struct pinctrl_dev *pctrldev,
+					 unsigned selector)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+	if (selector >= info->num_funcs)
+		return NULL;
+
+	return info->funcs[selector].name;
+}
+
+static int ltq_pmx_get_groups(struct pinctrl_dev *pctrldev,
+				unsigned func,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+	*groups = info->funcs[func].groups;
+	*num_groups = info->funcs[func].num_groups;
+
+	return 0;
+}
+
+/* Return function number. If failure, return negative value. */
+static int match_mux(const struct ltq_mfp_pin *mfp, unsigned mux)
+{
+	int i;
+	for (i = 0; i < LTQ_MAX_MUX; i++) {
+		if (mfp->func[i] == mux)
+			break;
+	}
+	if (i >= LTQ_MAX_MUX)
+		return -EINVAL;
+	return i;
+}
+
+/* check whether current pin configuration is valid. Negative for failure */
+static int match_group_mux(const struct ltq_pin_group *grp,
+			   const struct ltq_pinmux_info *info,
+			   unsigned mux)
+{
+	int i, pin, ret = 0;
+	for (i = 0; i < grp->npins; i++) {
+		pin = grp->pins[i];
+		ret = match_mux(&info->mfp[pin], mux);
+		if (ret < 0) {
+			dev_err(info->dev, "Can't find mux %d on pin%d\n",
+				mux, pin);
+			break;
+		}
+	}
+	return ret;
+}
+
+static int ltq_pmx_enable(struct pinctrl_dev *pctrldev,
+				unsigned func,
+				unsigned group)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	const struct ltq_pin_group *pin_grp = &info->grps[group];
+	int i, pin, pin_func;
+
+	if (!pin_grp->npins ||
+		(match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
+		dev_err(info->dev, "Failed to set the pin group: %s\n",
+			info->grps[group].name);
+		return -EINVAL;
+	}
+	for (i = 0; i < pin_grp->npins; i++) {
+		pin = pin_grp->pins[i];
+		pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
+		info->apply_mux(pctrldev, pin, pin_func);
+	}
+	return 0;
+}
+
+static void ltq_pmx_disable(struct pinctrl_dev *pctrldev,
+				unsigned func,
+				unsigned group)
+{
+}
+
+static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
+				struct pinctrl_gpio_range *range,
+				unsigned pin)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	int pin_func;
+
+	/* all our pins are gpio when muxing is set to 0. check anyhow */
+	pin_func = match_mux(&info->mfp[pin], 0);
+	if (pin_func < 0) {
+		dev_err(info->dev, "No GPIO function on pin%d\n", pin);
+		return -EINVAL;
+	}
+
+	info->apply_mux(pctrldev, pin, 0);
+
+	return 0;
+}
+
+static struct pinmux_ops ltq_pmx_ops = {
+	.get_functions_count	= ltq_pmx_func_count,
+	.get_function_name	= ltq_pmx_func_name,
+	.get_function_groups	= ltq_pmx_get_groups,
+	.enable			= ltq_pmx_enable,
+	.disable		= ltq_pmx_disable,
+	.gpio_request_enable	= ltq_pmx_gpio_request_enable,
+};
+
+/*
+ * allow different socs to register with the generic part of the lanti
+ * pinctrl code
+ */
+int ltq_pinctrl_register(struct platform_device *pdev,
+				struct ltq_pinmux_info *info)
+{
+	struct pinctrl_desc *desc;
+
+	if (!info)
+		return -EINVAL;
+	desc = info->desc;
+	desc->pctlops = &ltq_pctrl_ops;
+	desc->pmxops = &ltq_pmx_ops;
+	info->dev = &pdev->dev;
+
+	info->pctrl = pinctrl_register(desc, &pdev->dev, info);
+	if (!info->pctrl) {
+		dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n");
+		return -EINVAL;
+	}
+	platform_set_drvdata(pdev, info);
+	return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
new file mode 100644
index 0000000..dc84c09
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-lantiq.h
@@ -0,0 +1,184 @@
+/*
+ *  linux/drivers/pinctrl/pinctrl-lantiq.h
+ *  based on linux/drivers/pinctrl/pinctrl-pxa3xx.h
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
+ */
+
+#ifndef __PINCTRL_LANTIQ_H
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
+
+#define LTQ_MAX_MUX		4
+#define MFPR_FUNC_MASK		0x3
+
+#define LTQ_PINCONF_PACK(_param_, _arg_)	((_param_) << 16 | (_arg_))
+#define LTQ_PINCONF_UNPACK_PARAM(_conf_)	((_conf_) >> 16)
+#define LTQ_PINCONF_UNPACK_ARG(_conf_)		((_conf_) & 0xffff)
+
+enum ltq_pinconf_param {
+	LTQ_PINCONF_PARAM_PULL,
+	LTQ_PINCONF_PARAM_OPEN_DRAIN,
+	LTQ_PINCONF_PARAM_DRIVE_CURRENT,
+	LTQ_PINCONF_PARAM_SLEW_RATE,
+};
+
+struct ltq_cfg_param {
+	const char *property;
+	enum ltq_pinconf_param param;
+};
+
+struct ltq_mfp_pin {
+	const char *name;
+	const unsigned int pin;
+	const unsigned short func[LTQ_MAX_MUX];
+};
+
+struct ltq_pin_group {
+	const char *name;
+	const unsigned mux;
+	const unsigned *pins;
+	const unsigned npins;
+};
+
+struct ltq_pmx_func {
+	const char *name;
+	const char * const *groups;
+	const unsigned num_groups;
+};
+
+struct ltq_pinmux_info {
+	struct device *dev;
+	struct pinctrl_dev *pctrl;
+
+	/* we need to manage up to 5 padcontrolers */
+	void __iomem *membase[5];
+
+	/* the handler for the subsystem */
+	struct pinctrl_desc *desc;
+
+	/* we expose our pads to the subsystem */
+	struct pinctrl_pin_desc *pads;
+
+	/* the number of pads. this varies between socs */
+	unsigned int num_gpio;
+
+	/* these are our multifunction pins */
+	const struct ltq_mfp_pin *mfp;
+	unsigned int num_mfp;
+
+	/* a number of multifunction pins can be grouped together */
+	const struct ltq_pin_group *grps;
+	unsigned int num_grps;
+
+	/* a mapping between function string and id */
+	const struct ltq_pmx_func *funcs;
+	unsigned int num_funcs;
+
+	/* the pinconf options that we are able to read from the DT */
+	const struct ltq_cfg_param *params;
+	unsigned int num_params;
+
+	/* soc specific callback used to apply muxing */
+	int (*apply_mux)(struct pinctrl_dev *pctrldev, int pin, int mux);
+};
+
+enum ltq_pin_list {
+	GPIO0 = 0,
+	GPIO1,
+	GPIO2,
+	GPIO3,
+	GPIO4,
+	GPIO5,
+	GPIO6,
+	GPIO7,
+	GPIO8,
+	GPIO9,
+	GPIO10, /* 10 */
+	GPIO11,
+	GPIO12,
+	GPIO13,
+	GPIO14,
+	GPIO15,
+	GPIO16,
+	GPIO17,
+	GPIO18,
+	GPIO19,
+	GPIO20, /* 20 */
+	GPIO21,
+	GPIO22,
+	GPIO23,
+	GPIO24,
+	GPIO25,
+	GPIO26,
+	GPIO27,
+	GPIO28,
+	GPIO29,
+	GPIO30, /* 30 */
+	GPIO31,
+	GPIO32,
+	GPIO33,
+	GPIO34,
+	GPIO35,
+	GPIO36,
+	GPIO37,
+	GPIO38,
+	GPIO39,
+	GPIO40, /* 40 */
+	GPIO41,
+	GPIO42,
+	GPIO43,
+	GPIO44,
+	GPIO45,
+	GPIO46,
+	GPIO47,
+	GPIO48,
+	GPIO49,
+	GPIO50, /* 50 */
+	GPIO51,
+	GPIO52,
+	GPIO53,
+	GPIO54,
+	GPIO55,
+
+	GPIO64,
+	GPIO65,
+	GPIO66,
+	GPIO67,
+	GPIO68,
+	GPIO69,
+	GPIO70,
+	GPIO71,
+	GPIO72,
+	GPIO73,
+	GPIO74,
+	GPIO75,
+	GPIO76,
+	GPIO77,
+	GPIO78,
+	GPIO79,
+	GPIO80,
+	GPIO81,
+	GPIO82,
+	GPIO83,
+	GPIO84,
+	GPIO85,
+	GPIO86,
+	GPIO87,
+	GPIO88,
+};
+
+extern int ltq_pinctrl_register(struct platform_device *pdev,
+				   struct ltq_pinmux_info *info);
+extern int ltq_pinctrl_unregister(struct platform_device *pdev);
+#endif	/* __PINCTRL_PXA3XX_H */
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
new file mode 100644
index 0000000..efc3174
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -0,0 +1,702 @@
+/*
+ *  linux/drivers/pinctrl/pinmux-xway.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
+ *  publishhed by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-lantiq.h"
+
+#include <lantiq_soc.h>
+
+/* we have 3 1/2 banks of 16 bit each */
+#define PINS			16
+#define PORT(x)			(x / PINS)
+#define PORT_PIN(x)		(x % PINS)
+
+/*
+ * each bank has this offset apart from the 1/2 bank that is mixed into the
+ * other 3 ranges
+ */
+#define REG_OFF			0x30
+
+/* these are the offsets to our registers */
+#define GPIO_BASE(p)		(REG_OFF * PORT(p))
+#define GPIO_OUT(p)		GPIO_BASE(p)
+#define GPIO_IN(p)		(GPIO_BASE(p) + 0x04)
+#define GPIO_DIR(p)		(GPIO_BASE(p) + 0x08)
+#define GPIO_ALT0(p)		(GPIO_BASE(p) + 0x0C)
+#define GPIO_ALT1(p)		(GPIO_BASE(p) + 0x10)
+#define GPIO_OD(p)		(GPIO_BASE(p) + 0x14)
+#define GPIO_PUDSEL(p)		(GPIO_BASE(p) + 0x1c)
+#define GPIO_PUDEN(p)		(GPIO_BASE(p) + 0x20)
+
+/* the 1/2 port needs special offsets for some registers */
+#define GPIO3_OD		(GPIO_BASE(0) + 0x24)
+#define GPIO3_PUDSEL		(GPIO_BASE(0) + 0x28)
+#define GPIO3_PUDEN		(GPIO_BASE(0) + 0x2C)
+#define GPIO3_ALT1		(GPIO_BASE(PINS) + 0x24)
+
+/* PORT3 only has 8 pins and its register layout
+   is slightly different */
+#define PINS_PER_PORT		16
+#define PINS_PORT3		8
+#define MAX_PORTS		4
+#define MAX_PIN			56
+
+/* macros to help us access the registers */
+#define gpio_getbit(m, r, p)	(!!(ltq_r32(m + r) & (1 << p)))
+#define gpio_setbit(m, r, p)	ltq_w32_mask(0, (1 << p), m + r)
+#define gpio_clearbit(m, r, p)	ltq_w32_mask((1 << p), 0, m + r)
+
+#define MFP_XWAY(a, f0, f1, f2, f3)	\
+	{				\
+		.name = #a,		\
+		.pin = a,		\
+		.func = {		\
+			XWAY_MUX_##f0,	\
+			XWAY_MUX_##f1,	\
+			XWAY_MUX_##f2,	\
+			XWAY_MUX_##f3,	\
+		},			\
+	}
+
+#define GRP_MUX(a, m, p)		\
+	{ .name = a, .mux = XWAY_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
+
+#define FUNC_MUX(f, m)		\
+	{ .func = f, .mux = XWAY_MUX_##m, }
+
+enum xway_mux {
+	XWAY_MUX_GPIO = 0,
+	XWAY_MUX_SPI,
+	XWAY_MUX_ASC,
+	XWAY_MUX_PCI,
+	XWAY_MUX_CGU,
+	XWAY_MUX_EBU,
+	XWAY_MUX_JTAG,
+	XWAY_MUX_EXIN,
+	XWAY_MUX_TDM,
+	XWAY_MUX_STP,
+	XWAY_MUX_SIN,
+	XWAY_MUX_GPT,
+	XWAY_MUX_NMI,
+	XWAY_MUX_NONE = 0xffff,
+};
+
+static const struct ltq_mfp_pin xway_mfp[] = {
+	/*       pin    f0	f1	f2	f3   */
+	MFP_XWAY(GPIO0, GPIO,	EXIN,	NONE,	TDM),
+	MFP_XWAY(GPIO1, GPIO,	EXIN,	NONE,	NONE),
+	MFP_XWAY(GPIO2, GPIO,	CGU,	EXIN,	NONE),
+	MFP_XWAY(GPIO3, GPIO,	CGU,	NONE,	PCI),
+	MFP_XWAY(GPIO4, GPIO,	STP,	NONE,	ASC),
+	MFP_XWAY(GPIO5, GPIO,	STP,	NONE,	NONE),
+	MFP_XWAY(GPIO6, GPIO,	STP,	GPT,	ASC),
+	MFP_XWAY(GPIO7, GPIO,	CGU,	PCI,	NONE),
+	MFP_XWAY(GPIO8, GPIO,	CGU,	NMI,	NONE),
+	MFP_XWAY(GPIO9, GPIO,	ASC,	SPI,	NONE),
+	MFP_XWAY(GPIO10, GPIO,	ASC,	SPI,	NONE),
+	MFP_XWAY(GPIO11, GPIO,	ASC,	PCI,	SPI),
+	MFP_XWAY(GPIO12, GPIO,	ASC,	NONE,	NONE),
+	MFP_XWAY(GPIO13, GPIO,	EBU,	SPI,	NONE),
+	MFP_XWAY(GPIO14, GPIO,	CGU,	PCI,	NONE),
+	MFP_XWAY(GPIO15, GPIO,	SPI,	JTAG,	NONE),
+	MFP_XWAY(GPIO16, GPIO,	SPI,	NONE,	JTAG),
+	MFP_XWAY(GPIO17, GPIO,	SPI,	NONE,	JTAG),
+	MFP_XWAY(GPIO18, GPIO,	SPI,	NONE,	JTAG),
+	MFP_XWAY(GPIO19, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO20, GPIO,	JTAG,	NONE,	NONE),
+	MFP_XWAY(GPIO21, GPIO,	PCI,	EBU,	GPT),
+	MFP_XWAY(GPIO22, GPIO,	SPI,	NONE,	NONE),
+	MFP_XWAY(GPIO23, GPIO,	EBU,	PCI,	STP),
+	MFP_XWAY(GPIO24, GPIO,	EBU,	TDM,	PCI),
+	MFP_XWAY(GPIO25, GPIO,	TDM,	NONE,	ASC),
+	MFP_XWAY(GPIO26, GPIO,	EBU,	NONE,	TDM),
+	MFP_XWAY(GPIO27, GPIO,	TDM,	NONE,	ASC),
+	MFP_XWAY(GPIO28, GPIO,	GPT,	NONE,	NONE),
+	MFP_XWAY(GPIO29, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO30, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO31, GPIO,	EBU,	PCI,	NONE),
+	MFP_XWAY(GPIO32, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO33, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO34, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO35, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO36, GPIO,	SIN,	NONE,	EBU),
+	MFP_XWAY(GPIO37, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO38, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO39, GPIO,	EXIN,	NONE,	NONE),
+	MFP_XWAY(GPIO40, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO41, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO42, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO43, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO44, GPIO,	NONE,	NONE,	SIN),
+	MFP_XWAY(GPIO45, GPIO,	NONE,	NONE,	SIN),
+	MFP_XWAY(GPIO46, GPIO,	NONE,	NONE,	EXIN),
+	MFP_XWAY(GPIO47, GPIO,	NONE,	NONE,	SIN),
+	MFP_XWAY(GPIO48, GPIO,	EBU,	NONE,	NONE),
+	MFP_XWAY(GPIO49, GPIO,	EBU,	NONE,	NONE),
+	MFP_XWAY(GPIO50, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO51, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO52, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO53, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO54, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO55, GPIO,	NONE,	NONE,	NONE),
+};
+
+static const unsigned pins_jtag[] = {GPIO15, GPIO16, GPIO17, GPIO19, GPIO35};
+static const unsigned pins_asc0[] = {GPIO11, GPIO12};
+static const unsigned pins_asc0_cts_rts[] = {GPIO9, GPIO10};
+static const unsigned pins_stp[] = {GPIO4, GPIO5, GPIO6};
+static const unsigned pins_nmi[] = {GPIO8};
+
+static const unsigned pins_ebu_a24[] = {GPIO13};
+static const unsigned pins_ebu_clk[] = {GPIO21};
+static const unsigned pins_ebu_cs1[] = {GPIO23};
+static const unsigned pins_ebu_a23[] = {GPIO24};
+static const unsigned pins_ebu_wait[] = {GPIO26};
+static const unsigned pins_ebu_a25[] = {GPIO31};
+static const unsigned pins_ebu_rdy[] = {GPIO48};
+static const unsigned pins_ebu_rd[] = {GPIO49};
+
+static const unsigned pins_nand_ale[] = {GPIO13};
+static const unsigned pins_nand_cs1[] = {GPIO23};
+static const unsigned pins_nand_cle[] = {GPIO24};
+static const unsigned pins_nand_rdy[] = {GPIO48};
+static const unsigned pins_nand_rd[] = {GPIO49};
+
+static const unsigned pins_exin0[] = {GPIO0};
+static const unsigned pins_exin1[] = {GPIO1};
+static const unsigned pins_exin2[] = {GPIO2};
+static const unsigned pins_exin3[] = {GPIO39};
+static const unsigned pins_exin4[] = {GPIO46};
+
+static const unsigned pins_spi[] = {GPIO16, GPIO17, GPIO18};
+static const unsigned pins_spi_cs1[] = {GPIO15};
+static const unsigned pins_spi_cs2[] = {GPIO21};
+static const unsigned pins_spi_cs3[] = {GPIO13};
+static const unsigned pins_spi_cs4[] = {GPIO10};
+static const unsigned pins_spi_cs5[] = {GPIO9};
+static const unsigned pins_spi_cs6[] = {GPIO11};
+
+static const unsigned pins_gpt1[] = {GPIO28};
+static const unsigned pins_gpt2[] = {GPIO21};
+static const unsigned pins_gpt3[] = {GPIO6};
+
+static const unsigned pins_clkout0[] = {GPIO8};
+static const unsigned pins_clkout1[] = {GPIO7};
+static const unsigned pins_clkout2[] = {GPIO3};
+static const unsigned pins_clkout3[] = {GPIO2};
+
+static const unsigned pins_pci_gnt1[] = {GPIO30};
+static const unsigned pins_pci_gnt2[] = {GPIO23};
+static const unsigned pins_pci_gnt3[] = {GPIO19};
+static const unsigned pins_pci_gnt4[] = {GPIO38};
+static const unsigned pins_pci_req1[] = {GPIO29};
+static const unsigned pins_pci_req2[] = {GPIO31};
+static const unsigned pins_pci_req3[] = {GPIO3};
+static const unsigned pins_pci_req4[] = {GPIO37};
+
+static const struct ltq_pin_group xway_grps[] = {
+	GRP_MUX("exin0", EXIN, pins_exin0),
+	GRP_MUX("exin1", EXIN, pins_exin1),
+	GRP_MUX("exin2", EXIN, pins_exin2),
+	GRP_MUX("jtag", JTAG, pins_jtag),
+	GRP_MUX("ebu a23", EBU, pins_ebu_a23),
+	GRP_MUX("ebu a24", EBU, pins_ebu_a24),
+	GRP_MUX("ebu a25", EBU, pins_ebu_a25),
+	GRP_MUX("ebu clk", EBU, pins_ebu_clk),
+	GRP_MUX("ebu cs1", EBU, pins_ebu_cs1),
+	GRP_MUX("ebu wait", EBU, pins_ebu_wait),
+	GRP_MUX("nand ale", EBU, pins_nand_ale),
+	GRP_MUX("nand cs1", EBU, pins_nand_cs1),
+	GRP_MUX("nand cle", EBU, pins_nand_cle),
+	GRP_MUX("spi", SPI, pins_spi),
+	GRP_MUX("spi_cs1", SPI, pins_spi_cs1),
+	GRP_MUX("spi_cs2", SPI, pins_spi_cs2),
+	GRP_MUX("spi_cs3", SPI, pins_spi_cs3),
+	GRP_MUX("spi_cs4", SPI, pins_spi_cs4),
+	GRP_MUX("spi_cs5", SPI, pins_spi_cs5),
+	GRP_MUX("spi_cs6", SPI, pins_spi_cs6),
+	GRP_MUX("asc0", ASC, pins_asc0),
+	GRP_MUX("asc0 cts rts", ASC, pins_asc0_cts_rts),
+	GRP_MUX("stp", STP, pins_stp),
+	GRP_MUX("nmi", NMI, pins_nmi),
+	GRP_MUX("gpt1", GPT, pins_gpt1),
+	GRP_MUX("gpt2", GPT, pins_gpt2),
+	GRP_MUX("gpt3", GPT, pins_gpt3),
+	GRP_MUX("clkout0", CGU, pins_clkout0),
+	GRP_MUX("clkout1", CGU, pins_clkout1),
+	GRP_MUX("clkout2", CGU, pins_clkout2),
+	GRP_MUX("clkout3", CGU, pins_clkout3),
+	GRP_MUX("gnt1", PCI, pins_pci_gnt1),
+	GRP_MUX("gnt2", PCI, pins_pci_gnt2),
+	GRP_MUX("gnt3", PCI, pins_pci_gnt3),
+	GRP_MUX("req1", PCI, pins_pci_req1),
+	GRP_MUX("req2", PCI, pins_pci_req2),
+	GRP_MUX("req3", PCI, pins_pci_req3),
+/* xrx only */
+	GRP_MUX("nand rdy", EBU, pins_nand_rdy),
+	GRP_MUX("nand rd", EBU, pins_nand_rd),
+	GRP_MUX("exin3", EXIN, pins_exin3),
+	GRP_MUX("exin4", EXIN, pins_exin4),
+	GRP_MUX("gnt4", PCI, pins_pci_gnt4),
+	GRP_MUX("req4", PCI, pins_pci_gnt4),
+};
+
+static const char * const xway_pci_grps[] = {"gnt1", "gnt2",
+						"gnt3", "req1",
+						"req2", "req3"};
+static const char * const xway_spi_grps[] = {"spi", "spi_cs1",
+						"spi_cs2", "spi_cs3",
+						"spi_cs4", "spi_cs5",
+						"spi_cs6"};
+static const char * const xway_cgu_grps[] = {"clkout0", "clkout1",
+						"clkout2", "clkout3"};
+static const char * const xway_ebu_grps[] = {"ebu a23", "ebu a24",
+						"ebu a25", "ebu cs1",
+						"ebu wait", "ebu clk",
+						"nand ale", "nand cs1",
+						"nand cle"};
+static const char * const xway_exin_grps[] = {"exin0", "exin1", "exin2"};
+static const char * const xway_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
+static const char * const xway_asc_grps[] = {"asc0", "asc0 cts rts"};
+static const char * const xway_jtag_grps[] = {"jtag"};
+static const char * const xway_stp_grps[] = {"stp"};
+static const char * const xway_nmi_grps[] = {"nmi"};
+
+/* ar9/vr9/gr9 */
+static const char * const xrx_ebu_grps[] = {"ebu a23", "ebu a24",
+						"ebu a25", "ebu cs1",
+						"ebu wait", "ebu clk",
+						"nand ale", "nand cs1",
+						"nand cle", "nand rdy",
+						"nand rd"};
+static const char * const xrx_exin_grps[] = {"exin0", "exin1", "exin2",
+						"exin3", "exin4"};
+static const char * const xrx_pci_grps[] = {"gnt1", "gnt2",
+						"gnt3", "gnt4",
+						"req1", "req2",
+						"req3", "req4"};
+
+static const struct ltq_pmx_func danube_funcs[] = {
+	{"spi",		ARRAY_AND_SIZE(xway_spi_grps)},
+	{"asc",		ARRAY_AND_SIZE(xway_asc_grps)},
+	{"cgu",		ARRAY_AND_SIZE(xway_cgu_grps)},
+	{"jtag",	ARRAY_AND_SIZE(xway_jtag_grps)},
+	{"exin",	ARRAY_AND_SIZE(xway_exin_grps)},
+	{"stp",		ARRAY_AND_SIZE(xway_stp_grps)},
+	{"gpt",		ARRAY_AND_SIZE(xway_gpt_grps)},
+	{"nmi",		ARRAY_AND_SIZE(xway_nmi_grps)},
+	{"pci",		ARRAY_AND_SIZE(xway_pci_grps)},
+	{"ebu",		ARRAY_AND_SIZE(xway_ebu_grps)},
+};
+
+static const struct ltq_pmx_func xrx_funcs[] = {
+	{"spi",		ARRAY_AND_SIZE(xway_spi_grps)},
+	{"asc",		ARRAY_AND_SIZE(xway_asc_grps)},
+	{"cgu",		ARRAY_AND_SIZE(xway_cgu_grps)},
+	{"jtag",	ARRAY_AND_SIZE(xway_jtag_grps)},
+	{"exin",	ARRAY_AND_SIZE(xrx_exin_grps)},
+	{"stp",		ARRAY_AND_SIZE(xway_stp_grps)},
+	{"gpt",		ARRAY_AND_SIZE(xway_gpt_grps)},
+	{"nmi",		ARRAY_AND_SIZE(xway_nmi_grps)},
+	{"pci",		ARRAY_AND_SIZE(xrx_pci_grps)},
+	{"ebu",		ARRAY_AND_SIZE(xrx_ebu_grps)},
+};
+
+
+
+
+
+
+/* ---------  pinconf related code --------- */
+static int xway_pinconf_group_get(struct pinctrl_dev *pctldev,
+				unsigned group,
+				unsigned long *config)
+{
+	return -ENOTSUPP;
+}
+
+static int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
+				unsigned group,
+				unsigned long config)
+{
+	return -ENOTSUPP;
+}
+
+static int xway_pinconf_get(struct pinctrl_dev *pctldev,
+				unsigned pin,
+				unsigned long *config)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+	enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(*config);
+	int port = PORT(pin);
+	u32 reg;
+
+	switch (param) {
+	case LTQ_PINCONF_PARAM_OPEN_DRAIN:
+		if (port == 3)
+			reg = GPIO3_OD;
+		else
+			reg = GPIO_OD(port);
+		*config = LTQ_PINCONF_PACK(param,
+			!!gpio_getbit(info->membase[0], reg, PORT_PIN(port)));
+		break;
+
+	case LTQ_PINCONF_PARAM_PULL:
+		if (port == 3)
+			reg = GPIO3_PUDEN;
+		else
+			reg = GPIO_PUDEN(port);
+		if (!gpio_getbit(info->membase[0], reg, PORT_PIN(port))) {
+			*config = LTQ_PINCONF_PACK(param, 0);
+			break;
+		}
+
+		if (port == 3)
+			reg = GPIO3_PUDSEL;
+		else
+			reg = GPIO_PUDSEL(port);
+		if (!gpio_getbit(info->membase[0], reg, PORT_PIN(port)))
+			*config = LTQ_PINCONF_PACK(param, 2);
+		else
+			*config = LTQ_PINCONF_PACK(param, 1);
+		break;
+
+	default:
+		pr_err("%s: Invalid config param %04x\n",
+					pinctrl_dev_get_name(pctldev), param);
+		return -ENOTSUPP;
+	}
+	return 0;
+}
+
+static int xway_pinconf_set(struct pinctrl_dev *pctldev,
+				unsigned pin,
+				unsigned long config)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+	enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(config);
+	int arg = LTQ_PINCONF_UNPACK_ARG(config);
+	int port = PORT(pin);
+	u32 reg;
+
+	switch (param) {
+	case LTQ_PINCONF_PARAM_OPEN_DRAIN:
+		if (port == 3)
+			reg = GPIO3_OD;
+		else
+			reg = GPIO_OD(port);
+		gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+		break;
+
+	case LTQ_PINCONF_PARAM_PULL:
+		if (port == 3)
+			reg = GPIO3_PUDEN;
+		else
+			reg = GPIO_PUDEN(port);
+		if (arg == 0) {
+			gpio_clearbit(info->membase[0], reg, PORT_PIN(port));
+			break;
+		}
+		gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+
+		if (port == 3)
+			reg = GPIO3_PUDSEL;
+		else
+			reg = GPIO_PUDSEL(port);
+		if (arg == 1)
+			gpio_clearbit(info->membase[0], reg, PORT_PIN(port));
+		else if (arg == 2)
+			gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+		else
+			pr_err("%s: Invalid pull value %d\n",
+				pinctrl_dev_get_name(pctldev), arg);
+		break;
+
+	default:
+		pr_err("%s: Invalid config param %04x\n",
+					pinctrl_dev_get_name(pctldev), param);
+		return -ENOTSUPP;
+	}
+	return 0;
+}
+
+static void xway_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s, unsigned offset)
+{
+}
+
+static void xway_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s, unsigned selector)
+{
+}
+
+struct pinconf_ops xway_pinconf_ops = {
+	.pin_config_get			= xway_pinconf_get,
+	.pin_config_set			= xway_pinconf_set,
+	.pin_config_group_get		= xway_pinconf_group_get,
+	.pin_config_group_set		= xway_pinconf_group_set,
+	.pin_config_dbg_show		= xway_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= xway_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc xway_pctrl_desc = {
+	.owner		= THIS_MODULE,
+	.confops	= &xway_pinconf_ops,
+};
+
+static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
+				int pin, int mux)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	int port = PORT(pin);
+
+	if (mux & 0x1)
+		gpio_setbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
+	else
+		gpio_clearbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
+
+	if ((port == 3) && (mux & 0x2))
+		gpio_setbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
+	else if (mux & 0x2)
+		gpio_setbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
+	else if (port == 3)
+		gpio_clearbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
+	else
+		gpio_clearbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
+
+	return 0;
+}
+
+static const struct ltq_cfg_param xway_cfg_params[] = {
+	{"lantiq,pull",		LTQ_PINCONF_PARAM_PULL},
+	{"lantiq,open-drain",	LTQ_PINCONF_PARAM_OPEN_DRAIN},
+};
+
+static struct ltq_pinmux_info xway_info = {
+	.mfp		= xway_mfp,
+	.desc		= &xway_pctrl_desc,
+	.apply_mux	= xway_mux_apply,
+	.params		= xway_cfg_params,
+	.num_params	= ARRAY_SIZE(xway_cfg_params),
+};
+
+
+
+
+/* ---------  gpio_chip related code --------- */
+
+int gpio_to_irq(unsigned int gpio)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned int gpio)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL(irq_to_gpio);
+
+static inline int xway_gpio_pin_count(void)
+{
+	if (of_machine_is_compatible("lantiq,ar9") ||
+			of_machine_is_compatible("lantiq,gr9") ||
+			of_machine_is_compatible("lantiq,vr9"))
+		return 56;
+	return 32;
+}
+
+static void xway_gpio_set(struct gpio_chip *chip, unsigned int pin, int val)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	if (val)
+		gpio_setbit(info->membase[0], GPIO_OUT(pin), PORT_PIN(pin));
+	else
+		gpio_clearbit(info->membase[0], GPIO_OUT(pin), PORT_PIN(pin));
+}
+
+static int xway_gpio_get(struct gpio_chip *chip, unsigned int pin)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	return gpio_getbit(info->membase[0], GPIO_IN(pin), PORT_PIN(pin));
+}
+
+static int xway_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	gpio_clearbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+
+	return 0;
+}
+
+static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+	xway_gpio_set(chip, pin, val);
+
+	return 0;
+}
+
+static int xway_gpio_req(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static struct gpio_chip xway_chip = {
+	.label = "gpio-xway",
+	.direction_input = xway_gpio_dir_in,
+	.direction_output = xway_gpio_dir_out,
+	.get = xway_gpio_get,
+	.set = xway_gpio_set,
+	.request = xway_gpio_req,
+	.free = xway_gpio_free,
+	.base = 0,
+};
+
+
+
+
+/* --------- register the pinctrl layer --------- */
+
+static struct pinctrl_gpio_range xway_gpio_range = {
+	.name	= "XWAY GPIO",
+	.id	= 0,
+	.base	= 0,
+	.gc	= &xway_chip,
+};
+
+static int __devinit pinmux_xway_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret, i;
+
+	/* get and remap our register range */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get resource\n");
+		return -ENOENT;
+	}
+	xway_info.membase[0] = devm_request_and_ioremap(&pdev->dev, res);
+	if (!xway_info.membase[0]) {
+		dev_err(&pdev->dev, "Failed to remap resource\n");
+		return -ENOMEM;
+	}
+
+	/* find out how many pads we have */
+	xway_chip.ngpio = xway_gpio_pin_count();
+
+	/* load our pad descriptors */
+	xway_info.pads = devm_kzalloc(&pdev->dev,
+			sizeof(struct pinctrl_pin_desc) * xway_chip.ngpio,
+			GFP_KERNEL);
+	if (!xway_info.pads) {
+		dev_err(&pdev->dev, "Failed to allocate pads\n");
+		return -ENOMEM;
+	}
+	for (i = 0; i < xway_chip.ngpio; i++) {
+		/* strlen("ioXY") + 1 = 5 */
+		char *name = devm_kzalloc(&pdev->dev, 5, GFP_KERNEL);
+
+		if (!name) {
+			dev_err(&pdev->dev, "Failed to allocate pad name\n");
+			return -ENOMEM;
+		}
+		snprintf(name, 5, "io%d", i);
+		xway_info.pads[i].number = GPIO0 + i;
+		xway_info.pads[i].name = name;
+	}
+	xway_pctrl_desc.pins = xway_info.pads;
+
+	/* load the gpio chip */
+	xway_chip.dev = &pdev->dev;
+	of_gpiochip_add(&xway_chip);
+	ret = gpiochip_add(&xway_chip);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register gpio chip\n");
+		return ret;
+	}
+
+	/* setup the data needed by pinctrl */
+	xway_pctrl_desc.name	= dev_name(&pdev->dev);
+	xway_pctrl_desc.npins	= xway_chip.ngpio;
+
+	xway_info.num_gpio	= xway_chip.ngpio;
+	xway_info.num_mfp	= xway_chip.ngpio;
+	xway_info.grps		= xway_grps;
+	xway_info.num_grps	= ARRAY_SIZE(xway_grps);
+	if (xway_gpio_pin_count() == 56) {
+		xway_info.funcs		= xrx_funcs;
+		xway_info.num_funcs	= ARRAY_SIZE(xrx_funcs);
+	} else {
+		xway_info.funcs		= danube_funcs;
+		xway_info.num_funcs	= ARRAY_SIZE(danube_funcs);
+	}
+
+	/* register with the generic lantiq layer */
+	ret = ltq_pinctrl_register(pdev, &xway_info);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register pinctrl driver\n");
+		return ret;
+	}
+
+	/* finish with registering the gpio range in pinctrl */
+	xway_gpio_range.npins = xway_chip.ngpio;
+	pinctrl_add_gpio_range(xway_info.pctrl, &xway_gpio_range);
+	dev_info(&pdev->dev, "Init done\n");
+	return 0;
+}
+
+static const struct of_device_id xway_match[] = {
+	{ .compatible = "lantiq,pinctrl-xway" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xway_match);
+
+static struct platform_driver pinmux_xway_driver = {
+	.probe	= pinmux_xway_probe,
+	.driver = {
+		.name	= "pinctrl-xway",
+		.owner	= THIS_MODULE,
+		.of_match_table = xway_match,
+	},
+};
+
+static int __init pinmux_xway_init(void)
+{
+	return platform_driver_register(&pinmux_xway_driver);
+}
+
+core_initcall_sync(pinmux_xway_init);
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-04 12:18     ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, John Crispin, devicetree-discuss, Linus Walleij,
	Stephen Warren

Implement support for pinctrl on lantiq/xway socs. The IO core found on these
socs has the registers for pinctrl, pinconf and gpio mixed up in the same
register range. As the gpio_chip handling is only a few lines, the driver also
implements the gpio functionality. This obseletes the old gpio driver that was
located in the arch/ folder.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Stephen Warren <swarren@wwwdotorg.org>
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/Kconfig                                  |    1 +
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    2 -
 arch/mips/lantiq/Kconfig                           |    1 +
 arch/mips/lantiq/xway/Makefile                     |    2 +-
 arch/mips/lantiq/xway/gpio.c                       |  195 ------
 arch/mips/lantiq/xway/gpio_stp.c                   |    5 -
 arch/mips/pci/pci-lantiq.c                         |   44 +--
 drivers/pinctrl/Kconfig                            |    9 +
 drivers/pinctrl/Makefile                           |    2 +
 drivers/pinctrl/pinctrl-lantiq.c                   |  308 +++++++++
 drivers/pinctrl/pinctrl-lantiq.h                   |  184 +++++
 drivers/pinctrl/pinctrl-xway.c                     |  702 ++++++++++++++++++++
 12 files changed, 1209 insertions(+), 246 deletions(-)
 delete mode 100644 arch/mips/lantiq/xway/gpio.c
 create mode 100644 drivers/pinctrl/pinctrl-lantiq.c
 create mode 100644 drivers/pinctrl/pinctrl-lantiq.h
 create mode 100644 drivers/pinctrl/pinctrl-xway.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fbb5639..00a0482 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -216,6 +216,7 @@ config MACH_JZ4740
 config LANTIQ
 	bool "Lantiq based platforms"
 	select DMA_NONCOHERENT
+	select PINCTRL
 	select IRQ_CPU
 	select CEVT_R4K
 	select CSRC_R4K
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 15eb4dc..150c7be 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -153,8 +153,6 @@
 #define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
 /* request a non-gpio and set the PIO config */
-extern int  ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name);
 extern void ltq_pmu_enable(unsigned int module);
 extern void ltq_pmu_disable(unsigned int module);
 
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 9485fe5..b86d942 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -2,6 +2,7 @@ if LANTIQ
 
 config SOC_TYPE_XWAY
 	bool
+	select PINCTRL_XWAY
 	default n
 
 choice
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 7a6c30f..323b574 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
-obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o dma.o
+obj-y := prom.o pmu.o ebu.o reset.o gpio_stp.o gpio_ebu.o dma.o
 
 obj-$(CONFIG_SOC_XWAY) += clk-xway.o
 obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
deleted file mode 100644
index c429a5b..0000000
--- a/arch/mips/lantiq/xway/gpio.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <lantiq_soc.h>
-
-#define LTQ_GPIO_OUT		0x00
-#define LTQ_GPIO_IN		0x04
-#define LTQ_GPIO_DIR		0x08
-#define LTQ_GPIO_ALTSEL0	0x0C
-#define LTQ_GPIO_ALTSEL1	0x10
-#define LTQ_GPIO_OD		0x14
-
-#define PINS_PER_PORT		16
-#define MAX_PORTS		3
-
-#define ltq_gpio_getbit(m, r, p)	(!!(ltq_r32(m + r) & (1 << p)))
-#define ltq_gpio_setbit(m, r, p)	ltq_w32_mask(0, (1 << p), m + r)
-#define ltq_gpio_clearbit(m, r, p)	ltq_w32_mask((1 << p), 0, m + r)
-
-struct ltq_gpio {
-	void __iomem *membase;
-	struct gpio_chip chip;
-};
-
-static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
-
-int gpio_to_irq(unsigned int gpio)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_to_irq);
-
-int irq_to_gpio(unsigned int gpio)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL(irq_to_gpio);
-
-int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name)
-{
-	int id = 0;
-
-	if (pin >= (MAX_PORTS * PINS_PER_PORT))
-		return -EINVAL;
-	if (gpio_request(pin, name)) {
-		pr_err("failed to setup lantiq gpio: %s\n", name);
-		return -EBUSY;
-	}
-	if (dir)
-		gpio_direction_output(pin, 1);
-	else
-		gpio_direction_input(pin);
-	while (pin >= PINS_PER_PORT) {
-		pin -= PINS_PER_PORT;
-		id++;
-	}
-	if (alt0)
-		ltq_gpio_setbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL0, pin);
-	else
-		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL0, pin);
-	if (alt1)
-		ltq_gpio_setbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL1, pin);
-	else
-		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL1, pin);
-	return 0;
-}
-EXPORT_SYMBOL(ltq_gpio_request);
-
-static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	if (value)
-		ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
-	else
-		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
-}
-
-static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset);
-}
-
-static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
-
-	return 0;
-}
-
-static int ltq_gpio_direction_output(struct gpio_chip *chip,
-	unsigned int offset, int value)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
-	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
-	ltq_gpio_set(chip, offset, value);
-
-	return 0;
-}
-
-static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
-{
-	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
-
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
-	return 0;
-}
-
-static int ltq_gpio_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-
-	if (pdev->id >= MAX_PORTS) {
-		dev_err(&pdev->dev, "invalid gpio port %d\n",
-			pdev->id);
-		return -EINVAL;
-	}
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
-			pdev->id);
-		return -ENOENT;
-	}
-	res = devm_request_mem_region(&pdev->dev, res->start,
-		resource_size(res), dev_name(&pdev->dev));
-	if (!res) {
-		dev_err(&pdev->dev,
-			"failed to request memory for gpio port %d\n",
-			pdev->id);
-		return -EBUSY;
-	}
-	ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev,
-		res->start, resource_size(res));
-	if (!ltq_gpio_port[pdev->id].membase) {
-		dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n",
-			pdev->id);
-		return -ENOMEM;
-	}
-	ltq_gpio_port[pdev->id].chip.label = "ltq_gpio";
-	ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input;
-	ltq_gpio_port[pdev->id].chip.direction_output =
-		ltq_gpio_direction_output;
-	ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get;
-	ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
-	ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
-	ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
-	ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
-	platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
-	return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
-}
-
-static struct platform_driver
-ltq_gpio_driver = {
-	.probe = ltq_gpio_probe,
-	.driver = {
-		.name = "ltq_gpio",
-		.owner = THIS_MODULE,
-	},
-};
-
-int __init ltq_gpio_init(void)
-{
-	int ret = platform_driver_register(&ltq_gpio_driver);
-
-	if (ret)
-		pr_info("ltq_gpio : Error registering platform driver!");
-	return ret;
-}
-
-postcore_initcall(ltq_gpio_init);
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
index fd07d87..4f4bd61 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -78,11 +78,6 @@ static struct gpio_chip ltq_stp_chip = {
 
 static int ltq_stp_hw_init(void)
 {
-	/* the 3 pins used to control the external stp */
-	ltq_gpio_request(4, 1, 0, 1, "stp-st");
-	ltq_gpio_request(5, 1, 0, 1, "stp-d");
-	ltq_gpio_request(6, 1, 0, 1, "stp-sh");
-
 	/* sane defaults */
 	ltq_stp_w32(0, LTQ_STP_AR);
 	ltq_stp_w32(0, LTQ_STP_CPU0);
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
index 70fdf2c..3418178 100644
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -68,32 +68,6 @@
 #define ltq_pci_cfg_w32(x, y)	ltq_w32((x), ltq_pci_mapped_cfg + (y))
 #define ltq_pci_cfg_r32(x)	ltq_r32(ltq_pci_mapped_cfg + (x))
 
-struct ltq_pci_gpio_map {
-	int pin;
-	int alt0;
-	int alt1;
-	int dir;
-	char *name;
-};
-
-/* the pci core can make use of the following gpios */
-static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
-	{ 0, 1, 0, 0, "pci-exin0" },
-	{ 1, 1, 0, 0, "pci-exin1" },
-	{ 2, 1, 0, 0, "pci-exin2" },
-	{ 39, 1, 0, 0, "pci-exin3" },
-	{ 10, 1, 0, 0, "pci-exin4" },
-	{ 9, 1, 0, 0, "pci-exin5" },
-	{ 30, 1, 0, 1, "pci-gnt1" },
-	{ 23, 1, 0, 1, "pci-gnt2" },
-	{ 19, 1, 0, 1, "pci-gnt3" },
-	{ 38, 1, 0, 1, "pci-gnt4" },
-	{ 29, 1, 0, 0, "pci-req1" },
-	{ 31, 1, 0, 0, "pci-req2" },
-	{ 3, 1, 0, 0, "pci-req3" },
-	{ 37, 1, 0, 0, "pci-req4" },
-};
-
 __iomem void *ltq_pci_mapped_cfg;
 static __iomem void *ltq_pci_membase;
 
@@ -151,22 +125,6 @@ static u32 ltq_calc_bar11mask(void)
 	return bar11mask;
 }
 
-static void ltq_pci_setup_gpio(int gpio)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
-		if (gpio & (1 << i)) {
-			ltq_gpio_request(ltq_pci_gpio_map[i].pin,
-				ltq_pci_gpio_map[i].alt0,
-				ltq_pci_gpio_map[i].alt1,
-				ltq_pci_gpio_map[i].dir,
-				ltq_pci_gpio_map[i].name);
-		}
-	}
-	ltq_gpio_request(21, 0, 0, 1, "pci-reset");
-	ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
-}
-
 static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
 {
 	u32 temp_buffer;
@@ -192,7 +150,7 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
 	}
 
 	/* setup pci clock and gpis used by pci */
-	ltq_pci_setup_gpio(conf->gpio);
+	gpio_request(21, "pci-reset");
 
 	/* enable auto-switching between PCI and EBU */
 	ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f73a5ea..a19bac96 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
 	bool
 	select PINMUX
 
+config PINCTRL_LANTIQ
+	bool
+	select PINMUX
+	select PINCONF
+
 config PINCTRL_MMP2
 	bool "MMP2 pin controller driver"
 	depends on ARCH_MMP
@@ -83,6 +88,10 @@ config PINCTRL_COH901
 	  COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
 	  ports of 8 GPIO pins each.
 
+config PINCTRL_XWAY
+	bool
+	select PINCTRL_LANTIQ
+
 endmenu
 
 endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 8e3c95a..15bf5a3 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -19,3 +19,5 @@ obj-$(CONFIG_PINCTRL_TEGRA20)	+= pinctrl-tegra20.o
 obj-$(CONFIG_PINCTRL_TEGRA30)	+= pinctrl-tegra30.o
 obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
+obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
+obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
new file mode 100644
index 0000000..f2e28a5
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -0,0 +1,308 @@
+/*
+ *  linux/drivers/pinctrl/pinctrl-lantiq.c
+ *  based on linux/drivers/pinctrl/pinctrl-pxa3xx.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
+ *  publishhed by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "core.h"
+
+#include "pinctrl-lantiq.h"
+
+static int ltq_get_group_count(struct pinctrl_dev *pctrldev)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	return info->num_grps;
+}
+
+static const char *ltq_get_group_name(struct pinctrl_dev *pctrldev,
+					 unsigned selector)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	if (selector >= info->num_grps)
+		return NULL;
+	return info->grps[selector].name;
+}
+
+static int ltq_get_group_pins(struct pinctrl_dev *pctrldev,
+				 unsigned selector,
+				 const unsigned **pins,
+				 unsigned *num_pins)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	if (selector >= info->num_grps)
+		return -EINVAL;
+	*pins = info->grps[selector].pins;
+	*num_pins = info->grps[selector].npins;
+	return 0;
+}
+
+void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+	int i;
+
+	for (i = 0; i < num_maps; i++)
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+			kfree(map[i].data.configs.configs);
+	kfree(map);
+}
+
+static void ltq_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s,
+					unsigned offset)
+{
+	seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+				struct device_node *np,
+				struct pinctrl_map **map)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+	unsigned long configs[3];
+	unsigned num_configs = 0;
+	struct property *prop;
+	const char *group, *pin;
+	const char *function;
+	int ret, i;
+
+	ret = of_property_read_string(np, "lantiq,function", &function);
+	if (!ret) {
+		of_property_for_each_string(np, "lantiq,groups", prop, group) {
+			(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
+			(*map)->name = function;
+			(*map)->data.mux.group = group;
+			(*map)->data.mux.function = function;
+			(*map)++;
+		}
+		if (of_find_property(np, "lantiq,pins", NULL))
+			dev_err(pctldev->dev,
+				"%s mixes pins and groups settings\n",
+				np->name);
+		return 0;
+	}
+
+	for (i = 0; i < info->num_params; i++) {
+		u32 val;
+		int ret = of_property_read_u32(np,
+				info->params[i].property, &val);
+		if (!ret)
+			configs[num_configs++] =
+				LTQ_PINCONF_PACK(info->params[i].param,
+				val);
+	}
+
+	if (!num_configs)
+		return -EINVAL;
+
+	of_property_for_each_string(np, "lantiq,pins", prop, pin) {
+		(*map)->data.configs.configs = kmemdup(configs,
+					num_configs * sizeof(unsigned long),
+					GFP_KERNEL);
+		(*map)->type = PIN_MAP_TYPE_CONFIGS_PIN;
+		(*map)->name = pin;
+		(*map)->data.configs.group_or_pin = pin;
+		(*map)->data.configs.num_configs = num_configs;
+		(*map)++;
+	}
+	return 0;
+}
+
+static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
+{
+	int ret;
+
+	ret = of_property_count_strings(np, "lantiq,groups");
+	if (ret < 0)
+		ret = of_property_count_strings(np, "lantiq,pins");
+	return ret;
+}
+
+int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+				struct device_node *np_config,
+				struct pinctrl_map **map,
+				unsigned *num_maps)
+{
+	struct pinctrl_map *tmp;
+	struct device_node *np;
+	int ret;
+
+	*num_maps = 0;
+	for_each_child_of_node(np_config, np)
+		*num_maps += ltq_pinctrl_dt_subnode_size(np);
+	*map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
+	tmp = *map;
+
+	for_each_child_of_node(np_config, np) {
+		ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
+		if (ret < 0) {
+			ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static struct pinctrl_ops ltq_pctrl_ops = {
+	.get_groups_count	= ltq_get_group_count,
+	.get_group_name		= ltq_get_group_name,
+	.get_group_pins		= ltq_get_group_pins,
+	.pin_dbg_show		= ltq_pinctrl_pin_dbg_show,
+	.dt_node_to_map		= ltq_pinctrl_dt_node_to_map,
+	.dt_free_map		= ltq_pinctrl_dt_free_map,
+};
+
+static int ltq_pmx_func_count(struct pinctrl_dev *pctrldev)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+	return info->num_funcs;
+}
+
+static const char *ltq_pmx_func_name(struct pinctrl_dev *pctrldev,
+					 unsigned selector)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+	if (selector >= info->num_funcs)
+		return NULL;
+
+	return info->funcs[selector].name;
+}
+
+static int ltq_pmx_get_groups(struct pinctrl_dev *pctrldev,
+				unsigned func,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+	*groups = info->funcs[func].groups;
+	*num_groups = info->funcs[func].num_groups;
+
+	return 0;
+}
+
+/* Return function number. If failure, return negative value. */
+static int match_mux(const struct ltq_mfp_pin *mfp, unsigned mux)
+{
+	int i;
+	for (i = 0; i < LTQ_MAX_MUX; i++) {
+		if (mfp->func[i] == mux)
+			break;
+	}
+	if (i >= LTQ_MAX_MUX)
+		return -EINVAL;
+	return i;
+}
+
+/* check whether current pin configuration is valid. Negative for failure */
+static int match_group_mux(const struct ltq_pin_group *grp,
+			   const struct ltq_pinmux_info *info,
+			   unsigned mux)
+{
+	int i, pin, ret = 0;
+	for (i = 0; i < grp->npins; i++) {
+		pin = grp->pins[i];
+		ret = match_mux(&info->mfp[pin], mux);
+		if (ret < 0) {
+			dev_err(info->dev, "Can't find mux %d on pin%d\n",
+				mux, pin);
+			break;
+		}
+	}
+	return ret;
+}
+
+static int ltq_pmx_enable(struct pinctrl_dev *pctrldev,
+				unsigned func,
+				unsigned group)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	const struct ltq_pin_group *pin_grp = &info->grps[group];
+	int i, pin, pin_func;
+
+	if (!pin_grp->npins ||
+		(match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
+		dev_err(info->dev, "Failed to set the pin group: %s\n",
+			info->grps[group].name);
+		return -EINVAL;
+	}
+	for (i = 0; i < pin_grp->npins; i++) {
+		pin = pin_grp->pins[i];
+		pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
+		info->apply_mux(pctrldev, pin, pin_func);
+	}
+	return 0;
+}
+
+static void ltq_pmx_disable(struct pinctrl_dev *pctrldev,
+				unsigned func,
+				unsigned group)
+{
+}
+
+static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
+				struct pinctrl_gpio_range *range,
+				unsigned pin)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	int pin_func;
+
+	/* all our pins are gpio when muxing is set to 0. check anyhow */
+	pin_func = match_mux(&info->mfp[pin], 0);
+	if (pin_func < 0) {
+		dev_err(info->dev, "No GPIO function on pin%d\n", pin);
+		return -EINVAL;
+	}
+
+	info->apply_mux(pctrldev, pin, 0);
+
+	return 0;
+}
+
+static struct pinmux_ops ltq_pmx_ops = {
+	.get_functions_count	= ltq_pmx_func_count,
+	.get_function_name	= ltq_pmx_func_name,
+	.get_function_groups	= ltq_pmx_get_groups,
+	.enable			= ltq_pmx_enable,
+	.disable		= ltq_pmx_disable,
+	.gpio_request_enable	= ltq_pmx_gpio_request_enable,
+};
+
+/*
+ * allow different socs to register with the generic part of the lanti
+ * pinctrl code
+ */
+int ltq_pinctrl_register(struct platform_device *pdev,
+				struct ltq_pinmux_info *info)
+{
+	struct pinctrl_desc *desc;
+
+	if (!info)
+		return -EINVAL;
+	desc = info->desc;
+	desc->pctlops = &ltq_pctrl_ops;
+	desc->pmxops = &ltq_pmx_ops;
+	info->dev = &pdev->dev;
+
+	info->pctrl = pinctrl_register(desc, &pdev->dev, info);
+	if (!info->pctrl) {
+		dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n");
+		return -EINVAL;
+	}
+	platform_set_drvdata(pdev, info);
+	return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
new file mode 100644
index 0000000..dc84c09
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-lantiq.h
@@ -0,0 +1,184 @@
+/*
+ *  linux/drivers/pinctrl/pinctrl-lantiq.h
+ *  based on linux/drivers/pinctrl/pinctrl-pxa3xx.h
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef __PINCTRL_LANTIQ_H
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
+
+#define LTQ_MAX_MUX		4
+#define MFPR_FUNC_MASK		0x3
+
+#define LTQ_PINCONF_PACK(_param_, _arg_)	((_param_) << 16 | (_arg_))
+#define LTQ_PINCONF_UNPACK_PARAM(_conf_)	((_conf_) >> 16)
+#define LTQ_PINCONF_UNPACK_ARG(_conf_)		((_conf_) & 0xffff)
+
+enum ltq_pinconf_param {
+	LTQ_PINCONF_PARAM_PULL,
+	LTQ_PINCONF_PARAM_OPEN_DRAIN,
+	LTQ_PINCONF_PARAM_DRIVE_CURRENT,
+	LTQ_PINCONF_PARAM_SLEW_RATE,
+};
+
+struct ltq_cfg_param {
+	const char *property;
+	enum ltq_pinconf_param param;
+};
+
+struct ltq_mfp_pin {
+	const char *name;
+	const unsigned int pin;
+	const unsigned short func[LTQ_MAX_MUX];
+};
+
+struct ltq_pin_group {
+	const char *name;
+	const unsigned mux;
+	const unsigned *pins;
+	const unsigned npins;
+};
+
+struct ltq_pmx_func {
+	const char *name;
+	const char * const *groups;
+	const unsigned num_groups;
+};
+
+struct ltq_pinmux_info {
+	struct device *dev;
+	struct pinctrl_dev *pctrl;
+
+	/* we need to manage up to 5 padcontrolers */
+	void __iomem *membase[5];
+
+	/* the handler for the subsystem */
+	struct pinctrl_desc *desc;
+
+	/* we expose our pads to the subsystem */
+	struct pinctrl_pin_desc *pads;
+
+	/* the number of pads. this varies between socs */
+	unsigned int num_gpio;
+
+	/* these are our multifunction pins */
+	const struct ltq_mfp_pin *mfp;
+	unsigned int num_mfp;
+
+	/* a number of multifunction pins can be grouped together */
+	const struct ltq_pin_group *grps;
+	unsigned int num_grps;
+
+	/* a mapping between function string and id */
+	const struct ltq_pmx_func *funcs;
+	unsigned int num_funcs;
+
+	/* the pinconf options that we are able to read from the DT */
+	const struct ltq_cfg_param *params;
+	unsigned int num_params;
+
+	/* soc specific callback used to apply muxing */
+	int (*apply_mux)(struct pinctrl_dev *pctrldev, int pin, int mux);
+};
+
+enum ltq_pin_list {
+	GPIO0 = 0,
+	GPIO1,
+	GPIO2,
+	GPIO3,
+	GPIO4,
+	GPIO5,
+	GPIO6,
+	GPIO7,
+	GPIO8,
+	GPIO9,
+	GPIO10, /* 10 */
+	GPIO11,
+	GPIO12,
+	GPIO13,
+	GPIO14,
+	GPIO15,
+	GPIO16,
+	GPIO17,
+	GPIO18,
+	GPIO19,
+	GPIO20, /* 20 */
+	GPIO21,
+	GPIO22,
+	GPIO23,
+	GPIO24,
+	GPIO25,
+	GPIO26,
+	GPIO27,
+	GPIO28,
+	GPIO29,
+	GPIO30, /* 30 */
+	GPIO31,
+	GPIO32,
+	GPIO33,
+	GPIO34,
+	GPIO35,
+	GPIO36,
+	GPIO37,
+	GPIO38,
+	GPIO39,
+	GPIO40, /* 40 */
+	GPIO41,
+	GPIO42,
+	GPIO43,
+	GPIO44,
+	GPIO45,
+	GPIO46,
+	GPIO47,
+	GPIO48,
+	GPIO49,
+	GPIO50, /* 50 */
+	GPIO51,
+	GPIO52,
+	GPIO53,
+	GPIO54,
+	GPIO55,
+
+	GPIO64,
+	GPIO65,
+	GPIO66,
+	GPIO67,
+	GPIO68,
+	GPIO69,
+	GPIO70,
+	GPIO71,
+	GPIO72,
+	GPIO73,
+	GPIO74,
+	GPIO75,
+	GPIO76,
+	GPIO77,
+	GPIO78,
+	GPIO79,
+	GPIO80,
+	GPIO81,
+	GPIO82,
+	GPIO83,
+	GPIO84,
+	GPIO85,
+	GPIO86,
+	GPIO87,
+	GPIO88,
+};
+
+extern int ltq_pinctrl_register(struct platform_device *pdev,
+				   struct ltq_pinmux_info *info);
+extern int ltq_pinctrl_unregister(struct platform_device *pdev);
+#endif	/* __PINCTRL_PXA3XX_H */
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
new file mode 100644
index 0000000..efc3174
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -0,0 +1,702 @@
+/*
+ *  linux/drivers/pinctrl/pinmux-xway.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
+ *  publishhed by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-lantiq.h"
+
+#include <lantiq_soc.h>
+
+/* we have 3 1/2 banks of 16 bit each */
+#define PINS			16
+#define PORT(x)			(x / PINS)
+#define PORT_PIN(x)		(x % PINS)
+
+/*
+ * each bank has this offset apart from the 1/2 bank that is mixed into the
+ * other 3 ranges
+ */
+#define REG_OFF			0x30
+
+/* these are the offsets to our registers */
+#define GPIO_BASE(p)		(REG_OFF * PORT(p))
+#define GPIO_OUT(p)		GPIO_BASE(p)
+#define GPIO_IN(p)		(GPIO_BASE(p) + 0x04)
+#define GPIO_DIR(p)		(GPIO_BASE(p) + 0x08)
+#define GPIO_ALT0(p)		(GPIO_BASE(p) + 0x0C)
+#define GPIO_ALT1(p)		(GPIO_BASE(p) + 0x10)
+#define GPIO_OD(p)		(GPIO_BASE(p) + 0x14)
+#define GPIO_PUDSEL(p)		(GPIO_BASE(p) + 0x1c)
+#define GPIO_PUDEN(p)		(GPIO_BASE(p) + 0x20)
+
+/* the 1/2 port needs special offsets for some registers */
+#define GPIO3_OD		(GPIO_BASE(0) + 0x24)
+#define GPIO3_PUDSEL		(GPIO_BASE(0) + 0x28)
+#define GPIO3_PUDEN		(GPIO_BASE(0) + 0x2C)
+#define GPIO3_ALT1		(GPIO_BASE(PINS) + 0x24)
+
+/* PORT3 only has 8 pins and its register layout
+   is slightly different */
+#define PINS_PER_PORT		16
+#define PINS_PORT3		8
+#define MAX_PORTS		4
+#define MAX_PIN			56
+
+/* macros to help us access the registers */
+#define gpio_getbit(m, r, p)	(!!(ltq_r32(m + r) & (1 << p)))
+#define gpio_setbit(m, r, p)	ltq_w32_mask(0, (1 << p), m + r)
+#define gpio_clearbit(m, r, p)	ltq_w32_mask((1 << p), 0, m + r)
+
+#define MFP_XWAY(a, f0, f1, f2, f3)	\
+	{				\
+		.name = #a,		\
+		.pin = a,		\
+		.func = {		\
+			XWAY_MUX_##f0,	\
+			XWAY_MUX_##f1,	\
+			XWAY_MUX_##f2,	\
+			XWAY_MUX_##f3,	\
+		},			\
+	}
+
+#define GRP_MUX(a, m, p)		\
+	{ .name = a, .mux = XWAY_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
+
+#define FUNC_MUX(f, m)		\
+	{ .func = f, .mux = XWAY_MUX_##m, }
+
+enum xway_mux {
+	XWAY_MUX_GPIO = 0,
+	XWAY_MUX_SPI,
+	XWAY_MUX_ASC,
+	XWAY_MUX_PCI,
+	XWAY_MUX_CGU,
+	XWAY_MUX_EBU,
+	XWAY_MUX_JTAG,
+	XWAY_MUX_EXIN,
+	XWAY_MUX_TDM,
+	XWAY_MUX_STP,
+	XWAY_MUX_SIN,
+	XWAY_MUX_GPT,
+	XWAY_MUX_NMI,
+	XWAY_MUX_NONE = 0xffff,
+};
+
+static const struct ltq_mfp_pin xway_mfp[] = {
+	/*       pin    f0	f1	f2	f3   */
+	MFP_XWAY(GPIO0, GPIO,	EXIN,	NONE,	TDM),
+	MFP_XWAY(GPIO1, GPIO,	EXIN,	NONE,	NONE),
+	MFP_XWAY(GPIO2, GPIO,	CGU,	EXIN,	NONE),
+	MFP_XWAY(GPIO3, GPIO,	CGU,	NONE,	PCI),
+	MFP_XWAY(GPIO4, GPIO,	STP,	NONE,	ASC),
+	MFP_XWAY(GPIO5, GPIO,	STP,	NONE,	NONE),
+	MFP_XWAY(GPIO6, GPIO,	STP,	GPT,	ASC),
+	MFP_XWAY(GPIO7, GPIO,	CGU,	PCI,	NONE),
+	MFP_XWAY(GPIO8, GPIO,	CGU,	NMI,	NONE),
+	MFP_XWAY(GPIO9, GPIO,	ASC,	SPI,	NONE),
+	MFP_XWAY(GPIO10, GPIO,	ASC,	SPI,	NONE),
+	MFP_XWAY(GPIO11, GPIO,	ASC,	PCI,	SPI),
+	MFP_XWAY(GPIO12, GPIO,	ASC,	NONE,	NONE),
+	MFP_XWAY(GPIO13, GPIO,	EBU,	SPI,	NONE),
+	MFP_XWAY(GPIO14, GPIO,	CGU,	PCI,	NONE),
+	MFP_XWAY(GPIO15, GPIO,	SPI,	JTAG,	NONE),
+	MFP_XWAY(GPIO16, GPIO,	SPI,	NONE,	JTAG),
+	MFP_XWAY(GPIO17, GPIO,	SPI,	NONE,	JTAG),
+	MFP_XWAY(GPIO18, GPIO,	SPI,	NONE,	JTAG),
+	MFP_XWAY(GPIO19, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO20, GPIO,	JTAG,	NONE,	NONE),
+	MFP_XWAY(GPIO21, GPIO,	PCI,	EBU,	GPT),
+	MFP_XWAY(GPIO22, GPIO,	SPI,	NONE,	NONE),
+	MFP_XWAY(GPIO23, GPIO,	EBU,	PCI,	STP),
+	MFP_XWAY(GPIO24, GPIO,	EBU,	TDM,	PCI),
+	MFP_XWAY(GPIO25, GPIO,	TDM,	NONE,	ASC),
+	MFP_XWAY(GPIO26, GPIO,	EBU,	NONE,	TDM),
+	MFP_XWAY(GPIO27, GPIO,	TDM,	NONE,	ASC),
+	MFP_XWAY(GPIO28, GPIO,	GPT,	NONE,	NONE),
+	MFP_XWAY(GPIO29, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO30, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO31, GPIO,	EBU,	PCI,	NONE),
+	MFP_XWAY(GPIO32, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO33, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO34, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO35, GPIO,	NONE,	NONE,	EBU),
+	MFP_XWAY(GPIO36, GPIO,	SIN,	NONE,	EBU),
+	MFP_XWAY(GPIO37, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO38, GPIO,	PCI,	NONE,	NONE),
+	MFP_XWAY(GPIO39, GPIO,	EXIN,	NONE,	NONE),
+	MFP_XWAY(GPIO40, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO41, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO42, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO43, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO44, GPIO,	NONE,	NONE,	SIN),
+	MFP_XWAY(GPIO45, GPIO,	NONE,	NONE,	SIN),
+	MFP_XWAY(GPIO46, GPIO,	NONE,	NONE,	EXIN),
+	MFP_XWAY(GPIO47, GPIO,	NONE,	NONE,	SIN),
+	MFP_XWAY(GPIO48, GPIO,	EBU,	NONE,	NONE),
+	MFP_XWAY(GPIO49, GPIO,	EBU,	NONE,	NONE),
+	MFP_XWAY(GPIO50, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO51, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO52, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO53, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO54, GPIO,	NONE,	NONE,	NONE),
+	MFP_XWAY(GPIO55, GPIO,	NONE,	NONE,	NONE),
+};
+
+static const unsigned pins_jtag[] = {GPIO15, GPIO16, GPIO17, GPIO19, GPIO35};
+static const unsigned pins_asc0[] = {GPIO11, GPIO12};
+static const unsigned pins_asc0_cts_rts[] = {GPIO9, GPIO10};
+static const unsigned pins_stp[] = {GPIO4, GPIO5, GPIO6};
+static const unsigned pins_nmi[] = {GPIO8};
+
+static const unsigned pins_ebu_a24[] = {GPIO13};
+static const unsigned pins_ebu_clk[] = {GPIO21};
+static const unsigned pins_ebu_cs1[] = {GPIO23};
+static const unsigned pins_ebu_a23[] = {GPIO24};
+static const unsigned pins_ebu_wait[] = {GPIO26};
+static const unsigned pins_ebu_a25[] = {GPIO31};
+static const unsigned pins_ebu_rdy[] = {GPIO48};
+static const unsigned pins_ebu_rd[] = {GPIO49};
+
+static const unsigned pins_nand_ale[] = {GPIO13};
+static const unsigned pins_nand_cs1[] = {GPIO23};
+static const unsigned pins_nand_cle[] = {GPIO24};
+static const unsigned pins_nand_rdy[] = {GPIO48};
+static const unsigned pins_nand_rd[] = {GPIO49};
+
+static const unsigned pins_exin0[] = {GPIO0};
+static const unsigned pins_exin1[] = {GPIO1};
+static const unsigned pins_exin2[] = {GPIO2};
+static const unsigned pins_exin3[] = {GPIO39};
+static const unsigned pins_exin4[] = {GPIO46};
+
+static const unsigned pins_spi[] = {GPIO16, GPIO17, GPIO18};
+static const unsigned pins_spi_cs1[] = {GPIO15};
+static const unsigned pins_spi_cs2[] = {GPIO21};
+static const unsigned pins_spi_cs3[] = {GPIO13};
+static const unsigned pins_spi_cs4[] = {GPIO10};
+static const unsigned pins_spi_cs5[] = {GPIO9};
+static const unsigned pins_spi_cs6[] = {GPIO11};
+
+static const unsigned pins_gpt1[] = {GPIO28};
+static const unsigned pins_gpt2[] = {GPIO21};
+static const unsigned pins_gpt3[] = {GPIO6};
+
+static const unsigned pins_clkout0[] = {GPIO8};
+static const unsigned pins_clkout1[] = {GPIO7};
+static const unsigned pins_clkout2[] = {GPIO3};
+static const unsigned pins_clkout3[] = {GPIO2};
+
+static const unsigned pins_pci_gnt1[] = {GPIO30};
+static const unsigned pins_pci_gnt2[] = {GPIO23};
+static const unsigned pins_pci_gnt3[] = {GPIO19};
+static const unsigned pins_pci_gnt4[] = {GPIO38};
+static const unsigned pins_pci_req1[] = {GPIO29};
+static const unsigned pins_pci_req2[] = {GPIO31};
+static const unsigned pins_pci_req3[] = {GPIO3};
+static const unsigned pins_pci_req4[] = {GPIO37};
+
+static const struct ltq_pin_group xway_grps[] = {
+	GRP_MUX("exin0", EXIN, pins_exin0),
+	GRP_MUX("exin1", EXIN, pins_exin1),
+	GRP_MUX("exin2", EXIN, pins_exin2),
+	GRP_MUX("jtag", JTAG, pins_jtag),
+	GRP_MUX("ebu a23", EBU, pins_ebu_a23),
+	GRP_MUX("ebu a24", EBU, pins_ebu_a24),
+	GRP_MUX("ebu a25", EBU, pins_ebu_a25),
+	GRP_MUX("ebu clk", EBU, pins_ebu_clk),
+	GRP_MUX("ebu cs1", EBU, pins_ebu_cs1),
+	GRP_MUX("ebu wait", EBU, pins_ebu_wait),
+	GRP_MUX("nand ale", EBU, pins_nand_ale),
+	GRP_MUX("nand cs1", EBU, pins_nand_cs1),
+	GRP_MUX("nand cle", EBU, pins_nand_cle),
+	GRP_MUX("spi", SPI, pins_spi),
+	GRP_MUX("spi_cs1", SPI, pins_spi_cs1),
+	GRP_MUX("spi_cs2", SPI, pins_spi_cs2),
+	GRP_MUX("spi_cs3", SPI, pins_spi_cs3),
+	GRP_MUX("spi_cs4", SPI, pins_spi_cs4),
+	GRP_MUX("spi_cs5", SPI, pins_spi_cs5),
+	GRP_MUX("spi_cs6", SPI, pins_spi_cs6),
+	GRP_MUX("asc0", ASC, pins_asc0),
+	GRP_MUX("asc0 cts rts", ASC, pins_asc0_cts_rts),
+	GRP_MUX("stp", STP, pins_stp),
+	GRP_MUX("nmi", NMI, pins_nmi),
+	GRP_MUX("gpt1", GPT, pins_gpt1),
+	GRP_MUX("gpt2", GPT, pins_gpt2),
+	GRP_MUX("gpt3", GPT, pins_gpt3),
+	GRP_MUX("clkout0", CGU, pins_clkout0),
+	GRP_MUX("clkout1", CGU, pins_clkout1),
+	GRP_MUX("clkout2", CGU, pins_clkout2),
+	GRP_MUX("clkout3", CGU, pins_clkout3),
+	GRP_MUX("gnt1", PCI, pins_pci_gnt1),
+	GRP_MUX("gnt2", PCI, pins_pci_gnt2),
+	GRP_MUX("gnt3", PCI, pins_pci_gnt3),
+	GRP_MUX("req1", PCI, pins_pci_req1),
+	GRP_MUX("req2", PCI, pins_pci_req2),
+	GRP_MUX("req3", PCI, pins_pci_req3),
+/* xrx only */
+	GRP_MUX("nand rdy", EBU, pins_nand_rdy),
+	GRP_MUX("nand rd", EBU, pins_nand_rd),
+	GRP_MUX("exin3", EXIN, pins_exin3),
+	GRP_MUX("exin4", EXIN, pins_exin4),
+	GRP_MUX("gnt4", PCI, pins_pci_gnt4),
+	GRP_MUX("req4", PCI, pins_pci_gnt4),
+};
+
+static const char * const xway_pci_grps[] = {"gnt1", "gnt2",
+						"gnt3", "req1",
+						"req2", "req3"};
+static const char * const xway_spi_grps[] = {"spi", "spi_cs1",
+						"spi_cs2", "spi_cs3",
+						"spi_cs4", "spi_cs5",
+						"spi_cs6"};
+static const char * const xway_cgu_grps[] = {"clkout0", "clkout1",
+						"clkout2", "clkout3"};
+static const char * const xway_ebu_grps[] = {"ebu a23", "ebu a24",
+						"ebu a25", "ebu cs1",
+						"ebu wait", "ebu clk",
+						"nand ale", "nand cs1",
+						"nand cle"};
+static const char * const xway_exin_grps[] = {"exin0", "exin1", "exin2"};
+static const char * const xway_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
+static const char * const xway_asc_grps[] = {"asc0", "asc0 cts rts"};
+static const char * const xway_jtag_grps[] = {"jtag"};
+static const char * const xway_stp_grps[] = {"stp"};
+static const char * const xway_nmi_grps[] = {"nmi"};
+
+/* ar9/vr9/gr9 */
+static const char * const xrx_ebu_grps[] = {"ebu a23", "ebu a24",
+						"ebu a25", "ebu cs1",
+						"ebu wait", "ebu clk",
+						"nand ale", "nand cs1",
+						"nand cle", "nand rdy",
+						"nand rd"};
+static const char * const xrx_exin_grps[] = {"exin0", "exin1", "exin2",
+						"exin3", "exin4"};
+static const char * const xrx_pci_grps[] = {"gnt1", "gnt2",
+						"gnt3", "gnt4",
+						"req1", "req2",
+						"req3", "req4"};
+
+static const struct ltq_pmx_func danube_funcs[] = {
+	{"spi",		ARRAY_AND_SIZE(xway_spi_grps)},
+	{"asc",		ARRAY_AND_SIZE(xway_asc_grps)},
+	{"cgu",		ARRAY_AND_SIZE(xway_cgu_grps)},
+	{"jtag",	ARRAY_AND_SIZE(xway_jtag_grps)},
+	{"exin",	ARRAY_AND_SIZE(xway_exin_grps)},
+	{"stp",		ARRAY_AND_SIZE(xway_stp_grps)},
+	{"gpt",		ARRAY_AND_SIZE(xway_gpt_grps)},
+	{"nmi",		ARRAY_AND_SIZE(xway_nmi_grps)},
+	{"pci",		ARRAY_AND_SIZE(xway_pci_grps)},
+	{"ebu",		ARRAY_AND_SIZE(xway_ebu_grps)},
+};
+
+static const struct ltq_pmx_func xrx_funcs[] = {
+	{"spi",		ARRAY_AND_SIZE(xway_spi_grps)},
+	{"asc",		ARRAY_AND_SIZE(xway_asc_grps)},
+	{"cgu",		ARRAY_AND_SIZE(xway_cgu_grps)},
+	{"jtag",	ARRAY_AND_SIZE(xway_jtag_grps)},
+	{"exin",	ARRAY_AND_SIZE(xrx_exin_grps)},
+	{"stp",		ARRAY_AND_SIZE(xway_stp_grps)},
+	{"gpt",		ARRAY_AND_SIZE(xway_gpt_grps)},
+	{"nmi",		ARRAY_AND_SIZE(xway_nmi_grps)},
+	{"pci",		ARRAY_AND_SIZE(xrx_pci_grps)},
+	{"ebu",		ARRAY_AND_SIZE(xrx_ebu_grps)},
+};
+
+
+
+
+
+
+/* ---------  pinconf related code --------- */
+static int xway_pinconf_group_get(struct pinctrl_dev *pctldev,
+				unsigned group,
+				unsigned long *config)
+{
+	return -ENOTSUPP;
+}
+
+static int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
+				unsigned group,
+				unsigned long config)
+{
+	return -ENOTSUPP;
+}
+
+static int xway_pinconf_get(struct pinctrl_dev *pctldev,
+				unsigned pin,
+				unsigned long *config)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+	enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(*config);
+	int port = PORT(pin);
+	u32 reg;
+
+	switch (param) {
+	case LTQ_PINCONF_PARAM_OPEN_DRAIN:
+		if (port == 3)
+			reg = GPIO3_OD;
+		else
+			reg = GPIO_OD(port);
+		*config = LTQ_PINCONF_PACK(param,
+			!!gpio_getbit(info->membase[0], reg, PORT_PIN(port)));
+		break;
+
+	case LTQ_PINCONF_PARAM_PULL:
+		if (port == 3)
+			reg = GPIO3_PUDEN;
+		else
+			reg = GPIO_PUDEN(port);
+		if (!gpio_getbit(info->membase[0], reg, PORT_PIN(port))) {
+			*config = LTQ_PINCONF_PACK(param, 0);
+			break;
+		}
+
+		if (port == 3)
+			reg = GPIO3_PUDSEL;
+		else
+			reg = GPIO_PUDSEL(port);
+		if (!gpio_getbit(info->membase[0], reg, PORT_PIN(port)))
+			*config = LTQ_PINCONF_PACK(param, 2);
+		else
+			*config = LTQ_PINCONF_PACK(param, 1);
+		break;
+
+	default:
+		pr_err("%s: Invalid config param %04x\n",
+					pinctrl_dev_get_name(pctldev), param);
+		return -ENOTSUPP;
+	}
+	return 0;
+}
+
+static int xway_pinconf_set(struct pinctrl_dev *pctldev,
+				unsigned pin,
+				unsigned long config)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+	enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(config);
+	int arg = LTQ_PINCONF_UNPACK_ARG(config);
+	int port = PORT(pin);
+	u32 reg;
+
+	switch (param) {
+	case LTQ_PINCONF_PARAM_OPEN_DRAIN:
+		if (port == 3)
+			reg = GPIO3_OD;
+		else
+			reg = GPIO_OD(port);
+		gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+		break;
+
+	case LTQ_PINCONF_PARAM_PULL:
+		if (port == 3)
+			reg = GPIO3_PUDEN;
+		else
+			reg = GPIO_PUDEN(port);
+		if (arg == 0) {
+			gpio_clearbit(info->membase[0], reg, PORT_PIN(port));
+			break;
+		}
+		gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+
+		if (port == 3)
+			reg = GPIO3_PUDSEL;
+		else
+			reg = GPIO_PUDSEL(port);
+		if (arg == 1)
+			gpio_clearbit(info->membase[0], reg, PORT_PIN(port));
+		else if (arg == 2)
+			gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+		else
+			pr_err("%s: Invalid pull value %d\n",
+				pinctrl_dev_get_name(pctldev), arg);
+		break;
+
+	default:
+		pr_err("%s: Invalid config param %04x\n",
+					pinctrl_dev_get_name(pctldev), param);
+		return -ENOTSUPP;
+	}
+	return 0;
+}
+
+static void xway_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s, unsigned offset)
+{
+}
+
+static void xway_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s, unsigned selector)
+{
+}
+
+struct pinconf_ops xway_pinconf_ops = {
+	.pin_config_get			= xway_pinconf_get,
+	.pin_config_set			= xway_pinconf_set,
+	.pin_config_group_get		= xway_pinconf_group_get,
+	.pin_config_group_set		= xway_pinconf_group_set,
+	.pin_config_dbg_show		= xway_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= xway_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc xway_pctrl_desc = {
+	.owner		= THIS_MODULE,
+	.confops	= &xway_pinconf_ops,
+};
+
+static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
+				int pin, int mux)
+{
+	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+	int port = PORT(pin);
+
+	if (mux & 0x1)
+		gpio_setbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
+	else
+		gpio_clearbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
+
+	if ((port == 3) && (mux & 0x2))
+		gpio_setbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
+	else if (mux & 0x2)
+		gpio_setbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
+	else if (port == 3)
+		gpio_clearbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
+	else
+		gpio_clearbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
+
+	return 0;
+}
+
+static const struct ltq_cfg_param xway_cfg_params[] = {
+	{"lantiq,pull",		LTQ_PINCONF_PARAM_PULL},
+	{"lantiq,open-drain",	LTQ_PINCONF_PARAM_OPEN_DRAIN},
+};
+
+static struct ltq_pinmux_info xway_info = {
+	.mfp		= xway_mfp,
+	.desc		= &xway_pctrl_desc,
+	.apply_mux	= xway_mux_apply,
+	.params		= xway_cfg_params,
+	.num_params	= ARRAY_SIZE(xway_cfg_params),
+};
+
+
+
+
+/* ---------  gpio_chip related code --------- */
+
+int gpio_to_irq(unsigned int gpio)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned int gpio)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL(irq_to_gpio);
+
+static inline int xway_gpio_pin_count(void)
+{
+	if (of_machine_is_compatible("lantiq,ar9") ||
+			of_machine_is_compatible("lantiq,gr9") ||
+			of_machine_is_compatible("lantiq,vr9"))
+		return 56;
+	return 32;
+}
+
+static void xway_gpio_set(struct gpio_chip *chip, unsigned int pin, int val)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	if (val)
+		gpio_setbit(info->membase[0], GPIO_OUT(pin), PORT_PIN(pin));
+	else
+		gpio_clearbit(info->membase[0], GPIO_OUT(pin), PORT_PIN(pin));
+}
+
+static int xway_gpio_get(struct gpio_chip *chip, unsigned int pin)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	return gpio_getbit(info->membase[0], GPIO_IN(pin), PORT_PIN(pin));
+}
+
+static int xway_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	gpio_clearbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+
+	return 0;
+}
+
+static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
+{
+	struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+
+	gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+	xway_gpio_set(chip, pin, val);
+
+	return 0;
+}
+
+static int xway_gpio_req(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static struct gpio_chip xway_chip = {
+	.label = "gpio-xway",
+	.direction_input = xway_gpio_dir_in,
+	.direction_output = xway_gpio_dir_out,
+	.get = xway_gpio_get,
+	.set = xway_gpio_set,
+	.request = xway_gpio_req,
+	.free = xway_gpio_free,
+	.base = 0,
+};
+
+
+
+
+/* --------- register the pinctrl layer --------- */
+
+static struct pinctrl_gpio_range xway_gpio_range = {
+	.name	= "XWAY GPIO",
+	.id	= 0,
+	.base	= 0,
+	.gc	= &xway_chip,
+};
+
+static int __devinit pinmux_xway_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret, i;
+
+	/* get and remap our register range */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get resource\n");
+		return -ENOENT;
+	}
+	xway_info.membase[0] = devm_request_and_ioremap(&pdev->dev, res);
+	if (!xway_info.membase[0]) {
+		dev_err(&pdev->dev, "Failed to remap resource\n");
+		return -ENOMEM;
+	}
+
+	/* find out how many pads we have */
+	xway_chip.ngpio = xway_gpio_pin_count();
+
+	/* load our pad descriptors */
+	xway_info.pads = devm_kzalloc(&pdev->dev,
+			sizeof(struct pinctrl_pin_desc) * xway_chip.ngpio,
+			GFP_KERNEL);
+	if (!xway_info.pads) {
+		dev_err(&pdev->dev, "Failed to allocate pads\n");
+		return -ENOMEM;
+	}
+	for (i = 0; i < xway_chip.ngpio; i++) {
+		/* strlen("ioXY") + 1 = 5 */
+		char *name = devm_kzalloc(&pdev->dev, 5, GFP_KERNEL);
+
+		if (!name) {
+			dev_err(&pdev->dev, "Failed to allocate pad name\n");
+			return -ENOMEM;
+		}
+		snprintf(name, 5, "io%d", i);
+		xway_info.pads[i].number = GPIO0 + i;
+		xway_info.pads[i].name = name;
+	}
+	xway_pctrl_desc.pins = xway_info.pads;
+
+	/* load the gpio chip */
+	xway_chip.dev = &pdev->dev;
+	of_gpiochip_add(&xway_chip);
+	ret = gpiochip_add(&xway_chip);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register gpio chip\n");
+		return ret;
+	}
+
+	/* setup the data needed by pinctrl */
+	xway_pctrl_desc.name	= dev_name(&pdev->dev);
+	xway_pctrl_desc.npins	= xway_chip.ngpio;
+
+	xway_info.num_gpio	= xway_chip.ngpio;
+	xway_info.num_mfp	= xway_chip.ngpio;
+	xway_info.grps		= xway_grps;
+	xway_info.num_grps	= ARRAY_SIZE(xway_grps);
+	if (xway_gpio_pin_count() == 56) {
+		xway_info.funcs		= xrx_funcs;
+		xway_info.num_funcs	= ARRAY_SIZE(xrx_funcs);
+	} else {
+		xway_info.funcs		= danube_funcs;
+		xway_info.num_funcs	= ARRAY_SIZE(danube_funcs);
+	}
+
+	/* register with the generic lantiq layer */
+	ret = ltq_pinctrl_register(pdev, &xway_info);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register pinctrl driver\n");
+		return ret;
+	}
+
+	/* finish with registering the gpio range in pinctrl */
+	xway_gpio_range.npins = xway_chip.ngpio;
+	pinctrl_add_gpio_range(xway_info.pctrl, &xway_gpio_range);
+	dev_info(&pdev->dev, "Init done\n");
+	return 0;
+}
+
+static const struct of_device_id xway_match[] = {
+	{ .compatible = "lantiq,pinctrl-xway" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xway_match);
+
+static struct platform_driver pinmux_xway_driver = {
+	.probe	= pinmux_xway_probe,
+	.driver = {
+		.name	= "pinctrl-xway",
+		.owner	= THIS_MODULE,
+		.of_match_table = xway_match,
+	},
+};
+
+static int __init pinmux_xway_init(void)
+{
+	return platform_driver_register(&pinmux_xway_driver);
+}
+
+core_initcall_sync(pinmux_xway_init);
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 05/14] MIPS: lantiq: implement support for clkdev api
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
       [not found] ` <1336133919-26525-1-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 06/14] MIPS: lantiq: convert dma to platform driver John Crispin
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin

This code unifies all clock generation and gating code into one file.
All drivers will now be able to request their clocks via their device.
This patch also adds support for the clockout feature, which allows
clock generation on external pins.

Support for COMMON_CLK will be provided in the next series.

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/Kconfig                                  |    3 +-
 arch/mips/include/asm/mach-lantiq/lantiq.h         |   27 +-
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    5 +
 arch/mips/lantiq/clk.c                             |  140 ++++----
 arch/mips/lantiq/clk.h                             |   67 ++++-
 arch/mips/lantiq/xway/Makefile                     |    5 +-
 arch/mips/lantiq/xway/clk-ase.c                    |   48 ---
 arch/mips/lantiq/xway/clk-xway.c                   |  223 ------------
 arch/mips/lantiq/xway/clk.c                        |  151 ++++++++
 arch/mips/lantiq/xway/ebu.c                        |   48 ---
 arch/mips/lantiq/xway/pmu.c                        |   69 ----
 arch/mips/lantiq/xway/sysctrl.c                    |  364 ++++++++++++++++++++
 12 files changed, 671 insertions(+), 479 deletions(-)
 delete mode 100644 arch/mips/lantiq/xway/clk-ase.c
 delete mode 100644 arch/mips/lantiq/xway/clk-xway.c
 create mode 100644 arch/mips/lantiq/xway/clk.c
 delete mode 100644 arch/mips/lantiq/xway/ebu.c
 delete mode 100644 arch/mips/lantiq/xway/pmu.c
 create mode 100644 arch/mips/lantiq/xway/sysctrl.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 00a0482..8ba19da 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -229,7 +229,8 @@ config LANTIQ
 	select ARCH_REQUIRE_GPIOLIB
 	select SWAP_IO_SPACE
 	select BOOT_RAW
-	select HAVE_CLK
+	select HAVE_MACH_CLKDEV
+	select CLKDEV_LOOKUP
 	select USE_OF
 
 config LASAT
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index 7a90190..c955e8d 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -9,6 +9,8 @@
 #define _LANTIQ_H__
 
 #include <linux/irq.h>
+#include <linux/device.h>
+#include <linux/clk.h>
 
 /* generic reg access functions */
 #define ltq_r32(reg)		__raw_readl(reg)
@@ -21,26 +23,13 @@
 /* register access macros for EBU and CGU */
 #define ltq_ebu_w32(x, y)	ltq_w32((x), ltq_ebu_membase + (y))
 #define ltq_ebu_r32(x)		ltq_r32(ltq_ebu_membase + (x))
-#define ltq_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
-#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
-
+#define ltq_ebu_w32_mask(x, y, z) \
+	ltq_w32_mask(x, y, ltq_ebu_membase + (z))
 extern __iomem void *ltq_ebu_membase;
-extern __iomem void *ltq_cgu_membase;
 
 extern unsigned int ltq_get_cpu_ver(void);
 extern unsigned int ltq_get_soc_type(void);
 
-/* clock speeds */
-#define CLOCK_60M	60000000
-#define CLOCK_83M	83333333
-#define CLOCK_111M	111111111
-#define CLOCK_133M	133333333
-#define CLOCK_167M	166666667
-#define CLOCK_200M	200000000
-#define CLOCK_266M	266666666
-#define CLOCK_333M	333333333
-#define CLOCK_400M	400000000
-
 /* spinlock all ebu i/o */
 extern spinlock_t ebu_lock;
 
@@ -48,6 +37,14 @@ extern spinlock_t ebu_lock;
 extern void ltq_disable_irq(struct irq_data *data);
 extern void ltq_mask_and_ack_irq(struct irq_data *data);
 extern void ltq_enable_irq(struct irq_data *data);
+
+/* clock handling */
+extern int clk_activate(struct clk *clk);
+extern void clk_deactivate(struct clk *clk);
+extern struct clk *clk_get_cpu(void);
+extern struct clk *clk_get_fpi(void);
+#define clk_get_io	clk_get_fpi
+
 /* find out what bootsource we have */
 extern unsigned char ltq_boot_select(void);
 /* find out what caused the last cpu reset */
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 150c7be..b5a2acf 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -59,6 +59,11 @@
 #define BS_NAND			0x6
 #define BS_RMII0		0x7
 
+/* helpers used to access the cgu */
+#define ltq_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
+#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
+extern __iomem void *ltq_cgu_membase;
+
 /*
  * during early_printk no ioremap is possible
  * lets use KSEG1 instead
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 412814f..f41fc52 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/list.h>
 
@@ -22,46 +23,28 @@
 #include <lantiq_soc.h>
 
 #include "clk.h"
+#include "prom.h"
 
-struct clk {
-	const char *name;
-	unsigned long rate;
-	unsigned long (*get_rate) (void);
-};
+/* lantiq socs have 3 static clocks */
+static struct clk cpu_clk_generic[2];
 
-static struct clk *cpu_clk;
-static int cpu_clk_cnt;
+void clkdev_add_static(unsigned long cpu, unsigned long fpi)
+{
+	cpu_clk_generic[0].rate = cpu;
+	cpu_clk_generic[1].rate = fpi;
+}
 
-/* lantiq socs have 3 static clocks */
-static struct clk cpu_clk_generic[] = {
-	{
-		.name = "cpu",
-		.get_rate = ltq_get_cpu_hz,
-	}, {
-		.name = "fpi",
-		.get_rate = ltq_get_fpi_hz,
-	}, {
-		.name = "io",
-		.get_rate = ltq_get_io_region_clock,
-	},
-};
-
-static struct resource ltq_cgu_resource = {
-	.name	= "cgu",
-	.start	= LTQ_CGU_BASE_ADDR,
-	.end	= LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-/* remapped clock register range */
-void __iomem *ltq_cgu_membase;
-
-void clk_init(void)
+struct clk *clk_get_cpu(void)
 {
-	cpu_clk = cpu_clk_generic;
-	cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
+	return &cpu_clk_generic[0];
 }
 
+struct clk *clk_get_fpi(void)
+{
+	return &cpu_clk_generic[1];
+}
+EXPORT_SYMBOL_GPL(clk_get_fpi);
+
 static inline int clk_good(struct clk *clk)
 {
 	return clk && !IS_ERR(clk);
@@ -82,38 +65,71 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
-struct clk *clk_get(struct device *dev, const char *id)
+int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	int i;
-
-	for (i = 0; i < cpu_clk_cnt; i++)
-		if (!strcmp(id, cpu_clk[i].name))
-			return &cpu_clk[i];
-	BUG();
-	return ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-	/* not used */
+	if (unlikely(!clk_good(clk)))
+		return 0;
+	if (clk->rates && *clk->rates) {
+		unsigned long *r = clk->rates;
+
+		while (*r && (*r != rate))
+			r++;
+		if (!*r) {
+			pr_err("clk %s.%s: trying to set invalid rate %ld\n",
+				clk->cl.dev_id, clk->cl.con_id, rate);
+			return -1;
+		}
+	}
+	clk->rate = rate;
+	return 0;
 }
-EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_set_rate);
 
 int clk_enable(struct clk *clk)
 {
-	/* not used */
-	return 0;
+	if (unlikely(!clk_good(clk)))
+		return -1;
+
+	if (clk->enable)
+		return clk->enable(clk);
+
+	return -1;
 }
 EXPORT_SYMBOL(clk_enable);
 
 void clk_disable(struct clk *clk)
 {
-	/* not used */
+	if (unlikely(!clk_good(clk)))
+		return;
+
+	if (clk->disable)
+		clk->disable(clk);
 }
 EXPORT_SYMBOL(clk_disable);
 
-static inline u32 ltq_get_counter_resolution(void)
+int clk_activate(struct clk *clk)
+{
+	if (unlikely(!clk_good(clk)))
+		return -1;
+
+	if (clk->activate)
+		return clk->activate(clk);
+
+	return -1;
+}
+EXPORT_SYMBOL(clk_activate);
+
+void clk_deactivate(struct clk *clk)
+{
+	if (unlikely(!clk_good(clk)))
+		return;
+
+	if (clk->deactivate)
+		clk->deactivate(clk);
+}
+EXPORT_SYMBOL(clk_deactivate);
+
+static inline u32 get_counter_resolution(void)
 {
 	u32 res;
 
@@ -133,21 +149,11 @@ void __init plat_time_init(void)
 {
 	struct clk *clk;
 
-	if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
-		panic("Failed to insert cgu memory");
+	ltq_soc_init();
 
-	if (request_mem_region(ltq_cgu_resource.start,
-			resource_size(&ltq_cgu_resource), "cgu") < 0)
-		panic("Failed to request cgu memory");
-
-	ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
-				resource_size(&ltq_cgu_resource));
-	if (!ltq_cgu_membase) {
-		pr_err("Failed to remap cgu memory\n");
-		unreachable();
-	}
-	clk = clk_get(0, "cpu");
-	mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
+	clk = clk_get_cpu();
+	mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
 	write_c0_compare(read_c0_count());
+	pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
 	clk_put(clk);
 }
diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
index 3328925..daed627 100644
--- a/arch/mips/lantiq/clk.h
+++ b/arch/mips/lantiq/clk.h
@@ -9,10 +9,69 @@
 #ifndef _LTQ_CLK_H__
 #define _LTQ_CLK_H__
 
-extern void clk_init(void);
+#include <linux/clkdev.h>
 
-extern unsigned long ltq_get_cpu_hz(void);
-extern unsigned long ltq_get_fpi_hz(void);
-extern unsigned long ltq_get_io_region_clock(void);
+/* clock speeds */
+#define CLOCK_33M	33333333
+#define CLOCK_60M	60000000
+#define CLOCK_62_5M	62500000
+#define CLOCK_83M	83333333
+#define CLOCK_83_5M	83500000
+#define CLOCK_98_304M	98304000
+#define CLOCK_100M	100000000
+#define CLOCK_111M	111111111
+#define CLOCK_125M	125000000
+#define CLOCK_133M	133333333
+#define CLOCK_150M	150000000
+#define CLOCK_166M	166666666
+#define CLOCK_167M	166666667
+#define CLOCK_196_608M	196608000
+#define CLOCK_200M	200000000
+#define CLOCK_250M	250000000
+#define CLOCK_266M	266666666
+#define CLOCK_300M	300000000
+#define CLOCK_333M	333333333
+#define CLOCK_393M	393215332
+#define CLOCK_400M	400000000
+#define CLOCK_500M	500000000
+#define CLOCK_600M	600000000
+
+/* clock out speeds */
+#define CLOCK_32_768K	32768
+#define CLOCK_1_536M	1536000
+#define CLOCK_2_5M	2500000
+#define CLOCK_12M	12000000
+#define CLOCK_24M	24000000
+#define CLOCK_25M	25000000
+#define CLOCK_30M	30000000
+#define CLOCK_40M	40000000
+#define CLOCK_48M	48000000
+#define CLOCK_50M	50000000
+#define CLOCK_60M	60000000
+
+struct clk {
+	struct clk_lookup cl;
+	unsigned long rate;
+	unsigned long *rates;
+	unsigned int module;
+	unsigned int bits;
+	unsigned long (*get_rate) (void);
+	int (*enable) (struct clk *clk);
+	void (*disable) (struct clk *clk);
+	int (*activate) (struct clk *clk);
+	void (*deactivate) (struct clk *clk);
+	void (*reboot) (struct clk *clk);
+};
+
+extern void clkdev_add_static(unsigned long cpu, unsigned long fpi);
+
+extern unsigned long ltq_danube_cpu_hz(void);
+extern unsigned long ltq_danube_fpi_hz(void);
+
+extern unsigned long ltq_ar9_cpu_hz(void);
+extern unsigned long ltq_ar9_fpi_hz(void);
+
+extern unsigned long ltq_vr9_cpu_hz(void);
+extern unsigned long ltq_vr9_fpi_hz(void);
 
 #endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 323b574..6e930b70 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1 @@
-obj-y := prom.o pmu.o ebu.o reset.o gpio_stp.o gpio_ebu.o dma.o
-
-obj-$(CONFIG_SOC_XWAY) += clk-xway.o
-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o
+obj-y := prom.o sysctrl.o clk.o reset.o dma.o gpio_stp.o gpio_ebu.o
diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
deleted file mode 100644
index 6522583..0000000
--- a/arch/mips/lantiq/xway/clk-ase.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  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) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/time.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include <lantiq_soc.h>
-
-/* cgu registers */
-#define LTQ_CGU_SYS	0x0010
-
-unsigned int ltq_get_io_region_clock(void)
-{
-	return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_io_region_clock);
-
-unsigned int ltq_get_fpi_bus_clock(int fpi)
-{
-	return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
-
-unsigned int ltq_get_cpu_hz(void)
-{
-	if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
-		return CLOCK_266M;
-	else
-		return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_cpu_hz);
-
-unsigned int ltq_get_fpi_hz(void)
-{
-	return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c
deleted file mode 100644
index 696b1a3..0000000
--- a/arch/mips/lantiq/xway/clk-xway.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/time.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include <lantiq_soc.h>
-
-static unsigned int ltq_ram_clocks[] = {
-	CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
-#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
-
-#define BASIC_FREQUENCY_1	35328000
-#define BASIC_FREQUENCY_2	36000000
-#define BASIS_REQUENCY_USB	12000000
-
-#define GET_BITS(x, msb, lsb) \
-	(((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
-
-#define LTQ_CGU_PLL0_CFG	0x0004
-#define LTQ_CGU_PLL1_CFG	0x0008
-#define LTQ_CGU_PLL2_CFG	0x000C
-#define LTQ_CGU_SYS		0x0010
-#define LTQ_CGU_UPDATE		0x0014
-#define LTQ_CGU_IF_CLK		0x0018
-#define LTQ_CGU_OSC_CON		0x001C
-#define LTQ_CGU_SMD		0x0020
-#define LTQ_CGU_CT1SR		0x0028
-#define LTQ_CGU_CT2SR		0x002C
-#define LTQ_CGU_PCMCR		0x0030
-#define LTQ_CGU_PCI_CR		0x0034
-#define LTQ_CGU_PD_PC		0x0038
-#define LTQ_CGU_FMR		0x003C
-
-#define CGU_PLL0_PHASE_DIVIDER_ENABLE	\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
-#define CGU_PLL0_BYPASS			\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
-#define CGU_PLL0_CFG_DSMSEL		\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
-#define CGU_PLL0_CFG_FRAC_EN		\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
-#define CGU_PLL1_SRC			\
-	(ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
-#define CGU_PLL2_PHASE_DIVIDER_ENABLE	\
-	(ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
-#define CGU_SYS_FPI_SEL			(1 << 6)
-#define CGU_SYS_DDR_SEL			0x3
-#define CGU_PLL0_SRC			(1 << 29)
-
-#define CGU_PLL0_CFG_PLLK	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
-#define CGU_PLL0_CFG_PLLN	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
-#define CGU_PLL0_CFG_PLLM	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
-#define CGU_PLL2_SRC		GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
-#define CGU_PLL2_CFG_INPUT_DIV	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
-
-static unsigned int ltq_get_pll0_fdiv(void);
-
-static inline unsigned int get_input_clock(int pll)
-{
-	switch (pll) {
-	case 0:
-		if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
-			return BASIS_REQUENCY_USB;
-		else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
-			return BASIC_FREQUENCY_1;
-		else
-			return BASIC_FREQUENCY_2;
-	case 1:
-		if (CGU_PLL1_SRC)
-			return BASIS_REQUENCY_USB;
-		else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
-			return BASIC_FREQUENCY_1;
-		else
-			return BASIC_FREQUENCY_2;
-	case 2:
-		switch (CGU_PLL2_SRC) {
-		case 0:
-			return ltq_get_pll0_fdiv();
-		case 1:
-			return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
-				BASIC_FREQUENCY_1 :
-				BASIC_FREQUENCY_2;
-		case 2:
-			return BASIS_REQUENCY_USB;
-		}
-	default:
-		return 0;
-	}
-}
-
-static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
-{
-	u64 res, clock = get_input_clock(pll);
-
-	res = num * clock;
-	do_div(res, den);
-	return res;
-}
-
-static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
-	unsigned int K)
-{
-	unsigned int num = ((N + 1) << 10) + K;
-	unsigned int den = (M + 1) << 10;
-
-	return cal_dsm(pll, num, den);
-}
-
-static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
-	unsigned int K)
-{
-	unsigned int num = ((N + 1) << 11) + K + 512;
-	unsigned int den = (M + 1) << 11;
-
-	return cal_dsm(pll, num, den);
-}
-
-static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
-	unsigned int K)
-{
-	unsigned int num = K >= 512 ?
-		((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
-	unsigned int den = (M + 1) << 12;
-
-	return cal_dsm(pll, num, den);
-}
-
-static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
-	unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
-{
-	if (!dsmsel)
-		return mash_dsm(pll, M, N, K);
-	else if (!phase_div_en)
-		return mash_dsm(pll, M, N, K);
-	else
-		return ssff_dsm_2(pll, M, N, K);
-}
-
-static inline unsigned int ltq_get_pll0_fosc(void)
-{
-	if (CGU_PLL0_BYPASS)
-		return get_input_clock(0);
-	else
-		return !CGU_PLL0_CFG_FRAC_EN
-			? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
-				CGU_PLL0_CFG_DSMSEL,
-				CGU_PLL0_PHASE_DIVIDER_ENABLE)
-			: dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
-				CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
-				CGU_PLL0_PHASE_DIVIDER_ENABLE);
-}
-
-static unsigned int ltq_get_pll0_fdiv(void)
-{
-	unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
-
-	return (ltq_get_pll0_fosc() + (div >> 1)) / div;
-}
-
-unsigned int ltq_get_io_region_clock(void)
-{
-	unsigned int ret = ltq_get_pll0_fosc();
-
-	switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
-	default:
-	case 0:
-		return (ret + 1) / 2;
-	case 1:
-		return (ret * 2 + 2) / 5;
-	case 2:
-		return (ret + 1) / 3;
-	case 3:
-		return (ret + 2) / 4;
-	}
-}
-EXPORT_SYMBOL(ltq_get_io_region_clock);
-
-unsigned int ltq_get_fpi_bus_clock(int fpi)
-{
-	unsigned int ret = ltq_get_io_region_clock();
-
-	if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
-		ret >>= 1;
-	return ret;
-}
-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
-
-unsigned int ltq_get_cpu_hz(void)
-{
-	switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
-	case 0:
-		return CLOCK_333M;
-	case 4:
-		return DDR_HZ;
-	case 8:
-		return DDR_HZ << 1;
-	default:
-		return DDR_HZ >> 1;
-	}
-}
-EXPORT_SYMBOL(ltq_get_cpu_hz);
-
-unsigned int ltq_get_fpi_hz(void)
-{
-	unsigned int ddr_clock = DDR_HZ;
-
-	if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
-		return ddr_clock >> 1;
-	return ddr_clock;
-}
-EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
new file mode 100644
index 0000000..9aa17f7
--- /dev/null
+++ b/arch/mips/lantiq/xway/clk.c
@@ -0,0 +1,151 @@
+/*
+ *  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) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+
+#include "../clk.h"
+
+static unsigned int ram_clocks[] = {
+	CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
+#define DDR_HZ ram_clocks[ltq_cgu_r32(CGU_SYS) & 0x3]
+
+/* legacy xway clock */
+#define CGU_SYS			0x10
+
+/* vr9 clock */
+#define CGU_SYS_VR9		0x0c
+#define CGU_IF_CLK_VR9		0x24
+
+unsigned long ltq_danube_fpi_hz(void)
+{
+	unsigned long ddr_clock = DDR_HZ;
+
+	if (ltq_cgu_r32(CGU_SYS) & 0x40)
+		return ddr_clock >> 1;
+	return ddr_clock;
+}
+
+unsigned long ltq_danube_cpu_hz(void)
+{
+	switch (ltq_cgu_r32(CGU_SYS) & 0xc) {
+	case 0:
+		return CLOCK_333M;
+	case 4:
+		return DDR_HZ;
+	case 8:
+		return DDR_HZ << 1;
+	default:
+		return DDR_HZ >> 1;
+	}
+}
+
+unsigned long ltq_ar9_sys_hz(void)
+{
+	if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2)
+		return CLOCK_393M;
+	return CLOCK_333M;
+}
+
+unsigned long ltq_ar9_fpi_hz(void)
+{
+	unsigned long sys = ltq_ar9_sys_hz();
+
+	if (ltq_cgu_r32(CGU_SYS) & BIT(0))
+		return sys;
+	return sys >> 1;
+}
+
+unsigned long ltq_ar9_cpu_hz(void)
+{
+	if (ltq_cgu_r32(CGU_SYS) & BIT(2))
+		return ltq_ar9_fpi_hz();
+	else
+		return ltq_ar9_sys_hz();
+}
+
+unsigned long ltq_vr9_cpu_hz(void)
+{
+	unsigned int cpu_sel;
+	unsigned long clk;
+
+	cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf;
+
+	switch (cpu_sel) {
+	case 0:
+		clk = CLOCK_600M;
+		break;
+	case 1:
+		clk = CLOCK_500M;
+		break;
+	case 2:
+		clk = CLOCK_393M;
+		break;
+	case 3:
+		clk = CLOCK_333M;
+		break;
+	case 5:
+	case 6:
+		clk = CLOCK_196_608M;
+		break;
+	case 7:
+		clk = CLOCK_167M;
+		break;
+	case 4:
+	case 8:
+	case 9:
+		clk = CLOCK_125M;
+		break;
+	default:
+		clk = 0;
+		break;
+	}
+
+	return clk;
+}
+
+unsigned long ltq_vr9_fpi_hz(void)
+{
+	unsigned int ocp_sel, cpu_clk;
+	unsigned long clk;
+
+	cpu_clk = ltq_vr9_cpu_hz();
+	ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3;
+
+	switch (ocp_sel) {
+	case 0:
+		/* OCP ratio 1 */
+		clk = cpu_clk;
+		break;
+	case 2:
+		/* OCP ratio 2 */
+		clk = cpu_clk / 2;
+		break;
+	case 3:
+		/* OCP ratio 2.5 */
+		clk = (cpu_clk * 2) / 5;
+		break;
+	case 4:
+		/* OCP ratio 3 */
+		clk = cpu_clk / 3;
+		break;
+	default:
+		clk = 0;
+		break;
+	}
+
+	return clk;
+}
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
deleted file mode 100644
index 419b47b..0000000
--- a/arch/mips/lantiq/xway/ebu.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  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.
- *
- *  EBU - the external bus unit attaches PCI, NOR and NAND
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
-
-static struct resource ltq_ebu_resource = {
-	.name	= "ebu",
-	.start	= LTQ_EBU_BASE_ADDR,
-	.end	= LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-/* remapped base addr of the clock unit and external bus unit */
-void __iomem *ltq_ebu_membase;
-
-static int __init lantiq_ebu_init(void)
-{
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
-		panic("Failed to insert ebu memory");
-
-	if (request_mem_region(ltq_ebu_resource.start,
-			resource_size(&ltq_ebu_resource), "ebu") < 0)
-		panic("Failed to request ebu memory");
-
-	/* remap ebu register range */
-	ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
-				resource_size(&ltq_ebu_resource));
-	if (!ltq_ebu_membase)
-		panic("Failed to remap ebu memory");
-
-	/* make sure to unprotect the memory region where flash is located */
-	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
-	return 0;
-}
-
-postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
deleted file mode 100644
index fe85361..0000000
--- a/arch/mips/lantiq/xway/pmu.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
-
-/* PMU - the power management unit allows us to turn part of the core
- * on and off
- */
-
-/* the enable / disable registers */
-#define LTQ_PMU_PWDCR	0x1C
-#define LTQ_PMU_PWDSR	0x20
-
-#define ltq_pmu_w32(x, y)	ltq_w32((x), ltq_pmu_membase + (y))
-#define ltq_pmu_r32(x)		ltq_r32(ltq_pmu_membase + (x))
-
-static struct resource ltq_pmu_resource = {
-	.name	= "pmu",
-	.start	= LTQ_PMU_BASE_ADDR,
-	.end	= LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static void __iomem *ltq_pmu_membase;
-
-void ltq_pmu_enable(unsigned int module)
-{
-	int err = 1000000;
-
-	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
-	do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
-
-	if (!err)
-		panic("activating PMU module failed!");
-}
-EXPORT_SYMBOL(ltq_pmu_enable);
-
-void ltq_pmu_disable(unsigned int module)
-{
-	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
-}
-EXPORT_SYMBOL(ltq_pmu_disable);
-
-int __init ltq_pmu_init(void)
-{
-	if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
-		panic("Failed to insert pmu memory");
-
-	if (request_mem_region(ltq_pmu_resource.start,
-			resource_size(&ltq_pmu_resource), "pmu") < 0)
-		panic("Failed to request pmu memory");
-
-	ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
-				resource_size(&ltq_pmu_resource));
-	if (!ltq_pmu_membase)
-		panic("Failed to remap pmu memory");
-	return 0;
-}
-
-core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
new file mode 100644
index 0000000..3029139
--- /dev/null
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -0,0 +1,364 @@
+/*
+ *  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) 2011-2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/export.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#include <lantiq_soc.h>
+
+#include "../clk.h"
+#include "../prom.h"
+
+/* clock control register */
+#define CGU_IFCCR	0x0018
+/* system clock register */
+#define CGU_SYS		0x0010
+/* pci control register */
+#define CGU_PCICR	0x0034
+/* ephy configuration register */
+#define CGU_EPHY	0x10
+/* power control register */
+#define PMU_PWDCR	0x1C
+/* power status register */
+#define PMU_PWDSR	0x20
+/* power control register */
+#define PMU_PWDCR1	0x24
+/* power status register */
+#define PMU_PWDSR1	0x28
+/* power control register */
+#define PWDCR(x) ((x) ? (PMU_PWDCR1) : (PMU_PWDCR))
+/* power status register */
+#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
+
+/* clock gates that we can en/disable */
+#define PMU_USB0_P	BIT(0)
+#define PMU_PCI		BIT(4)
+#define PMU_USB0	BIT(6)
+#define PMU_ASC0	BIT(7)
+#define PMU_EPHY	BIT(7)	/* ase */
+#define PMU_SPI		BIT(8)
+#define PMU_DFE		BIT(9)
+#define PMU_EBU		BIT(10)
+#define PMU_STP		BIT(11)
+#define PMU_AHBS	BIT(13) /* vr9 */
+#define PMU_AHBM	BIT(15)
+#define PMU_ASC1	BIT(17)
+#define PMU_PPE_QSB	BIT(18)
+#define PMU_PPE_SLL01	BIT(19)
+#define PMU_PPE_TC	BIT(21)
+#define PMU_PPE_EMA	BIT(22)
+#define PMU_PPE_DPLUM	BIT(23)
+#define PMU_PPE_DPLUS	BIT(24)
+#define PMU_USB1_P	BIT(26)
+#define PMU_USB1	BIT(27)
+#define PMU_PPE_TOP	BIT(29)
+#define PMU_GPHY	BIT(30)
+#define PMU_PCIE_CLK	BIT(31)
+
+#define PMU1_PCIE_PHY	BIT(0)
+#define PMU1_PCIE_CTL	BIT(1)
+#define PMU1_PCIE_PDI	BIT(4)
+#define PMU1_PCIE_MSI	BIT(5)
+
+#define pmu_w32(x, y)	ltq_w32((x), pmu_membase + (y))
+#define pmu_r32(x)	ltq_r32(pmu_membase + (x))
+
+static void __iomem *pmu_membase;
+void __iomem *ltq_cgu_membase;
+void __iomem *ltq_ebu_membase;
+
+/* legacy function kept alive to ease clkdev transition */
+void ltq_pmu_enable(unsigned int module)
+{
+	int err = 1000000;
+
+	pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
+	do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
+
+	if (!err)
+		panic("activating PMU module failed!");
+}
+EXPORT_SYMBOL(ltq_pmu_enable);
+
+/* legacy function kept alive to ease clkdev transition */
+void ltq_pmu_disable(unsigned int module)
+{
+	pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
+}
+EXPORT_SYMBOL(ltq_pmu_disable);
+
+/* enable a hw clock */
+static int cgu_enable(struct clk *clk)
+{
+	ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR);
+	return 0;
+}
+
+/* disable a hw clock */
+static void cgu_disable(struct clk *clk)
+{
+	ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR);
+}
+
+/* enable a clock gate */
+static int pmu_enable(struct clk *clk)
+{
+	int err = 1000000;
+
+	pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
+		PWDCR(clk->module));
+	do {} while (--err && (pmu_r32(PWDSR(clk->module)) & clk->bits));
+
+	if (!err)
+		panic("activating PMU module failed!\n");
+
+	return 0;
+}
+
+/* disable a clock gate */
+static void pmu_disable(struct clk *clk)
+{
+	pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
+		PWDCR(clk->module));
+}
+
+/* the pci enable helper */
+static int pci_enable(struct clk *clk)
+{
+	unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
+	/* set bus clock speed */
+	if (of_machine_is_compatible("lantiq,ar9")) {
+		ifccr &= ~0x1f00000;
+		if (clk->rate == CLOCK_33M)
+			ifccr |= 0xe00000;
+		else
+			ifccr |= 0x700000; /* 62.5M */
+	} else {
+		ifccr &= ~0xf00000;
+		if (clk->rate == CLOCK_33M)
+			ifccr |= 0x800000;
+		else
+			ifccr |= 0x400000; /* 62.5M */
+	}
+	ltq_cgu_w32(ifccr, CGU_IFCCR);
+	pmu_enable(clk);
+	return 0;
+}
+
+/* enable the external clock as a source */
+static int pci_ext_enable(struct clk *clk)
+{
+	ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16),
+		CGU_IFCCR);
+	ltq_cgu_w32((1 << 30), CGU_PCICR);
+	return 0;
+}
+
+/* disable the external clock as a source */
+static void pci_ext_disable(struct clk *clk)
+{
+	ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16),
+		CGU_IFCCR);
+	ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR);
+}
+
+/* enable a clockout source */
+static int clkout_enable(struct clk *clk)
+{
+	int i;
+
+	/* get the correct rate */
+	for (i = 0; i < 4; i++) {
+		if (clk->rates[i] == clk->rate) {
+			int shift = 14 - (2 * clk->module);
+			unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
+
+			ifccr &= ~(3 << shift);
+			ifccr |= i << shift;
+			ltq_cgu_w32(ifccr, CGU_IFCCR);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+/* manage the clock gates via PMU */
+static void clkdev_add_pmu(const char *dev, const char *con,
+					unsigned int module, unsigned int bits)
+{
+	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
+	clk->cl.dev_id = dev;
+	clk->cl.con_id = con;
+	clk->cl.clk = clk;
+	clk->enable = pmu_enable;
+	clk->disable = pmu_disable;
+	clk->module = module;
+	clk->bits = bits;
+	clkdev_add(&clk->cl);
+}
+
+/* manage the clock generator */
+static void clkdev_add_cgu(const char *dev, const char *con,
+					unsigned int bits)
+{
+	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
+	clk->cl.dev_id = dev;
+	clk->cl.con_id = con;
+	clk->cl.clk = clk;
+	clk->enable = cgu_enable;
+	clk->disable = cgu_disable;
+	clk->bits = bits;
+	clkdev_add(&clk->cl);
+}
+
+/* pci needs its own enable function as the setup is a bit more complex */
+static unsigned long valid_pci_rates[] = {CLOCK_33M, CLOCK_62_5M, 0};
+
+static void clkdev_add_pci(void)
+{
+	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+	struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
+	/* main pci clock */
+	clk->cl.dev_id = "17000000.pci";
+	clk->cl.con_id = NULL;
+	clk->cl.clk = clk;
+	clk->rate = CLOCK_33M;
+	clk->rates = valid_pci_rates;
+	clk->enable = pci_enable;
+	clk->disable = pmu_disable;
+	clk->module = 0;
+	clk->bits = PMU_PCI;
+	clkdev_add(&clk->cl);
+
+	/* use internal/external bus clock */
+	clk_ext->cl.dev_id = "17000000.pci";
+	clk_ext->cl.con_id = "external";
+	clk_ext->cl.clk = clk_ext;
+	clk_ext->enable = pci_ext_enable;
+	clk_ext->disable = pci_ext_disable;
+	clkdev_add(&clk_ext->cl);
+}
+
+/* xway socs can generate clocks on gpio pins */
+static unsigned long valid_clkout_rates[4][5] = {
+	{CLOCK_32_768K, CLOCK_1_536M, CLOCK_2_5M, CLOCK_12M, 0},
+	{CLOCK_40M, CLOCK_12M, CLOCK_24M, CLOCK_48M, 0},
+	{CLOCK_25M, CLOCK_40M, CLOCK_30M, CLOCK_60M, 0},
+	{CLOCK_12M, CLOCK_50M, CLOCK_32_768K, CLOCK_25M, 0},
+};
+
+static void clkdev_add_clkout(void)
+{
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		struct clk *clk;
+		char *name;
+
+		name = kzalloc(sizeof("clkout0"), GFP_KERNEL);
+		sprintf(name, "clkout%d", i);
+
+		clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+		clk->cl.dev_id = "1f103000.cgu";
+		clk->cl.con_id = name;
+		clk->cl.clk = clk;
+		clk->rate = 0;
+		clk->rates = valid_clkout_rates[i];
+		clk->enable = clkout_enable;
+		clk->module = i;
+		clkdev_add(&clk->cl);
+	}
+}
+
+/* bring up all register ranges that we need for basic system control */
+void __init ltq_soc_init(void)
+{
+	struct resource res_pmu, res_cgu, res_ebu;
+	struct device_node *np_pmu =
+			of_find_compatible_node(NULL, NULL, "lantiq,pmu-xway");
+	struct device_node *np_cgu =
+			of_find_compatible_node(NULL, NULL, "lantiq,cgu-xway");
+	struct device_node *np_ebu =
+			of_find_compatible_node(NULL, NULL, "lantiq,ebu-xway");
+
+	/* check if all the core register ranges are available */
+	if (!np_pmu || !np_cgu || !np_ebu)
+		panic("Failed to load core nodess from devicetree");
+
+	if (of_address_to_resource(np_pmu, 0, &res_pmu) ||
+			of_address_to_resource(np_cgu, 0, &res_cgu) ||
+			of_address_to_resource(np_ebu, 0, &res_ebu))
+		panic("Failed to get core resources");
+
+	if ((request_mem_region(res_pmu.start, resource_size(&res_pmu),
+				res_pmu.name) < 0) ||
+		(request_mem_region(res_cgu.start, resource_size(&res_cgu),
+				res_cgu.name) < 0) ||
+		(request_mem_region(res_ebu.start, resource_size(&res_ebu),
+				res_ebu.name) < 0))
+		pr_err("Failed to request core reources");
+
+	pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
+	ltq_cgu_membase = ioremap_nocache(res_cgu.start,
+						resource_size(&res_cgu));
+	ltq_ebu_membase = ioremap_nocache(res_ebu.start,
+						resource_size(&res_ebu));
+	if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
+		panic("Failed to remap core resources");
+
+	/* make sure to unprotect the memory region where flash is located */
+	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
+
+	/* add our generic xway clocks */
+	clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI);
+	clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0);
+	clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT);
+	clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP);
+	clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA);
+	clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI);
+	clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU);
+	clkdev_add_clkout();
+
+	/* add the soc dependent clocks */
+	if (!of_machine_is_compatible("lantiq,vr9"))
+		clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE);
+
+	if (!of_machine_is_compatible("lantiq,ase")) {
+		clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1);
+		clkdev_add_pci();
+	}
+
+	if (of_machine_is_compatible("lantiq,ase")) {
+		if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
+			clkdev_add_static(CLOCK_266M, CLOCK_133M);
+		else
+			clkdev_add_static(CLOCK_133M, CLOCK_133M);
+		clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
+		clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
+	} else if (of_machine_is_compatible("lantiq,vr9")) {
+		clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz());
+		clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
+		clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
+		clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
+		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);
+	} else if (of_machine_is_compatible("lantiq,ar9")) {
+		clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz());
+		clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
+	} else {
+		clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz());
+	}
+}
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 06/14] MIPS: lantiq: convert dma to platform driver
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
       [not found] ` <1336133919-26525-1-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
  2012-05-04 12:18 ` [PATCH 05/14] MIPS: lantiq: implement support for clkdev api John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 07/14] MIPS: pci: convert lantiq driver to OF John Crispin
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin

Add code to make the dma driver load as a platform device from the devicetree.

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/lantiq/xway/dma.c |   65 ++++++++++++++++++++++++++++--------------
 1 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index b210e93..0dffb94 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -19,7 +19,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
-#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/clk.h>
 
 #include <lantiq_soc.h>
 #include <xway_dma.h>
@@ -55,13 +56,6 @@
 #define ltq_dma_w32_mask(x, y, z)	ltq_w32_mask(x, y, \
 						ltq_dma_membase + (z))
 
-static struct resource ltq_dma_resource = {
-	.name	= "dma",
-	.start	= LTQ_DMA_BASE_ADDR,
-	.end	= LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
 static void __iomem *ltq_dma_membase;
 
 void
@@ -215,27 +209,28 @@ ltq_dma_init_port(int p)
 }
 EXPORT_SYMBOL_GPL(ltq_dma_init_port);
 
-int __init
-ltq_dma_init(void)
+static int __devinit
+ltq_dma_init(struct platform_device *pdev)
 {
+	struct clk *clk;
+	struct resource *res;
 	int i;
 
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
-		panic("Failed to insert dma memory");
-
-	if (request_mem_region(ltq_dma_resource.start,
-			resource_size(&ltq_dma_resource), "dma") < 0)
-		panic("Failed to request dma memory");
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		panic("Failed to get dma resource");
 
 	/* remap dma register range */
-	ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
-				resource_size(&ltq_dma_resource));
+	ltq_dma_membase = devm_request_and_ioremap(&pdev->dev, res);
 	if (!ltq_dma_membase)
-		panic("Failed to remap dma memory");
+		panic("Failed to remap dma resource");
 
 	/* power up and reset the dma engine */
-	ltq_pmu_enable(PMU_DMA);
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		panic("Failed to get dma clock");
+
+	clk_enable(clk);
 	ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
 
 	/* disable all interrupts */
@@ -248,7 +243,33 @@ ltq_dma_init(void)
 		ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
 		ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
 	}
+	dev_info(&pdev->dev, "init done\n");
 	return 0;
 }
 
-postcore_initcall(ltq_dma_init);
+static const struct of_device_id dma_match[] = {
+	{ .compatible = "lantiq,dma-xway" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dma_match);
+
+static struct platform_driver dma_driver = {
+	.probe = ltq_dma_init,
+	.driver = {
+		.name = "dma-xway",
+		.owner = THIS_MODULE,
+		.of_match_table = dma_match,
+	},
+};
+
+int __init
+dma_init(void)
+{
+	int ret = platform_driver_register(&dma_driver);
+
+	if (ret)
+		pr_info("ltq_dma : Error registering platfom driver!");
+	return ret;
+}
+
+postcore_initcall(dma_init);
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 07/14] MIPS: pci: convert lantiq driver to OF
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (2 preceding siblings ...)
  2012-05-04 12:18 ` [PATCH 06/14] MIPS: lantiq: convert dma to platform driver John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 08/14] GPIO: MIPS: lantiq: convert gpio-stp to OF and move it to subsystem John Crispin
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin

Implement support for OF inside the lantiq PCI driver. The patch also splits
pcibios_plat_dev_init and pcibios_map_irq out into their own file to accomodate
coexistance with the upcoming pcie driver.

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/lantiq/Kconfig     |    5 +-
 arch/mips/pci/Makefile       |    3 +-
 arch/mips/pci/fixup-lantiq.c |   40 ++++++++++
 arch/mips/pci/pci-lantiq.c   |  177 ++++++++++++++++++++----------------------
 4 files changed, 131 insertions(+), 94 deletions(-)
 create mode 100644 arch/mips/pci/fixup-lantiq.c

diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index b86d942..c645b44 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -19,7 +19,6 @@ config SOC_XWAY
 	select HW_HAS_PCI
 endchoice
 
-
 choice
 	prompt "Devicetree"
 
@@ -28,4 +27,8 @@ config DT_EASY50712
 	depends on SOC_XWAY
 endchoice
 
+config PCI_LANTIQ
+	bool "PCI Support"
+	depends on SOC_XWAY && PCI
+
 endif
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index c3ac4b0..499a019 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -41,7 +41,8 @@ obj-$(CONFIG_SIBYTE_SB1250)	+= fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM112X)	+= fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM1x80)	+= pci-bcm1480.o pci-bcm1480ht.o
 obj-$(CONFIG_SNI_RM)		+= fixup-sni.o ops-sni.o
-obj-$(CONFIG_SOC_XWAY)		+= pci-lantiq.o ops-lantiq.o
+obj-$(CONFIG_LANTIQ)		+= fixup-lantiq.o
+obj-$(CONFIG_PCI_LANTIQ)	+= pci-lantiq.o ops-lantiq.o
 obj-$(CONFIG_TANBAC_TB0219)	+= fixup-tb0219.o
 obj-$(CONFIG_TANBAC_TB0226)	+= fixup-tb0226.o
 obj-$(CONFIG_TANBAC_TB0287)	+= fixup-tb0287.o
diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
new file mode 100644
index 0000000..6c829df
--- /dev/null
+++ b/arch/mips/pci/fixup-lantiq.c
@@ -0,0 +1,40 @@
+/*
+ *  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>
+ */
+
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+
+int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL;
+int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL;
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	if (ltq_pci_plat_arch_init)
+		return ltq_pci_plat_arch_init(dev);
+
+	if (ltq_pci_plat_dev_init)
+		return ltq_pci_plat_dev_init(dev);
+
+	return 0;
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct of_irq dev_irq;
+	int irq;
+
+	if (of_irq_map_pci(dev, &dev_irq)) {
+		dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n",
+			slot, pin);
+		return 0;
+	}
+	irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier,
+					dev_irq.size);
+	dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
+	return irq;
+}
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
index 3418178..ea45353 100644
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -13,8 +13,12 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
 
 #include <asm/pci.h>
 #include <asm/gpio.h>
@@ -22,17 +26,9 @@
 
 #include <lantiq_soc.h>
 #include <lantiq_irq.h>
-#include <lantiq_platform.h>
 
 #include "pci-lantiq.h"
 
-#define LTQ_PCI_CFG_BASE		0x17000000
-#define LTQ_PCI_CFG_SIZE		0x00008000
-#define LTQ_PCI_MEM_BASE		0x18000000
-#define LTQ_PCI_MEM_SIZE		0x02000000
-#define LTQ_PCI_IO_BASE			0x1AE00000
-#define LTQ_PCI_IO_SIZE			0x00200000
-
 #define PCI_CR_FCI_ADDR_MAP0		0x00C0
 #define PCI_CR_FCI_ADDR_MAP1		0x00C4
 #define PCI_CR_FCI_ADDR_MAP2		0x00C8
@@ -71,50 +67,24 @@
 __iomem void *ltq_pci_mapped_cfg;
 static __iomem void *ltq_pci_membase;
 
-int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;
-
-/* Since the PCI REQ pins can be reused for other functionality, make it
-   possible to exclude those from interpretation by the PCI controller */
-static int ltq_pci_req_mask = 0xf;
-
-static int *ltq_pci_irq_map;
-
-struct pci_ops ltq_pci_ops = {
+static int reset_gpio;
+static struct clk *clk_pci, *clk_external;
+static struct resource pci_io_resource;
+static struct resource pci_mem_resource;
+static struct pci_ops pci_ops = {
 	.read	= ltq_pci_read_config_dword,
 	.write	= ltq_pci_write_config_dword
 };
 
-static struct resource pci_io_resource = {
-	.name	= "pci io space",
-	.start	= LTQ_PCI_IO_BASE,
-	.end	= LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	.name	= "pci memory space",
-	.start	= LTQ_PCI_MEM_BASE,
-	.end	= LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-static struct pci_controller ltq_pci_controller = {
-	.pci_ops	= &ltq_pci_ops,
+static struct pci_controller pci_controller = {
+	.pci_ops	= &pci_ops,
 	.mem_resource	= &pci_mem_resource,
 	.mem_offset	= 0x00000000UL,
 	.io_resource	= &pci_io_resource,
 	.io_offset	= 0x00000000UL,
 };
 
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	if (ltqpci_plat_dev_init)
-		return ltqpci_plat_dev_init(dev);
-
-	return 0;
-}
-
-static u32 ltq_calc_bar11mask(void)
+static inline u32 ltq_calc_bar11mask(void)
 {
 	u32 mem, bar11mask;
 
@@ -125,32 +95,42 @@ static u32 ltq_calc_bar11mask(void)
 	return bar11mask;
 }
 
-static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
+static int __devinit ltq_pci_startup(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
+	const __be32 *req_mask, *bus_clk;
 	u32 temp_buffer;
 
-	/* set clock to 33Mhz */
-	if (ltq_is_ar9()) {
-		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR);
-		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR);
-	} else {
-		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
-		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+	/* get our clocks */
+	clk_pci = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk_pci)) {
+		dev_err(&pdev->dev, "failed to get pci clock\n");
+		return PTR_ERR(clk_pci);
 	}
 
-	/* external or internal clock ? */
-	if (conf->clock) {
-		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16),
-			LTQ_CGU_IFCCR);
-		ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR);
-	} else {
-		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16),
-			LTQ_CGU_IFCCR);
-		ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR);
+	clk_external = clk_get(&pdev->dev, "external");
+	if (IS_ERR(clk_external)) {
+		clk_put(clk_pci);
+		dev_err(&pdev->dev, "failed to get external pci clock\n");
+		return PTR_ERR(clk_external);
 	}
 
-	/* setup pci clock and gpis used by pci */
-	gpio_request(21, "pci-reset");
+	/* read the bus speed that we want */
+	bus_clk = of_get_property(node, "lantiq,bus-clock", NULL);
+	if (bus_clk)
+		clk_set_rate(clk_pci, *bus_clk);
+
+	/* and enable the clocks */
+	clk_enable(clk_pci);
+	if (of_find_property(node, "lantiq,external-clock", NULL))
+		clk_enable(clk_external);
+	else
+		clk_disable(clk_external);
+
+	/* setup reset gpio used by pci */
+	reset_gpio = of_get_named_gpio(node, "gpio-reset", 0);
+	if (reset_gpio > 0)
+		devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset");
 
 	/* enable auto-switching between PCI and EBU */
 	ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
@@ -163,7 +143,12 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
 
 	/* enable external 2 PCI masters */
 	temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB);
-	temp_buffer &= (~(ltq_pci_req_mask << 16));
+	/* setup the request mask */
+	req_mask = of_get_property(node, "req-mask", NULL);
+	if (req_mask)
+		temp_buffer &= ~((*req_mask & 0xf) << 16);
+	else
+		temp_buffer &= ~0xf0000;
 	/* enable internal arbiter */
 	temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
 	/* enable internal PCI master reqest */
@@ -207,47 +192,55 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
 	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
 
 	/* toggle reset pin */
-	__gpio_set_value(21, 0);
-	wmb();
-	mdelay(1);
-	__gpio_set_value(21, 1);
-	return 0;
-}
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	if (ltq_pci_irq_map[slot])
-		return ltq_pci_irq_map[slot];
-	printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n",
-		slot);
-
+	if (reset_gpio > 0) {
+		__gpio_set_value(reset_gpio, 0);
+		wmb();
+		mdelay(1);
+		__gpio_set_value(reset_gpio, 1);
+	}
 	return 0;
 }
 
 static int __devinit ltq_pci_probe(struct platform_device *pdev)
 {
-	struct ltq_pci_data *ltq_pci_data =
-		(struct ltq_pci_data *) pdev->dev.platform_data;
+	struct resource *res_cfg, *res_bridge;
 
 	pci_clear_flags(PCI_PROBE_ONLY);
-	ltq_pci_irq_map = ltq_pci_data->irq;
-	ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
-	ltq_pci_mapped_cfg =
-		ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
-	ltq_pci_controller.io_map_base =
-		(unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
-	ltq_pci_startup(ltq_pci_data);
-	register_pci_controller(&ltq_pci_controller);
 
+	res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_bridge = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res_cfg || !res_bridge) {
+		dev_err(&pdev->dev, "missing memory reources\n");
+		return -EINVAL;
+	}
+
+	ltq_pci_membase = devm_request_and_ioremap(&pdev->dev, res_bridge);
+	ltq_pci_mapped_cfg = devm_request_and_ioremap(&pdev->dev, res_cfg);
+
+	if (!ltq_pci_membase || !ltq_pci_mapped_cfg) {
+		dev_err(&pdev->dev, "failed to remap resources\n");
+		return -ENOMEM;
+	}
+
+	ltq_pci_startup(pdev);
+
+	pci_load_of_ranges(&pci_controller, pdev->dev.of_node);
+	register_pci_controller(&pci_controller);
 	return 0;
 }
 
-static struct platform_driver
-ltq_pci_driver = {
+static const struct of_device_id ltq_pci_match[] = {
+	{ .compatible = "lantiq,pci-xway" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_pci_match);
+
+static struct platform_driver ltq_pci_driver = {
 	.probe = ltq_pci_probe,
 	.driver = {
-		.name = "ltq_pci",
+		.name = "pci-xway",
 		.owner = THIS_MODULE,
+		.of_match_table = ltq_pci_match,
 	},
 };
 
@@ -255,7 +248,7 @@ int __init pcibios_init(void)
 {
 	int ret = platform_driver_register(&ltq_pci_driver);
 	if (ret)
-		printk(KERN_INFO "ltq_pci: Error registering platform driver!");
+		pr_info("pci-xway: Error registering platform driver!");
 	return ret;
 }
 
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 08/14] GPIO: MIPS: lantiq: convert gpio-stp to OF and move it to subsystem
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (3 preceding siblings ...)
  2012-05-04 12:18 ` [PATCH 07/14] MIPS: pci: convert lantiq driver to OF John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 09/14] GPIO: MIPS: lantiq: convert gpio-ebu " John Crispin
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Grant Likely, linux-kernel

Implements OF support and moves the driver from arch/mips/lantiq/xway/ to the
gpio subsystem.

The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a
peripheral controller used to drive external shift register cascades. At most
3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem
to drive the 2 LSBs of the cascade automatically. The driver currently only
supports output functionality. Patches for the input feature found on newer
generations of the soc will be provided in a later series.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: linux-kernel@vger.kernel.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/lantiq/xway/Makefile   |    2 +-
 arch/mips/lantiq/xway/gpio_stp.c |  152 -------------------
 drivers/gpio/Kconfig             |   10 ++
 drivers/gpio/Makefile            |    1 +
 drivers/gpio/gpio-stp-xway.c     |  300 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 312 insertions(+), 153 deletions(-)
 delete mode 100644 arch/mips/lantiq/xway/gpio_stp.c
 create mode 100644 drivers/gpio/gpio-stp-xway.c

diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 6e930b70..9c5d69f 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 gpio_stp.o gpio_ebu.o
+obj-y := prom.o sysctrl.o clk.o reset.o dma.o gpio_ebu.o
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
deleted file mode 100644
index 4f4bd61..0000000
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- *  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) 2007 John Crispin <blogic@openwrt.org>
- *
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <lantiq_soc.h>
-
-#define LTQ_STP_CON0		0x00
-#define LTQ_STP_CON1		0x04
-#define LTQ_STP_CPU0		0x08
-#define LTQ_STP_CPU1		0x0C
-#define LTQ_STP_AR		0x10
-
-#define LTQ_STP_CON_SWU		(1 << 31)
-#define LTQ_STP_2HZ		0
-#define LTQ_STP_4HZ		(1 << 23)
-#define LTQ_STP_8HZ		(2 << 23)
-#define LTQ_STP_10HZ		(3 << 23)
-#define LTQ_STP_SPEED_MASK	(0xf << 23)
-#define LTQ_STP_UPD_FPI		(1 << 31)
-#define LTQ_STP_UPD_MASK	(3 << 30)
-#define LTQ_STP_ADSL_SRC	(3 << 24)
-
-#define LTQ_STP_GROUP0		(1 << 0)
-
-#define LTQ_STP_RISING		0
-#define LTQ_STP_FALLING		(1 << 26)
-#define LTQ_STP_EDGE_MASK	(1 << 26)
-
-#define ltq_stp_r32(reg)	__raw_readl(ltq_stp_membase + reg)
-#define ltq_stp_w32(val, reg)	__raw_writel(val, ltq_stp_membase + reg)
-#define ltq_stp_w32_mask(clear, set, reg) \
-		ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \
-		ltq_stp_membase + (reg))
-
-static int ltq_stp_shadow = 0xffff;
-static void __iomem *ltq_stp_membase;
-
-static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	if (value)
-		ltq_stp_shadow |= (1 << offset);
-	else
-		ltq_stp_shadow &= ~(1 << offset);
-	ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
-}
-
-static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
-	int value)
-{
-	ltq_stp_set(chip, offset, value);
-
-	return 0;
-}
-
-static struct gpio_chip ltq_stp_chip = {
-	.label = "ltq_stp",
-	.direction_output = ltq_stp_direction_output,
-	.set = ltq_stp_set,
-	.base = 48,
-	.ngpio = 24,
-	.can_sleep = 1,
-	.owner = THIS_MODULE,
-};
-
-static int ltq_stp_hw_init(void)
-{
-	/* sane defaults */
-	ltq_stp_w32(0, LTQ_STP_AR);
-	ltq_stp_w32(0, LTQ_STP_CPU0);
-	ltq_stp_w32(0, LTQ_STP_CPU1);
-	ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);
-	ltq_stp_w32(0, LTQ_STP_CON1);
-
-	/* rising or falling edge */
-	ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
-
-	/* per default stp 15-0 are set */
-	ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
-
-	/* stp are update periodically by the FPI bus */
-	ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
-
-	/* set stp update speed */
-	ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
-
-	/* tell the hardware that pin (led) 0 and 1 are controlled
-	 *  by the dsl arc
-	 */
-	ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
-
-	ltq_pmu_enable(PMU_LED);
-	return 0;
-}
-
-static int __devinit ltq_stp_probe(struct platform_device *pdev)
-{
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	int ret = 0;
-
-	if (!res)
-		return -ENOENT;
-	res = devm_request_mem_region(&pdev->dev, res->start,
-		resource_size(res), dev_name(&pdev->dev));
-	if (!res) {
-		dev_err(&pdev->dev, "failed to request STP memory\n");
-		return -EBUSY;
-	}
-	ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,
-		resource_size(res));
-	if (!ltq_stp_membase) {
-		dev_err(&pdev->dev, "failed to remap STP memory\n");
-		return -ENOMEM;
-	}
-	ret = gpiochip_add(&ltq_stp_chip);
-	if (!ret)
-		ret = ltq_stp_hw_init();
-
-	return ret;
-}
-
-static struct platform_driver ltq_stp_driver = {
-	.probe = ltq_stp_probe,
-	.driver = {
-		.name = "ltq_stp",
-		.owner = THIS_MODULE,
-	},
-};
-
-int __init ltq_stp_init(void)
-{
-	int ret = platform_driver_register(&ltq_stp_driver);
-
-	if (ret)
-		pr_info("ltq_stp: error registering platform driver");
-	return ret;
-}
-
-postcore_initcall(ltq_stp_init);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 7875c3f..2ec6a3b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -311,6 +311,16 @@ config GPIO_STMPE
 	  This enables support for the GPIOs found on the STMPE I/O
 	  Expanders.
 
+config GPIO_STP_XWAY
+	bool "XWAY STP GPIOs"
+	depends on SOC_XWAY
+	help
+	  This enables support for the Serial To Parallel (STP) unit found on
+	  XWAY SoC. The STP allows the SoC to drive a shift registers cascade,
+	  that can be up to 24 bit. This peripheral is aimed at driving leds.
+	  Some of the gpios/leds can be auto updated by the soc with dsl and
+	  phy status.
+
 config GPIO_TC3589X
 	bool "TC3589X GPIOs"
 	depends on MFD_TC3589X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 1c2f6c0..ff85e12 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SODAVILLE)	+= gpio-sodaville.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
+obj-$(CONFIG_GPIO_STP_XWAY)	+= gpio-stp-xway.o
 obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
 obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
new file mode 100644
index 0000000..9b53adf
--- /dev/null
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -0,0 +1,300 @@
+/*
+ *  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>
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/of_platform.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <lantiq_soc.h>
+
+/*
+ * The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a
+ * peripheral controller used to drive external shift register cascades. At most
+ * 3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem
+ * to drive the 2 LSBs of the cascade automatically.
+ */
+
+/* control register 0 */
+#define XWAY_STP_CON0		0x00
+/* control register 1 */
+#define XWAY_STP_CON1		0x04
+/* data register 0 */
+#define XWAY_STP_CPU0		0x08
+/* data register 1 */
+#define XWAY_STP_CPU1		0x0C
+/* access register */
+#define XWAY_STP_AR		0x10
+
+/* software or hardware update select bit */
+#define XWAY_STP_CON_SWU	BIT(31)
+
+/* automatic update rates */
+#define XWAY_STP_2HZ		0
+#define XWAY_STP_4HZ		BIT(23)
+#define XWAY_STP_8HZ		BIT(24)
+#define XWAY_STP_10HZ		(BIT(24) | BIT(23))
+#define XWAY_STP_SPEED_MASK	(0xf << 23)
+
+/* clock source for automatic update */
+#define XWAY_STP_UPD_FPI	BIT(31)
+#define XWAY_STP_UPD_MASK	(BIT(31) | BIT(30))
+
+/* let the adsl core drive the 2 LSBs */
+#define XWAY_STP_ADSL_SHIFT	24
+#define XWAY_STP_ADSL_MASK	0x3
+
+/* 2 groups of 3 bits can be driven by the phys */
+#define XWAY_STP_PHY_MASK	0x3
+#define XWAY_STP_PHY1_SHIFT	27
+#define XWAY_STP_PHY2_SHIFT	15
+
+/* STP has 3 groups of 8 bits */
+#define XWAY_STP_GROUP0		BIT(0)
+#define XWAY_STP_GROUP1		BIT(1)
+#define XWAY_STP_GROUP2		BIT(2)
+#define XWAY_STP_GROUP_MASK	(0x7)
+
+/* Edge configuration bits */
+#define XWAY_STP_FALLING	BIT(26)
+#define XWAY_STP_EDGE_MASK	BIT(26)
+
+#define xway_stp_r32(m, reg)		__raw_readl(m + reg)
+#define xway_stp_w32(m, val, reg)	__raw_writel(val, m + reg)
+#define xway_stp_w32_mask(m, clear, set, reg) \
+		ltq_w32((ltq_r32(m + reg) & ~(clear)) | (set), \
+		m + reg)
+
+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 */
+	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 */
+	u8 phy2;	/* 3 bits can be driven by phy2 */
+	u8 reserved;	/* mask out the hw driven bits in gpio_request */
+};
+
+/*
+ * xway_stp_set - gpio_chip->set - set gpios.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * Set the shadow value and call ltq_ebu_apply.
+ */
+static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val)
+{
+	struct xway_stp *chip =
+		container_of(gc, struct xway_stp, gc);
+
+	if (val)
+		chip->shadow |= BIT(gpio);
+	else
+		chip->shadow &= ~BIT(gpio);
+	xway_stp_w32(chip->virt, chip->shadow, XWAY_STP_CPU0);
+	xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0);
+}
+
+/*
+ * xway_stp_dir_out - gpio_chip->dir_out - set gpio direction.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * Same as xway_stp_set, always returns 0.
+ */
+static int xway_stp_dir_out(struct gpio_chip *gc, unsigned gpio, int val)
+{
+	xway_stp_set(gc, gpio, val);
+
+	return 0;
+}
+
+/*
+ * xway_stp_request - gpio_chip->request
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ *
+ * We mask out the HW driven pins
+ */
+static int xway_stp_request(struct gpio_chip *gc, unsigned gpio)
+{
+	struct xway_stp *chip =
+		container_of(gc, struct xway_stp, gc);
+
+	if ((gpio < 8) && (chip->reserved & BIT(gpio))) {
+		dev_err(gc->dev, "GPIO %d is driven by hardware\n", gpio);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * xway_stp_hw_init - Configure the STP unit and enable the clock gate
+ * @virt: pointer to the remapped register range
+ */
+static int xway_stp_hw_init(struct xway_stp *chip)
+{
+	/* sane defaults */
+	xway_stp_w32(chip->virt, 0, XWAY_STP_AR);
+	xway_stp_w32(chip->virt, 0, XWAY_STP_CPU0);
+	xway_stp_w32(chip->virt, 0, XWAY_STP_CPU1);
+	xway_stp_w32(chip->virt, XWAY_STP_CON_SWU, XWAY_STP_CON0);
+	xway_stp_w32(chip->virt, 0, XWAY_STP_CON1);
+
+	/* apply edge trigger settings for the shift register */
+	xway_stp_w32_mask(chip->virt, XWAY_STP_EDGE_MASK,
+				chip->edge, XWAY_STP_CON0);
+
+	/* apply led group settings */
+	xway_stp_w32_mask(chip->virt, XWAY_STP_GROUP_MASK,
+				chip->groups, XWAY_STP_CON1);
+
+	/* tell the hardware which pins are controlled by the dsl modem */
+	xway_stp_w32_mask(chip->virt,
+			XWAY_STP_ADSL_MASK << XWAY_STP_ADSL_SHIFT,
+			chip->dsl << XWAY_STP_ADSL_SHIFT,
+			XWAY_STP_CON0);
+
+	/* tell the hardware which pins are controlled by the phys */
+	xway_stp_w32_mask(chip->virt,
+			XWAY_STP_PHY_MASK << XWAY_STP_PHY1_SHIFT,
+			chip->phy1 << XWAY_STP_PHY1_SHIFT,
+			XWAY_STP_CON0);
+	xway_stp_w32_mask(chip->virt,
+			XWAY_STP_PHY_MASK << XWAY_STP_PHY2_SHIFT,
+			chip->phy2 << XWAY_STP_PHY2_SHIFT,
+			XWAY_STP_CON1);
+
+	/* mask out the hw driven bits in gpio_request */
+	chip->reserved = (chip->phy2 << 5) | (chip->phy1 << 2) | chip->dsl;
+
+	/*
+	 * if we have pins that are driven by hw, we need to tell the stp what
+	 * clock to use as a timer.
+	 */
+	if (chip->reserved)
+		xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK,
+			XWAY_STP_UPD_FPI, XWAY_STP_CON1);
+
+	return 0;
+}
+
+static int __devinit xway_stp_probe(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	const __be32 *shadow, *groups, *dsl, *phy;
+	struct xway_stp *chip;
+	struct clk *clk;
+	int ret = 0;
+
+	if (!res) {
+		dev_err(&pdev->dev, "failed to request STP resource\n");
+		return -ENOENT;
+	}
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->virt = devm_request_and_ioremap(&pdev->dev, res);
+	if (!chip->virt) {
+		dev_err(&pdev->dev, "failed to remap STP memory\n");
+		return -ENOMEM;
+	}
+	chip->gc.dev = &pdev->dev;
+	chip->gc.label = "stp-xway";
+	chip->gc.direction_output = xway_stp_dir_out;
+	chip->gc.set = xway_stp_set;
+	chip->gc.request = xway_stp_request;
+	chip->gc.base = -1;
+	chip->gc.owner = THIS_MODULE;
+
+	/* store the shadow value if one was passed by the devicetree */
+	shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL);
+	if (shadow)
+		chip->shadow = *shadow;
+
+	/* find out which gpio groups should be enabled */
+	groups = of_get_property(pdev->dev.of_node, "lantiq,groups", NULL);
+	if (groups)
+		chip->groups = *groups & XWAY_STP_GROUP_MASK;
+	else
+		chip->groups = XWAY_STP_GROUP0;
+	chip->gc.ngpio = fls(chip->groups) * 8;
+
+	/* find out which gpios are controlled by the dsl core */
+	dsl = of_get_property(pdev->dev.of_node, "lantiq,dsl", NULL);
+	if (dsl)
+		chip->dsl = *dsl & XWAY_STP_ADSL_MASK;
+
+	/* find out which gpios are controlled by the phys */
+	if (of_machine_is_compatible("lantiq,ar9") ||
+			of_machine_is_compatible("lantiq,gr9") ||
+			of_machine_is_compatible("lantiq,vr9")) {
+		phy = of_get_property(pdev->dev.of_node, "lantiq,phy1", NULL);
+		if (phy)
+			chip->phy1 = *phy & XWAY_STP_PHY_MASK;
+		phy = of_get_property(pdev->dev.of_node, "lantiq,phy2", NULL);
+		if (phy)
+			chip->phy2 = *phy & XWAY_STP_PHY_MASK;
+	}
+
+	/* check which edge trigger we should use, default to a falling edge */
+	if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL))
+		chip->edge = XWAY_STP_FALLING;
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Failed to get clock\n");
+		return PTR_ERR(clk);
+	}
+	clk_enable(clk);
+
+	ret = xway_stp_hw_init(chip);
+	if (!ret)
+		ret = gpiochip_add(&chip->gc);
+
+	if (!ret)
+		dev_info(&pdev->dev, "Init done\n");
+
+	return ret;
+}
+
+static const struct of_device_id xway_stp_match[] = {
+	{ .compatible = "lantiq,gpio-stp-xway" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xway_stp_match);
+
+static struct platform_driver xway_stp_driver = {
+	.probe = xway_stp_probe,
+	.driver = {
+		.name = "gpio-stp-xway",
+		.owner = THIS_MODULE,
+		.of_match_table = xway_stp_match,
+	},
+};
+
+int __init xway_stp_init(void)
+{
+	return platform_driver_register(&xway_stp_driver);
+}
+
+subsys_initcall(xway_stp_init);
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 09/14] GPIO: MIPS: lantiq: convert gpio-ebu to OF and move it to subsystem
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (4 preceding siblings ...)
  2012-05-04 12:18 ` [PATCH 08/14] GPIO: MIPS: lantiq: convert gpio-stp to OF and move it to subsystem John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 10/14] SERIAL: MIPS: lantiq: implement OF support John Crispin
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Grant Likely, linux-kernel

Implements OF support and moves the driver from arch/mips/lantiq/xway/ to the
gpio subsystem.

By attaching hardware latches to the External Bus Unit (EBU) on Lantiq SoC, it
is possible to create output only gpios. This driver configures a special
memory address, which when written to, outputs 16 bit to the latches.

This driver makes use of of_mm_gpio.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: linux-kernel@vger.kernel.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/lantiq/xway/Makefile   |    2 +-
 arch/mips/lantiq/xway/gpio_ebu.c |  126 ------------------------------
 drivers/gpio/Kconfig             |    8 ++
 drivers/gpio/Makefile            |    1 +
 drivers/gpio/gpio-mm-lantiq.c    |  157 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 167 insertions(+), 127 deletions(-)
 delete mode 100644 arch/mips/lantiq/xway/gpio_ebu.c
 create mode 100644 drivers/gpio/gpio-mm-lantiq.c

diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 9c5d69f..729ea9e 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 gpio_ebu.o
+obj-y := prom.o sysctrl.o clk.o reset.o dma.o
diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
deleted file mode 100644
index aae1717..0000000
--- a/arch/mips/lantiq/xway/gpio_ebu.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <lantiq_soc.h>
-
-/*
- * By attaching hardware latches to the EBU it is possible to create output
- * only gpios. This driver configures a special memory address, which when
- * written to outputs 16 bit to the latches.
- */
-
-#define LTQ_EBU_BUSCON	0x1e7ff		/* 16 bit access, slowest timing */
-#define LTQ_EBU_WP	0x80000000	/* write protect bit */
-
-/* we keep a shadow value of the last value written to the ebu */
-static int ltq_ebu_gpio_shadow = 0x0;
-static void __iomem *ltq_ebu_gpio_membase;
-
-static void ltq_ebu_apply(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ebu_lock, flags);
-	ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
-	*((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow;
-	ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
-	spin_unlock_irqrestore(&ebu_lock, flags);
-}
-
-static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	if (value)
-		ltq_ebu_gpio_shadow |= (1 << offset);
-	else
-		ltq_ebu_gpio_shadow &= ~(1 << offset);
-	ltq_ebu_apply();
-}
-
-static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset,
-	int value)
-{
-	ltq_ebu_set(chip, offset, value);
-
-	return 0;
-}
-
-static struct gpio_chip ltq_ebu_chip = {
-	.label = "ltq_ebu",
-	.direction_output = ltq_ebu_direction_output,
-	.set = ltq_ebu_set,
-	.base = 72,
-	.ngpio = 16,
-	.can_sleep = 1,
-	.owner = THIS_MODULE,
-};
-
-static int ltq_ebu_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get memory resource\n");
-		return -ENOENT;
-	}
-
-	res = devm_request_mem_region(&pdev->dev, res->start,
-		resource_size(res), dev_name(&pdev->dev));
-	if (!res) {
-		dev_err(&pdev->dev, "failed to request memory resource\n");
-		return -EBUSY;
-	}
-
-	ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start,
-		resource_size(res));
-	if (!ltq_ebu_gpio_membase) {
-		dev_err(&pdev->dev, "Failed to ioremap mem region\n");
-		return -ENOMEM;
-	}
-
-	/* grab the default shadow value passed form the platform code */
-	ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data;
-
-	/* tell the ebu controller which memory address we will be using */
-	ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1);
-
-	/* write protect the region */
-	ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
-
-	ret = gpiochip_add(&ltq_ebu_chip);
-	if (!ret)
-		ltq_ebu_apply();
-	return ret;
-}
-
-static struct platform_driver ltq_ebu_driver = {
-	.probe = ltq_ebu_probe,
-	.driver = {
-		.name = "ltq_ebu",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init ltq_ebu_init(void)
-{
-	int ret = platform_driver_register(&ltq_ebu_driver);
-
-	if (ret)
-		pr_info("ltq_ebu : Error registering platform driver!");
-	return ret;
-}
-
-postcore_initcall(ltq_ebu_init);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2ec6a3b..73da6bc 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -100,6 +100,14 @@ config GPIO_EP93XX
 	depends on ARCH_EP93XX
 	select GPIO_GENERIC
 
+config GPIO_MM_LANTIQ
+	bool "Lantiq Memory mapped GPIOs"
+	depends on LANTIQ && SOC_XWAY
+	help
+	  This enables support for memory mapped GPIOs on the External Bus Unit
+	  (EBU) found on Lantiq SoCs. The gpios are output only as they are
+	  created by attaching a 16bit latch to the bus.
+
 config GPIO_MPC5200
 	def_bool y
 	depends on PPC_MPC52xx
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ff85e12..239b290 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_GPIO_MC33880)	+= gpio-mc33880.o
 obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
+obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSM_V1)	+= gpio-msm-v1.o
diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c
new file mode 100644
index 0000000..9296801
--- /dev/null
+++ b/drivers/gpio/gpio-mm-lantiq.c
@@ -0,0 +1,157 @@
+/*
+ *  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>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <lantiq_soc.h>
+
+/*
+ * By attaching hardware latches to the EBU it is possible to create output
+ * only gpios. This driver configures a special memory address, which when
+ * written to outputs 16 bit to the latches.
+ */
+
+#define LTQ_EBU_BUSCON	0x1e7ff		/* 16 bit access, slowest timing */
+#define LTQ_EBU_WP	0x80000000	/* write protect bit */
+
+struct ltq_mm {
+	struct of_mm_gpio_chip mmchip;
+	u16 shadow;	/* shadow the latches state */
+};
+
+/*
+ * ltq_mm_apply - write the shadow value to the ebu address.
+ * @chip:     Pointer to our private data structure.
+ *
+ * Write the shadow value to the EBU to set the gpios. We need to set the
+ * global EBU lock to make sure that PCI/MTD dont break.
+ */
+static void ltq_mm_apply(struct ltq_mm *chip)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ebu_lock, flags);
+	ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
+	*((__u16 *)chip->mmchip.regs) = chip->shadow;
+	ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
+	spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+/*
+ * ltq_mm_set - gpio_chip->set - set gpios.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * Set the shadow value and call ltq_mm_apply.
+ */
+static void ltq_mm_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct ltq_mm *chip =
+		container_of(mm_gc, struct ltq_mm, mmchip);
+
+	if (value)
+		chip->shadow |= (1 << offset);
+	else
+		chip->shadow &= ~(1 << offset);
+	ltq_mm_apply(chip);
+}
+
+/*
+ * ltq_mm_dir_out - gpio_chip->dir_out - set gpio direction.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * Same as ltq_mm_set, always returns 0.
+ */
+static int ltq_mm_dir_out(struct gpio_chip *gc, unsigned offset, int value)
+{
+	ltq_mm_set(gc, offset, value);
+
+	return 0;
+}
+
+/*
+ * ltq_mm_save_regs - Set initial values of GPIO pins
+ * @mm_gc: pointer to memory mapped GPIO chip structure
+ */
+static void ltq_mm_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+	struct ltq_mm *chip =
+		container_of(mm_gc, struct ltq_mm, mmchip);
+
+	/* tell the ebu controller which memory address we will be using */
+	ltq_ebu_w32(CPHYSADDR(chip->mmchip.regs) | 0x1, LTQ_EBU_ADDRSEL1);
+
+	ltq_mm_apply(chip);
+}
+
+static int ltq_mm_probe(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct ltq_mm *chip;
+	const __be32 *shadow;
+	int ret = 0;
+
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get memory resource\n");
+		return -ENOENT;
+	}
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->mmchip.gc.ngpio = 16;
+	chip->mmchip.gc.label = "gpio-mm-ltq";
+	chip->mmchip.gc.direction_output = ltq_mm_dir_out;
+	chip->mmchip.gc.set = ltq_mm_set;
+	chip->mmchip.save_regs = ltq_mm_save_regs;
+
+	/* store the shadow value if one was passed by the devicetree */
+	shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL);
+	if (shadow)
+		chip->shadow = *shadow;
+
+	ret = of_mm_gpiochip_add(pdev->dev.of_node, &chip->mmchip);
+	if (ret)
+		kfree(chip);
+	return ret;
+}
+
+static const struct of_device_id ltq_mm_match[] = {
+	{ .compatible = "lantiq,gpio-mm" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_mm_match);
+
+static struct platform_driver ltq_mm_driver = {
+	.probe = ltq_mm_probe,
+	.driver = {
+		.name = "gpio-mm-ltq",
+		.owner = THIS_MODULE,
+		.of_match_table = ltq_mm_match,
+	},
+};
+
+static int __init ltq_mm_init(void)
+{
+	return platform_driver_register(&ltq_mm_driver);
+}
+
+subsys_initcall(ltq_mm_init);
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 10/14] SERIAL: MIPS: lantiq: implement OF support
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (5 preceding siblings ...)
  2012-05-04 12:18 ` [PATCH 09/14] GPIO: MIPS: lantiq: convert gpio-ebu " John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 11/14] watchdog: MIPS: lantiq: implement OF support and minor fixes John Crispin
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Alan Cox, linux-serial

Add devicetree and handling for our new clkdev clocks. The patch is rather
straightforward. .of_match_table is set and the 3 irqs are now loaded from the
devicetree.

This series converts the lantiq target to clkdev amongst other things. The
driver needs to handle two clocks now. The fpi bus clock used to derive the
divider and the clock gate needed on some socs to make the secondary port work.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Alan Cox <alan@linux.intel.com>
Cc: linux-serial@vger.kernel.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 drivers/tty/serial/lantiq.c |   83 ++++++++++++++++++++++++++----------------
 1 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 96c1cac..b5044fa 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -31,16 +31,19 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
-#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
 
 #include <lantiq_soc.h>
 
 #define PORT_LTQ_ASC		111
 #define MAXPORTS		2
 #define UART_DUMMY_UER_RX	1
-#define DRVNAME			"ltq_asc"
+#define DRVNAME			"lantiq,asc"
 #ifdef __BIG_ENDIAN
 #define LTQ_ASC_TBUF		(0x0020 + 3)
 #define LTQ_ASC_RBUF		(0x0024 + 3)
@@ -114,6 +117,9 @@ static DEFINE_SPINLOCK(ltq_asc_lock);
 
 struct ltq_uart_port {
 	struct uart_port	port;
+	/* clock used to derive divider */
+	struct clk		*fpiclk;
+	/* clock gating of the ASC core */
 	struct clk		*clk;
 	unsigned int		tx_irq;
 	unsigned int		rx_irq;
@@ -316,7 +322,9 @@ lqasc_startup(struct uart_port *port)
 	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 	int retval;
 
-	port->uartclk = clk_get_rate(ltq_port->clk);
+	if (ltq_port->clk)
+		clk_enable(ltq_port->clk);
+	port->uartclk = clk_get_rate(ltq_port->fpiclk);
 
 	ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
 		port->membase + LTQ_ASC_CLC);
@@ -382,6 +390,8 @@ lqasc_shutdown(struct uart_port *port)
 		port->membase + LTQ_ASC_RXFCON);
 	ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
 		port->membase + LTQ_ASC_TXFCON);
+	if (ltq_port->clk)
+		clk_disable(ltq_port->clk);
 }
 
 static void
@@ -630,7 +640,7 @@ lqasc_console_setup(struct console *co, char *options)
 
 	port = &ltq_port->port;
 
-	port->uartclk = clk_get_rate(ltq_port->clk);
+	port->uartclk = clk_get_rate(ltq_port->fpiclk);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -668,37 +678,32 @@ static struct uart_driver lqasc_reg = {
 static int __init
 lqasc_probe(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
 	struct ltq_uart_port *ltq_port;
 	struct uart_port *port;
-	struct resource *mmres, *irqres;
-	int tx_irq, rx_irq, err_irq;
-	struct clk *clk;
+	struct resource *mmres, irqres[3];
+	int line = 0;
 	int ret;
 
 	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!mmres || !irqres)
+	ret = of_irq_to_resource_table(node, irqres, 3);
+	if (!mmres || (ret != 3)) {
+		dev_err(&pdev->dev,
+			"failed to get memory/irq for serial port\n");
 		return -ENODEV;
+	}
 
-	if (pdev->id >= MAXPORTS)
-		return -EBUSY;
+	/* check if this is the console port */
+	if (mmres->start != LTQ_ASC1_BASE_ADDR)
+		line = 1;
 
-	if (lqasc_port[pdev->id] != NULL)
+	if (lqasc_port[line]) {
+		dev_err(&pdev->dev, "port %d already allocated\n", line);
 		return -EBUSY;
-
-	clk = clk_get(&pdev->dev, "fpi");
-	if (IS_ERR(clk)) {
-		pr_err("failed to get fpi clk\n");
-		return -ENOENT;
 	}
 
-	tx_irq = platform_get_irq_byname(pdev, "tx");
-	rx_irq = platform_get_irq_byname(pdev, "rx");
-	err_irq = platform_get_irq_byname(pdev, "err");
-	if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0))
-		return -ENODEV;
-
-	ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL);
+	ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port),
+			GFP_KERNEL);
 	if (!ltq_port)
 		return -ENOMEM;
 
@@ -709,19 +714,26 @@ lqasc_probe(struct platform_device *pdev)
 	port->ops	= &lqasc_pops;
 	port->fifosize	= 16;
 	port->type	= PORT_LTQ_ASC,
-	port->line	= pdev->id;
+	port->line	= line;
 	port->dev	= &pdev->dev;
-
-	port->irq	= tx_irq; /* unused, just to be backward-compatibe */
+	/* unused, just to be backward-compatible */
+	port->irq	= irqres[0].start;
 	port->mapbase	= mmres->start;
 
-	ltq_port->clk	= clk;
+	ltq_port->fpiclk = clk_get_fpi();
+	if (IS_ERR(ltq_port->fpiclk)) {
+		pr_err("failed to get fpi clk\n");
+		return -ENOENT;
+	}
 
-	ltq_port->tx_irq = tx_irq;
-	ltq_port->rx_irq = rx_irq;
-	ltq_port->err_irq = err_irq;
+	/* not all asc ports have clock gates, lets ignore the return code */
+	ltq_port->clk = clk_get(&pdev->dev, NULL);
 
-	lqasc_port[pdev->id] = ltq_port;
+	ltq_port->tx_irq = irqres[0].start;
+	ltq_port->rx_irq = irqres[1].start;
+	ltq_port->err_irq = irqres[2].start;
+
+	lqasc_port[line] = ltq_port;
 	platform_set_drvdata(pdev, ltq_port);
 
 	ret = uart_add_one_port(&lqasc_reg, port);
@@ -729,10 +741,17 @@ lqasc_probe(struct platform_device *pdev)
 	return ret;
 }
 
+static const struct of_device_id ltq_asc_match[] = {
+	{ .compatible = DRVNAME },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_asc_match);
+
 static struct platform_driver lqasc_driver = {
 	.driver		= {
 		.name	= DRVNAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = ltq_asc_match,
 	},
 };
 
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 11/14] watchdog: MIPS: lantiq: implement OF support and minor fixes
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (6 preceding siblings ...)
  2012-05-04 12:18 ` [PATCH 10/14] SERIAL: MIPS: lantiq: implement OF support John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 13:22   ` Wim Van Sebroeck
  2012-05-04 12:18   ` John Crispin
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, Wim Van Sebroeck, linux-watchdog

Add support for OF. We also apply the following small fixes
* reduce boiler plate by using devm_request_and_ioremap
* sane error path for the clock
* move LTQ_RST_CAUSE_WDTRST to a soc specific header file
* add a message to show that the driver loaded

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: linux-watchdog@vger.kernel.org

---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 arch/mips/include/asm/mach-lantiq/lantiq.h         |    1 -
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    2 +
 drivers/watchdog/lantiq_wdt.c                      |   56 +++++++++-----------
 3 files changed, 27 insertions(+), 32 deletions(-)

diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index c955e8d..161cce3 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -49,7 +49,6 @@ extern struct clk *clk_get_fpi(void);
 extern unsigned char ltq_boot_select(void);
 /* find out what caused the last cpu reset */
 extern int ltq_reset_cause(void);
-#define LTQ_RST_CAUSE_WDTRST	0x20
 
 #define IOPORT_RESOURCE_START	0x10000000
 #define IOPORT_RESOURCE_END	0xffffffff
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 b5a2acf..d0d40a4 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -133,6 +133,8 @@ extern __iomem void *ltq_cgu_membase;
 #define LTQ_WDT_BASE_ADDR	0x1F8803F0
 #define LTQ_WDT_SIZE		0x10
 
+#define LTQ_RST_CAUSE_WDTRST	0x20
+
 /* STP - serial to parallel conversion unit */
 #define LTQ_STP_BASE_ADDR	0x1E100BB0
 #define LTQ_STP_SIZE		0x40
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
index a9593a3..f66a9e6 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -13,14 +13,15 @@
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/platform_device.h>
+#include <linux/of_platform.h>
 #include <linux/uaccess.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <lantiq.h>
+#include <lantiq_soc.h>
 
-/* Section 3.4 of the datasheet
+/*
+ * Section 3.4 of the datasheet
  * The password sequence protects the WDT control register from unintended
  * write actions, which might cause malfunction of the WDT.
  *
@@ -70,7 +71,8 @@ ltq_wdt_disable(void)
 {
 	/* write the first password magic */
 	ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
-	/* write the second password magic with no config
+	/*
+	 * write the second password magic with no config
 	 * this turns the watchdog off
 	 */
 	ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR);
@@ -184,7 +186,7 @@ static struct miscdevice ltq_wdt_miscdev = {
 	.fops	= &ltq_wdt_fops,
 };
 
-static int __init
+static int __devinit
 ltq_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -194,28 +196,27 @@ ltq_wdt_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "cannot obtain I/O memory region");
 		return -ENOENT;
 	}
-	res = devm_request_mem_region(&pdev->dev, res->start,
-		resource_size(res), dev_name(&pdev->dev));
-	if (!res) {
-		dev_err(&pdev->dev, "cannot request I/O memory region");
-		return -EBUSY;
-	}
-	ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start,
-		resource_size(res));
+
+	ltq_wdt_membase = devm_request_and_ioremap(&pdev->dev, res);
 	if (!ltq_wdt_membase) {
 		dev_err(&pdev->dev, "cannot remap I/O memory region\n");
 		return -ENOMEM;
 	}
 
 	/* we do not need to enable the clock as it is always running */
-	clk = clk_get(&pdev->dev, "io");
-	WARN_ON(!clk);
+	clk = clk_get_fpi();
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Failed to get clock\n");
+		return -ENOENT;
+	}
 	ltq_io_region_clk_rate = clk_get_rate(clk);
 	clk_put(clk);
 
+	/* find out if the watchdog caused the last reboot */
 	if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST)
 		ltq_wdt_bootstatus = WDIOF_CARDRESET;
 
+	dev_info(&pdev->dev, "Init done\n");
 	return misc_register(&ltq_wdt_miscdev);
 }
 
@@ -227,33 +228,26 @@ ltq_wdt_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id ltq_wdt_match[] = {
+	{ .compatible = "lantiq,wdt" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_wdt_match);
 
 static struct platform_driver ltq_wdt_driver = {
+	.probe = ltq_wdt_probe,
 	.remove = __devexit_p(ltq_wdt_remove),
 	.driver = {
-		.name = "ltq_wdt",
+		.name = "wdt",
 		.owner = THIS_MODULE,
+		.of_match_table = ltq_wdt_match,
 	},
 };
 
-static int __init
-init_ltq_wdt(void)
-{
-	return platform_driver_probe(&ltq_wdt_driver, ltq_wdt_probe);
-}
-
-static void __exit
-exit_ltq_wdt(void)
-{
-	return platform_driver_unregister(&ltq_wdt_driver);
-}
-
-module_init(init_ltq_wdt);
-module_exit(exit_ltq_wdt);
+module_platform_driver(ltq_wdt_driver);
 
 module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
 MODULE_DESCRIPTION("Lantiq SoC Watchdog");
 MODULE_LICENSE("GPL");
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
@ 2012-05-04 12:18   ` John Crispin
  2012-05-04 12:18 ` [PATCH 05/14] MIPS: lantiq: implement support for clkdev api John Crispin
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, linux-mtd

Adds bindings for OF and make use of module_platform_driver for lantiq
based socs.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mtd@lists.infradead.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 drivers/mtd/maps/lantiq-flash.c |   69 ++++++++++++++-------------------------
 1 files changed, 25 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index b5401e3..aefa111 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -21,7 +21,6 @@
 #include <linux/mtd/physmap.h>
 
 #include <lantiq_soc.h>
-#include <lantiq_platform.h>
 
 /*
  * The NOR flash is connected to the same external bus unit (EBU) as PCI.
@@ -44,8 +43,9 @@ struct ltq_mtd {
 	struct map_info *map;
 };
 
-static char ltq_map_name[] = "ltq_nor";
-static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL };
+static const char ltq_map_name[] = "ltq_nor";
+static const char *ltq_probe_types[] __devinitconst = {
+					"cmdlinepart", "ofpart", NULL };
 
 static map_word
 ltq_read16(struct map_info *map, unsigned long adr)
@@ -108,12 +108,11 @@ ltq_copy_to(struct map_info *map, unsigned long to,
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
-static int __init
+static int __devinit
 ltq_mtd_probe(struct platform_device *pdev)
 {
-	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
+	struct mtd_part_parser_data ppdata;
 	struct ltq_mtd *ltq_mtd;
-	struct resource *res;
 	struct cfi_private *cfi;
 	int err;
 
@@ -122,28 +121,19 @@ ltq_mtd_probe(struct platform_device *pdev)
 
 	ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!ltq_mtd->res) {
-		dev_err(&pdev->dev, "failed to get memory resource");
+		dev_err(&pdev->dev, "failed to get memory resource\n");
 		err = -ENOENT;
 		goto err_out;
 	}
 
-	res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start,
-		resource_size(ltq_mtd->res), dev_name(&pdev->dev));
-	if (!ltq_mtd->res) {
-		dev_err(&pdev->dev, "failed to request mem resource");
-		err = -EBUSY;
-		goto err_out;
-	}
-
 	ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
-	ltq_mtd->map->phys = res->start;
-	ltq_mtd->map->size = resource_size(res);
-	ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev,
-				ltq_mtd->map->phys, ltq_mtd->map->size);
+	ltq_mtd->map->phys = ltq_mtd->res->start;
+	ltq_mtd->map->size = resource_size(ltq_mtd->res);
+	ltq_mtd->map->virt = devm_request_and_ioremap(&pdev->dev, ltq_mtd->res);
 	if (!ltq_mtd->map->virt) {
-		dev_err(&pdev->dev, "failed to ioremap!\n");
-		err = -ENOMEM;
-		goto err_free;
+		dev_err(&pdev->dev, "failed to remap mem resource\n");
+		err = -EBUSY;
+		goto err_out;
 	}
 
 	ltq_mtd->map->name = ltq_map_name;
@@ -169,9 +159,9 @@ ltq_mtd_probe(struct platform_device *pdev)
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 1;
 
-	err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, NULL,
-					ltq_mtd_data->parts,
-					ltq_mtd_data->nr_parts);
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types,
+					&ppdata, NULL, 0);
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		goto err_destroy;
@@ -204,32 +194,23 @@ ltq_mtd_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id ltq_mtd_match[] = {
+	{ .compatible = "lantiq,nor" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_mtd_match);
+
 static struct platform_driver ltq_mtd_driver = {
+	.probe = ltq_mtd_probe,
 	.remove = __devexit_p(ltq_mtd_remove),
 	.driver = {
-		.name = "ltq_nor",
+		.name = "ltq-nor",
 		.owner = THIS_MODULE,
+		.of_match_table = ltq_mtd_match,
 	},
 };
 
-static int __init
-init_ltq_mtd(void)
-{
-	int ret = platform_driver_probe(&ltq_mtd_driver, ltq_mtd_probe);
-
-	if (ret)
-		pr_err("ltq_nor: error registering platform driver");
-	return ret;
-}
-
-static void __exit
-exit_ltq_mtd(void)
-{
-	platform_driver_unregister(&ltq_mtd_driver);
-}
-
-module_init(init_ltq_mtd);
-module_exit(exit_ltq_mtd);
+module_platform_driver(ltq_mtd_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
@ 2012-05-04 12:18   ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-mtd, John Crispin

Adds bindings for OF and make use of module_platform_driver for lantiq
based socs.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mtd@lists.infradead.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 drivers/mtd/maps/lantiq-flash.c |   69 ++++++++++++++-------------------------
 1 files changed, 25 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index b5401e3..aefa111 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -21,7 +21,6 @@
 #include <linux/mtd/physmap.h>
 
 #include <lantiq_soc.h>
-#include <lantiq_platform.h>
 
 /*
  * The NOR flash is connected to the same external bus unit (EBU) as PCI.
@@ -44,8 +43,9 @@ struct ltq_mtd {
 	struct map_info *map;
 };
 
-static char ltq_map_name[] = "ltq_nor";
-static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL };
+static const char ltq_map_name[] = "ltq_nor";
+static const char *ltq_probe_types[] __devinitconst = {
+					"cmdlinepart", "ofpart", NULL };
 
 static map_word
 ltq_read16(struct map_info *map, unsigned long adr)
@@ -108,12 +108,11 @@ ltq_copy_to(struct map_info *map, unsigned long to,
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
-static int __init
+static int __devinit
 ltq_mtd_probe(struct platform_device *pdev)
 {
-	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
+	struct mtd_part_parser_data ppdata;
 	struct ltq_mtd *ltq_mtd;
-	struct resource *res;
 	struct cfi_private *cfi;
 	int err;
 
@@ -122,28 +121,19 @@ ltq_mtd_probe(struct platform_device *pdev)
 
 	ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!ltq_mtd->res) {
-		dev_err(&pdev->dev, "failed to get memory resource");
+		dev_err(&pdev->dev, "failed to get memory resource\n");
 		err = -ENOENT;
 		goto err_out;
 	}
 
-	res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start,
-		resource_size(ltq_mtd->res), dev_name(&pdev->dev));
-	if (!ltq_mtd->res) {
-		dev_err(&pdev->dev, "failed to request mem resource");
-		err = -EBUSY;
-		goto err_out;
-	}
-
 	ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
-	ltq_mtd->map->phys = res->start;
-	ltq_mtd->map->size = resource_size(res);
-	ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev,
-				ltq_mtd->map->phys, ltq_mtd->map->size);
+	ltq_mtd->map->phys = ltq_mtd->res->start;
+	ltq_mtd->map->size = resource_size(ltq_mtd->res);
+	ltq_mtd->map->virt = devm_request_and_ioremap(&pdev->dev, ltq_mtd->res);
 	if (!ltq_mtd->map->virt) {
-		dev_err(&pdev->dev, "failed to ioremap!\n");
-		err = -ENOMEM;
-		goto err_free;
+		dev_err(&pdev->dev, "failed to remap mem resource\n");
+		err = -EBUSY;
+		goto err_out;
 	}
 
 	ltq_mtd->map->name = ltq_map_name;
@@ -169,9 +159,9 @@ ltq_mtd_probe(struct platform_device *pdev)
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 1;
 
-	err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, NULL,
-					ltq_mtd_data->parts,
-					ltq_mtd_data->nr_parts);
+	ppdata.of_node = pdev->dev.of_node;
+	err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types,
+					&ppdata, NULL, 0);
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		goto err_destroy;
@@ -204,32 +194,23 @@ ltq_mtd_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id ltq_mtd_match[] = {
+	{ .compatible = "lantiq,nor" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ltq_mtd_match);
+
 static struct platform_driver ltq_mtd_driver = {
+	.probe = ltq_mtd_probe,
 	.remove = __devexit_p(ltq_mtd_remove),
 	.driver = {
-		.name = "ltq_nor",
+		.name = "ltq-nor",
 		.owner = THIS_MODULE,
+		.of_match_table = ltq_mtd_match,
 	},
 };
 
-static int __init
-init_ltq_mtd(void)
-{
-	int ret = platform_driver_probe(&ltq_mtd_driver, ltq_mtd_probe);
-
-	if (ret)
-		pr_err("ltq_nor: error registering platform driver");
-	return ret;
-}
-
-static void __exit
-exit_ltq_mtd(void)
-{
-	platform_driver_unregister(&ltq_mtd_driver);
-}
-
-module_init(init_ltq_mtd);
-module_exit(exit_ltq_mtd);
+module_platform_driver(ltq_mtd_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 13/14] NET: MIPS: lantiq: implement OF support inside the etop driver
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (8 preceding siblings ...)
  2012-05-04 12:18   ` John Crispin
@ 2012-05-04 12:18 ` John Crispin
  2012-05-04 12:18 ` [PATCH 14/14] MIPS: lantiq: remove orphaned code John Crispin
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin, netdev

This patch makes it possible to load the driver for the ETOP ethernet on
Lantiq SoC from a devicetree.

Additionally we convert the driver to using the new clkdev clock in favour of
the old ltq_pmu_*() api.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: netdev@vger.kernel.org
---
This patch is part of a series moving the mips/lantiq target to OF and clkdev
support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

 drivers/net/ethernet/lantiq_etop.c |   63 +++++++++++++++++++++++++++++------
 1 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 5dc9cbd..c0443d4 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -29,19 +29,22 @@
 #include <linux/tcp.h>
 #include <linux/skbuff.h>
 #include <linux/mm.h>
-#include <linux/platform_device.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/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 <xway_dma.h>
-#include <lantiq_platform.h>
 
 #define LTQ_ETOP_MDIO		0x11804
 #define MDIO_REQUEST		0x80000000
@@ -73,6 +76,7 @@
 #define ETOP_CGEN		0x800
 
 /* use 2 static channels for TX/RX */
+#define LTQ_DMA_CH0_INT		INT_NUM_IM2_IRL0
 #define LTQ_ETOP_TX_CHANNEL	1
 #define LTQ_ETOP_RX_CHANNEL	6
 #define IS_TX(x)		(x == LTQ_ETOP_TX_CHANNEL)
@@ -99,12 +103,17 @@ 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 clk *clk;
+	const void *mac;
+	int mii_mode;
+	int tx_irq;
+	int rx_irq;
+
 	struct ltq_etop_chan ch[MAX_DMA_CHAN];
 	int tx_free[MAX_DMA_CHAN >> 1];
 
@@ -239,7 +248,7 @@ ltq_etop_hw_exit(struct net_device *dev)
 	struct ltq_etop_priv *priv = netdev_priv(dev);
 	int i;
 
-	ltq_pmu_disable(PMU_PPE);
+	clk_disable(priv->clk);
 	for (i = 0; i < MAX_DMA_CHAN; i++)
 		if (IS_TX(i) || IS_RX(i))
 			ltq_etop_free_channel(dev, &priv->ch[i]);
@@ -251,9 +260,9 @@ 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);
 
-	switch (priv->pldata->mii_mode) {
+	switch (priv->mii_mode) {
 	case PHY_INTERFACE_MODE_RMII:
 		ltq_etop_w32_mask(ETOP_MII_MASK,
 			ETOP_MII_REVERSE, LTQ_ETOP_CFG);
@@ -266,7 +275,7 @@ ltq_etop_hw_init(struct net_device *dev)
 
 	default:
 		netdev_err(dev, "unknown mii mode %d\n",
-			priv->pldata->mii_mode);
+			priv->mii_mode);
 		return -ENOTSUPP;
 	}
 
@@ -395,7 +404,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");
@@ -643,7 +652,7 @@ ltq_etop_init(struct net_device *dev)
 		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");
 		random_ether_addr(mac.sa_data);
@@ -707,9 +716,12 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
 static int __init
 ltq_etop_probe(struct platform_device *pdev)
 {
+	struct device_node *node = pdev->dev.of_node;
 	struct net_device *dev;
 	struct ltq_etop_priv *priv;
 	struct resource *res;
+	struct clk *clk;
+	struct resource irqres[2];
 	int err;
 	int i;
 
@@ -737,6 +749,20 @@ ltq_etop_probe(struct platform_device *pdev)
 		goto err_out;
 	}
 
+	err = of_irq_to_resource_table(node, irqres, 2);
+	if (err != 2) {
+		dev_err(&pdev->dev, "not enough irqs defined\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Failed to get clock\n");
+		err = PTR_ERR(clk);
+		goto err_out;
+	}
+
 	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
 	if (!dev) {
 		err = -ENOMEM;
@@ -748,9 +774,15 @@ ltq_etop_probe(struct platform_device *pdev)
 	priv = netdev_priv(dev);
 	priv->res = res;
 	priv->pdev = pdev;
-	priv->pldata = dev_get_platdata(&pdev->dev);
 	priv->netdev = dev;
 	spin_lock_init(&priv->lock);
+	priv->tx_irq = irqres[0].start;
+	priv->rx_irq = irqres[1].start;
+	priv->mii_mode = of_get_phy_mode(node);
+	priv->mac = of_get_mac_address(node);
+	priv->clk = clk;
+	if (priv->mii_mode < 0)
+		priv->mii_mode = PHY_INTERFACE_MODE_MII;
 
 	for (i = 0; i < MAX_DMA_CHAN; i++) {
 		if (IS_TX(i))
@@ -779,21 +811,30 @@ static int __devexit
 ltq_etop_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+	struct ltq_etop_priv *priv = netdev_priv(dev);
 
 	if (dev) {
 		netif_tx_stop_all_queues(dev);
 		ltq_etop_hw_exit(dev);
 		ltq_etop_mdio_cleanup(dev);
+		clk_put(priv->clk);
 		unregister_netdev(dev);
 	}
 	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 = {
 	.remove = __devexit_p(ltq_etop_remove),
 	.driver = {
-		.name = "ltq_etop",
+		.name = "etop-xway",
 		.owner = THIS_MODULE,
+		.of_match_table = ltq_etop_match,
 	},
 };
 
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 14/14] MIPS: lantiq: remove orphaned code
  2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
                   ` (9 preceding siblings ...)
  2012-05-04 12:18 ` [PATCH 13/14] NET: MIPS: lantiq: implement OF support inside the etop driver John Crispin
@ 2012-05-04 12:18 ` John Crispin
  10 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 12:18 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, John Crispin

Now that all drivers are converted to OF we are able to remove some remaining
pieces of orphaned code.

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/include/asm/mach-lantiq/lantiq.h         |    6 --
 .../mips/include/asm/mach-lantiq/lantiq_platform.h |   53 -----------
 .../mips/include/asm/mach-lantiq/xway/lantiq_irq.h |   46 +----------
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   93 +-------------------
 arch/mips/lantiq/prom.c                            |    6 --
 arch/mips/lantiq/xway/sysctrl.c                    |   25 +----
 6 files changed, 7 insertions(+), 222 deletions(-)
 delete mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_platform.h

diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index 161cce3..1aaf265 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -27,9 +27,6 @@
 	ltq_w32_mask(x, y, ltq_ebu_membase + (z))
 extern __iomem void *ltq_ebu_membase;
 
-extern unsigned int ltq_get_cpu_ver(void);
-extern unsigned int ltq_get_soc_type(void);
-
 /* spinlock all ebu i/o */
 extern spinlock_t ebu_lock;
 
@@ -43,7 +40,6 @@ extern int clk_activate(struct clk *clk);
 extern void clk_deactivate(struct clk *clk);
 extern struct clk *clk_get_cpu(void);
 extern struct clk *clk_get_fpi(void);
-#define clk_get_io	clk_get_fpi
 
 /* find out what bootsource we have */
 extern unsigned char ltq_boot_select(void);
@@ -54,7 +50,5 @@ extern int ltq_reset_cause(void);
 #define IOPORT_RESOURCE_END	0xffffffff
 #define IOMEM_RESOURCE_START	0x10000000
 #define IOMEM_RESOURCE_END	0xffffffff
-#define LTQ_FLASH_START		0x10000000
-#define LTQ_FLASH_MAX		0x04000000
 
 #endif
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
deleted file mode 100644
index a305f1d..0000000
--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  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) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#ifndef _LANTIQ_PLATFORM_H__
-#define _LANTIQ_PLATFORM_H__
-
-#include <linux/mtd/partitions.h>
-#include <linux/socket.h>
-
-/* struct used to pass info to the pci core */
-enum {
-	PCI_CLOCK_INT = 0,
-	PCI_CLOCK_EXT
-};
-
-#define PCI_EXIN0	0x0001
-#define PCI_EXIN1	0x0002
-#define PCI_EXIN2	0x0004
-#define PCI_EXIN3	0x0008
-#define PCI_EXIN4	0x0010
-#define PCI_EXIN5	0x0020
-#define PCI_EXIN_MAX	6
-
-#define PCI_GNT1	0x0040
-#define PCI_GNT2	0x0080
-#define PCI_GNT3	0x0100
-#define PCI_GNT4	0x0200
-
-#define PCI_REQ1	0x0400
-#define PCI_REQ2	0x0800
-#define PCI_REQ3	0x1000
-#define PCI_REQ4	0x2000
-#define PCI_REQ_SHIFT	10
-#define PCI_REQ_MASK	0xf
-
-struct ltq_pci_data {
-	int clock;
-	int gpio;
-	int irq[16];
-};
-
-/* struct used to pass info to network drivers */
-struct ltq_eth_data {
-	struct sockaddr mac;
-	int mii_mode;
-};
-
-#endif
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 b4465a8..885a429 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -17,50 +17,6 @@
 #define INT_NUM_IM4_IRL0	(INT_NUM_IRQ0 + 128)
 #define INT_NUM_IM_OFFSET	(INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
 
-#define LTQ_ASC_TIR(x)		(INT_NUM_IM3_IRL0 + (x * 8))
-#define LTQ_ASC_RIR(x)		(INT_NUM_IM3_IRL0 + (x * 8) + 1)
-#define LTQ_ASC_EIR(x)		(INT_NUM_IM3_IRL0 + (x * 8) + 2)
-
-#define LTQ_ASC_ASE_TIR		INT_NUM_IM2_IRL0
-#define LTQ_ASC_ASE_RIR		(INT_NUM_IM2_IRL0 + 2)
-#define LTQ_ASC_ASE_EIR		(INT_NUM_IM2_IRL0 + 3)
-
-#define LTQ_SSC_TIR		(INT_NUM_IM0_IRL0 + 15)
-#define LTQ_SSC_RIR		(INT_NUM_IM0_IRL0 + 14)
-#define LTQ_SSC_EIR		(INT_NUM_IM0_IRL0 + 16)
-
-#define LTQ_MEI_DYING_GASP_INT	(INT_NUM_IM1_IRL0 + 21)
-#define LTQ_MEI_INT		(INT_NUM_IM1_IRL0 + 23)
-
-#define LTQ_TIMER6_INT		(INT_NUM_IM1_IRL0 + 23)
-#define LTQ_USB_INT		(INT_NUM_IM1_IRL0 + 22)
-#define LTQ_USB_OC_INT		(INT_NUM_IM4_IRL0 + 23)
-
-#define MIPS_CPU_TIMER_IRQ		7
-
-#define LTQ_DMA_CH0_INT		(INT_NUM_IM2_IRL0)
-#define LTQ_DMA_CH1_INT		(INT_NUM_IM2_IRL0 + 1)
-#define LTQ_DMA_CH2_INT		(INT_NUM_IM2_IRL0 + 2)
-#define LTQ_DMA_CH3_INT		(INT_NUM_IM2_IRL0 + 3)
-#define LTQ_DMA_CH4_INT		(INT_NUM_IM2_IRL0 + 4)
-#define LTQ_DMA_CH5_INT		(INT_NUM_IM2_IRL0 + 5)
-#define LTQ_DMA_CH6_INT		(INT_NUM_IM2_IRL0 + 6)
-#define LTQ_DMA_CH7_INT		(INT_NUM_IM2_IRL0 + 7)
-#define LTQ_DMA_CH8_INT		(INT_NUM_IM2_IRL0 + 8)
-#define LTQ_DMA_CH9_INT		(INT_NUM_IM2_IRL0 + 9)
-#define LTQ_DMA_CH10_INT	(INT_NUM_IM2_IRL0 + 10)
-#define LTQ_DMA_CH11_INT	(INT_NUM_IM2_IRL0 + 11)
-#define LTQ_DMA_CH12_INT	(INT_NUM_IM2_IRL0 + 25)
-#define LTQ_DMA_CH13_INT	(INT_NUM_IM2_IRL0 + 26)
-#define LTQ_DMA_CH14_INT	(INT_NUM_IM2_IRL0 + 27)
-#define LTQ_DMA_CH15_INT	(INT_NUM_IM2_IRL0 + 28)
-#define LTQ_DMA_CH16_INT	(INT_NUM_IM2_IRL0 + 29)
-#define LTQ_DMA_CH17_INT	(INT_NUM_IM2_IRL0 + 30)
-#define LTQ_DMA_CH18_INT	(INT_NUM_IM2_IRL0 + 16)
-#define LTQ_DMA_CH19_INT	(INT_NUM_IM2_IRL0 + 21)
-
-#define LTQ_PPE_MBOX_INT	(INT_NUM_IM2_IRL0 + 24)
-
-#define INT_NUM_IM4_IRL14	(INT_NUM_IM4_IRL0 + 14)
+#define MIPS_CPU_TIMER_IRQ	7
 
 #endif
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 d0d40a4..fb3e65f 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -44,11 +44,6 @@
 #define SOC_TYPE_VR9_2		0x05 /* v1.2 */
 #define SOC_TYPE_AMAZON_SE	0x06
 
-/* ASC0/1 - serial port */
-#define LTQ_ASC0_BASE_ADDR	0x1E100400
-#define LTQ_ASC1_BASE_ADDR	0x1E100C00
-#define LTQ_ASC_SIZE		0x400
-
 /* BOOT_SEL - find what boot media we have */
 #define BS_EXT_ROM		0x0
 #define BS_FLASH		0x1
@@ -68,23 +63,10 @@ extern __iomem void *ltq_cgu_membase;
  * during early_printk no ioremap is possible
  * lets use KSEG1 instead
  */
+#define LTQ_ASC1_BASE_ADDR	0x1E100C00
 #define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
 
-/* RCU - reset control unit */
-#define LTQ_RCU_BASE_ADDR	0x1F203000
-#define LTQ_RCU_SIZE		0x1000
-
-/* GPTU - general purpose timer unit */
-#define LTQ_GPTU_BASE_ADDR	0x18000300
-#define LTQ_GPTU_SIZE		0x100
-
 /* EBU - external bus unit */
-#define LTQ_EBU_GPIO_START	0x14000000
-#define LTQ_EBU_GPIO_SIZE	0x1000
-
-#define LTQ_EBU_BASE_ADDR	0x1E105300
-#define LTQ_EBU_SIZE		0x100
-
 #define LTQ_EBU_BUSCON0		0x0060
 #define LTQ_EBU_PCC_CON		0x0090
 #define LTQ_EBU_PCC_IEN		0x00A4
@@ -93,85 +75,12 @@ extern __iomem void *ltq_cgu_membase;
 #define LTQ_EBU_ADDRSEL1	0x0024
 #define EBU_WRDIS		0x80000000
 
-/* CGU - clock generation unit */
-#define LTQ_CGU_BASE_ADDR	0x1F103000
-#define LTQ_CGU_SIZE		0x1000
-
-/* ICU - interrupt control unit */
-#define LTQ_ICU_BASE_ADDR	0x1F880200
-#define LTQ_ICU_SIZE		0x100
-
-/* EIU - external interrupt unit */
-#define LTQ_EIU_BASE_ADDR	0x1F101000
-#define LTQ_EIU_SIZE		0x1000
-
-/* PMU - power management unit */
-#define LTQ_PMU_BASE_ADDR	0x1F102000
-#define LTQ_PMU_SIZE		0x1000
-
-#define PMU_DMA			0x0020
-#define PMU_USB			0x8041
-#define PMU_LED			0x0800
-#define PMU_GPT			0x1000
-#define PMU_PPE			0x2000
-#define PMU_FPI			0x4000
-#define PMU_SWITCH		0x10000000
-
-/* ETOP - ethernet */
-#define LTQ_ETOP_BASE_ADDR	0x1E180000
-#define LTQ_ETOP_SIZE		0x40000
-
-/* DMA */
-#define LTQ_DMA_BASE_ADDR	0x1E104100
-#define LTQ_DMA_SIZE		0x800
-
-/* PCI */
-#define PCI_CR_BASE_ADDR	0x1E105400
-#define PCI_CR_SIZE		0x400
-
 /* WDT */
-#define LTQ_WDT_BASE_ADDR	0x1F8803F0
-#define LTQ_WDT_SIZE		0x10
-
 #define LTQ_RST_CAUSE_WDTRST	0x20
 
-/* STP - serial to parallel conversion unit */
-#define LTQ_STP_BASE_ADDR	0x1E100BB0
-#define LTQ_STP_SIZE		0x40
-
-/* GPIO */
-#define LTQ_GPIO0_BASE_ADDR	0x1E100B10
-#define LTQ_GPIO1_BASE_ADDR	0x1E100B40
-#define LTQ_GPIO2_BASE_ADDR	0x1E100B70
-#define LTQ_GPIO_SIZE		0x30
-
-/* SSC */
-#define LTQ_SSC_BASE_ADDR	0x1e100800
-#define LTQ_SSC_SIZE		0x100
-
-/* MEI - dsl core */
-#define LTQ_MEI_BASE_ADDR	0x1E116000
-
-/* DEU - data encryption unit */
-#define LTQ_DEU_BASE_ADDR	0x1E103100
-
 /* MPS - multi processor unit (voice) */
 #define LTQ_MPS_BASE_ADDR	(KSEG1 + 0x1F107000)
 #define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
-/* request a non-gpio and set the PIO config */
-extern void ltq_pmu_enable(unsigned int module);
-extern void ltq_pmu_disable(unsigned int module);
-
-static inline int ltq_is_ar9(void)
-{
-	return (ltq_get_soc_type() == SOC_TYPE_AR9);
-}
-
-static inline int ltq_is_vr9(void)
-{
-	return (ltq_get_soc_type() == SOC_TYPE_VR9);
-}
-
 #endif /* CONFIG_SOC_TYPE_XWAY */
 #endif /* _LTQ_XWAY_H__ */
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 413ed53..d185e84 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -27,12 +27,6 @@ EXPORT_SYMBOL_GPL(ebu_lock);
  */
 static struct ltq_soc_info soc_info;
 
-unsigned int ltq_get_soc_type(void)
-{
-	return soc_info.type;
-}
-EXPORT_SYMBOL(ltq_get_soc_type);
-
 const char *get_system_type(void)
 {
 	return soc_info.sys_type;
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 3029139..02d2f15 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -42,6 +42,7 @@
 /* clock gates that we can en/disable */
 #define PMU_USB0_P	BIT(0)
 #define PMU_PCI		BIT(4)
+#define PMU_DMA		BIT(5)
 #define PMU_USB0	BIT(6)
 #define PMU_ASC0	BIT(7)
 #define PMU_EPHY	BIT(7)	/* ase */
@@ -49,7 +50,10 @@
 #define PMU_DFE		BIT(9)
 #define PMU_EBU		BIT(10)
 #define PMU_STP		BIT(11)
+#define PMU_GPT		BIT(12)
+#define PMU_PPE		BIT(13)
 #define PMU_AHBS	BIT(13) /* vr9 */
+#define PMU_FPI		BIT(14)
 #define PMU_AHBM	BIT(15)
 #define PMU_ASC1	BIT(17)
 #define PMU_PPE_QSB	BIT(18)
@@ -60,6 +64,7 @@
 #define PMU_PPE_DPLUS	BIT(24)
 #define PMU_USB1_P	BIT(26)
 #define PMU_USB1	BIT(27)
+#define PMU_SWITCH	BIT(28)
 #define PMU_PPE_TOP	BIT(29)
 #define PMU_GPHY	BIT(30)
 #define PMU_PCIE_CLK	BIT(31)
@@ -76,26 +81,6 @@ static void __iomem *pmu_membase;
 void __iomem *ltq_cgu_membase;
 void __iomem *ltq_ebu_membase;
 
-/* legacy function kept alive to ease clkdev transition */
-void ltq_pmu_enable(unsigned int module)
-{
-	int err = 1000000;
-
-	pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
-	do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
-
-	if (!err)
-		panic("activating PMU module failed!");
-}
-EXPORT_SYMBOL(ltq_pmu_enable);
-
-/* legacy function kept alive to ease clkdev transition */
-void ltq_pmu_disable(unsigned int module)
-{
-	pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
-}
-EXPORT_SYMBOL(ltq_pmu_disable);
-
 /* enable a hw clock */
 static int cgu_enable(struct clk *clk)
 {
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH 11/14] watchdog: MIPS: lantiq: implement OF support and minor fixes
  2012-05-04 12:18 ` [PATCH 11/14] watchdog: MIPS: lantiq: implement OF support and minor fixes John Crispin
@ 2012-05-04 13:22   ` Wim Van Sebroeck
  0 siblings, 0 replies; 48+ messages in thread
From: Wim Van Sebroeck @ 2012-05-04 13:22 UTC (permalink / raw)
  To: John Crispin; +Cc: Ralf Baechle, linux-mips, linux-watchdog

Hi,

> Add support for OF. We also apply the following small fixes
> * reduce boiler plate by using devm_request_and_ioremap
> * sane error path for the clock
> * move LTQ_RST_CAUSE_WDTRST to a soc specific header file
> * add a message to show that the driver loaded
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: Wim Van Sebroeck <wim@iguana.be>
> Cc: linux-watchdog@vger.kernel.org
> 
> ---
> This patch is part of a series moving the mips/lantiq target to OF and clkdev
> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

Acked-by: Wim Van Sebroeck <wim@iguana.be>

Kind regards,
Wim.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-04 12:18     ` John Crispin
  (?)
@ 2012-05-04 20:57     ` Stephen Warren
       [not found]       ` <4FA442B6.1020501-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
  -1 siblings, 1 reply; 48+ messages in thread
From: Stephen Warren @ 2012-05-04 20:57 UTC (permalink / raw)
  To: John Crispin; +Cc: Ralf Baechle, linux-mips, devicetree-discuss, Linus Walleij

On 05/04/2012 06:18 AM, John Crispin wrote:
> Implement support for pinctrl on lantiq/xway socs. The IO core found on these
> socs has the registers for pinctrl, pinconf and gpio mixed up in the same
> register range. As the gpio_chip handling is only a few lines, the driver also
> implements the gpio functionality. This obseletes the old gpio driver that was
> located in the arch/ folder.

Overall looks pretty reasonable. Some comments below.

There doesn't appear to be binding documentation. Something is needed to
describe how to instantiate the pinctrl driver, and the format of the
"pin configuration nodes". See
Documentation/devicetree/bindings/pinctrl/ for some examples.

> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig

>  config LANTIQ
...
> +	select PINCTRL

> diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig

>  config SOC_TYPE_XWAY
>  	bool
> +	select PINCTRL_XWAY

I'd be tempted to just select PINCTRL and PINCTRL_XWAY in the same place
under SOC_TYPE_XWAY.

> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile

>  obj-$(CONFIG_PINCTRL_TEGRA30)	+= pinctrl-tegra30.o
>  obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
>  obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
> +obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
> +obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o

It'd be nice to keep this sorted. I know COH901 isn't right now; I guess
I should send a patch for that.

> diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c

> +static const char *ltq_get_group_name(struct pinctrl_dev *pctrldev,
> +					 unsigned selector)
> +{
> +	struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
> +	if (selector >= info->num_grps)
> +		return NULL;

Most/all other drivers removed this range checking, instead relying on
the pinctrl core to not be buggy, and to respect the limits set out in
the pinctrl device descriptor.

> +static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,

> +				"%s mixes pins and groups settings\n",

s/mixes/muxes/.

> +int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,

> +	*map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL);

Check for failure.

> diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c

> +static int xway_pinconf_get(struct pinctrl_dev *pctldev,
...
> +	default:
> +		pr_err("%s: Invalid config param %04x\n",
> +					pinctrl_dev_get_name(pctldev), param);

Use dev_err instead of pr_err everywhere?

> +int irq_to_gpio(unsigned int gpio)
> +{
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL(irq_to_gpio);

Hasn't this function been removed? Perhaps it's only ARM that removed it.

> +static inline int xway_gpio_pin_count(void)
> +{
> +	if (of_machine_is_compatible("lantiq,ar9") ||
> +			of_machine_is_compatible("lantiq,gr9") ||
> +			of_machine_is_compatible("lantiq,vr9"))
> +		return 56;
> +	return 32;
> +}

What are those compatible values? Are they SoC variants or boards?

If they're SoC variants, then putting each of those compatible values
into the of_device_id table, and storing the per-SoC information in the
.data field is one way to go. Or, simply put this information into a
device-tree property.

If they're board names, this seems wrong; the code should be switching
on the SoC variant rather than the individual board. If a board happens
to hook up fewer of the pins that other boards that's fine, just don't
use them, but they still exist on the SoC and hence are reasonable to
represent in the driver.

> +static int __devinit pinmux_xway_probe(struct platform_device *pdev)

> +	for (i = 0; i < xway_chip.ngpio; i++) {
> +		/* strlen("ioXY") + 1 = 5 */
> +		char *name = devm_kzalloc(&pdev->dev, 5, GFP_KERNEL);
> +
> +		if (!name) {
> +			dev_err(&pdev->dev, "Failed to allocate pad name\n");
> +			return -ENOMEM;
> +		}
> +		snprintf(name, 5, "io%d", i);

Maybe time for a devm_kasprintf()?

> +	/* finish with registering the gpio range in pinctrl */
> +	xway_gpio_range.npins = xway_chip.ngpio;

Presumably, of_gpiochip_add() above dynamically allocates the base GPIO
number? If so, that value needs to be transferred into
xway_gpio_range.base too.

> +core_initcall_sync(pinmux_xway_init);

Does this need to be a core_initcall_sync; would a simple module_init()
do instead?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
       [not found]       ` <4FA442B6.1020501-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2012-05-04 21:29         ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-04 21:29 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

Hi Stephen,

Thanks for the comments
> Overall looks pretty reasonable. Some comments below.
>
> There doesn't appear to be binding documentation. Something is needed to
> describe how to instantiate the pinctrl driver, and the format of the
> "pin configuration nodes". See
> Documentation/devicetree/bindings/pinctrl/ for some examples.
>
I am expecting to send a V2 of the series. This will include a patch
with the binding documentation. I am still fine tuning the patch.
>> +int irq_to_gpio(unsigned int gpio)
>> +{
>> +	return -EINVAL;
>> +}
>> +EXPORT_SYMBOL(irq_to_gpio);
> Hasn't this function been removed? Perhaps it's only ARM that removed it.

We need it on MIPS. I am not sure if other arches need it.  OF does
obselete this function i guess.

>> +static inline int xway_gpio_pin_count(void)
>> +{
>> +	if (of_machine_is_compatible("lantiq,ar9") ||
>> +			of_machine_is_compatible("lantiq,gr9") ||
>> +			of_machine_is_compatible("lantiq,vr9"))
>> +		return 56;
>> +	return 32;
>> +}
> What are those compatible values? Are they SoC variants or boards?

These are the adsl, vdsl and no dsl SoCs. I don't really want this info
inside the DT as it is static. I will follow the .data variant you proposed.
> Presumably, of_gpiochip_add() above dynamically allocates the base GPIO
> number? If so, that value needs to be transferred into
> xway_gpio_range.base too.
>

Yes, i missed that one.


Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-04 12:18     ` John Crispin
@ 2012-05-08 13:21         ` Linus Walleij
  -1 siblings, 0 replies; 48+ messages in thread
From: Linus Walleij @ 2012-05-08 13:21 UTC (permalink / raw)
  To: John Crispin
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle

On Fri, May 4, 2012 at 2:18 PM, John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org> wrote:

> Implement support for pinctrl on lantiq/xway socs. The IO core found on these
> socs has the registers for pinctrl, pinconf and gpio mixed up in the same
> register range. As the gpio_chip handling is only a few lines, the driver also
> implements the gpio functionality. This obseletes the old gpio driver that was
> located in the arch/ folder.
>
> Signed-off-by: John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>

Overall this is looking very good and a positive development for these SoCs.

Nitpicking below.

> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -216,6 +216,7 @@ config MACH_JZ4740
>  config LANTIQ
>        bool "Lantiq based platforms"
>        select DMA_NONCOHERENT
> +       select PINCTRL

Shouldn't this be:
select PINCTRL
select PINCTRL_LANTIQ

?

> diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
> index 9485fe5..b86d942 100644
> --- a/arch/mips/lantiq/Kconfig
> +++ b/arch/mips/lantiq/Kconfig
> @@ -2,6 +2,7 @@ if LANTIQ
>
>  config SOC_TYPE_XWAY
>        bool
> +       select PINCTRL_XWAY
>        default n

OK...

> -obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o dma.o
> +obj-y := prom.o pmu.o ebu.o reset.o gpio_stp.o gpio_ebu.o dma.o

Yeah good riddance :-)

> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index f73a5ea..a19bac96 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
>        bool
>        select PINMUX
>
> +config PINCTRL_LANTIQ
> +       bool
> +       select PINMUX
> +       select PINCONF

depends on LANTIQ

?

I don't think anyone else is going to want to compile
this.

> +
>  config PINCTRL_MMP2
>        bool "MMP2 pin controller driver"
>        depends on ARCH_MMP
> @@ -83,6 +88,10 @@ config PINCTRL_COH901
>          COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
>          ports of 8 GPIO pins each.
>
> +config PINCTRL_XWAY
> +       bool
> +       select PINCTRL_LANTIQ

Shouldn't this be:

depends on SOC_TYPE_XWAY
depends on PINCTRL_LANTIQ

?

So LANTIQ selects it's pinctrl driver, the the xway SoC
selects its driver and they both are dependent on their
respective system.

> diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h

> +#define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)

Hm if we redefine this I start to wonder if this
should go into <linux/kernel.h>

No big deal, we can alsway refactor later.

> +#define LTQ_PINCONF_PACK(_param_, _arg_)       ((_param_) << 16 | (_arg_))
> +#define LTQ_PINCONF_UNPACK_PARAM(_conf_)       ((_conf_) >> 16)
> +#define LTQ_PINCONF_UNPACK_ARG(_conf_)         ((_conf_) & 0xffff)

No need to add _underscores_ around the macro parameters?
I've not seen any coding convention requiring this.

> +struct ltq_pinmux_info {
> +       struct device *dev;
> +       struct pinctrl_dev *pctrl;
> +
> +       /* we need to manage up to 5 padcontrolers */

controllers

> +       void __iomem *membase[5];
> +
> +       /* the handler for the subsystem */
> +       struct pinctrl_desc *desc;

It's a descriptor not a handler.

> +       /* we expose our pads to the subsystem */
> +       struct pinctrl_pin_desc *pads;
> +
> +       /* the number of pads. this varies between socs */
> +       unsigned int num_gpio;

Why not call it num_pads, atleast use the same name for
the array and the count.

> +       /* these are our multifunction pins */
> +       const struct ltq_mfp_pin *mfp;
> +       unsigned int num_mfp;
> +
> +       /* a number of multifunction pins can be grouped together */
> +       const struct ltq_pin_group *grps;
> +       unsigned int num_grps;
> +
> +       /* a mapping between function string and id */
> +       const struct ltq_pmx_func *funcs;
> +       unsigned int num_funcs;
> +
> +       /* the pinconf options that we are able to read from the DT */
> +       const struct ltq_cfg_param *params;
> +       unsigned int num_params;
> +
> +       /* soc specific callback used to apply muxing */
> +       int (*apply_mux)(struct pinctrl_dev *pctrldev, int pin, int mux);
> +};
>
> +enum ltq_pin_list {
> +       GPIO0 = 0,
> +       GPIO1,

Wait, this enum is called something ending with _list but it's not
a list, it's a pin. The enum is like a type, so should define the basic
unit we're dealing with, not a collection of such units, so rename it
"ltq_pin" simply.

You could also consider using:
#define GPIO0 0
#define GPIO1 1

etc like some other drivers do. (Your pick.)

> diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c

> +/* macros to help us access the registers */
> +#define gpio_getbit(m, r, p)   (!!(ltq_r32(m + r) & (1 << p)))
> +#define gpio_setbit(m, r, p)   ltq_w32_mask(0, (1 << p), m + r)
> +#define gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)

So what makes this arch so fantastic that it needs its own read/write functions?
(Just curious...)

You could replace (1 << p) with BIT(p) by using <linux/bitops.h>

> +       {"pci",         ARRAY_AND_SIZE(xrx_pci_grps)},
> +       {"ebu",         ARRAY_AND_SIZE(xrx_ebu_grps)},
> +};
> +
> +
> +
> +
> +
> +

You can never get enough whitespace :-)

Please trim it down...

> +/* ---------  pinconf related code --------- */
> +static int xway_pinconf_group_get(struct pinctrl_dev *pctldev,
> +                               unsigned group,
> +                               unsigned long *config)
> +{
> +       return -ENOTSUPP;
> +}
> +
> +static int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
> +                               unsigned group,
> +                               unsigned long config)
> +{
> +       return -ENOTSUPP;
> +}

Just don't define these function pointers and leave callbacks as NULL.
The pinctrl core should handle this and if it doesn't, patch the core
in pinconf.c.

> +static void xway_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +                                       struct seq_file *s, unsigned offset)
> +{
> +}
> +
> +static void xway_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
> +                                       struct seq_file *s, unsigned selector)
> +{
> +}

Just don't define them if you don't use them, leave pointers as NULL.

These are however good for verbose pretty-printing the pins/groups
hardware state.

> +static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
> +                               int pin, int mux)
> +{
> +       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
> +       int port = PORT(pin);
> +
> +       if (mux & 0x1)
> +               gpio_setbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
> +       else
> +               gpio_clearbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
> +
> +       if ((port == 3) && (mux & 0x2))
> +               gpio_setbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
> +       else if (mux & 0x2)
> +               gpio_setbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
> +       else if (port == 3)
> +               gpio_clearbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
> +       else
> +               gpio_clearbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
> +
> +       return 0;
> +}

Please introduce some #defines for the magic numbers used above:

0x1, 3, 0x2, 3, etc so we can easily figure out what's going on.

> +static struct ltq_pinmux_info xway_info = {
> +       .mfp            = xway_mfp,
> +       .desc           = &xway_pctrl_desc,
> +       .apply_mux      = xway_mux_apply,
> +       .params         = xway_cfg_params,
> +       .num_params     = ARRAY_SIZE(xway_cfg_params),
> +};
> +
> +
> +
> +

Whitespacey...

> +/* ---------  gpio_chip related code --------- */
> +
> +int gpio_to_irq(unsigned int gpio)
> +{
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(gpio_to_irq);
> +
> +int irq_to_gpio(unsigned int gpio)
> +{
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(irq_to_gpio);

Can't you just leave them undefined?

> +static struct gpio_chip xway_chip = {
> +       .label = "gpio-xway",
> +       .direction_input = xway_gpio_dir_in,
> +       .direction_output = xway_gpio_dir_out,
> +       .get = xway_gpio_get,
> +       .set = xway_gpio_set,
> +       .request = xway_gpio_req,
> +       .free = xway_gpio_free,
> +       .base = 0,
> +};
> +
> +
> +
> +

Whitespace.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-08 13:21         ` Linus Walleij
  0 siblings, 0 replies; 48+ messages in thread
From: Linus Walleij @ 2012-05-08 13:21 UTC (permalink / raw)
  To: John Crispin; +Cc: Ralf Baechle, linux-mips, devicetree-discuss, Stephen Warren

On Fri, May 4, 2012 at 2:18 PM, John Crispin <blogic@openwrt.org> wrote:

> Implement support for pinctrl on lantiq/xway socs. The IO core found on these
> socs has the registers for pinctrl, pinconf and gpio mixed up in the same
> register range. As the gpio_chip handling is only a few lines, the driver also
> implements the gpio functionality. This obseletes the old gpio driver that was
> located in the arch/ folder.
>
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Stephen Warren <swarren@wwwdotorg.org>

Overall this is looking very good and a positive development for these SoCs.

Nitpicking below.

> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -216,6 +216,7 @@ config MACH_JZ4740
>  config LANTIQ
>        bool "Lantiq based platforms"
>        select DMA_NONCOHERENT
> +       select PINCTRL

Shouldn't this be:
select PINCTRL
select PINCTRL_LANTIQ

?

> diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
> index 9485fe5..b86d942 100644
> --- a/arch/mips/lantiq/Kconfig
> +++ b/arch/mips/lantiq/Kconfig
> @@ -2,6 +2,7 @@ if LANTIQ
>
>  config SOC_TYPE_XWAY
>        bool
> +       select PINCTRL_XWAY
>        default n

OK...

> -obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o dma.o
> +obj-y := prom.o pmu.o ebu.o reset.o gpio_stp.o gpio_ebu.o dma.o

Yeah good riddance :-)

> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index f73a5ea..a19bac96 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
>        bool
>        select PINMUX
>
> +config PINCTRL_LANTIQ
> +       bool
> +       select PINMUX
> +       select PINCONF

depends on LANTIQ

?

I don't think anyone else is going to want to compile
this.

> +
>  config PINCTRL_MMP2
>        bool "MMP2 pin controller driver"
>        depends on ARCH_MMP
> @@ -83,6 +88,10 @@ config PINCTRL_COH901
>          COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
>          ports of 8 GPIO pins each.
>
> +config PINCTRL_XWAY
> +       bool
> +       select PINCTRL_LANTIQ

Shouldn't this be:

depends on SOC_TYPE_XWAY
depends on PINCTRL_LANTIQ

?

So LANTIQ selects it's pinctrl driver, the the xway SoC
selects its driver and they both are dependent on their
respective system.

> diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h

> +#define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)

Hm if we redefine this I start to wonder if this
should go into <linux/kernel.h>

No big deal, we can alsway refactor later.

> +#define LTQ_PINCONF_PACK(_param_, _arg_)       ((_param_) << 16 | (_arg_))
> +#define LTQ_PINCONF_UNPACK_PARAM(_conf_)       ((_conf_) >> 16)
> +#define LTQ_PINCONF_UNPACK_ARG(_conf_)         ((_conf_) & 0xffff)

No need to add _underscores_ around the macro parameters?
I've not seen any coding convention requiring this.

> +struct ltq_pinmux_info {
> +       struct device *dev;
> +       struct pinctrl_dev *pctrl;
> +
> +       /* we need to manage up to 5 padcontrolers */

controllers

> +       void __iomem *membase[5];
> +
> +       /* the handler for the subsystem */
> +       struct pinctrl_desc *desc;

It's a descriptor not a handler.

> +       /* we expose our pads to the subsystem */
> +       struct pinctrl_pin_desc *pads;
> +
> +       /* the number of pads. this varies between socs */
> +       unsigned int num_gpio;

Why not call it num_pads, atleast use the same name for
the array and the count.

> +       /* these are our multifunction pins */
> +       const struct ltq_mfp_pin *mfp;
> +       unsigned int num_mfp;
> +
> +       /* a number of multifunction pins can be grouped together */
> +       const struct ltq_pin_group *grps;
> +       unsigned int num_grps;
> +
> +       /* a mapping between function string and id */
> +       const struct ltq_pmx_func *funcs;
> +       unsigned int num_funcs;
> +
> +       /* the pinconf options that we are able to read from the DT */
> +       const struct ltq_cfg_param *params;
> +       unsigned int num_params;
> +
> +       /* soc specific callback used to apply muxing */
> +       int (*apply_mux)(struct pinctrl_dev *pctrldev, int pin, int mux);
> +};
>
> +enum ltq_pin_list {
> +       GPIO0 = 0,
> +       GPIO1,

Wait, this enum is called something ending with _list but it's not
a list, it's a pin. The enum is like a type, so should define the basic
unit we're dealing with, not a collection of such units, so rename it
"ltq_pin" simply.

You could also consider using:
#define GPIO0 0
#define GPIO1 1

etc like some other drivers do. (Your pick.)

> diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c

> +/* macros to help us access the registers */
> +#define gpio_getbit(m, r, p)   (!!(ltq_r32(m + r) & (1 << p)))
> +#define gpio_setbit(m, r, p)   ltq_w32_mask(0, (1 << p), m + r)
> +#define gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)

So what makes this arch so fantastic that it needs its own read/write functions?
(Just curious...)

You could replace (1 << p) with BIT(p) by using <linux/bitops.h>

> +       {"pci",         ARRAY_AND_SIZE(xrx_pci_grps)},
> +       {"ebu",         ARRAY_AND_SIZE(xrx_ebu_grps)},
> +};
> +
> +
> +
> +
> +
> +

You can never get enough whitespace :-)

Please trim it down...

> +/* ---------  pinconf related code --------- */
> +static int xway_pinconf_group_get(struct pinctrl_dev *pctldev,
> +                               unsigned group,
> +                               unsigned long *config)
> +{
> +       return -ENOTSUPP;
> +}
> +
> +static int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
> +                               unsigned group,
> +                               unsigned long config)
> +{
> +       return -ENOTSUPP;
> +}

Just don't define these function pointers and leave callbacks as NULL.
The pinctrl core should handle this and if it doesn't, patch the core
in pinconf.c.

> +static void xway_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +                                       struct seq_file *s, unsigned offset)
> +{
> +}
> +
> +static void xway_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
> +                                       struct seq_file *s, unsigned selector)
> +{
> +}

Just don't define them if you don't use them, leave pointers as NULL.

These are however good for verbose pretty-printing the pins/groups
hardware state.

> +static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
> +                               int pin, int mux)
> +{
> +       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
> +       int port = PORT(pin);
> +
> +       if (mux & 0x1)
> +               gpio_setbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
> +       else
> +               gpio_clearbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
> +
> +       if ((port == 3) && (mux & 0x2))
> +               gpio_setbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
> +       else if (mux & 0x2)
> +               gpio_setbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
> +       else if (port == 3)
> +               gpio_clearbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
> +       else
> +               gpio_clearbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
> +
> +       return 0;
> +}

Please introduce some #defines for the magic numbers used above:

0x1, 3, 0x2, 3, etc so we can easily figure out what's going on.

> +static struct ltq_pinmux_info xway_info = {
> +       .mfp            = xway_mfp,
> +       .desc           = &xway_pctrl_desc,
> +       .apply_mux      = xway_mux_apply,
> +       .params         = xway_cfg_params,
> +       .num_params     = ARRAY_SIZE(xway_cfg_params),
> +};
> +
> +
> +
> +

Whitespacey...

> +/* ---------  gpio_chip related code --------- */
> +
> +int gpio_to_irq(unsigned int gpio)
> +{
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(gpio_to_irq);
> +
> +int irq_to_gpio(unsigned int gpio)
> +{
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(irq_to_gpio);

Can't you just leave them undefined?

> +static struct gpio_chip xway_chip = {
> +       .label = "gpio-xway",
> +       .direction_input = xway_gpio_dir_in,
> +       .direction_output = xway_gpio_dir_out,
> +       .get = xway_gpio_get,
> +       .set = xway_gpio_set,
> +       .request = xway_gpio_req,
> +       .free = xway_gpio_free,
> +       .base = 0,
> +};
> +
> +
> +
> +

Whitespace.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-08 13:21         ` Linus Walleij
@ 2012-05-08 14:12             ` John Crispin
  -1 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 14:12 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle

Hi Linus,

Thanks. I will fold your comments with Stephen's into a V2 and resend it.

> Shouldn't this be:
>
> depends on SOC_TYPE_XWAY
> depends on PINCTRL_LANTIQ
>
> ?
>
> So LANTIQ selects it's pinctrl driver, the the xway SoC
> selects its driver and they both are dependent on their
> respective system.
>
The whole select/depends part is broken. I will clean this up properly

>> diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
>> +#define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)
I was actually considering to drop this. Having a "," inside a macro is
a bit ugly.
It leads to the calling code invoking the function with N-1 parameters,
although the function takes N parameters. I find this a bit
confusing/inconsistent.


>> +/* macros to help us access the registers */
>> +#define gpio_getbit(m, r, p)   (!!(ltq_r32(m + r) & (1 << p)))
>> +#define gpio_setbit(m, r, p)   ltq_w32_mask(0, (1 << p), m + r)
>> +#define gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)
> So what makes this arch so fantastic that it needs its own read/write functions?
> (Just curious...)
Nothing. Its a legacy macro from a few years ago when I first added
lantiq support inside openwrt. I personally like the macro. I use it
wherever I access lantiq registers.
When accessing generic memory ranges, as in the nand driver, I use
writeb() and co.

Matter of taste really. I would prefer to keep it this way if there are
no guidelines against it.

>> +/* ---------  gpio_chip related code --------- */
>> +
>> +int gpio_to_irq(unsigned int gpio)
>> +{
>> +       return -EINVAL;
>> +}
>> +EXPORT_SYMBOL(gpio_to_irq);
>> +
>> +int irq_to_gpio(unsigned int gpio)
>> +{
>> +       return -EINVAL;
>> +}
>> +EXPORT_SYMBOL(irq_to_gpio);
> Can't you just leave them undefined?

I just checked how ARM does it. They use
   arch/arm/include/asm/gpio.h

Let me talk to Ralf about this and make a MIPS version of said header file.

Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-08 14:12             ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 14:12 UTC (permalink / raw)
  To: Linus Walleij; +Cc: linux-mips, devicetree-discuss, Ralf Baechle

Hi Linus,

Thanks. I will fold your comments with Stephen's into a V2 and resend it.

> Shouldn't this be:
>
> depends on SOC_TYPE_XWAY
> depends on PINCTRL_LANTIQ
>
> ?
>
> So LANTIQ selects it's pinctrl driver, the the xway SoC
> selects its driver and they both are dependent on their
> respective system.
>
The whole select/depends part is broken. I will clean this up properly

>> diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
>> +#define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)
I was actually considering to drop this. Having a "," inside a macro is
a bit ugly.
It leads to the calling code invoking the function with N-1 parameters,
although the function takes N parameters. I find this a bit
confusing/inconsistent.


>> +/* macros to help us access the registers */
>> +#define gpio_getbit(m, r, p)   (!!(ltq_r32(m + r) & (1 << p)))
>> +#define gpio_setbit(m, r, p)   ltq_w32_mask(0, (1 << p), m + r)
>> +#define gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)
> So what makes this arch so fantastic that it needs its own read/write functions?
> (Just curious...)
Nothing. Its a legacy macro from a few years ago when I first added
lantiq support inside openwrt. I personally like the macro. I use it
wherever I access lantiq registers.
When accessing generic memory ranges, as in the nand driver, I use
writeb() and co.

Matter of taste really. I would prefer to keep it this way if there are
no guidelines against it.

>> +/* ---------  gpio_chip related code --------- */
>> +
>> +int gpio_to_irq(unsigned int gpio)
>> +{
>> +       return -EINVAL;
>> +}
>> +EXPORT_SYMBOL(gpio_to_irq);
>> +
>> +int irq_to_gpio(unsigned int gpio)
>> +{
>> +       return -EINVAL;
>> +}
>> +EXPORT_SYMBOL(irq_to_gpio);
> Can't you just leave them undefined?

I just checked how ARM does it. They use
   arch/arm/include/asm/gpio.h

Let me talk to Ralf about this and make a MIPS version of said header file.

Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-08 13:21         ` Linus Walleij
@ 2012-05-08 15:28             ` Stephen Warren
  -1 siblings, 0 replies; 48+ messages in thread
From: Stephen Warren @ 2012-05-08 15:28 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle

On 05/08/2012 07:21 AM, Linus Walleij wrote:
> On Fri, May 4, 2012 at 2:18 PM, John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org> wrote:
> 
>> Implement support for pinctrl on lantiq/xway socs. The IO core found on these
>> socs has the registers for pinctrl, pinconf and gpio mixed up in the same
>> register range. As the gpio_chip handling is only a few lines, the driver also
>> implements the gpio functionality. This obseletes the old gpio driver that was
>> located in the arch/ folder.
...
>> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
>> index f73a5ea..a19bac96 100644
>> --- a/drivers/pinctrl/Kconfig
>> +++ b/drivers/pinctrl/Kconfig
>> @@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
>>        bool
>>        select PINMUX
>>
>> +config PINCTRL_LANTIQ
>> +       bool
>> +       select PINMUX
>> +       select PINCONF
> 
> depends on LANTIQ
> 
> ?
> 
> I don't think anyone else is going to want to compile
> this.

This Kconfig option is selected by the ARCH Kconfig, so only selected at
the right time. The user won't get prompted for it since there's no
string after "bool". I think this is OK. Tegra's pinctrl Kconfig option
doesn't have any "depends ARCH_TEGRA" here either, although I note that
many other pinctrl drivers do.

>>  config PINCTRL_MMP2
>>        bool "MMP2 pin controller driver"
>>        depends on ARCH_MMP
>> @@ -83,6 +88,10 @@ config PINCTRL_COH901
>>          COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
>>          ports of 8 GPIO pins each.
>>
>> +config PINCTRL_XWAY
>> +       bool
>> +       select PINCTRL_LANTIQ
> 
> Shouldn't this be:
> 
> depends on SOC_TYPE_XWAY

Maybe, but see comments above.

> depends on PINCTRL_LANTIQ

Selecting PINCTRL_LANTIQ seems more appropriate; the ARCH Kconfig just
selects PINCTRL_XWAY when appropriate, and that then selects anything it
depends on.

(IIRC, the driver for SOC_TYPE_XWAY uses the driver for LANTIQ, not the
other way around?)

> So LANTIQ selects it's pinctrl driver, the the xway SoC
> selects its driver and they both are dependent on their
> respective system.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-08 15:28             ` Stephen Warren
  0 siblings, 0 replies; 48+ messages in thread
From: Stephen Warren @ 2012-05-08 15:28 UTC (permalink / raw)
  To: Linus Walleij; +Cc: John Crispin, Ralf Baechle, linux-mips, devicetree-discuss

On 05/08/2012 07:21 AM, Linus Walleij wrote:
> On Fri, May 4, 2012 at 2:18 PM, John Crispin <blogic@openwrt.org> wrote:
> 
>> Implement support for pinctrl on lantiq/xway socs. The IO core found on these
>> socs has the registers for pinctrl, pinconf and gpio mixed up in the same
>> register range. As the gpio_chip handling is only a few lines, the driver also
>> implements the gpio functionality. This obseletes the old gpio driver that was
>> located in the arch/ folder.
...
>> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
>> index f73a5ea..a19bac96 100644
>> --- a/drivers/pinctrl/Kconfig
>> +++ b/drivers/pinctrl/Kconfig
>> @@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
>>        bool
>>        select PINMUX
>>
>> +config PINCTRL_LANTIQ
>> +       bool
>> +       select PINMUX
>> +       select PINCONF
> 
> depends on LANTIQ
> 
> ?
> 
> I don't think anyone else is going to want to compile
> this.

This Kconfig option is selected by the ARCH Kconfig, so only selected at
the right time. The user won't get prompted for it since there's no
string after "bool". I think this is OK. Tegra's pinctrl Kconfig option
doesn't have any "depends ARCH_TEGRA" here either, although I note that
many other pinctrl drivers do.

>>  config PINCTRL_MMP2
>>        bool "MMP2 pin controller driver"
>>        depends on ARCH_MMP
>> @@ -83,6 +88,10 @@ config PINCTRL_COH901
>>          COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
>>          ports of 8 GPIO pins each.
>>
>> +config PINCTRL_XWAY
>> +       bool
>> +       select PINCTRL_LANTIQ
> 
> Shouldn't this be:
> 
> depends on SOC_TYPE_XWAY

Maybe, but see comments above.

> depends on PINCTRL_LANTIQ

Selecting PINCTRL_LANTIQ seems more appropriate; the ARCH Kconfig just
selects PINCTRL_XWAY when appropriate, and that then selects anything it
depends on.

(IIRC, the driver for SOC_TYPE_XWAY uses the driver for LANTIQ, not the
other way around?)

> So LANTIQ selects it's pinctrl driver, the the xway SoC
> selects its driver and they both are dependent on their
> respective system.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-08 15:28             ` Stephen Warren
@ 2012-05-08 15:39                 ` John Crispin
  -1 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 15:39 UTC (permalink / raw)
  To: Stephen Warren
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle

>> I don't think anyone else is going to want to compile
>> this.
>
> This Kconfig option is selected by the ARCH Kconfig, so only selected at
> the right time. The user won't get prompted for it since there's no
> string after "bool". I think this is OK. Tegra's pinctrl Kconfig option
> doesn't have any "depends ARCH_TEGRA" here either, although I note that
> many other pinctrl drivers do.

Hi,

I guess it makes it more apparent, that the symbol is specific to a
arch/soc. Tegra is a well known SoC, so its easy to figure out what the
codes purpose is. Other files might not be that easy to guess.

For the Lantiq SoC to function normally we need to always load these
drivers. PINTCTRL_LANTIQ has some generic functions and
PINTCTRL_LANTIQ_XWAY holds the code specific to the XWAY SoC. (i have a
patch in the local queue to add FALCON SoC support, giving
PINTCTRL_LANTIQ 2 users)

How about we do the following.

config LANTIQ
	select PINCTRL

config PINCTRL_LANTIQ
	def_bool y
	depends on LANTIQ

config PINCTRL_LANTIQ_XWAY
	def_bool y
	depends on SOC_TYPE_XWAY

This would auto select the right symbols, have all the dependency logic
in 1 place and reduce the size of arch/mips/lantiq/Kconfig

Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-08 15:39                 ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 15:39 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Linus Walleij, linux-mips, devicetree-discuss, Ralf Baechle

>> I don't think anyone else is going to want to compile
>> this.
>
> This Kconfig option is selected by the ARCH Kconfig, so only selected at
> the right time. The user won't get prompted for it since there's no
> string after "bool". I think this is OK. Tegra's pinctrl Kconfig option
> doesn't have any "depends ARCH_TEGRA" here either, although I note that
> many other pinctrl drivers do.

Hi,

I guess it makes it more apparent, that the symbol is specific to a
arch/soc. Tegra is a well known SoC, so its easy to figure out what the
codes purpose is. Other files might not be that easy to guess.

For the Lantiq SoC to function normally we need to always load these
drivers. PINTCTRL_LANTIQ has some generic functions and
PINTCTRL_LANTIQ_XWAY holds the code specific to the XWAY SoC. (i have a
patch in the local queue to add FALCON SoC support, giving
PINTCTRL_LANTIQ 2 users)

How about we do the following.

config LANTIQ
	select PINCTRL

config PINCTRL_LANTIQ
	def_bool y
	depends on LANTIQ

config PINCTRL_LANTIQ_XWAY
	def_bool y
	depends on SOC_TYPE_XWAY

This would auto select the right symbols, have all the dependency logic
in 1 place and reduce the size of arch/mips/lantiq/Kconfig

Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-08 15:39                 ` John Crispin
@ 2012-05-08 15:51                     ` Stephen Warren
  -1 siblings, 0 replies; 48+ messages in thread
From: Stephen Warren @ 2012-05-08 15:51 UTC (permalink / raw)
  To: John Crispin
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle

On 05/08/2012 09:39 AM, John Crispin wrote:
>>> I don't think anyone else is going to want to compile
>>> this.
>>
>> This Kconfig option is selected by the ARCH Kconfig, so only selected at
>> the right time. The user won't get prompted for it since there's no
>> string after "bool". I think this is OK. Tegra's pinctrl Kconfig option
>> doesn't have any "depends ARCH_TEGRA" here either, although I note that
>> many other pinctrl drivers do.
> 
> Hi,
> 
> I guess it makes it more apparent, that the symbol is specific to a
> arch/soc. Tegra is a well known SoC, so its easy to figure out what the
> codes purpose is. Other files might not be that easy to guess.
> 
> For the Lantiq SoC to function normally we need to always load these
> drivers. PINTCTRL_LANTIQ has some generic functions and
> PINTCTRL_LANTIQ_XWAY holds the code specific to the XWAY SoC. (i have a
> patch in the local queue to add FALCON SoC support, giving
> PINTCTRL_LANTIQ 2 users)
> 
> How about we do the following.
> 
> config LANTIQ
> 	select PINCTRL
> 
> config PINCTRL_LANTIQ
> 	def_bool y
> 	depends on LANTIQ
> 
> config PINCTRL_LANTIQ_XWAY
> 	def_bool y
> 	depends on SOC_TYPE_XWAY
> 
> This would auto select the right symbols, have all the dependency logic
> in 1 place and reduce the size of arch/mips/lantiq/Kconfig

Is it useful to build a kernel for XWAY without pinctrl, once the driver
is there? That's the main difference between arch/mips/lantiq/Kconfig
selecting PINCTRL_LANTIQ_XWAY vs that being a def_bool, and hence
allowing the user to deselect it.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-08 15:51                     ` Stephen Warren
  0 siblings, 0 replies; 48+ messages in thread
From: Stephen Warren @ 2012-05-08 15:51 UTC (permalink / raw)
  To: John Crispin; +Cc: Linus Walleij, linux-mips, devicetree-discuss, Ralf Baechle

On 05/08/2012 09:39 AM, John Crispin wrote:
>>> I don't think anyone else is going to want to compile
>>> this.
>>
>> This Kconfig option is selected by the ARCH Kconfig, so only selected at
>> the right time. The user won't get prompted for it since there's no
>> string after "bool". I think this is OK. Tegra's pinctrl Kconfig option
>> doesn't have any "depends ARCH_TEGRA" here either, although I note that
>> many other pinctrl drivers do.
> 
> Hi,
> 
> I guess it makes it more apparent, that the symbol is specific to a
> arch/soc. Tegra is a well known SoC, so its easy to figure out what the
> codes purpose is. Other files might not be that easy to guess.
> 
> For the Lantiq SoC to function normally we need to always load these
> drivers. PINTCTRL_LANTIQ has some generic functions and
> PINTCTRL_LANTIQ_XWAY holds the code specific to the XWAY SoC. (i have a
> patch in the local queue to add FALCON SoC support, giving
> PINTCTRL_LANTIQ 2 users)
> 
> How about we do the following.
> 
> config LANTIQ
> 	select PINCTRL
> 
> config PINCTRL_LANTIQ
> 	def_bool y
> 	depends on LANTIQ
> 
> config PINCTRL_LANTIQ_XWAY
> 	def_bool y
> 	depends on SOC_TYPE_XWAY
> 
> This would auto select the right symbols, have all the dependency logic
> in 1 place and reduce the size of arch/mips/lantiq/Kconfig

Is it useful to build a kernel for XWAY without pinctrl, once the driver
is there? That's the main difference between arch/mips/lantiq/Kconfig
selecting PINCTRL_LANTIQ_XWAY vs that being a def_bool, and hence
allowing the user to deselect it.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
  2012-05-08 15:51                     ` Stephen Warren
@ 2012-05-08 15:59                         ` John Crispin
  -1 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 15:59 UTC (permalink / raw)
  To: Stephen Warren
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle


>> How about we do the following.
>>
>> config LANTIQ
>> 	select PINCTRL
>>
>> config PINCTRL_LANTIQ
>> 	def_bool y
>> 	depends on LANTIQ
>>
>> config PINCTRL_LANTIQ_XWAY
>> 	def_bool y
>> 	depends on SOC_TYPE_XWAY
>>
>> This would auto select the right symbols, have all the dependency logic
>> in 1 place and reduce the size of arch/mips/lantiq/Kconfig
> 
> Is it useful to build a kernel for XWAY without pinctrl, once the driver
> is there? That's the main difference between arch/mips/lantiq/Kconfig
> selecting PINCTRL_LANTIQ_XWAY vs that being a def_bool, and hence
> allowing the user to deselect it.
> 

it would not make sense to build an image without.

config LANTIQ and config SOC_TYPE_XWAY should explicitly select the
symbols that they need.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support
@ 2012-05-08 15:59                         ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 15:59 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Linus Walleij, linux-mips, devicetree-discuss, Ralf Baechle


>> How about we do the following.
>>
>> config LANTIQ
>> 	select PINCTRL
>>
>> config PINCTRL_LANTIQ
>> 	def_bool y
>> 	depends on LANTIQ
>>
>> config PINCTRL_LANTIQ_XWAY
>> 	def_bool y
>> 	depends on SOC_TYPE_XWAY
>>
>> This would auto select the right symbols, have all the dependency logic
>> in 1 place and reduce the size of arch/mips/lantiq/Kconfig
> 
> Is it useful to build a kernel for XWAY without pinctrl, once the driver
> is there? That's the main difference between arch/mips/lantiq/Kconfig
> selecting PINCTRL_LANTIQ_XWAY vs that being a def_bool, and hence
> allowing the user to deselect it.
> 

it would not make sense to build an image without.

config LANTIQ and config SOC_TYPE_XWAY should explicitly select the
symbols that they need.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support
  2012-05-04 12:18     ` John Crispin
@ 2012-05-08 17:53         ` Grant Likely
  -1 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2012-05-08 17:53 UTC (permalink / raw)
  To: John Crispin, Ralf Baechle
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

On Fri,  4 May 2012 14:18:28 +0200, John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org> wrote:
> Add support for irq_domain on lantiq socs. The conversion is straight forward
> as the ICU found inside the socs allows the usage of irq_domain_add_linear.
> 
> Signed-off-by: John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> ---
> This patch is part of a series moving the mips/lantiq target to OF and clkdev
> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

Yes, this looks like the right direction, but there is a pretty major
bug that needs to be delt with.  All of the irq ops need are still
using hardcoded (d->irq - INT_NUM_IRQ0) calculations to figure out the
irq number, but that doesn't work with the linear mapping.  The only
reason it's probably working right now is that the linear mapping uses
a 'hint' value to try and make the irq and the hwirq the same number,
but the hint feature is going to be removed soon.

All of the references to d->irq - INT_NUM_IRQ0 need to be replaced
with d->hwirq which the irq_domain manages for you.

You should probably also inspect the ltq_{startup,shutdown}_eiu_irq
functions to make sure they're also doing the right thing.

I could also complain about some cosmetic ugliness in the map
function, but that really isn't something I'm going to get upset over.

g.

> 
>  arch/mips/lantiq/irq.c |  120 +++++++++++++++++++++++++++---------------------
>  1 files changed, 68 insertions(+), 52 deletions(-)
> 
> diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
> index d227be1..170e6cb 100644
> --- a/arch/mips/lantiq/irq.c
> +++ b/arch/mips/lantiq/irq.c
> @@ -9,6 +9,11 @@
>  
>  #include <linux/interrupt.h>
>  #include <linux/ioport.h>
> +#include <linux/sched.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  
>  #include <asm/bootinfo.h>
>  #include <asm/irq_cpu.h>
> @@ -16,7 +21,7 @@
>  #include <lantiq_soc.h>
>  #include <irq.h>
>  
> -/* register definitions */
> +/* register definitions - internal irqs */
>  #define LTQ_ICU_IM0_ISR		0x0000
>  #define LTQ_ICU_IM0_IER		0x0008
>  #define LTQ_ICU_IM0_IOSR	0x0010
> @@ -25,6 +30,7 @@
>  #define LTQ_ICU_IM1_ISR		0x0028
>  #define LTQ_ICU_OFFSET		(LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
>  
> +/* register definitions - external irqs */
>  #define LTQ_EIU_EXIN_C		0x0000
>  #define LTQ_EIU_EXIN_INIC	0x0004
>  #define LTQ_EIU_EXIN_INEN	0x000C
> @@ -37,13 +43,13 @@
>  #define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1)
>  #define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2)
>  #define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30)
> -
>  #define MAX_EIU			6
>  
>  /* the performance counter */
>  #define LTQ_PERF_IRQ		(INT_NUM_IM4_IRL0 + 31)
>  
> -/* irqs generated by device attached to the EBU need to be acked in
> +/*
> + * irqs generated by devices attached to the EBU need to be acked in
>   * a special manner
>   */
>  #define LTQ_ICU_EBU_IRQ		22
> @@ -71,20 +77,6 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
>  	LTQ_EIU_IR5,
>  };
>  
> -static struct resource ltq_icu_resource = {
> -	.name	= "icu",
> -	.start	= LTQ_ICU_BASE_ADDR,
> -	.end	= LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
> -	.flags	= IORESOURCE_MEM,
> -};
> -
> -static struct resource ltq_eiu_resource = {
> -	.name	= "eiu",
> -	.start	= LTQ_EIU_BASE_ADDR,
> -	.end	= LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
> -	.flags	= IORESOURCE_MEM,
> -};
> -
>  static void __iomem *ltq_icu_membase;
>  static void __iomem *ltq_eiu_membase;
>  
> @@ -199,14 +191,15 @@ static void ltq_hw_irqdispatch(int module)
>  	if (irq == 0)
>  		return;
>  
> -	/* silicon bug causes only the msb set to 1 to be valid. all
> +	/*
> +	 * silicon bug causes only the msb set to 1 to be valid. all
>  	 * other bits might be bogus
>  	 */
>  	irq = __fls(irq);
>  	do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
>  
>  	/* if this is a EBU irq, we need to ack it or get a deadlock */
> -	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
> +	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
>  		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
>  			LTQ_EBU_PCC_ISTAT);
>  }
> @@ -290,38 +283,62 @@ out:
>  	return;
>  }
>  
> +static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
> +{
> +	if (((irq == LTQ_EIU_IR0) || (irq == LTQ_EIU_IR1) ||
> +			(irq == LTQ_EIU_IR2)) && ltq_eiu_membase)
> +		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
> +	/* EIU3-5 only exist on ar9 and vr9 */
> +	else if (((irq == LTQ_EIU_IR3) || (irq == LTQ_EIU_IR4) ||
> +			(irq == LTQ_EIU_IR5)) &&
> +			(of_machine_is_compatible("lantiq,ar9") ||
> +				of_machine_is_compatible("lantiq,vr9")) &&
> +			ltq_eiu_membase)
> +		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
> +	else
> +		irq_set_chip_and_handler(irq, &ltq_irq_type, handle_level_irq);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops irq_domain_ops = {
> +	.xlate = irq_domain_xlate_onetwocell,
> +	.map = icu_map,
> +};
> +
>  static struct irqaction cascade = {
>  	.handler = no_action,
>  	.name = "cascade",
>  };
>  
> -void __init arch_init_irq(void)
> +int __init icu_of_init(struct device_node *node, struct device_node *parent)
>  {
> +	struct device_node *eiu_node;
> +	struct resource res;
>  	int i;
>  
> -	if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
> -		panic("Failed to insert icu memory");
> +	if (of_address_to_resource(node, 0, &res))
> +		panic("Failed to get icu memory range");
>  
> -	if (request_mem_region(ltq_icu_resource.start,
> -			resource_size(&ltq_icu_resource), "icu") < 0)
> -		panic("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(ltq_icu_resource.start,
> -				resource_size(&ltq_icu_resource));
> +	ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res));
>  	if (!ltq_icu_membase)
>  		panic("Failed to remap icu memory");
>  
> -	if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
> -		panic("Failed to insert eiu memory");
> -
> -	if (request_mem_region(ltq_eiu_resource.start,
> -			resource_size(&ltq_eiu_resource), "eiu") < 0)
> -		panic("Failed to request eiu memory");
> -
> -	ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
> -				resource_size(&ltq_eiu_resource));
> -	if (!ltq_eiu_membase)
> -		panic("Failed to remap eiu memory");
> +	/* 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 (request_mem_region(res.start, resource_size(&res),
> +							res.name) < 0)
> +			pr_err("Failed to request eiu memory");
> +
> +		ltq_eiu_membase = ioremap_nocache(res.start,
> +							resource_size(&res));
> +		if (!ltq_eiu_membase)
> +			panic("Failed to remap eiu memory");
> +	}
>  
>  	/* turn off all irqs by default */
>  	for (i = 0; i < 5; i++) {
> @@ -346,20 +363,8 @@ void __init arch_init_irq(void)
>  		set_vi_handler(7, ltq_hw5_irqdispatch);
>  	}
>  
> -	for (i = INT_NUM_IRQ0;
> -		i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
> -		if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
> -			(i == LTQ_EIU_IR2))
> -			irq_set_chip_and_handler(i, &ltq_eiu_type,
> -				handle_level_irq);
> -		/* EIU3-5 only exist on ar9 and vr9 */
> -		else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
> -			(i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
> -			irq_set_chip_and_handler(i, &ltq_eiu_type,
> -				handle_level_irq);
> -		else
> -			irq_set_chip_and_handler(i, &ltq_irq_type,
> -				handle_level_irq);
> +	irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET,
> +		&irq_domain_ops, 0);
>  
>  #if defined(CONFIG_MIPS_MT_SMP)
>  	if (cpu_has_vint) {
> @@ -382,9 +387,20 @@ void __init arch_init_irq(void)
>  
>  	/* tell oprofile which irq to use */
>  	cp0_perfcount_irq = LTQ_PERF_IRQ;
> +	return 0;
>  }
>  
>  unsigned int __cpuinit get_c0_compare_int(void)
>  {
>  	return CP0_LEGACY_COMPARE_IRQ;
>  }
> +
> +static struct of_device_id __initdata of_irq_ids[] = {
> +	{ .compatible = "lantiq,icu", .data = icu_of_init },
> +	{},
> +};
> +
> +void __init arch_init_irq(void)
> +{
> +	of_irq_init(of_irq_ids);
> +}
> -- 
> 1.7.9.1
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss

-- 
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support
@ 2012-05-08 17:53         ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2012-05-08 17:53 UTC (permalink / raw)
  To: John Crispin, Ralf Baechle; +Cc: linux-mips, devicetree-discuss

On Fri,  4 May 2012 14:18:28 +0200, John Crispin <blogic@openwrt.org> wrote:
> Add support for irq_domain on lantiq socs. The conversion is straight forward
> as the ICU found inside the socs allows the usage of irq_domain_add_linear.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: devicetree-discuss@lists.ozlabs.org
> ---
> This patch is part of a series moving the mips/lantiq target to OF and clkdev
> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

Yes, this looks like the right direction, but there is a pretty major
bug that needs to be delt with.  All of the irq ops need are still
using hardcoded (d->irq - INT_NUM_IRQ0) calculations to figure out the
irq number, but that doesn't work with the linear mapping.  The only
reason it's probably working right now is that the linear mapping uses
a 'hint' value to try and make the irq and the hwirq the same number,
but the hint feature is going to be removed soon.

All of the references to d->irq - INT_NUM_IRQ0 need to be replaced
with d->hwirq which the irq_domain manages for you.

You should probably also inspect the ltq_{startup,shutdown}_eiu_irq
functions to make sure they're also doing the right thing.

I could also complain about some cosmetic ugliness in the map
function, but that really isn't something I'm going to get upset over.

g.

> 
>  arch/mips/lantiq/irq.c |  120 +++++++++++++++++++++++++++---------------------
>  1 files changed, 68 insertions(+), 52 deletions(-)
> 
> diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
> index d227be1..170e6cb 100644
> --- a/arch/mips/lantiq/irq.c
> +++ b/arch/mips/lantiq/irq.c
> @@ -9,6 +9,11 @@
>  
>  #include <linux/interrupt.h>
>  #include <linux/ioport.h>
> +#include <linux/sched.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  
>  #include <asm/bootinfo.h>
>  #include <asm/irq_cpu.h>
> @@ -16,7 +21,7 @@
>  #include <lantiq_soc.h>
>  #include <irq.h>
>  
> -/* register definitions */
> +/* register definitions - internal irqs */
>  #define LTQ_ICU_IM0_ISR		0x0000
>  #define LTQ_ICU_IM0_IER		0x0008
>  #define LTQ_ICU_IM0_IOSR	0x0010
> @@ -25,6 +30,7 @@
>  #define LTQ_ICU_IM1_ISR		0x0028
>  #define LTQ_ICU_OFFSET		(LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
>  
> +/* register definitions - external irqs */
>  #define LTQ_EIU_EXIN_C		0x0000
>  #define LTQ_EIU_EXIN_INIC	0x0004
>  #define LTQ_EIU_EXIN_INEN	0x000C
> @@ -37,13 +43,13 @@
>  #define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1)
>  #define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2)
>  #define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30)
> -
>  #define MAX_EIU			6
>  
>  /* the performance counter */
>  #define LTQ_PERF_IRQ		(INT_NUM_IM4_IRL0 + 31)
>  
> -/* irqs generated by device attached to the EBU need to be acked in
> +/*
> + * irqs generated by devices attached to the EBU need to be acked in
>   * a special manner
>   */
>  #define LTQ_ICU_EBU_IRQ		22
> @@ -71,20 +77,6 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
>  	LTQ_EIU_IR5,
>  };
>  
> -static struct resource ltq_icu_resource = {
> -	.name	= "icu",
> -	.start	= LTQ_ICU_BASE_ADDR,
> -	.end	= LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
> -	.flags	= IORESOURCE_MEM,
> -};
> -
> -static struct resource ltq_eiu_resource = {
> -	.name	= "eiu",
> -	.start	= LTQ_EIU_BASE_ADDR,
> -	.end	= LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
> -	.flags	= IORESOURCE_MEM,
> -};
> -
>  static void __iomem *ltq_icu_membase;
>  static void __iomem *ltq_eiu_membase;
>  
> @@ -199,14 +191,15 @@ static void ltq_hw_irqdispatch(int module)
>  	if (irq == 0)
>  		return;
>  
> -	/* silicon bug causes only the msb set to 1 to be valid. all
> +	/*
> +	 * silicon bug causes only the msb set to 1 to be valid. all
>  	 * other bits might be bogus
>  	 */
>  	irq = __fls(irq);
>  	do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
>  
>  	/* if this is a EBU irq, we need to ack it or get a deadlock */
> -	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
> +	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
>  		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
>  			LTQ_EBU_PCC_ISTAT);
>  }
> @@ -290,38 +283,62 @@ out:
>  	return;
>  }
>  
> +static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
> +{
> +	if (((irq == LTQ_EIU_IR0) || (irq == LTQ_EIU_IR1) ||
> +			(irq == LTQ_EIU_IR2)) && ltq_eiu_membase)
> +		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
> +	/* EIU3-5 only exist on ar9 and vr9 */
> +	else if (((irq == LTQ_EIU_IR3) || (irq == LTQ_EIU_IR4) ||
> +			(irq == LTQ_EIU_IR5)) &&
> +			(of_machine_is_compatible("lantiq,ar9") ||
> +				of_machine_is_compatible("lantiq,vr9")) &&
> +			ltq_eiu_membase)
> +		irq_set_chip_and_handler(irq, &ltq_eiu_type, handle_level_irq);
> +	else
> +		irq_set_chip_and_handler(irq, &ltq_irq_type, handle_level_irq);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops irq_domain_ops = {
> +	.xlate = irq_domain_xlate_onetwocell,
> +	.map = icu_map,
> +};
> +
>  static struct irqaction cascade = {
>  	.handler = no_action,
>  	.name = "cascade",
>  };
>  
> -void __init arch_init_irq(void)
> +int __init icu_of_init(struct device_node *node, struct device_node *parent)
>  {
> +	struct device_node *eiu_node;
> +	struct resource res;
>  	int i;
>  
> -	if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
> -		panic("Failed to insert icu memory");
> +	if (of_address_to_resource(node, 0, &res))
> +		panic("Failed to get icu memory range");
>  
> -	if (request_mem_region(ltq_icu_resource.start,
> -			resource_size(&ltq_icu_resource), "icu") < 0)
> -		panic("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(ltq_icu_resource.start,
> -				resource_size(&ltq_icu_resource));
> +	ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res));
>  	if (!ltq_icu_membase)
>  		panic("Failed to remap icu memory");
>  
> -	if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
> -		panic("Failed to insert eiu memory");
> -
> -	if (request_mem_region(ltq_eiu_resource.start,
> -			resource_size(&ltq_eiu_resource), "eiu") < 0)
> -		panic("Failed to request eiu memory");
> -
> -	ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
> -				resource_size(&ltq_eiu_resource));
> -	if (!ltq_eiu_membase)
> -		panic("Failed to remap eiu memory");
> +	/* 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 (request_mem_region(res.start, resource_size(&res),
> +							res.name) < 0)
> +			pr_err("Failed to request eiu memory");
> +
> +		ltq_eiu_membase = ioremap_nocache(res.start,
> +							resource_size(&res));
> +		if (!ltq_eiu_membase)
> +			panic("Failed to remap eiu memory");
> +	}
>  
>  	/* turn off all irqs by default */
>  	for (i = 0; i < 5; i++) {
> @@ -346,20 +363,8 @@ void __init arch_init_irq(void)
>  		set_vi_handler(7, ltq_hw5_irqdispatch);
>  	}
>  
> -	for (i = INT_NUM_IRQ0;
> -		i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
> -		if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
> -			(i == LTQ_EIU_IR2))
> -			irq_set_chip_and_handler(i, &ltq_eiu_type,
> -				handle_level_irq);
> -		/* EIU3-5 only exist on ar9 and vr9 */
> -		else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
> -			(i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
> -			irq_set_chip_and_handler(i, &ltq_eiu_type,
> -				handle_level_irq);
> -		else
> -			irq_set_chip_and_handler(i, &ltq_irq_type,
> -				handle_level_irq);
> +	irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET,
> +		&irq_domain_ops, 0);
>  
>  #if defined(CONFIG_MIPS_MT_SMP)
>  	if (cpu_has_vint) {
> @@ -382,9 +387,20 @@ void __init arch_init_irq(void)
>  
>  	/* tell oprofile which irq to use */
>  	cp0_perfcount_irq = LTQ_PERF_IRQ;
> +	return 0;
>  }
>  
>  unsigned int __cpuinit get_c0_compare_int(void)
>  {
>  	return CP0_LEGACY_COMPARE_IRQ;
>  }
> +
> +static struct of_device_id __initdata of_irq_ids[] = {
> +	{ .compatible = "lantiq,icu", .data = icu_of_init },
> +	{},
> +};
> +
> +void __init arch_init_irq(void)
> +{
> +	of_irq_init(of_irq_ids);
> +}
> -- 
> 1.7.9.1
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss

-- 
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support
  2012-05-08 17:53         ` Grant Likely
@ 2012-05-08 18:05           ` John Crispin
  -1 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 18:05 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ralf Baechle

Hi Grant,

> I could also complain about some cosmetic ugliness in the map
> function, but that really isn't something I'm going to get upset over.

Let me clean up the map function while I am at it.

Thanks for the comments
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support
@ 2012-05-08 18:05           ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-08 18:05 UTC (permalink / raw)
  To: Grant Likely; +Cc: Ralf Baechle, linux-mips, devicetree-discuss

Hi Grant,

> I could also complain about some cosmetic ugliness in the map
> function, but that really isn't something I'm going to get upset over.

Let me clean up the map function while I am at it.

Thanks for the comments
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
  2012-05-11 14:06     ` Artem Bityutskiy
@ 2012-05-11 14:04       ` John Crispin
  -1 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-11 14:04 UTC (permalink / raw)
  To: dedekind1; +Cc: Ralf Baechle, linux-mips, linux-mtd

On 11/05/12 16:06, Artem Bityutskiy wrote:
> On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
>> Adds bindings for OF and make use of module_platform_driver for lantiq
>> based socs.
>>
>> Signed-off-by: John Crispin <blogic@openwrt.org>
>> Cc: linux-mtd@lists.infradead.org
>> ---
>> This patch is part of a series moving the mips/lantiq target to OF and clkdev
>> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.
> Looks ok, but could you please send me the entire series anyway, may be
> privately. I want to feed it to aiaiai and check before acking this
> patch. Also, please, make sure you add dependency on OF in Kconfig.

Hi Artem,

The lantiq platform selects USE_OF

config USE_OF
        bool "Flattened Device Tree support"
        select OF
        select OF_EARLY_FLATTREE
        select IRQ_DOMAIN
        help
          Include support for flattened device tree machine descriptions.

Do i still need an explicit dependency on OF in this case ?

Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
@ 2012-05-11 14:04       ` John Crispin
  0 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-11 14:04 UTC (permalink / raw)
  To: dedekind1; +Cc: linux-mips, linux-mtd, Ralf Baechle

On 11/05/12 16:06, Artem Bityutskiy wrote:
> On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
>> Adds bindings for OF and make use of module_platform_driver for lantiq
>> based socs.
>>
>> Signed-off-by: John Crispin <blogic@openwrt.org>
>> Cc: linux-mtd@lists.infradead.org
>> ---
>> This patch is part of a series moving the mips/lantiq target to OF and clkdev
>> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.
> Looks ok, but could you please send me the entire series anyway, may be
> privately. I want to feed it to aiaiai and check before acking this
> patch. Also, please, make sure you add dependency on OF in Kconfig.

Hi Artem,

The lantiq platform selects USE_OF

config USE_OF
        bool "Flattened Device Tree support"
        select OF
        select OF_EARLY_FLATTREE
        select IRQ_DOMAIN
        help
          Include support for flattened device tree machine descriptions.

Do i still need an explicit dependency on OF in this case ?

Thanks,
John

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
  2012-05-04 12:18   ` John Crispin
@ 2012-05-11 14:06     ` Artem Bityutskiy
  -1 siblings, 0 replies; 48+ messages in thread
From: Artem Bityutskiy @ 2012-05-11 14:06 UTC (permalink / raw)
  To: John Crispin; +Cc: Ralf Baechle, linux-mips, linux-mtd

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]

On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
> Adds bindings for OF and make use of module_platform_driver for lantiq
> based socs.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: linux-mtd@lists.infradead.org
> ---
> This patch is part of a series moving the mips/lantiq target to OF and clkdev
> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

Looks ok, but could you please send me the entire series anyway, may be
privately. I want to feed it to aiaiai and check before acking this
patch. Also, please, make sure you add dependency on OF in Kconfig.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
@ 2012-05-11 14:06     ` Artem Bityutskiy
  0 siblings, 0 replies; 48+ messages in thread
From: Artem Bityutskiy @ 2012-05-11 14:06 UTC (permalink / raw)
  To: John Crispin; +Cc: linux-mips, linux-mtd, Ralf Baechle

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]

On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
> Adds bindings for OF and make use of module_platform_driver for lantiq
> based socs.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: linux-mtd@lists.infradead.org
> ---
> This patch is part of a series moving the mips/lantiq target to OF and clkdev
> support. The patch, once Acked, should go upstream via Ralf's MIPS tree.

Looks ok, but could you please send me the entire series anyway, may be
privately. I want to feed it to aiaiai and check before acking this
patch. Also, please, make sure you add dependency on OF in Kconfig.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
  2012-05-11 14:04       ` John Crispin
@ 2012-05-11 14:16         ` Artem Bityutskiy
  -1 siblings, 0 replies; 48+ messages in thread
From: Artem Bityutskiy @ 2012-05-11 14:16 UTC (permalink / raw)
  To: John Crispin; +Cc: Ralf Baechle, linux-mips, linux-mtd

[-- Attachment #1: Type: text/plain, Size: 485 bytes --]

On Fri, 2012-05-11 at 16:04 +0200, John Crispin wrote:
> The lantiq platform selects USE_OF
> 
> config USE_OF
>         bool "Flattened Device Tree support"
>         select OF
>         select OF_EARLY_FLATTREE
>         select IRQ_DOMAIN
>         help
>           Include support for flattened device tree machine descriptions.

OK.

> Do i still need an explicit dependency on OF in this case ?

Not sure, but probably not.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
@ 2012-05-11 14:16         ` Artem Bityutskiy
  0 siblings, 0 replies; 48+ messages in thread
From: Artem Bityutskiy @ 2012-05-11 14:16 UTC (permalink / raw)
  To: John Crispin; +Cc: linux-mips, linux-mtd, Ralf Baechle

[-- Attachment #1: Type: text/plain, Size: 485 bytes --]

On Fri, 2012-05-11 at 16:04 +0200, John Crispin wrote:
> The lantiq platform selects USE_OF
> 
> config USE_OF
>         bool "Flattened Device Tree support"
>         select OF
>         select OF_EARLY_FLATTREE
>         select IRQ_DOMAIN
>         help
>           Include support for flattened device tree machine descriptions.

OK.

> Do i still need an explicit dependency on OF in this case ?

Not sure, but probably not.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 02/14] OF: MIPS: lantiq: implement OF support
  2012-05-04 12:18     ` John Crispin
@ 2012-05-12  0:47         ` Grant Likely
  -1 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2012-05-12  0:47 UTC (permalink / raw)
  To: John Crispin, Ralf Baechle
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

On Fri,  4 May 2012 14:18:27 +0200, John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org> wrote:
> Activate USE_OF, add a sample DTS file and convert the core soc code to OF.
> 
> Signed-off-by: John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> ---
> diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
> index cd56892..413ed53 100644
> --- a/arch/mips/lantiq/prom.c
> +++ b/arch/mips/lantiq/prom.c
> @@ -8,6 +8,7 @@
>  
>  #include <linux/export.h>
>  #include <linux/clk.h>
> +#include <linux/of_platform.h>
>  #include <asm/bootinfo.h>
>  #include <asm/time.h>
>  
> @@ -16,13 +17,15 @@
>  #include "prom.h"
>  #include "clk.h"
>  
> -static struct ltq_soc_info soc_info;
> +/* access to the ebu needs to be locked between different drivers */
> +DEFINE_SPINLOCK(ebu_lock);
> +EXPORT_SYMBOL_GPL(ebu_lock);
>  
> -unsigned int ltq_get_cpu_ver(void)
> -{
> -	return soc_info.rev;
> -}
> -EXPORT_SYMBOL(ltq_get_cpu_ver);
> +/*
> + * this struct is filled by the soc specific detection code and holds
> + * information about the specific soc type, revision and name
> + */
> +static struct ltq_soc_info soc_info;
>  
>  unsigned int ltq_get_soc_type(void)
>  {
> @@ -57,16 +60,28 @@ static void __init prom_init_cmdline(void)
>  	}
>  }
>  
> -void __init prom_init(void)
> +void __init plat_mem_setup(void)
>  {
> -	struct clk *clk;
> +	ioport_resource.start = IOPORT_RESOURCE_START;
> +	ioport_resource.end = IOPORT_RESOURCE_END;
> +	iomem_resource.start = IOMEM_RESOURCE_START;
> +	iomem_resource.end = IOMEM_RESOURCE_END;
> +
> +	set_io_port_base((unsigned long) KSEG1);
> +
> +	/*
> +	 * Load the builtin devicetree. This causes the chosen node to be
> +	 * parsed resulting in our memory appearing
> +	 */
> +	__dt_setup_arch(&__dtb_start);
> +}
>  
> +void __init prom_init(void)
> +{
> +	/* call the soc specific detetcion code and get it to fill soc_info */
>  	ltq_soc_detect(&soc_info);
> -	clk_init();
> -	clk = clk_get(0, "cpu");
> -	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
> -		soc_info.name, soc_info.rev);
> -	clk_put(clk);
> +	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
> +		soc_info.name, soc_info.rev_type);
>  	soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
>  	pr_info("SoC: %s\n", soc_info.sys_type);
>  	prom_init_cmdline();
> @@ -76,3 +91,19 @@ void __init prom_init(void)
>  		panic("failed to register_vsmp_smp_ops()");
>  #endif
>  }
> +
> +int __init plat_of_setup(void)
> +{
> +	static struct of_device_id of_ids[3];
> +
> +	if (!of_have_populated_dt())
> +		panic("device tree not present");
> +
> +	strncpy(of_ids[0].compatible, soc_info.compatible,
> +		sizeof(of_ids[0].compatible));
> +	strncpy(of_ids[1].compatible, "simple-bus",
> +		sizeof(of_ids[1].compatible));

?!?  That's rather weird.  Why not simply a static of_device_id table
and add all possible compatible values to it which in this case is
"simple-bus" and whatever values are possible for soc_info.compatible?

> +	return of_platform_bus_probe(NULL, of_ids, NULL);

of_platform_bus_probe() is deprecated.  Use of_platform_populate()
instead.  The semantics make more sense on that one.

g.
> +}
> +
> +arch_initcall(plat_of_setup);
> diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
> index f7c2a79..a3fa1a2 100644
> --- a/arch/mips/lantiq/prom.h
> +++ b/arch/mips/lantiq/prom.h
> @@ -26,4 +26,6 @@ struct ltq_soc_info {
>  extern void ltq_soc_detect(struct ltq_soc_info *i);
>  extern void ltq_soc_init(void);
>  
> +extern struct boot_param_header __dtb_start;
> +
>  #endif
> diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
> deleted file mode 100644
> index f1c605a..0000000
> --- a/arch/mips/lantiq/setup.c
> +++ /dev/null
> @@ -1,43 +0,0 @@
> -/*
> - *  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) 2010 John Crispin <blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/export.h>
> -#include <linux/io.h>
> -#include <linux/ioport.h>
> -#include <asm/bootinfo.h>
> -
> -#include <lantiq_soc.h>
> -
> -#include "prom.h"
> -
> -void __init plat_mem_setup(void)
> -{
> -	/* assume 16M as default incase uboot fails to pass proper ramsize */
> -	unsigned long memsize = 16;
> -	char **envp = (char **) KSEG1ADDR(fw_arg2);
> -
> -	ioport_resource.start = IOPORT_RESOURCE_START;
> -	ioport_resource.end = IOPORT_RESOURCE_END;
> -	iomem_resource.start = IOMEM_RESOURCE_START;
> -	iomem_resource.end = IOMEM_RESOURCE_END;
> -
> -	set_io_port_base((unsigned long) KSEG1);
> -
> -	while (*envp) {
> -		char *e = (char *)KSEG1ADDR(*envp);
> -		if (!strncmp(e, "memsize=", 8)) {
> -			e += 8;
> -			if (strict_strtoul(e, 0, &memsize))
> -				pr_warn("bad memsize specified\n");
> -		}
> -		envp++;
> -	}
> -	memsize *= 1024 * 1024;
> -	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
> -}
> diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
> index 862e3e8..419b47b 100644
> --- a/arch/mips/lantiq/xway/ebu.c
> +++ b/arch/mips/lantiq/xway/ebu.c
> @@ -14,10 +14,6 @@
>  
>  #include <lantiq_soc.h>
>  
> -/* all access to the ebu must be locked */
> -DEFINE_SPINLOCK(ebu_lock);
> -EXPORT_SYMBOL_GPL(ebu_lock);
> -
>  static struct resource ltq_ebu_resource = {
>  	.name	= "ebu",
>  	.start	= LTQ_EBU_BASE_ADDR,
> diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
> index 3327211..22c55f7 100644
> --- a/arch/mips/lantiq/xway/reset.c
> +++ b/arch/mips/lantiq/xway/reset.c
> @@ -37,13 +37,6 @@
>  #define RCU_BOOT_SEL_SHIFT	26
>  #define RCU_BOOT_SEL_MASK	0x7
>  
> -static struct resource ltq_rcu_resource = {
> -	.name   = "rcu",
> -	.start  = LTQ_RCU_BASE_ADDR,
> -	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
> -	.flags  = IORESOURCE_MEM,
> -};
> -
>  /* remapped base addr of the reset control unit */
>  static void __iomem *ltq_rcu_membase;
>  
> @@ -91,17 +84,21 @@ static void ltq_machine_power_off(void)
>  
>  static int __init mips_reboot_setup(void)
>  {
> -	/* insert and request the memory region */
> -	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
> -		panic("Failed to insert rcu memory");
> +	struct resource res;
> +	struct device_node *np =
> +		of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
> +
> +	/* check if all the reset register range is available */
> +	if (!np)
> +		panic("Failed to load reset resources from devicetree");
> +
> +	if (of_address_to_resource(np, 0, &res))
> +		panic("Failed to get rcu memory range");
>  
> -	if (request_mem_region(ltq_rcu_resource.start,
> -			resource_size(&ltq_rcu_resource), "rcu") < 0)
> -		panic("Failed to request rcu memory");
> +	if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
> +		pr_err("Failed to request rcu memory");
>  
> -	/* remap rcu register range */
> -	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
> -				resource_size(&ltq_rcu_resource));
> +	ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
>  	if (!ltq_rcu_membase)
>  		panic("Failed to remap core memory");
>  
> -- 
> 1.7.9.1
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss

-- 
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 02/14] OF: MIPS: lantiq: implement OF support
@ 2012-05-12  0:47         ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2012-05-12  0:47 UTC (permalink / raw)
  To: John Crispin, Ralf Baechle; +Cc: linux-mips, devicetree-discuss

On Fri,  4 May 2012 14:18:27 +0200, John Crispin <blogic@openwrt.org> wrote:
> Activate USE_OF, add a sample DTS file and convert the core soc code to OF.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: devicetree-discuss@lists.ozlabs.org
> ---
> diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
> index cd56892..413ed53 100644
> --- a/arch/mips/lantiq/prom.c
> +++ b/arch/mips/lantiq/prom.c
> @@ -8,6 +8,7 @@
>  
>  #include <linux/export.h>
>  #include <linux/clk.h>
> +#include <linux/of_platform.h>
>  #include <asm/bootinfo.h>
>  #include <asm/time.h>
>  
> @@ -16,13 +17,15 @@
>  #include "prom.h"
>  #include "clk.h"
>  
> -static struct ltq_soc_info soc_info;
> +/* access to the ebu needs to be locked between different drivers */
> +DEFINE_SPINLOCK(ebu_lock);
> +EXPORT_SYMBOL_GPL(ebu_lock);
>  
> -unsigned int ltq_get_cpu_ver(void)
> -{
> -	return soc_info.rev;
> -}
> -EXPORT_SYMBOL(ltq_get_cpu_ver);
> +/*
> + * this struct is filled by the soc specific detection code and holds
> + * information about the specific soc type, revision and name
> + */
> +static struct ltq_soc_info soc_info;
>  
>  unsigned int ltq_get_soc_type(void)
>  {
> @@ -57,16 +60,28 @@ static void __init prom_init_cmdline(void)
>  	}
>  }
>  
> -void __init prom_init(void)
> +void __init plat_mem_setup(void)
>  {
> -	struct clk *clk;
> +	ioport_resource.start = IOPORT_RESOURCE_START;
> +	ioport_resource.end = IOPORT_RESOURCE_END;
> +	iomem_resource.start = IOMEM_RESOURCE_START;
> +	iomem_resource.end = IOMEM_RESOURCE_END;
> +
> +	set_io_port_base((unsigned long) KSEG1);
> +
> +	/*
> +	 * Load the builtin devicetree. This causes the chosen node to be
> +	 * parsed resulting in our memory appearing
> +	 */
> +	__dt_setup_arch(&__dtb_start);
> +}
>  
> +void __init prom_init(void)
> +{
> +	/* call the soc specific detetcion code and get it to fill soc_info */
>  	ltq_soc_detect(&soc_info);
> -	clk_init();
> -	clk = clk_get(0, "cpu");
> -	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
> -		soc_info.name, soc_info.rev);
> -	clk_put(clk);
> +	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
> +		soc_info.name, soc_info.rev_type);
>  	soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
>  	pr_info("SoC: %s\n", soc_info.sys_type);
>  	prom_init_cmdline();
> @@ -76,3 +91,19 @@ void __init prom_init(void)
>  		panic("failed to register_vsmp_smp_ops()");
>  #endif
>  }
> +
> +int __init plat_of_setup(void)
> +{
> +	static struct of_device_id of_ids[3];
> +
> +	if (!of_have_populated_dt())
> +		panic("device tree not present");
> +
> +	strncpy(of_ids[0].compatible, soc_info.compatible,
> +		sizeof(of_ids[0].compatible));
> +	strncpy(of_ids[1].compatible, "simple-bus",
> +		sizeof(of_ids[1].compatible));

?!?  That's rather weird.  Why not simply a static of_device_id table
and add all possible compatible values to it which in this case is
"simple-bus" and whatever values are possible for soc_info.compatible?

> +	return of_platform_bus_probe(NULL, of_ids, NULL);

of_platform_bus_probe() is deprecated.  Use of_platform_populate()
instead.  The semantics make more sense on that one.

g.
> +}
> +
> +arch_initcall(plat_of_setup);
> diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
> index f7c2a79..a3fa1a2 100644
> --- a/arch/mips/lantiq/prom.h
> +++ b/arch/mips/lantiq/prom.h
> @@ -26,4 +26,6 @@ struct ltq_soc_info {
>  extern void ltq_soc_detect(struct ltq_soc_info *i);
>  extern void ltq_soc_init(void);
>  
> +extern struct boot_param_header __dtb_start;
> +
>  #endif
> diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
> deleted file mode 100644
> index f1c605a..0000000
> --- a/arch/mips/lantiq/setup.c
> +++ /dev/null
> @@ -1,43 +0,0 @@
> -/*
> - *  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) 2010 John Crispin <blogic@openwrt.org>
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/export.h>
> -#include <linux/io.h>
> -#include <linux/ioport.h>
> -#include <asm/bootinfo.h>
> -
> -#include <lantiq_soc.h>
> -
> -#include "prom.h"
> -
> -void __init plat_mem_setup(void)
> -{
> -	/* assume 16M as default incase uboot fails to pass proper ramsize */
> -	unsigned long memsize = 16;
> -	char **envp = (char **) KSEG1ADDR(fw_arg2);
> -
> -	ioport_resource.start = IOPORT_RESOURCE_START;
> -	ioport_resource.end = IOPORT_RESOURCE_END;
> -	iomem_resource.start = IOMEM_RESOURCE_START;
> -	iomem_resource.end = IOMEM_RESOURCE_END;
> -
> -	set_io_port_base((unsigned long) KSEG1);
> -
> -	while (*envp) {
> -		char *e = (char *)KSEG1ADDR(*envp);
> -		if (!strncmp(e, "memsize=", 8)) {
> -			e += 8;
> -			if (strict_strtoul(e, 0, &memsize))
> -				pr_warn("bad memsize specified\n");
> -		}
> -		envp++;
> -	}
> -	memsize *= 1024 * 1024;
> -	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
> -}
> diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
> index 862e3e8..419b47b 100644
> --- a/arch/mips/lantiq/xway/ebu.c
> +++ b/arch/mips/lantiq/xway/ebu.c
> @@ -14,10 +14,6 @@
>  
>  #include <lantiq_soc.h>
>  
> -/* all access to the ebu must be locked */
> -DEFINE_SPINLOCK(ebu_lock);
> -EXPORT_SYMBOL_GPL(ebu_lock);
> -
>  static struct resource ltq_ebu_resource = {
>  	.name	= "ebu",
>  	.start	= LTQ_EBU_BASE_ADDR,
> diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
> index 3327211..22c55f7 100644
> --- a/arch/mips/lantiq/xway/reset.c
> +++ b/arch/mips/lantiq/xway/reset.c
> @@ -37,13 +37,6 @@
>  #define RCU_BOOT_SEL_SHIFT	26
>  #define RCU_BOOT_SEL_MASK	0x7
>  
> -static struct resource ltq_rcu_resource = {
> -	.name   = "rcu",
> -	.start  = LTQ_RCU_BASE_ADDR,
> -	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
> -	.flags  = IORESOURCE_MEM,
> -};
> -
>  /* remapped base addr of the reset control unit */
>  static void __iomem *ltq_rcu_membase;
>  
> @@ -91,17 +84,21 @@ static void ltq_machine_power_off(void)
>  
>  static int __init mips_reboot_setup(void)
>  {
> -	/* insert and request the memory region */
> -	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
> -		panic("Failed to insert rcu memory");
> +	struct resource res;
> +	struct device_node *np =
> +		of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
> +
> +	/* check if all the reset register range is available */
> +	if (!np)
> +		panic("Failed to load reset resources from devicetree");
> +
> +	if (of_address_to_resource(np, 0, &res))
> +		panic("Failed to get rcu memory range");
>  
> -	if (request_mem_region(ltq_rcu_resource.start,
> -			resource_size(&ltq_rcu_resource), "rcu") < 0)
> -		panic("Failed to request rcu memory");
> +	if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
> +		pr_err("Failed to request rcu memory");
>  
> -	/* remap rcu register range */
> -	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
> -				resource_size(&ltq_rcu_resource));
> +	ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
>  	if (!ltq_rcu_membase)
>  		panic("Failed to remap core memory");
>  
> -- 
> 1.7.9.1
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss

-- 
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies, Ltd.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
  2012-05-04 12:18   ` John Crispin
@ 2012-05-14 12:21     ` Artem Bityutskiy
  -1 siblings, 0 replies; 48+ messages in thread
From: Artem Bityutskiy @ 2012-05-14 12:21 UTC (permalink / raw)
  To: John Crispin; +Cc: Ralf Baechle, linux-mips, linux-mtd

[-- Attachment #1: Type: text/plain, Size: 343 bytes --]

On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
> Adds bindings for OF and make use of module_platform_driver for lantiq
> based socs.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: linux-mtd@lists.infradead.org

Acked-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
@ 2012-05-14 12:21     ` Artem Bityutskiy
  0 siblings, 0 replies; 48+ messages in thread
From: Artem Bityutskiy @ 2012-05-14 12:21 UTC (permalink / raw)
  To: John Crispin; +Cc: linux-mips, linux-mtd, Ralf Baechle

[-- Attachment #1: Type: text/plain, Size: 343 bytes --]

On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
> Adds bindings for OF and make use of module_platform_driver for lantiq
> based socs.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Cc: linux-mtd@lists.infradead.org

Acked-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 12/14] MTD: MIPS: lantiq: implement OF support
  2012-05-14 12:21     ` Artem Bityutskiy
  (?)
@ 2012-05-14 12:31     ` John Crispin
  -1 siblings, 0 replies; 48+ messages in thread
From: John Crispin @ 2012-05-14 12:31 UTC (permalink / raw)
  To: dedekind1; +Cc: linux-mips, linux-mtd

On 14/05/12 14:21, Artem Bityutskiy wrote:
> On Fri, 2012-05-04 at 14:18 +0200, John Crispin wrote:
>> Adds bindings for OF and make use of module_platform_driver for lantiq
>> based socs.
>>
>> Signed-off-by: John Crispin <blogic@openwrt.org>
>> Cc: linux-mtd@lists.infradead.org
> Acked-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
>

Thank you very much !

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2012-05-14 12:31 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-04 12:18 [PATCH 01/14] MIPS: lantiq: drop mips_machine support John Crispin
     [not found] ` <1336133919-26525-1-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
2012-05-04 12:18   ` [PATCH 02/14] OF: MIPS: lantiq: implement OF support John Crispin
2012-05-04 12:18     ` John Crispin
     [not found]     ` <1336133919-26525-2-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
2012-05-12  0:47       ` Grant Likely
2012-05-12  0:47         ` Grant Likely
2012-05-04 12:18   ` [PATCH 03/14] OF: MIPS: lantiq: implement irq_domain support John Crispin
2012-05-04 12:18     ` John Crispin
     [not found]     ` <1336133919-26525-3-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
2012-05-08 17:53       ` Grant Likely
2012-05-08 17:53         ` Grant Likely
2012-05-08 18:05         ` John Crispin
2012-05-08 18:05           ` John Crispin
2012-05-04 12:18   ` [PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support John Crispin
2012-05-04 12:18     ` John Crispin
2012-05-04 20:57     ` Stephen Warren
     [not found]       ` <4FA442B6.1020501-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2012-05-04 21:29         ` John Crispin
     [not found]     ` <1336133919-26525-4-git-send-email-blogic-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
2012-05-08 13:21       ` Linus Walleij
2012-05-08 13:21         ` Linus Walleij
     [not found]         ` <CACRpkdYJDd84GbKM7r4Xy+d4iOtdD+rJ3kdq-zwVbf_Attj2Gw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-05-08 14:12           ` John Crispin
2012-05-08 14:12             ` John Crispin
2012-05-08 15:28           ` Stephen Warren
2012-05-08 15:28             ` Stephen Warren
     [not found]             ` <4FA93B97.4070406-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2012-05-08 15:39               ` John Crispin
2012-05-08 15:39                 ` John Crispin
     [not found]                 ` <4FA93E37.70305-Pj+rj9U5foFAfugRpC6u6w@public.gmane.org>
2012-05-08 15:51                   ` Stephen Warren
2012-05-08 15:51                     ` Stephen Warren
     [not found]                     ` <4FA940F3.4090008-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2012-05-08 15:59                       ` John Crispin
2012-05-08 15:59                         ` John Crispin
2012-05-04 12:18 ` [PATCH 05/14] MIPS: lantiq: implement support for clkdev api John Crispin
2012-05-04 12:18 ` [PATCH 06/14] MIPS: lantiq: convert dma to platform driver John Crispin
2012-05-04 12:18 ` [PATCH 07/14] MIPS: pci: convert lantiq driver to OF John Crispin
2012-05-04 12:18 ` [PATCH 08/14] GPIO: MIPS: lantiq: convert gpio-stp to OF and move it to subsystem John Crispin
2012-05-04 12:18 ` [PATCH 09/14] GPIO: MIPS: lantiq: convert gpio-ebu " John Crispin
2012-05-04 12:18 ` [PATCH 10/14] SERIAL: MIPS: lantiq: implement OF support John Crispin
2012-05-04 12:18 ` [PATCH 11/14] watchdog: MIPS: lantiq: implement OF support and minor fixes John Crispin
2012-05-04 13:22   ` Wim Van Sebroeck
2012-05-04 12:18 ` [PATCH 12/14] MTD: MIPS: lantiq: implement OF support John Crispin
2012-05-04 12:18   ` John Crispin
2012-05-11 14:06   ` Artem Bityutskiy
2012-05-11 14:06     ` Artem Bityutskiy
2012-05-11 14:04     ` John Crispin
2012-05-11 14:04       ` John Crispin
2012-05-11 14:16       ` Artem Bityutskiy
2012-05-11 14:16         ` Artem Bityutskiy
2012-05-14 12:21   ` Artem Bityutskiy
2012-05-14 12:21     ` Artem Bityutskiy
2012-05-14 12:31     ` John Crispin
2012-05-04 12:18 ` [PATCH 13/14] NET: MIPS: lantiq: implement OF support inside the etop driver John Crispin
2012-05-04 12:18 ` [PATCH 14/14] MIPS: lantiq: remove orphaned code John Crispin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.