All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] Add Initial support for PLX Technology OX810SE
@ 2016-03-03 11:39 ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux; +Cc: Neil Armstrong

This serie adds initial support (IRQ, Timer, GPIO, Reset, Serial, Clocks) for
the PLX Technology OX810SE used in the well-known Western Digital My Book
World Edition Network Attached Storage device.

Extended support for SATA, DMA and Ethernet will come in further patches.

Upstream support for following devices like the OX820SE is welcome !

Neil Armstrong (17):
  dt-bindings: vendor-prefixes: Add PLX Technology
  irqchip: Add PLX Technology RPS IRQ Controller
  dt-bindings: Add PLX Technology RPS IRQ Controller bindings
  clocksource: Add PLX Technology RPS Timer
  dt-bindings: Add PLX Technology RPS Timer bindings
  reset: Add PLX Technology Reset Controller driver
  dt-bindings: Add PLX Technology Reset Controller bindings
  clk: Add PLX Technology OXNAS Standard Clocks
  dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  arm: Add new mach-oxnas
  arm: Add build support for mach-oxnas
  arm: boot: dts: Add PLX Technology OX810SE dtsi
  dt-bindings: Add OXNAS bindings
  dt-bindings: Add Western Digital to vendor prefixes
  arm: boot: dts: Add Western Digital My Book World Edition device tree

 Documentation/devicetree/bindings/arm/oxnas.txt    |    9 +
 .../devicetree/bindings/clock/plxtech,stdclk.txt   |   24 +
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |   27 +
 .../interrupt-controller/plxtech,rps-irq.txt       |   17 +
 .../bindings/pinctrl/plxtech,pinctrl.txt           |  100 ++
 .../devicetree/bindings/reset/plxtech,reset.txt    |   25 +
 .../bindings/timer/plxtech,rps-timer.txt           |   17 +
 .../devicetree/bindings/vendor-prefixes.txt        |    2 +
 arch/arm/Kconfig                                   |    2 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/boot/dts/Makefile                         |    2 +
 arch/arm/boot/dts/ox810se.dtsi                     |  279 ++++
 arch/arm/boot/dts/wd-mbwe.dts                      |  106 ++
 arch/arm/mach-oxnas/Kconfig                        |   24 +
 arch/arm/mach-oxnas/Makefile                       |    1 +
 arch/arm/mach-oxnas/oxnas.c                        |   34 +
 drivers/clk/Kconfig                                |    6 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk-oxnas.c                            |  159 +++
 drivers/clocksource/Kconfig                        |    6 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-rps.c                    |  249 ++++
 drivers/irqchip/Kconfig                            |    5 +
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-rps.c                          |  128 ++
 drivers/pinctrl/Kconfig                            |    9 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-oxnas.c                    | 1393 ++++++++++++++++++++
 drivers/reset/Kconfig                              |    4 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/reset-oxnas.c                        |  149 +++
 31 files changed, 2783 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt
 create mode 100644 Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile
 create mode 100644 arch/arm/mach-oxnas/oxnas.c
 create mode 100644 drivers/clk/clk-oxnas.c
 create mode 100644 drivers/clocksource/timer-rps.c
 create mode 100644 drivers/irqchip/irq-rps.c
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c
 create mode 100644 drivers/reset/reset-oxnas.c

-- 
1.9.1

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

* [PATCH 00/17] Add Initial support for PLX Technology OX810SE
@ 2016-03-03 11:39 ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

This serie adds initial support (IRQ, Timer, GPIO, Reset, Serial, Clocks) for
the PLX Technology OX810SE used in the well-known Western Digital My Book
World Edition Network Attached Storage device.

Extended support for SATA, DMA and Ethernet will come in further patches.

Upstream support for following devices like the OX820SE is welcome !

Neil Armstrong (17):
  dt-bindings: vendor-prefixes: Add PLX Technology
  irqchip: Add PLX Technology RPS IRQ Controller
  dt-bindings: Add PLX Technology RPS IRQ Controller bindings
  clocksource: Add PLX Technology RPS Timer
  dt-bindings: Add PLX Technology RPS Timer bindings
  reset: Add PLX Technology Reset Controller driver
  dt-bindings: Add PLX Technology Reset Controller bindings
  clk: Add PLX Technology OXNAS Standard Clocks
  dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  arm: Add new mach-oxnas
  arm: Add build support for mach-oxnas
  arm: boot: dts: Add PLX Technology OX810SE dtsi
  dt-bindings: Add OXNAS bindings
  dt-bindings: Add Western Digital to vendor prefixes
  arm: boot: dts: Add Western Digital My Book World Edition device tree

 Documentation/devicetree/bindings/arm/oxnas.txt    |    9 +
 .../devicetree/bindings/clock/plxtech,stdclk.txt   |   24 +
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |   27 +
 .../interrupt-controller/plxtech,rps-irq.txt       |   17 +
 .../bindings/pinctrl/plxtech,pinctrl.txt           |  100 ++
 .../devicetree/bindings/reset/plxtech,reset.txt    |   25 +
 .../bindings/timer/plxtech,rps-timer.txt           |   17 +
 .../devicetree/bindings/vendor-prefixes.txt        |    2 +
 arch/arm/Kconfig                                   |    2 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/boot/dts/Makefile                         |    2 +
 arch/arm/boot/dts/ox810se.dtsi                     |  279 ++++
 arch/arm/boot/dts/wd-mbwe.dts                      |  106 ++
 arch/arm/mach-oxnas/Kconfig                        |   24 +
 arch/arm/mach-oxnas/Makefile                       |    1 +
 arch/arm/mach-oxnas/oxnas.c                        |   34 +
 drivers/clk/Kconfig                                |    6 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk-oxnas.c                            |  159 +++
 drivers/clocksource/Kconfig                        |    6 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-rps.c                    |  249 ++++
 drivers/irqchip/Kconfig                            |    5 +
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-rps.c                          |  128 ++
 drivers/pinctrl/Kconfig                            |    9 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-oxnas.c                    | 1393 ++++++++++++++++++++
 drivers/reset/Kconfig                              |    4 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/reset-oxnas.c                        |  149 +++
 31 files changed, 2783 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt
 create mode 100644 Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile
 create mode 100644 arch/arm/mach-oxnas/oxnas.c
 create mode 100644 drivers/clk/clk-oxnas.c
 create mode 100644 drivers/clocksource/timer-rps.c
 create mode 100644 drivers/irqchip/irq-rps.c
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c
 create mode 100644 drivers/reset/reset-oxnas.c

-- 
1.9.1

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

* [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Add PLX Technology vendor prefix.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 72e2c5a..03970fb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -178,6 +178,7 @@ picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
 plda	PLDA
 pixcir  PIXCIR MICROELECTRONICS Co., Ltd
+plxtech	PLX Technology, Inc.
 pulsedlight	PulsedLight, Inc
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
-- 
1.9.1

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

* [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Neil Armstrong

Add PLX Technology vendor prefix.

Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 72e2c5a..03970fb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -178,6 +178,7 @@ picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
 plda	PLDA
 pixcir  PIXCIR MICROELECTRONICS Co., Ltd
+plxtech	PLX Technology, Inc.
 pulsedlight	PulsedLight, Inc
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

Add PLX Technology vendor prefix.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 72e2c5a..03970fb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -178,6 +178,7 @@ picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
 plda	PLDA
 pixcir  PIXCIR MICROELECTRONICS Co., Ltd
+plxtech	PLX Technology, Inc.
 pulsedlight	PulsedLight, Inc
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
-- 
1.9.1

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:39   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, tglx, jason, marc.zyngier
  Cc: Neil Armstrong, Ma Haijun

Add PLX Technology RPS IRQ Controller as irqchip driver.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/irqchip/Kconfig   |   5 ++
 drivers/irqchip/Makefile  |   1 +
 drivers/irqchip/irq-rps.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 drivers/irqchip/irq-rps.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fb50911..7892c1a 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -135,6 +135,11 @@ config PIC32_EVIC
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config PLXTECH_RPS
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+
 config RENESAS_INTC_IRQPIN
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 18caacb..3eec3a0 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_I8259)			+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
+obj-$(CONFIG_PLXTECH_RPS)		+= irq-rps.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-rps.c b/drivers/irqchip/irq-rps.c
new file mode 100644
index 0000000..bcd4a31
--- /dev/null
+++ b/drivers/irqchip/irq-rps.c
@@ -0,0 +1,128 @@
+/*
+ * drivers/irqchip/irq-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/irqchip.h>
+
+#include <asm/exception.h>
+
+struct rps_chip_data {
+	void __iomem *base;
+	struct irq_domain *domain;
+} rps_data;
+
+enum {
+	RPS_IRQ_COUNT = 32,
+
+	RPS_STATUS = 0,
+	RPS_RAW_STATUS = 4,
+	RPS_UNMASK = 8,
+	RPS_MASK = 0xc,
+};
+
+/* Routines to acknowledge, disable and enable interrupts */
+static void rps_mask_irq(struct irq_data *d)
+{
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_MASK);
+}
+
+static void rps_unmask_irq(struct irq_data *d)
+{
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_UNMASK);
+}
+
+static void rps_ack_irq(struct irq_data *d)
+{
+	/* NOP */
+}
+
+static void __exception_irq_entry handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat;
+	int hwirq;
+
+	irqstat = ioread32(rps_data.base + RPS_STATUS);
+	hwirq = __ffs(irqstat);
+
+	do {
+		handle_IRQ(irq_find_mapping(rps_data.domain, hwirq), regs);
+
+		irqstat = ioread32(rps_data.base + RPS_STATUS);
+		hwirq = __ffs(irqstat);
+	} while (irqstat);
+}
+
+int __init rps_of_init(struct device_node *node, struct device_node *parent)
+{
+	int ret;
+	struct irq_chip_generic *gc;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	rps_data.base = of_iomap(node, 0);
+	WARN(!rps_data.base, "unable to map rps registers\n");
+
+	rps_data.domain = irq_domain_add_linear(node, RPS_IRQ_COUNT,
+						&irq_generic_chip_ops,
+						NULL);
+	if (!rps_data.domain) {
+		pr_err("%s: could add irq domain\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(rps_data.domain, RPS_IRQ_COUNT, 1,
+					     "RPS", handle_level_irq,
+					     0, 0, IRQ_GC_INIT_NESTED_LOCK);
+	if (ret) {
+		pr_err("%s: could not allocate generic chip\n",
+		       node->full_name);
+		irq_domain_remove(rps_data.domain);
+		return -EINVAL;
+	}
+
+	gc = irq_get_domain_generic_chip(rps_data.domain, 0);
+	gc->chip_types[0].chip.irq_ack = rps_ack_irq;
+	gc->chip_types[0].chip.irq_mask = rps_mask_irq;
+	gc->chip_types[0].chip.irq_unmask = rps_unmask_irq;
+
+	/* Disable all IRQs */
+	iowrite32(~0, rps_data.base + RPS_MASK);
+
+	set_handle_irq(handle_irq);
+
+	pr_info("Registered %d rps interrupts\n", RPS_IRQ_COUNT);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
-- 
1.9.1

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

Add PLX Technology RPS IRQ Controller as irqchip driver.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/irqchip/Kconfig   |   5 ++
 drivers/irqchip/Makefile  |   1 +
 drivers/irqchip/irq-rps.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 drivers/irqchip/irq-rps.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fb50911..7892c1a 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -135,6 +135,11 @@ config PIC32_EVIC
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config PLXTECH_RPS
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+
 config RENESAS_INTC_IRQPIN
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 18caacb..3eec3a0 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_I8259)			+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
+obj-$(CONFIG_PLXTECH_RPS)		+= irq-rps.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-rps.c b/drivers/irqchip/irq-rps.c
new file mode 100644
index 0000000..bcd4a31
--- /dev/null
+++ b/drivers/irqchip/irq-rps.c
@@ -0,0 +1,128 @@
+/*
+ * drivers/irqchip/irq-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/irqchip.h>
+
+#include <asm/exception.h>
+
+struct rps_chip_data {
+	void __iomem *base;
+	struct irq_domain *domain;
+} rps_data;
+
+enum {
+	RPS_IRQ_COUNT = 32,
+
+	RPS_STATUS = 0,
+	RPS_RAW_STATUS = 4,
+	RPS_UNMASK = 8,
+	RPS_MASK = 0xc,
+};
+
+/* Routines to acknowledge, disable and enable interrupts */
+static void rps_mask_irq(struct irq_data *d)
+{
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_MASK);
+}
+
+static void rps_unmask_irq(struct irq_data *d)
+{
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_UNMASK);
+}
+
+static void rps_ack_irq(struct irq_data *d)
+{
+	/* NOP */
+}
+
+static void __exception_irq_entry handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat;
+	int hwirq;
+
+	irqstat = ioread32(rps_data.base + RPS_STATUS);
+	hwirq = __ffs(irqstat);
+
+	do {
+		handle_IRQ(irq_find_mapping(rps_data.domain, hwirq), regs);
+
+		irqstat = ioread32(rps_data.base + RPS_STATUS);
+		hwirq = __ffs(irqstat);
+	} while (irqstat);
+}
+
+int __init rps_of_init(struct device_node *node, struct device_node *parent)
+{
+	int ret;
+	struct irq_chip_generic *gc;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	rps_data.base = of_iomap(node, 0);
+	WARN(!rps_data.base, "unable to map rps registers\n");
+
+	rps_data.domain = irq_domain_add_linear(node, RPS_IRQ_COUNT,
+						&irq_generic_chip_ops,
+						NULL);
+	if (!rps_data.domain) {
+		pr_err("%s: could add irq domain\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(rps_data.domain, RPS_IRQ_COUNT, 1,
+					     "RPS", handle_level_irq,
+					     0, 0, IRQ_GC_INIT_NESTED_LOCK);
+	if (ret) {
+		pr_err("%s: could not allocate generic chip\n",
+		       node->full_name);
+		irq_domain_remove(rps_data.domain);
+		return -EINVAL;
+	}
+
+	gc = irq_get_domain_generic_chip(rps_data.domain, 0);
+	gc->chip_types[0].chip.irq_ack = rps_ack_irq;
+	gc->chip_types[0].chip.irq_mask = rps_mask_irq;
+	gc->chip_types[0].chip.irq_unmask = rps_unmask_irq;
+
+	/* Disable all IRQs */
+	iowrite32(~0, rps_data.base + RPS_MASK);
+
+	set_handle_irq(handle_irq);
+
+	pr_info("Registered %d rps interrupts\n", RPS_IRQ_COUNT);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
-- 
1.9.1

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

* [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:39   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../bindings/interrupt-controller/plxtech,rps-irq.txt   | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
new file mode 100644
index 0000000..db117a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
@@ -0,0 +1,17 @@
+PLX Technology OXNAS SoCs Family RPS Interrupt Controller
+=========================================================
+
+Required properties:
+- compatible: Should be "plxtech,nas782x-rps"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Should be 1
+
+example:
+
+intc: interrupt-controller@0 {
+	compatible = "plxtech,nas782x-rps";
+	interrupt-controller;
+	reg = <0 0x200>;
+	#interrupt-cells = <1>;
+};
-- 
1.9.1

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

* [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../bindings/interrupt-controller/plxtech,rps-irq.txt   | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
new file mode 100644
index 0000000..db117a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
@@ -0,0 +1,17 @@
+PLX Technology OXNAS SoCs Family RPS Interrupt Controller
+=========================================================
+
+Required properties:
+- compatible: Should be "plxtech,nas782x-rps"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Should be 1
+
+example:
+
+intc: interrupt-controller at 0 {
+	compatible = "plxtech,nas782x-rps";
+	interrupt-controller;
+	reg = <0 0x200>;
+	#interrupt-cells = <1>;
+};
-- 
1.9.1

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

* [PATCH 04/17] clocksource: Add PLX Technology RPS Timer
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:39   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, daniel.lezcano, tglx
  Cc: Neil Armstrong, Ma Haijun

Add clocksource and clockevent driver from dual RPS timer.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clocksource/Kconfig     |   6 +
 drivers/clocksource/Makefile    |   1 +
 drivers/clocksource/timer-rps.c | 249 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 256 insertions(+)
 create mode 100644 drivers/clocksource/timer-rps.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 33db740..f79bc0f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -276,6 +276,12 @@ config VF_PIT_TIMER
 	help
 	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
 
+config CLKSRC_RPS_TIMER
+	bool
+	select CLKSRC_MMIO
+	help
+	  This enables support for the PLX Tech OXNAS RPS timers.
+
 config SYS_SUPPORTS_SH_CMT
         bool
 
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index dc2b899..120bc09 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
+obj-$(CONFIG_CLKSRC_RPS_TIMER)	+= timer-rps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/timer-rps.c b/drivers/clocksource/timer-rps.c
new file mode 100644
index 0000000..79621b8
--- /dev/null
+++ b/drivers/clocksource/timer-rps.c
@@ -0,0 +1,249 @@
+/*
+ * drivers/clocksource/timer-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/sched_clock.h>
+
+/* TIMER1 as tick
+ * TIMER2 as clocksource
+ */
+
+enum {
+	TIMER_LOAD = 0,
+	TIMER_CURR = 4,
+	TIMER_CTRL = 8,
+	TIMER_CLRINT = 0xC,
+
+	TIMER_BITS = 24,
+
+	TIMER_MAX_VAL = (1 << TIMER_BITS) - 1,
+
+	TIMER_PERIODIC = (1 << 6),
+	TIMER_ENABLE = (1 << 7),
+
+	TIMER_DIV1  = (0 << 2),
+	TIMER_DIV16  = (1 << 2),
+	TIMER_DIV256  = (2 << 2),
+
+	TIMER1_OFFSET = 0,
+	TIMER2_OFFSET = 0x20,
+};
+
+/* Clockevent */
+
+static unsigned long timer_period = HZ;
+static unsigned timer_prescaler = 1;
+static void __iomem *timer_base;
+
+static irqreturn_t rps_timer_irq(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	iowrite32(0, timer_base + TIMER_CLRINT);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void rps_timer_config(unsigned long period, unsigned periodic)
+{
+	uint32_t cfg = 0;
+
+	if (period)
+		cfg |= TIMER_ENABLE;
+
+	if (periodic)
+		cfg |= TIMER_PERIODIC;
+
+	switch (timer_prescaler) {
+	case 1:
+		cfg |= TIMER_DIV1;
+		break;
+	case 16:
+		cfg |= TIMER_DIV16;
+		break;
+	case 256:
+		cfg |= TIMER_DIV256;
+		break;
+	}
+
+	iowrite32(period, timer_base + TIMER_LOAD);
+	iowrite32(cfg, timer_base + TIMER_CTRL);
+}
+
+static int rps_timer_shutdown(struct clock_event_device *evt)
+{
+	if (!clockevent_state_periodic(evt))
+		return 0;
+
+	rps_timer_config(0, 0);
+
+	return 0;
+}
+
+static int rps_timer_set_periodic(struct clock_event_device *evt)
+{
+	rps_timer_config(timer_period, 1);
+
+	return 0;
+}
+
+static int rps_timer_set_oneshot(struct clock_event_device *evt)
+{
+	rps_timer_config(timer_period, 0);
+
+	return 0;
+}
+
+static int rps_timer_next_event(unsigned long delta,
+				struct clock_event_device *evt)
+{
+	rps_timer_config(delta, 0);
+
+	return 0;
+}
+
+static struct clock_event_device rps_clockevent = {
+	.name = "rps",
+	.features = CLOCK_EVT_FEAT_PERIODIC |
+		    CLOCK_EVT_FEAT_ONESHOT,
+	.tick_resume = rps_timer_shutdown,
+	.set_state_shutdown = rps_timer_shutdown,
+	.set_state_periodic = rps_timer_set_periodic,
+	.set_state_oneshot = rps_timer_set_oneshot,
+	.set_next_event = rps_timer_next_event,
+	.rating = 200,
+};
+
+static void __init rps_clockevent_init(void __iomem *base, ulong ref_rate,
+				       int irq)
+{
+	timer_base = base;
+
+	/* Start with prescaler 1 */
+	timer_prescaler = 1;
+	timer_period = DIV_ROUND_UP(ref_rate, HZ);
+
+	if (timer_period > TIMER_MAX_VAL) {
+		timer_prescaler = 16;
+		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);
+	}
+	if (timer_period > TIMER_MAX_VAL) {
+		timer_prescaler = 256;
+		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);
+	}
+
+	rps_clockevent.cpumask = cpu_possible_mask;
+	rps_clockevent.irq = irq;
+	clockevents_config_and_register(&rps_clockevent,
+					ref_rate / timer_prescaler,
+					1,
+					TIMER_MAX_VAL);
+
+	pr_info("rps: Registered clock event rate %luHz prescaler %d period %lu\n",
+			ref_rate,
+			timer_prescaler,
+			timer_period);
+}
+
+/* Clocksource */
+
+static void __iomem *timer_curr;
+
+static u64 notrace rps_read_sched_clock(void)
+{
+	return ~readl_relaxed(timer_curr);
+}
+
+static void __init rps_clocksource_init(void __iomem *base, ulong ref_rate)
+{
+	int ret;
+	ulong clock_rate;
+	/* use prescale 16 */
+	clock_rate = ref_rate / 16;
+
+	iowrite32(TIMER_MAX_VAL, base + TIMER_LOAD);
+	iowrite32(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16,
+			base + TIMER_CTRL);
+
+	timer_curr = base + TIMER_CURR;
+	sched_clock_register(rps_read_sched_clock, TIMER_BITS, clock_rate);
+	ret = clocksource_mmio_init(base + TIMER_CURR, "rps_clocksource_timer",
+					clock_rate, 250, TIMER_BITS,
+					clocksource_mmio_readl_down);
+	if (ret)
+		panic("can't register clocksource\n");
+
+	pr_info("rps: Registered clocksource rate %luHz\n", clock_rate);
+}
+
+static struct irqaction rps_timer_irqaction = {
+	.name		= "rps_timer",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= rps_timer_irq,
+	.dev_id		= &rps_clockevent,
+};
+
+static void __init rps_timer_init(struct device_node *np)
+{
+	struct clk *refclk;
+	unsigned long ref_rate;
+	void __iomem *base;
+	int irq, ret;
+
+	refclk = of_clk_get(np, 0);
+
+	if (IS_ERR(refclk) || clk_prepare_enable(refclk))
+		panic("rps_timer_init: failed to get refclk\n");
+	ref_rate = clk_get_rate(refclk);
+
+	base = of_iomap(np, 0);
+	if (!base)
+		panic("rps_timer_init: failed to map io\n");
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq < 0)
+		panic("rps_timer_init: failed to parse IRQ\n");
+
+	/* Disable timers */
+	iowrite32(0, base + TIMER1_OFFSET + TIMER_CTRL);
+	iowrite32(0, base + TIMER2_OFFSET + TIMER_CTRL);
+	iowrite32(0, base + TIMER1_OFFSET + TIMER_LOAD);
+	iowrite32(0, base + TIMER2_OFFSET + TIMER_LOAD);
+	iowrite32(0, base + TIMER1_OFFSET + TIMER_CLRINT);
+	iowrite32(0, base + TIMER2_OFFSET + TIMER_CLRINT);
+
+	rps_clocksource_init(base + TIMER2_OFFSET, ref_rate);
+	rps_clockevent_init(base + TIMER1_OFFSET, ref_rate, irq);
+
+	ret = setup_irq(irq, &rps_timer_irqaction);
+	if (ret)
+		panic("rps_timer_init: failed to request irq\n");
+}
+
+CLOCKSOURCE_OF_DECLARE(nas782x, "plxtech,nas782x-rps-timer", rps_timer_init);
-- 
1.9.1

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

* [PATCH 04/17] clocksource: Add PLX Technology RPS Timer
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

Add clocksource and clockevent driver from dual RPS timer.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clocksource/Kconfig     |   6 +
 drivers/clocksource/Makefile    |   1 +
 drivers/clocksource/timer-rps.c | 249 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 256 insertions(+)
 create mode 100644 drivers/clocksource/timer-rps.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 33db740..f79bc0f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -276,6 +276,12 @@ config VF_PIT_TIMER
 	help
 	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
 
+config CLKSRC_RPS_TIMER
+	bool
+	select CLKSRC_MMIO
+	help
+	  This enables support for the PLX Tech OXNAS RPS timers.
+
 config SYS_SUPPORTS_SH_CMT
         bool
 
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index dc2b899..120bc09 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
+obj-$(CONFIG_CLKSRC_RPS_TIMER)	+= timer-rps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/timer-rps.c b/drivers/clocksource/timer-rps.c
new file mode 100644
index 0000000..79621b8
--- /dev/null
+++ b/drivers/clocksource/timer-rps.c
@@ -0,0 +1,249 @@
+/*
+ * drivers/clocksource/timer-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/sched_clock.h>
+
+/* TIMER1 as tick
+ * TIMER2 as clocksource
+ */
+
+enum {
+	TIMER_LOAD = 0,
+	TIMER_CURR = 4,
+	TIMER_CTRL = 8,
+	TIMER_CLRINT = 0xC,
+
+	TIMER_BITS = 24,
+
+	TIMER_MAX_VAL = (1 << TIMER_BITS) - 1,
+
+	TIMER_PERIODIC = (1 << 6),
+	TIMER_ENABLE = (1 << 7),
+
+	TIMER_DIV1  = (0 << 2),
+	TIMER_DIV16  = (1 << 2),
+	TIMER_DIV256  = (2 << 2),
+
+	TIMER1_OFFSET = 0,
+	TIMER2_OFFSET = 0x20,
+};
+
+/* Clockevent */
+
+static unsigned long timer_period = HZ;
+static unsigned timer_prescaler = 1;
+static void __iomem *timer_base;
+
+static irqreturn_t rps_timer_irq(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	iowrite32(0, timer_base + TIMER_CLRINT);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void rps_timer_config(unsigned long period, unsigned periodic)
+{
+	uint32_t cfg = 0;
+
+	if (period)
+		cfg |= TIMER_ENABLE;
+
+	if (periodic)
+		cfg |= TIMER_PERIODIC;
+
+	switch (timer_prescaler) {
+	case 1:
+		cfg |= TIMER_DIV1;
+		break;
+	case 16:
+		cfg |= TIMER_DIV16;
+		break;
+	case 256:
+		cfg |= TIMER_DIV256;
+		break;
+	}
+
+	iowrite32(period, timer_base + TIMER_LOAD);
+	iowrite32(cfg, timer_base + TIMER_CTRL);
+}
+
+static int rps_timer_shutdown(struct clock_event_device *evt)
+{
+	if (!clockevent_state_periodic(evt))
+		return 0;
+
+	rps_timer_config(0, 0);
+
+	return 0;
+}
+
+static int rps_timer_set_periodic(struct clock_event_device *evt)
+{
+	rps_timer_config(timer_period, 1);
+
+	return 0;
+}
+
+static int rps_timer_set_oneshot(struct clock_event_device *evt)
+{
+	rps_timer_config(timer_period, 0);
+
+	return 0;
+}
+
+static int rps_timer_next_event(unsigned long delta,
+				struct clock_event_device *evt)
+{
+	rps_timer_config(delta, 0);
+
+	return 0;
+}
+
+static struct clock_event_device rps_clockevent = {
+	.name = "rps",
+	.features = CLOCK_EVT_FEAT_PERIODIC |
+		    CLOCK_EVT_FEAT_ONESHOT,
+	.tick_resume = rps_timer_shutdown,
+	.set_state_shutdown = rps_timer_shutdown,
+	.set_state_periodic = rps_timer_set_periodic,
+	.set_state_oneshot = rps_timer_set_oneshot,
+	.set_next_event = rps_timer_next_event,
+	.rating = 200,
+};
+
+static void __init rps_clockevent_init(void __iomem *base, ulong ref_rate,
+				       int irq)
+{
+	timer_base = base;
+
+	/* Start with prescaler 1 */
+	timer_prescaler = 1;
+	timer_period = DIV_ROUND_UP(ref_rate, HZ);
+
+	if (timer_period > TIMER_MAX_VAL) {
+		timer_prescaler = 16;
+		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);
+	}
+	if (timer_period > TIMER_MAX_VAL) {
+		timer_prescaler = 256;
+		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);
+	}
+
+	rps_clockevent.cpumask = cpu_possible_mask;
+	rps_clockevent.irq = irq;
+	clockevents_config_and_register(&rps_clockevent,
+					ref_rate / timer_prescaler,
+					1,
+					TIMER_MAX_VAL);
+
+	pr_info("rps: Registered clock event rate %luHz prescaler %d period %lu\n",
+			ref_rate,
+			timer_prescaler,
+			timer_period);
+}
+
+/* Clocksource */
+
+static void __iomem *timer_curr;
+
+static u64 notrace rps_read_sched_clock(void)
+{
+	return ~readl_relaxed(timer_curr);
+}
+
+static void __init rps_clocksource_init(void __iomem *base, ulong ref_rate)
+{
+	int ret;
+	ulong clock_rate;
+	/* use prescale 16 */
+	clock_rate = ref_rate / 16;
+
+	iowrite32(TIMER_MAX_VAL, base + TIMER_LOAD);
+	iowrite32(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16,
+			base + TIMER_CTRL);
+
+	timer_curr = base + TIMER_CURR;
+	sched_clock_register(rps_read_sched_clock, TIMER_BITS, clock_rate);
+	ret = clocksource_mmio_init(base + TIMER_CURR, "rps_clocksource_timer",
+					clock_rate, 250, TIMER_BITS,
+					clocksource_mmio_readl_down);
+	if (ret)
+		panic("can't register clocksource\n");
+
+	pr_info("rps: Registered clocksource rate %luHz\n", clock_rate);
+}
+
+static struct irqaction rps_timer_irqaction = {
+	.name		= "rps_timer",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= rps_timer_irq,
+	.dev_id		= &rps_clockevent,
+};
+
+static void __init rps_timer_init(struct device_node *np)
+{
+	struct clk *refclk;
+	unsigned long ref_rate;
+	void __iomem *base;
+	int irq, ret;
+
+	refclk = of_clk_get(np, 0);
+
+	if (IS_ERR(refclk) || clk_prepare_enable(refclk))
+		panic("rps_timer_init: failed to get refclk\n");
+	ref_rate = clk_get_rate(refclk);
+
+	base = of_iomap(np, 0);
+	if (!base)
+		panic("rps_timer_init: failed to map io\n");
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq < 0)
+		panic("rps_timer_init: failed to parse IRQ\n");
+
+	/* Disable timers */
+	iowrite32(0, base + TIMER1_OFFSET + TIMER_CTRL);
+	iowrite32(0, base + TIMER2_OFFSET + TIMER_CTRL);
+	iowrite32(0, base + TIMER1_OFFSET + TIMER_LOAD);
+	iowrite32(0, base + TIMER2_OFFSET + TIMER_LOAD);
+	iowrite32(0, base + TIMER1_OFFSET + TIMER_CLRINT);
+	iowrite32(0, base + TIMER2_OFFSET + TIMER_CLRINT);
+
+	rps_clocksource_init(base + TIMER2_OFFSET, ref_rate);
+	rps_clockevent_init(base + TIMER1_OFFSET, ref_rate, irq);
+
+	ret = setup_irq(irq, &rps_timer_irqaction);
+	if (ret)
+		panic("rps_timer_init: failed to request irq\n");
+}
+
+CLOCKSOURCE_OF_DECLARE(nas782x, "plxtech,nas782x-rps-timer", rps_timer_init);
-- 
1.9.1

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

* [PATCH 05/17] dt-bindings: Add PLX Technology RPS Timer bindings
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:39   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/timer/plxtech,rps-timer.txt     | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt b/Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt
new file mode 100644
index 0000000..bc7cb33
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt
@@ -0,0 +1,17 @@
+PLX Technology OXNAS SoCs Family RPS Timer
+==========================================
+
+Required properties:
+- compatible: Should be "plxtech,nas782x-rps-timer"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : The interrupt of the first timer
+- clocks : The phandle of the timer clock source
+
+example:
+
+timer0: timer@200 {
+	compatible = "plxtech,nas782x-rps-timer";
+	reg = <0x200 0x40>;
+	clocks = <&rpsclk>;
+	interrupts = <4 5>;
+};
-- 
1.9.1

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

* [PATCH 05/17] dt-bindings: Add PLX Technology RPS Timer bindings
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/timer/plxtech,rps-timer.txt     | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt b/Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt
new file mode 100644
index 0000000..bc7cb33
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/plxtech,rps-timer.txt
@@ -0,0 +1,17 @@
+PLX Technology OXNAS SoCs Family RPS Timer
+==========================================
+
+Required properties:
+- compatible: Should be "plxtech,nas782x-rps-timer"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : The interrupt of the first timer
+- clocks : The phandle of the timer clock source
+
+example:
+
+timer0: timer at 200 {
+	compatible = "plxtech,nas782x-rps-timer";
+	reg = <0x200 0x40>;
+	clocks = <&rpsclk>;
+	interrupts = <4 5>;
+};
-- 
1.9.1

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

* [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:39   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, p.zabel; +Cc: Neil Armstrong, Ma Haijun

Add System reset controller driver for PLX Technology OXNAS SoC Family.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/reset/Kconfig       |   4 ++
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-oxnas.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)
 create mode 100644 drivers/reset/reset-oxnas.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..f0ea63b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,9 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+config RESET_OXNAS
+	bool
+	select MFD_SYSCON
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 4d7178e..97e04c5 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
 obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
new file mode 100644
index 0000000..d0ab670
--- /dev/null
+++ b/drivers/reset/reset-oxnas.c
@@ -0,0 +1,149 @@
+/*
+ * drivers/reset/reset-oxnas.c
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Regmap offsets */
+#define RST_SET_REGOFFSET	0x34
+#define RST_CLR_REGOFFSET	0x38
+
+struct oxnas_reset {
+	struct regmap *regmap;
+	struct reset_controller_dev rcdev;
+};
+
+static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+	msleep(50);
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static struct reset_control_ops oxnas_reset_ops = {
+	.reset		= oxnas_reset_reset,
+	.assert		= oxnas_reset_assert,
+	.deassert	= oxnas_reset_deassert,
+};
+
+static const struct of_device_id oxnas_reset_dt_ids[] = {
+	 { .compatible = "plxtech,nas782x-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
+
+static int oxnas_reset_probe(struct platform_device *pdev)
+{
+	struct oxnas_reset *data;
+	struct device *parent;
+
+	parent = pdev->dev.parent;
+	if (!parent) {
+		dev_err(&pdev->dev, "no parent\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->regmap = syscon_node_to_regmap(parent->of_node);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&pdev->dev, "failed to get parent regmap\n");
+		return -ENODEV;
+	}
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = 32;
+	data->rcdev.ops = &oxnas_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+	reset_controller_register(&data->rcdev);
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int oxnas_reset_remove(struct platform_device *pdev)
+{
+	struct oxnas_reset *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+
+	return 0;
+}
+
+static struct platform_driver oxnas_reset_driver = {
+	.probe	= oxnas_reset_probe,
+	.remove	= oxnas_reset_remove,
+	.driver = {
+		.name		= "oxnas-reset",
+		.owner		= THIS_MODULE,
+		.of_match_table	= oxnas_reset_dt_ids,
+	},
+};
+
+static int __init oxnas_reset_init(void)
+{
+	return platform_driver_probe(&oxnas_reset_driver,
+				     oxnas_reset_probe);
+}
+
+/*
+ * Reset controller does not support probe deferral, so it has to be
+ * initialized before any user, in particular, PCIE uses subsys_initcall.
+ */
+arch_initcall(oxnas_reset_init);
-- 
1.9.1

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

* [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
@ 2016-03-03 11:39   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

Add System reset controller driver for PLX Technology OXNAS SoC Family.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/reset/Kconfig       |   4 ++
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-oxnas.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)
 create mode 100644 drivers/reset/reset-oxnas.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..f0ea63b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,9 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+config RESET_OXNAS
+	bool
+	select MFD_SYSCON
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 4d7178e..97e04c5 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
 obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
new file mode 100644
index 0000000..d0ab670
--- /dev/null
+++ b/drivers/reset/reset-oxnas.c
@@ -0,0 +1,149 @@
+/*
+ * drivers/reset/reset-oxnas.c
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Regmap offsets */
+#define RST_SET_REGOFFSET	0x34
+#define RST_CLR_REGOFFSET	0x38
+
+struct oxnas_reset {
+	struct regmap *regmap;
+	struct reset_controller_dev rcdev;
+};
+
+static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+	msleep(50);
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static struct reset_control_ops oxnas_reset_ops = {
+	.reset		= oxnas_reset_reset,
+	.assert		= oxnas_reset_assert,
+	.deassert	= oxnas_reset_deassert,
+};
+
+static const struct of_device_id oxnas_reset_dt_ids[] = {
+	 { .compatible = "plxtech,nas782x-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
+
+static int oxnas_reset_probe(struct platform_device *pdev)
+{
+	struct oxnas_reset *data;
+	struct device *parent;
+
+	parent = pdev->dev.parent;
+	if (!parent) {
+		dev_err(&pdev->dev, "no parent\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->regmap = syscon_node_to_regmap(parent->of_node);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&pdev->dev, "failed to get parent regmap\n");
+		return -ENODEV;
+	}
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = 32;
+	data->rcdev.ops = &oxnas_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+	reset_controller_register(&data->rcdev);
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
+}
+
+static int oxnas_reset_remove(struct platform_device *pdev)
+{
+	struct oxnas_reset *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+
+	return 0;
+}
+
+static struct platform_driver oxnas_reset_driver = {
+	.probe	= oxnas_reset_probe,
+	.remove	= oxnas_reset_remove,
+	.driver = {
+		.name		= "oxnas-reset",
+		.owner		= THIS_MODULE,
+		.of_match_table	= oxnas_reset_dt_ids,
+	},
+};
+
+static int __init oxnas_reset_init(void)
+{
+	return platform_driver_probe(&oxnas_reset_driver,
+				     oxnas_reset_probe);
+}
+
+/*
+ * Reset controller does not support probe deferral, so it has to be
+ * initialized before any user, in particular, PCIE uses subsys_initcall.
+ */
+arch_initcall(oxnas_reset_init);
-- 
1.9.1

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

* [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/reset/plxtech,reset.txt    | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

diff --git a/Documentation/devicetree/bindings/reset/plxtech,reset.txt b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
new file mode 100644
index 0000000..e99648d
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
@@ -0,0 +1,25 @@
+PLX Technology OXNAS SoC Family RESET Controller
+================================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "plxtech,nas782x-reset"
+- #reset-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+example:
+
+sys: sys-ctrl@000000 {
+	compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	reset: reset-controller {
+		compatible = "plxtech,nas782x-reset";
+		#reset-cells = <1>;
+
+	};
+};
-- 
1.9.1

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

* [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/reset/plxtech,reset.txt    | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

diff --git a/Documentation/devicetree/bindings/reset/plxtech,reset.txt b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
new file mode 100644
index 0000000..e99648d
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
@@ -0,0 +1,25 @@
+PLX Technology OXNAS SoC Family RESET Controller
+================================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "plxtech,nas782x-reset"
+- #reset-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+example:
+
+sys: sys-ctrl at 000000 {
+	compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	reset: reset-controller {
+		compatible = "plxtech,nas782x-reset";
+		#reset-cells = <1>;
+
+	};
+};
-- 
1.9.1

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

* [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
  2016-03-03 11:39 ` Neil Armstrong
  (?)
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-clk; +Cc: Neil Armstrong

Add PLX Technology OXNAS SoC Family Standard Clocks support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/Kconfig     |   6 ++
 drivers/clk/Makefile    |   1 +
 drivers/clk/clk-oxnas.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/clk/clk-oxnas.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index eca8e01..b75ef5c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -192,6 +192,12 @@ config COMMON_CLK_PXA
 	---help---
 	  Sypport for the Marvell PXA SoC.
 
+config COMMON_CLK_OXNAS
+	def_bool COMMON_CLK
+	select MFD_SYSCON
+	---help---
+	  Sypport for the OXNAS SoC Family clocks.
+
 config COMMON_CLK_CDCE706
 	tristate "Clock driver for TI CDCE706 clock synthesizer"
 	depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bae4be6..a5d45d8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_OXNAS)		+= clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
new file mode 100644
index 0000000..c4b903f
--- /dev/null
+++ b/drivers/clk/clk-oxnas.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Standard regmap gate clocks */
+struct clk_std {
+	struct clk_hw hw;
+	signed char bit;
+	struct regmap *regmap;
+};
+
+/* Regmap offsets */
+#define CLK_STAT_REGOFFSET	0x24
+#define CLK_SET_REGOFFSET	0x2c
+#define CLK_CLR_REGOFFSET	0x30
+
+#define NUM_STD_CLKS 10
+#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
+
+static int std_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(std->bit);
+}
+
+static int std_clk_enable(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+
+	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
+
+	return 0;
+}
+
+static void std_clk_disable(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+
+	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
+}
+
+static struct clk_ops std_clk_ops = {
+	.enable = std_clk_enable,
+	.disable = std_clk_disable,
+	.is_enabled = std_clk_is_enabled,
+};
+
+static const char *const std_clk_parents[] = {
+	"oscillator",
+};
+
+static const char *const eth_parents[] = {
+	"gmacclk",
+};
+
+#define DECLARE_STD_CLKP(__clk, __bit, __parent)	\
+static struct clk_init_data clk_##__clk##_init = {	\
+	.name = __stringify(__clk),			\
+	.ops = &std_clk_ops,				\
+	.parent_names = __parent,		\
+	.num_parents = ARRAY_SIZE(__parent),	\
+};							\
+							\
+static struct clk_std clk_##__clk = {			\
+	.bit = __bit,					\
+	.hw = {						\
+		.init = &clk_##__clk##_init,		\
+	},						\
+}
+
+#define DECLARE_STD_CLK(__clk, __bit) DECLARE_STD_CLKP(__clk, __bit, \
+							std_clk_parents)
+
+DECLARE_STD_CLK(leon, 0);
+DECLARE_STD_CLK(dma_sgdma, 1);
+DECLARE_STD_CLK(cipher, 2);
+/* DECLARE_STD_CLK(sd, 3); - Do not touch DDR clock */
+DECLARE_STD_CLK(sata, 4);
+DECLARE_STD_CLK(audio, 5);
+DECLARE_STD_CLK(usbmph, 6);
+DECLARE_STD_CLKP(etha, 7, eth_parents);
+DECLARE_STD_CLK(pciea, 8);
+DECLARE_STD_CLK(nand, 9);
+
+static struct clk_hw *std_clk_hw_tbl[] = {
+	&clk_leon.hw,
+	&clk_dma_sgdma.hw,
+	&clk_cipher.hw,
+	&clk_sata.hw,
+	&clk_audio.hw,
+	&clk_usbmph.hw,
+	&clk_etha.hw,
+	&clk_pciea.hw,
+	&clk_nand.hw,
+};
+
+static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
+
+static struct clk_onecell_data std_clk_data;
+
+static void __init oxnas_init_stdclk(struct device_node *np)
+{
+	int i;
+	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
+
+	if (!regmap)
+		panic("failed to have parent regmap\n");
+
+	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
+		struct clk_std *std = container_of(std_clk_hw_tbl[i],
+						   struct clk_std, hw);
+
+		if (WARN_ON(!std))
+			return;
+		std->regmap = regmap;
+
+		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
+		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
+			return;
+	}
+
+	std_clk_data.clks = std_clk_tbl;
+	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
+}
+CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);
-- 
1.9.1

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

* [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-clk; +Cc: Neil Armstrong

Add PLX Technology OXNAS SoC Family Standard Clocks support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/Kconfig     |   6 ++
 drivers/clk/Makefile    |   1 +
 drivers/clk/clk-oxnas.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/clk/clk-oxnas.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index eca8e01..b75ef5c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -192,6 +192,12 @@ config COMMON_CLK_PXA
 	---help---
 	  Sypport for the Marvell PXA SoC.
 
+config COMMON_CLK_OXNAS
+	def_bool COMMON_CLK
+	select MFD_SYSCON
+	---help---
+	  Sypport for the OXNAS SoC Family clocks.
+
 config COMMON_CLK_CDCE706
 	tristate "Clock driver for TI CDCE706 clock synthesizer"
 	depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bae4be6..a5d45d8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_OXNAS)		+= clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
new file mode 100644
index 0000000..c4b903f
--- /dev/null
+++ b/drivers/clk/clk-oxnas.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Standard regmap gate clocks */
+struct clk_std {
+	struct clk_hw hw;
+	signed char bit;
+	struct regmap *regmap;
+};
+
+/* Regmap offsets */
+#define CLK_STAT_REGOFFSET	0x24
+#define CLK_SET_REGOFFSET	0x2c
+#define CLK_CLR_REGOFFSET	0x30
+
+#define NUM_STD_CLKS 10
+#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
+
+static int std_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(std->bit);
+}
+
+static int std_clk_enable(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+
+	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
+
+	return 0;
+}
+
+static void std_clk_disable(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+
+	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
+}
+
+static struct clk_ops std_clk_ops = {
+	.enable = std_clk_enable,
+	.disable = std_clk_disable,
+	.is_enabled = std_clk_is_enabled,
+};
+
+static const char *const std_clk_parents[] = {
+	"oscillator",
+};
+
+static const char *const eth_parents[] = {
+	"gmacclk",
+};
+
+#define DECLARE_STD_CLKP(__clk, __bit, __parent)	\
+static struct clk_init_data clk_##__clk##_init = {	\
+	.name = __stringify(__clk),			\
+	.ops = &std_clk_ops,				\
+	.parent_names = __parent,		\
+	.num_parents = ARRAY_SIZE(__parent),	\
+};							\
+							\
+static struct clk_std clk_##__clk = {			\
+	.bit = __bit,					\
+	.hw = {						\
+		.init = &clk_##__clk##_init,		\
+	},						\
+}
+
+#define DECLARE_STD_CLK(__clk, __bit) DECLARE_STD_CLKP(__clk, __bit, \
+							std_clk_parents)
+
+DECLARE_STD_CLK(leon, 0);
+DECLARE_STD_CLK(dma_sgdma, 1);
+DECLARE_STD_CLK(cipher, 2);
+/* DECLARE_STD_CLK(sd, 3); - Do not touch DDR clock */
+DECLARE_STD_CLK(sata, 4);
+DECLARE_STD_CLK(audio, 5);
+DECLARE_STD_CLK(usbmph, 6);
+DECLARE_STD_CLKP(etha, 7, eth_parents);
+DECLARE_STD_CLK(pciea, 8);
+DECLARE_STD_CLK(nand, 9);
+
+static struct clk_hw *std_clk_hw_tbl[] = {
+	&clk_leon.hw,
+	&clk_dma_sgdma.hw,
+	&clk_cipher.hw,
+	&clk_sata.hw,
+	&clk_audio.hw,
+	&clk_usbmph.hw,
+	&clk_etha.hw,
+	&clk_pciea.hw,
+	&clk_nand.hw,
+};
+
+static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
+
+static struct clk_onecell_data std_clk_data;
+
+static void __init oxnas_init_stdclk(struct device_node *np)
+{
+	int i;
+	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
+
+	if (!regmap)
+		panic("failed to have parent regmap\n");
+
+	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
+		struct clk_std *std = container_of(std_clk_hw_tbl[i],
+						   struct clk_std, hw);
+
+		if (WARN_ON(!std))
+			return;
+		std->regmap = regmap;
+
+		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
+		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
+			return;
+	}
+
+	std_clk_data.clks = std_clk_tbl;
+	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
+}
+CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Add PLX Technology OXNAS SoC Family Standard Clocks support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/Kconfig     |   6 ++
 drivers/clk/Makefile    |   1 +
 drivers/clk/clk-oxnas.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/clk/clk-oxnas.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index eca8e01..b75ef5c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -192,6 +192,12 @@ config COMMON_CLK_PXA
 	---help---
 	  Sypport for the Marvell PXA SoC.
 
+config COMMON_CLK_OXNAS
+	def_bool COMMON_CLK
+	select MFD_SYSCON
+	---help---
+	  Sypport for the OXNAS SoC Family clocks.
+
 config COMMON_CLK_CDCE706
 	tristate "Clock driver for TI CDCE706 clock synthesizer"
 	depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bae4be6..a5d45d8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_OXNAS)		+= clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
new file mode 100644
index 0000000..c4b903f
--- /dev/null
+++ b/drivers/clk/clk-oxnas.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Standard regmap gate clocks */
+struct clk_std {
+	struct clk_hw hw;
+	signed char bit;
+	struct regmap *regmap;
+};
+
+/* Regmap offsets */
+#define CLK_STAT_REGOFFSET	0x24
+#define CLK_SET_REGOFFSET	0x2c
+#define CLK_CLR_REGOFFSET	0x30
+
+#define NUM_STD_CLKS 10
+#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
+
+static int std_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(std->bit);
+}
+
+static int std_clk_enable(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+
+	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
+
+	return 0;
+}
+
+static void std_clk_disable(struct clk_hw *hw)
+{
+	struct clk_std *std = to_stdclk(hw);
+
+	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
+}
+
+static struct clk_ops std_clk_ops = {
+	.enable = std_clk_enable,
+	.disable = std_clk_disable,
+	.is_enabled = std_clk_is_enabled,
+};
+
+static const char *const std_clk_parents[] = {
+	"oscillator",
+};
+
+static const char *const eth_parents[] = {
+	"gmacclk",
+};
+
+#define DECLARE_STD_CLKP(__clk, __bit, __parent)	\
+static struct clk_init_data clk_##__clk##_init = {	\
+	.name = __stringify(__clk),			\
+	.ops = &std_clk_ops,				\
+	.parent_names = __parent,		\
+	.num_parents = ARRAY_SIZE(__parent),	\
+};							\
+							\
+static struct clk_std clk_##__clk = {			\
+	.bit = __bit,					\
+	.hw = {						\
+		.init = &clk_##__clk##_init,		\
+	},						\
+}
+
+#define DECLARE_STD_CLK(__clk, __bit) DECLARE_STD_CLKP(__clk, __bit, \
+							std_clk_parents)
+
+DECLARE_STD_CLK(leon, 0);
+DECLARE_STD_CLK(dma_sgdma, 1);
+DECLARE_STD_CLK(cipher, 2);
+/* DECLARE_STD_CLK(sd, 3); - Do not touch DDR clock */
+DECLARE_STD_CLK(sata, 4);
+DECLARE_STD_CLK(audio, 5);
+DECLARE_STD_CLK(usbmph, 6);
+DECLARE_STD_CLKP(etha, 7, eth_parents);
+DECLARE_STD_CLK(pciea, 8);
+DECLARE_STD_CLK(nand, 9);
+
+static struct clk_hw *std_clk_hw_tbl[] = {
+	&clk_leon.hw,
+	&clk_dma_sgdma.hw,
+	&clk_cipher.hw,
+	&clk_sata.hw,
+	&clk_audio.hw,
+	&clk_usbmph.hw,
+	&clk_etha.hw,
+	&clk_pciea.hw,
+	&clk_nand.hw,
+};
+
+static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
+
+static struct clk_onecell_data std_clk_data;
+
+static void __init oxnas_init_stdclk(struct device_node *np)
+{
+	int i;
+	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
+
+	if (!regmap)
+		panic("failed to have parent regmap\n");
+
+	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
+		struct clk_std *std = container_of(std_clk_hw_tbl[i],
+						   struct clk_std, hw);
+
+		if (WARN_ON(!std))
+			return;
+		std->regmap = regmap;
+
+		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
+		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
+			return;
+	}
+
+	std_clk_data.clks = std_clk_tbl;
+	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
+}
+CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);
-- 
1.9.1

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

* [PATCH 09/17] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/clock/plxtech,stdclk.txt   | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt

diff --git a/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
new file mode 100644
index 0000000..46465c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
@@ -0,0 +1,24 @@
+PLX Technology OXNAS SoC Family Standard Clocks
+================================================
+
+Please also refer to clock-bindings.txt in this directory for common clock
+bindings usage.
+
+Required properties:
+- compatible: Should be "plxtech,ox810se-stdclk" or "plxtech,nas782x-stdclk"
+- #clock-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+example:
+
+sys: sys-ctrl@000000 {
+	compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	stdclk: stdclk {
+		compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
+		#reset-cells = <1>;
+	};
+};
-- 
1.9.1

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

* [PATCH 09/17] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/clock/plxtech,stdclk.txt   | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt

diff --git a/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
new file mode 100644
index 0000000..46465c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
@@ -0,0 +1,24 @@
+PLX Technology OXNAS SoC Family Standard Clocks
+================================================
+
+Please also refer to clock-bindings.txt in this directory for common clock
+bindings usage.
+
+Required properties:
+- compatible: Should be "plxtech,ox810se-stdclk" or "plxtech,nas782x-stdclk"
+- #clock-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+example:
+
+sys: sys-ctrl at 000000 {
+	compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	stdclk: stdclk {
+		compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
+		#reset-cells = <1>;
+	};
+};
-- 
1.9.1

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

* [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  2016-03-03 11:39 ` Neil Armstrong
  (?)
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linus.walleij, linux-gpio
  Cc: Ma Haijun, Jean-Christophe PLAGNIOL-VILLARD, Neil Armstrong

Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

CC: Ma Haijun <mahaijuns@gmail.com>
CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/pinctrl/Kconfig         |    9 +
 drivers/pinctrl/Makefile        |    1 +
 drivers/pinctrl/pinctrl-oxnas.c | 1393 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1403 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 99a4c10..1d0c513 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -129,6 +129,15 @@ config PINCTRL_MESON
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_OXNAS
+	bool
+	depends on OF
+	select PINMUX
+	select PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select MFD_SYSCON
+
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bf1b5ca..3351d10 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_OXNAS)	+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
new file mode 100644
index 0000000..5dfd3a9
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -0,0 +1,1393 @@
+/*
+ * PLX Technology OXNAS Pinctrl driver based on at91 pinctrl driver
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Hajun <mahaijuns@gmail.com>
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+#include <linux/version.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK	32
+#define MAX_GPIO_BANKS		2
+
+struct oxnas_gpio_chip {
+	struct gpio_chip	chip;
+	struct pinctrl_gpio_range range;
+	void __iomem		*regbase;  /* GPIOA/B virtual address */
+	struct irq_domain	*domain;   /* associated irq domain */
+	struct regmap		*regmap;
+};
+
+#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)
+
+static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+/**
+ * struct oxnas_pmx_func - describes pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct oxnas_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+enum oxnas_mux {
+	OXNAS_PINMUX_GPIO,
+	OXNAS_PINMUX_FUNC1,
+	OXNAS_PINMUX_FUNC2,
+	OXNAS_PINMUX_FUNC3,
+};
+
+enum {
+	INPUT_VALUE = 0,
+	OUTPUT_ENABLE = 4,
+	IRQ_PENDING = 0xC,
+	OUTPUT_VALUE = 0x10,
+	OUTPUT_SET = 0x14,
+	OUTPUT_CLEAR = 0x18,
+	OUTPUT_EN_SET = 0x1C,
+	OUTPUT_EN_CLEAR = 0x20,
+	RE_IRQ_ENABLE = 0x28, /* rising edge */
+	FE_IRQ_ENABLE = 0x2C, /* falling edge */
+	RE_IRQ_PENDING = 0x30, /* rising edge */
+	FE_IRQ_PENDING = 0x34, /* falling edge */
+};
+
+enum {
+	PINMUX_PRIMARY_SEL0 = 0x0c,
+	PINMUX_PRIMARY_SEL1 = 0x10,
+	PINMUX_SECONDARY_SEL0 = 0x14,
+	PINMUX_SECONDARY_SEL1 = 0x18,
+	PINMUX_TERTIARY_SEL0 = 0x8c,
+	PINMUX_TERTIARY_SEL1 = 0x90,
+};
+
+/**
+ * struct oxnas_pmx_pin - describes an pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct oxnas_pmx_pin {
+	uint32_t	bank;
+	uint32_t	pin;
+	enum oxnas_mux	mux;
+	unsigned long	conf;
+};
+
+/**
+ * struct oxnas_pin_group - describes an pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *	array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ */
+struct oxnas_pin_group {
+	const char		*name;
+	struct oxnas_pmx_pin	*pins_conf;
+	unsigned int		*pins;
+	unsigned		npins;
+};
+
+struct oxnas_pinctrl {
+	struct device		*dev;
+	struct pinctrl_dev	*pctl;
+	struct regmap		*regmap;
+
+	int			nbanks;
+
+	uint32_t		*mux_mask;
+	int			nmux;
+
+	struct oxnas_pmx_func	*functions;
+	int			nfunctions;
+
+	struct oxnas_pin_group	*groups;
+	int			ngroups;
+};
+
+static const inline struct oxnas_pin_group *oxnas_pinctrl_find_group_by_name(
+				const struct oxnas_pinctrl *info,
+				const char *name)
+{
+	const struct oxnas_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (strcmp(info->groups[i].name, name))
+			continue;
+
+		grp = &info->groups[i];
+		dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins,
+			grp->pins[0]);
+		break;
+	}
+
+	return grp;
+}
+
+static int oxnas_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *oxnas_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int oxnas_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *npins)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void oxnas_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = oxnas_pinctrl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
+			       GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+		new_map[i].data.configs.num_configs = 1;
+	}
+
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static const struct pinctrl_ops oxnas_pctrl_ops = {
+	.get_groups_count	= oxnas_get_groups_count,
+	.get_group_name		= oxnas_get_group_name,
+	.get_group_pins		= oxnas_get_group_pins,
+	.pin_dbg_show		= oxnas_pin_dbg_show,
+	.dt_node_to_map		= oxnas_dt_node_to_map,
+	.dt_free_map		= oxnas_dt_free_map,
+};
+
+static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
+				 unsigned int bank)
+{
+	return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+	return pin / MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static void oxnas_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+	writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void oxnas_mux_set_func1(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func2(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func3(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, mask);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, mask);
+	}
+}
+
+static void oxnas_mux_set_gpio(struct oxnas_pinctrl *ctrl,
+			       unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static enum oxnas_mux oxnas_mux_get_func(struct regmap *regmap,
+					 unsigned bank, unsigned mask)
+{
+	unsigned int val;
+
+	if (!bank) {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	} else {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	}
+
+	return OXNAS_PINMUX_GPIO;
+}
+
+static void oxnas_pin_dbg(const struct device *dev,
+			  const struct oxnas_pmx_pin *pin)
+{
+	if (pin->mux) {
+		dev_dbg(dev,
+			"MF_%c%d configured as periph%c with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A',
+			pin->conf);
+	} else {
+		dev_dbg(dev, "MF_%c%d configured as gpio with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->conf);
+	}
+}
+
+static int pin_check_config(struct oxnas_pinctrl *info, const char *name,
+			    int index, const struct oxnas_pmx_pin *pin)
+{
+	int mux;
+
+	/* check if it's a valid config */
+	if (pin->bank >= info->nbanks) {
+		dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+			name, index, pin->bank, info->nbanks);
+		return -EINVAL;
+	}
+
+	if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+		dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+			name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+		return -EINVAL;
+	}
+	/* gpio always allowed */
+	if (!pin->mux)
+		return 0;
+
+	mux = pin->mux - 1;
+
+	if (mux >= info->nmux) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+			name, index, mux, info->nmux);
+		return -EINVAL;
+	}
+
+	if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for MF_%c%d\n",
+			name, index, mux, pin->bank + 'A', pin->pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void oxnas_mux_gpio_enable(struct oxnas_pinctrl *ctrl,
+				  int bank,
+				  void __iomem *pio,
+				  unsigned mask, bool input)
+{
+	oxnas_mux_set_gpio(ctrl, bank, mask);
+
+	if (input)
+		writel_relaxed(mask, pio + OUTPUT_EN_CLEAR);
+	else
+		writel_relaxed(mask, pio + OUTPUT_EN_SET);
+}
+
+static void oxnas_mux_gpio_disable(struct oxnas_pinctrl *ctrl,
+				   int bank,
+				   unsigned mask)
+{
+	/* when switch to other function, gpio is disabled automatically */
+}
+
+static int oxnas_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+			    unsigned group)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct oxnas_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i, ret;
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	/* first check that all the pins of the group are valid with a valid
+	 * parameter
+	 */
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		ret = pin_check_config(info, info->groups[group].name, i, pin);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		oxnas_pin_dbg(info->dev, pin);
+
+		pio = pin_to_gpioctrl(info, pin->bank);
+
+		mask = pin_to_mask(pin->pin);
+		oxnas_mux_disable_interrupt(pio, mask);
+
+		switch (pin->mux) {
+		case OXNAS_PINMUX_GPIO:
+			oxnas_mux_gpio_enable(info, pin->bank, pio, mask, 1);
+			break;
+		case OXNAS_PINMUX_FUNC1:
+			oxnas_mux_set_func1(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC2:
+			oxnas_mux_set_func2(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC3:
+			oxnas_mux_set_func3(info, pin->bank, mask);
+			break;
+		}
+		if (pin->mux)
+			oxnas_mux_gpio_disable(info, pin->bank, mask);
+	}
+
+	return 0;
+}
+
+static int oxnas_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+static const char *oxnas_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					   unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int oxnas_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_chip *oxnas_chip;
+	struct gpio_chip *chip;
+	unsigned mask;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	oxnas_chip = container_of(chip, struct oxnas_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	mask = 1 << (offset - chip->base);
+
+	dev_dbg(npct->dev, "enable pin %u as MF_%c%d 0x%x\n",
+		offset, 'A' + range->id, offset - chip->base, mask);
+
+	oxnas_mux_set_gpio(npct, range->id, mask);
+
+	return 0;
+}
+
+static void oxnas_gpio_disable_free(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static const struct pinmux_ops oxnas_pmx_ops = {
+	.get_functions_count	= oxnas_pmx_get_funcs_count,
+	.get_function_name	= oxnas_pmx_get_func_name,
+	.get_function_groups	= oxnas_pmx_get_groups,
+	.set_mux		= oxnas_pmx_set_mux,
+	.gpio_request_enable	= oxnas_gpio_request_enable,
+	.gpio_disable_free	= oxnas_gpio_disable_free,
+};
+
+static int oxnas_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static int oxnas_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *configs,
+			     unsigned num_configs)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static void oxnas_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void oxnas_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+}
+
+static const struct pinconf_ops oxnas_pinconf_ops = {
+	.pin_config_get			= oxnas_pinconf_get,
+	.pin_config_set			= oxnas_pinconf_set,
+	.pin_config_dbg_show		= oxnas_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= oxnas_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc oxnas_pinctrl_desc = {
+	.pctlops	= &oxnas_pctrl_ops,
+	.pmxops		= &oxnas_pmx_ops,
+	.confops	= &oxnas_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
+static const char *gpio_compat = "plxtech,nas782x-gpio";
+
+static void oxnas_pinctrl_child_count(struct oxnas_pinctrl *info,
+				      struct device_node *np)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int oxnas_pinctrl_mux_mask(struct oxnas_pinctrl *info,
+				  struct device_node *np)
+{
+	int ret = 0;
+	int size;
+	const __be32 *list;
+
+	list = of_get_property(np, "plxtech,mux-mask", &size);
+	if (!list) {
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+		return -EINVAL;
+	}
+
+	size /= sizeof(*list);
+	if (!size || size % info->nbanks) {
+		dev_err(info->dev, "wrong mux mask array should be by %d\n",
+			info->nbanks);
+		return -EINVAL;
+	}
+	info->nmux = size / info->nbanks;
+
+	info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size,
+				      GFP_KERNEL);
+	if (!info->mux_mask)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(np, "plxtech,mux-mask",
+					  info->mux_mask, size);
+	if (ret)
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+	return ret;
+}
+
+static int oxnas_pinctrl_parse_groups(struct device_node *np,
+				      struct oxnas_pin_group *grp,
+				      struct oxnas_pinctrl *info, u32 index)
+{
+	struct oxnas_pmx_pin *pin;
+	int size;
+	const __be32 *list;
+	int i, j;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is plxtech,pins = <bank pin mux CONFIG ...>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "plxtech,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	size /= sizeof(*list);
+	if (!size || size % 4) {
+		dev_err(info->dev, "wrong pins number or pins and configs should be divisible by 4\n");
+		return -EINVAL;
+	}
+
+	grp->npins = size / 4;
+	pin = grp->pins_conf = devm_kzalloc(info->dev,
+				grp->npins * sizeof(struct oxnas_pmx_pin),
+				GFP_KERNEL);
+	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
+	if (!grp->pins_conf || !grp->pins)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < size; i += 4, j++) {
+		pin->bank = be32_to_cpu(*list++);
+		pin->pin = be32_to_cpu(*list++);
+		grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+		pin->mux = be32_to_cpu(*list++);
+		pin->conf = be32_to_cpu(*list++);
+
+		oxnas_pin_dbg(info->dev, pin);
+		pin++;
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_parse_functions(struct device_node *np,
+					struct oxnas_pinctrl *info, u32 index)
+{
+	struct device_node *child;
+	struct oxnas_pmx_func *func;
+	struct oxnas_pin_group *grp;
+	int ret;
+	static u32 grp_index;
+	u32 i = 0;
+
+	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &info->functions[index];
+
+	/* Initialise function */
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "no groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[grp_index++];
+		ret = oxnas_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+	{ .compatible = "plxtech,nas782x-pinctrl"},
+	{ .compatible = "plxtech,ox810se-pinctrl"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_pinctrl_probe_dt(struct platform_device *pdev,
+				 struct oxnas_pinctrl *info)
+{
+	int ret = 0;
+	int i, j;
+	uint32_t *tmp;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+
+	if (!np)
+		return -ENODEV;
+
+	info->dev = &pdev->dev;
+
+	oxnas_pinctrl_child_count(info, np);
+
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		return -EINVAL;
+	}
+
+	ret = oxnas_pinctrl_mux_mask(info, np);
+	if (ret)
+		return ret;
+
+	dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+	dev_dbg(&pdev->dev, "mux-mask\n");
+	tmp = info->mux_mask;
+	for (i = 0; i < info->nbanks; i++)
+		for (j = 0; j < info->nmux; j++, tmp++)
+			dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev, info->nfunctions *
+						sizeof(struct oxnas_pmx_func),
+					GFP_KERNEL);
+	if (!info->functions)
+		return -ENOMEM;
+
+	info->groups = devm_kzalloc(&pdev->dev, info->ngroups *
+					sizeof(struct oxnas_pin_group),
+				    GFP_KERNEL);
+	if (!info->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+	i = 0;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat))
+			continue;
+		ret = oxnas_pinctrl_parse_functions(child, info, i++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_probe(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info;
+	struct pinctrl_pin_desc *pdesc;
+	int ret, i, j, k;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						       "plxtech,sys-ctrl");
+	if (IS_ERR(info->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	ret = oxnas_pinctrl_probe_dt(pdev, info);
+	if (ret)
+		return ret;
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < info->nbanks; i++) {
+		if (!gpio_chips[i]) {
+			dev_warn(&pdev->dev,
+				 "GPIO chip %d not registered yet\n", i);
+			devm_kfree(&pdev->dev, info);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	oxnas_pinctrl_desc.name = dev_name(&pdev->dev);
+	oxnas_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+	oxnas_pinctrl_desc.pins = pdesc =
+		devm_kzalloc(&pdev->dev, sizeof(*pdesc) *
+				oxnas_pinctrl_desc.npins, GFP_KERNEL);
+
+	if (!oxnas_pinctrl_desc.pins)
+		return -ENOMEM;
+
+	for (i = 0, k = 0; i < info->nbanks; i++) {
+		for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+			pdesc->number = k;
+			pdesc->name = kasprintf(GFP_KERNEL, "MF_%c%d", i + 'A',
+						j);
+			pdesc++;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+	info->pctl = pinctrl_register(&oxnas_pinctrl_desc, &pdev->dev, info);
+
+	if (!info->pctl) {
+		dev_err(&pdev->dev, "could not register OXNAS pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+	dev_info(&pdev->dev, "initialized OXNAS pinctrl driver\n");
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int oxnas_pinctrl_remove(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(info->pctl);
+
+	return 0;
+}
+
+static int oxnas_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+	int bank = chip->base / chip->ngpio;
+
+	dev_dbg(chip->parent, "%s:%d MF_%c%d(%d)\n", __func__, __LINE__,
+		'A' + bank, offset, gpio);
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void oxnas_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int oxnas_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_CLEAR);
+	return 0;
+}
+
+static int oxnas_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 pdsr = 0;
+
+	pdsr = readl_relaxed(pio + INPUT_VALUE);
+	return (pdsr & mask) != 0;
+}
+
+static void oxnas_gpio_set(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+}
+
+static int oxnas_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_SET);
+
+	return 0;
+}
+
+static int oxnas_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	int virq;
+
+	if (offset < chip->ngpio)
+		virq = irq_create_mapping(oxnas_gpio->domain, offset);
+	else
+		virq = -ENXIO;
+
+	dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n",
+				chip->label, offset + chip->base, virq);
+	return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void oxnas_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int i;
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	enum oxnas_mux mux;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		unsigned mask = pin_to_mask(pin);
+		unsigned bank = pin_to_bank(pin);
+		const char *gpio_label;
+		u32 pdsr;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (gpio_label) {
+			seq_printf(s, "[%s]\tGPIO%s%d: ",
+				   gpio_label, chip->label, i);
+			pdsr = readl_relaxed(pio + INPUT_VALUE);
+
+			seq_printf(s, "[gpio] %s\n",
+					pdsr & mask ?
+					"set" : "clear");
+		} else {
+			mux = oxnas_mux_get_func(oxnas_gpio->regmap,
+						 bank,
+						 mask);
+			seq_printf(s, "\tGPIO%s%d: [func%d]\n",
+				   chip->label, i, mux);
+		}
+
+	}
+}
+#else
+#define oxnas_gpio_dbg_show	NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * oxnas_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) | mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) | mask, pio + FE_IRQ_ENABLE);
+}
+
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
+		pr_warn("oxnas: Unsupported type for irq %d\n",
+			gpio_to_irq(d->irq));
+		return -EINVAL;
+	}
+	/* seems no way to set trigger type without enable irq,
+	 * so leave it to unmask time
+	 */
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
+};
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned long isr;
+	int n;
+
+	chained_irq_enter(chip, desc);
+	for (;;) {
+		isr = readl_relaxed(pio + IRQ_PENDING);
+		if (!isr)
+			break;
+
+		/* acks pending interrupts */
+		writel_relaxed(isr, pio + IRQ_PENDING);
+
+		for_each_set_bit(n, &isr, BITS_PER_LONG) {
+			generic_handle_irq(irq_find_mapping(oxnas_gpio->domain,
+							    n));
+		}
+	}
+	chained_irq_exit(chip, desc);
+	/* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
+
+	irq_set_lockdep_class(virq, &gpio_lock_class);
+
+	irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);
+
+	irq_set_chip_data(virq, oxnas_gpio);
+
+	return 0;
+}
+
+static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
+				       struct device_node *ctrlr,
+				       const u32 *intspec,
+				       unsigned int intsize,
+				       irq_hw_number_t *out_hwirq,
+				       unsigned int *out_type)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
+	int ret;
+	int pin = oxnas_gpio->chip.base + intspec[0];
+
+	if (WARN_ON(intsize < 2))
+		return -EINVAL;
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	ret = gpio_request(pin, ctrlr->full_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_direction_input(pin);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct irq_domain_ops oxnas_gpio_ops = {
+	.map	= oxnas_gpio_irq_map,
+	.xlate	= oxnas_gpio_irq_domain_xlate,
+};
+
+static int oxnas_gpio_of_irq_setup(struct device_node *node,
+				   struct oxnas_gpio_chip *oxnas_gpio,
+				   unsigned int irq)
+{
+	/* Disable irqs of this controller */
+	writel_relaxed(0, oxnas_gpio->regbase + RE_IRQ_ENABLE);
+	writel_relaxed(0, oxnas_gpio->regbase + FE_IRQ_ENABLE);
+
+	/* Setup irq domain */
+	oxnas_gpio->domain = irq_domain_add_linear(node, oxnas_gpio->chip.ngpio,
+						   &oxnas_gpio_ops, oxnas_gpio);
+	if (!oxnas_gpio->domain)
+		panic("oxnas_gpio: couldn't allocate irq domain (DT).\n");
+
+	irq_set_chip_data(irq, oxnas_gpio);
+	irq_set_chained_handler(irq, gpio_irq_handler);
+
+	return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip oxnas_gpio_template = {
+	.request		= oxnas_gpio_request,
+	.free			= oxnas_gpio_free,
+	.direction_input	= oxnas_gpio_direction_input,
+	.get			= oxnas_gpio_get,
+	.direction_output	= oxnas_gpio_direction_output,
+	.set			= oxnas_gpio_set,
+	.to_irq			= oxnas_gpio_to_irq,
+	.dbg_show		= oxnas_gpio_dbg_show,
+	.can_sleep		= 0,
+	.ngpio			= MAX_NB_GPIO_PER_BANK,
+};
+
+static const struct of_device_id oxnas_gpio_of_match[] = {
+	{ .compatible = "plxtech,nas782x-gpio"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct oxnas_gpio_chip *oxnas_chip = NULL;
+	struct gpio_chip *chip;
+	struct pinctrl_gpio_range *range;
+	struct device_node *node = pdev->dev.of_node;
+	int ret = 0;
+	int irq, i;
+	int alias_idx = of_alias_get_id(np, "gpio");
+	uint32_t ngpio;
+	char **names;
+
+	if (WARN_ON(alias_idx >= ARRAY_SIZE(gpio_chips)))
+		return -EINVAL;
+
+	if (gpio_chips[alias_idx]) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err;
+	}
+
+	oxnas_chip = devm_kzalloc(&pdev->dev, sizeof(*oxnas_chip), GFP_KERNEL);
+	if (!oxnas_chip) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Get pinctrl sys control regmap */
+	oxnas_chip->regmap =
+		syscon_regmap_lookup_by_phandle(of_get_parent(node),
+						"plxtech,sys-ctrl");
+	if (IS_ERR(oxnas_chip->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	oxnas_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oxnas_chip->regbase)) {
+		ret = PTR_ERR(oxnas_chip->regbase);
+		goto err;
+	}
+
+	oxnas_chip->chip = oxnas_gpio_template;
+
+	chip = &oxnas_chip->chip;
+	chip->of_node = np;
+	chip->label = dev_name(&pdev->dev);
+	chip->parent = &pdev->dev;
+	chip->owner = THIS_MODULE;
+	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+		if (ngpio > MAX_NB_GPIO_PER_BANK)
+			pr_err("oxnas_gpio.%d, gpio-nb >= %d failback to %d\n",
+			       alias_idx, MAX_NB_GPIO_PER_BANK,
+			       MAX_NB_GPIO_PER_BANK);
+		else
+			chip->ngpio = ngpio;
+	}
+
+	names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+			     GFP_KERNEL);
+
+	if (!names) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < chip->ngpio; i++)
+		names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
+
+	chip->names = (const char *const *)names;
+
+	range = &oxnas_chip->range;
+	range->name = chip->label;
+	range->id = alias_idx;
+	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+	range->npins = chip->ngpio;
+	range->gc = chip;
+
+	ret = gpiochip_add(chip);
+	if (ret)
+		goto err;
+
+	gpio_chips[alias_idx] = oxnas_chip;
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+
+	oxnas_gpio_of_irq_setup(np, oxnas_chip, irq);
+
+	dev_info(&pdev->dev, "at address %p\n", oxnas_chip->regbase);
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+	return ret;
+}
+
+static struct platform_driver oxnas_gpio_driver = {
+	.driver = {
+		.name = "gpio-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_gpio_of_match),
+	},
+	.probe = oxnas_gpio_probe,
+};
+
+static struct platform_driver oxnas_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_pinctrl_of_match),
+	},
+	.probe = oxnas_pinctrl_probe,
+	.remove = oxnas_pinctrl_remove,
+};
+
+static int __init oxnas_pinctrl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&oxnas_gpio_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&oxnas_pinctrl_driver);
+}
+arch_initcall(oxnas_pinctrl_init);
+
+static void __exit oxnas_pinctrl_exit(void)
+{
+	platform_driver_unregister(&oxnas_pinctrl_driver);
+}
+
+module_exit(oxnas_pinctrl_exit);
-- 
1.9.1

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

* [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linus.walleij, linux-gpio
  Cc: Neil Armstrong, Ma Haijun, Jean-Christophe PLAGNIOL-VILLARD

Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

CC: Ma Haijun <mahaijuns@gmail.com>
CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/pinctrl/Kconfig         |    9 +
 drivers/pinctrl/Makefile        |    1 +
 drivers/pinctrl/pinctrl-oxnas.c | 1393 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1403 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 99a4c10..1d0c513 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -129,6 +129,15 @@ config PINCTRL_MESON
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_OXNAS
+	bool
+	depends on OF
+	select PINMUX
+	select PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select MFD_SYSCON
+
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bf1b5ca..3351d10 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_OXNAS)	+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
new file mode 100644
index 0000000..5dfd3a9
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -0,0 +1,1393 @@
+/*
+ * PLX Technology OXNAS Pinctrl driver based on at91 pinctrl driver
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Hajun <mahaijuns@gmail.com>
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+#include <linux/version.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK	32
+#define MAX_GPIO_BANKS		2
+
+struct oxnas_gpio_chip {
+	struct gpio_chip	chip;
+	struct pinctrl_gpio_range range;
+	void __iomem		*regbase;  /* GPIOA/B virtual address */
+	struct irq_domain	*domain;   /* associated irq domain */
+	struct regmap		*regmap;
+};
+
+#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)
+
+static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+/**
+ * struct oxnas_pmx_func - describes pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct oxnas_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+enum oxnas_mux {
+	OXNAS_PINMUX_GPIO,
+	OXNAS_PINMUX_FUNC1,
+	OXNAS_PINMUX_FUNC2,
+	OXNAS_PINMUX_FUNC3,
+};
+
+enum {
+	INPUT_VALUE = 0,
+	OUTPUT_ENABLE = 4,
+	IRQ_PENDING = 0xC,
+	OUTPUT_VALUE = 0x10,
+	OUTPUT_SET = 0x14,
+	OUTPUT_CLEAR = 0x18,
+	OUTPUT_EN_SET = 0x1C,
+	OUTPUT_EN_CLEAR = 0x20,
+	RE_IRQ_ENABLE = 0x28, /* rising edge */
+	FE_IRQ_ENABLE = 0x2C, /* falling edge */
+	RE_IRQ_PENDING = 0x30, /* rising edge */
+	FE_IRQ_PENDING = 0x34, /* falling edge */
+};
+
+enum {
+	PINMUX_PRIMARY_SEL0 = 0x0c,
+	PINMUX_PRIMARY_SEL1 = 0x10,
+	PINMUX_SECONDARY_SEL0 = 0x14,
+	PINMUX_SECONDARY_SEL1 = 0x18,
+	PINMUX_TERTIARY_SEL0 = 0x8c,
+	PINMUX_TERTIARY_SEL1 = 0x90,
+};
+
+/**
+ * struct oxnas_pmx_pin - describes an pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct oxnas_pmx_pin {
+	uint32_t	bank;
+	uint32_t	pin;
+	enum oxnas_mux	mux;
+	unsigned long	conf;
+};
+
+/**
+ * struct oxnas_pin_group - describes an pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *	array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ */
+struct oxnas_pin_group {
+	const char		*name;
+	struct oxnas_pmx_pin	*pins_conf;
+	unsigned int		*pins;
+	unsigned		npins;
+};
+
+struct oxnas_pinctrl {
+	struct device		*dev;
+	struct pinctrl_dev	*pctl;
+	struct regmap		*regmap;
+
+	int			nbanks;
+
+	uint32_t		*mux_mask;
+	int			nmux;
+
+	struct oxnas_pmx_func	*functions;
+	int			nfunctions;
+
+	struct oxnas_pin_group	*groups;
+	int			ngroups;
+};
+
+static const inline struct oxnas_pin_group *oxnas_pinctrl_find_group_by_name(
+				const struct oxnas_pinctrl *info,
+				const char *name)
+{
+	const struct oxnas_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (strcmp(info->groups[i].name, name))
+			continue;
+
+		grp = &info->groups[i];
+		dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins,
+			grp->pins[0]);
+		break;
+	}
+
+	return grp;
+}
+
+static int oxnas_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *oxnas_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int oxnas_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *npins)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void oxnas_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = oxnas_pinctrl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
+			       GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+		new_map[i].data.configs.num_configs = 1;
+	}
+
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static const struct pinctrl_ops oxnas_pctrl_ops = {
+	.get_groups_count	= oxnas_get_groups_count,
+	.get_group_name		= oxnas_get_group_name,
+	.get_group_pins		= oxnas_get_group_pins,
+	.pin_dbg_show		= oxnas_pin_dbg_show,
+	.dt_node_to_map		= oxnas_dt_node_to_map,
+	.dt_free_map		= oxnas_dt_free_map,
+};
+
+static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
+				 unsigned int bank)
+{
+	return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+	return pin / MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static void oxnas_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+	writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void oxnas_mux_set_func1(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func2(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func3(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, mask);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, mask);
+	}
+}
+
+static void oxnas_mux_set_gpio(struct oxnas_pinctrl *ctrl,
+			       unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static enum oxnas_mux oxnas_mux_get_func(struct regmap *regmap,
+					 unsigned bank, unsigned mask)
+{
+	unsigned int val;
+
+	if (!bank) {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	} else {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	}
+
+	return OXNAS_PINMUX_GPIO;
+}
+
+static void oxnas_pin_dbg(const struct device *dev,
+			  const struct oxnas_pmx_pin *pin)
+{
+	if (pin->mux) {
+		dev_dbg(dev,
+			"MF_%c%d configured as periph%c with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A',
+			pin->conf);
+	} else {
+		dev_dbg(dev, "MF_%c%d configured as gpio with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->conf);
+	}
+}
+
+static int pin_check_config(struct oxnas_pinctrl *info, const char *name,
+			    int index, const struct oxnas_pmx_pin *pin)
+{
+	int mux;
+
+	/* check if it's a valid config */
+	if (pin->bank >= info->nbanks) {
+		dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+			name, index, pin->bank, info->nbanks);
+		return -EINVAL;
+	}
+
+	if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+		dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+			name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+		return -EINVAL;
+	}
+	/* gpio always allowed */
+	if (!pin->mux)
+		return 0;
+
+	mux = pin->mux - 1;
+
+	if (mux >= info->nmux) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+			name, index, mux, info->nmux);
+		return -EINVAL;
+	}
+
+	if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for MF_%c%d\n",
+			name, index, mux, pin->bank + 'A', pin->pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void oxnas_mux_gpio_enable(struct oxnas_pinctrl *ctrl,
+				  int bank,
+				  void __iomem *pio,
+				  unsigned mask, bool input)
+{
+	oxnas_mux_set_gpio(ctrl, bank, mask);
+
+	if (input)
+		writel_relaxed(mask, pio + OUTPUT_EN_CLEAR);
+	else
+		writel_relaxed(mask, pio + OUTPUT_EN_SET);
+}
+
+static void oxnas_mux_gpio_disable(struct oxnas_pinctrl *ctrl,
+				   int bank,
+				   unsigned mask)
+{
+	/* when switch to other function, gpio is disabled automatically */
+}
+
+static int oxnas_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+			    unsigned group)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct oxnas_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i, ret;
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	/* first check that all the pins of the group are valid with a valid
+	 * parameter
+	 */
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		ret = pin_check_config(info, info->groups[group].name, i, pin);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		oxnas_pin_dbg(info->dev, pin);
+
+		pio = pin_to_gpioctrl(info, pin->bank);
+
+		mask = pin_to_mask(pin->pin);
+		oxnas_mux_disable_interrupt(pio, mask);
+
+		switch (pin->mux) {
+		case OXNAS_PINMUX_GPIO:
+			oxnas_mux_gpio_enable(info, pin->bank, pio, mask, 1);
+			break;
+		case OXNAS_PINMUX_FUNC1:
+			oxnas_mux_set_func1(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC2:
+			oxnas_mux_set_func2(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC3:
+			oxnas_mux_set_func3(info, pin->bank, mask);
+			break;
+		}
+		if (pin->mux)
+			oxnas_mux_gpio_disable(info, pin->bank, mask);
+	}
+
+	return 0;
+}
+
+static int oxnas_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+static const char *oxnas_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					   unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int oxnas_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_chip *oxnas_chip;
+	struct gpio_chip *chip;
+	unsigned mask;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	oxnas_chip = container_of(chip, struct oxnas_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	mask = 1 << (offset - chip->base);
+
+	dev_dbg(npct->dev, "enable pin %u as MF_%c%d 0x%x\n",
+		offset, 'A' + range->id, offset - chip->base, mask);
+
+	oxnas_mux_set_gpio(npct, range->id, mask);
+
+	return 0;
+}
+
+static void oxnas_gpio_disable_free(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static const struct pinmux_ops oxnas_pmx_ops = {
+	.get_functions_count	= oxnas_pmx_get_funcs_count,
+	.get_function_name	= oxnas_pmx_get_func_name,
+	.get_function_groups	= oxnas_pmx_get_groups,
+	.set_mux		= oxnas_pmx_set_mux,
+	.gpio_request_enable	= oxnas_gpio_request_enable,
+	.gpio_disable_free	= oxnas_gpio_disable_free,
+};
+
+static int oxnas_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static int oxnas_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *configs,
+			     unsigned num_configs)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static void oxnas_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void oxnas_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+}
+
+static const struct pinconf_ops oxnas_pinconf_ops = {
+	.pin_config_get			= oxnas_pinconf_get,
+	.pin_config_set			= oxnas_pinconf_set,
+	.pin_config_dbg_show		= oxnas_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= oxnas_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc oxnas_pinctrl_desc = {
+	.pctlops	= &oxnas_pctrl_ops,
+	.pmxops		= &oxnas_pmx_ops,
+	.confops	= &oxnas_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
+static const char *gpio_compat = "plxtech,nas782x-gpio";
+
+static void oxnas_pinctrl_child_count(struct oxnas_pinctrl *info,
+				      struct device_node *np)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int oxnas_pinctrl_mux_mask(struct oxnas_pinctrl *info,
+				  struct device_node *np)
+{
+	int ret = 0;
+	int size;
+	const __be32 *list;
+
+	list = of_get_property(np, "plxtech,mux-mask", &size);
+	if (!list) {
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+		return -EINVAL;
+	}
+
+	size /= sizeof(*list);
+	if (!size || size % info->nbanks) {
+		dev_err(info->dev, "wrong mux mask array should be by %d\n",
+			info->nbanks);
+		return -EINVAL;
+	}
+	info->nmux = size / info->nbanks;
+
+	info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size,
+				      GFP_KERNEL);
+	if (!info->mux_mask)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(np, "plxtech,mux-mask",
+					  info->mux_mask, size);
+	if (ret)
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+	return ret;
+}
+
+static int oxnas_pinctrl_parse_groups(struct device_node *np,
+				      struct oxnas_pin_group *grp,
+				      struct oxnas_pinctrl *info, u32 index)
+{
+	struct oxnas_pmx_pin *pin;
+	int size;
+	const __be32 *list;
+	int i, j;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is plxtech,pins = <bank pin mux CONFIG ...>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "plxtech,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	size /= sizeof(*list);
+	if (!size || size % 4) {
+		dev_err(info->dev, "wrong pins number or pins and configs should be divisible by 4\n");
+		return -EINVAL;
+	}
+
+	grp->npins = size / 4;
+	pin = grp->pins_conf = devm_kzalloc(info->dev,
+				grp->npins * sizeof(struct oxnas_pmx_pin),
+				GFP_KERNEL);
+	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
+	if (!grp->pins_conf || !grp->pins)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < size; i += 4, j++) {
+		pin->bank = be32_to_cpu(*list++);
+		pin->pin = be32_to_cpu(*list++);
+		grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+		pin->mux = be32_to_cpu(*list++);
+		pin->conf = be32_to_cpu(*list++);
+
+		oxnas_pin_dbg(info->dev, pin);
+		pin++;
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_parse_functions(struct device_node *np,
+					struct oxnas_pinctrl *info, u32 index)
+{
+	struct device_node *child;
+	struct oxnas_pmx_func *func;
+	struct oxnas_pin_group *grp;
+	int ret;
+	static u32 grp_index;
+	u32 i = 0;
+
+	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &info->functions[index];
+
+	/* Initialise function */
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "no groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[grp_index++];
+		ret = oxnas_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+	{ .compatible = "plxtech,nas782x-pinctrl"},
+	{ .compatible = "plxtech,ox810se-pinctrl"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_pinctrl_probe_dt(struct platform_device *pdev,
+				 struct oxnas_pinctrl *info)
+{
+	int ret = 0;
+	int i, j;
+	uint32_t *tmp;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+
+	if (!np)
+		return -ENODEV;
+
+	info->dev = &pdev->dev;
+
+	oxnas_pinctrl_child_count(info, np);
+
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		return -EINVAL;
+	}
+
+	ret = oxnas_pinctrl_mux_mask(info, np);
+	if (ret)
+		return ret;
+
+	dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+	dev_dbg(&pdev->dev, "mux-mask\n");
+	tmp = info->mux_mask;
+	for (i = 0; i < info->nbanks; i++)
+		for (j = 0; j < info->nmux; j++, tmp++)
+			dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev, info->nfunctions *
+						sizeof(struct oxnas_pmx_func),
+					GFP_KERNEL);
+	if (!info->functions)
+		return -ENOMEM;
+
+	info->groups = devm_kzalloc(&pdev->dev, info->ngroups *
+					sizeof(struct oxnas_pin_group),
+				    GFP_KERNEL);
+	if (!info->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+	i = 0;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat))
+			continue;
+		ret = oxnas_pinctrl_parse_functions(child, info, i++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_probe(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info;
+	struct pinctrl_pin_desc *pdesc;
+	int ret, i, j, k;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						       "plxtech,sys-ctrl");
+	if (IS_ERR(info->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	ret = oxnas_pinctrl_probe_dt(pdev, info);
+	if (ret)
+		return ret;
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < info->nbanks; i++) {
+		if (!gpio_chips[i]) {
+			dev_warn(&pdev->dev,
+				 "GPIO chip %d not registered yet\n", i);
+			devm_kfree(&pdev->dev, info);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	oxnas_pinctrl_desc.name = dev_name(&pdev->dev);
+	oxnas_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+	oxnas_pinctrl_desc.pins = pdesc =
+		devm_kzalloc(&pdev->dev, sizeof(*pdesc) *
+				oxnas_pinctrl_desc.npins, GFP_KERNEL);
+
+	if (!oxnas_pinctrl_desc.pins)
+		return -ENOMEM;
+
+	for (i = 0, k = 0; i < info->nbanks; i++) {
+		for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+			pdesc->number = k;
+			pdesc->name = kasprintf(GFP_KERNEL, "MF_%c%d", i + 'A',
+						j);
+			pdesc++;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+	info->pctl = pinctrl_register(&oxnas_pinctrl_desc, &pdev->dev, info);
+
+	if (!info->pctl) {
+		dev_err(&pdev->dev, "could not register OXNAS pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+	dev_info(&pdev->dev, "initialized OXNAS pinctrl driver\n");
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int oxnas_pinctrl_remove(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(info->pctl);
+
+	return 0;
+}
+
+static int oxnas_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+	int bank = chip->base / chip->ngpio;
+
+	dev_dbg(chip->parent, "%s:%d MF_%c%d(%d)\n", __func__, __LINE__,
+		'A' + bank, offset, gpio);
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void oxnas_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int oxnas_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_CLEAR);
+	return 0;
+}
+
+static int oxnas_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 pdsr = 0;
+
+	pdsr = readl_relaxed(pio + INPUT_VALUE);
+	return (pdsr & mask) != 0;
+}
+
+static void oxnas_gpio_set(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+}
+
+static int oxnas_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_SET);
+
+	return 0;
+}
+
+static int oxnas_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	int virq;
+
+	if (offset < chip->ngpio)
+		virq = irq_create_mapping(oxnas_gpio->domain, offset);
+	else
+		virq = -ENXIO;
+
+	dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n",
+				chip->label, offset + chip->base, virq);
+	return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void oxnas_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int i;
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	enum oxnas_mux mux;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		unsigned mask = pin_to_mask(pin);
+		unsigned bank = pin_to_bank(pin);
+		const char *gpio_label;
+		u32 pdsr;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (gpio_label) {
+			seq_printf(s, "[%s]\tGPIO%s%d: ",
+				   gpio_label, chip->label, i);
+			pdsr = readl_relaxed(pio + INPUT_VALUE);
+
+			seq_printf(s, "[gpio] %s\n",
+					pdsr & mask ?
+					"set" : "clear");
+		} else {
+			mux = oxnas_mux_get_func(oxnas_gpio->regmap,
+						 bank,
+						 mask);
+			seq_printf(s, "\tGPIO%s%d: [func%d]\n",
+				   chip->label, i, mux);
+		}
+
+	}
+}
+#else
+#define oxnas_gpio_dbg_show	NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * oxnas_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) | mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) | mask, pio + FE_IRQ_ENABLE);
+}
+
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
+		pr_warn("oxnas: Unsupported type for irq %d\n",
+			gpio_to_irq(d->irq));
+		return -EINVAL;
+	}
+	/* seems no way to set trigger type without enable irq,
+	 * so leave it to unmask time
+	 */
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
+};
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned long isr;
+	int n;
+
+	chained_irq_enter(chip, desc);
+	for (;;) {
+		isr = readl_relaxed(pio + IRQ_PENDING);
+		if (!isr)
+			break;
+
+		/* acks pending interrupts */
+		writel_relaxed(isr, pio + IRQ_PENDING);
+
+		for_each_set_bit(n, &isr, BITS_PER_LONG) {
+			generic_handle_irq(irq_find_mapping(oxnas_gpio->domain,
+							    n));
+		}
+	}
+	chained_irq_exit(chip, desc);
+	/* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
+
+	irq_set_lockdep_class(virq, &gpio_lock_class);
+
+	irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);
+
+	irq_set_chip_data(virq, oxnas_gpio);
+
+	return 0;
+}
+
+static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
+				       struct device_node *ctrlr,
+				       const u32 *intspec,
+				       unsigned int intsize,
+				       irq_hw_number_t *out_hwirq,
+				       unsigned int *out_type)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
+	int ret;
+	int pin = oxnas_gpio->chip.base + intspec[0];
+
+	if (WARN_ON(intsize < 2))
+		return -EINVAL;
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	ret = gpio_request(pin, ctrlr->full_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_direction_input(pin);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct irq_domain_ops oxnas_gpio_ops = {
+	.map	= oxnas_gpio_irq_map,
+	.xlate	= oxnas_gpio_irq_domain_xlate,
+};
+
+static int oxnas_gpio_of_irq_setup(struct device_node *node,
+				   struct oxnas_gpio_chip *oxnas_gpio,
+				   unsigned int irq)
+{
+	/* Disable irqs of this controller */
+	writel_relaxed(0, oxnas_gpio->regbase + RE_IRQ_ENABLE);
+	writel_relaxed(0, oxnas_gpio->regbase + FE_IRQ_ENABLE);
+
+	/* Setup irq domain */
+	oxnas_gpio->domain = irq_domain_add_linear(node, oxnas_gpio->chip.ngpio,
+						   &oxnas_gpio_ops, oxnas_gpio);
+	if (!oxnas_gpio->domain)
+		panic("oxnas_gpio: couldn't allocate irq domain (DT).\n");
+
+	irq_set_chip_data(irq, oxnas_gpio);
+	irq_set_chained_handler(irq, gpio_irq_handler);
+
+	return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip oxnas_gpio_template = {
+	.request		= oxnas_gpio_request,
+	.free			= oxnas_gpio_free,
+	.direction_input	= oxnas_gpio_direction_input,
+	.get			= oxnas_gpio_get,
+	.direction_output	= oxnas_gpio_direction_output,
+	.set			= oxnas_gpio_set,
+	.to_irq			= oxnas_gpio_to_irq,
+	.dbg_show		= oxnas_gpio_dbg_show,
+	.can_sleep		= 0,
+	.ngpio			= MAX_NB_GPIO_PER_BANK,
+};
+
+static const struct of_device_id oxnas_gpio_of_match[] = {
+	{ .compatible = "plxtech,nas782x-gpio"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct oxnas_gpio_chip *oxnas_chip = NULL;
+	struct gpio_chip *chip;
+	struct pinctrl_gpio_range *range;
+	struct device_node *node = pdev->dev.of_node;
+	int ret = 0;
+	int irq, i;
+	int alias_idx = of_alias_get_id(np, "gpio");
+	uint32_t ngpio;
+	char **names;
+
+	if (WARN_ON(alias_idx >= ARRAY_SIZE(gpio_chips)))
+		return -EINVAL;
+
+	if (gpio_chips[alias_idx]) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err;
+	}
+
+	oxnas_chip = devm_kzalloc(&pdev->dev, sizeof(*oxnas_chip), GFP_KERNEL);
+	if (!oxnas_chip) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Get pinctrl sys control regmap */
+	oxnas_chip->regmap =
+		syscon_regmap_lookup_by_phandle(of_get_parent(node),
+						"plxtech,sys-ctrl");
+	if (IS_ERR(oxnas_chip->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	oxnas_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oxnas_chip->regbase)) {
+		ret = PTR_ERR(oxnas_chip->regbase);
+		goto err;
+	}
+
+	oxnas_chip->chip = oxnas_gpio_template;
+
+	chip = &oxnas_chip->chip;
+	chip->of_node = np;
+	chip->label = dev_name(&pdev->dev);
+	chip->parent = &pdev->dev;
+	chip->owner = THIS_MODULE;
+	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+		if (ngpio > MAX_NB_GPIO_PER_BANK)
+			pr_err("oxnas_gpio.%d, gpio-nb >= %d failback to %d\n",
+			       alias_idx, MAX_NB_GPIO_PER_BANK,
+			       MAX_NB_GPIO_PER_BANK);
+		else
+			chip->ngpio = ngpio;
+	}
+
+	names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+			     GFP_KERNEL);
+
+	if (!names) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < chip->ngpio; i++)
+		names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
+
+	chip->names = (const char *const *)names;
+
+	range = &oxnas_chip->range;
+	range->name = chip->label;
+	range->id = alias_idx;
+	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+	range->npins = chip->ngpio;
+	range->gc = chip;
+
+	ret = gpiochip_add(chip);
+	if (ret)
+		goto err;
+
+	gpio_chips[alias_idx] = oxnas_chip;
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+
+	oxnas_gpio_of_irq_setup(np, oxnas_chip, irq);
+
+	dev_info(&pdev->dev, "at address %p\n", oxnas_chip->regbase);
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+	return ret;
+}
+
+static struct platform_driver oxnas_gpio_driver = {
+	.driver = {
+		.name = "gpio-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_gpio_of_match),
+	},
+	.probe = oxnas_gpio_probe,
+};
+
+static struct platform_driver oxnas_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_pinctrl_of_match),
+	},
+	.probe = oxnas_pinctrl_probe,
+	.remove = oxnas_pinctrl_remove,
+};
+
+static int __init oxnas_pinctrl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&oxnas_gpio_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&oxnas_pinctrl_driver);
+}
+arch_initcall(oxnas_pinctrl_init);
+
+static void __exit oxnas_pinctrl_exit(void)
+{
+	platform_driver_unregister(&oxnas_pinctrl_driver);
+}
+
+module_exit(oxnas_pinctrl_exit);
-- 
1.9.1

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

* [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

CC: Ma Haijun <mahaijuns@gmail.com>
CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/pinctrl/Kconfig         |    9 +
 drivers/pinctrl/Makefile        |    1 +
 drivers/pinctrl/pinctrl-oxnas.c | 1393 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1403 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 99a4c10..1d0c513 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -129,6 +129,15 @@ config PINCTRL_MESON
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_OXNAS
+	bool
+	depends on OF
+	select PINMUX
+	select PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select MFD_SYSCON
+
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bf1b5ca..3351d10 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_OXNAS)	+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
new file mode 100644
index 0000000..5dfd3a9
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -0,0 +1,1393 @@
+/*
+ * PLX Technology OXNAS Pinctrl driver based on at91 pinctrl driver
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Hajun <mahaijuns@gmail.com>
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+#include <linux/version.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK	32
+#define MAX_GPIO_BANKS		2
+
+struct oxnas_gpio_chip {
+	struct gpio_chip	chip;
+	struct pinctrl_gpio_range range;
+	void __iomem		*regbase;  /* GPIOA/B virtual address */
+	struct irq_domain	*domain;   /* associated irq domain */
+	struct regmap		*regmap;
+};
+
+#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)
+
+static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+/**
+ * struct oxnas_pmx_func - describes pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct oxnas_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+enum oxnas_mux {
+	OXNAS_PINMUX_GPIO,
+	OXNAS_PINMUX_FUNC1,
+	OXNAS_PINMUX_FUNC2,
+	OXNAS_PINMUX_FUNC3,
+};
+
+enum {
+	INPUT_VALUE = 0,
+	OUTPUT_ENABLE = 4,
+	IRQ_PENDING = 0xC,
+	OUTPUT_VALUE = 0x10,
+	OUTPUT_SET = 0x14,
+	OUTPUT_CLEAR = 0x18,
+	OUTPUT_EN_SET = 0x1C,
+	OUTPUT_EN_CLEAR = 0x20,
+	RE_IRQ_ENABLE = 0x28, /* rising edge */
+	FE_IRQ_ENABLE = 0x2C, /* falling edge */
+	RE_IRQ_PENDING = 0x30, /* rising edge */
+	FE_IRQ_PENDING = 0x34, /* falling edge */
+};
+
+enum {
+	PINMUX_PRIMARY_SEL0 = 0x0c,
+	PINMUX_PRIMARY_SEL1 = 0x10,
+	PINMUX_SECONDARY_SEL0 = 0x14,
+	PINMUX_SECONDARY_SEL1 = 0x18,
+	PINMUX_TERTIARY_SEL0 = 0x8c,
+	PINMUX_TERTIARY_SEL1 = 0x90,
+};
+
+/**
+ * struct oxnas_pmx_pin - describes an pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct oxnas_pmx_pin {
+	uint32_t	bank;
+	uint32_t	pin;
+	enum oxnas_mux	mux;
+	unsigned long	conf;
+};
+
+/**
+ * struct oxnas_pin_group - describes an pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *	array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ */
+struct oxnas_pin_group {
+	const char		*name;
+	struct oxnas_pmx_pin	*pins_conf;
+	unsigned int		*pins;
+	unsigned		npins;
+};
+
+struct oxnas_pinctrl {
+	struct device		*dev;
+	struct pinctrl_dev	*pctl;
+	struct regmap		*regmap;
+
+	int			nbanks;
+
+	uint32_t		*mux_mask;
+	int			nmux;
+
+	struct oxnas_pmx_func	*functions;
+	int			nfunctions;
+
+	struct oxnas_pin_group	*groups;
+	int			ngroups;
+};
+
+static const inline struct oxnas_pin_group *oxnas_pinctrl_find_group_by_name(
+				const struct oxnas_pinctrl *info,
+				const char *name)
+{
+	const struct oxnas_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (strcmp(info->groups[i].name, name))
+			continue;
+
+		grp = &info->groups[i];
+		dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins,
+			grp->pins[0]);
+		break;
+	}
+
+	return grp;
+}
+
+static int oxnas_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *oxnas_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int oxnas_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *npins)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void oxnas_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = oxnas_pinctrl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
+			       GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+		new_map[i].data.configs.num_configs = 1;
+	}
+
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static const struct pinctrl_ops oxnas_pctrl_ops = {
+	.get_groups_count	= oxnas_get_groups_count,
+	.get_group_name		= oxnas_get_group_name,
+	.get_group_pins		= oxnas_get_group_pins,
+	.pin_dbg_show		= oxnas_pin_dbg_show,
+	.dt_node_to_map		= oxnas_dt_node_to_map,
+	.dt_free_map		= oxnas_dt_free_map,
+};
+
+static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
+				 unsigned int bank)
+{
+	return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+	return pin / MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static void oxnas_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+	writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void oxnas_mux_set_func1(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func2(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func3(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, mask);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, mask);
+	}
+}
+
+static void oxnas_mux_set_gpio(struct oxnas_pinctrl *ctrl,
+			       unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static enum oxnas_mux oxnas_mux_get_func(struct regmap *regmap,
+					 unsigned bank, unsigned mask)
+{
+	unsigned int val;
+
+	if (!bank) {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	} else {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	}
+
+	return OXNAS_PINMUX_GPIO;
+}
+
+static void oxnas_pin_dbg(const struct device *dev,
+			  const struct oxnas_pmx_pin *pin)
+{
+	if (pin->mux) {
+		dev_dbg(dev,
+			"MF_%c%d configured as periph%c with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A',
+			pin->conf);
+	} else {
+		dev_dbg(dev, "MF_%c%d configured as gpio with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->conf);
+	}
+}
+
+static int pin_check_config(struct oxnas_pinctrl *info, const char *name,
+			    int index, const struct oxnas_pmx_pin *pin)
+{
+	int mux;
+
+	/* check if it's a valid config */
+	if (pin->bank >= info->nbanks) {
+		dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+			name, index, pin->bank, info->nbanks);
+		return -EINVAL;
+	}
+
+	if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+		dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+			name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+		return -EINVAL;
+	}
+	/* gpio always allowed */
+	if (!pin->mux)
+		return 0;
+
+	mux = pin->mux - 1;
+
+	if (mux >= info->nmux) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+			name, index, mux, info->nmux);
+		return -EINVAL;
+	}
+
+	if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for MF_%c%d\n",
+			name, index, mux, pin->bank + 'A', pin->pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void oxnas_mux_gpio_enable(struct oxnas_pinctrl *ctrl,
+				  int bank,
+				  void __iomem *pio,
+				  unsigned mask, bool input)
+{
+	oxnas_mux_set_gpio(ctrl, bank, mask);
+
+	if (input)
+		writel_relaxed(mask, pio + OUTPUT_EN_CLEAR);
+	else
+		writel_relaxed(mask, pio + OUTPUT_EN_SET);
+}
+
+static void oxnas_mux_gpio_disable(struct oxnas_pinctrl *ctrl,
+				   int bank,
+				   unsigned mask)
+{
+	/* when switch to other function, gpio is disabled automatically */
+}
+
+static int oxnas_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+			    unsigned group)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct oxnas_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i, ret;
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	/* first check that all the pins of the group are valid with a valid
+	 * parameter
+	 */
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		ret = pin_check_config(info, info->groups[group].name, i, pin);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		oxnas_pin_dbg(info->dev, pin);
+
+		pio = pin_to_gpioctrl(info, pin->bank);
+
+		mask = pin_to_mask(pin->pin);
+		oxnas_mux_disable_interrupt(pio, mask);
+
+		switch (pin->mux) {
+		case OXNAS_PINMUX_GPIO:
+			oxnas_mux_gpio_enable(info, pin->bank, pio, mask, 1);
+			break;
+		case OXNAS_PINMUX_FUNC1:
+			oxnas_mux_set_func1(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC2:
+			oxnas_mux_set_func2(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC3:
+			oxnas_mux_set_func3(info, pin->bank, mask);
+			break;
+		}
+		if (pin->mux)
+			oxnas_mux_gpio_disable(info, pin->bank, mask);
+	}
+
+	return 0;
+}
+
+static int oxnas_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+static const char *oxnas_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					   unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int oxnas_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_chip *oxnas_chip;
+	struct gpio_chip *chip;
+	unsigned mask;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	oxnas_chip = container_of(chip, struct oxnas_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	mask = 1 << (offset - chip->base);
+
+	dev_dbg(npct->dev, "enable pin %u as MF_%c%d 0x%x\n",
+		offset, 'A' + range->id, offset - chip->base, mask);
+
+	oxnas_mux_set_gpio(npct, range->id, mask);
+
+	return 0;
+}
+
+static void oxnas_gpio_disable_free(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static const struct pinmux_ops oxnas_pmx_ops = {
+	.get_functions_count	= oxnas_pmx_get_funcs_count,
+	.get_function_name	= oxnas_pmx_get_func_name,
+	.get_function_groups	= oxnas_pmx_get_groups,
+	.set_mux		= oxnas_pmx_set_mux,
+	.gpio_request_enable	= oxnas_gpio_request_enable,
+	.gpio_disable_free	= oxnas_gpio_disable_free,
+};
+
+static int oxnas_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static int oxnas_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *configs,
+			     unsigned num_configs)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static void oxnas_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void oxnas_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+}
+
+static const struct pinconf_ops oxnas_pinconf_ops = {
+	.pin_config_get			= oxnas_pinconf_get,
+	.pin_config_set			= oxnas_pinconf_set,
+	.pin_config_dbg_show		= oxnas_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= oxnas_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc oxnas_pinctrl_desc = {
+	.pctlops	= &oxnas_pctrl_ops,
+	.pmxops		= &oxnas_pmx_ops,
+	.confops	= &oxnas_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
+static const char *gpio_compat = "plxtech,nas782x-gpio";
+
+static void oxnas_pinctrl_child_count(struct oxnas_pinctrl *info,
+				      struct device_node *np)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int oxnas_pinctrl_mux_mask(struct oxnas_pinctrl *info,
+				  struct device_node *np)
+{
+	int ret = 0;
+	int size;
+	const __be32 *list;
+
+	list = of_get_property(np, "plxtech,mux-mask", &size);
+	if (!list) {
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+		return -EINVAL;
+	}
+
+	size /= sizeof(*list);
+	if (!size || size % info->nbanks) {
+		dev_err(info->dev, "wrong mux mask array should be by %d\n",
+			info->nbanks);
+		return -EINVAL;
+	}
+	info->nmux = size / info->nbanks;
+
+	info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size,
+				      GFP_KERNEL);
+	if (!info->mux_mask)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(np, "plxtech,mux-mask",
+					  info->mux_mask, size);
+	if (ret)
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+	return ret;
+}
+
+static int oxnas_pinctrl_parse_groups(struct device_node *np,
+				      struct oxnas_pin_group *grp,
+				      struct oxnas_pinctrl *info, u32 index)
+{
+	struct oxnas_pmx_pin *pin;
+	int size;
+	const __be32 *list;
+	int i, j;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is plxtech,pins = <bank pin mux CONFIG ...>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "plxtech,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	size /= sizeof(*list);
+	if (!size || size % 4) {
+		dev_err(info->dev, "wrong pins number or pins and configs should be divisible by 4\n");
+		return -EINVAL;
+	}
+
+	grp->npins = size / 4;
+	pin = grp->pins_conf = devm_kzalloc(info->dev,
+				grp->npins * sizeof(struct oxnas_pmx_pin),
+				GFP_KERNEL);
+	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
+	if (!grp->pins_conf || !grp->pins)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < size; i += 4, j++) {
+		pin->bank = be32_to_cpu(*list++);
+		pin->pin = be32_to_cpu(*list++);
+		grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+		pin->mux = be32_to_cpu(*list++);
+		pin->conf = be32_to_cpu(*list++);
+
+		oxnas_pin_dbg(info->dev, pin);
+		pin++;
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_parse_functions(struct device_node *np,
+					struct oxnas_pinctrl *info, u32 index)
+{
+	struct device_node *child;
+	struct oxnas_pmx_func *func;
+	struct oxnas_pin_group *grp;
+	int ret;
+	static u32 grp_index;
+	u32 i = 0;
+
+	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &info->functions[index];
+
+	/* Initialise function */
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "no groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[grp_index++];
+		ret = oxnas_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+	{ .compatible = "plxtech,nas782x-pinctrl"},
+	{ .compatible = "plxtech,ox810se-pinctrl"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_pinctrl_probe_dt(struct platform_device *pdev,
+				 struct oxnas_pinctrl *info)
+{
+	int ret = 0;
+	int i, j;
+	uint32_t *tmp;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+
+	if (!np)
+		return -ENODEV;
+
+	info->dev = &pdev->dev;
+
+	oxnas_pinctrl_child_count(info, np);
+
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		return -EINVAL;
+	}
+
+	ret = oxnas_pinctrl_mux_mask(info, np);
+	if (ret)
+		return ret;
+
+	dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+	dev_dbg(&pdev->dev, "mux-mask\n");
+	tmp = info->mux_mask;
+	for (i = 0; i < info->nbanks; i++)
+		for (j = 0; j < info->nmux; j++, tmp++)
+			dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev, info->nfunctions *
+						sizeof(struct oxnas_pmx_func),
+					GFP_KERNEL);
+	if (!info->functions)
+		return -ENOMEM;
+
+	info->groups = devm_kzalloc(&pdev->dev, info->ngroups *
+					sizeof(struct oxnas_pin_group),
+				    GFP_KERNEL);
+	if (!info->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+	i = 0;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat))
+			continue;
+		ret = oxnas_pinctrl_parse_functions(child, info, i++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_probe(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info;
+	struct pinctrl_pin_desc *pdesc;
+	int ret, i, j, k;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						       "plxtech,sys-ctrl");
+	if (IS_ERR(info->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	ret = oxnas_pinctrl_probe_dt(pdev, info);
+	if (ret)
+		return ret;
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < info->nbanks; i++) {
+		if (!gpio_chips[i]) {
+			dev_warn(&pdev->dev,
+				 "GPIO chip %d not registered yet\n", i);
+			devm_kfree(&pdev->dev, info);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	oxnas_pinctrl_desc.name = dev_name(&pdev->dev);
+	oxnas_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+	oxnas_pinctrl_desc.pins = pdesc =
+		devm_kzalloc(&pdev->dev, sizeof(*pdesc) *
+				oxnas_pinctrl_desc.npins, GFP_KERNEL);
+
+	if (!oxnas_pinctrl_desc.pins)
+		return -ENOMEM;
+
+	for (i = 0, k = 0; i < info->nbanks; i++) {
+		for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+			pdesc->number = k;
+			pdesc->name = kasprintf(GFP_KERNEL, "MF_%c%d", i + 'A',
+						j);
+			pdesc++;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+	info->pctl = pinctrl_register(&oxnas_pinctrl_desc, &pdev->dev, info);
+
+	if (!info->pctl) {
+		dev_err(&pdev->dev, "could not register OXNAS pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+	dev_info(&pdev->dev, "initialized OXNAS pinctrl driver\n");
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int oxnas_pinctrl_remove(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(info->pctl);
+
+	return 0;
+}
+
+static int oxnas_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+	int bank = chip->base / chip->ngpio;
+
+	dev_dbg(chip->parent, "%s:%d MF_%c%d(%d)\n", __func__, __LINE__,
+		'A' + bank, offset, gpio);
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void oxnas_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int oxnas_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_CLEAR);
+	return 0;
+}
+
+static int oxnas_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 pdsr = 0;
+
+	pdsr = readl_relaxed(pio + INPUT_VALUE);
+	return (pdsr & mask) != 0;
+}
+
+static void oxnas_gpio_set(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+}
+
+static int oxnas_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_SET);
+
+	return 0;
+}
+
+static int oxnas_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	int virq;
+
+	if (offset < chip->ngpio)
+		virq = irq_create_mapping(oxnas_gpio->domain, offset);
+	else
+		virq = -ENXIO;
+
+	dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n",
+				chip->label, offset + chip->base, virq);
+	return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void oxnas_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int i;
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	enum oxnas_mux mux;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		unsigned mask = pin_to_mask(pin);
+		unsigned bank = pin_to_bank(pin);
+		const char *gpio_label;
+		u32 pdsr;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (gpio_label) {
+			seq_printf(s, "[%s]\tGPIO%s%d: ",
+				   gpio_label, chip->label, i);
+			pdsr = readl_relaxed(pio + INPUT_VALUE);
+
+			seq_printf(s, "[gpio] %s\n",
+					pdsr & mask ?
+					"set" : "clear");
+		} else {
+			mux = oxnas_mux_get_func(oxnas_gpio->regmap,
+						 bank,
+						 mask);
+			seq_printf(s, "\tGPIO%s%d: [func%d]\n",
+				   chip->label, i, mux);
+		}
+
+	}
+}
+#else
+#define oxnas_gpio_dbg_show	NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * oxnas_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) | mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) | mask, pio + FE_IRQ_ENABLE);
+}
+
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
+		pr_warn("oxnas: Unsupported type for irq %d\n",
+			gpio_to_irq(d->irq));
+		return -EINVAL;
+	}
+	/* seems no way to set trigger type without enable irq,
+	 * so leave it to unmask time
+	 */
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
+};
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned long isr;
+	int n;
+
+	chained_irq_enter(chip, desc);
+	for (;;) {
+		isr = readl_relaxed(pio + IRQ_PENDING);
+		if (!isr)
+			break;
+
+		/* acks pending interrupts */
+		writel_relaxed(isr, pio + IRQ_PENDING);
+
+		for_each_set_bit(n, &isr, BITS_PER_LONG) {
+			generic_handle_irq(irq_find_mapping(oxnas_gpio->domain,
+							    n));
+		}
+	}
+	chained_irq_exit(chip, desc);
+	/* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
+
+	irq_set_lockdep_class(virq, &gpio_lock_class);
+
+	irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);
+
+	irq_set_chip_data(virq, oxnas_gpio);
+
+	return 0;
+}
+
+static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
+				       struct device_node *ctrlr,
+				       const u32 *intspec,
+				       unsigned int intsize,
+				       irq_hw_number_t *out_hwirq,
+				       unsigned int *out_type)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
+	int ret;
+	int pin = oxnas_gpio->chip.base + intspec[0];
+
+	if (WARN_ON(intsize < 2))
+		return -EINVAL;
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	ret = gpio_request(pin, ctrlr->full_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_direction_input(pin);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct irq_domain_ops oxnas_gpio_ops = {
+	.map	= oxnas_gpio_irq_map,
+	.xlate	= oxnas_gpio_irq_domain_xlate,
+};
+
+static int oxnas_gpio_of_irq_setup(struct device_node *node,
+				   struct oxnas_gpio_chip *oxnas_gpio,
+				   unsigned int irq)
+{
+	/* Disable irqs of this controller */
+	writel_relaxed(0, oxnas_gpio->regbase + RE_IRQ_ENABLE);
+	writel_relaxed(0, oxnas_gpio->regbase + FE_IRQ_ENABLE);
+
+	/* Setup irq domain */
+	oxnas_gpio->domain = irq_domain_add_linear(node, oxnas_gpio->chip.ngpio,
+						   &oxnas_gpio_ops, oxnas_gpio);
+	if (!oxnas_gpio->domain)
+		panic("oxnas_gpio: couldn't allocate irq domain (DT).\n");
+
+	irq_set_chip_data(irq, oxnas_gpio);
+	irq_set_chained_handler(irq, gpio_irq_handler);
+
+	return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip oxnas_gpio_template = {
+	.request		= oxnas_gpio_request,
+	.free			= oxnas_gpio_free,
+	.direction_input	= oxnas_gpio_direction_input,
+	.get			= oxnas_gpio_get,
+	.direction_output	= oxnas_gpio_direction_output,
+	.set			= oxnas_gpio_set,
+	.to_irq			= oxnas_gpio_to_irq,
+	.dbg_show		= oxnas_gpio_dbg_show,
+	.can_sleep		= 0,
+	.ngpio			= MAX_NB_GPIO_PER_BANK,
+};
+
+static const struct of_device_id oxnas_gpio_of_match[] = {
+	{ .compatible = "plxtech,nas782x-gpio"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct oxnas_gpio_chip *oxnas_chip = NULL;
+	struct gpio_chip *chip;
+	struct pinctrl_gpio_range *range;
+	struct device_node *node = pdev->dev.of_node;
+	int ret = 0;
+	int irq, i;
+	int alias_idx = of_alias_get_id(np, "gpio");
+	uint32_t ngpio;
+	char **names;
+
+	if (WARN_ON(alias_idx >= ARRAY_SIZE(gpio_chips)))
+		return -EINVAL;
+
+	if (gpio_chips[alias_idx]) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err;
+	}
+
+	oxnas_chip = devm_kzalloc(&pdev->dev, sizeof(*oxnas_chip), GFP_KERNEL);
+	if (!oxnas_chip) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Get pinctrl sys control regmap */
+	oxnas_chip->regmap =
+		syscon_regmap_lookup_by_phandle(of_get_parent(node),
+						"plxtech,sys-ctrl");
+	if (IS_ERR(oxnas_chip->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	oxnas_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oxnas_chip->regbase)) {
+		ret = PTR_ERR(oxnas_chip->regbase);
+		goto err;
+	}
+
+	oxnas_chip->chip = oxnas_gpio_template;
+
+	chip = &oxnas_chip->chip;
+	chip->of_node = np;
+	chip->label = dev_name(&pdev->dev);
+	chip->parent = &pdev->dev;
+	chip->owner = THIS_MODULE;
+	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+		if (ngpio > MAX_NB_GPIO_PER_BANK)
+			pr_err("oxnas_gpio.%d, gpio-nb >= %d failback to %d\n",
+			       alias_idx, MAX_NB_GPIO_PER_BANK,
+			       MAX_NB_GPIO_PER_BANK);
+		else
+			chip->ngpio = ngpio;
+	}
+
+	names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+			     GFP_KERNEL);
+
+	if (!names) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < chip->ngpio; i++)
+		names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
+
+	chip->names = (const char *const *)names;
+
+	range = &oxnas_chip->range;
+	range->name = chip->label;
+	range->id = alias_idx;
+	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+	range->npins = chip->ngpio;
+	range->gc = chip;
+
+	ret = gpiochip_add(chip);
+	if (ret)
+		goto err;
+
+	gpio_chips[alias_idx] = oxnas_chip;
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+
+	oxnas_gpio_of_irq_setup(np, oxnas_chip, irq);
+
+	dev_info(&pdev->dev, "at address %p\n", oxnas_chip->regbase);
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+	return ret;
+}
+
+static struct platform_driver oxnas_gpio_driver = {
+	.driver = {
+		.name = "gpio-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_gpio_of_match),
+	},
+	.probe = oxnas_gpio_probe,
+};
+
+static struct platform_driver oxnas_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_pinctrl_of_match),
+	},
+	.probe = oxnas_pinctrl_probe,
+	.remove = oxnas_pinctrl_remove,
+};
+
+static int __init oxnas_pinctrl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&oxnas_gpio_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&oxnas_pinctrl_driver);
+}
+arch_initcall(oxnas_pinctrl_init);
+
+static void __exit oxnas_pinctrl_exit(void)
+{
+	platform_driver_unregister(&oxnas_pinctrl_driver);
+}
+
+module_exit(oxnas_pinctrl_exit);
-- 
1.9.1

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

* [PATCH 11/17] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |  27 ++++++
 .../bindings/pinctrl/plxtech,pinctrl.txt           | 100 +++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
new file mode 100644
index 0000000..0ef6c55
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -0,0 +1,27 @@
+PLX Technology OXNAS SoC GPIO Controller
+==========================================
+
+Required properties:
+- compatible: "plxtech,nas782x-gpio".
+- reg: Should contain GPIO controller registers location and length
+- interrupts: Should be the port interrupt shared by all the pins.
+- #gpio-cells: Should be two.  The first cell is the pin number and
+  the second cell is used to specify optional parameters (currently
+  unused).
+- gpio-controller: Marks the device node as a GPIO controller.
+
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
+Example:
+	gpio0: gpio@000000 {
+		compatible = "plxtech,nas782x-gpio";
+		reg = <0x000000 0x100000>;
+		interrupts = <21>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		#gpio-lines = <32>;
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
new file mode 100644
index 0000000..30f013f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
@@ -0,0 +1,100 @@
+PLX Technology OXNAS SoC Pinmux Controller
+==========================================
+
+The OXNAS Pinmux Controller, enables the IC to share one PAD to several
+functional blocks. The sharing is done by multiplexing the PAD input/output
+signals. For each PAD there are up to 8 muxing options (called periph modes).
+Since different modules require different PAD settings
+(like pull up, keeper, etc) the contoller controls also the PAD settings
+parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+OXNAS pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "plxtech,nas782x-pinctrl" or "plxtech,ox810se-pinctrl"
+- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
+  configured in this periph mode. All the periph and bank need to be describe.
+- plxtech,sys-ctrl: a phandle to the system controller syscon node
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+For example :
+Peripheral: 2 ( A and B)
+Bank: 2 (A, B and C)
+=>
+
+  /*    A         B     */
+  0xffffffff 0xffc00c3b  /* pioA */
+  0xffffffff 0x7fff3ccf  /* pioB */
+
+For each peripheral/bank we will descibe in a u32 if a pin can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Required properties for pin configuration node:
+- plxtech,pins: 4 integers array, represents a group of pins mux and config
+  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
+
+Bits used for CONFIG:
+ - None Yet
+
+Examples:
+
+pinctrl: pinctrl {
+	compatible = "plxtech,nas782x-pinctrl", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	/* Regmap for sys registers */
+	plxtech,sys-ctrl = <&sys>;
+
+	/* Default, all-open mux-map */
+	plxtech,mux-mask = <
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 >;
+
+	uart0 {
+		pinctrl_uart0: uart0 {
+			plxtech,pins = <0 31 3 0
+					0 32 3 0>;
+		};
+		pinctrl_uart0_modem: uart0_modem {
+			plxtech,pins = <0 27 3 0
+					0 28 3 0
+					0 29 3 0
+					0 30 3 0
+					0 33 3 0
+					0 34 3 0>;
+		};
+	};
+};
+
+uart0: uart@200000 {
+	compatible = "ns16550a";
+	reg = <0x200000 0x100000>;
+	clocks = <&sysclk>;
+	interrupts = <23>;
+	reg-shift = <0>;
+	fifo-size = <16>;
+	reg-io-width = <1>;
+	current-speed = <115200>;
+	no-loopback-test;
+	status = "disabled";
+	resets = <&reset 17>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+};
-- 
1.9.1

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

* [PATCH 11/17] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |  27 ++++++
 .../bindings/pinctrl/plxtech,pinctrl.txt           | 100 +++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
new file mode 100644
index 0000000..0ef6c55
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -0,0 +1,27 @@
+PLX Technology OXNAS SoC GPIO Controller
+==========================================
+
+Required properties:
+- compatible: "plxtech,nas782x-gpio".
+- reg: Should contain GPIO controller registers location and length
+- interrupts: Should be the port interrupt shared by all the pins.
+- #gpio-cells: Should be two.  The first cell is the pin number and
+  the second cell is used to specify optional parameters (currently
+  unused).
+- gpio-controller: Marks the device node as a GPIO controller.
+
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
+Example:
+	gpio0: gpio at 000000 {
+		compatible = "plxtech,nas782x-gpio";
+		reg = <0x000000 0x100000>;
+		interrupts = <21>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		#gpio-lines = <32>;
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
new file mode 100644
index 0000000..30f013f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
@@ -0,0 +1,100 @@
+PLX Technology OXNAS SoC Pinmux Controller
+==========================================
+
+The OXNAS Pinmux Controller, enables the IC to share one PAD to several
+functional blocks. The sharing is done by multiplexing the PAD input/output
+signals. For each PAD there are up to 8 muxing options (called periph modes).
+Since different modules require different PAD settings
+(like pull up, keeper, etc) the contoller controls also the PAD settings
+parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+OXNAS pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "plxtech,nas782x-pinctrl" or "plxtech,ox810se-pinctrl"
+- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
+  configured in this periph mode. All the periph and bank need to be describe.
+- plxtech,sys-ctrl: a phandle to the system controller syscon node
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+For example :
+Peripheral: 2 ( A and B)
+Bank: 2 (A, B and C)
+=>
+
+  /*    A         B     */
+  0xffffffff 0xffc00c3b  /* pioA */
+  0xffffffff 0x7fff3ccf  /* pioB */
+
+For each peripheral/bank we will descibe in a u32 if a pin can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Required properties for pin configuration node:
+- plxtech,pins: 4 integers array, represents a group of pins mux and config
+  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
+
+Bits used for CONFIG:
+ - None Yet
+
+Examples:
+
+pinctrl: pinctrl {
+	compatible = "plxtech,nas782x-pinctrl", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	/* Regmap for sys registers */
+	plxtech,sys-ctrl = <&sys>;
+
+	/* Default, all-open mux-map */
+	plxtech,mux-mask = <
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 >;
+
+	uart0 {
+		pinctrl_uart0: uart0 {
+			plxtech,pins = <0 31 3 0
+					0 32 3 0>;
+		};
+		pinctrl_uart0_modem: uart0_modem {
+			plxtech,pins = <0 27 3 0
+					0 28 3 0
+					0 29 3 0
+					0 30 3 0
+					0 33 3 0
+					0 34 3 0>;
+		};
+	};
+};
+
+uart0: uart at 200000 {
+	compatible = "ns16550a";
+	reg = <0x200000 0x100000>;
+	clocks = <&sysclk>;
+	interrupts = <23>;
+	reg-shift = <0>;
+	fifo-size = <16>;
+	reg-io-width = <1>;
+	current-speed = <115200>;
+	no-loopback-test;
+	status = "disabled";
+	resets = <&reset 17>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+};
-- 
1.9.1

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

* [PATCH 12/17] arm: Add new mach-oxnas
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux; +Cc: Neil Armstrong

Add mach-oxnas directory containing Kconfig and generic oxnas
handling for future SoC specific features like system reset.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/mach-oxnas/Kconfig  | 24 ++++++++++++++++++++++++
 arch/arm/mach-oxnas/Makefile |  1 +
 arch/arm/mach-oxnas/oxnas.c  | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+)
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile
 create mode 100644 arch/arm/mach-oxnas/oxnas.c

diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
new file mode 100644
index 0000000..6a1f24c
--- /dev/null
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -0,0 +1,24 @@
+menuconfig ARCH_OXNAS
+	bool "PLX Technology OXNAS Family SoCs"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_RESET_CONTROLLER
+	select PINCTRL
+	depends on ARCH_MULTI_V5
+	help
+	  Support for OxNas SoC family developed by PLX Technology.
+	  (Formely Oxford Semiconductor)
+
+if ARCH_OXNAS
+
+config MACH_OX810SE
+	bool "Support OX810SE Based Products"
+	select CPU_ARM926T
+	select PLXTECH_RPS
+	select CLKSRC_RPS_TIMER
+	select RESET_OXNAS
+	select COMMON_CLK_OXNAS
+	select PINCTRL_OXNAS
+	help
+	  Include Support for the PLX Technology OX810SE SoC Based Products.
+
+endif
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
new file mode 100644
index 0000000..c54bec7
--- /dev/null
+++ b/arch/arm/mach-oxnas/Makefile
@@ -0,0 +1 @@
+obj-y			:= oxnas.o
diff --git a/arch/arm/mach-oxnas/oxnas.c b/arch/arm/mach-oxnas/oxnas.c
new file mode 100644
index 0000000..ebdcd9d
--- /dev/null
+++ b/arch/arm/mach-oxnas/oxnas.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+static const char * const oxnas_dt_compat[] __initconst = {
+	"plxtech,ox810se",
+	NULL,
+};
+
+static void __init oxnas_init(void)
+{
+	pr_info("OXNAS Device Tree boot\n");
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+DT_MACHINE_START(OXNAS, "PLX Technology OXNAS Family")
+	.dt_compat	= oxnas_dt_compat,
+	.init_machine	= oxnas_init,
+MACHINE_END
-- 
1.9.1

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

* [PATCH 12/17] arm: Add new mach-oxnas
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Add mach-oxnas directory containing Kconfig and generic oxnas
handling for future SoC specific features like system reset.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/mach-oxnas/Kconfig  | 24 ++++++++++++++++++++++++
 arch/arm/mach-oxnas/Makefile |  1 +
 arch/arm/mach-oxnas/oxnas.c  | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+)
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile
 create mode 100644 arch/arm/mach-oxnas/oxnas.c

diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
new file mode 100644
index 0000000..6a1f24c
--- /dev/null
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -0,0 +1,24 @@
+menuconfig ARCH_OXNAS
+	bool "PLX Technology OXNAS Family SoCs"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_RESET_CONTROLLER
+	select PINCTRL
+	depends on ARCH_MULTI_V5
+	help
+	  Support for OxNas SoC family developed by PLX Technology.
+	  (Formely Oxford Semiconductor)
+
+if ARCH_OXNAS
+
+config MACH_OX810SE
+	bool "Support OX810SE Based Products"
+	select CPU_ARM926T
+	select PLXTECH_RPS
+	select CLKSRC_RPS_TIMER
+	select RESET_OXNAS
+	select COMMON_CLK_OXNAS
+	select PINCTRL_OXNAS
+	help
+	  Include Support for the PLX Technology OX810SE SoC Based Products.
+
+endif
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
new file mode 100644
index 0000000..c54bec7
--- /dev/null
+++ b/arch/arm/mach-oxnas/Makefile
@@ -0,0 +1 @@
+obj-y			:= oxnas.o
diff --git a/arch/arm/mach-oxnas/oxnas.c b/arch/arm/mach-oxnas/oxnas.c
new file mode 100644
index 0000000..ebdcd9d
--- /dev/null
+++ b/arch/arm/mach-oxnas/oxnas.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+static const char * const oxnas_dt_compat[] __initconst = {
+	"plxtech,ox810se",
+	NULL,
+};
+
+static void __init oxnas_init(void)
+{
+	pr_info("OXNAS Device Tree boot\n");
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+DT_MACHINE_START(OXNAS, "PLX Technology OXNAS Family")
+	.dt_compat	= oxnas_dt_compat,
+	.init_machine	= oxnas_init,
+MACHINE_END
-- 
1.9.1

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

* [PATCH 13/17] arm: Add build support for mach-oxnas
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux; +Cc: Neil Armstrong

Add Kconfig and Makefile support for mach-oxnas.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/Kconfig  | 2 ++
 arch/arm/Makefile | 1 +
 2 files changed, 3 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4f799e5..2025fc9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -801,6 +801,8 @@ source "arch/arm/plat-pxa/Kconfig"
 
 source "arch/arm/mach-mmp/Kconfig"
 
+source "arch/arm/mach-oxnas/Kconfig"
+
 source "arch/arm/mach-qcom/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fe25410..0e96c63 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -194,6 +194,7 @@ machine-$(CONFIG_ARCH_NSPIRE)		+= nspire
 machine-$(CONFIG_ARCH_OMAP1)		+= omap1
 machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
+machine-$(CONFIG_ARCH_OXNAS)		+= oxnas
 machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
 machine-$(CONFIG_ARCH_PXA)		+= pxa
 machine-$(CONFIG_ARCH_QCOM)		+= qcom
-- 
1.9.1

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

* [PATCH 13/17] arm: Add build support for mach-oxnas
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Add Kconfig and Makefile support for mach-oxnas.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/Kconfig  | 2 ++
 arch/arm/Makefile | 1 +
 2 files changed, 3 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4f799e5..2025fc9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -801,6 +801,8 @@ source "arch/arm/plat-pxa/Kconfig"
 
 source "arch/arm/mach-mmp/Kconfig"
 
+source "arch/arm/mach-oxnas/Kconfig"
+
 source "arch/arm/mach-qcom/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fe25410..0e96c63 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -194,6 +194,7 @@ machine-$(CONFIG_ARCH_NSPIRE)		+= nspire
 machine-$(CONFIG_ARCH_OMAP1)		+= omap1
 machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
+machine-$(CONFIG_ARCH_OXNAS)		+= oxnas
 machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
 machine-$(CONFIG_ARCH_PXA)		+= pxa
 machine-$(CONFIG_ARCH_QCOM)		+= qcom
-- 
1.9.1

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

* [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree, linux; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/ox810se.dtsi | 279 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 279 insertions(+)
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi

diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi
new file mode 100644
index 0000000..a86d7f0
--- /dev/null
+++ b/arch/arm/boot/dts/ox810se.dtsi
@@ -0,0 +1,279 @@
+/*
+ * ox810se.dtsi - Device tree file for PLX Technology OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "plxtech,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rspclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge@44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "plxtech,nas782x-pinctrl", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				/* Regmap for sys registers */
+				plxtech,sys-ctrl = <&sys>;
+
+				/* Default, all-open mux-map */
+				plxtech,mux-mask = <
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					>;
+
+				gpio0: gpio@000000 {
+					compatible = "plxtech,nas782x-gpio";
+					reg = <0x000000 0x100000>;
+					interrupts = <21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <32>;
+				};
+
+				gpio1: gpio@100000 {
+					compatible = "plxtech,nas782x-gpio";
+					reg = <0x100000 0x100000>;
+					interrupts = <22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <3>;
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0 {
+						plxtech,pins = <0 31 3 0
+								0 32 3 0>;
+					};
+					pinctrl_uart0_modem: uart0_modem {
+						plxtech,pins = <0 27 3 0
+								0 28 3 0
+								0 29 3 0
+								0 30 3 0
+								0 33 3 0
+								0 34 3 0>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1 {
+						plxtech,pins = <0 20 3 0
+								0 22 3 0>;
+					};
+					pinctrl_uart1_modem: uart1_modem {
+						plxtech,pins = <0 8 3 0
+								0 9 3 0
+								0 23 3 0
+								0 24 3 0
+								0 25 3 0
+								0 26 3 0>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2 {
+						plxtech,pins = <0 6 3 0
+								0 7 3 0>;
+					};
+					pinctrl_uart2_modem: uart2_modem {
+						plxtech,pins = <0 0 3 0
+								0 1 3 0
+								0 2 3 0
+								0 3 3 0
+								0 4 3 0
+								0 5 3 0>;
+					};
+				};
+			};
+
+			uart0: uart@200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: uart@300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: uart@900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: uart@a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge@45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl@000000 {
+				compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "plxtech,nas782x-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps@300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller@0 {
+					compatible = "plxtech,nas782x-rps";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+				};
+
+				timer0: timer@200 {
+					compatible = "plxtech,nas782x-rps-timer";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, linux-lFZ/pmaqli7XmaaqVzeoHQ
  Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
 arch/arm/boot/dts/ox810se.dtsi | 279 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 279 insertions(+)
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi

diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi
new file mode 100644
index 0000000..a86d7f0
--- /dev/null
+++ b/arch/arm/boot/dts/ox810se.dtsi
@@ -0,0 +1,279 @@
+/*
+ * ox810se.dtsi - Device tree file for PLX Technology OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "plxtech,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rspclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge@44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "plxtech,nas782x-pinctrl", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				/* Regmap for sys registers */
+				plxtech,sys-ctrl = <&sys>;
+
+				/* Default, all-open mux-map */
+				plxtech,mux-mask = <
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					>;
+
+				gpio0: gpio@000000 {
+					compatible = "plxtech,nas782x-gpio";
+					reg = <0x000000 0x100000>;
+					interrupts = <21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <32>;
+				};
+
+				gpio1: gpio@100000 {
+					compatible = "plxtech,nas782x-gpio";
+					reg = <0x100000 0x100000>;
+					interrupts = <22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <3>;
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0 {
+						plxtech,pins = <0 31 3 0
+								0 32 3 0>;
+					};
+					pinctrl_uart0_modem: uart0_modem {
+						plxtech,pins = <0 27 3 0
+								0 28 3 0
+								0 29 3 0
+								0 30 3 0
+								0 33 3 0
+								0 34 3 0>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1 {
+						plxtech,pins = <0 20 3 0
+								0 22 3 0>;
+					};
+					pinctrl_uart1_modem: uart1_modem {
+						plxtech,pins = <0 8 3 0
+								0 9 3 0
+								0 23 3 0
+								0 24 3 0
+								0 25 3 0
+								0 26 3 0>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2 {
+						plxtech,pins = <0 6 3 0
+								0 7 3 0>;
+					};
+					pinctrl_uart2_modem: uart2_modem {
+						plxtech,pins = <0 0 3 0
+								0 1 3 0
+								0 2 3 0
+								0 3 3 0
+								0 4 3 0
+								0 5 3 0>;
+					};
+				};
+			};
+
+			uart0: uart@200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: uart@300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: uart@900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: uart@a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge@45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl@000000 {
+				compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "plxtech,nas782x-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps@300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller@0 {
+					compatible = "plxtech,nas782x-rps";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+				};
+
+				timer0: timer@200 {
+					compatible = "plxtech,nas782x-rps-timer";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/ox810se.dtsi | 279 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 279 insertions(+)
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi

diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi
new file mode 100644
index 0000000..a86d7f0
--- /dev/null
+++ b/arch/arm/boot/dts/ox810se.dtsi
@@ -0,0 +1,279 @@
+/*
+ * ox810se.dtsi - Device tree file for PLX Technology OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "plxtech,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rspclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge at 44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "plxtech,nas782x-pinctrl", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				/* Regmap for sys registers */
+				plxtech,sys-ctrl = <&sys>;
+
+				/* Default, all-open mux-map */
+				plxtech,mux-mask = <
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					>;
+
+				gpio0: gpio at 000000 {
+					compatible = "plxtech,nas782x-gpio";
+					reg = <0x000000 0x100000>;
+					interrupts = <21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <32>;
+				};
+
+				gpio1: gpio at 100000 {
+					compatible = "plxtech,nas782x-gpio";
+					reg = <0x100000 0x100000>;
+					interrupts = <22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <3>;
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0 {
+						plxtech,pins = <0 31 3 0
+								0 32 3 0>;
+					};
+					pinctrl_uart0_modem: uart0_modem {
+						plxtech,pins = <0 27 3 0
+								0 28 3 0
+								0 29 3 0
+								0 30 3 0
+								0 33 3 0
+								0 34 3 0>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1 {
+						plxtech,pins = <0 20 3 0
+								0 22 3 0>;
+					};
+					pinctrl_uart1_modem: uart1_modem {
+						plxtech,pins = <0 8 3 0
+								0 9 3 0
+								0 23 3 0
+								0 24 3 0
+								0 25 3 0
+								0 26 3 0>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2 {
+						plxtech,pins = <0 6 3 0
+								0 7 3 0>;
+					};
+					pinctrl_uart2_modem: uart2_modem {
+						plxtech,pins = <0 0 3 0
+								0 1 3 0
+								0 2 3 0
+								0 3 3 0
+								0 4 3 0
+								0 5 3 0>;
+					};
+				};
+			};
+
+			uart0: uart at 200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: uart at 300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: uart at 900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: uart at a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge at 45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl at 000000 {
+				compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "plxtech,nas782x-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps at 300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller at 0 {
+					compatible = "plxtech,nas782x-rps";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+				};
+
+				timer0: timer at 200 {
+					compatible = "plxtech,nas782x-rps-timer";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH 15/17] dt-bindings: Add OXNAS bindings
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt

diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
new file mode 100644
index 0000000..6e17ca4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/oxnas.txt
@@ -0,0 +1,9 @@
+PLX Technology OXNAS SoCs Family device tree bindings
+-------------------------------------------
+
+Boards with the OX810SE Soc SoC shall have the following properties:
+  Required root node property:
+    compatible: "plxtech,ox810se"
+
+Board compatible values:
+  - "wd,mbwe" (OX810SE)
-- 
1.9.1

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

* [PATCH 15/17] dt-bindings: Add OXNAS bindings
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt

diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
new file mode 100644
index 0000000..6e17ca4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/oxnas.txt
@@ -0,0 +1,9 @@
+PLX Technology OXNAS SoCs Family device tree bindings
+-------------------------------------------
+
+Boards with the OX810SE Soc SoC shall have the following properties:
+  Required root node property:
+    compatible: "plxtech,ox810se"
+
+Board compatible values:
+  - "wd,mbwe" (OX810SE)
-- 
1.9.1

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

* [PATCH 16/17] dt-bindings: Add Western Digital to vendor prefixes
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 03970fb..4055608 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -248,6 +248,7 @@ via	VIA Technologies, Inc.
 virtio	Virtual I/O Device Specification, developed by the OASIS consortium
 vivante	Vivante Corporation
 voipac	Voipac Technologies s.r.o.
+wd	Western Digital Corp.
 wexler	Wexler
 winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
-- 
1.9.1

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

* [PATCH 16/17] dt-bindings: Add Western Digital to vendor prefixes
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 03970fb..4055608 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -248,6 +248,7 @@ via	VIA Technologies, Inc.
 virtio	Virtual I/O Device Specification, developed by the OASIS consortium
 vivante	Vivante Corporation
 voipac	Voipac Technologies s.r.o.
+wd	Western Digital Corp.
 wexler	Wexler
 winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
-- 
1.9.1

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

* [PATCH 17/17] arm: boot: dts: Add Western Digital My Book World Edition device tree
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 11:40   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree, linux; +Cc: Neil Armstrong

Add Western Digital My Book World Edition device tree based on
PLX Technology OX810SE SoC.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/Makefile    |   2 +
 arch/arm/boot/dts/wd-mbwe.dts | 106 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a4a6d70..0395674 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -520,6 +520,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_ARCH_OXNAS) += \
+	wd-mbwe.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/wd-mbwe.dts b/arch/arm/boot/dts/wd-mbwe.dts
new file mode 100644
index 0000000..ad97e2f
--- /dev/null
+++ b/arch/arm/boot/dts/wd-mbwe.dts
@@ -0,0 +1,106 @@
+/*
+ * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox810se.dtsi"
+
+/ {
+	model = "Western Digital My Book World Edition";
+
+	compatible = "wd,mbwe", "plxtech,ox810se";
+
+	chosen {
+		bootargs = "console=ttyS1,115200n8 earlyprintk=serial";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x48000000 0x8000000>;
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		power {
+			label = "power";
+			gpios = <&gpio0 0 1>;
+			linux,code = <0x198>;
+		};
+
+		recovery {
+			label = "recovery";
+			gpios = <&gpio0 4 1>;
+			linux,code = <0xab>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		a0 {
+			label = "activity0";
+			gpios = <&gpio0 25 0>;
+			default-state = "keep";
+		};
+
+		a1 {
+			label = "activity1";
+			gpios = <&gpio0 26 0>;
+			default-state = "keep";
+		};
+
+		a2 {
+			label = "activity2";
+			gpios = <&gpio0 5 0>;
+			default-state = "keep";
+		};
+
+		a3 {
+			label = "activity3";
+			gpios = <&gpio0 6 0>;
+			default-state = "keep";
+		};
+
+		a4 {
+			label = "activity4";
+			gpios = <&gpio0 7 0>;
+			default-state = "keep";
+		};
+
+		a5 {
+			label = "activity5";
+			gpios = <&gpio1 2 0>;
+			default-state = "keep";
+		};
+	};
+
+	i2c-gpio {
+		compatible = "i2c-gpio";
+		gpios = <&gpio0 3 0 /* sda */
+			 &gpio0 2 0 /* scl */
+			 >;
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc0: rtc@48 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
-- 
1.9.1

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

* [PATCH 17/17] arm: boot: dts: Add Western Digital My Book World Edition device tree
@ 2016-03-03 11:40   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Add Western Digital My Book World Edition device tree based on
PLX Technology OX810SE SoC.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/Makefile    |   2 +
 arch/arm/boot/dts/wd-mbwe.dts | 106 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a4a6d70..0395674 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -520,6 +520,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_ARCH_OXNAS) += \
+	wd-mbwe.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/wd-mbwe.dts b/arch/arm/boot/dts/wd-mbwe.dts
new file mode 100644
index 0000000..ad97e2f
--- /dev/null
+++ b/arch/arm/boot/dts/wd-mbwe.dts
@@ -0,0 +1,106 @@
+/*
+ * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox810se.dtsi"
+
+/ {
+	model = "Western Digital My Book World Edition";
+
+	compatible = "wd,mbwe", "plxtech,ox810se";
+
+	chosen {
+		bootargs = "console=ttyS1,115200n8 earlyprintk=serial";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x48000000 0x8000000>;
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		power {
+			label = "power";
+			gpios = <&gpio0 0 1>;
+			linux,code = <0x198>;
+		};
+
+		recovery {
+			label = "recovery";
+			gpios = <&gpio0 4 1>;
+			linux,code = <0xab>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		a0 {
+			label = "activity0";
+			gpios = <&gpio0 25 0>;
+			default-state = "keep";
+		};
+
+		a1 {
+			label = "activity1";
+			gpios = <&gpio0 26 0>;
+			default-state = "keep";
+		};
+
+		a2 {
+			label = "activity2";
+			gpios = <&gpio0 5 0>;
+			default-state = "keep";
+		};
+
+		a3 {
+			label = "activity3";
+			gpios = <&gpio0 6 0>;
+			default-state = "keep";
+		};
+
+		a4 {
+			label = "activity4";
+			gpios = <&gpio0 7 0>;
+			default-state = "keep";
+		};
+
+		a5 {
+			label = "activity5";
+			gpios = <&gpio1 2 0>;
+			default-state = "keep";
+		};
+	};
+
+	i2c-gpio {
+		compatible = "i2c-gpio";
+		gpios = <&gpio0 3 0 /* sda */
+			 &gpio0 2 0 /* scl */
+			 >;
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc0: rtc at 48 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
-- 
1.9.1

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

* Re: [PATCH 12/17] arm: Add new mach-oxnas
  2016-03-03 11:40   ` Neil Armstrong
@ 2016-03-03 11:49     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 208+ messages in thread
From: Russell King - ARM Linux @ 2016-03-03 11:49 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel

On Thu, Mar 03, 2016 at 12:40:05PM +0100, Neil Armstrong wrote:
> Add mach-oxnas directory containing Kconfig and generic oxnas
> handling for future SoC specific features like system reset.

Looking at the current contents of oxnas.c, do you actually need it?
What happens if you boot your with your DT without this file being
built?

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH 12/17] arm: Add new mach-oxnas
@ 2016-03-03 11:49     ` Russell King - ARM Linux
  0 siblings, 0 replies; 208+ messages in thread
From: Russell King - ARM Linux @ 2016-03-03 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 12:40:05PM +0100, Neil Armstrong wrote:
> Add mach-oxnas directory containing Kconfig and generic oxnas
> handling for future SoC specific features like system reset.

Looking at the current contents of oxnas.c, do you actually need it?
What happens if you boot your with your DT without this file being
built?

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
  2016-03-03 11:40   ` Neil Armstrong
@ 2016-03-03 12:15     ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 12:15 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Neil Armstrong, linux-kernel, devicetree, linux

On Thursday 03 March 2016 12:40:07 Neil Armstrong wrote:
> +
> +	aliases {
> +		serial0 = &uart0;
> +		serial1 = &uart1;
> +		serial2 = &uart2;
> +		serial3 = &uart3;
> +		gpio0 = &gpio0;
> +		gpio1 = &gpio1;
> +	};
>
Please put the aliases in the per-board file and list only the
devices that are actually connected (in case of uart)

> +			uart0: uart@200000 {

Make this serial@200000, to follow the standard naming convention

> +
> +				reset: reset-controller {
> +					compatible = "plxtech,nas782x-reset";
> +					#reset-cells = <1>;
> +				};
> +
> +				stdclk: stdclk {
> +					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
> +					#clock-cells = <1>;
> +				};
> +			};

Please change the compatible strings to have no 'x' wildcards in them, but
instead use a specific model.

Regarding the vendor prefixes, my understanding is that "ox810se" was the name
of the chip from Oxford Semiconductor, while nas7820 is a product name from
PLX. I think it would be logical to use "oxford" as the vendor prefix
for anything with a ox810se or ox820 ID in it rather than plxtech.

Note that both of them are now historic, as PLX itself got bought by
Avago and they seem to be discontinuing both the PLX and Oxfor brand
names.

	Arnd

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

* [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-03 12:15     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 03 March 2016 12:40:07 Neil Armstrong wrote:
> +
> +	aliases {
> +		serial0 = &uart0;
> +		serial1 = &uart1;
> +		serial2 = &uart2;
> +		serial3 = &uart3;
> +		gpio0 = &gpio0;
> +		gpio1 = &gpio1;
> +	};
>
Please put the aliases in the per-board file and list only the
devices that are actually connected (in case of uart)

> +			uart0: uart at 200000 {

Make this serial at 200000, to follow the standard naming convention

> +
> +				reset: reset-controller {
> +					compatible = "plxtech,nas782x-reset";
> +					#reset-cells = <1>;
> +				};
> +
> +				stdclk: stdclk {
> +					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
> +					#clock-cells = <1>;
> +				};
> +			};

Please change the compatible strings to have no 'x' wildcards in them, but
instead use a specific model.

Regarding the vendor prefixes, my understanding is that "ox810se" was the name
of the chip from Oxford Semiconductor, while nas7820 is a product name from
PLX. I think it would be logical to use "oxford" as the vendor prefix
for anything with a ox810se or ox820 ID in it rather than plxtech.

Note that both of them are now historic, as PLX itself got bought by
Avago and they seem to be discontinuing both the PLX and Oxfor brand
names.

	Arnd

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

* Re: [PATCH 00/17] Add Initial support for PLX Technology OX810SE
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-03 12:23   ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 12:23 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Neil Armstrong, linux-kernel, linux, John Crispin, Ma Haijun

On Thursday 03 March 2016 12:39:53 Neil Armstrong wrote:
> This serie adds initial support (IRQ, Timer, GPIO, Reset, Serial, Clocks) for
> the PLX Technology OX810SE used in the well-known Western Digital My Book
> World Edition Network Attached Storage device.
> 
> Extended support for SATA, DMA and Ethernet will come in further patches.
> 
> Upstream support for following devices like the OX820SE is welcome !
> 

Looks very nice overall. I think with the timing, it's a way too
late for 4.6 now, but there should be no problem merging this for 4.7.
I assume it's not urgent on your end, as this seems to be a somewhat
historic platform.

I had no idea there was an ARM9 based predecessor of OX820SE, so I was
surprised to see this one instead. How closely related are they?

	Arnd

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

* [PATCH 00/17] Add Initial support for PLX Technology OX810SE
@ 2016-03-03 12:23   ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 03 March 2016 12:39:53 Neil Armstrong wrote:
> This serie adds initial support (IRQ, Timer, GPIO, Reset, Serial, Clocks) for
> the PLX Technology OX810SE used in the well-known Western Digital My Book
> World Edition Network Attached Storage device.
> 
> Extended support for SATA, DMA and Ethernet will come in further patches.
> 
> Upstream support for following devices like the OX820SE is welcome !
> 

Looks very nice overall. I think with the timing, it's a way too
late for 4.6 now, but there should be no problem merging this for 4.7.
I assume it's not urgent on your end, as this seems to be a somewhat
historic platform.

I had no idea there was an ARM9 based predecessor of OX820SE, so I was
surprised to see this one instead. How closely related are they?

	Arnd

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

* Re: [PATCH 00/17] Add Initial support for PLX Technology OX810SE
  2016-03-03 12:23   ` Arnd Bergmann
@ 2016-03-03 12:36     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 12:36 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: linux-kernel, linux, John Crispin, Ma Haijun

On 03/03/2016 01:23 PM, Arnd Bergmann wrote:
> Looks very nice overall. I think with the timing, it's a way too
> late for 4.6 now, but there should be no problem merging this for 4.7.
> I assume it's not urgent on your end, as this seems to be a somewhat
> historic platform.

Yes, it's not urgent, I will certainly post a v2 following your device tree comments.

> I had no idea there was an ARM9 based predecessor of OX820SE, so I was
> surprised to see this one instead. How closely related are they?
They seem very close, the only differences seems to be in the MP CORE, the SATA
IP and the pinctrl.

> 
> 	Arnd
> 

Thanks !

Neil

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

* [PATCH 00/17] Add Initial support for PLX Technology OX810SE
@ 2016-03-03 12:36     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 12:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 01:23 PM, Arnd Bergmann wrote:
> Looks very nice overall. I think with the timing, it's a way too
> late for 4.6 now, but there should be no problem merging this for 4.7.
> I assume it's not urgent on your end, as this seems to be a somewhat
> historic platform.

Yes, it's not urgent, I will certainly post a v2 following your device tree comments.

> I had no idea there was an ARM9 based predecessor of OX820SE, so I was
> surprised to see this one instead. How closely related are they?
They seem very close, the only differences seems to be in the MP CORE, the SATA
IP and the pinctrl.

> 
> 	Arnd
> 

Thanks !

Neil

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

* Re: [PATCH 12/17] arm: Add new mach-oxnas
  2016-03-03 11:49     ` Russell King - ARM Linux
@ 2016-03-03 12:37       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 12:37 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: linux-kernel, linux-arm-kernel

On 03/03/2016 12:49 PM, Russell King - ARM Linux wrote:
> Looking at the current contents of oxnas.c, do you actually need it?
> What happens if you boot your with your DT without this file being
> built?
> 

No, it's useless for now, it boots perfectly without.
It was only a base for adding the reset management in a next patchset.

Neil

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

* [PATCH 12/17] arm: Add new mach-oxnas
@ 2016-03-03 12:37       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 12:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 12:49 PM, Russell King - ARM Linux wrote:
> Looking at the current contents of oxnas.c, do you actually need it?
> What happens if you boot your with your DT without this file being
> built?
> 

No, it's useless for now, it boots perfectly without.
It was only a base for adding the reset management in a next patchset.

Neil

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

* Re: [PATCH 12/17] arm: Add new mach-oxnas
  2016-03-03 11:40   ` Neil Armstrong
@ 2016-03-03 12:56     ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 12:56 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Neil Armstrong, linux-kernel, linux

On Thursday 03 March 2016 12:40:05 Neil Armstrong wrote:
> +
> +config MACH_OX810SE
> +	bool "Support OX810SE Based Products"
> +	select CPU_ARM926T
> +	select PLXTECH_RPS
> +	select CLKSRC_RPS_TIMER
> +	select RESET_OXNAS
> +	select COMMON_CLK_OXNAS
> +	select PINCTRL_OXNAS

Please sort these alphabetically

> +
> +static void __init oxnas_init(void)
> +{
> +	pr_info("OXNAS Device Tree boot\n");
> +
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +}

I think you should at least remove this function, as the pr_info is not
needed and the rest is the default.

As Russell mentioned, the entire file is not really needed either, but
so far we have left the trivial per-platform files in place generally.

	Arnd

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

* [PATCH 12/17] arm: Add new mach-oxnas
@ 2016-03-03 12:56     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 12:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 03 March 2016 12:40:05 Neil Armstrong wrote:
> +
> +config MACH_OX810SE
> +	bool "Support OX810SE Based Products"
> +	select CPU_ARM926T
> +	select PLXTECH_RPS
> +	select CLKSRC_RPS_TIMER
> +	select RESET_OXNAS
> +	select COMMON_CLK_OXNAS
> +	select PINCTRL_OXNAS

Please sort these alphabetically

> +
> +static void __init oxnas_init(void)
> +{
> +	pr_info("OXNAS Device Tree boot\n");
> +
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +}

I think you should at least remove this function, as the pr_info is not
needed and the rest is the default.

As Russell mentioned, the entire file is not really needed either, but
so far we have left the trivial per-platform files in place generally.

	Arnd

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 11:39   ` Neil Armstrong
@ 2016-03-03 13:01     ` Marc Zyngier
  -1 siblings, 0 replies; 208+ messages in thread
From: Marc Zyngier @ 2016-03-03 13:01 UTC (permalink / raw)
  To: Neil Armstrong, linux-kernel, linux-arm-kernel, tglx, jason; +Cc: Ma Haijun

Neil,

On 03/03/16 11:39, Neil Armstrong wrote:
> Add PLX Technology RPS IRQ Controller as irqchip driver.
> 
> CC: Ma Haijun <mahaijuns@gmail.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/irqchip/Kconfig   |   5 ++
>  drivers/irqchip/Makefile  |   1 +
>  drivers/irqchip/irq-rps.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 134 insertions(+)
>  create mode 100644 drivers/irqchip/irq-rps.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index fb50911..7892c1a 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -135,6 +135,11 @@ config PIC32_EVIC
>  	select GENERIC_IRQ_CHIP
>  	select IRQ_DOMAIN
>  
> +config PLXTECH_RPS
> +	bool
> +	select GENERIC_IRQ_CHIP
> +	select IRQ_DOMAIN
> +
>  config RENESAS_INTC_IRQPIN
>  	bool
>  	select IRQ_DOMAIN
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 18caacb..3eec3a0 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_I8259)			+= irq-i8259.o
>  obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
>  obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
>  obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
> +obj-$(CONFIG_PLXTECH_RPS)		+= irq-rps.o
>  obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
>  obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
>  obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
> diff --git a/drivers/irqchip/irq-rps.c b/drivers/irqchip/irq-rps.c
> new file mode 100644
> index 0000000..bcd4a31
> --- /dev/null
> +++ b/drivers/irqchip/irq-rps.c
> @@ -0,0 +1,128 @@
> +/*
> + * drivers/irqchip/irq-rps.c
> + *
> + * Copyright (C) 2009 Oxford Semiconductor Ltd
> + * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/irqdomain.h>
> +#include <linux/irq.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/version.h>
> +#include <linux/irqchip.h>
> +
> +#include <asm/exception.h>
> +
> +struct rps_chip_data {
> +	void __iomem *base;
> +	struct irq_domain *domain;
> +} rps_data;
> +
> +enum {
> +	RPS_IRQ_COUNT = 32,
> +
> +	RPS_STATUS = 0,
> +	RPS_RAW_STATUS = 4,
> +	RPS_UNMASK = 8,
> +	RPS_MASK = 0xc,
> +};

As much as I hate macros (despite making a living out of writing
complicated/braindead ones), shoving random and unrelated values in an
enum doesn't make much sense. Please convert this to a set of #defines.

> +
> +/* Routines to acknowledge, disable and enable interrupts */
> +static void rps_mask_irq(struct irq_data *d)
> +{
> +	u32 mask = BIT(d->hwirq);
> +
> +	iowrite32(mask, rps_data.base + RPS_MASK);

I do question the use of iowrite32 here (and its ioread32 pendent
anywhere else), as it actually translates in a writel, which contains a
memory barrier. Do you have any case that requires the use of such a
barrier? if not, consider switching to relaxed accessors (which are the

> +}
> +
> +static void rps_unmask_irq(struct irq_data *d)
> +{
> +	u32 mask = BIT(d->hwirq);
> +
> +	iowrite32(mask, rps_data.base + RPS_UNMASK);
> +}
> +
> +static void rps_ack_irq(struct irq_data *d)
> +{
> +	/* NOP */
> +}

If that's a nop, you probably don't need it, see below.

> +
> +static void __exception_irq_entry handle_irq(struct pt_regs *regs)
> +{
> +	u32 irqstat;
> +	int hwirq;
> +
> +	irqstat = ioread32(rps_data.base + RPS_STATUS);
> +	hwirq = __ffs(irqstat);
> +
> +	do {
> +		handle_IRQ(irq_find_mapping(rps_data.domain, hwirq), regs);

Please use handle_domain_irq() which will do the right thing (and save
you from RCU shouting at you).

> +
> +		irqstat = ioread32(rps_data.base + RPS_STATUS);
> +		hwirq = __ffs(irqstat);
> +	} while (irqstat);
> +}

Can you get more that a single bit set in one read from the status
register? If so, you'd be better off handling all the pending interrupts
before reading from the MMIO again, since that's a slow operation.

> +
> +int __init rps_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	int ret;
> +	struct irq_chip_generic *gc;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	rps_data.base = of_iomap(node, 0);
> +	WARN(!rps_data.base, "unable to map rps registers\n");
> +
> +	rps_data.domain = irq_domain_add_linear(node, RPS_IRQ_COUNT,
> +						&irq_generic_chip_ops,
> +						NULL);
> +	if (!rps_data.domain) {
> +		pr_err("%s: could add irq domain\n",
> +		       node->full_name);
> +		return -ENOMEM;
> +	}
> +
> +	ret = irq_alloc_domain_generic_chips(rps_data.domain, RPS_IRQ_COUNT, 1,
> +					     "RPS", handle_level_irq,

Given that all your interrupts are level triggered...

> +					     0, 0, IRQ_GC_INIT_NESTED_LOCK);
> +	if (ret) {
> +		pr_err("%s: could not allocate generic chip\n",
> +		       node->full_name);
> +		irq_domain_remove(rps_data.domain);
> +		return -EINVAL;
> +	}
> +
> +	gc = irq_get_domain_generic_chip(rps_data.domain, 0);
> +	gc->chip_types[0].chip.irq_ack = rps_ack_irq;

... I believe you can loose this callback, it is never used by the handler.

> +	gc->chip_types[0].chip.irq_mask = rps_mask_irq;
> +	gc->chip_types[0].chip.irq_unmask = rps_unmask_irq;
> +
> +	/* Disable all IRQs */
> +	iowrite32(~0, rps_data.base + RPS_MASK);
> +
> +	set_handle_irq(handle_irq);
> +
> +	pr_info("Registered %d rps interrupts\n", RPS_IRQ_COUNT);

Given that this is always the same value, I don't think this is a very
useful message...

> +
> +	return 0;
> +}
> +
> +IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 13:01     ` Marc Zyngier
  0 siblings, 0 replies; 208+ messages in thread
From: Marc Zyngier @ 2016-03-03 13:01 UTC (permalink / raw)
  To: linux-arm-kernel

Neil,

On 03/03/16 11:39, Neil Armstrong wrote:
> Add PLX Technology RPS IRQ Controller as irqchip driver.
> 
> CC: Ma Haijun <mahaijuns@gmail.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/irqchip/Kconfig   |   5 ++
>  drivers/irqchip/Makefile  |   1 +
>  drivers/irqchip/irq-rps.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 134 insertions(+)
>  create mode 100644 drivers/irqchip/irq-rps.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index fb50911..7892c1a 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -135,6 +135,11 @@ config PIC32_EVIC
>  	select GENERIC_IRQ_CHIP
>  	select IRQ_DOMAIN
>  
> +config PLXTECH_RPS
> +	bool
> +	select GENERIC_IRQ_CHIP
> +	select IRQ_DOMAIN
> +
>  config RENESAS_INTC_IRQPIN
>  	bool
>  	select IRQ_DOMAIN
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 18caacb..3eec3a0 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_I8259)			+= irq-i8259.o
>  obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
>  obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
>  obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
> +obj-$(CONFIG_PLXTECH_RPS)		+= irq-rps.o
>  obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
>  obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
>  obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
> diff --git a/drivers/irqchip/irq-rps.c b/drivers/irqchip/irq-rps.c
> new file mode 100644
> index 0000000..bcd4a31
> --- /dev/null
> +++ b/drivers/irqchip/irq-rps.c
> @@ -0,0 +1,128 @@
> +/*
> + * drivers/irqchip/irq-rps.c
> + *
> + * Copyright (C) 2009 Oxford Semiconductor Ltd
> + * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/irqdomain.h>
> +#include <linux/irq.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/version.h>
> +#include <linux/irqchip.h>
> +
> +#include <asm/exception.h>
> +
> +struct rps_chip_data {
> +	void __iomem *base;
> +	struct irq_domain *domain;
> +} rps_data;
> +
> +enum {
> +	RPS_IRQ_COUNT = 32,
> +
> +	RPS_STATUS = 0,
> +	RPS_RAW_STATUS = 4,
> +	RPS_UNMASK = 8,
> +	RPS_MASK = 0xc,
> +};

As much as I hate macros (despite making a living out of writing
complicated/braindead ones), shoving random and unrelated values in an
enum doesn't make much sense. Please convert this to a set of #defines.

> +
> +/* Routines to acknowledge, disable and enable interrupts */
> +static void rps_mask_irq(struct irq_data *d)
> +{
> +	u32 mask = BIT(d->hwirq);
> +
> +	iowrite32(mask, rps_data.base + RPS_MASK);

I do question the use of iowrite32 here (and its ioread32 pendent
anywhere else), as it actually translates in a writel, which contains a
memory barrier. Do you have any case that requires the use of such a
barrier? if not, consider switching to relaxed accessors (which are the

> +}
> +
> +static void rps_unmask_irq(struct irq_data *d)
> +{
> +	u32 mask = BIT(d->hwirq);
> +
> +	iowrite32(mask, rps_data.base + RPS_UNMASK);
> +}
> +
> +static void rps_ack_irq(struct irq_data *d)
> +{
> +	/* NOP */
> +}

If that's a nop, you probably don't need it, see below.

> +
> +static void __exception_irq_entry handle_irq(struct pt_regs *regs)
> +{
> +	u32 irqstat;
> +	int hwirq;
> +
> +	irqstat = ioread32(rps_data.base + RPS_STATUS);
> +	hwirq = __ffs(irqstat);
> +
> +	do {
> +		handle_IRQ(irq_find_mapping(rps_data.domain, hwirq), regs);

Please use handle_domain_irq() which will do the right thing (and save
you from RCU shouting at you).

> +
> +		irqstat = ioread32(rps_data.base + RPS_STATUS);
> +		hwirq = __ffs(irqstat);
> +	} while (irqstat);
> +}

Can you get more that a single bit set in one read from the status
register? If so, you'd be better off handling all the pending interrupts
before reading from the MMIO again, since that's a slow operation.

> +
> +int __init rps_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	int ret;
> +	struct irq_chip_generic *gc;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	rps_data.base = of_iomap(node, 0);
> +	WARN(!rps_data.base, "unable to map rps registers\n");
> +
> +	rps_data.domain = irq_domain_add_linear(node, RPS_IRQ_COUNT,
> +						&irq_generic_chip_ops,
> +						NULL);
> +	if (!rps_data.domain) {
> +		pr_err("%s: could add irq domain\n",
> +		       node->full_name);
> +		return -ENOMEM;
> +	}
> +
> +	ret = irq_alloc_domain_generic_chips(rps_data.domain, RPS_IRQ_COUNT, 1,
> +					     "RPS", handle_level_irq,

Given that all your interrupts are level triggered...

> +					     0, 0, IRQ_GC_INIT_NESTED_LOCK);
> +	if (ret) {
> +		pr_err("%s: could not allocate generic chip\n",
> +		       node->full_name);
> +		irq_domain_remove(rps_data.domain);
> +		return -EINVAL;
> +	}
> +
> +	gc = irq_get_domain_generic_chip(rps_data.domain, 0);
> +	gc->chip_types[0].chip.irq_ack = rps_ack_irq;

... I believe you can loose this callback, it is never used by the handler.

> +	gc->chip_types[0].chip.irq_mask = rps_mask_irq;
> +	gc->chip_types[0].chip.irq_unmask = rps_unmask_irq;
> +
> +	/* Disable all IRQs */
> +	iowrite32(~0, rps_data.base + RPS_MASK);
> +
> +	set_handle_irq(handle_irq);
> +
> +	pr_info("Registered %d rps interrupts\n", RPS_IRQ_COUNT);

Given that this is always the same value, I don't think this is a very
useful message...

> +
> +	return 0;
> +}
> +
> +IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 13:01     ` Marc Zyngier
@ 2016-03-03 13:08       ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 13:08 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Marc Zyngier, Neil Armstrong, linux-kernel, tglx, jason, Ma Haijun

On Thursday 03 March 2016 13:01:13 Marc Zyngier wrote:
> > +/* Routines to acknowledge, disable and enable interrupts */
> > +static void rps_mask_irq(struct irq_data *d)
> > +{
> > +     u32 mask = BIT(d->hwirq);
> > +
> > +     iowrite32(mask, rps_data.base + RPS_MASK);
> 
> I do question the use of iowrite32 here (and its ioread32 pendent
> anywhere else), as it actually translates in a writel, which contains a
> memory barrier. Do you have any case that requires the use of such a
> barrier? if not, consider switching to relaxed accessors (which are the
> 

I really ask everyone to do the opposite: we have seen several drivers
blindlessly using the relaxed accessors and actually introducing bugs
that way, so I'd rather see the readl/writel ones used by default.

In any performance critical code, it's reasonable to take a closer
look and use the relaxed version with an added comment explaining
why it's safe there.

	Arnd

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 13:08       ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 13:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 03 March 2016 13:01:13 Marc Zyngier wrote:
> > +/* Routines to acknowledge, disable and enable interrupts */
> > +static void rps_mask_irq(struct irq_data *d)
> > +{
> > +     u32 mask = BIT(d->hwirq);
> > +
> > +     iowrite32(mask, rps_data.base + RPS_MASK);
> 
> I do question the use of iowrite32 here (and its ioread32 pendent
> anywhere else), as it actually translates in a writel, which contains a
> memory barrier. Do you have any case that requires the use of such a
> barrier? if not, consider switching to relaxed accessors (which are the
> 

I really ask everyone to do the opposite: we have seen several drivers
blindlessly using the relaxed accessors and actually introducing bugs
that way, so I'd rather see the readl/writel ones used by default.

In any performance critical code, it's reasonable to take a closer
look and use the relaxed version with an added comment explaining
why it's safe there.

	Arnd

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

* Re: [PATCH 12/17] arm: Add new mach-oxnas
  2016-03-03 12:56     ` Arnd Bergmann
@ 2016-03-03 13:29       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 208+ messages in thread
From: Russell King - ARM Linux @ 2016-03-03 13:29 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linux-arm-kernel, Neil Armstrong, linux-kernel

On Thu, Mar 03, 2016 at 01:56:56PM +0100, Arnd Bergmann wrote:
> As Russell mentioned, the entire file is not really needed either, but
> so far we have left the trivial per-platform files in place generally.

I think that's something we should be looking to remove: if the
per-platform files give no benefit, then there is no point in
having them, and they just increase the size of the code base.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH 12/17] arm: Add new mach-oxnas
@ 2016-03-03 13:29       ` Russell King - ARM Linux
  0 siblings, 0 replies; 208+ messages in thread
From: Russell King - ARM Linux @ 2016-03-03 13:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 01:56:56PM +0100, Arnd Bergmann wrote:
> As Russell mentioned, the entire file is not really needed either, but
> so far we have left the trivial per-platform files in place generally.

I think that's something we should be looking to remove: if the
per-platform files give no benefit, then there is no point in
having them, and they just increase the size of the code base.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 13:08       ` Arnd Bergmann
@ 2016-03-03 13:36         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 208+ messages in thread
From: Russell King - ARM Linux @ 2016-03-03 13:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, jason, Neil Armstrong, Marc Zyngier,
	linux-kernel, tglx, Ma Haijun

On Thu, Mar 03, 2016 at 02:08:19PM +0100, Arnd Bergmann wrote:
> On Thursday 03 March 2016 13:01:13 Marc Zyngier wrote:
> > > +/* Routines to acknowledge, disable and enable interrupts */
> > > +static void rps_mask_irq(struct irq_data *d)
> > > +{
> > > +     u32 mask = BIT(d->hwirq);
> > > +
> > > +     iowrite32(mask, rps_data.base + RPS_MASK);
> > 
> > I do question the use of iowrite32 here (and its ioread32 pendent
> > anywhere else), as it actually translates in a writel, which contains a
> > memory barrier. Do you have any case that requires the use of such a
> > barrier? if not, consider switching to relaxed accessors (which are the
> > 
> 
> I really ask everyone to do the opposite: we have seen several drivers
> blindlessly using the relaxed accessors and actually introducing bugs
> that way, so I'd rather see the readl/writel ones used by default.

I actually agree with Marc - we have far too many drivers using the
barriered IO accessors, which are really very expensive on 32-bit
ARM.

For most ARM systems, the rules are quite simple: a write which causes
DMA memory to be accessed by the device must be using the barriered
IO accessor, and a read from a DMA status register must be too.
Everything else need not be.  Barriered IO accessors are only about
access ordering.

That's independent of whether you need a read-back to ensure that the
write has hit the hardware: that's a completely different problem, and
one which is harder for people to understand and get right.  (Eg, for
interrupt registers.)

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 13:36         ` Russell King - ARM Linux
  0 siblings, 0 replies; 208+ messages in thread
From: Russell King - ARM Linux @ 2016-03-03 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 02:08:19PM +0100, Arnd Bergmann wrote:
> On Thursday 03 March 2016 13:01:13 Marc Zyngier wrote:
> > > +/* Routines to acknowledge, disable and enable interrupts */
> > > +static void rps_mask_irq(struct irq_data *d)
> > > +{
> > > +     u32 mask = BIT(d->hwirq);
> > > +
> > > +     iowrite32(mask, rps_data.base + RPS_MASK);
> > 
> > I do question the use of iowrite32 here (and its ioread32 pendent
> > anywhere else), as it actually translates in a writel, which contains a
> > memory barrier. Do you have any case that requires the use of such a
> > barrier? if not, consider switching to relaxed accessors (which are the
> > 
> 
> I really ask everyone to do the opposite: we have seen several drivers
> blindlessly using the relaxed accessors and actually introducing bugs
> that way, so I'd rather see the readl/writel ones used by default.

I actually agree with Marc - we have far too many drivers using the
barriered IO accessors, which are really very expensive on 32-bit
ARM.

For most ARM systems, the rules are quite simple: a write which causes
DMA memory to be accessed by the device must be using the barriered
IO accessor, and a read from a DMA status register must be too.
Everything else need not be.  Barriered IO accessors are only about
access ordering.

That's independent of whether you need a read-back to ensure that the
write has hit the hardware: that's a completely different problem, and
one which is harder for people to understand and get right.  (Eg, for
interrupt registers.)

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
  2016-03-03 12:15     ` Arnd Bergmann
  (?)
@ 2016-03-03 13:39       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 13:39 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel; +Cc: linux-kernel, devicetree, linux

On 03/03/2016 01:15 PM, Arnd Bergmann wrote:
> On Thursday 03 March 2016 12:40:07 Neil Armstrong wrote:
>> +
>> +	aliases {
>> +		serial0 = &uart0;
>> +		serial1 = &uart1;
>> +		serial2 = &uart2;
>> +		serial3 = &uart3;
>> +		gpio0 = &gpio0;
>> +		gpio1 = &gpio1;
>> +	};
>>
> Please put the aliases in the per-board file and list only the
> devices that are actually connected (in case of uart)
Done.

> 
>> +			uart0: uart@200000 {
> 
> Make this serial@200000, to follow the standard naming convention
Done.

> 
>> +
>> +				reset: reset-controller {
>> +					compatible = "plxtech,nas782x-reset";
>> +					#reset-cells = <1>;
>> +				};
>> +
>> +				stdclk: stdclk {
>> +					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
>> +					#clock-cells = <1>;
>> +				};
>> +			};
> 
> Please change the compatible strings to have no 'x' wildcards in them, but
> instead use a specific model.
Ok, I switched to only oxsemi,ox810se-* strings.
> 
> Regarding the vendor prefixes, my understanding is that "ox810se" was the name
> of the chip from Oxford Semiconductor, while nas7820 is a product name from
> PLX. I think it would be logical to use "oxford" as the vendor prefix
> for anything with a ox810se or ox820 ID in it rather than plxtech.
Ok, I switched to oxsemi but keeped plxtech and added oxsemi in the vendor prefixes.

> 
> Note that both of them are now historic, as PLX itself got bought by
> Avago and they seem to be discontinuing both the PLX and Oxfor brand
> names.
Yes, it's kind of a mess. The ox820 has been rebranded to plx7821, but not the ox810...
> 
> 	Arnd
> 

Thanks,
Neil

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

* Re: [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-03 13:39       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 13:39 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, linux-lFZ/pmaqli7XmaaqVzeoHQ

On 03/03/2016 01:15 PM, Arnd Bergmann wrote:
> On Thursday 03 March 2016 12:40:07 Neil Armstrong wrote:
>> +
>> +	aliases {
>> +		serial0 = &uart0;
>> +		serial1 = &uart1;
>> +		serial2 = &uart2;
>> +		serial3 = &uart3;
>> +		gpio0 = &gpio0;
>> +		gpio1 = &gpio1;
>> +	};
>>
> Please put the aliases in the per-board file and list only the
> devices that are actually connected (in case of uart)
Done.

> 
>> +			uart0: uart@200000 {
> 
> Make this serial@200000, to follow the standard naming convention
Done.

> 
>> +
>> +				reset: reset-controller {
>> +					compatible = "plxtech,nas782x-reset";
>> +					#reset-cells = <1>;
>> +				};
>> +
>> +				stdclk: stdclk {
>> +					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
>> +					#clock-cells = <1>;
>> +				};
>> +			};
> 
> Please change the compatible strings to have no 'x' wildcards in them, but
> instead use a specific model.
Ok, I switched to only oxsemi,ox810se-* strings.
> 
> Regarding the vendor prefixes, my understanding is that "ox810se" was the name
> of the chip from Oxford Semiconductor, while nas7820 is a product name from
> PLX. I think it would be logical to use "oxford" as the vendor prefix
> for anything with a ox810se or ox820 ID in it rather than plxtech.
Ok, I switched to oxsemi but keeped plxtech and added oxsemi in the vendor prefixes.

> 
> Note that both of them are now historic, as PLX itself got bought by
> Avago and they seem to be discontinuing both the PLX and Oxfor brand
> names.
Yes, it's kind of a mess. The ox820 has been rebranded to plx7821, but not the ox810...
> 
> 	Arnd
> 

Thanks,
Neil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-03 13:39       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 01:15 PM, Arnd Bergmann wrote:
> On Thursday 03 March 2016 12:40:07 Neil Armstrong wrote:
>> +
>> +	aliases {
>> +		serial0 = &uart0;
>> +		serial1 = &uart1;
>> +		serial2 = &uart2;
>> +		serial3 = &uart3;
>> +		gpio0 = &gpio0;
>> +		gpio1 = &gpio1;
>> +	};
>>
> Please put the aliases in the per-board file and list only the
> devices that are actually connected (in case of uart)
Done.

> 
>> +			uart0: uart at 200000 {
> 
> Make this serial at 200000, to follow the standard naming convention
Done.

> 
>> +
>> +				reset: reset-controller {
>> +					compatible = "plxtech,nas782x-reset";
>> +					#reset-cells = <1>;
>> +				};
>> +
>> +				stdclk: stdclk {
>> +					compatible = "plxtech,ox810se-stdclk", "plxtech,nas782x-stdclk";
>> +					#clock-cells = <1>;
>> +				};
>> +			};
> 
> Please change the compatible strings to have no 'x' wildcards in them, but
> instead use a specific model.
Ok, I switched to only oxsemi,ox810se-* strings.
> 
> Regarding the vendor prefixes, my understanding is that "ox810se" was the name
> of the chip from Oxford Semiconductor, while nas7820 is a product name from
> PLX. I think it would be logical to use "oxford" as the vendor prefix
> for anything with a ox810se or ox820 ID in it rather than plxtech.
Ok, I switched to oxsemi but keeped plxtech and added oxsemi in the vendor prefixes.

> 
> Note that both of them are now historic, as PLX itself got bought by
> Avago and they seem to be discontinuing both the PLX and Oxfor brand
> names.
Yes, it's kind of a mess. The ox820 has been rebranded to plx7821, but not the ox810...
> 
> 	Arnd
> 

Thanks,
Neil

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

* Re: [PATCH 12/17] arm: Add new mach-oxnas
  2016-03-03 13:29       ` Russell King - ARM Linux
@ 2016-03-03 13:40         ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 13:40 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Russell King - ARM Linux, linux-kernel, Neil Armstrong

On Thursday 03 March 2016 13:29:56 Russell King - ARM Linux wrote:
> On Thu, Mar 03, 2016 at 01:56:56PM +0100, Arnd Bergmann wrote:
> > As Russell mentioned, the entire file is not really needed either, but
> > so far we have left the trivial per-platform files in place generally.
> 
> I think that's something we should be looking to remove: if the
> per-platform files give no benefit, then there is no point in
> having them, and they just increase the size of the code base.
> 

I agree, I think the main reason it hasn't been done yet is that
nobody has thought in detail about whether or how to keep
the last remaining piece of information (the machine name as
printed in /proc/cpuinfo) when removing the machine descriptors.

If we want to keep that around, we could probably have a global
lookup table of root node compatible strings, or we decide to
use the contents of the "model" property instead. This has been
discussed several times in the pasts, without any real consensus.

	Arnd

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

* [PATCH 12/17] arm: Add new mach-oxnas
@ 2016-03-03 13:40         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 13:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 03 March 2016 13:29:56 Russell King - ARM Linux wrote:
> On Thu, Mar 03, 2016 at 01:56:56PM +0100, Arnd Bergmann wrote:
> > As Russell mentioned, the entire file is not really needed either, but
> > so far we have left the trivial per-platform files in place generally.
> 
> I think that's something we should be looking to remove: if the
> per-platform files give no benefit, then there is no point in
> having them, and they just increase the size of the code base.
> 

I agree, I think the main reason it hasn't been done yet is that
nobody has thought in detail about whether or how to keep
the last remaining piece of information (the machine name as
printed in /proc/cpuinfo) when removing the machine descriptors.

If we want to keep that around, we could probably have a global
lookup table of root node compatible strings, or we decide to
use the contents of the "model" property instead. This has been
discussed several times in the pasts, without any real consensus.

	Arnd

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

* Re: [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
  2016-03-03 11:39   ` Neil Armstrong
@ 2016-03-03 14:18     ` Philipp Zabel
  -1 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 14:18 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, Ma Haijun

Hi Neil,

Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> Add System reset controller driver for PLX Technology OXNAS SoC Family.
> 
> CC: Ma Haijun <mahaijuns@gmail.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/reset/Kconfig       |   4 ++
>  drivers/reset/Makefile      |   1 +
>  drivers/reset/reset-oxnas.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 154 insertions(+)
>  create mode 100644 drivers/reset/reset-oxnas.c
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index df37212..f0ea63b 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -12,5 +12,9 @@ menuconfig RESET_CONTROLLER
>  
>  	  If unsure, say no.
>  
> +config RESET_OXNAS
> +	bool
> +	select MFD_SYSCON

I'd prefer not to select MFD_SYSCON here, but rather let ARCH_OXNAS do
that.

>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 4d7178e..97e04c5 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
>  obj-$(CONFIG_ARCH_HISI) += hisilicon/
>  obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
>  obj-$(CONFIG_ATH79) += reset-ath79.o
> +obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
> diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
> new file mode 100644
> index 0000000..d0ab670
> --- /dev/null
> +++ b/drivers/reset/reset-oxnas.c
> @@ -0,0 +1,149 @@
> +/*
> + * drivers/reset/reset-oxnas.c
> + *
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
> + * Copyright (C) 2009 Oxford Semiconductor Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/err.h>
> +#include <linux/io.h>

Is there any need to include linux/io.h ?

> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/types.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +/* Regmap offsets */
> +#define RST_SET_REGOFFSET	0x34
> +#define RST_CLR_REGOFFSET	0x38
> +
> +struct oxnas_reset {
> +	struct regmap *regmap;
> +	struct reset_controller_dev rcdev;
> +};
> +
> +static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct oxnas_reset *data =
> +		container_of(rcdev, struct oxnas_reset, rcdev);
> +
> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
> +	msleep(50);

Is this the right delay for all of the resets in this register?
If not, I'd drop the .reset callback.

> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
> +
> +	return 0;
> +}
> +
> +static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct oxnas_reset *data =
> +		container_of(rcdev, struct oxnas_reset, rcdev);
> +
> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
> +
> +	return 0;
> +}
> +
> +static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
> +				unsigned long id)
> +{
> +	struct oxnas_reset *data =
> +		container_of(rcdev, struct oxnas_reset, rcdev);
> +
> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
> +
> +	return 0;
> +}
> +
> +static struct reset_control_ops oxnas_reset_ops = {

const

> +	.reset		= oxnas_reset_reset,
> +	.assert		= oxnas_reset_assert,
> +	.deassert	= oxnas_reset_deassert,
> +};
> +
> +static const struct of_device_id oxnas_reset_dt_ids[] = {
> +	 { .compatible = "plxtech,nas782x-reset", },
> +	 { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
> +
> +static int oxnas_reset_probe(struct platform_device *pdev)
> +{
> +	struct oxnas_reset *data;
> +	struct device *parent;
> +
> +	parent = pdev->dev.parent;
> +	if (!parent) {
> +		dev_err(&pdev->dev, "no parent\n");

Can this even happen?

> +		return -ENODEV;
> +	}
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->regmap = syscon_node_to_regmap(parent->of_node);
> +	if (IS_ERR(data->regmap)) {
> +		dev_err(&pdev->dev, "failed to get parent regmap\n");
> +		return -ENODEV;

Better print the error code and return it.

> +	}
> +
> +	data->rcdev.owner = THIS_MODULE;
> +	data->rcdev.nr_resets = 32;
> +	data->rcdev.ops = &oxnas_reset_ops;
> +	data->rcdev.of_node = pdev->dev.of_node;
> +	reset_controller_register(&data->rcdev);

Move this down a bit:

> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;

and
	return reset_controller_register(&data->rcdev);
here.

> +}
> +
> +static int oxnas_reset_remove(struct platform_device *pdev)
> +{
> +	struct oxnas_reset *data = platform_get_drvdata(pdev);
> +
> +	reset_controller_unregister(&data->rcdev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver oxnas_reset_driver = {
> +	.probe	= oxnas_reset_probe,
> +	.remove	= oxnas_reset_remove,
> +	.driver = {
> +		.name		= "oxnas-reset",
> +		.owner		= THIS_MODULE,

The .owner field is overwritten by __platform_driver_register() anyway,
just drop it.

> +		.of_match_table	= oxnas_reset_dt_ids,
> +	},
> +};
> +
> +static int __init oxnas_reset_init(void)
> +{
> +	return platform_driver_probe(&oxnas_reset_driver,
> +				     oxnas_reset_probe);
> +}
> +
> +/*
> + * Reset controller does not support probe deferral, so it has to be
> + * initialized before any user, in particular, PCIE uses subsys_initcall.
> + */
> +arch_initcall(oxnas_reset_init);

That doesn't sound right. (of_)reset_control_get return -EPROBE_DEFER if
the rcdev isn't found in the list. Could you elaborate on this?

regards
Philipp

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

* [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
@ 2016-03-03 14:18     ` Philipp Zabel
  0 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 14:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Neil,

Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> Add System reset controller driver for PLX Technology OXNAS SoC Family.
> 
> CC: Ma Haijun <mahaijuns@gmail.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/reset/Kconfig       |   4 ++
>  drivers/reset/Makefile      |   1 +
>  drivers/reset/reset-oxnas.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 154 insertions(+)
>  create mode 100644 drivers/reset/reset-oxnas.c
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index df37212..f0ea63b 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -12,5 +12,9 @@ menuconfig RESET_CONTROLLER
>  
>  	  If unsure, say no.
>  
> +config RESET_OXNAS
> +	bool
> +	select MFD_SYSCON

I'd prefer not to select MFD_SYSCON here, but rather let ARCH_OXNAS do
that.

>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 4d7178e..97e04c5 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
>  obj-$(CONFIG_ARCH_HISI) += hisilicon/
>  obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
>  obj-$(CONFIG_ATH79) += reset-ath79.o
> +obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
> diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
> new file mode 100644
> index 0000000..d0ab670
> --- /dev/null
> +++ b/drivers/reset/reset-oxnas.c
> @@ -0,0 +1,149 @@
> +/*
> + * drivers/reset/reset-oxnas.c
> + *
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
> + * Copyright (C) 2009 Oxford Semiconductor Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/err.h>
> +#include <linux/io.h>

Is there any need to include linux/io.h ?

> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/types.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +/* Regmap offsets */
> +#define RST_SET_REGOFFSET	0x34
> +#define RST_CLR_REGOFFSET	0x38
> +
> +struct oxnas_reset {
> +	struct regmap *regmap;
> +	struct reset_controller_dev rcdev;
> +};
> +
> +static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct oxnas_reset *data =
> +		container_of(rcdev, struct oxnas_reset, rcdev);
> +
> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
> +	msleep(50);

Is this the right delay for all of the resets in this register?
If not, I'd drop the .reset callback.

> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
> +
> +	return 0;
> +}
> +
> +static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct oxnas_reset *data =
> +		container_of(rcdev, struct oxnas_reset, rcdev);
> +
> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
> +
> +	return 0;
> +}
> +
> +static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
> +				unsigned long id)
> +{
> +	struct oxnas_reset *data =
> +		container_of(rcdev, struct oxnas_reset, rcdev);
> +
> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
> +
> +	return 0;
> +}
> +
> +static struct reset_control_ops oxnas_reset_ops = {

const

> +	.reset		= oxnas_reset_reset,
> +	.assert		= oxnas_reset_assert,
> +	.deassert	= oxnas_reset_deassert,
> +};
> +
> +static const struct of_device_id oxnas_reset_dt_ids[] = {
> +	 { .compatible = "plxtech,nas782x-reset", },
> +	 { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
> +
> +static int oxnas_reset_probe(struct platform_device *pdev)
> +{
> +	struct oxnas_reset *data;
> +	struct device *parent;
> +
> +	parent = pdev->dev.parent;
> +	if (!parent) {
> +		dev_err(&pdev->dev, "no parent\n");

Can this even happen?

> +		return -ENODEV;
> +	}
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->regmap = syscon_node_to_regmap(parent->of_node);
> +	if (IS_ERR(data->regmap)) {
> +		dev_err(&pdev->dev, "failed to get parent regmap\n");
> +		return -ENODEV;

Better print the error code and return it.

> +	}
> +
> +	data->rcdev.owner = THIS_MODULE;
> +	data->rcdev.nr_resets = 32;
> +	data->rcdev.ops = &oxnas_reset_ops;
> +	data->rcdev.of_node = pdev->dev.of_node;
> +	reset_controller_register(&data->rcdev);

Move this down a bit:

> +
> +	platform_set_drvdata(pdev, data);
> +
> +	return 0;

and
	return reset_controller_register(&data->rcdev);
here.

> +}
> +
> +static int oxnas_reset_remove(struct platform_device *pdev)
> +{
> +	struct oxnas_reset *data = platform_get_drvdata(pdev);
> +
> +	reset_controller_unregister(&data->rcdev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver oxnas_reset_driver = {
> +	.probe	= oxnas_reset_probe,
> +	.remove	= oxnas_reset_remove,
> +	.driver = {
> +		.name		= "oxnas-reset",
> +		.owner		= THIS_MODULE,

The .owner field is overwritten by __platform_driver_register() anyway,
just drop it.

> +		.of_match_table	= oxnas_reset_dt_ids,
> +	},
> +};
> +
> +static int __init oxnas_reset_init(void)
> +{
> +	return platform_driver_probe(&oxnas_reset_driver,
> +				     oxnas_reset_probe);
> +}
> +
> +/*
> + * Reset controller does not support probe deferral, so it has to be
> + * initialized before any user, in particular, PCIE uses subsys_initcall.
> + */
> +arch_initcall(oxnas_reset_init);

That doesn't sound right. (of_)reset_control_get return -EPROBE_DEFER if
the rcdev isn't found in the list. Could you elaborate on this?

regards
Philipp

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

* Re: [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
  2016-03-03 11:40   ` Neil Armstrong
@ 2016-03-03 14:21     ` Philipp Zabel
  -1 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 14:21 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/reset/plxtech,reset.txt    | 25 ++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt
> 
> diff --git a/Documentation/devicetree/bindings/reset/plxtech,reset.txt b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
> new file mode 100644
> index 0000000..e99648d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
> @@ -0,0 +1,25 @@
> +PLX Technology OXNAS SoC Family RESET Controller
> +================================================
> +
> +Please also refer to reset.txt in this directory for common reset
> +controller binding usage.
> +
> +Required properties:
> +- compatible: Should be "plxtech,nas782x-reset"
> +- #reset-cells: 1, see below
> +
> +Parent node should have the following properties :
> +- compatible: Should be "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd"
> +
> +example:
> +
> +sys: sys-ctrl@000000 {
> +	compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
> +	reg = <0x000000 0x100000>;
> +
> +	reset: reset-controller {
> +		compatible = "plxtech,nas782x-reset";
> +		#reset-cells = <1>;
> +
> +	};
> +};

Is there a list of the reset bits in this register?

regards
Philipp

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

* [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-03 14:21     ` Philipp Zabel
  0 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/reset/plxtech,reset.txt    | 25 ++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt
> 
> diff --git a/Documentation/devicetree/bindings/reset/plxtech,reset.txt b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
> new file mode 100644
> index 0000000..e99648d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
> @@ -0,0 +1,25 @@
> +PLX Technology OXNAS SoC Family RESET Controller
> +================================================
> +
> +Please also refer to reset.txt in this directory for common reset
> +controller binding usage.
> +
> +Required properties:
> +- compatible: Should be "plxtech,nas782x-reset"
> +- #reset-cells: 1, see below
> +
> +Parent node should have the following properties :
> +- compatible: Should be "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd"
> +
> +example:
> +
> +sys: sys-ctrl at 000000 {
> +	compatible = "plxtech,ox810se-sys-ctrl", "syscon", "simple-mfd";
> +	reg = <0x000000 0x100000>;
> +
> +	reset: reset-controller {
> +		compatible = "plxtech,nas782x-reset";
> +		#reset-cells = <1>;
> +
> +	};
> +};

Is there a list of the reset bits in this register?

regards
Philipp

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

* Re: [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-03 14:24       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:24 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: linux-kernel, linux-arm-kernel, devicetree

On 03/03/2016 03:21 PM, Philipp Zabel wrote:
> Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> Is there a list of the reset bits in this register?
> 
> regards
> Philipp
> 

Yes, should I add it to the bindings ?

Neil

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

* Re: [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-03 14:24       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:24 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On 03/03/2016 03:21 PM, Philipp Zabel wrote:
> Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
>> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> 
> Is there a list of the reset bits in this register?
> 
> regards
> Philipp
> 

Yes, should I add it to the bindings ?

Neil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-03 14:24       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 03:21 PM, Philipp Zabel wrote:
> Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> Is there a list of the reset bits in this register?
> 
> regards
> Philipp
> 

Yes, should I add it to the bindings ?

Neil

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

* Re: [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
  2016-03-03 14:18     ` Philipp Zabel
@ 2016-03-03 14:29       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:29 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: linux-kernel, linux-arm-kernel, Ma Haijun

On 03/03/2016 03:18 PM, Philipp Zabel wrote:
> Hi Neil,
> 
>> +config RESET_OXNAS
>> +	bool
>> +	select MFD_SYSCON
> 
> I'd prefer not to select MFD_SYSCON here, but rather let ARCH_OXNAS do
> that.
> 
OK.

>> +#include <linux/io.h>
> 
> Is there any need to include linux/io.h ?

No, dropping.

>> +static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
>> +			      unsigned long id)
>> +{
>> +	struct oxnas_reset *data =
>> +		container_of(rcdev, struct oxnas_reset, rcdev);
>> +
>> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
>> +	msleep(50);
> 
> Is this the right delay for all of the resets in this register?
> If not, I'd drop the .reset callback.
> 
The delay is not strictly necessary, but better to avoid any HW issues.
And the .reset callback is needed since reset_control_reset
does not assert -> deassert as fallback.

>> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
>> +
>> +	return 0;
>> +}
>> +
>> +static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
>> +			      unsigned long id)
>> +{
>> +	struct oxnas_reset *data =
>> +		container_of(rcdev, struct oxnas_reset, rcdev);
>> +
>> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
>> +
>> +	return 0;
>> +}
>> +
>> +static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
>> +				unsigned long id)
>> +{
>> +	struct oxnas_reset *data =
>> +		container_of(rcdev, struct oxnas_reset, rcdev);
>> +
>> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
>> +
>> +	return 0;
>> +}
>> +
>> +static struct reset_control_ops oxnas_reset_ops = {
> 
> const
> 
Something checkpatch should report...

>> +	.reset		= oxnas_reset_reset,
>> +	.assert		= oxnas_reset_assert,
>> +	.deassert	= oxnas_reset_deassert,
>> +};
>> +
>> +static const struct of_device_id oxnas_reset_dt_ids[] = {
>> +	 { .compatible = "plxtech,nas782x-reset", },
>> +	 { /* sentinel */ },
>> +};
>> +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
>> +
>> +static int oxnas_reset_probe(struct platform_device *pdev)
>> +{
>> +	struct oxnas_reset *data;
>> +	struct device *parent;
>> +
>> +	parent = pdev->dev.parent;
>> +	if (!parent) {
>> +		dev_err(&pdev->dev, "no parent\n");
> 
> Can this even happen?
> 
It's to make sure parent->of_node is valid for syscon_node_to_regmap.

>> +		return -ENODEV;
>> +	}
>> +
>> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
>> +	if (!data)
>> +		return -ENOMEM;
>> +
>> +	data->regmap = syscon_node_to_regmap(parent->of_node);
>> +	if (IS_ERR(data->regmap)) {
>> +		dev_err(&pdev->dev, "failed to get parent regmap\n");
>> +		return -ENODEV;
> 
> Better print the error code and return it.
> 
Good point.

>> +	}
>> +
>> +	data->rcdev.owner = THIS_MODULE;
>> +	data->rcdev.nr_resets = 32;
>> +	data->rcdev.ops = &oxnas_reset_ops;
>> +	data->rcdev.of_node = pdev->dev.of_node;
>> +	reset_controller_register(&data->rcdev);
> 
> Move this down a bit:
> 
>> +
>> +	platform_set_drvdata(pdev, data);
>> +
>> +	return 0;
> 
> and
> 	return reset_controller_register(&data->rcdev);
> here.
> 
Yes, sound better...

>> +static struct platform_driver oxnas_reset_driver = {
>> +	.probe	= oxnas_reset_probe,
>> +	.remove	= oxnas_reset_remove,
>> +	.driver = {
>> +		.name		= "oxnas-reset",
>> +		.owner		= THIS_MODULE,
> 
> The .owner field is overwritten by __platform_driver_register() anyway,
> just drop it.
OK

>> +/*
>> + * Reset controller does not support probe deferral, so it has to be
>> + * initialized before any user, in particular, PCIE uses subsys_initcall.
>> + */
>> +arch_initcall(oxnas_reset_init);
> 
> That doesn't sound right. (of_)reset_control_get return -EPROBE_DEFER if
> the rcdev isn't found in the list. Could you elaborate on this?
It was an old change, I will put back the generic module platform init.

> 
> regards
> Philipp
> 
Thanks,

Neil

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

* [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
@ 2016-03-03 14:29       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 03:18 PM, Philipp Zabel wrote:
> Hi Neil,
> 
>> +config RESET_OXNAS
>> +	bool
>> +	select MFD_SYSCON
> 
> I'd prefer not to select MFD_SYSCON here, but rather let ARCH_OXNAS do
> that.
> 
OK.

>> +#include <linux/io.h>
> 
> Is there any need to include linux/io.h ?

No, dropping.

>> +static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
>> +			      unsigned long id)
>> +{
>> +	struct oxnas_reset *data =
>> +		container_of(rcdev, struct oxnas_reset, rcdev);
>> +
>> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
>> +	msleep(50);
> 
> Is this the right delay for all of the resets in this register?
> If not, I'd drop the .reset callback.
> 
The delay is not strictly necessary, but better to avoid any HW issues.
And the .reset callback is needed since reset_control_reset
does not assert -> deassert as fallback.

>> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
>> +
>> +	return 0;
>> +}
>> +
>> +static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
>> +			      unsigned long id)
>> +{
>> +	struct oxnas_reset *data =
>> +		container_of(rcdev, struct oxnas_reset, rcdev);
>> +
>> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
>> +
>> +	return 0;
>> +}
>> +
>> +static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
>> +				unsigned long id)
>> +{
>> +	struct oxnas_reset *data =
>> +		container_of(rcdev, struct oxnas_reset, rcdev);
>> +
>> +	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
>> +
>> +	return 0;
>> +}
>> +
>> +static struct reset_control_ops oxnas_reset_ops = {
> 
> const
> 
Something checkpatch should report...

>> +	.reset		= oxnas_reset_reset,
>> +	.assert		= oxnas_reset_assert,
>> +	.deassert	= oxnas_reset_deassert,
>> +};
>> +
>> +static const struct of_device_id oxnas_reset_dt_ids[] = {
>> +	 { .compatible = "plxtech,nas782x-reset", },
>> +	 { /* sentinel */ },
>> +};
>> +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
>> +
>> +static int oxnas_reset_probe(struct platform_device *pdev)
>> +{
>> +	struct oxnas_reset *data;
>> +	struct device *parent;
>> +
>> +	parent = pdev->dev.parent;
>> +	if (!parent) {
>> +		dev_err(&pdev->dev, "no parent\n");
> 
> Can this even happen?
> 
It's to make sure parent->of_node is valid for syscon_node_to_regmap.

>> +		return -ENODEV;
>> +	}
>> +
>> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
>> +	if (!data)
>> +		return -ENOMEM;
>> +
>> +	data->regmap = syscon_node_to_regmap(parent->of_node);
>> +	if (IS_ERR(data->regmap)) {
>> +		dev_err(&pdev->dev, "failed to get parent regmap\n");
>> +		return -ENODEV;
> 
> Better print the error code and return it.
> 
Good point.

>> +	}
>> +
>> +	data->rcdev.owner = THIS_MODULE;
>> +	data->rcdev.nr_resets = 32;
>> +	data->rcdev.ops = &oxnas_reset_ops;
>> +	data->rcdev.of_node = pdev->dev.of_node;
>> +	reset_controller_register(&data->rcdev);
> 
> Move this down a bit:
> 
>> +
>> +	platform_set_drvdata(pdev, data);
>> +
>> +	return 0;
> 
> and
> 	return reset_controller_register(&data->rcdev);
> here.
> 
Yes, sound better...

>> +static struct platform_driver oxnas_reset_driver = {
>> +	.probe	= oxnas_reset_probe,
>> +	.remove	= oxnas_reset_remove,
>> +	.driver = {
>> +		.name		= "oxnas-reset",
>> +		.owner		= THIS_MODULE,
> 
> The .owner field is overwritten by __platform_driver_register() anyway,
> just drop it.
OK

>> +/*
>> + * Reset controller does not support probe deferral, so it has to be
>> + * initialized before any user, in particular, PCIE uses subsys_initcall.
>> + */
>> +arch_initcall(oxnas_reset_init);
> 
> That doesn't sound right. (of_)reset_control_get return -EPROBE_DEFER if
> the rcdev isn't found in the list. Could you elaborate on this?
It was an old change, I will put back the generic module platform init.

> 
> regards
> Philipp
> 
Thanks,

Neil

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

* Re: [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
  2016-03-03 14:24       ` Neil Armstrong
@ 2016-03-03 14:31         ` Philipp Zabel
  -1 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 14:31 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

Am Donnerstag, den 03.03.2016, 15:24 +0100 schrieb Neil Armstrong:
> On 03/03/2016 03:21 PM, Philipp Zabel wrote:
> > Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
> >> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > 
> > Is there a list of the reset bits in this register?
> > 
> > regards
> > Philipp
> > 
> 
> Yes, should I add it to the bindings ?

Yes, please. Either that or add a header file with #defines to
include/dt-bindings/reset and use it in the dtsi.

regards
Philipp

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

* [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-03 14:31         ` Philipp Zabel
  0 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 14:31 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, den 03.03.2016, 15:24 +0100 schrieb Neil Armstrong:
> On 03/03/2016 03:21 PM, Philipp Zabel wrote:
> > Am Donnerstag, den 03.03.2016, 12:40 +0100 schrieb Neil Armstrong:
> >> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > 
> > Is there a list of the reset bits in this register?
> > 
> > regards
> > Philipp
> > 
> 
> Yes, should I add it to the bindings ?

Yes, please. Either that or add a header file with #defines to
include/dt-bindings/reset and use it in the dtsi.

regards
Philipp

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

* Re: [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
  2016-03-03 11:39   ` Neil Armstrong
@ 2016-03-03 14:53     ` Andrew Lunn
  -1 siblings, 0 replies; 208+ messages in thread
From: Andrew Lunn @ 2016-03-03 14:53 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Thu, Mar 03, 2016 at 12:39:56PM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../bindings/interrupt-controller/plxtech,rps-irq.txt   | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
> new file mode 100644
> index 0000000..db117a0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt

...

> +- compatible: Should be "plxtech,nas782x-rps"

Hi Neil

It would be nice to be consistent with the naming.

Maybe also the filename of the driver itself should be changed. You
had an interesting sorting problem in the Makefile, which a consistent
name would help with.

     Andrew

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

* [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
@ 2016-03-03 14:53     ` Andrew Lunn
  0 siblings, 0 replies; 208+ messages in thread
From: Andrew Lunn @ 2016-03-03 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 12:39:56PM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../bindings/interrupt-controller/plxtech,rps-irq.txt   | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt
> new file mode 100644
> index 0000000..db117a0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/plxtech,rps-irq.txt

...

> +- compatible: Should be "plxtech,nas782x-rps"

Hi Neil

It would be nice to be consistent with the naming.

Maybe also the filename of the driver itself should be changed. You
had an interesting sorting problem in the Makefile, which a consistent
name would help with.

     Andrew

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

* Re: [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
  2016-03-03 14:53     ` Andrew Lunn
@ 2016-03-03 14:57       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:57 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: linux-kernel, linux-arm-kernel, devicetree

Hi Andrew,

On 03/03/2016 03:53 PM, Andrew Lunn wrote:
> 
>> +- compatible: Should be "plxtech,nas782x-rps"
> 
> Hi Neil
> 
> It would be nice to be consistent with the naming.
The compatible is now oxsemi,os810se-rps-irq which is consistent with the timer.

> 
> Maybe also the filename of the driver itself should be changed. You
> had an interesting sorting problem in the Makefile, which a consistent
> name would help with.
Yes, I will add -irq to the driver name and _IRQ to the config name.

> 
>      Andrew
> 
Thanks,
Neil

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

* [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
@ 2016-03-03 14:57       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 14:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Andrew,

On 03/03/2016 03:53 PM, Andrew Lunn wrote:
> 
>> +- compatible: Should be "plxtech,nas782x-rps"
> 
> Hi Neil
> 
> It would be nice to be consistent with the naming.
The compatible is now oxsemi,os810se-rps-irq which is consistent with the timer.

> 
> Maybe also the filename of the driver itself should be changed. You
> had an interesting sorting problem in the Makefile, which a consistent
> name would help with.
Yes, I will add -irq to the driver name and _IRQ to the config name.

> 
>      Andrew
> 
Thanks,
Neil

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

* Re: [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
  2016-03-03 14:29       ` Neil Armstrong
@ 2016-03-03 15:00         ` Philipp Zabel
  -1 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 15:00 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, Ma Haijun

Am Donnerstag, den 03.03.2016, 15:29 +0100 schrieb Neil Armstrong:
> >> +static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
> >> +			      unsigned long id)
> >> +{
> >> +	struct oxnas_reset *data =
> >> +		container_of(rcdev, struct oxnas_reset, rcdev);
> >> +
> >> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
> >> +	msleep(50);
> > 
> > Is this the right delay for all of the resets in this register?
> > If not, I'd drop the .reset callback.
> > 
> The delay is not strictly necessary, but better to avoid any HW issues.

Ok, maybe add a comment.

> And the .reset callback is needed since reset_control_reset
> does not assert -> deassert as fallback.

That's because some controllers don't even have manual
assertion/deassertion, and for some reset lines the drivers better know
the timing or they want to do other stuff while the reset is asserted.

[...]
> >> +static struct reset_control_ops oxnas_reset_ops = {
> > 
> > const
> > 
> Something checkpatch should report...

This is new in any case. rcdev->ops was not const* until recently.

> >> +	.reset		= oxnas_reset_reset,
> >> +	.assert		= oxnas_reset_assert,
> >> +	.deassert	= oxnas_reset_deassert,
> >> +};
> >> +
> >> +static const struct of_device_id oxnas_reset_dt_ids[] = {
> >> +	 { .compatible = "plxtech,nas782x-reset", },
> >> +	 { /* sentinel */ },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
> >> +
> >> +static int oxnas_reset_probe(struct platform_device *pdev)
> >> +{
> >> +	struct oxnas_reset *data;
> >> +	struct device *parent;
> >> +
> >> +	parent = pdev->dev.parent;
> >> +	if (!parent) {
> >> +		dev_err(&pdev->dev, "no parent\n");
> > 
> > Can this even happen?
> > 
> It's to make sure parent->of_node is valid for syscon_node_to_regmap.

Since this is a platform device probed via device tree,
pdev->dev.parent should always be set (see of_device_alloc()).

regards
Philipp

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

* [PATCH 06/17] reset: Add PLX Technology Reset Controller driver
@ 2016-03-03 15:00         ` Philipp Zabel
  0 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 15:00 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, den 03.03.2016, 15:29 +0100 schrieb Neil Armstrong:
> >> +static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
> >> +			      unsigned long id)
> >> +{
> >> +	struct oxnas_reset *data =
> >> +		container_of(rcdev, struct oxnas_reset, rcdev);
> >> +
> >> +	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
> >> +	msleep(50);
> > 
> > Is this the right delay for all of the resets in this register?
> > If not, I'd drop the .reset callback.
> > 
> The delay is not strictly necessary, but better to avoid any HW issues.

Ok, maybe add a comment.

> And the .reset callback is needed since reset_control_reset
> does not assert -> deassert as fallback.

That's because some controllers don't even have manual
assertion/deassertion, and for some reset lines the drivers better know
the timing or they want to do other stuff while the reset is asserted.

[...]
> >> +static struct reset_control_ops oxnas_reset_ops = {
> > 
> > const
> > 
> Something checkpatch should report...

This is new in any case. rcdev->ops was not const* until recently.

> >> +	.reset		= oxnas_reset_reset,
> >> +	.assert		= oxnas_reset_assert,
> >> +	.deassert	= oxnas_reset_deassert,
> >> +};
> >> +
> >> +static const struct of_device_id oxnas_reset_dt_ids[] = {
> >> +	 { .compatible = "plxtech,nas782x-reset", },
> >> +	 { /* sentinel */ },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
> >> +
> >> +static int oxnas_reset_probe(struct platform_device *pdev)
> >> +{
> >> +	struct oxnas_reset *data;
> >> +	struct device *parent;
> >> +
> >> +	parent = pdev->dev.parent;
> >> +	if (!parent) {
> >> +		dev_err(&pdev->dev, "no parent\n");
> > 
> > Can this even happen?
> > 
> It's to make sure parent->of_node is valid for syscon_node_to_regmap.

Since this is a platform device probed via device tree,
pdev->dev.parent should always be set (see of_device_alloc()).

regards
Philipp

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

* Re: [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
  2016-03-03 11:39   ` Neil Armstrong
@ 2016-03-03 15:02     ` Philipp Zabel
  -1 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 15:02 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> Add PLX Technology vendor prefix.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 72e2c5a..03970fb 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -178,6 +178,7 @@ picochip	Picochip Ltd
>  plathome	Plat'Home Co., Ltd.
>  plda	PLDA
>  pixcir  PIXCIR MICROELECTRONICS Co., Ltd
> +plxtech	PLX Technology, Inc.

The PLX Technology NASDAQ symbol used to be PLXT.
Personally, I prefer the more verbose name, just pointing out that
"plxt," might also be an option.

regards
Philipp

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

* [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-03 15:02     ` Philipp Zabel
  0 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-03 15:02 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> Add PLX Technology vendor prefix.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 72e2c5a..03970fb 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -178,6 +178,7 @@ picochip	Picochip Ltd
>  plathome	Plat'Home Co., Ltd.
>  plda	PLDA
>  pixcir  PIXCIR MICROELECTRONICS Co., Ltd
> +plxtech	PLX Technology, Inc.

The PLX Technology NASDAQ symbol used to be PLXT.
Personally, I prefer the more verbose name, just pointing out that
"plxt," might also be an option.

regards
Philipp

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

* Re: [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
@ 2016-03-03 15:06         ` Andrew Lunn
  0 siblings, 0 replies; 208+ messages in thread
From: Andrew Lunn @ 2016-03-03 15:06 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: devicetree, linux-kernel, linux-arm-kernel

On Thu, Mar 03, 2016 at 03:57:10PM +0100, Neil Armstrong wrote:
> Hi Andrew,
> 
> On 03/03/2016 03:53 PM, Andrew Lunn wrote:
> > 
> >> +- compatible: Should be "plxtech,nas782x-rps"
> > 
> > Hi Neil
> > 
> > It would be nice to be consistent with the naming.
> The compatible is now oxsemi,os810se-rps-irq which is consistent with the timer.

Ah, i had not read that far down the thread yet.

Thanks
	Andrew

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

* Re: [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
@ 2016-03-03 15:06         ` Andrew Lunn
  0 siblings, 0 replies; 208+ messages in thread
From: Andrew Lunn @ 2016-03-03 15:06 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Thu, Mar 03, 2016 at 03:57:10PM +0100, Neil Armstrong wrote:
> Hi Andrew,
> 
> On 03/03/2016 03:53 PM, Andrew Lunn wrote:
> > 
> >> +- compatible: Should be "plxtech,nas782x-rps"
> > 
> > Hi Neil
> > 
> > It would be nice to be consistent with the naming.
> The compatible is now oxsemi,os810se-rps-irq which is consistent with the timer.

Ah, i had not read that far down the thread yet.

Thanks
	Andrew
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings
@ 2016-03-03 15:06         ` Andrew Lunn
  0 siblings, 0 replies; 208+ messages in thread
From: Andrew Lunn @ 2016-03-03 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 03:57:10PM +0100, Neil Armstrong wrote:
> Hi Andrew,
> 
> On 03/03/2016 03:53 PM, Andrew Lunn wrote:
> > 
> >> +- compatible: Should be "plxtech,nas782x-rps"
> > 
> > Hi Neil
> > 
> > It would be nice to be consistent with the naming.
> The compatible is now oxsemi,os810se-rps-irq which is consistent with the timer.

Ah, i had not read that far down the thread yet.

Thanks
	Andrew

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

* RE: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 11:39   ` Neil Armstrong
@ 2016-03-03 15:32     ` Ma Haijun
  -1 siblings, 0 replies; 208+ messages in thread
From: Ma Haijun @ 2016-03-03 15:32 UTC (permalink / raw)
  To: 'Neil Armstrong',
	linux-kernel, linux-arm-kernel, tglx, jason, marc.zyngier

Hi Neil,

Glad to see the mainline efforts of this SoC family.

Previously, I did not really understand what this "RPS" stood for.
After some digging(1)., now I believe it means ARM's Reference Peripheral
Specification
though the spec itself seems not publicly available, the peripheral specs
are accessible.
The interrupt controller is an AMBA Interrupt Controller(2) and the timers
are
AMBA Timer(3). Besides, ARM Dual-Timer Module (SP804)(4) looks like an
extended version
of the AMBA timer

1)
http://infocenter.arm.com/help/topic/com.arm.doc.dai0030a/DAI0030A_sw_int_ap
psnote.pdf
2) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0047d/DDI0047.pdf
3) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0049c/AMBA_Timer.pdf
4) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf

Regards,
Haijun

-----Original Message-----
From: Neil Armstrong [mailto:narmstrong@baylibre.com] 
Subject: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller

Add PLX Technology RPS IRQ Controller as irqchip driver.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/irqchip/Kconfig   |   5 ++
 drivers/irqchip/Makefile  |   1 +
 drivers/irqchip/irq-rps.c | 128
++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 drivers/irqchip/irq-rps.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
fb50911..7892c1a 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -135,6 +135,11 @@ config PIC32_EVIC
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config PLXTECH_RPS
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+
 config RENESAS_INTC_IRQPIN
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index
18caacb..3eec3a0 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_I8259)			+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
+obj-$(CONFIG_PLXTECH_RPS)		+= irq-rps.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-rps.c b/drivers/irqchip/irq-rps.c new file
mode 100644 index 0000000..bcd4a31
--- /dev/null
+++ b/drivers/irqchip/irq-rps.c
@@ -0,0 +1,128 @@
+/*
+ * drivers/irqchip/irq-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify 
+it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but 
+WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public 
+License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/irqchip.h>
+
+#include <asm/exception.h>
+
+struct rps_chip_data {
+	void __iomem *base;
+	struct irq_domain *domain;
+} rps_data;
+
+enum {
+	RPS_IRQ_COUNT = 32,
+
+	RPS_STATUS = 0,
+	RPS_RAW_STATUS = 4,
+	RPS_UNMASK = 8,
+	RPS_MASK = 0xc,
+};
+
+/* Routines to acknowledge, disable and enable interrupts */ static 
+void rps_mask_irq(struct irq_data *d) {
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_MASK); }
+
+static void rps_unmask_irq(struct irq_data *d) {
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_UNMASK); }
+
+static void rps_ack_irq(struct irq_data *d) {
+	/* NOP */
+}
+
+static void __exception_irq_entry handle_irq(struct pt_regs *regs) {
+	u32 irqstat;
+	int hwirq;
+
+	irqstat = ioread32(rps_data.base + RPS_STATUS);
+	hwirq = __ffs(irqstat);
+
+	do {
+		handle_IRQ(irq_find_mapping(rps_data.domain, hwirq), regs);
+
+		irqstat = ioread32(rps_data.base + RPS_STATUS);
+		hwirq = __ffs(irqstat);
+	} while (irqstat);
+}
+
+int __init rps_of_init(struct device_node *node, struct device_node 
+*parent) {
+	int ret;
+	struct irq_chip_generic *gc;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	rps_data.base = of_iomap(node, 0);
+	WARN(!rps_data.base, "unable to map rps registers\n");
+
+	rps_data.domain = irq_domain_add_linear(node, RPS_IRQ_COUNT,
+						&irq_generic_chip_ops,
+						NULL);
+	if (!rps_data.domain) {
+		pr_err("%s: could add irq domain\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(rps_data.domain, RPS_IRQ_COUNT,
1,
+					     "RPS", handle_level_irq,
+					     0, 0, IRQ_GC_INIT_NESTED_LOCK);
+	if (ret) {
+		pr_err("%s: could not allocate generic chip\n",
+		       node->full_name);
+		irq_domain_remove(rps_data.domain);
+		return -EINVAL;
+	}
+
+	gc = irq_get_domain_generic_chip(rps_data.domain, 0);
+	gc->chip_types[0].chip.irq_ack = rps_ack_irq;
+	gc->chip_types[0].chip.irq_mask = rps_mask_irq;
+	gc->chip_types[0].chip.irq_unmask = rps_unmask_irq;
+
+	/* Disable all IRQs */
+	iowrite32(~0, rps_data.base + RPS_MASK);
+
+	set_handle_irq(handle_irq);
+
+	pr_info("Registered %d rps interrupts\n", RPS_IRQ_COUNT);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
--
1.9.1

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 15:32     ` Ma Haijun
  0 siblings, 0 replies; 208+ messages in thread
From: Ma Haijun @ 2016-03-03 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Neil,

Glad to see the mainline efforts of this SoC family.

Previously, I did not really understand what this "RPS" stood for.
After some digging(1)., now I believe it means ARM's Reference Peripheral
Specification
though the spec itself seems not publicly available, the peripheral specs
are accessible.
The interrupt controller is an AMBA Interrupt Controller(2) and the timers
are
AMBA Timer(3). Besides, ARM Dual-Timer Module (SP804)(4) looks like an
extended version
of the AMBA timer

1)
http://infocenter.arm.com/help/topic/com.arm.doc.dai0030a/DAI0030A_sw_int_ap
psnote.pdf
2) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0047d/DDI0047.pdf
3) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0049c/AMBA_Timer.pdf
4) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf

Regards,
Haijun

-----Original Message-----
From: Neil Armstrong [mailto:narmstrong at baylibre.com] 
Subject: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller

Add PLX Technology RPS IRQ Controller as irqchip driver.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/irqchip/Kconfig   |   5 ++
 drivers/irqchip/Makefile  |   1 +
 drivers/irqchip/irq-rps.c | 128
++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 drivers/irqchip/irq-rps.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
fb50911..7892c1a 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -135,6 +135,11 @@ config PIC32_EVIC
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config PLXTECH_RPS
+	bool
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+
 config RENESAS_INTC_IRQPIN
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index
18caacb..3eec3a0 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_I8259)			+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
+obj-$(CONFIG_PLXTECH_RPS)		+= irq-rps.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-rps.c b/drivers/irqchip/irq-rps.c new file
mode 100644 index 0000000..bcd4a31
--- /dev/null
+++ b/drivers/irqchip/irq-rps.c
@@ -0,0 +1,128 @@
+/*
+ * drivers/irqchip/irq-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify 
+it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but 
+WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public 
+License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/irqchip.h>
+
+#include <asm/exception.h>
+
+struct rps_chip_data {
+	void __iomem *base;
+	struct irq_domain *domain;
+} rps_data;
+
+enum {
+	RPS_IRQ_COUNT = 32,
+
+	RPS_STATUS = 0,
+	RPS_RAW_STATUS = 4,
+	RPS_UNMASK = 8,
+	RPS_MASK = 0xc,
+};
+
+/* Routines to acknowledge, disable and enable interrupts */ static 
+void rps_mask_irq(struct irq_data *d) {
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_MASK); }
+
+static void rps_unmask_irq(struct irq_data *d) {
+	u32 mask = BIT(d->hwirq);
+
+	iowrite32(mask, rps_data.base + RPS_UNMASK); }
+
+static void rps_ack_irq(struct irq_data *d) {
+	/* NOP */
+}
+
+static void __exception_irq_entry handle_irq(struct pt_regs *regs) {
+	u32 irqstat;
+	int hwirq;
+
+	irqstat = ioread32(rps_data.base + RPS_STATUS);
+	hwirq = __ffs(irqstat);
+
+	do {
+		handle_IRQ(irq_find_mapping(rps_data.domain, hwirq), regs);
+
+		irqstat = ioread32(rps_data.base + RPS_STATUS);
+		hwirq = __ffs(irqstat);
+	} while (irqstat);
+}
+
+int __init rps_of_init(struct device_node *node, struct device_node 
+*parent) {
+	int ret;
+	struct irq_chip_generic *gc;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	rps_data.base = of_iomap(node, 0);
+	WARN(!rps_data.base, "unable to map rps registers\n");
+
+	rps_data.domain = irq_domain_add_linear(node, RPS_IRQ_COUNT,
+						&irq_generic_chip_ops,
+						NULL);
+	if (!rps_data.domain) {
+		pr_err("%s: could add irq domain\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(rps_data.domain, RPS_IRQ_COUNT,
1,
+					     "RPS", handle_level_irq,
+					     0, 0, IRQ_GC_INIT_NESTED_LOCK);
+	if (ret) {
+		pr_err("%s: could not allocate generic chip\n",
+		       node->full_name);
+		irq_domain_remove(rps_data.domain);
+		return -EINVAL;
+	}
+
+	gc = irq_get_domain_generic_chip(rps_data.domain, 0);
+	gc->chip_types[0].chip.irq_ack = rps_ack_irq;
+	gc->chip_types[0].chip.irq_mask = rps_mask_irq;
+	gc->chip_types[0].chip.irq_unmask = rps_unmask_irq;
+
+	/* Disable all IRQs */
+	iowrite32(~0, rps_data.base + RPS_MASK);
+
+	set_handle_irq(handle_irq);
+
+	pr_info("Registered %d rps interrupts\n", RPS_IRQ_COUNT);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
--
1.9.1

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 15:32     ` Ma Haijun
@ 2016-03-03 16:56       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 16:56 UTC (permalink / raw)
  To: Ma Haijun, linux-kernel, linux-arm-kernel, tglx, jason, marc.zyngier

On 03/03/2016 04:32 PM, Ma Haijun wrote:
> Hi Neil,
> 
> Glad to see the mainline efforts of this SoC family.
> 
> Previously, I did not really understand what this "RPS" stood for.
> After some digging(1)., now I believe it means ARM's Reference Peripheral
> Specification
> though the spec itself seems not publicly available, the peripheral specs
> are accessible.
> The interrupt controller is an AMBA Interrupt Controller(2) and the timers
> are
> AMBA Timer(3). Besides, ARM Dual-Timer Module (SP804)(4) looks like an
> extended version
> of the AMBA timer
> 
> 1)
> http://infocenter.arm.com/help/topic/com.arm.doc.dai0030a/DAI0030A_sw_int_ap
> psnote.pdf
> 2) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0047d/DDI0047.pdf
> 3) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0049c/AMBA_Timer.pdf
> 4) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf
> 
> Regards,
> Haijun

Hi Haijun,

Thanks for the tips !

Indeed the timer looks like the timer-sp804 actually upstream, I'll try this driver before posting a v2.

Concerning the IRQ controller, I did not find any similar drivers.

Marc, Arnd, should I create a specific "arm RPS irq controller" instead ?

Neil

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 16:56       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-03 16:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 04:32 PM, Ma Haijun wrote:
> Hi Neil,
> 
> Glad to see the mainline efforts of this SoC family.
> 
> Previously, I did not really understand what this "RPS" stood for.
> After some digging(1)., now I believe it means ARM's Reference Peripheral
> Specification
> though the spec itself seems not publicly available, the peripheral specs
> are accessible.
> The interrupt controller is an AMBA Interrupt Controller(2) and the timers
> are
> AMBA Timer(3). Besides, ARM Dual-Timer Module (SP804)(4) looks like an
> extended version
> of the AMBA timer
> 
> 1)
> http://infocenter.arm.com/help/topic/com.arm.doc.dai0030a/DAI0030A_sw_int_ap
> psnote.pdf
> 2) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0047d/DDI0047.pdf
> 3) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0049c/AMBA_Timer.pdf
> 4) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf
> 
> Regards,
> Haijun

Hi Haijun,

Thanks for the tips !

Indeed the timer looks like the timer-sp804 actually upstream, I'll try this driver before posting a v2.

Concerning the IRQ controller, I did not find any similar drivers.

Marc, Arnd, should I create a specific "arm RPS irq controller" instead ?

Neil

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 16:56       ` Neil Armstrong
@ 2016-03-03 17:17         ` Marc Zyngier
  -1 siblings, 0 replies; 208+ messages in thread
From: Marc Zyngier @ 2016-03-03 17:17 UTC (permalink / raw)
  To: Neil Armstrong, Ma Haijun, linux-kernel, linux-arm-kernel, tglx, jason

On 03/03/16 16:56, Neil Armstrong wrote:
> On 03/03/2016 04:32 PM, Ma Haijun wrote:
>> Hi Neil,
>>
>> Glad to see the mainline efforts of this SoC family.
>>
>> Previously, I did not really understand what this "RPS" stood for.
>> After some digging(1)., now I believe it means ARM's Reference Peripheral
>> Specification
>> though the spec itself seems not publicly available, the peripheral specs
>> are accessible.
>> The interrupt controller is an AMBA Interrupt Controller(2) and the timers
>> are
>> AMBA Timer(3). Besides, ARM Dual-Timer Module (SP804)(4) looks like an
>> extended version
>> of the AMBA timer
>>
>> 1)
>> http://infocenter.arm.com/help/topic/com.arm.doc.dai0030a/DAI0030A_sw_int_ap
>> psnote.pdf
>> 2) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0047d/DDI0047.pdf
>> 3) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0049c/AMBA_Timer.pdf
>> 4) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf
>>
>> Regards,
>> Haijun
> 
> Hi Haijun,
> 
> Thanks for the tips !
> 
> Indeed the timer looks like the timer-sp804 actually upstream, I'll try this driver before posting a v2.
> 
> Concerning the IRQ controller, I did not find any similar drivers.
> 
> Marc, Arnd, should I create a specific "arm RPS irq controller" instead ?

Why not - I wonder which HW this controller got slapped on... It doesn't
even have a cryptic name! ;-)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 17:17         ` Marc Zyngier
  0 siblings, 0 replies; 208+ messages in thread
From: Marc Zyngier @ 2016-03-03 17:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/16 16:56, Neil Armstrong wrote:
> On 03/03/2016 04:32 PM, Ma Haijun wrote:
>> Hi Neil,
>>
>> Glad to see the mainline efforts of this SoC family.
>>
>> Previously, I did not really understand what this "RPS" stood for.
>> After some digging(1)., now I believe it means ARM's Reference Peripheral
>> Specification
>> though the spec itself seems not publicly available, the peripheral specs
>> are accessible.
>> The interrupt controller is an AMBA Interrupt Controller(2) and the timers
>> are
>> AMBA Timer(3). Besides, ARM Dual-Timer Module (SP804)(4) looks like an
>> extended version
>> of the AMBA timer
>>
>> 1)
>> http://infocenter.arm.com/help/topic/com.arm.doc.dai0030a/DAI0030A_sw_int_ap
>> psnote.pdf
>> 2) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0047d/DDI0047.pdf
>> 3) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0049c/AMBA_Timer.pdf
>> 4) http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf
>>
>> Regards,
>> Haijun
> 
> Hi Haijun,
> 
> Thanks for the tips !
> 
> Indeed the timer looks like the timer-sp804 actually upstream, I'll try this driver before posting a v2.
> 
> Concerning the IRQ controller, I did not find any similar drivers.
> 
> Marc, Arnd, should I create a specific "arm RPS irq controller" instead ?

Why not - I wonder which HW this controller got slapped on... It doesn't
even have a cryptic name! ;-)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 13:36         ` Russell King - ARM Linux
@ 2016-03-03 17:32           ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 17:32 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Russell King - ARM Linux, jason, Neil Armstrong, Marc Zyngier,
	linux-kernel, tglx, Ma Haijun

On Thursday 03 March 2016 13:36:49 Russell King - ARM Linux wrote:
> On Thu, Mar 03, 2016 at 02:08:19PM +0100, Arnd Bergmann wrote:
> > On Thursday 03 March 2016 13:01:13 Marc Zyngier wrote:
> > > > +/* Routines to acknowledge, disable and enable interrupts */
> > > > +static void rps_mask_irq(struct irq_data *d)
> > > > +{
> > > > +     u32 mask = BIT(d->hwirq);
> > > > +
> > > > +     iowrite32(mask, rps_data.base + RPS_MASK);
> > > 
> > > I do question the use of iowrite32 here (and its ioread32 pendent
> > > anywhere else), as it actually translates in a writel, which contains a
> > > memory barrier. Do you have any case that requires the use of such a
> > > barrier? if not, consider switching to relaxed accessors (which are the
> > > 
> > 
> > I really ask everyone to do the opposite: we have seen several drivers
> > blindlessly using the relaxed accessors and actually introducing bugs
> > that way, so I'd rather see the readl/writel ones used by default.
> 
> I actually agree with Marc - we have far too many drivers using the
> barriered IO accessors, which are really very expensive on 32-bit
> ARM.
> 
> For most ARM systems, the rules are quite simple: a write which causes
> DMA memory to be accessed by the device must be using the barriered
> IO accessor, and a read from a DMA status register must be too.
> Everything else need not be.  Barriered IO accessors are only about
> access ordering.

My main worry is really about code getting copied from drivers that
are fine with just relaxed accessors into other drivers by developers
that have never heard about the difference and just want to follow
best practices.

	Arnd

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-03 17:32           ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2016-03-03 17:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 03 March 2016 13:36:49 Russell King - ARM Linux wrote:
> On Thu, Mar 03, 2016 at 02:08:19PM +0100, Arnd Bergmann wrote:
> > On Thursday 03 March 2016 13:01:13 Marc Zyngier wrote:
> > > > +/* Routines to acknowledge, disable and enable interrupts */
> > > > +static void rps_mask_irq(struct irq_data *d)
> > > > +{
> > > > +     u32 mask = BIT(d->hwirq);
> > > > +
> > > > +     iowrite32(mask, rps_data.base + RPS_MASK);
> > > 
> > > I do question the use of iowrite32 here (and its ioread32 pendent
> > > anywhere else), as it actually translates in a writel, which contains a
> > > memory barrier. Do you have any case that requires the use of such a
> > > barrier? if not, consider switching to relaxed accessors (which are the
> > > 
> > 
> > I really ask everyone to do the opposite: we have seen several drivers
> > blindlessly using the relaxed accessors and actually introducing bugs
> > that way, so I'd rather see the readl/writel ones used by default.
> 
> I actually agree with Marc - we have far too many drivers using the
> barriered IO accessors, which are really very expensive on 32-bit
> ARM.
> 
> For most ARM systems, the rules are quite simple: a write which causes
> DMA memory to be accessed by the device must be using the barriered
> IO accessor, and a read from a DMA status register must be too.
> Everything else need not be.  Barriered IO accessors are only about
> access ordering.

My main worry is really about code getting copied from drivers that
are fine with just relaxed accessors into other drivers by developers
that have never heard about the difference and just want to follow
best practices.

	Arnd

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

* Re: [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
  2016-03-03 11:40   ` Neil Armstrong
@ 2016-03-04  2:25     ` Stephen Boyd
  -1 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2016-03-04  2:25 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, linux-clk

On 03/03, Neil Armstrong wrote:
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index eca8e01..b75ef5c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -192,6 +192,12 @@ config COMMON_CLK_PXA
>  	---help---
>  	  Sypport for the Marvell PXA SoC.
>  
> +config COMMON_CLK_OXNAS
> +	def_bool COMMON_CLK
> +	select MFD_SYSCON

So this is always built if I have the common clk framework
enabled? Not good.

> +	---help---
> +	  Sypport for the OXNAS SoC Family clocks.
> +
>  config COMMON_CLK_CDCE706
>  	tristate "Clock driver for TI CDCE706 clock synthesizer"
>  	depends on I2C
> diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
> new file mode 100644
> index 0000000..c4b903f
> --- /dev/null
> +++ b/drivers/clk/clk-oxnas.c
> @@ -0,0 +1,159 @@
> +/*
> + * Copyright (C) 2010 Broadcom
> + * Copyright (C) 2012 Stephen Warren
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>

Are either of these includes used?

> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/delay.h>

Is this include used?

> +#include <linux/stringify.h>
> +#include <linux/reset.h>

Is this include used?

> +#include <linux/io.h>

Is this include used?

> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>

#include <linux/kernel.h> for container_of?

> +
> +/* Standard regmap gate clocks */
> +struct clk_std {
> +	struct clk_hw hw;
> +	signed char bit;
> +	struct regmap *regmap;
> +};
> +
> +/* Regmap offsets */
> +#define CLK_STAT_REGOFFSET	0x24
> +#define CLK_SET_REGOFFSET	0x2c
> +#define CLK_CLR_REGOFFSET	0x30
> +
> +#define NUM_STD_CLKS 10
> +#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
> +
> +static int std_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct clk_std *std = to_stdclk(hw);
> +	int ret;
> +	unsigned int val;
> +
> +	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	return val & BIT(std->bit);
> +}
> +
> +static int std_clk_enable(struct clk_hw *hw)
> +{
> +	struct clk_std *std = to_stdclk(hw);
> +
> +	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));

I hope the regmap is fast_io? Otherwise this is scheduling while
atomic.

> +
> +	return 0;
> +}
> +
> +static void std_clk_disable(struct clk_hw *hw)
> +{
> +	struct clk_std *std = to_stdclk(hw);
> +
> +	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
> +}
> +
> +static struct clk_ops std_clk_ops = {

const?

> +	.enable = std_clk_enable,
> +	.disable = std_clk_disable,
> +	.is_enabled = std_clk_is_enabled,
> +};
> +
[..]
> +
> +static struct clk_hw *std_clk_hw_tbl[] = {

const?

> +	&clk_leon.hw,
> +	&clk_dma_sgdma.hw,
> +	&clk_cipher.hw,
> +	&clk_sata.hw,
> +	&clk_audio.hw,
> +	&clk_usbmph.hw,
> +	&clk_etha.hw,
> +	&clk_pciea.hw,
> +	&clk_nand.hw,
> +};
> +
> +static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
> +
> +static struct clk_onecell_data std_clk_data;

These are pretty generic. Perhaps oxnas_clk_data and
oxnas_clk_hw_tbl?

> +
> +static void __init oxnas_init_stdclk(struct device_node *np)
> +{
> +	int i;
> +	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
> +
> +	if (!regmap)
> +		panic("failed to have parent regmap\n");
> +
> +	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
> +		struct clk_std *std = container_of(std_clk_hw_tbl[i],
> +						   struct clk_std, hw);
> +
> +		if (WARN_ON(!std))
> +			return;
> +		std->regmap = regmap;
> +
> +		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
> +		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
> +			return;
> +	}
> +
> +	std_clk_data.clks = std_clk_tbl;
> +	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
> +
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
> +}
> +CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);

Can this be a platform driver instead?

Is there a binding for this compatible?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
@ 2016-03-04  2:25     ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2016-03-04  2:25 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03, Neil Armstrong wrote:
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index eca8e01..b75ef5c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -192,6 +192,12 @@ config COMMON_CLK_PXA
>  	---help---
>  	  Sypport for the Marvell PXA SoC.
>  
> +config COMMON_CLK_OXNAS
> +	def_bool COMMON_CLK
> +	select MFD_SYSCON

So this is always built if I have the common clk framework
enabled? Not good.

> +	---help---
> +	  Sypport for the OXNAS SoC Family clocks.
> +
>  config COMMON_CLK_CDCE706
>  	tristate "Clock driver for TI CDCE706 clock synthesizer"
>  	depends on I2C
> diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
> new file mode 100644
> index 0000000..c4b903f
> --- /dev/null
> +++ b/drivers/clk/clk-oxnas.c
> @@ -0,0 +1,159 @@
> +/*
> + * Copyright (C) 2010 Broadcom
> + * Copyright (C) 2012 Stephen Warren
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>

Are either of these includes used?

> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/delay.h>

Is this include used?

> +#include <linux/stringify.h>
> +#include <linux/reset.h>

Is this include used?

> +#include <linux/io.h>

Is this include used?

> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>

#include <linux/kernel.h> for container_of?

> +
> +/* Standard regmap gate clocks */
> +struct clk_std {
> +	struct clk_hw hw;
> +	signed char bit;
> +	struct regmap *regmap;
> +};
> +
> +/* Regmap offsets */
> +#define CLK_STAT_REGOFFSET	0x24
> +#define CLK_SET_REGOFFSET	0x2c
> +#define CLK_CLR_REGOFFSET	0x30
> +
> +#define NUM_STD_CLKS 10
> +#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
> +
> +static int std_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct clk_std *std = to_stdclk(hw);
> +	int ret;
> +	unsigned int val;
> +
> +	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	return val & BIT(std->bit);
> +}
> +
> +static int std_clk_enable(struct clk_hw *hw)
> +{
> +	struct clk_std *std = to_stdclk(hw);
> +
> +	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));

I hope the regmap is fast_io? Otherwise this is scheduling while
atomic.

> +
> +	return 0;
> +}
> +
> +static void std_clk_disable(struct clk_hw *hw)
> +{
> +	struct clk_std *std = to_stdclk(hw);
> +
> +	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
> +}
> +
> +static struct clk_ops std_clk_ops = {

const?

> +	.enable = std_clk_enable,
> +	.disable = std_clk_disable,
> +	.is_enabled = std_clk_is_enabled,
> +};
> +
[..]
> +
> +static struct clk_hw *std_clk_hw_tbl[] = {

const?

> +	&clk_leon.hw,
> +	&clk_dma_sgdma.hw,
> +	&clk_cipher.hw,
> +	&clk_sata.hw,
> +	&clk_audio.hw,
> +	&clk_usbmph.hw,
> +	&clk_etha.hw,
> +	&clk_pciea.hw,
> +	&clk_nand.hw,
> +};
> +
> +static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
> +
> +static struct clk_onecell_data std_clk_data;

These are pretty generic. Perhaps oxnas_clk_data and
oxnas_clk_hw_tbl?

> +
> +static void __init oxnas_init_stdclk(struct device_node *np)
> +{
> +	int i;
> +	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
> +
> +	if (!regmap)
> +		panic("failed to have parent regmap\n");
> +
> +	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
> +		struct clk_std *std = container_of(std_clk_hw_tbl[i],
> +						   struct clk_std, hw);
> +
> +		if (WARN_ON(!std))
> +			return;
> +		std->regmap = regmap;
> +
> +		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
> +		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
> +			return;
> +	}
> +
> +	std_clk_data.clks = std_clk_tbl;
> +	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
> +
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
> +}
> +CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);

Can this be a platform driver instead?

Is there a binding for this compatible?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
  2016-03-03 17:17         ` Marc Zyngier
@ 2016-03-04 11:10           ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-04 11:10 UTC (permalink / raw)
  To: Marc Zyngier, Ma Haijun, linux-kernel, linux-arm-kernel, tglx, jason

On 03/03/2016 06:17 PM, Marc Zyngier wrote:
> On 03/03/16 16:56, Neil Armstrong wrote:
>> On 03/03/2016 04:32 PM, Ma Haijun wrote:
>> Hi Haijun,
>>
>> Thanks for the tips !
>>
>> Indeed the timer looks like the timer-sp804 actually upstream, I'll try this driver before posting a v2.
>>
>> Concerning the IRQ controller, I did not find any similar drivers.
>>
>> Marc, Arnd, should I create a specific "arm RPS irq controller" instead ?
> 
> Why not - I wonder which HW this controller got slapped on... It doesn't
> even have a cryptic name! ;-)
> 
> Thanks,
> 
> 	M.
> 

Actually, it seems we already have an implementation in irq-versatile-fpga, it matches !

Adding a single "arm,rps-irq" compatible string should work.

Neil

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

* [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller
@ 2016-03-04 11:10           ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-04 11:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/03/2016 06:17 PM, Marc Zyngier wrote:
> On 03/03/16 16:56, Neil Armstrong wrote:
>> On 03/03/2016 04:32 PM, Ma Haijun wrote:
>> Hi Haijun,
>>
>> Thanks for the tips !
>>
>> Indeed the timer looks like the timer-sp804 actually upstream, I'll try this driver before posting a v2.
>>
>> Concerning the IRQ controller, I did not find any similar drivers.
>>
>> Marc, Arnd, should I create a specific "arm RPS irq controller" instead ?
> 
> Why not - I wonder which HW this controller got slapped on... It doesn't
> even have a cryptic name! ;-)
> 
> Thanks,
> 
> 	M.
> 

Actually, it seems we already have an implementation in irq-versatile-fpga, it matches !

Adding a single "arm,rps-irq" compatible string should work.

Neil

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

* Re: [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
  2016-03-03 15:02     ` Philipp Zabel
@ 2016-03-05  4:29       ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-05  4:29 UTC (permalink / raw)
  To: Philipp Zabel, Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Thu, Mar 03, 2016 at 04:02:15PM +0100, Philipp Zabel wrote:
> Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> > Add PLX Technology vendor prefix.
> > 
> > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > ---
> >  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > index 72e2c5a..03970fb 100644
> > --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> > +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > @@ -178,6 +178,7 @@ picochip	Picochip Ltd
> >  plathome	Plat'Home Co., Ltd.
> >  plda	PLDA
> >  pixcir  PIXCIR MICROELECTRONICS Co., Ltd
> > +plxtech	PLX Technology, Inc.
> 
> The PLX Technology NASDAQ symbol used to be PLXT.

And is no longer listed? If not, then plxtech is fine. Otherwise, use 
plxt.

Can you fix the alphabetizing while you are at it.

Rob

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

* [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-05  4:29       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-05  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 04:02:15PM +0100, Philipp Zabel wrote:
> Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> > Add PLX Technology vendor prefix.
> > 
> > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > ---
> >  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > index 72e2c5a..03970fb 100644
> > --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> > +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > @@ -178,6 +178,7 @@ picochip	Picochip Ltd
> >  plathome	Plat'Home Co., Ltd.
> >  plda	PLDA
> >  pixcir  PIXCIR MICROELECTRONICS Co., Ltd
> > +plxtech	PLX Technology, Inc.
> 
> The PLX Technology NASDAQ symbol used to be PLXT.

And is no longer listed? If not, then plxtech is fine. Otherwise, use 
plxt.

Can you fix the alphabetizing while you are at it.

Rob

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

* Re: [PATCH 16/17] dt-bindings: Add Western Digital to vendor prefixes
  2016-03-03 11:40   ` Neil Armstrong
@ 2016-03-05  4:29     ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-05  4:29 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Thu, Mar 03, 2016 at 12:40:09PM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Rob Herring <robh@kernel.org>

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

* [PATCH 16/17] dt-bindings: Add Western Digital to vendor prefixes
@ 2016-03-05  4:29     ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-05  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2016 at 12:40:09PM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
  2016-03-05  4:29       ` Rob Herring
@ 2016-03-07  9:55         ` Philipp Zabel
  -1 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-07  9:55 UTC (permalink / raw)
  To: Rob Herring; +Cc: Neil Armstrong, linux-kernel, linux-arm-kernel, devicetree

Am Freitag, den 04.03.2016, 22:29 -0600 schrieb Rob Herring:
> On Thu, Mar 03, 2016 at 04:02:15PM +0100, Philipp Zabel wrote:
> > Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> > > Add PLX Technology vendor prefix.
> > > 
> > > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > > ---
> > >  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> > >  1 file changed, 1 insertion(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > > index 72e2c5a..03970fb 100644
> > > --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> > > +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > > @@ -178,6 +178,7 @@ picochip	Picochip Ltd
> > >  plathome	Plat'Home Co., Ltd.
> > >  plda	PLDA
> > >  pixcir  PIXCIR MICROELECTRONICS Co., Ltd
> > > +plxtech	PLX Technology, Inc.
> > 
> > The PLX Technology NASDAQ symbol used to be PLXT.
> 
> And is no longer listed? If not, then plxtech is fine. Otherwise, use 
> plxt.

PLXT was listed until August 2014, when Avago (now Broadcom Limited)
acquired PLX Technology.

regards
Philipp

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

* [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-07  9:55         ` Philipp Zabel
  0 siblings, 0 replies; 208+ messages in thread
From: Philipp Zabel @ 2016-03-07  9:55 UTC (permalink / raw)
  To: linux-arm-kernel

Am Freitag, den 04.03.2016, 22:29 -0600 schrieb Rob Herring:
> On Thu, Mar 03, 2016 at 04:02:15PM +0100, Philipp Zabel wrote:
> > Am Donnerstag, den 03.03.2016, 12:39 +0100 schrieb Neil Armstrong:
> > > Add PLX Technology vendor prefix.
> > > 
> > > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > > ---
> > >  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> > >  1 file changed, 1 insertion(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > > index 72e2c5a..03970fb 100644
> > > --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> > > +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > > @@ -178,6 +178,7 @@ picochip	Picochip Ltd
> > >  plathome	Plat'Home Co., Ltd.
> > >  plda	PLDA
> > >  pixcir  PIXCIR MICROELECTRONICS Co., Ltd
> > > +plxtech	PLX Technology, Inc.
> > 
> > The PLX Technology NASDAQ symbol used to be PLXT.
> 
> And is no longer listed? If not, then plxtech is fine. Otherwise, use 
> plxt.

PLXT was listed until August 2014, when Avago (now Broadcom Limited)
acquired PLX Technology.

regards
Philipp

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

* Re: [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
  2016-03-04  2:25     ` Stephen Boyd
@ 2016-03-07 11:24       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-07 11:24 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: linux-kernel, linux-arm-kernel, linux-clk

On 03/04/2016 03:25 AM, Stephen Boyd wrote:
> On 03/03, Neil Armstrong wrote:
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index eca8e01..b75ef5c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -192,6 +192,12 @@ config COMMON_CLK_PXA
>>  	---help---
>>  	  Sypport for the Marvell PXA SoC.
>>  
>> +config COMMON_CLK_OXNAS
>> +	def_bool COMMON_CLK
>> +	select MFD_SYSCON
> 
> So this is always built if I have the common clk framework
> enabled? Not good.
Fixed.

>> +#include <linux/clk.h>
>> +#include <linux/clkdev.h>
> 
> Are either of these includes used?
> 
>> +#include <linux/clk-provider.h>
>> +#include <linux/of.h>
>> +#include <linux/delay.h>
> 
> Is this include used?
> 
>> +#include <linux/stringify.h>
>> +#include <linux/reset.h>
> 
> Is this include used?
> 
>> +#include <linux/io.h>
> 
> Is this include used?
> 
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
> 
> #include <linux/kernel.h> for container_of?

Fixed an cleaned up, thanks.


>> +static int std_clk_enable(struct clk_hw *hw)
>> +{
>> +	struct clk_std *std = to_stdclk(hw);
>> +
>> +	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
> 
> I hope the regmap is fast_io? Otherwise this is scheduling while
> atomic.
Yes, but due to the nature of the registers, I can't use the clk-regmap module.

>> +
>> +	return 0;
>> +}
>> +
>> +static void std_clk_disable(struct clk_hw *hw)
>> +{
>> +	struct clk_std *std = to_stdclk(hw);
>> +
>> +	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
>> +}
>> +
>> +static struct clk_ops std_clk_ops = {
> 
> const?
> 
>> +	.enable = std_clk_enable,
>> +	.disable = std_clk_disable,
>> +	.is_enabled = std_clk_is_enabled,
>> +};
>> +
> [..]
>> +
>> +static struct clk_hw *std_clk_hw_tbl[] = {
> 
> const?
> 
>> +	&clk_leon.hw,
>> +	&clk_dma_sgdma.hw,
>> +	&clk_cipher.hw,
>> +	&clk_sata.hw,
>> +	&clk_audio.hw,
>> +	&clk_usbmph.hw,
>> +	&clk_etha.hw,
>> +	&clk_pciea.hw,
>> +	&clk_nand.hw,
>> +};
>> +
>> +static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
>> +
>> +static struct clk_onecell_data std_clk_data;
> 
> These are pretty generic. Perhaps oxnas_clk_data and
> oxnas_clk_hw_tbl?
> 
>> +
>> +static void __init oxnas_init_stdclk(struct device_node *np)
>> +{
>> +	int i;
>> +	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
>> +
>> +	if (!regmap)
>> +		panic("failed to have parent regmap\n");
>> +
>> +	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
>> +		struct clk_std *std = container_of(std_clk_hw_tbl[i],
>> +						   struct clk_std, hw);
>> +
>> +		if (WARN_ON(!std))
>> +			return;
>> +		std->regmap = regmap;
>> +
>> +		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
>> +		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
>> +			return;
>> +	}
>> +
>> +	std_clk_data.clks = std_clk_tbl;
>> +	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
>> +
>> +	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
>> +}
>> +CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);
> 
> Can this be a platform driver instead?
> 
> Is there a binding for this compatible?

I refactored the driver to be platform driver and cleaned up the structure to be const and allocate the clocks at probe.

The bindings was in a separate patch, I forgot to CC linux-clk :
http://lkml.kernel.org/r/1457005210-18485-10-git-send-email-narmstrong@baylibre.com

In the meantime I added the indices description in the bindings.

Neil

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

* [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks
@ 2016-03-07 11:24       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-07 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/04/2016 03:25 AM, Stephen Boyd wrote:
> On 03/03, Neil Armstrong wrote:
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index eca8e01..b75ef5c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -192,6 +192,12 @@ config COMMON_CLK_PXA
>>  	---help---
>>  	  Sypport for the Marvell PXA SoC.
>>  
>> +config COMMON_CLK_OXNAS
>> +	def_bool COMMON_CLK
>> +	select MFD_SYSCON
> 
> So this is always built if I have the common clk framework
> enabled? Not good.
Fixed.

>> +#include <linux/clk.h>
>> +#include <linux/clkdev.h>
> 
> Are either of these includes used?
> 
>> +#include <linux/clk-provider.h>
>> +#include <linux/of.h>
>> +#include <linux/delay.h>
> 
> Is this include used?
> 
>> +#include <linux/stringify.h>
>> +#include <linux/reset.h>
> 
> Is this include used?
> 
>> +#include <linux/io.h>
> 
> Is this include used?
> 
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
> 
> #include <linux/kernel.h> for container_of?

Fixed an cleaned up, thanks.


>> +static int std_clk_enable(struct clk_hw *hw)
>> +{
>> +	struct clk_std *std = to_stdclk(hw);
>> +
>> +	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
> 
> I hope the regmap is fast_io? Otherwise this is scheduling while
> atomic.
Yes, but due to the nature of the registers, I can't use the clk-regmap module.

>> +
>> +	return 0;
>> +}
>> +
>> +static void std_clk_disable(struct clk_hw *hw)
>> +{
>> +	struct clk_std *std = to_stdclk(hw);
>> +
>> +	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
>> +}
>> +
>> +static struct clk_ops std_clk_ops = {
> 
> const?
> 
>> +	.enable = std_clk_enable,
>> +	.disable = std_clk_disable,
>> +	.is_enabled = std_clk_is_enabled,
>> +};
>> +
> [..]
>> +
>> +static struct clk_hw *std_clk_hw_tbl[] = {
> 
> const?
> 
>> +	&clk_leon.hw,
>> +	&clk_dma_sgdma.hw,
>> +	&clk_cipher.hw,
>> +	&clk_sata.hw,
>> +	&clk_audio.hw,
>> +	&clk_usbmph.hw,
>> +	&clk_etha.hw,
>> +	&clk_pciea.hw,
>> +	&clk_nand.hw,
>> +};
>> +
>> +static struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)];
>> +
>> +static struct clk_onecell_data std_clk_data;
> 
> These are pretty generic. Perhaps oxnas_clk_data and
> oxnas_clk_hw_tbl?
> 
>> +
>> +static void __init oxnas_init_stdclk(struct device_node *np)
>> +{
>> +	int i;
>> +	struct regmap *regmap = syscon_node_to_regmap(of_get_parent(np));
>> +
>> +	if (!regmap)
>> +		panic("failed to have parent regmap\n");
>> +
>> +	for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) {
>> +		struct clk_std *std = container_of(std_clk_hw_tbl[i],
>> +						   struct clk_std, hw);
>> +
>> +		if (WARN_ON(!std))
>> +			return;
>> +		std->regmap = regmap;
>> +
>> +		std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]);
>> +		if (WARN_ON(IS_ERR(std_clk_tbl[i])))
>> +			return;
>> +	}
>> +
>> +	std_clk_data.clks = std_clk_tbl;
>> +	std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl);
>> +
>> +	of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data);
>> +}
>> +CLK_OF_DECLARE(oxnas_pllstd, "plxtech,ox810se-stdclk", oxnas_init_stdclk);
> 
> Can this be a platform driver instead?
> 
> Is there a binding for this compatible?

I refactored the driver to be platform driver and cleaned up the structure to be const and allocate the clocks at probe.

The bindings was in a separate patch, I forgot to CC linux-clk :
http://lkml.kernel.org/r/1457005210-18485-10-git-send-email-narmstrong at baylibre.com

In the meantime I added the indices description in the bindings.

Neil

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

* [PATCH v2 00/18] Add Initial support for PLX Technology OX810SE
  2016-03-03 11:39 ` Neil Armstrong
@ 2016-03-09 10:24   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux; +Cc: Neil Armstrong

This serie adds initial support (IRQ, Timer, GPIO, Reset, Serial, Clocks) for
the PLX Technology OX810SE used in the well-known Western Digital My Book
World Edition Network Attached Storage device.

Extended support for SATA, DMA and Ethernet will come in further patches.

Upstream support for following devices like the OX820SE is welcome !

v2 changes :
- switch all compatible string to oxsemi,ox820se
- add oxsemi to prefixes
- switch to versatile-fpga interrupt controller with new compatible
- switch to sp804 timer with new timer width property
- cleanup of mach-oxnas (removal of generic oxnas.c)
- cleanup of standard clock to a platform driver

v1 : http://lkml.kernel.org/r/1457005210-18485-1-git-send-email-narmstrong@baylibre.com

Neil Armstrong (18):
  clocksource: sp804: Add support for non-32bit width counter
  dt-bindings: timer: sp804: add timer-width property
  irqchip: versatile-fpga: add new arm,rps-irq compatible
  dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible
    string
  dt-bindings: vendor-prefixes: Add PLX Technology
  dt-bindings: Add Oxford Semiconductors to vendor prefixes
  reset: Add PLX Technology Reset Controller driver
  dt-bindings: Add PLX Technology Reset Controller bindings
  clk: Add PLX Technology OXNAS Standard Clocks
  dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  arm: Add new mach-oxnas
  arm: Add build support for mach-oxnas
  arm: boot: dts: Add PLX Technology OX810SE dtsi
  dt-bindings: Add OXNAS bindings
  dt-bindings: Add Western Digital to vendor prefixes
  arm: boot: dts: Add Western Digital My Book World Edition device tree

 Documentation/devicetree/bindings/arm/oxnas.txt    |    9 +
 .../devicetree/bindings/clock/plxtech,stdclk.txt   |   35 +
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |   27 +
 .../arm,versatile-fpga-irq.txt                     |    2 +-
 .../bindings/pinctrl/plxtech,pinctrl.txt           |  100 ++
 .../devicetree/bindings/reset/plxtech,reset.txt    |   58 +
 .../devicetree/bindings/timer/arm,sp804.txt        |    2 +
 .../devicetree/bindings/vendor-prefixes.txt        |    5 +-
 arch/arm/Kconfig                                   |    2 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/boot/dts/Makefile                         |    2 +
 arch/arm/boot/dts/ox810se.dtsi                     |  273 ++++
 arch/arm/boot/dts/wd-mbwe.dts                      |  112 ++
 arch/arm/mach-oxnas/Kconfig                        |   25 +
 arch/arm/mach-oxnas/Makefile                       |    1 +
 drivers/clk/Kconfig                                |    6 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk-oxnas.c                            |  202 +++
 drivers/clocksource/timer-sp804.c                  |   38 +-
 drivers/irqchip/irq-versatile-fpga.c               |    1 +
 drivers/pinctrl/Kconfig                            |    9 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-oxnas.c                    | 1392 ++++++++++++++++++++
 drivers/reset/Kconfig                              |    3 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/reset-oxnas.c                        |  136 ++
 include/clocksource/timer-sp804.h                  |   11 +-
 27 files changed, 2437 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile
 create mode 100644 drivers/clk/clk-oxnas.c
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c
 create mode 100644 drivers/reset/reset-oxnas.c

-- 
1.9.1

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

* [PATCH v2 00/18] Add Initial support for PLX Technology OX810SE
@ 2016-03-09 10:24   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

This serie adds initial support (IRQ, Timer, GPIO, Reset, Serial, Clocks) for
the PLX Technology OX810SE used in the well-known Western Digital My Book
World Edition Network Attached Storage device.

Extended support for SATA, DMA and Ethernet will come in further patches.

Upstream support for following devices like the OX820SE is welcome !

v2 changes :
- switch all compatible string to oxsemi,ox820se
- add oxsemi to prefixes
- switch to versatile-fpga interrupt controller with new compatible
- switch to sp804 timer with new timer width property
- cleanup of mach-oxnas (removal of generic oxnas.c)
- cleanup of standard clock to a platform driver

v1 : http://lkml.kernel.org/r/1457005210-18485-1-git-send-email-narmstrong at baylibre.com

Neil Armstrong (18):
  clocksource: sp804: Add support for non-32bit width counter
  dt-bindings: timer: sp804: add timer-width property
  irqchip: versatile-fpga: add new arm,rps-irq compatible
  dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible
    string
  dt-bindings: vendor-prefixes: Add PLX Technology
  dt-bindings: Add Oxford Semiconductors to vendor prefixes
  reset: Add PLX Technology Reset Controller driver
  dt-bindings: Add PLX Technology Reset Controller bindings
  clk: Add PLX Technology OXNAS Standard Clocks
  dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  arm: Add new mach-oxnas
  arm: Add build support for mach-oxnas
  arm: boot: dts: Add PLX Technology OX810SE dtsi
  dt-bindings: Add OXNAS bindings
  dt-bindings: Add Western Digital to vendor prefixes
  arm: boot: dts: Add Western Digital My Book World Edition device tree

 Documentation/devicetree/bindings/arm/oxnas.txt    |    9 +
 .../devicetree/bindings/clock/plxtech,stdclk.txt   |   35 +
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |   27 +
 .../arm,versatile-fpga-irq.txt                     |    2 +-
 .../bindings/pinctrl/plxtech,pinctrl.txt           |  100 ++
 .../devicetree/bindings/reset/plxtech,reset.txt    |   58 +
 .../devicetree/bindings/timer/arm,sp804.txt        |    2 +
 .../devicetree/bindings/vendor-prefixes.txt        |    5 +-
 arch/arm/Kconfig                                   |    2 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/boot/dts/Makefile                         |    2 +
 arch/arm/boot/dts/ox810se.dtsi                     |  273 ++++
 arch/arm/boot/dts/wd-mbwe.dts                      |  112 ++
 arch/arm/mach-oxnas/Kconfig                        |   25 +
 arch/arm/mach-oxnas/Makefile                       |    1 +
 drivers/clk/Kconfig                                |    6 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk-oxnas.c                            |  202 +++
 drivers/clocksource/timer-sp804.c                  |   38 +-
 drivers/irqchip/irq-versatile-fpga.c               |    1 +
 drivers/pinctrl/Kconfig                            |    9 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-oxnas.c                    | 1392 ++++++++++++++++++++
 drivers/reset/Kconfig                              |    3 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/reset-oxnas.c                        |  136 ++
 include/clocksource/timer-sp804.h                  |   11 +-
 27 files changed, 2437 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile
 create mode 100644 drivers/clk/clk-oxnas.c
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c
 create mode 100644 drivers/reset/reset-oxnas.c

-- 
1.9.1

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

* [PATCH v2 01/18] clocksource: sp804: Add support for non-32bit width counter
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, daniel.lezcano, tglx, rmk+kernel,
	sudeep.holla
  Cc: Neil Armstrong

Some vendor variants can implement norrower counter width, add
an optional DT property changing the clocksource width and the
clockevent mask, but keeping 32bit as default for legacy interface.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clocksource/timer-sp804.c | 38 +++++++++++++++++++++++++++-----------
 include/clocksource/timer-sp804.h | 11 ++++++-----
 2 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 5f45b9a..8acf524 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -80,7 +80,8 @@ void __init sp804_timer_disable(void __iomem *base)
 void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 						     const char *name,
 						     struct clk *clk,
-						     int use_sched_clock)
+						     int use_sched_clock,
+						     unsigned width)
 {
 	long rate;
 
@@ -93,6 +94,9 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 		}
 	}
 
+	if (!width || width > 32)
+		width = 32;
+
 	rate = sp804_get_clock_rate(clk);
 
 	if (rate < 0)
@@ -106,11 +110,11 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 		base + TIMER_CTRL);
 
 	clocksource_mmio_init(base + TIMER_VALUE, name,
-		rate, 200, 32, clocksource_mmio_readl_down);
+		rate, 200, width, clocksource_mmio_readl_down);
 
 	if (use_sched_clock) {
 		sched_clock_base = base;
-		sched_clock_register(sp804_read, 32, rate);
+		sched_clock_register(sp804_read, width, rate);
 	}
 }
 
@@ -186,7 +190,9 @@ static struct irqaction sp804_timer_irq = {
 	.dev_id		= &sp804_clockevent,
 };
 
-void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
+void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq,
+				     struct clk *clk, const char *name,
+				     unsigned width)
 {
 	struct clock_event_device *evt = &sp804_clockevent;
 	long rate;
@@ -199,6 +205,9 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
 		return;
 	}
 
+	if (!width || width > 32)
+		width = 32;
+
 	rate = sp804_get_clock_rate(clk);
 	if (rate < 0)
 		return;
@@ -212,7 +221,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
 	writel(0, base + TIMER_CTRL);
 
 	setup_irq(irq, &sp804_timer_irq);
-	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
+	clockevents_config_and_register(evt, rate, 0xf, GENMASK(width-1, 0));
 }
 
 static void __init sp804_of_init(struct device_node *np)
@@ -223,6 +232,7 @@ static void __init sp804_of_init(struct device_node *np)
 	u32 irq_num = 0;
 	struct clk *clk1, *clk2;
 	const char *name = of_get_property(np, "compatible", NULL);
+	u32 width = 32;
 
 	base = of_iomap(np, 0);
 	if (WARN_ON(!base))
@@ -254,14 +264,19 @@ static void __init sp804_of_init(struct device_node *np)
 	if (irq <= 0)
 		goto err;
 
+	/* Some vendor variants can have a different counter width */
+	of_property_read_u32(np, "arm,timer-width", &width);
+
 	of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
 	if (irq_num == 2) {
-		__sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
-		__sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
+		__sp804_clockevents_init(base + TIMER_2_BASE, irq,
+					 clk2, name, width);
+		__sp804_clocksource_and_sched_clock_init(base, name,
+							 clk1, 1, width);
 	} else {
-		__sp804_clockevents_init(base, irq, clk1 , name);
+		__sp804_clockevents_init(base, irq, clk1, name, width);
 		__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
-							 name, clk2, 1);
+							 name, clk2, 1, width);
 	}
 	initialized = true;
 
@@ -293,13 +308,14 @@ static void __init integrator_cp_of_init(struct device_node *np)
 		goto err;
 
 	if (!init_count)
-		__sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
+		__sp804_clocksource_and_sched_clock_init(base, name,
+							 clk, 0, 32);
 	else {
 		irq = irq_of_parse_and_map(np, 0);
 		if (irq <= 0)
 			goto err;
 
-		__sp804_clockevents_init(base, irq, clk, name);
+		__sp804_clockevents_init(base, irq, clk, name, 32);
 	}
 
 	init_count++;
diff --git a/include/clocksource/timer-sp804.h b/include/clocksource/timer-sp804.h
index 1f8a1ca..ad71fcb 100644
--- a/include/clocksource/timer-sp804.h
+++ b/include/clocksource/timer-sp804.h
@@ -4,25 +4,26 @@
 struct clk;
 
 void __sp804_clocksource_and_sched_clock_init(void __iomem *,
-					      const char *, struct clk *, int);
+					      const char *, struct clk *,
+					      int, unsigned);
 void __sp804_clockevents_init(void __iomem *, unsigned int,
-			      struct clk *, const char *);
+			      struct clk *, const char *, unsigned);
 void sp804_timer_disable(void __iomem *);
 
 static inline void sp804_clocksource_init(void __iomem *base, const char *name)
 {
-	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0);
+	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0, 32);
 }
 
 static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
 							  const char *name)
 {
-	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1);
+	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1, 32);
 }
 
 static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name)
 {
-	__sp804_clockevents_init(base, irq, NULL, name);
+	__sp804_clockevents_init(base, irq, NULL, name, 32);
 
 }
 #endif
-- 
1.9.1

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

* [PATCH v2 01/18] clocksource: sp804: Add support for non-32bit width counter
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Some vendor variants can implement norrower counter width, add
an optional DT property changing the clocksource width and the
clockevent mask, but keeping 32bit as default for legacy interface.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clocksource/timer-sp804.c | 38 +++++++++++++++++++++++++++-----------
 include/clocksource/timer-sp804.h | 11 ++++++-----
 2 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 5f45b9a..8acf524 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -80,7 +80,8 @@ void __init sp804_timer_disable(void __iomem *base)
 void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 						     const char *name,
 						     struct clk *clk,
-						     int use_sched_clock)
+						     int use_sched_clock,
+						     unsigned width)
 {
 	long rate;
 
@@ -93,6 +94,9 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 		}
 	}
 
+	if (!width || width > 32)
+		width = 32;
+
 	rate = sp804_get_clock_rate(clk);
 
 	if (rate < 0)
@@ -106,11 +110,11 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 		base + TIMER_CTRL);
 
 	clocksource_mmio_init(base + TIMER_VALUE, name,
-		rate, 200, 32, clocksource_mmio_readl_down);
+		rate, 200, width, clocksource_mmio_readl_down);
 
 	if (use_sched_clock) {
 		sched_clock_base = base;
-		sched_clock_register(sp804_read, 32, rate);
+		sched_clock_register(sp804_read, width, rate);
 	}
 }
 
@@ -186,7 +190,9 @@ static struct irqaction sp804_timer_irq = {
 	.dev_id		= &sp804_clockevent,
 };
 
-void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
+void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq,
+				     struct clk *clk, const char *name,
+				     unsigned width)
 {
 	struct clock_event_device *evt = &sp804_clockevent;
 	long rate;
@@ -199,6 +205,9 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
 		return;
 	}
 
+	if (!width || width > 32)
+		width = 32;
+
 	rate = sp804_get_clock_rate(clk);
 	if (rate < 0)
 		return;
@@ -212,7 +221,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
 	writel(0, base + TIMER_CTRL);
 
 	setup_irq(irq, &sp804_timer_irq);
-	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
+	clockevents_config_and_register(evt, rate, 0xf, GENMASK(width-1, 0));
 }
 
 static void __init sp804_of_init(struct device_node *np)
@@ -223,6 +232,7 @@ static void __init sp804_of_init(struct device_node *np)
 	u32 irq_num = 0;
 	struct clk *clk1, *clk2;
 	const char *name = of_get_property(np, "compatible", NULL);
+	u32 width = 32;
 
 	base = of_iomap(np, 0);
 	if (WARN_ON(!base))
@@ -254,14 +264,19 @@ static void __init sp804_of_init(struct device_node *np)
 	if (irq <= 0)
 		goto err;
 
+	/* Some vendor variants can have a different counter width */
+	of_property_read_u32(np, "arm,timer-width", &width);
+
 	of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
 	if (irq_num == 2) {
-		__sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
-		__sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
+		__sp804_clockevents_init(base + TIMER_2_BASE, irq,
+					 clk2, name, width);
+		__sp804_clocksource_and_sched_clock_init(base, name,
+							 clk1, 1, width);
 	} else {
-		__sp804_clockevents_init(base, irq, clk1 , name);
+		__sp804_clockevents_init(base, irq, clk1, name, width);
 		__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
-							 name, clk2, 1);
+							 name, clk2, 1, width);
 	}
 	initialized = true;
 
@@ -293,13 +308,14 @@ static void __init integrator_cp_of_init(struct device_node *np)
 		goto err;
 
 	if (!init_count)
-		__sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
+		__sp804_clocksource_and_sched_clock_init(base, name,
+							 clk, 0, 32);
 	else {
 		irq = irq_of_parse_and_map(np, 0);
 		if (irq <= 0)
 			goto err;
 
-		__sp804_clockevents_init(base, irq, clk, name);
+		__sp804_clockevents_init(base, irq, clk, name, 32);
 	}
 
 	init_count++;
diff --git a/include/clocksource/timer-sp804.h b/include/clocksource/timer-sp804.h
index 1f8a1ca..ad71fcb 100644
--- a/include/clocksource/timer-sp804.h
+++ b/include/clocksource/timer-sp804.h
@@ -4,25 +4,26 @@
 struct clk;
 
 void __sp804_clocksource_and_sched_clock_init(void __iomem *,
-					      const char *, struct clk *, int);
+					      const char *, struct clk *,
+					      int, unsigned);
 void __sp804_clockevents_init(void __iomem *, unsigned int,
-			      struct clk *, const char *);
+			      struct clk *, const char *, unsigned);
 void sp804_timer_disable(void __iomem *);
 
 static inline void sp804_clocksource_init(void __iomem *base, const char *name)
 {
-	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0);
+	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0, 32);
 }
 
 static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
 							  const char *name)
 {
-	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1);
+	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1, 32);
 }
 
 static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name)
 {
-	__sp804_clockevents_init(base, irq, NULL, name);
+	__sp804_clockevents_init(base, irq, NULL, name, 32);
 
 }
 #endif
-- 
1.9.1

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, daniel.lezcano, tglx, rmk+kernel,
	sudeep.holla, devicetree
  Cc: Neil Armstrong

Add timer-width optional property to specify a different vendor
specific timer counter bit-width.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
index 5cd8eee7..141e143 100644
--- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
+++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
@@ -17,6 +17,8 @@ Optional properties:
 - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
 	specifies if the irq connection is for timer 1 or timer 2. A value of 1
 	or 2 should be used.
+- arm,timer-width: Should contain the width in number of bits of the counter,
+	is considered by default 32 but can be changed for vendor variants.
 
 Example:
 
-- 
1.9.1

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add timer-width optional property to specify a different vendor
specific timer counter bit-width.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
index 5cd8eee7..141e143 100644
--- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
+++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
@@ -17,6 +17,8 @@ Optional properties:
 - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
 	specifies if the irq connection is for timer 1 or timer 2. A value of 1
 	or 2 should be used.
+- arm,timer-width: Should contain the width in number of bits of the counter,
+	is considered by default 32 but can be changed for vendor variants.
 
 Example:
 
-- 
1.9.1

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

* [PATCH v2 03/18] irqchip: versatile-fpga: add new arm,rps-irq compatible
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, tglx, jason, marc.zyngier; +Cc: Neil Armstrong

Under the OX810SE, this exact same interface is used as "Reference Peripheral
Specification" Interrupt Controller, so add a new compatible string.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/irqchip/irq-versatile-fpga.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 598ab3f..389b8e2 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -227,4 +227,5 @@ int __init fpga_irq_of_init(struct device_node *node,
 }
 IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
 IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
+IRQCHIP_DECLARE(arm_rps, "arm,rps-irq", fpga_irq_of_init);
 #endif
-- 
1.9.1

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

* [PATCH v2 03/18] irqchip: versatile-fpga: add new arm, rps-irq compatible
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Under the OX810SE, this exact same interface is used as "Reference Peripheral
Specification" Interrupt Controller, so add a new compatible string.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/irqchip/irq-versatile-fpga.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 598ab3f..389b8e2 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -227,4 +227,5 @@ int __init fpga_irq_of_init(struct device_node *node,
 }
 IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
 IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
+IRQCHIP_DECLARE(arm_rps, "arm,rps-irq", fpga_irq_of_init);
 #endif
-- 
1.9.1

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

* [PATCH v2 04/18] dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible string
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, tglx, jason, marc.zyngier, devicetree
  Cc: Neil Armstrong

Under the OX810SE, this same controller is used as "Reference Peripheral
Specification" Interrupt Controller, so add new compatible string.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
index c9cf605..2fe78d5 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
@@ -6,7 +6,7 @@ controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
 instance can handle up to 32 interrupts.
 
 Required properties:
-- compatible: "arm,versatile-fpga-irq"
+- compatible: "arm,versatile-fpga-irq" or "arm,rps-irq"
 - interrupt-controller: Identifies the node as an interrupt controller
 - #interrupt-cells: The number of cells to define the interrupts.  Must be 1
   as the FPGA IRQ controller has no configuration options for interrupt
-- 
1.9.1

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

* [PATCH v2 04/18] dt-bindings: irq: arm, versatile-fpga: add arm, rps-irq compatible string
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Under the OX810SE, this same controller is used as "Reference Peripheral
Specification" Interrupt Controller, so add new compatible string.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
index c9cf605..2fe78d5 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
@@ -6,7 +6,7 @@ controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
 instance can handle up to 32 interrupts.
 
 Required properties:
-- compatible: "arm,versatile-fpga-irq"
+- compatible: "arm,versatile-fpga-irq" or "arm,rps-irq"
 - interrupt-controller: Identifies the node as an interrupt controller
 - #interrupt-cells: The number of cells to define the interrupts.  Must be 1
   as the FPGA IRQ controller has no configuration options for interrupt
-- 
1.9.1

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

* [PATCH v2 05/18] dt-bindings: vendor-prefixes: Add PLX Technology
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Add PLX Technology vendor prefix.
Fixed "pixdir" alphabetizing.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 72e2c5a..8c084c1 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -175,9 +175,10 @@ parade	Parade Technologies Inc.
 pericom	Pericom Technology Inc.
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
+pixcir  PIXCIR MICROELECTRONICS Co., Ltd
 plathome	Plat'Home Co., Ltd.
 plda	PLDA
-pixcir  PIXCIR MICROELECTRONICS Co., Ltd
+plxtech	PLX Technology, Inc.
 pulsedlight	PulsedLight, Inc
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
-- 
1.9.1

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

* [PATCH v2 05/18] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add PLX Technology vendor prefix.
Fixed "pixdir" alphabetizing.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 72e2c5a..8c084c1 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -175,9 +175,10 @@ parade	Parade Technologies Inc.
 pericom	Pericom Technology Inc.
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
+pixcir  PIXCIR MICROELECTRONICS Co., Ltd
 plathome	Plat'Home Co., Ltd.
 plda	PLDA
-pixcir  PIXCIR MICROELECTRONICS Co., Ltd
+plxtech	PLX Technology, Inc.
 pulsedlight	PulsedLight, Inc
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
-- 
1.9.1

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

* [PATCH v2 06/18] dt-bindings: Add Oxford Semiconductors to vendor prefixes
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 8c084c1..188671f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -170,6 +170,7 @@ opencores	OpenCores.org
 option	Option NV
 ortustech	Ortus Technology Co., Ltd.
 ovti	OmniVision Technologies
+oxsemi	Oxford Semiconductors, Ltd.
 panasonic	Panasonic Corporation
 parade	Parade Technologies Inc.
 pericom	Pericom Technology Inc.
-- 
1.9.1

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

* [PATCH v2 06/18] dt-bindings: Add Oxford Semiconductors to vendor prefixes
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 8c084c1..188671f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -170,6 +170,7 @@ opencores	OpenCores.org
 option	Option NV
 ortustech	Ortus Technology Co., Ltd.
 ovti	OmniVision Technologies
+oxsemi	Oxford Semiconductors, Ltd.
 panasonic	Panasonic Corporation
 parade	Parade Technologies Inc.
 pericom	Pericom Technology Inc.
-- 
1.9.1

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

* [PATCH v2 07/18] reset: Add PLX Technology Reset Controller driver
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, p.zabel; +Cc: Neil Armstrong, Ma Haijun

Add System reset controller driver for PLX Technology OXNAS SoC Family.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/reset/Kconfig       |   3 +
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-oxnas.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+)
 create mode 100644 drivers/reset/reset-oxnas.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..0b2733d 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+config RESET_OXNAS
+	bool
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 4d7178e..97e04c5 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
 obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
new file mode 100644
index 0000000..9cce026
--- /dev/null
+++ b/drivers/reset/reset-oxnas.c
@@ -0,0 +1,136 @@
+/*
+ * drivers/reset/reset-oxnas.c
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Regmap offsets */
+#define RST_SET_REGOFFSET	0x34
+#define RST_CLR_REGOFFSET	0x38
+
+struct oxnas_reset {
+	struct regmap *regmap;
+	struct reset_controller_dev rcdev;
+};
+
+static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+	msleep(50);
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static const struct reset_control_ops oxnas_reset_ops = {
+	.reset		= oxnas_reset_reset,
+	.assert		= oxnas_reset_assert,
+	.deassert	= oxnas_reset_deassert,
+};
+
+static const struct of_device_id oxnas_reset_dt_ids[] = {
+	 { .compatible = "oxsemi,ox810se-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
+
+static int oxnas_reset_probe(struct platform_device *pdev)
+{
+	struct oxnas_reset *data;
+	struct device *parent;
+
+	parent = pdev->dev.parent;
+	if (!parent) {
+		dev_err(&pdev->dev, "no parent\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->regmap = syscon_node_to_regmap(parent->of_node);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&pdev->dev, "failed to get parent regmap\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	platform_set_drvdata(pdev, data);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = 32;
+	data->rcdev.ops = &oxnas_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return reset_controller_register(&data->rcdev);
+}
+
+static int oxnas_reset_remove(struct platform_device *pdev)
+{
+	struct oxnas_reset *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+
+	return 0;
+}
+
+static struct platform_driver oxnas_reset_driver = {
+	.probe	= oxnas_reset_probe,
+	.remove	= oxnas_reset_remove,
+	.driver = {
+		.name		= "oxnas-reset",
+		.of_match_table	= oxnas_reset_dt_ids,
+	},
+};
+
+module_platform_driver(oxnas_reset_driver);
-- 
1.9.1

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

* [PATCH v2 07/18] reset: Add PLX Technology Reset Controller driver
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add System reset controller driver for PLX Technology OXNAS SoC Family.

CC: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/reset/Kconfig       |   3 +
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-oxnas.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+)
 create mode 100644 drivers/reset/reset-oxnas.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..0b2733d 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,8 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+config RESET_OXNAS
+	bool
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 4d7178e..97e04c5 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
 obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
new file mode 100644
index 0000000..9cce026
--- /dev/null
+++ b/drivers/reset/reset-oxnas.c
@@ -0,0 +1,136 @@
+/*
+ * drivers/reset/reset-oxnas.c
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Regmap offsets */
+#define RST_SET_REGOFFSET	0x34
+#define RST_CLR_REGOFFSET	0x38
+
+struct oxnas_reset {
+	struct regmap *regmap;
+	struct reset_controller_dev rcdev;
+};
+
+static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+	msleep(50);
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct oxnas_reset *data =
+		container_of(rcdev, struct oxnas_reset, rcdev);
+
+	regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
+
+	return 0;
+}
+
+static const struct reset_control_ops oxnas_reset_ops = {
+	.reset		= oxnas_reset_reset,
+	.assert		= oxnas_reset_assert,
+	.deassert	= oxnas_reset_deassert,
+};
+
+static const struct of_device_id oxnas_reset_dt_ids[] = {
+	 { .compatible = "oxsemi,ox810se-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
+
+static int oxnas_reset_probe(struct platform_device *pdev)
+{
+	struct oxnas_reset *data;
+	struct device *parent;
+
+	parent = pdev->dev.parent;
+	if (!parent) {
+		dev_err(&pdev->dev, "no parent\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->regmap = syscon_node_to_regmap(parent->of_node);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&pdev->dev, "failed to get parent regmap\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	platform_set_drvdata(pdev, data);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = 32;
+	data->rcdev.ops = &oxnas_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return reset_controller_register(&data->rcdev);
+}
+
+static int oxnas_reset_remove(struct platform_device *pdev)
+{
+	struct oxnas_reset *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+
+	return 0;
+}
+
+static struct platform_driver oxnas_reset_driver = {
+	.probe	= oxnas_reset_probe,
+	.remove	= oxnas_reset_remove,
+	.driver = {
+		.name		= "oxnas-reset",
+		.of_match_table	= oxnas_reset_dt_ids,
+	},
+};
+
+module_platform_driver(oxnas_reset_driver);
-- 
1.9.1

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

* [PATCH v2 08/18] dt-bindings: Add PLX Technology Reset Controller bindings
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, p.zabel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/reset/plxtech,reset.txt    | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

diff --git a/Documentation/devicetree/bindings/reset/plxtech,reset.txt b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
new file mode 100644
index 0000000..581c974
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
@@ -0,0 +1,58 @@
+PLX Technology OXNAS SoC Family RESET Controller
+================================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-reset"
+- #reset-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+For OX810SE, the indices are :
+ - 0 : ARM
+ - 1 : COPRO
+ - 2 : Reserved
+ - 3 : Reserved
+ - 4 : USBHS
+ - 5 : USBHSPHY
+ - 6 : MAC
+ - 7 : PCI
+ - 8 : DMA
+ - 9 : DPE
+ - 10 : DDR
+ - 11 : SATA
+ - 12 : SATA_LINK
+ - 13 : SATA_PHY
+ - 14 : Reserved
+ - 15 : NAND
+ - 16 : GPIO
+ - 17 : UART1
+ - 18 : UART2
+ - 19 : MISC
+ - 20 : I2S
+ - 21 : AHB_MON
+ - 22 : UART3
+ - 23 : UART4
+ - 24 : SGDMA
+ - 25 : Reserved
+ - 26 : Reserved
+ - 27 : Reserved
+ - 28 : Reserved
+ - 29 : Reserved
+ - 30 : Reserved
+ - 31 : BUS
+
+example:
+
+sys: sys-ctrl@000000 {
+	compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	reset: reset-controller {
+		compatible = "oxsemi,ox810se-reset";
+		#reset-cells = <1>;
+	};
+};
-- 
1.9.1

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

* [PATCH v2 08/18] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/reset/plxtech,reset.txt    | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

diff --git a/Documentation/devicetree/bindings/reset/plxtech,reset.txt b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
new file mode 100644
index 0000000..581c974
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/plxtech,reset.txt
@@ -0,0 +1,58 @@
+PLX Technology OXNAS SoC Family RESET Controller
+================================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-reset"
+- #reset-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+For OX810SE, the indices are :
+ - 0 : ARM
+ - 1 : COPRO
+ - 2 : Reserved
+ - 3 : Reserved
+ - 4 : USBHS
+ - 5 : USBHSPHY
+ - 6 : MAC
+ - 7 : PCI
+ - 8 : DMA
+ - 9 : DPE
+ - 10 : DDR
+ - 11 : SATA
+ - 12 : SATA_LINK
+ - 13 : SATA_PHY
+ - 14 : Reserved
+ - 15 : NAND
+ - 16 : GPIO
+ - 17 : UART1
+ - 18 : UART2
+ - 19 : MISC
+ - 20 : I2S
+ - 21 : AHB_MON
+ - 22 : UART3
+ - 23 : UART4
+ - 24 : SGDMA
+ - 25 : Reserved
+ - 26 : Reserved
+ - 27 : Reserved
+ - 28 : Reserved
+ - 29 : Reserved
+ - 30 : Reserved
+ - 31 : BUS
+
+example:
+
+sys: sys-ctrl at 000000 {
+	compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	reset: reset-controller {
+		compatible = "oxsemi,ox810se-reset";
+		#reset-cells = <1>;
+	};
+};
-- 
1.9.1

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

* [PATCH v2 09/18] clk: Add PLX Technology OXNAS Standard Clocks
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-clk; +Cc: Neil Armstrong

Add PLX Technology OXNAS SoC Family Standard Clocks support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/Kconfig     |   6 ++
 drivers/clk/Makefile    |   1 +
 drivers/clk/clk-oxnas.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 209 insertions(+)
 create mode 100644 drivers/clk/clk-oxnas.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index eca8e01..16fa822 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -192,6 +192,12 @@ config COMMON_CLK_PXA
 	---help---
 	  Sypport for the Marvell PXA SoC.
 
+config COMMON_CLK_OXNAS
+	bool
+	select MFD_SYSCON
+	---help---
+	  Sypport for the OXNAS SoC Family clocks.
+
 config COMMON_CLK_CDCE706
 	tristate "Clock driver for TI CDCE706 clock synthesizer"
 	depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bae4be6..a5d45d8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_OXNAS)		+= clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
new file mode 100644
index 0000000..58b984b
--- /dev/null
+++ b/drivers/clk/clk-oxnas.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/stringify.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Standard regmap gate clocks */
+struct clk_oxnas {
+	struct clk_hw hw;
+	signed char bit;
+	struct regmap *regmap;
+};
+
+/* Regmap offsets */
+#define CLK_STAT_REGOFFSET	0x24
+#define CLK_SET_REGOFFSET	0x2c
+#define CLK_CLR_REGOFFSET	0x30
+
+static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw)
+{
+	return container_of(hw, struct clk_oxnas, hw);
+}
+
+static int oxnas_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(std->bit);
+}
+
+static int oxnas_clk_enable(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+
+	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
+
+	return 0;
+}
+
+static void oxnas_clk_disable(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+
+	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
+}
+
+static const struct clk_ops oxnas_clk_ops = {
+	.enable = oxnas_clk_enable,
+	.disable = oxnas_clk_disable,
+	.is_enabled = oxnas_clk_is_enabled,
+};
+
+static const char *const oxnas_clk_parents[] = {
+	"oscillator",
+};
+
+static const char *const eth_parents[] = {
+	"gmacclk",
+};
+
+#define DECLARE_STD_CLKP(__clk, __parent)			\
+static const struct clk_init_data clk_##__clk##_init = {	\
+	.name = __stringify(__clk),				\
+	.ops = &oxnas_clk_ops,					\
+	.parent_names = __parent,				\
+	.num_parents = ARRAY_SIZE(__parent),			\
+}
+
+#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents)
+
+/* Clk init data declaration */
+DECLARE_STD_CLK(leon);
+DECLARE_STD_CLK(dma_sgdma);
+DECLARE_STD_CLK(cipher);
+DECLARE_STD_CLK(sata);
+DECLARE_STD_CLK(audio);
+DECLARE_STD_CLK(usbmph);
+DECLARE_STD_CLKP(etha, eth_parents);
+DECLARE_STD_CLK(pciea);
+DECLARE_STD_CLK(nand);
+
+/* Bit - Name association */
+static const struct clk_init_data *clk_oxnas_init[] = {
+	[0] = &clk_leon_init,
+	[1] = &clk_dma_sgdma_init,
+	[2] = &clk_cipher_init,
+	[3] = NULL,		/* Do not touch to DDR clock */
+	[4] = &clk_sata_init,
+	[5] = &clk_audio_init,
+	[6] = &clk_usbmph_init,
+	[7] = &clk_etha_init,
+	[8] = &clk_pciea_init,
+	[9] = &clk_nand_init,
+};
+
+static int oxnas_stdclk_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct regmap *regmap;
+	struct clk_oxnas *clk_oxnas;
+	struct clk_onecell_data *onecell_data;
+	struct clk **clks;
+	unsigned int clks_count = 0;
+	int i;
+
+	clk_oxnas = devm_kzalloc(&pdev->dev,
+				 sizeof(*clk_oxnas)*ARRAY_SIZE(clk_oxnas_init),
+				 GFP_KERNEL);
+	if (!clk_oxnas)
+		return -ENOMEM;
+
+	clks = devm_kzalloc(&pdev->dev,
+			    sizeof(*clks)*ARRAY_SIZE(clk_oxnas_init),
+			    GFP_KERNEL);
+	if (!clks)
+		return -ENOMEM;
+
+	onecell_data = devm_kzalloc(&pdev->dev, sizeof(*onecell_data),
+				     GFP_KERNEL);
+	if (!onecell_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(of_get_parent(np));
+	if (!regmap) {
+		dev_err(&pdev->dev, "failed to have parent regmap\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) {
+		struct clk_oxnas *_clk;
+
+		if (!clk_oxnas_init[i])
+			continue;
+
+		_clk = &clk_oxnas[i];
+		_clk->bit = i;
+		_clk->hw.init = clk_oxnas_init[i];
+		_clk->regmap = regmap;
+
+		clks[clks_count] = devm_clk_register(&pdev->dev, &_clk->hw);
+		if (WARN_ON(IS_ERR(clks[clks_count])))
+			return PTR_ERR(clks[clks_count]);
+
+		++clks_count;
+	}
+
+	onecell_data->clks = clks;
+	onecell_data->clk_num = clks_count;
+
+	return of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
+}
+
+static int oxnas_stdclk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_stdclk_dt_ids[] = {
+	{ .compatible = "oxsemi,ox810se-stdclk" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids);
+
+static struct platform_driver oxnas_stdclk_driver = {
+	.probe = oxnas_stdclk_probe,
+	.remove = oxnas_stdclk_remove,
+	.driver	= {
+		.name = "oxnas-stdclk",
+		.of_match_table = of_match_ptr(oxnas_stdclk_dt_ids),
+	},
+};
+
+module_platform_driver(oxnas_stdclk_driver);
-- 
1.9.1

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

* [PATCH v2 09/18] clk: Add PLX Technology OXNAS Standard Clocks
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add PLX Technology OXNAS SoC Family Standard Clocks support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/Kconfig     |   6 ++
 drivers/clk/Makefile    |   1 +
 drivers/clk/clk-oxnas.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 209 insertions(+)
 create mode 100644 drivers/clk/clk-oxnas.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index eca8e01..16fa822 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -192,6 +192,12 @@ config COMMON_CLK_PXA
 	---help---
 	  Sypport for the Marvell PXA SoC.
 
+config COMMON_CLK_OXNAS
+	bool
+	select MFD_SYSCON
+	---help---
+	  Sypport for the OXNAS SoC Family clocks.
+
 config COMMON_CLK_CDCE706
 	tristate "Clock driver for TI CDCE706 clock synthesizer"
 	depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bae4be6..a5d45d8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_OXNAS)		+= clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c
new file mode 100644
index 0000000..58b984b
--- /dev/null
+++ b/drivers/clk/clk-oxnas.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/stringify.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Standard regmap gate clocks */
+struct clk_oxnas {
+	struct clk_hw hw;
+	signed char bit;
+	struct regmap *regmap;
+};
+
+/* Regmap offsets */
+#define CLK_STAT_REGOFFSET	0x24
+#define CLK_SET_REGOFFSET	0x2c
+#define CLK_CLR_REGOFFSET	0x30
+
+static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw)
+{
+	return container_of(hw, struct clk_oxnas, hw);
+}
+
+static int oxnas_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(std->bit);
+}
+
+static int oxnas_clk_enable(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+
+	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
+
+	return 0;
+}
+
+static void oxnas_clk_disable(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+
+	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
+}
+
+static const struct clk_ops oxnas_clk_ops = {
+	.enable = oxnas_clk_enable,
+	.disable = oxnas_clk_disable,
+	.is_enabled = oxnas_clk_is_enabled,
+};
+
+static const char *const oxnas_clk_parents[] = {
+	"oscillator",
+};
+
+static const char *const eth_parents[] = {
+	"gmacclk",
+};
+
+#define DECLARE_STD_CLKP(__clk, __parent)			\
+static const struct clk_init_data clk_##__clk##_init = {	\
+	.name = __stringify(__clk),				\
+	.ops = &oxnas_clk_ops,					\
+	.parent_names = __parent,				\
+	.num_parents = ARRAY_SIZE(__parent),			\
+}
+
+#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents)
+
+/* Clk init data declaration */
+DECLARE_STD_CLK(leon);
+DECLARE_STD_CLK(dma_sgdma);
+DECLARE_STD_CLK(cipher);
+DECLARE_STD_CLK(sata);
+DECLARE_STD_CLK(audio);
+DECLARE_STD_CLK(usbmph);
+DECLARE_STD_CLKP(etha, eth_parents);
+DECLARE_STD_CLK(pciea);
+DECLARE_STD_CLK(nand);
+
+/* Bit - Name association */
+static const struct clk_init_data *clk_oxnas_init[] = {
+	[0] = &clk_leon_init,
+	[1] = &clk_dma_sgdma_init,
+	[2] = &clk_cipher_init,
+	[3] = NULL,		/* Do not touch to DDR clock */
+	[4] = &clk_sata_init,
+	[5] = &clk_audio_init,
+	[6] = &clk_usbmph_init,
+	[7] = &clk_etha_init,
+	[8] = &clk_pciea_init,
+	[9] = &clk_nand_init,
+};
+
+static int oxnas_stdclk_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct regmap *regmap;
+	struct clk_oxnas *clk_oxnas;
+	struct clk_onecell_data *onecell_data;
+	struct clk **clks;
+	unsigned int clks_count = 0;
+	int i;
+
+	clk_oxnas = devm_kzalloc(&pdev->dev,
+				 sizeof(*clk_oxnas)*ARRAY_SIZE(clk_oxnas_init),
+				 GFP_KERNEL);
+	if (!clk_oxnas)
+		return -ENOMEM;
+
+	clks = devm_kzalloc(&pdev->dev,
+			    sizeof(*clks)*ARRAY_SIZE(clk_oxnas_init),
+			    GFP_KERNEL);
+	if (!clks)
+		return -ENOMEM;
+
+	onecell_data = devm_kzalloc(&pdev->dev, sizeof(*onecell_data),
+				     GFP_KERNEL);
+	if (!onecell_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(of_get_parent(np));
+	if (!regmap) {
+		dev_err(&pdev->dev, "failed to have parent regmap\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) {
+		struct clk_oxnas *_clk;
+
+		if (!clk_oxnas_init[i])
+			continue;
+
+		_clk = &clk_oxnas[i];
+		_clk->bit = i;
+		_clk->hw.init = clk_oxnas_init[i];
+		_clk->regmap = regmap;
+
+		clks[clks_count] = devm_clk_register(&pdev->dev, &_clk->hw);
+		if (WARN_ON(IS_ERR(clks[clks_count])))
+			return PTR_ERR(clks[clks_count]);
+
+		++clks_count;
+	}
+
+	onecell_data->clks = clks;
+	onecell_data->clk_num = clks_count;
+
+	return of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
+}
+
+static int oxnas_stdclk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_stdclk_dt_ids[] = {
+	{ .compatible = "oxsemi,ox810se-stdclk" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids);
+
+static struct platform_driver oxnas_stdclk_driver = {
+	.probe = oxnas_stdclk_probe,
+	.remove = oxnas_stdclk_remove,
+	.driver	= {
+		.name = "oxnas-stdclk",
+		.of_match_table = of_match_ptr(oxnas_stdclk_dt_ids),
+	},
+};
+
+module_platform_driver(oxnas_stdclk_driver);
-- 
1.9.1

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

* [PATCH v2 10/18] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-clk, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/clock/plxtech,stdclk.txt   | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt

diff --git a/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
new file mode 100644
index 0000000..c60b459
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
@@ -0,0 +1,35 @@
+PLX Technology OXNAS SoC Family Standard Clocks
+================================================
+
+Please also refer to clock-bindings.txt in this directory for common clock
+bindings usage.
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-stdclk"
+- #clock-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+For OX810SE, the clock indices are :
+ - 0: LEON
+ - 1: DMA_SGDMA
+ - 2: CIPHER
+ - 3: SATA
+ - 4: AUDIO
+ - 5: USBMPH
+ - 6: ETHA
+ - 7: PCIA
+ - 8: NAND
+
+example:
+
+sys: sys-ctrl@000000 {
+	compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	stdclk: stdclk {
+		compatible = "oxsemi,ox810se-stdclk";
+		#clock-cells = <1>;
+	};
+};
-- 
1.9.1

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

* [PATCH v2 10/18] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/clock/plxtech,stdclk.txt   | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt

diff --git a/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
new file mode 100644
index 0000000..c60b459
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/plxtech,stdclk.txt
@@ -0,0 +1,35 @@
+PLX Technology OXNAS SoC Family Standard Clocks
+================================================
+
+Please also refer to clock-bindings.txt in this directory for common clock
+bindings usage.
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-stdclk"
+- #clock-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+For OX810SE, the clock indices are :
+ - 0: LEON
+ - 1: DMA_SGDMA
+ - 2: CIPHER
+ - 3: SATA
+ - 4: AUDIO
+ - 5: USBMPH
+ - 6: ETHA
+ - 7: PCIA
+ - 8: NAND
+
+example:
+
+sys: sys-ctrl at 000000 {
+	compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	stdclk: stdclk {
+		compatible = "oxsemi,ox810se-stdclk";
+		#clock-cells = <1>;
+	};
+};
-- 
1.9.1

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

* [PATCH v2 11/18] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linus.walleij, linux-gpio
  Cc: Neil Armstrong, Ma Haijun, Jean-Christophe PLAGNIOL-VILLARD

Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

CC: Ma Haijun <mahaijuns@gmail.com>
CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/pinctrl/Kconfig         |    9 +
 drivers/pinctrl/Makefile        |    1 +
 drivers/pinctrl/pinctrl-oxnas.c | 1392 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1402 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 99a4c10..1d0c513 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -129,6 +129,15 @@ config PINCTRL_MESON
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_OXNAS
+	bool
+	depends on OF
+	select PINMUX
+	select PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select MFD_SYSCON
+
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bf1b5ca..3351d10 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_OXNAS)	+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
new file mode 100644
index 0000000..f35032a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -0,0 +1,1392 @@
+/*
+ * PLX Technology OXNAS Pinctrl driver based on at91 pinctrl driver
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Hajun <mahaijuns@gmail.com>
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+#include <linux/version.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK	32
+#define MAX_GPIO_BANKS		2
+
+struct oxnas_gpio_chip {
+	struct gpio_chip	chip;
+	struct pinctrl_gpio_range range;
+	void __iomem		*regbase;  /* GPIOA/B virtual address */
+	struct irq_domain	*domain;   /* associated irq domain */
+	struct regmap		*regmap;
+};
+
+#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)
+
+static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+/**
+ * struct oxnas_pmx_func - describes pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct oxnas_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+enum oxnas_mux {
+	OXNAS_PINMUX_GPIO,
+	OXNAS_PINMUX_FUNC1,
+	OXNAS_PINMUX_FUNC2,
+	OXNAS_PINMUX_FUNC3,
+};
+
+enum {
+	INPUT_VALUE = 0,
+	OUTPUT_ENABLE = 4,
+	IRQ_PENDING = 0xC,
+	OUTPUT_VALUE = 0x10,
+	OUTPUT_SET = 0x14,
+	OUTPUT_CLEAR = 0x18,
+	OUTPUT_EN_SET = 0x1C,
+	OUTPUT_EN_CLEAR = 0x20,
+	RE_IRQ_ENABLE = 0x28, /* rising edge */
+	FE_IRQ_ENABLE = 0x2C, /* falling edge */
+	RE_IRQ_PENDING = 0x30, /* rising edge */
+	FE_IRQ_PENDING = 0x34, /* falling edge */
+};
+
+enum {
+	PINMUX_PRIMARY_SEL0 = 0x0c,
+	PINMUX_PRIMARY_SEL1 = 0x10,
+	PINMUX_SECONDARY_SEL0 = 0x14,
+	PINMUX_SECONDARY_SEL1 = 0x18,
+	PINMUX_TERTIARY_SEL0 = 0x8c,
+	PINMUX_TERTIARY_SEL1 = 0x90,
+};
+
+/**
+ * struct oxnas_pmx_pin - describes an pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct oxnas_pmx_pin {
+	uint32_t	bank;
+	uint32_t	pin;
+	enum oxnas_mux	mux;
+	unsigned long	conf;
+};
+
+/**
+ * struct oxnas_pin_group - describes an pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *	array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ */
+struct oxnas_pin_group {
+	const char		*name;
+	struct oxnas_pmx_pin	*pins_conf;
+	unsigned int		*pins;
+	unsigned		npins;
+};
+
+struct oxnas_pinctrl {
+	struct device		*dev;
+	struct pinctrl_dev	*pctl;
+	struct regmap		*regmap;
+
+	int			nbanks;
+
+	uint32_t		*mux_mask;
+	int			nmux;
+
+	struct oxnas_pmx_func	*functions;
+	int			nfunctions;
+
+	struct oxnas_pin_group	*groups;
+	int			ngroups;
+};
+
+static const inline struct oxnas_pin_group *oxnas_pinctrl_find_group_by_name(
+				const struct oxnas_pinctrl *info,
+				const char *name)
+{
+	const struct oxnas_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (strcmp(info->groups[i].name, name))
+			continue;
+
+		grp = &info->groups[i];
+		dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins,
+			grp->pins[0]);
+		break;
+	}
+
+	return grp;
+}
+
+static int oxnas_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *oxnas_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int oxnas_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *npins)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void oxnas_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = oxnas_pinctrl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
+			       GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+		new_map[i].data.configs.num_configs = 1;
+	}
+
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static const struct pinctrl_ops oxnas_pctrl_ops = {
+	.get_groups_count	= oxnas_get_groups_count,
+	.get_group_name		= oxnas_get_group_name,
+	.get_group_pins		= oxnas_get_group_pins,
+	.pin_dbg_show		= oxnas_pin_dbg_show,
+	.dt_node_to_map		= oxnas_dt_node_to_map,
+	.dt_free_map		= oxnas_dt_free_map,
+};
+
+static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
+				 unsigned int bank)
+{
+	return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+	return pin / MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static void oxnas_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+	writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void oxnas_mux_set_func1(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func2(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func3(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, mask);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, mask);
+	}
+}
+
+static void oxnas_mux_set_gpio(struct oxnas_pinctrl *ctrl,
+			       unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static enum oxnas_mux oxnas_mux_get_func(struct regmap *regmap,
+					 unsigned bank, unsigned mask)
+{
+	unsigned int val;
+
+	if (!bank) {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	} else {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	}
+
+	return OXNAS_PINMUX_GPIO;
+}
+
+static void oxnas_pin_dbg(const struct device *dev,
+			  const struct oxnas_pmx_pin *pin)
+{
+	if (pin->mux) {
+		dev_dbg(dev,
+			"MF_%c%d configured as periph%c with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A',
+			pin->conf);
+	} else {
+		dev_dbg(dev, "MF_%c%d configured as gpio with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->conf);
+	}
+}
+
+static int pin_check_config(struct oxnas_pinctrl *info, const char *name,
+			    int index, const struct oxnas_pmx_pin *pin)
+{
+	int mux;
+
+	/* check if it's a valid config */
+	if (pin->bank >= info->nbanks) {
+		dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+			name, index, pin->bank, info->nbanks);
+		return -EINVAL;
+	}
+
+	if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+		dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+			name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+		return -EINVAL;
+	}
+	/* gpio always allowed */
+	if (!pin->mux)
+		return 0;
+
+	mux = pin->mux - 1;
+
+	if (mux >= info->nmux) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+			name, index, mux, info->nmux);
+		return -EINVAL;
+	}
+
+	if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for MF_%c%d\n",
+			name, index, mux, pin->bank + 'A', pin->pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void oxnas_mux_gpio_enable(struct oxnas_pinctrl *ctrl,
+				  int bank,
+				  void __iomem *pio,
+				  unsigned mask, bool input)
+{
+	oxnas_mux_set_gpio(ctrl, bank, mask);
+
+	if (input)
+		writel_relaxed(mask, pio + OUTPUT_EN_CLEAR);
+	else
+		writel_relaxed(mask, pio + OUTPUT_EN_SET);
+}
+
+static void oxnas_mux_gpio_disable(struct oxnas_pinctrl *ctrl,
+				   int bank,
+				   unsigned mask)
+{
+	/* when switch to other function, gpio is disabled automatically */
+}
+
+static int oxnas_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+			    unsigned group)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct oxnas_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i, ret;
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	/* first check that all the pins of the group are valid with a valid
+	 * parameter
+	 */
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		ret = pin_check_config(info, info->groups[group].name, i, pin);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		oxnas_pin_dbg(info->dev, pin);
+
+		pio = pin_to_gpioctrl(info, pin->bank);
+
+		mask = pin_to_mask(pin->pin);
+		oxnas_mux_disable_interrupt(pio, mask);
+
+		switch (pin->mux) {
+		case OXNAS_PINMUX_GPIO:
+			oxnas_mux_gpio_enable(info, pin->bank, pio, mask, 1);
+			break;
+		case OXNAS_PINMUX_FUNC1:
+			oxnas_mux_set_func1(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC2:
+			oxnas_mux_set_func2(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC3:
+			oxnas_mux_set_func3(info, pin->bank, mask);
+			break;
+		}
+		if (pin->mux)
+			oxnas_mux_gpio_disable(info, pin->bank, mask);
+	}
+
+	return 0;
+}
+
+static int oxnas_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+static const char *oxnas_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					   unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int oxnas_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_chip *oxnas_chip;
+	struct gpio_chip *chip;
+	unsigned mask;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	oxnas_chip = container_of(chip, struct oxnas_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	mask = 1 << (offset - chip->base);
+
+	dev_dbg(npct->dev, "enable pin %u as MF_%c%d 0x%x\n",
+		offset, 'A' + range->id, offset - chip->base, mask);
+
+	oxnas_mux_set_gpio(npct, range->id, mask);
+
+	return 0;
+}
+
+static void oxnas_gpio_disable_free(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static const struct pinmux_ops oxnas_pmx_ops = {
+	.get_functions_count	= oxnas_pmx_get_funcs_count,
+	.get_function_name	= oxnas_pmx_get_func_name,
+	.get_function_groups	= oxnas_pmx_get_groups,
+	.set_mux		= oxnas_pmx_set_mux,
+	.gpio_request_enable	= oxnas_gpio_request_enable,
+	.gpio_disable_free	= oxnas_gpio_disable_free,
+};
+
+static int oxnas_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static int oxnas_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *configs,
+			     unsigned num_configs)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static void oxnas_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void oxnas_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+}
+
+static const struct pinconf_ops oxnas_pinconf_ops = {
+	.pin_config_get			= oxnas_pinconf_get,
+	.pin_config_set			= oxnas_pinconf_set,
+	.pin_config_dbg_show		= oxnas_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= oxnas_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc oxnas_pinctrl_desc = {
+	.pctlops	= &oxnas_pctrl_ops,
+	.pmxops		= &oxnas_pmx_ops,
+	.confops	= &oxnas_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
+static const char *gpio_compat = "oxsemi,ox810se-gpio";
+
+static void oxnas_pinctrl_child_count(struct oxnas_pinctrl *info,
+				      struct device_node *np)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int oxnas_pinctrl_mux_mask(struct oxnas_pinctrl *info,
+				  struct device_node *np)
+{
+	int ret = 0;
+	int size;
+	const __be32 *list;
+
+	list = of_get_property(np, "plxtech,mux-mask", &size);
+	if (!list) {
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+		return -EINVAL;
+	}
+
+	size /= sizeof(*list);
+	if (!size || size % info->nbanks) {
+		dev_err(info->dev, "wrong mux mask array should be by %d\n",
+			info->nbanks);
+		return -EINVAL;
+	}
+	info->nmux = size / info->nbanks;
+
+	info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size,
+				      GFP_KERNEL);
+	if (!info->mux_mask)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(np, "plxtech,mux-mask",
+					  info->mux_mask, size);
+	if (ret)
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+	return ret;
+}
+
+static int oxnas_pinctrl_parse_groups(struct device_node *np,
+				      struct oxnas_pin_group *grp,
+				      struct oxnas_pinctrl *info, u32 index)
+{
+	struct oxnas_pmx_pin *pin;
+	int size;
+	const __be32 *list;
+	int i, j;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is plxtech,pins = <bank pin mux CONFIG ...>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "plxtech,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	size /= sizeof(*list);
+	if (!size || size % 4) {
+		dev_err(info->dev, "wrong pins number or pins and configs should be divisible by 4\n");
+		return -EINVAL;
+	}
+
+	grp->npins = size / 4;
+	pin = grp->pins_conf = devm_kzalloc(info->dev,
+				grp->npins * sizeof(struct oxnas_pmx_pin),
+				GFP_KERNEL);
+	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
+	if (!grp->pins_conf || !grp->pins)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < size; i += 4, j++) {
+		pin->bank = be32_to_cpu(*list++);
+		pin->pin = be32_to_cpu(*list++);
+		grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+		pin->mux = be32_to_cpu(*list++);
+		pin->conf = be32_to_cpu(*list++);
+
+		oxnas_pin_dbg(info->dev, pin);
+		pin++;
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_parse_functions(struct device_node *np,
+					struct oxnas_pinctrl *info, u32 index)
+{
+	struct device_node *child;
+	struct oxnas_pmx_func *func;
+	struct oxnas_pin_group *grp;
+	int ret;
+	static u32 grp_index;
+	u32 i = 0;
+
+	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &info->functions[index];
+
+	/* Initialise function */
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "no groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[grp_index++];
+		ret = oxnas_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+	{ .compatible = "oxsemi,ox810se-pinctrl"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_pinctrl_probe_dt(struct platform_device *pdev,
+				 struct oxnas_pinctrl *info)
+{
+	int ret = 0;
+	int i, j;
+	uint32_t *tmp;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+
+	if (!np)
+		return -ENODEV;
+
+	info->dev = &pdev->dev;
+
+	oxnas_pinctrl_child_count(info, np);
+
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		return -EINVAL;
+	}
+
+	ret = oxnas_pinctrl_mux_mask(info, np);
+	if (ret)
+		return ret;
+
+	dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+	dev_dbg(&pdev->dev, "mux-mask\n");
+	tmp = info->mux_mask;
+	for (i = 0; i < info->nbanks; i++)
+		for (j = 0; j < info->nmux; j++, tmp++)
+			dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev, info->nfunctions *
+						sizeof(struct oxnas_pmx_func),
+					GFP_KERNEL);
+	if (!info->functions)
+		return -ENOMEM;
+
+	info->groups = devm_kzalloc(&pdev->dev, info->ngroups *
+					sizeof(struct oxnas_pin_group),
+				    GFP_KERNEL);
+	if (!info->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+	i = 0;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat))
+			continue;
+		ret = oxnas_pinctrl_parse_functions(child, info, i++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_probe(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info;
+	struct pinctrl_pin_desc *pdesc;
+	int ret, i, j, k;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						       "plxtech,sys-ctrl");
+	if (IS_ERR(info->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	ret = oxnas_pinctrl_probe_dt(pdev, info);
+	if (ret)
+		return ret;
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < info->nbanks; i++) {
+		if (!gpio_chips[i]) {
+			dev_warn(&pdev->dev,
+				 "GPIO chip %d not registered yet\n", i);
+			devm_kfree(&pdev->dev, info);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	oxnas_pinctrl_desc.name = dev_name(&pdev->dev);
+	oxnas_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+	oxnas_pinctrl_desc.pins = pdesc =
+		devm_kzalloc(&pdev->dev, sizeof(*pdesc) *
+				oxnas_pinctrl_desc.npins, GFP_KERNEL);
+
+	if (!oxnas_pinctrl_desc.pins)
+		return -ENOMEM;
+
+	for (i = 0, k = 0; i < info->nbanks; i++) {
+		for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+			pdesc->number = k;
+			pdesc->name = kasprintf(GFP_KERNEL, "MF_%c%d", i + 'A',
+						j);
+			pdesc++;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+	info->pctl = pinctrl_register(&oxnas_pinctrl_desc, &pdev->dev, info);
+
+	if (!info->pctl) {
+		dev_err(&pdev->dev, "could not register OXNAS pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+	dev_info(&pdev->dev, "initialized OXNAS pinctrl driver\n");
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int oxnas_pinctrl_remove(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(info->pctl);
+
+	return 0;
+}
+
+static int oxnas_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+	int bank = chip->base / chip->ngpio;
+
+	dev_dbg(chip->parent, "%s:%d MF_%c%d(%d)\n", __func__, __LINE__,
+		'A' + bank, offset, gpio);
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void oxnas_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int oxnas_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_CLEAR);
+	return 0;
+}
+
+static int oxnas_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 pdsr = 0;
+
+	pdsr = readl_relaxed(pio + INPUT_VALUE);
+	return (pdsr & mask) != 0;
+}
+
+static void oxnas_gpio_set(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+}
+
+static int oxnas_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_SET);
+
+	return 0;
+}
+
+static int oxnas_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	int virq;
+
+	if (offset < chip->ngpio)
+		virq = irq_create_mapping(oxnas_gpio->domain, offset);
+	else
+		virq = -ENXIO;
+
+	dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n",
+				chip->label, offset + chip->base, virq);
+	return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void oxnas_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int i;
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	enum oxnas_mux mux;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		unsigned mask = pin_to_mask(pin);
+		unsigned bank = pin_to_bank(pin);
+		const char *gpio_label;
+		u32 pdsr;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (gpio_label) {
+			seq_printf(s, "[%s]\tGPIO%s%d: ",
+				   gpio_label, chip->label, i);
+			pdsr = readl_relaxed(pio + INPUT_VALUE);
+
+			seq_printf(s, "[gpio] %s\n",
+					pdsr & mask ?
+					"set" : "clear");
+		} else {
+			mux = oxnas_mux_get_func(oxnas_gpio->regmap,
+						 bank,
+						 mask);
+			seq_printf(s, "\tGPIO%s%d: [func%d]\n",
+				   chip->label, i, mux);
+		}
+
+	}
+}
+#else
+#define oxnas_gpio_dbg_show	NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * oxnas_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) | mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) | mask, pio + FE_IRQ_ENABLE);
+}
+
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
+		pr_warn("oxnas: Unsupported type for irq %d\n",
+			gpio_to_irq(d->irq));
+		return -EINVAL;
+	}
+	/* seems no way to set trigger type without enable irq,
+	 * so leave it to unmask time
+	 */
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
+};
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned long isr;
+	int n;
+
+	chained_irq_enter(chip, desc);
+	for (;;) {
+		isr = readl_relaxed(pio + IRQ_PENDING);
+		if (!isr)
+			break;
+
+		/* acks pending interrupts */
+		writel_relaxed(isr, pio + IRQ_PENDING);
+
+		for_each_set_bit(n, &isr, BITS_PER_LONG) {
+			generic_handle_irq(irq_find_mapping(oxnas_gpio->domain,
+							    n));
+		}
+	}
+	chained_irq_exit(chip, desc);
+	/* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
+
+	irq_set_lockdep_class(virq, &gpio_lock_class);
+
+	irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);
+
+	irq_set_chip_data(virq, oxnas_gpio);
+
+	return 0;
+}
+
+static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
+				       struct device_node *ctrlr,
+				       const u32 *intspec,
+				       unsigned int intsize,
+				       irq_hw_number_t *out_hwirq,
+				       unsigned int *out_type)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
+	int ret;
+	int pin = oxnas_gpio->chip.base + intspec[0];
+
+	if (WARN_ON(intsize < 2))
+		return -EINVAL;
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	ret = gpio_request(pin, ctrlr->full_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_direction_input(pin);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct irq_domain_ops oxnas_gpio_ops = {
+	.map	= oxnas_gpio_irq_map,
+	.xlate	= oxnas_gpio_irq_domain_xlate,
+};
+
+static int oxnas_gpio_of_irq_setup(struct device_node *node,
+				   struct oxnas_gpio_chip *oxnas_gpio,
+				   unsigned int irq)
+{
+	/* Disable irqs of this controller */
+	writel_relaxed(0, oxnas_gpio->regbase + RE_IRQ_ENABLE);
+	writel_relaxed(0, oxnas_gpio->regbase + FE_IRQ_ENABLE);
+
+	/* Setup irq domain */
+	oxnas_gpio->domain = irq_domain_add_linear(node, oxnas_gpio->chip.ngpio,
+						   &oxnas_gpio_ops, oxnas_gpio);
+	if (!oxnas_gpio->domain)
+		panic("oxnas_gpio: couldn't allocate irq domain (DT).\n");
+
+	irq_set_chip_data(irq, oxnas_gpio);
+	irq_set_chained_handler(irq, gpio_irq_handler);
+
+	return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip oxnas_gpio_template = {
+	.request		= oxnas_gpio_request,
+	.free			= oxnas_gpio_free,
+	.direction_input	= oxnas_gpio_direction_input,
+	.get			= oxnas_gpio_get,
+	.direction_output	= oxnas_gpio_direction_output,
+	.set			= oxnas_gpio_set,
+	.to_irq			= oxnas_gpio_to_irq,
+	.dbg_show		= oxnas_gpio_dbg_show,
+	.can_sleep		= 0,
+	.ngpio			= MAX_NB_GPIO_PER_BANK,
+};
+
+static const struct of_device_id oxnas_gpio_of_match[] = {
+	{ .compatible = "oxsemi,ox810se-gpio"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct oxnas_gpio_chip *oxnas_chip = NULL;
+	struct gpio_chip *chip;
+	struct pinctrl_gpio_range *range;
+	struct device_node *node = pdev->dev.of_node;
+	int ret = 0;
+	int irq, i;
+	int alias_idx = of_alias_get_id(np, "gpio");
+	uint32_t ngpio;
+	char **names;
+
+	if (WARN_ON(alias_idx >= ARRAY_SIZE(gpio_chips)))
+		return -EINVAL;
+
+	if (gpio_chips[alias_idx]) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err;
+	}
+
+	oxnas_chip = devm_kzalloc(&pdev->dev, sizeof(*oxnas_chip), GFP_KERNEL);
+	if (!oxnas_chip) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Get pinctrl sys control regmap */
+	oxnas_chip->regmap =
+		syscon_regmap_lookup_by_phandle(of_get_parent(node),
+						"plxtech,sys-ctrl");
+	if (IS_ERR(oxnas_chip->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	oxnas_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oxnas_chip->regbase)) {
+		ret = PTR_ERR(oxnas_chip->regbase);
+		goto err;
+	}
+
+	oxnas_chip->chip = oxnas_gpio_template;
+
+	chip = &oxnas_chip->chip;
+	chip->of_node = np;
+	chip->label = dev_name(&pdev->dev);
+	chip->parent = &pdev->dev;
+	chip->owner = THIS_MODULE;
+	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+		if (ngpio > MAX_NB_GPIO_PER_BANK)
+			pr_err("oxnas_gpio.%d, gpio-nb >= %d failback to %d\n",
+			       alias_idx, MAX_NB_GPIO_PER_BANK,
+			       MAX_NB_GPIO_PER_BANK);
+		else
+			chip->ngpio = ngpio;
+	}
+
+	names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+			     GFP_KERNEL);
+
+	if (!names) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < chip->ngpio; i++)
+		names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
+
+	chip->names = (const char *const *)names;
+
+	range = &oxnas_chip->range;
+	range->name = chip->label;
+	range->id = alias_idx;
+	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+	range->npins = chip->ngpio;
+	range->gc = chip;
+
+	ret = gpiochip_add(chip);
+	if (ret)
+		goto err;
+
+	gpio_chips[alias_idx] = oxnas_chip;
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+
+	oxnas_gpio_of_irq_setup(np, oxnas_chip, irq);
+
+	dev_info(&pdev->dev, "at address %p\n", oxnas_chip->regbase);
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+	return ret;
+}
+
+static struct platform_driver oxnas_gpio_driver = {
+	.driver = {
+		.name = "gpio-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_gpio_of_match),
+	},
+	.probe = oxnas_gpio_probe,
+};
+
+static struct platform_driver oxnas_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_pinctrl_of_match),
+	},
+	.probe = oxnas_pinctrl_probe,
+	.remove = oxnas_pinctrl_remove,
+};
+
+static int __init oxnas_pinctrl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&oxnas_gpio_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&oxnas_pinctrl_driver);
+}
+arch_initcall(oxnas_pinctrl_init);
+
+static void __exit oxnas_pinctrl_exit(void)
+{
+	platform_driver_unregister(&oxnas_pinctrl_driver);
+}
+
+module_exit(oxnas_pinctrl_exit);
-- 
1.9.1

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

* [PATCH v2 11/18] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

CC: Ma Haijun <mahaijuns@gmail.com>
CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/pinctrl/Kconfig         |    9 +
 drivers/pinctrl/Makefile        |    1 +
 drivers/pinctrl/pinctrl-oxnas.c | 1392 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1402 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 99a4c10..1d0c513 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -129,6 +129,15 @@ config PINCTRL_MESON
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_OXNAS
+	bool
+	depends on OF
+	select PINMUX
+	select PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select MFD_SYSCON
+
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bf1b5ca..3351d10 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_OXNAS)	+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
new file mode 100644
index 0000000..f35032a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -0,0 +1,1392 @@
+/*
+ * PLX Technology OXNAS Pinctrl driver based on at91 pinctrl driver
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Hajun <mahaijuns@gmail.com>
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+#include <linux/version.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK	32
+#define MAX_GPIO_BANKS		2
+
+struct oxnas_gpio_chip {
+	struct gpio_chip	chip;
+	struct pinctrl_gpio_range range;
+	void __iomem		*regbase;  /* GPIOA/B virtual address */
+	struct irq_domain	*domain;   /* associated irq domain */
+	struct regmap		*regmap;
+};
+
+#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)
+
+static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+/**
+ * struct oxnas_pmx_func - describes pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct oxnas_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+enum oxnas_mux {
+	OXNAS_PINMUX_GPIO,
+	OXNAS_PINMUX_FUNC1,
+	OXNAS_PINMUX_FUNC2,
+	OXNAS_PINMUX_FUNC3,
+};
+
+enum {
+	INPUT_VALUE = 0,
+	OUTPUT_ENABLE = 4,
+	IRQ_PENDING = 0xC,
+	OUTPUT_VALUE = 0x10,
+	OUTPUT_SET = 0x14,
+	OUTPUT_CLEAR = 0x18,
+	OUTPUT_EN_SET = 0x1C,
+	OUTPUT_EN_CLEAR = 0x20,
+	RE_IRQ_ENABLE = 0x28, /* rising edge */
+	FE_IRQ_ENABLE = 0x2C, /* falling edge */
+	RE_IRQ_PENDING = 0x30, /* rising edge */
+	FE_IRQ_PENDING = 0x34, /* falling edge */
+};
+
+enum {
+	PINMUX_PRIMARY_SEL0 = 0x0c,
+	PINMUX_PRIMARY_SEL1 = 0x10,
+	PINMUX_SECONDARY_SEL0 = 0x14,
+	PINMUX_SECONDARY_SEL1 = 0x18,
+	PINMUX_TERTIARY_SEL0 = 0x8c,
+	PINMUX_TERTIARY_SEL1 = 0x90,
+};
+
+/**
+ * struct oxnas_pmx_pin - describes an pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct oxnas_pmx_pin {
+	uint32_t	bank;
+	uint32_t	pin;
+	enum oxnas_mux	mux;
+	unsigned long	conf;
+};
+
+/**
+ * struct oxnas_pin_group - describes an pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *	array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @npins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ */
+struct oxnas_pin_group {
+	const char		*name;
+	struct oxnas_pmx_pin	*pins_conf;
+	unsigned int		*pins;
+	unsigned		npins;
+};
+
+struct oxnas_pinctrl {
+	struct device		*dev;
+	struct pinctrl_dev	*pctl;
+	struct regmap		*regmap;
+
+	int			nbanks;
+
+	uint32_t		*mux_mask;
+	int			nmux;
+
+	struct oxnas_pmx_func	*functions;
+	int			nfunctions;
+
+	struct oxnas_pin_group	*groups;
+	int			ngroups;
+};
+
+static const inline struct oxnas_pin_group *oxnas_pinctrl_find_group_by_name(
+				const struct oxnas_pinctrl *info,
+				const char *name)
+{
+	const struct oxnas_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (strcmp(info->groups[i].name, name))
+			continue;
+
+		grp = &info->groups[i];
+		dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins,
+			grp->pins[0]);
+		break;
+	}
+
+	return grp;
+}
+
+static int oxnas_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *oxnas_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int oxnas_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *npins)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void oxnas_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = oxnas_pinctrl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
+			       GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+		new_map[i].data.configs.num_configs = 1;
+	}
+
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static const struct pinctrl_ops oxnas_pctrl_ops = {
+	.get_groups_count	= oxnas_get_groups_count,
+	.get_group_name		= oxnas_get_group_name,
+	.get_group_pins		= oxnas_get_group_pins,
+	.pin_dbg_show		= oxnas_pin_dbg_show,
+	.dt_node_to_map		= oxnas_dt_node_to_map,
+	.dt_free_map		= oxnas_dt_free_map,
+};
+
+static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
+				 unsigned int bank)
+{
+	return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+	return pin / MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static void oxnas_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+	writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void oxnas_mux_set_func1(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func2(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, mask);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static void oxnas_mux_set_func3(struct oxnas_pinctrl *ctrl,
+				unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, mask);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, mask);
+	}
+}
+
+static void oxnas_mux_set_gpio(struct oxnas_pinctrl *ctrl,
+			       unsigned bank, unsigned mask)
+{
+	if (!bank) {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL0, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL0, mask, 0);
+	} else {
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_PRIMARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_SECONDARY_SEL1, mask, 0);
+		regmap_write_bits(ctrl->regmap,
+				PINMUX_TERTIARY_SEL1, mask, 0);
+	}
+}
+
+static enum oxnas_mux oxnas_mux_get_func(struct regmap *regmap,
+					 unsigned bank, unsigned mask)
+{
+	unsigned int val;
+
+	if (!bank) {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL0, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	} else {
+		if (!regmap_read(regmap, PINMUX_PRIMARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC1;
+		if (!regmap_read(regmap, PINMUX_SECONDARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC2;
+		if (!regmap_read(regmap, PINMUX_TERTIARY_SEL1, &val) &&
+		    (val & mask))
+			return OXNAS_PINMUX_FUNC3;
+	}
+
+	return OXNAS_PINMUX_GPIO;
+}
+
+static void oxnas_pin_dbg(const struct device *dev,
+			  const struct oxnas_pmx_pin *pin)
+{
+	if (pin->mux) {
+		dev_dbg(dev,
+			"MF_%c%d configured as periph%c with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A',
+			pin->conf);
+	} else {
+		dev_dbg(dev, "MF_%c%d configured as gpio with conf = %lu\n",
+			pin->bank + 'A', pin->pin, pin->conf);
+	}
+}
+
+static int pin_check_config(struct oxnas_pinctrl *info, const char *name,
+			    int index, const struct oxnas_pmx_pin *pin)
+{
+	int mux;
+
+	/* check if it's a valid config */
+	if (pin->bank >= info->nbanks) {
+		dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+			name, index, pin->bank, info->nbanks);
+		return -EINVAL;
+	}
+
+	if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+		dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+			name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+		return -EINVAL;
+	}
+	/* gpio always allowed */
+	if (!pin->mux)
+		return 0;
+
+	mux = pin->mux - 1;
+
+	if (mux >= info->nmux) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+			name, index, mux, info->nmux);
+		return -EINVAL;
+	}
+
+	if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for MF_%c%d\n",
+			name, index, mux, pin->bank + 'A', pin->pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void oxnas_mux_gpio_enable(struct oxnas_pinctrl *ctrl,
+				  int bank,
+				  void __iomem *pio,
+				  unsigned mask, bool input)
+{
+	oxnas_mux_set_gpio(ctrl, bank, mask);
+
+	if (input)
+		writel_relaxed(mask, pio + OUTPUT_EN_CLEAR);
+	else
+		writel_relaxed(mask, pio + OUTPUT_EN_SET);
+}
+
+static void oxnas_mux_gpio_disable(struct oxnas_pinctrl *ctrl,
+				   int bank,
+				   unsigned mask)
+{
+	/* when switch to other function, gpio is disabled automatically */
+}
+
+static int oxnas_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+			    unsigned group)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct oxnas_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i, ret;
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	/* first check that all the pins of the group are valid with a valid
+	 * parameter
+	 */
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		ret = pin_check_config(info, info->groups[group].name, i, pin);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		oxnas_pin_dbg(info->dev, pin);
+
+		pio = pin_to_gpioctrl(info, pin->bank);
+
+		mask = pin_to_mask(pin->pin);
+		oxnas_mux_disable_interrupt(pio, mask);
+
+		switch (pin->mux) {
+		case OXNAS_PINMUX_GPIO:
+			oxnas_mux_gpio_enable(info, pin->bank, pio, mask, 1);
+			break;
+		case OXNAS_PINMUX_FUNC1:
+			oxnas_mux_set_func1(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC2:
+			oxnas_mux_set_func2(info, pin->bank, mask);
+			break;
+		case OXNAS_PINMUX_FUNC3:
+			oxnas_mux_set_func3(info, pin->bank, mask);
+			break;
+		}
+		if (pin->mux)
+			oxnas_mux_gpio_disable(info, pin->bank, mask);
+	}
+
+	return 0;
+}
+
+static int oxnas_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+static const char *oxnas_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					   unsigned selector)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int oxnas_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_chip *oxnas_chip;
+	struct gpio_chip *chip;
+	unsigned mask;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	oxnas_chip = container_of(chip, struct oxnas_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	mask = 1 << (offset - chip->base);
+
+	dev_dbg(npct->dev, "enable pin %u as MF_%c%d 0x%x\n",
+		offset, 'A' + range->id, offset - chip->base, mask);
+
+	oxnas_mux_set_gpio(npct, range->id, mask);
+
+	return 0;
+}
+
+static void oxnas_gpio_disable_free(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned offset)
+{
+	struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static const struct pinmux_ops oxnas_pmx_ops = {
+	.get_functions_count	= oxnas_pmx_get_funcs_count,
+	.get_function_name	= oxnas_pmx_get_func_name,
+	.get_function_groups	= oxnas_pmx_get_groups,
+	.set_mux		= oxnas_pmx_set_mux,
+	.gpio_request_enable	= oxnas_gpio_request_enable,
+	.gpio_disable_free	= oxnas_gpio_disable_free,
+};
+
+static int oxnas_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static int oxnas_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *configs,
+			     unsigned num_configs)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static void oxnas_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void oxnas_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+}
+
+static const struct pinconf_ops oxnas_pinconf_ops = {
+	.pin_config_get			= oxnas_pinconf_get,
+	.pin_config_set			= oxnas_pinconf_set,
+	.pin_config_dbg_show		= oxnas_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= oxnas_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc oxnas_pinctrl_desc = {
+	.pctlops	= &oxnas_pctrl_ops,
+	.pmxops		= &oxnas_pmx_ops,
+	.confops	= &oxnas_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
+static const char *gpio_compat = "oxsemi,ox810se-gpio";
+
+static void oxnas_pinctrl_child_count(struct oxnas_pinctrl *info,
+				      struct device_node *np)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int oxnas_pinctrl_mux_mask(struct oxnas_pinctrl *info,
+				  struct device_node *np)
+{
+	int ret = 0;
+	int size;
+	const __be32 *list;
+
+	list = of_get_property(np, "plxtech,mux-mask", &size);
+	if (!list) {
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+		return -EINVAL;
+	}
+
+	size /= sizeof(*list);
+	if (!size || size % info->nbanks) {
+		dev_err(info->dev, "wrong mux mask array should be by %d\n",
+			info->nbanks);
+		return -EINVAL;
+	}
+	info->nmux = size / info->nbanks;
+
+	info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size,
+				      GFP_KERNEL);
+	if (!info->mux_mask)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(np, "plxtech,mux-mask",
+					  info->mux_mask, size);
+	if (ret)
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+	return ret;
+}
+
+static int oxnas_pinctrl_parse_groups(struct device_node *np,
+				      struct oxnas_pin_group *grp,
+				      struct oxnas_pinctrl *info, u32 index)
+{
+	struct oxnas_pmx_pin *pin;
+	int size;
+	const __be32 *list;
+	int i, j;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is plxtech,pins = <bank pin mux CONFIG ...>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "plxtech,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	size /= sizeof(*list);
+	if (!size || size % 4) {
+		dev_err(info->dev, "wrong pins number or pins and configs should be divisible by 4\n");
+		return -EINVAL;
+	}
+
+	grp->npins = size / 4;
+	pin = grp->pins_conf = devm_kzalloc(info->dev,
+				grp->npins * sizeof(struct oxnas_pmx_pin),
+				GFP_KERNEL);
+	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
+	if (!grp->pins_conf || !grp->pins)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < size; i += 4, j++) {
+		pin->bank = be32_to_cpu(*list++);
+		pin->pin = be32_to_cpu(*list++);
+		grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+		pin->mux = be32_to_cpu(*list++);
+		pin->conf = be32_to_cpu(*list++);
+
+		oxnas_pin_dbg(info->dev, pin);
+		pin++;
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_parse_functions(struct device_node *np,
+					struct oxnas_pinctrl *info, u32 index)
+{
+	struct device_node *child;
+	struct oxnas_pmx_func *func;
+	struct oxnas_pin_group *grp;
+	int ret;
+	static u32 grp_index;
+	u32 i = 0;
+
+	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &info->functions[index];
+
+	/* Initialise function */
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "no groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[grp_index++];
+		ret = oxnas_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+	{ .compatible = "oxsemi,ox810se-pinctrl"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_pinctrl_probe_dt(struct platform_device *pdev,
+				 struct oxnas_pinctrl *info)
+{
+	int ret = 0;
+	int i, j;
+	uint32_t *tmp;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+
+	if (!np)
+		return -ENODEV;
+
+	info->dev = &pdev->dev;
+
+	oxnas_pinctrl_child_count(info, np);
+
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		return -EINVAL;
+	}
+
+	ret = oxnas_pinctrl_mux_mask(info, np);
+	if (ret)
+		return ret;
+
+	dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+	dev_dbg(&pdev->dev, "mux-mask\n");
+	tmp = info->mux_mask;
+	for (i = 0; i < info->nbanks; i++)
+		for (j = 0; j < info->nmux; j++, tmp++)
+			dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev, info->nfunctions *
+						sizeof(struct oxnas_pmx_func),
+					GFP_KERNEL);
+	if (!info->functions)
+		return -ENOMEM;
+
+	info->groups = devm_kzalloc(&pdev->dev, info->ngroups *
+					sizeof(struct oxnas_pin_group),
+				    GFP_KERNEL);
+	if (!info->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+	i = 0;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat))
+			continue;
+		ret = oxnas_pinctrl_parse_functions(child, info, i++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int oxnas_pinctrl_probe(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info;
+	struct pinctrl_pin_desc *pdesc;
+	int ret, i, j, k;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						       "plxtech,sys-ctrl");
+	if (IS_ERR(info->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	ret = oxnas_pinctrl_probe_dt(pdev, info);
+	if (ret)
+		return ret;
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < info->nbanks; i++) {
+		if (!gpio_chips[i]) {
+			dev_warn(&pdev->dev,
+				 "GPIO chip %d not registered yet\n", i);
+			devm_kfree(&pdev->dev, info);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	oxnas_pinctrl_desc.name = dev_name(&pdev->dev);
+	oxnas_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+	oxnas_pinctrl_desc.pins = pdesc =
+		devm_kzalloc(&pdev->dev, sizeof(*pdesc) *
+				oxnas_pinctrl_desc.npins, GFP_KERNEL);
+
+	if (!oxnas_pinctrl_desc.pins)
+		return -ENOMEM;
+
+	for (i = 0, k = 0; i < info->nbanks; i++) {
+		for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+			pdesc->number = k;
+			pdesc->name = kasprintf(GFP_KERNEL, "MF_%c%d", i + 'A',
+						j);
+			pdesc++;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+	info->pctl = pinctrl_register(&oxnas_pinctrl_desc, &pdev->dev, info);
+
+	if (!info->pctl) {
+		dev_err(&pdev->dev, "could not register OXNAS pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+	dev_info(&pdev->dev, "initialized OXNAS pinctrl driver\n");
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int oxnas_pinctrl_remove(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *info = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(info->pctl);
+
+	return 0;
+}
+
+static int oxnas_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+	int bank = chip->base / chip->ngpio;
+
+	dev_dbg(chip->parent, "%s:%d MF_%c%d(%d)\n", __func__, __LINE__,
+		'A' + bank, offset, gpio);
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void oxnas_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int oxnas_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_CLEAR);
+	return 0;
+}
+
+static int oxnas_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 pdsr = 0;
+
+	pdsr = readl_relaxed(pio + INPUT_VALUE);
+	return (pdsr & mask) != 0;
+}
+
+static void oxnas_gpio_set(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+}
+
+static int oxnas_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+
+	if (val)
+		writel_relaxed(BIT(offset), pio + OUTPUT_SET);
+	else
+		writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR);
+
+	writel_relaxed(BIT(offset), pio + OUTPUT_EN_SET);
+
+	return 0;
+}
+
+static int oxnas_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	int virq;
+
+	if (offset < chip->ngpio)
+		virq = irq_create_mapping(oxnas_gpio->domain, offset);
+	else
+		virq = -ENXIO;
+
+	dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n",
+				chip->label, offset + chip->base, virq);
+	return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void oxnas_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int i;
+	struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip);
+	void __iomem *pio = oxnas_gpio->regbase;
+	enum oxnas_mux mux;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		unsigned mask = pin_to_mask(pin);
+		unsigned bank = pin_to_bank(pin);
+		const char *gpio_label;
+		u32 pdsr;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (gpio_label) {
+			seq_printf(s, "[%s]\tGPIO%s%d: ",
+				   gpio_label, chip->label, i);
+			pdsr = readl_relaxed(pio + INPUT_VALUE);
+
+			seq_printf(s, "[gpio] %s\n",
+					pdsr & mask ?
+					"set" : "clear");
+		} else {
+			mux = oxnas_mux_get_func(oxnas_gpio->regmap,
+						 bank,
+						 mask);
+			seq_printf(s, "\tGPIO%s%d: [func%d]\n",
+				   chip->label, i, mux);
+		}
+
+	}
+}
+#else
+#define oxnas_gpio_dbg_show	NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * oxnas_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) & ~mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) & ~mask, pio + FE_IRQ_ENABLE);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = oxnas_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+	unsigned	type = irqd_get_trigger_type(d);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(pio + RE_IRQ_ENABLE) | mask, pio + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(pio + FE_IRQ_ENABLE) | mask, pio + FE_IRQ_ENABLE);
+}
+
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
+		pr_warn("oxnas: Unsupported type for irq %d\n",
+			gpio_to_irq(d->irq));
+		return -EINVAL;
+	}
+	/* seems no way to set trigger type without enable irq,
+	 * so leave it to unmask time
+	 */
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
+};
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem *pio = oxnas_gpio->regbase;
+	unsigned long isr;
+	int n;
+
+	chained_irq_enter(chip, desc);
+	for (;;) {
+		isr = readl_relaxed(pio + IRQ_PENDING);
+		if (!isr)
+			break;
+
+		/* acks pending interrupts */
+		writel_relaxed(isr, pio + IRQ_PENDING);
+
+		for_each_set_bit(n, &isr, BITS_PER_LONG) {
+			generic_handle_irq(irq_find_mapping(oxnas_gpio->domain,
+							    n));
+		}
+	}
+	chained_irq_exit(chip, desc);
+	/* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+			      irq_hw_number_t hw)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
+
+	irq_set_lockdep_class(virq, &gpio_lock_class);
+
+	irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);
+
+	irq_set_chip_data(virq, oxnas_gpio);
+
+	return 0;
+}
+
+static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
+				       struct device_node *ctrlr,
+				       const u32 *intspec,
+				       unsigned int intsize,
+				       irq_hw_number_t *out_hwirq,
+				       unsigned int *out_type)
+{
+	struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
+	int ret;
+	int pin = oxnas_gpio->chip.base + intspec[0];
+
+	if (WARN_ON(intsize < 2))
+		return -EINVAL;
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	ret = gpio_request(pin, ctrlr->full_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_direction_input(pin);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct irq_domain_ops oxnas_gpio_ops = {
+	.map	= oxnas_gpio_irq_map,
+	.xlate	= oxnas_gpio_irq_domain_xlate,
+};
+
+static int oxnas_gpio_of_irq_setup(struct device_node *node,
+				   struct oxnas_gpio_chip *oxnas_gpio,
+				   unsigned int irq)
+{
+	/* Disable irqs of this controller */
+	writel_relaxed(0, oxnas_gpio->regbase + RE_IRQ_ENABLE);
+	writel_relaxed(0, oxnas_gpio->regbase + FE_IRQ_ENABLE);
+
+	/* Setup irq domain */
+	oxnas_gpio->domain = irq_domain_add_linear(node, oxnas_gpio->chip.ngpio,
+						   &oxnas_gpio_ops, oxnas_gpio);
+	if (!oxnas_gpio->domain)
+		panic("oxnas_gpio: couldn't allocate irq domain (DT).\n");
+
+	irq_set_chip_data(irq, oxnas_gpio);
+	irq_set_chained_handler(irq, gpio_irq_handler);
+
+	return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip oxnas_gpio_template = {
+	.request		= oxnas_gpio_request,
+	.free			= oxnas_gpio_free,
+	.direction_input	= oxnas_gpio_direction_input,
+	.get			= oxnas_gpio_get,
+	.direction_output	= oxnas_gpio_direction_output,
+	.set			= oxnas_gpio_set,
+	.to_irq			= oxnas_gpio_to_irq,
+	.dbg_show		= oxnas_gpio_dbg_show,
+	.can_sleep		= 0,
+	.ngpio			= MAX_NB_GPIO_PER_BANK,
+};
+
+static const struct of_device_id oxnas_gpio_of_match[] = {
+	{ .compatible = "oxsemi,ox810se-gpio"},
+	{ /* sentinel */ }
+};
+
+static int oxnas_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct oxnas_gpio_chip *oxnas_chip = NULL;
+	struct gpio_chip *chip;
+	struct pinctrl_gpio_range *range;
+	struct device_node *node = pdev->dev.of_node;
+	int ret = 0;
+	int irq, i;
+	int alias_idx = of_alias_get_id(np, "gpio");
+	uint32_t ngpio;
+	char **names;
+
+	if (WARN_ON(alias_idx >= ARRAY_SIZE(gpio_chips)))
+		return -EINVAL;
+
+	if (gpio_chips[alias_idx]) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err;
+	}
+
+	oxnas_chip = devm_kzalloc(&pdev->dev, sizeof(*oxnas_chip), GFP_KERNEL);
+	if (!oxnas_chip) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Get pinctrl sys control regmap */
+	oxnas_chip->regmap =
+		syscon_regmap_lookup_by_phandle(of_get_parent(node),
+						"plxtech,sys-ctrl");
+	if (IS_ERR(oxnas_chip->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	oxnas_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oxnas_chip->regbase)) {
+		ret = PTR_ERR(oxnas_chip->regbase);
+		goto err;
+	}
+
+	oxnas_chip->chip = oxnas_gpio_template;
+
+	chip = &oxnas_chip->chip;
+	chip->of_node = np;
+	chip->label = dev_name(&pdev->dev);
+	chip->parent = &pdev->dev;
+	chip->owner = THIS_MODULE;
+	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+		if (ngpio > MAX_NB_GPIO_PER_BANK)
+			pr_err("oxnas_gpio.%d, gpio-nb >= %d failback to %d\n",
+			       alias_idx, MAX_NB_GPIO_PER_BANK,
+			       MAX_NB_GPIO_PER_BANK);
+		else
+			chip->ngpio = ngpio;
+	}
+
+	names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+			     GFP_KERNEL);
+
+	if (!names) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < chip->ngpio; i++)
+		names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
+
+	chip->names = (const char *const *)names;
+
+	range = &oxnas_chip->range;
+	range->name = chip->label;
+	range->id = alias_idx;
+	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+	range->npins = chip->ngpio;
+	range->gc = chip;
+
+	ret = gpiochip_add(chip);
+	if (ret)
+		goto err;
+
+	gpio_chips[alias_idx] = oxnas_chip;
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+
+	oxnas_gpio_of_irq_setup(np, oxnas_chip, irq);
+
+	dev_info(&pdev->dev, "at address %p\n", oxnas_chip->regbase);
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+	return ret;
+}
+
+static struct platform_driver oxnas_gpio_driver = {
+	.driver = {
+		.name = "gpio-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_gpio_of_match),
+	},
+	.probe = oxnas_gpio_probe,
+};
+
+static struct platform_driver oxnas_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-oxnas",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(oxnas_pinctrl_of_match),
+	},
+	.probe = oxnas_pinctrl_probe,
+	.remove = oxnas_pinctrl_remove,
+};
+
+static int __init oxnas_pinctrl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&oxnas_gpio_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&oxnas_pinctrl_driver);
+}
+arch_initcall(oxnas_pinctrl_init);
+
+static void __exit oxnas_pinctrl_exit(void)
+{
+	platform_driver_unregister(&oxnas_pinctrl_driver);
+}
+
+module_exit(oxnas_pinctrl_exit);
-- 
1.9.1

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

* [PATCH v2 12/18] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linus.walleij, linux-gpio, devicetree
  Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |  27 ++++++
 .../bindings/pinctrl/plxtech,pinctrl.txt           | 100 +++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
new file mode 100644
index 0000000..cbb03c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -0,0 +1,27 @@
+PLX Technology OXNAS SoC GPIO Controller
+==========================================
+
+Required properties:
+- compatible: "oxsemi,ox810se-gpio".
+- reg: Should contain GPIO controller registers location and length
+- interrupts: Should be the port interrupt shared by all the pins.
+- #gpio-cells: Should be two.  The first cell is the pin number and
+  the second cell is used to specify optional parameters (currently
+  unused).
+- gpio-controller: Marks the device node as a GPIO controller.
+
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
+Example:
+	gpio0: gpio@000000 {
+		compatible = "oxsemi,ox810se-gpio";
+		reg = <0x000000 0x100000>;
+		interrupts = <21>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		#gpio-lines = <32>;
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
new file mode 100644
index 0000000..0c5051a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
@@ -0,0 +1,100 @@
+PLX Technology OXNAS SoC Pinmux Controller
+==========================================
+
+The OXNAS Pinmux Controller, enables the IC to share one PAD to several
+functional blocks. The sharing is done by multiplexing the PAD input/output
+signals. For each PAD there are up to 8 muxing options (called periph modes).
+Since different modules require different PAD settings
+(like pull up, keeper, etc) the contoller controls also the PAD settings
+parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+OXNAS pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "oxsemi,ox810se-pinctrl"
+- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
+  configured in this periph mode. All the periph and bank need to be describe.
+- plxtech,sys-ctrl: a phandle to the system controller syscon node
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+For example :
+Peripheral: 2 ( A and B)
+Bank: 2 (A, B and C)
+=>
+
+  /*    A         B     */
+  0xffffffff 0xffc00c3b  /* pioA */
+  0xffffffff 0x7fff3ccf  /* pioB */
+
+For each peripheral/bank we will descibe in a u32 if a pin can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Required properties for pin configuration node:
+- plxtech,pins: 4 integers array, represents a group of pins mux and config
+  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
+
+Bits used for CONFIG:
+ - None Yet
+
+Examples:
+
+pinctrl: pinctrl {
+	compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	/* Regmap for sys registers */
+	plxtech,sys-ctrl = <&sys>;
+
+	/* Default, all-open mux-map */
+	plxtech,mux-mask = <
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 >;
+
+	uart0 {
+		pinctrl_uart0: uart0 {
+			plxtech,pins = <0 31 3 0
+					0 32 3 0>;
+		};
+		pinctrl_uart0_modem: uart0_modem {
+			plxtech,pins = <0 27 3 0
+					0 28 3 0
+					0 29 3 0
+					0 30 3 0
+					0 33 3 0
+					0 34 3 0>;
+		};
+	};
+};
+
+uart0: uart@200000 {
+	compatible = "ns16550a";
+	reg = <0x200000 0x100000>;
+	clocks = <&sysclk>;
+	interrupts = <23>;
+	reg-shift = <0>;
+	fifo-size = <16>;
+	reg-io-width = <1>;
+	current-speed = <115200>;
+	no-loopback-test;
+	status = "disabled";
+	resets = <&reset 17>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+};
-- 
1.9.1


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

* [PATCH v2 12/18] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../devicetree/bindings/gpio/gpio_oxnas.txt        |  27 ++++++
 .../bindings/pinctrl/plxtech,pinctrl.txt           | 100 +++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
new file mode 100644
index 0000000..cbb03c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -0,0 +1,27 @@
+PLX Technology OXNAS SoC GPIO Controller
+==========================================
+
+Required properties:
+- compatible: "oxsemi,ox810se-gpio".
+- reg: Should contain GPIO controller registers location and length
+- interrupts: Should be the port interrupt shared by all the pins.
+- #gpio-cells: Should be two.  The first cell is the pin number and
+  the second cell is used to specify optional parameters (currently
+  unused).
+- gpio-controller: Marks the device node as a GPIO controller.
+
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
+Example:
+	gpio0: gpio at 000000 {
+		compatible = "oxsemi,ox810se-gpio";
+		reg = <0x000000 0x100000>;
+		interrupts = <21>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		#gpio-lines = <32>;
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
new file mode 100644
index 0000000..0c5051a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
@@ -0,0 +1,100 @@
+PLX Technology OXNAS SoC Pinmux Controller
+==========================================
+
+The OXNAS Pinmux Controller, enables the IC to share one PAD to several
+functional blocks. The sharing is done by multiplexing the PAD input/output
+signals. For each PAD there are up to 8 muxing options (called periph modes).
+Since different modules require different PAD settings
+(like pull up, keeper, etc) the contoller controls also the PAD settings
+parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+OXNAS pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "oxsemi,ox810se-pinctrl"
+- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
+  configured in this periph mode. All the periph and bank need to be describe.
+- plxtech,sys-ctrl: a phandle to the system controller syscon node
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+For example :
+Peripheral: 2 ( A and B)
+Bank: 2 (A, B and C)
+=>
+
+  /*    A         B     */
+  0xffffffff 0xffc00c3b  /* pioA */
+  0xffffffff 0x7fff3ccf  /* pioB */
+
+For each peripheral/bank we will descibe in a u32 if a pin can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Required properties for pin configuration node:
+- plxtech,pins: 4 integers array, represents a group of pins mux and config
+  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
+
+Bits used for CONFIG:
+ - None Yet
+
+Examples:
+
+pinctrl: pinctrl {
+	compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	/* Regmap for sys registers */
+	plxtech,sys-ctrl = <&sys>;
+
+	/* Default, all-open mux-map */
+	plxtech,mux-mask = <
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+		 >;
+
+	uart0 {
+		pinctrl_uart0: uart0 {
+			plxtech,pins = <0 31 3 0
+					0 32 3 0>;
+		};
+		pinctrl_uart0_modem: uart0_modem {
+			plxtech,pins = <0 27 3 0
+					0 28 3 0
+					0 29 3 0
+					0 30 3 0
+					0 33 3 0
+					0 34 3 0>;
+		};
+	};
+};
+
+uart0: uart at 200000 {
+	compatible = "ns16550a";
+	reg = <0x200000 0x100000>;
+	clocks = <&sysclk>;
+	interrupts = <23>;
+	reg-shift = <0>;
+	fifo-size = <16>;
+	reg-io-width = <1>;
+	current-speed = <115200>;
+	no-loopback-test;
+	status = "disabled";
+	resets = <&reset 17>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+};
-- 
1.9.1

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

* [PATCH v2 13/18] arm: Add new mach-oxnas
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux; +Cc: Neil Armstrong

Add mach-oxnas directory containing Kconfig.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/mach-oxnas/Kconfig  | 25 +++++++++++++++++++++++++
 arch/arm/mach-oxnas/Makefile |  1 +
 2 files changed, 26 insertions(+)
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile

diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
new file mode 100644
index 0000000..63cba044
--- /dev/null
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -0,0 +1,25 @@
+menuconfig ARCH_OXNAS
+	bool "PLX Technology OXNAS Family SoCs"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_RESET_CONTROLLER
+	select PINCTRL
+	depends on ARCH_MULTI_V5
+	help
+	  Support for OxNas SoC family developed by PLX Technology.
+	  (Formely Oxford Semiconductor)
+
+if ARCH_OXNAS
+
+config MACH_OX810SE
+	bool "Support OX810SE Based Products"
+	select ARM_TIMER_SP804
+	select COMMON_CLK_OXNAS
+	select CPU_ARM926T
+	select MFD_SYSCON
+	select PINCTRL_OXNAS
+	select RESET_OXNAS
+	select VERSATILE_FPGA_IRQ
+	help
+	  Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
+
+endif
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
new file mode 100644
index 0000000..d98d860
--- /dev/null
+++ b/arch/arm/mach-oxnas/Makefile
@@ -0,0 +1 @@
+# Nothing Yet
-- 
1.9.1

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

* [PATCH v2 13/18] arm: Add new mach-oxnas
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add mach-oxnas directory containing Kconfig.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/mach-oxnas/Kconfig  | 25 +++++++++++++++++++++++++
 arch/arm/mach-oxnas/Makefile |  1 +
 2 files changed, 26 insertions(+)
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-oxnas/Makefile

diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
new file mode 100644
index 0000000..63cba044
--- /dev/null
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -0,0 +1,25 @@
+menuconfig ARCH_OXNAS
+	bool "PLX Technology OXNAS Family SoCs"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_RESET_CONTROLLER
+	select PINCTRL
+	depends on ARCH_MULTI_V5
+	help
+	  Support for OxNas SoC family developed by PLX Technology.
+	  (Formely Oxford Semiconductor)
+
+if ARCH_OXNAS
+
+config MACH_OX810SE
+	bool "Support OX810SE Based Products"
+	select ARM_TIMER_SP804
+	select COMMON_CLK_OXNAS
+	select CPU_ARM926T
+	select MFD_SYSCON
+	select PINCTRL_OXNAS
+	select RESET_OXNAS
+	select VERSATILE_FPGA_IRQ
+	help
+	  Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
+
+endif
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
new file mode 100644
index 0000000..d98d860
--- /dev/null
+++ b/arch/arm/mach-oxnas/Makefile
@@ -0,0 +1 @@
+# Nothing Yet
-- 
1.9.1

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

* [PATCH v2 14/18] arm: Add build support for mach-oxnas
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux; +Cc: Neil Armstrong

Add Kconfig and Makefile support for mach-oxnas.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/Kconfig  | 2 ++
 arch/arm/Makefile | 1 +
 2 files changed, 3 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4f799e5..2025fc9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -801,6 +801,8 @@ source "arch/arm/plat-pxa/Kconfig"
 
 source "arch/arm/mach-mmp/Kconfig"
 
+source "arch/arm/mach-oxnas/Kconfig"
+
 source "arch/arm/mach-qcom/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fe25410..0e96c63 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -194,6 +194,7 @@ machine-$(CONFIG_ARCH_NSPIRE)		+= nspire
 machine-$(CONFIG_ARCH_OMAP1)		+= omap1
 machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
+machine-$(CONFIG_ARCH_OXNAS)		+= oxnas
 machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
 machine-$(CONFIG_ARCH_PXA)		+= pxa
 machine-$(CONFIG_ARCH_QCOM)		+= qcom
-- 
1.9.1

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

* [PATCH v2 14/18] arm: Add build support for mach-oxnas
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add Kconfig and Makefile support for mach-oxnas.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/Kconfig  | 2 ++
 arch/arm/Makefile | 1 +
 2 files changed, 3 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4f799e5..2025fc9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -801,6 +801,8 @@ source "arch/arm/plat-pxa/Kconfig"
 
 source "arch/arm/mach-mmp/Kconfig"
 
+source "arch/arm/mach-oxnas/Kconfig"
+
 source "arch/arm/mach-qcom/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fe25410..0e96c63 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -194,6 +194,7 @@ machine-$(CONFIG_ARCH_NSPIRE)		+= nspire
 machine-$(CONFIG_ARCH_OMAP1)		+= omap1
 machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
+machine-$(CONFIG_ARCH_OXNAS)		+= oxnas
 machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
 machine-$(CONFIG_ARCH_PXA)		+= pxa
 machine-$(CONFIG_ARCH_QCOM)		+= qcom
-- 
1.9.1

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

* [PATCH v2 15/18] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree, linux; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/ox810se.dtsi | 273 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 273 insertions(+)
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi

diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi
new file mode 100644
index 0000000..5852a57
--- /dev/null
+++ b/arch/arm/boot/dts/ox810se.dtsi
@@ -0,0 +1,273 @@
+/*
+ * ox810se.dtsi - Device tree file for Oxford Semiconductor OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "oxsemi,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rpsclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge@44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				/* Regmap for sys registers */
+				plxtech,sys-ctrl = <&sys>;
+
+				/* Default, all-open mux-map */
+				plxtech,mux-mask = <
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					>;
+
+				gpio0: gpio@000000 {
+					compatible = "oxsemi,ox810se-gpio";
+					reg = <0x000000 0x100000>;
+					interrupts = <21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <32>;
+				};
+
+				gpio1: gpio@100000 {
+					compatible = "oxsemi,ox810se-gpio";
+					reg = <0x100000 0x100000>;
+					interrupts = <22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <3>;
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0 {
+						plxtech,pins = <0 31 3 0
+								0 32 3 0>;
+					};
+					pinctrl_uart0_modem: uart0_modem {
+						plxtech,pins = <0 27 3 0
+								0 28 3 0
+								0 29 3 0
+								0 30 3 0
+								0 33 3 0
+								0 34 3 0>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1 {
+						plxtech,pins = <0 20 3 0
+								0 22 3 0>;
+					};
+					pinctrl_uart1_modem: uart1_modem {
+						plxtech,pins = <0 8 3 0
+								0 9 3 0
+								0 23 3 0
+								0 24 3 0
+								0 25 3 0
+								0 26 3 0>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2 {
+						plxtech,pins = <0 6 3 0
+								0 7 3 0>;
+					};
+					pinctrl_uart2_modem: uart2_modem {
+						plxtech,pins = <0 0 3 0
+								0 1 3 0
+								0 2 3 0
+								0 3 3 0
+								0 4 3 0
+								0 5 3 0>;
+					};
+				};
+			};
+
+			uart0: serial@200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: serial@300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: serial@900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: serial@a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge@45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl@000000 {
+				compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "oxsemi,ox810se-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "oxsemi,ox810se-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps@300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller@0 {
+					compatible = "arm,rps-irq";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+					valid-mask = <0xFFFFFFFF>;
+					clear-mask = <0>;
+				};
+
+				timer0: timer@200 {
+					compatible = "arm,sp804";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+					arm,timer-width = <24>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH v2 15/18] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, linux-lFZ/pmaqli7XmaaqVzeoHQ
  Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
 arch/arm/boot/dts/ox810se.dtsi | 273 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 273 insertions(+)
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi

diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi
new file mode 100644
index 0000000..5852a57
--- /dev/null
+++ b/arch/arm/boot/dts/ox810se.dtsi
@@ -0,0 +1,273 @@
+/*
+ * ox810se.dtsi - Device tree file for Oxford Semiconductor OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "oxsemi,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rpsclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge@44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				/* Regmap for sys registers */
+				plxtech,sys-ctrl = <&sys>;
+
+				/* Default, all-open mux-map */
+				plxtech,mux-mask = <
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					>;
+
+				gpio0: gpio@000000 {
+					compatible = "oxsemi,ox810se-gpio";
+					reg = <0x000000 0x100000>;
+					interrupts = <21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <32>;
+				};
+
+				gpio1: gpio@100000 {
+					compatible = "oxsemi,ox810se-gpio";
+					reg = <0x100000 0x100000>;
+					interrupts = <22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <3>;
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0 {
+						plxtech,pins = <0 31 3 0
+								0 32 3 0>;
+					};
+					pinctrl_uart0_modem: uart0_modem {
+						plxtech,pins = <0 27 3 0
+								0 28 3 0
+								0 29 3 0
+								0 30 3 0
+								0 33 3 0
+								0 34 3 0>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1 {
+						plxtech,pins = <0 20 3 0
+								0 22 3 0>;
+					};
+					pinctrl_uart1_modem: uart1_modem {
+						plxtech,pins = <0 8 3 0
+								0 9 3 0
+								0 23 3 0
+								0 24 3 0
+								0 25 3 0
+								0 26 3 0>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2 {
+						plxtech,pins = <0 6 3 0
+								0 7 3 0>;
+					};
+					pinctrl_uart2_modem: uart2_modem {
+						plxtech,pins = <0 0 3 0
+								0 1 3 0
+								0 2 3 0
+								0 3 3 0
+								0 4 3 0
+								0 5 3 0>;
+					};
+				};
+			};
+
+			uart0: serial@200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: serial@300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: serial@900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: serial@a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge@45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl@000000 {
+				compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "oxsemi,ox810se-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "oxsemi,ox810se-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps@300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller@0 {
+					compatible = "arm,rps-irq";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+					valid-mask = <0xFFFFFFFF>;
+					clear-mask = <0>;
+				};
+
+				timer0: timer@200 {
+					compatible = "arm,sp804";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+					arm,timer-width = <24>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 15/18] arm: boot: dts: Add PLX Technology OX810SE dtsi
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/ox810se.dtsi | 273 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 273 insertions(+)
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi

diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi
new file mode 100644
index 0000000..5852a57
--- /dev/null
+++ b/arch/arm/boot/dts/ox810se.dtsi
@@ -0,0 +1,273 @@
+/*
+ * ox810se.dtsi - Device tree file for Oxford Semiconductor OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "oxsemi,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rpsclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge at 44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges;
+
+				/* Regmap for sys registers */
+				plxtech,sys-ctrl = <&sys>;
+
+				/* Default, all-open mux-map */
+				plxtech,mux-mask = <
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
+					>;
+
+				gpio0: gpio at 000000 {
+					compatible = "oxsemi,ox810se-gpio";
+					reg = <0x000000 0x100000>;
+					interrupts = <21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <32>;
+				};
+
+				gpio1: gpio at 100000 {
+					compatible = "oxsemi,ox810se-gpio";
+					reg = <0x100000 0x100000>;
+					interrupts = <22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					#gpio-lines = <3>;
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0 {
+						plxtech,pins = <0 31 3 0
+								0 32 3 0>;
+					};
+					pinctrl_uart0_modem: uart0_modem {
+						plxtech,pins = <0 27 3 0
+								0 28 3 0
+								0 29 3 0
+								0 30 3 0
+								0 33 3 0
+								0 34 3 0>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1 {
+						plxtech,pins = <0 20 3 0
+								0 22 3 0>;
+					};
+					pinctrl_uart1_modem: uart1_modem {
+						plxtech,pins = <0 8 3 0
+								0 9 3 0
+								0 23 3 0
+								0 24 3 0
+								0 25 3 0
+								0 26 3 0>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2 {
+						plxtech,pins = <0 6 3 0
+								0 7 3 0>;
+					};
+					pinctrl_uart2_modem: uart2_modem {
+						plxtech,pins = <0 0 3 0
+								0 1 3 0
+								0 2 3 0
+								0 3 3 0
+								0 4 3 0
+								0 5 3 0>;
+					};
+				};
+			};
+
+			uart0: serial at 200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: serial at 300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: serial at 900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: serial at a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge at 45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl at 000000 {
+				compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "oxsemi,ox810se-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "oxsemi,ox810se-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps at 300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller at 0 {
+					compatible = "arm,rps-irq";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+					valid-mask = <0xFFFFFFFF>;
+					clear-mask = <0>;
+				};
+
+				timer0: timer at 200 {
+					compatible = "arm,sp804";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+					arm,timer-width = <24>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt

diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
new file mode 100644
index 0000000..f6032d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/oxnas.txt
@@ -0,0 +1,9 @@
+PLX Technology OXNAS SoCs Family device tree bindings
+-------------------------------------------
+
+Boards with the OX810SE Soc SoC shall have the following properties:
+  Required root node property:
+    compatible: "oxsemi,ox810se"
+
+Board compatible values:
+  - "wd,mbwe" (OX810SE)
-- 
1.9.1

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

* [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt

diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
new file mode 100644
index 0000000..f6032d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/oxnas.txt
@@ -0,0 +1,9 @@
+PLX Technology OXNAS SoCs Family device tree bindings
+-------------------------------------------
+
+Boards with the OX810SE Soc SoC shall have the following properties:
+  Required root node property:
+    compatible: "oxsemi,ox810se"
+
+Board compatible values:
+  - "wd,mbwe" (OX810SE)
-- 
1.9.1

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

* [PATCH v2 17/18] dt-bindings: Add Western Digital to vendor prefixes
  2016-03-09 10:24   ` Neil Armstrong
@ 2016-03-09 10:24     ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree; +Cc: Neil Armstrong

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 188671f..968d3f4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -249,6 +249,7 @@ via	VIA Technologies, Inc.
 virtio	Virtual I/O Device Specification, developed by the OASIS consortium
 vivante	Vivante Corporation
 voipac	Voipac Technologies s.r.o.
+wd	Western Digital Corp.
 wexler	Wexler
 winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
-- 
1.9.1

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

* [PATCH v2 17/18] dt-bindings: Add Western Digital to vendor prefixes
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 188671f..968d3f4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -249,6 +249,7 @@ via	VIA Technologies, Inc.
 virtio	Virtual I/O Device Specification, developed by the OASIS consortium
 vivante	Vivante Corporation
 voipac	Voipac Technologies s.r.o.
+wd	Western Digital Corp.
 wexler	Wexler
 winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
-- 
1.9.1

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

* [PATCH v2 18/18] arm: boot: dts: Add Western Digital My Book World Edition device tree
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree, linux; +Cc: Neil Armstrong

Add Western Digital My Book World Edition device tree based on
PLX Technology OX810SE SoC.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/Makefile    |   2 +
 arch/arm/boot/dts/wd-mbwe.dts | 112 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a4a6d70..0395674 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -520,6 +520,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_ARCH_OXNAS) += \
+	wd-mbwe.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/wd-mbwe.dts b/arch/arm/boot/dts/wd-mbwe.dts
new file mode 100644
index 0000000..ac3250a
--- /dev/null
+++ b/arch/arm/boot/dts/wd-mbwe.dts
@@ -0,0 +1,112 @@
+/*
+ * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox810se.dtsi"
+
+/ {
+	model = "Western Digital My Book World Edition";
+
+	compatible = "wd,mbwe", "oxsemi,ox810se";
+
+	chosen {
+		bootargs = "console=ttyS1,115200n8 earlyprintk=serial";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x48000000 0x8000000>;
+	};
+
+	aliases {
+		serial1 = &uart1;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		power {
+			label = "power";
+			gpios = <&gpio0 0 1>;
+			linux,code = <0x198>;
+		};
+
+		recovery {
+			label = "recovery";
+			gpios = <&gpio0 4 1>;
+			linux,code = <0xab>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		a0 {
+			label = "activity0";
+			gpios = <&gpio0 25 0>;
+			default-state = "keep";
+		};
+
+		a1 {
+			label = "activity1";
+			gpios = <&gpio0 26 0>;
+			default-state = "keep";
+		};
+
+		a2 {
+			label = "activity2";
+			gpios = <&gpio0 5 0>;
+			default-state = "keep";
+		};
+
+		a3 {
+			label = "activity3";
+			gpios = <&gpio0 6 0>;
+			default-state = "keep";
+		};
+
+		a4 {
+			label = "activity4";
+			gpios = <&gpio0 7 0>;
+			default-state = "keep";
+		};
+
+		a5 {
+			label = "activity5";
+			gpios = <&gpio1 2 0>;
+			default-state = "keep";
+		};
+	};
+
+	i2c-gpio {
+		compatible = "i2c-gpio";
+		gpios = <&gpio0 3 0 /* sda */
+			 &gpio0 2 0 /* scl */
+			 >;
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc0: rtc@48 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
-- 
1.9.1

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

* [PATCH v2 18/18] arm: boot: dts: Add Western Digital My Book World Edition device tree
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, linux-lFZ/pmaqli7XmaaqVzeoHQ
  Cc: Neil Armstrong

Add Western Digital My Book World Edition device tree based on
PLX Technology OX810SE SoC.

Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
 arch/arm/boot/dts/Makefile    |   2 +
 arch/arm/boot/dts/wd-mbwe.dts | 112 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a4a6d70..0395674 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -520,6 +520,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_ARCH_OXNAS) += \
+	wd-mbwe.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/wd-mbwe.dts b/arch/arm/boot/dts/wd-mbwe.dts
new file mode 100644
index 0000000..ac3250a
--- /dev/null
+++ b/arch/arm/boot/dts/wd-mbwe.dts
@@ -0,0 +1,112 @@
+/*
+ * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox810se.dtsi"
+
+/ {
+	model = "Western Digital My Book World Edition";
+
+	compatible = "wd,mbwe", "oxsemi,ox810se";
+
+	chosen {
+		bootargs = "console=ttyS1,115200n8 earlyprintk=serial";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x48000000 0x8000000>;
+	};
+
+	aliases {
+		serial1 = &uart1;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		power {
+			label = "power";
+			gpios = <&gpio0 0 1>;
+			linux,code = <0x198>;
+		};
+
+		recovery {
+			label = "recovery";
+			gpios = <&gpio0 4 1>;
+			linux,code = <0xab>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		a0 {
+			label = "activity0";
+			gpios = <&gpio0 25 0>;
+			default-state = "keep";
+		};
+
+		a1 {
+			label = "activity1";
+			gpios = <&gpio0 26 0>;
+			default-state = "keep";
+		};
+
+		a2 {
+			label = "activity2";
+			gpios = <&gpio0 5 0>;
+			default-state = "keep";
+		};
+
+		a3 {
+			label = "activity3";
+			gpios = <&gpio0 6 0>;
+			default-state = "keep";
+		};
+
+		a4 {
+			label = "activity4";
+			gpios = <&gpio0 7 0>;
+			default-state = "keep";
+		};
+
+		a5 {
+			label = "activity5";
+			gpios = <&gpio1 2 0>;
+			default-state = "keep";
+		};
+	};
+
+	i2c-gpio {
+		compatible = "i2c-gpio";
+		gpios = <&gpio0 3 0 /* sda */
+			 &gpio0 2 0 /* scl */
+			 >;
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc0: rtc@48 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 18/18] arm: boot: dts: Add Western Digital My Book World Edition device tree
@ 2016-03-09 10:24     ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-09 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add Western Digital My Book World Edition device tree based on
PLX Technology OX810SE SoC.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/boot/dts/Makefile    |   2 +
 arch/arm/boot/dts/wd-mbwe.dts | 112 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index a4a6d70..0395674 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -520,6 +520,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_ARCH_OXNAS) += \
+	wd-mbwe.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
diff --git a/arch/arm/boot/dts/wd-mbwe.dts b/arch/arm/boot/dts/wd-mbwe.dts
new file mode 100644
index 0000000..ac3250a
--- /dev/null
+++ b/arch/arm/boot/dts/wd-mbwe.dts
@@ -0,0 +1,112 @@
+/*
+ * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox810se.dtsi"
+
+/ {
+	model = "Western Digital My Book World Edition";
+
+	compatible = "wd,mbwe", "oxsemi,ox810se";
+
+	chosen {
+		bootargs = "console=ttyS1,115200n8 earlyprintk=serial";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x48000000 0x8000000>;
+	};
+
+	aliases {
+		serial1 = &uart1;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		power {
+			label = "power";
+			gpios = <&gpio0 0 1>;
+			linux,code = <0x198>;
+		};
+
+		recovery {
+			label = "recovery";
+			gpios = <&gpio0 4 1>;
+			linux,code = <0xab>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		a0 {
+			label = "activity0";
+			gpios = <&gpio0 25 0>;
+			default-state = "keep";
+		};
+
+		a1 {
+			label = "activity1";
+			gpios = <&gpio0 26 0>;
+			default-state = "keep";
+		};
+
+		a2 {
+			label = "activity2";
+			gpios = <&gpio0 5 0>;
+			default-state = "keep";
+		};
+
+		a3 {
+			label = "activity3";
+			gpios = <&gpio0 6 0>;
+			default-state = "keep";
+		};
+
+		a4 {
+			label = "activity4";
+			gpios = <&gpio0 7 0>;
+			default-state = "keep";
+		};
+
+		a5 {
+			label = "activity5";
+			gpios = <&gpio1 2 0>;
+			default-state = "keep";
+		};
+	};
+
+	i2c-gpio {
+		compatible = "i2c-gpio";
+		gpios = <&gpio0 3 0 /* sda */
+			 &gpio0 2 0 /* scl */
+			 >;
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc0: rtc at 48 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
-- 
1.9.1

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

* Re: [PATCH v2 11/18] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  2016-03-09 10:24     ` Neil Armstrong
  (?)
@ 2016-03-10 14:43       ` kbuild test robot
  -1 siblings, 0 replies; 208+ messages in thread
From: kbuild test robot @ 2016-03-10 14:43 UTC (permalink / raw)
  Cc: kbuild-all, linux-kernel, linux-arm-kernel, linus.walleij,
	linux-gpio, Neil Armstrong, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

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

Hi Neil,

[auto build test WARNING on robh/for-next]
[also build test WARNING on v4.5-rc7]
[cannot apply to next-20160310]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Neil-Armstrong/Add-Initial-support-for-PLX-Technology-OX810SE/20160309-183154
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux for-next
config: um-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=um 

All warnings (new ones prefixed by >>):

warning: (ST_IRQCHIP && HIP04_ETH && STMMAC_PLATFORM && DWMAC_IPQ806X && DWMAC_LPC18XX && DWMAC_ROCKCHIP && DWMAC_SOCFPGA && DWMAC_STI && TI_CPSW && PINCTRL_OXNAS && PINCTRL_ROCKCHIP && PINCTRL_DOVE && POWER_RESET_KEYSTONE && POWER_RESET_SYSCON && POWER_RESET_SYSCON_POWEROFF && S3C2410_WATCHDOG && VIDEO_OMAP3 && VIDEO_S5P_FIMC && USB_XHCI_MTK && RTC_DRV_AT91SAM9 && LPC18XX_DMAMUX && VIDEO_OMAP4 && COMMON_CLK_OXNAS && HWSPINLOCK_QCOM && ATMEL_ST && QCOM_GSBI && PHY_HI6220_USB) selects MFD_SYSCON which has unmet direct dependencies (HAS_IOMEM)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 17787 bytes --]

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

* Re: [PATCH v2 11/18] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-10 14:43       ` kbuild test robot
  0 siblings, 0 replies; 208+ messages in thread
From: kbuild test robot @ 2016-03-10 14:43 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: kbuild-all, linux-kernel, linux-arm-kernel, linus.walleij,
	linux-gpio, Neil Armstrong, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

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

Hi Neil,

[auto build test WARNING on robh/for-next]
[also build test WARNING on v4.5-rc7]
[cannot apply to next-20160310]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Neil-Armstrong/Add-Initial-support-for-PLX-Technology-OX810SE/20160309-183154
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux for-next
config: um-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=um 

All warnings (new ones prefixed by >>):

warning: (ST_IRQCHIP && HIP04_ETH && STMMAC_PLATFORM && DWMAC_IPQ806X && DWMAC_LPC18XX && DWMAC_ROCKCHIP && DWMAC_SOCFPGA && DWMAC_STI && TI_CPSW && PINCTRL_OXNAS && PINCTRL_ROCKCHIP && PINCTRL_DOVE && POWER_RESET_KEYSTONE && POWER_RESET_SYSCON && POWER_RESET_SYSCON_POWEROFF && S3C2410_WATCHDOG && VIDEO_OMAP3 && VIDEO_S5P_FIMC && USB_XHCI_MTK && RTC_DRV_AT91SAM9 && LPC18XX_DMAMUX && VIDEO_OMAP4 && COMMON_CLK_OXNAS && HWSPINLOCK_QCOM && ATMEL_ST && QCOM_GSBI && PHY_HI6220_USB) selects MFD_SYSCON which has unmet direct dependencies (HAS_IOMEM)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 17787 bytes --]

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

* [PATCH v2 11/18] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-10 14:43       ` kbuild test robot
  0 siblings, 0 replies; 208+ messages in thread
From: kbuild test robot @ 2016-03-10 14:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Neil,

[auto build test WARNING on robh/for-next]
[also build test WARNING on v4.5-rc7]
[cannot apply to next-20160310]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Neil-Armstrong/Add-Initial-support-for-PLX-Technology-OX810SE/20160309-183154
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux for-next
config: um-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=um 

All warnings (new ones prefixed by >>):

warning: (ST_IRQCHIP && HIP04_ETH && STMMAC_PLATFORM && DWMAC_IPQ806X && DWMAC_LPC18XX && DWMAC_ROCKCHIP && DWMAC_SOCFPGA && DWMAC_STI && TI_CPSW && PINCTRL_OXNAS && PINCTRL_ROCKCHIP && PINCTRL_DOVE && POWER_RESET_KEYSTONE && POWER_RESET_SYSCON && POWER_RESET_SYSCON_POWEROFF && S3C2410_WATCHDOG && VIDEO_OMAP3 && VIDEO_S5P_FIMC && USB_XHCI_MTK && RTC_DRV_AT91SAM9 && LPC18XX_DMAMUX && VIDEO_OMAP4 && COMMON_CLK_OXNAS && HWSPINLOCK_QCOM && ATMEL_ST && QCOM_GSBI && PHY_HI6220_USB) selects MFD_SYSCON which has unmet direct dependencies (HAS_IOMEM)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 17787 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160310/26c3135c/attachment.obj>

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

* Re: [PATCH v2 03/18] irqchip: versatile-fpga: add new arm,rps-irq compatible
  2016-03-09 10:24     ` [PATCH v2 03/18] irqchip: versatile-fpga: add new arm, rps-irq compatible Neil Armstrong
@ 2016-03-15 11:47       ` Marc Zyngier
  -1 siblings, 0 replies; 208+ messages in thread
From: Marc Zyngier @ 2016-03-15 11:47 UTC (permalink / raw)
  To: Neil Armstrong, linux-kernel, linux-arm-kernel, tglx, jason

On 09/03/16 10:24, Neil Armstrong wrote:
> Under the OX810SE, this exact same interface is used as "Reference Peripheral
> Specification" Interrupt Controller, so add a new compatible string.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH v2 03/18] irqchip: versatile-fpga: add new arm,rps-irq compatible
@ 2016-03-15 11:47       ` Marc Zyngier
  0 siblings, 0 replies; 208+ messages in thread
From: Marc Zyngier @ 2016-03-15 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/03/16 10:24, Neil Armstrong wrote:
> Under the OX810SE, this exact same interface is used as "Reference Peripheral
> Specification" Interrupt Controller, so add a new compatible string.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 11/17] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
@ 2016-03-15 14:30     ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-15 14:30 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

This is a vert terse zero-line commit message. Atleast describe what you are
trying to do.

> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

> +optional properties:
> +- #gpio-lines: Number of gpio if absent 32.

NACK, use ngpio from the gpio.txt document like
everyone else.

> +Required properties for iomux controller:
> +- compatible: "plxtech,nas782x-pinctrl" or "plxtech,ox810se-pinctrl"
> +- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
> +  configured in this periph mode. All the periph and bank need to be describe.

Why? Encode this into the driver and select muxmask from
the compatible string if it is a hardware limitation.

> +Each column will represent the possible peripheral of the pinctrl
> +Each line will represent a pio bank
> +
> +For example :
> +Peripheral: 2 ( A and B)
> +Bank: 2 (A, B and C)
> +=>
> +
> +  /*    A         B     */
> +  0xffffffff 0xffc00c3b  /* pioA */
> +  0xffffffff 0x7fff3ccf  /* pioB */
> +
> +For each peripheral/bank we will descibe in a u32 if a pin can be
> +configured in it by putting 1 to the pin bit (1 << pin)

That's just completely hopeless to understand for a DT author.
Put it into the driver.

> +Required properties for pin configuration node:
> +- plxtech,pins: 4 integers array, represents a group of pins mux and config
> +  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
> +  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
> +  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...

NACK, use the standard binding for "pins" from pinctrl-bindings.txt

Also make the driver use the existing helpers for this property.

Yours,
Linus Walleij

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

* Re: [PATCH 11/17] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
@ 2016-03-15 14:30     ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-15 14:30 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org> wrote:

This is a vert terse zero-line commit message. Atleast describe what you are
trying to do.

> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>

> +optional properties:
> +- #gpio-lines: Number of gpio if absent 32.

NACK, use ngpio from the gpio.txt document like
everyone else.

> +Required properties for iomux controller:
> +- compatible: "plxtech,nas782x-pinctrl" or "plxtech,ox810se-pinctrl"
> +- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
> +  configured in this periph mode. All the periph and bank need to be describe.

Why? Encode this into the driver and select muxmask from
the compatible string if it is a hardware limitation.

> +Each column will represent the possible peripheral of the pinctrl
> +Each line will represent a pio bank
> +
> +For example :
> +Peripheral: 2 ( A and B)
> +Bank: 2 (A, B and C)
> +=>
> +
> +  /*    A         B     */
> +  0xffffffff 0xffc00c3b  /* pioA */
> +  0xffffffff 0x7fff3ccf  /* pioB */
> +
> +For each peripheral/bank we will descibe in a u32 if a pin can be
> +configured in it by putting 1 to the pin bit (1 << pin)

That's just completely hopeless to understand for a DT author.
Put it into the driver.

> +Required properties for pin configuration node:
> +- plxtech,pins: 4 integers array, represents a group of pins mux and config
> +  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
> +  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
> +  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...

NACK, use the standard binding for "pins" from pinctrl-bindings.txt

Also make the driver use the existing helpers for this property.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 11/17] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
@ 2016-03-15 14:30     ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-15 14:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

This is a vert terse zero-line commit message. Atleast describe what you are
trying to do.

> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

> +optional properties:
> +- #gpio-lines: Number of gpio if absent 32.

NACK, use ngpio from the gpio.txt document like
everyone else.

> +Required properties for iomux controller:
> +- compatible: "plxtech,nas782x-pinctrl" or "plxtech,ox810se-pinctrl"
> +- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
> +  configured in this periph mode. All the periph and bank need to be describe.

Why? Encode this into the driver and select muxmask from
the compatible string if it is a hardware limitation.

> +Each column will represent the possible peripheral of the pinctrl
> +Each line will represent a pio bank
> +
> +For example :
> +Peripheral: 2 ( A and B)
> +Bank: 2 (A, B and C)
> +=>
> +
> +  /*    A         B     */
> +  0xffffffff 0xffc00c3b  /* pioA */
> +  0xffffffff 0x7fff3ccf  /* pioB */
> +
> +For each peripheral/bank we will descibe in a u32 if a pin can be
> +configured in it by putting 1 to the pin bit (1 << pin)

That's just completely hopeless to understand for a DT author.
Put it into the driver.

> +Required properties for pin configuration node:
> +- plxtech,pins: 4 integers array, represents a group of pins mux and config
> +  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
> +  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
> +  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...

NACK, use the standard binding for "pins" from pinctrl-bindings.txt

Also make the driver use the existing helpers for this property.

Yours,
Linus Walleij

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

* Re: [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  2016-03-03 11:40   ` Neil Armstrong
  (?)
@ 2016-03-15 14:56     ` Linus Walleij
  -1 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-15 14:56 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, linux-gpio, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

> Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

Be a bit more verbose. Is this MIPS? ARM? How many pins does it have? Etc.

> CC: Ma Haijun <mahaijuns@gmail.com>
> CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

This driver has some way to go, but let's work on it!

> +config PINCTRL_OXNAS
> +       bool
> +       depends on OF
> +       select PINMUX
> +       select PINCONF

Why is it not using GENERIC_PINCONF?

> +       select GPIOLIB
> +       select OF_GPIO

I can already see that this driver should use
select GPIOLIB_IRQCHIP and the existing infrastructure
to manage chained IRQs in the gpiolib core.

The driver need to be rewritten for this: see other drivers
using GPIOLIB_IRQCHIP for examples, both GPIO and pin control
drivers use this so there are plenty of examples.

As a result the code will shrink quite a bit.

> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/io.h>
> +#include <linux/gpio.h>

You should only need to include <linux/gpio/driver.h>

> +#include <linux/pinctrl/machine.h>

Why?

> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +/* Since we request GPIOs from ourself */
> +#include <linux/pinctrl/consumer.h>

So why do you do this? Is this a copy/paste?

> +#include <linux/version.h>

This looks like something from a porting shim that brings this
same driver to a few different kernel versions. This include should
not be needed.

> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +#include "core.h"
> +
> +#define MAX_NB_GPIO_PER_BANK   32
> +#define MAX_GPIO_BANKS         2
> +
> +struct oxnas_gpio_chip {
> +       struct gpio_chip        chip;
> +       struct pinctrl_gpio_range range;
> +       void __iomem            *regbase;  /* GPIOA/B virtual address */
> +       struct irq_domain       *domain;   /* associated irq domain */

Should not be needed with GPIOLIB_IRQCHIP

> +#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)

We nowadays use gpiochip_get_data() to get the state container pointer.
Use this along with gpiochip_add_data(), or even better:
devm_gpiochip_add_data()
which will be merged for v4.6.

> +static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];

Is that really needed? Oh well let's see as we work on this.

> +static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
> +                       struct device_node *np,
> +                       struct pinctrl_map **map, unsigned *num_maps)
> +{

> +       /*
> +        * first find the group of this node and check if we need create
> +        * config maps for pins
> +        */
> +       grp = oxnas_pinctrl_find_group_by_name(info, np->name);
> +       if (!grp) {
> +               dev_err(info->dev, "unable to find group for node %s\n",
> +                       np->name);
> +               return -EINVAL;
> +       }
> +
> +       map_num += grp->npins;
> +       new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
> +                              GFP_KERNEL);
> +       if (!new_map)
> +               return -ENOMEM;
> +
> +       *map = new_map;
> +       *num_maps = map_num;

Ugh this looks hairy. Can you not use the utility functions from
pinctrl-utils.h with pinctrl_utils_reserve_map() etc?

> +static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
> +                               struct pinctrl_map *map, unsigned num_maps)
> +{
> +}

Really? You don't fool me. ;)

pinctrl_utils_dt_free_map() from pinctrl-utils.h should be your friend,
if you follow the pattern from other drivers.

> +static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
> +                                unsigned int bank)
> +{
> +       return gpio_chips[bank]->regbase;
> +}
> +
> +static inline int pin_to_bank(unsigned pin)
> +{
> +       return pin / MAX_NB_GPIO_PER_BANK;
> +}
> +
> +static unsigned pin_to_mask(unsigned int pin)
> +{
> +       return 1 << pin;
> +}

Those are a bit simplistic. The last one can be replaced by the
this inline:

+ include <linux/bitops.h>

- pin_to_mask(foo);
+ BIT(foo);

> +static int gpio_irq_type(struct irq_data *d, unsigned type)
> +{
> +       if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
> +               pr_warn("oxnas: Unsupported type for irq %d\n",
> +                       gpio_to_irq(d->irq));
> +               return -EINVAL;
> +       }
> +       /* seems no way to set trigger type without enable irq,
> +        * so leave it to unmask time
> +        */
> +
> +       return 0;
> +}

This will make your interrupt chip accept level IRQ types
which it obviously does not support.

> +static struct irq_chip gpio_irqchip = {
> +       .name           = "GPIO",
> +       .irq_disable    = gpio_irq_mask,
> +       .irq_mask       = gpio_irq_mask,
> +       .irq_unmask     = gpio_irq_unmask,
> +       .irq_set_type   = gpio_irq_type,
> +};

I think you should implement .irq_ack which will ACK the
IRQ before continuing with the IRQ handler.

> +static void gpio_irq_handler(struct irq_desc *desc)
> +{
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       struct irq_data *idata = irq_desc_get_irq_data(desc);
> +       struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
> +       void __iomem *pio = oxnas_gpio->regbase;
> +       unsigned long isr;
> +       int n;
> +
> +       chained_irq_enter(chip, desc);
> +       for (;;) {
> +               isr = readl_relaxed(pio + IRQ_PENDING);
> +               if (!isr)
> +                       break;
> +
> +               /* acks pending interrupts */
> +               writel_relaxed(isr, pio + IRQ_PENDING);

This should not be done here but in the .irq_ack() function that you
should implement in the irq chip.

See drivers/gpio/gpio-pl061.c for inspiration.

> + * This lock class tells lockdep that GPIO irqs are in a different
> + * category than their parents, so it won't report false recursion.
> + */
> +static struct lock_class_key gpio_lock_class;

This is also handled by GPIOLIB_IRQCHIP.

> +static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
> +                             irq_hw_number_t hw)
> +{
> +       struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
> +
> +       irq_set_lockdep_class(virq, &gpio_lock_class);
> +
> +       irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);

So you use handle_edge_irq() but do not implement .irq_ack(), that
looks wrong.

> +
> +       irq_set_chip_data(virq, oxnas_gpio);
> +
> +       return 0;
> +}

And this is also handled by GPIOLIB_IRQCHIP by the way.

> +static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
> +                                      struct device_node *ctrlr,
> +                                      const u32 *intspec,
> +                                      unsigned int intsize,
> +                                      irq_hw_number_t *out_hwirq,
> +                                      unsigned int *out_type)
> +{
> +       struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
> +       int ret;
> +       int pin = oxnas_gpio->chip.base + intspec[0];
> +
> +       if (WARN_ON(intsize < 2))
> +               return -EINVAL;
> +       *out_hwirq = intspec[0];
> +       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
> +
> +       ret = gpio_request(pin, ctrlr->full_name);
> +       if (ret)
> +               return ret;

No, the IRQchip and gpiochip should be orthogonal.
The irqchip will mark lines as used for IRQ though.
Rely on GPIOLIB_IRQCHIP.

> +
> +       ret = gpio_direction_input(pin);
> +       if (ret)
> +               return ret;

Your irqchip code should set up the hardware for IRQ,
not the xlate function.

> +
> +       return 0;
> +}
> +
> +static struct irq_domain_ops oxnas_gpio_ops = {
> +       .map    = oxnas_gpio_irq_map,
> +       .xlate  = oxnas_gpio_irq_domain_xlate,
> +};

And all this goes away with GPIOLIB_IRQCHIP.

> +       names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
> +                            GFP_KERNEL);
> +
> +       if (!names) {
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       for (i = 0; i < chip->ngpio; i++)
> +               names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
> +
> +       chip->names = (const char *const *)names;

Clever, however we are discussing adding a method for naming the lines
to the device tree bindings, please see these discussions for information.
Do not use this method plese.

There will be more review comments but I look forward to v2 as the first
step, using more library functions and cutting down the code a bit!

Yours,
Linus Walleij

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

* Re: [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-15 14:56     ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-15 14:56 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, linux-gpio, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

> Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

Be a bit more verbose. Is this MIPS? ARM? How many pins does it have? Etc.

> CC: Ma Haijun <mahaijuns@gmail.com>
> CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

This driver has some way to go, but let's work on it!

> +config PINCTRL_OXNAS
> +       bool
> +       depends on OF
> +       select PINMUX
> +       select PINCONF

Why is it not using GENERIC_PINCONF?

> +       select GPIOLIB
> +       select OF_GPIO

I can already see that this driver should use
select GPIOLIB_IRQCHIP and the existing infrastructure
to manage chained IRQs in the gpiolib core.

The driver need to be rewritten for this: see other drivers
using GPIOLIB_IRQCHIP for examples, both GPIO and pin control
drivers use this so there are plenty of examples.

As a result the code will shrink quite a bit.

> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/io.h>
> +#include <linux/gpio.h>

You should only need to include <linux/gpio/driver.h>

> +#include <linux/pinctrl/machine.h>

Why?

> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +/* Since we request GPIOs from ourself */
> +#include <linux/pinctrl/consumer.h>

So why do you do this? Is this a copy/paste?

> +#include <linux/version.h>

This looks like something from a porting shim that brings this
same driver to a few different kernel versions. This include should
not be needed.

> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +#include "core.h"
> +
> +#define MAX_NB_GPIO_PER_BANK   32
> +#define MAX_GPIO_BANKS         2
> +
> +struct oxnas_gpio_chip {
> +       struct gpio_chip        chip;
> +       struct pinctrl_gpio_range range;
> +       void __iomem            *regbase;  /* GPIOA/B virtual address */
> +       struct irq_domain       *domain;   /* associated irq domain */

Should not be needed with GPIOLIB_IRQCHIP

> +#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)

We nowadays use gpiochip_get_data() to get the state container pointer.
Use this along with gpiochip_add_data(), or even better:
devm_gpiochip_add_data()
which will be merged for v4.6.

> +static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];

Is that really needed? Oh well let's see as we work on this.

> +static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
> +                       struct device_node *np,
> +                       struct pinctrl_map **map, unsigned *num_maps)
> +{

> +       /*
> +        * first find the group of this node and check if we need create
> +        * config maps for pins
> +        */
> +       grp = oxnas_pinctrl_find_group_by_name(info, np->name);
> +       if (!grp) {
> +               dev_err(info->dev, "unable to find group for node %s\n",
> +                       np->name);
> +               return -EINVAL;
> +       }
> +
> +       map_num += grp->npins;
> +       new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
> +                              GFP_KERNEL);
> +       if (!new_map)
> +               return -ENOMEM;
> +
> +       *map = new_map;
> +       *num_maps = map_num;

Ugh this looks hairy. Can you not use the utility functions from
pinctrl-utils.h with pinctrl_utils_reserve_map() etc?

> +static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
> +                               struct pinctrl_map *map, unsigned num_maps)
> +{
> +}

Really? You don't fool me. ;)

pinctrl_utils_dt_free_map() from pinctrl-utils.h should be your friend,
if you follow the pattern from other drivers.

> +static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
> +                                unsigned int bank)
> +{
> +       return gpio_chips[bank]->regbase;
> +}
> +
> +static inline int pin_to_bank(unsigned pin)
> +{
> +       return pin / MAX_NB_GPIO_PER_BANK;
> +}
> +
> +static unsigned pin_to_mask(unsigned int pin)
> +{
> +       return 1 << pin;
> +}

Those are a bit simplistic. The last one can be replaced by the
this inline:

+ include <linux/bitops.h>

- pin_to_mask(foo);
+ BIT(foo);

> +static int gpio_irq_type(struct irq_data *d, unsigned type)
> +{
> +       if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
> +               pr_warn("oxnas: Unsupported type for irq %d\n",
> +                       gpio_to_irq(d->irq));
> +               return -EINVAL;
> +       }
> +       /* seems no way to set trigger type without enable irq,
> +        * so leave it to unmask time
> +        */
> +
> +       return 0;
> +}

This will make your interrupt chip accept level IRQ types
which it obviously does not support.

> +static struct irq_chip gpio_irqchip = {
> +       .name           = "GPIO",
> +       .irq_disable    = gpio_irq_mask,
> +       .irq_mask       = gpio_irq_mask,
> +       .irq_unmask     = gpio_irq_unmask,
> +       .irq_set_type   = gpio_irq_type,
> +};

I think you should implement .irq_ack which will ACK the
IRQ before continuing with the IRQ handler.

> +static void gpio_irq_handler(struct irq_desc *desc)
> +{
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       struct irq_data *idata = irq_desc_get_irq_data(desc);
> +       struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
> +       void __iomem *pio = oxnas_gpio->regbase;
> +       unsigned long isr;
> +       int n;
> +
> +       chained_irq_enter(chip, desc);
> +       for (;;) {
> +               isr = readl_relaxed(pio + IRQ_PENDING);
> +               if (!isr)
> +                       break;
> +
> +               /* acks pending interrupts */
> +               writel_relaxed(isr, pio + IRQ_PENDING);

This should not be done here but in the .irq_ack() function that you
should implement in the irq chip.

See drivers/gpio/gpio-pl061.c for inspiration.

> + * This lock class tells lockdep that GPIO irqs are in a different
> + * category than their parents, so it won't report false recursion.
> + */
> +static struct lock_class_key gpio_lock_class;

This is also handled by GPIOLIB_IRQCHIP.

> +static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
> +                             irq_hw_number_t hw)
> +{
> +       struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
> +
> +       irq_set_lockdep_class(virq, &gpio_lock_class);
> +
> +       irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);

So you use handle_edge_irq() but do not implement .irq_ack(), that
looks wrong.

> +
> +       irq_set_chip_data(virq, oxnas_gpio);
> +
> +       return 0;
> +}

And this is also handled by GPIOLIB_IRQCHIP by the way.

> +static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
> +                                      struct device_node *ctrlr,
> +                                      const u32 *intspec,
> +                                      unsigned int intsize,
> +                                      irq_hw_number_t *out_hwirq,
> +                                      unsigned int *out_type)
> +{
> +       struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
> +       int ret;
> +       int pin = oxnas_gpio->chip.base + intspec[0];
> +
> +       if (WARN_ON(intsize < 2))
> +               return -EINVAL;
> +       *out_hwirq = intspec[0];
> +       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
> +
> +       ret = gpio_request(pin, ctrlr->full_name);
> +       if (ret)
> +               return ret;

No, the IRQchip and gpiochip should be orthogonal.
The irqchip will mark lines as used for IRQ though.
Rely on GPIOLIB_IRQCHIP.

> +
> +       ret = gpio_direction_input(pin);
> +       if (ret)
> +               return ret;

Your irqchip code should set up the hardware for IRQ,
not the xlate function.

> +
> +       return 0;
> +}
> +
> +static struct irq_domain_ops oxnas_gpio_ops = {
> +       .map    = oxnas_gpio_irq_map,
> +       .xlate  = oxnas_gpio_irq_domain_xlate,
> +};

And all this goes away with GPIOLIB_IRQCHIP.

> +       names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
> +                            GFP_KERNEL);
> +
> +       if (!names) {
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       for (i = 0; i < chip->ngpio; i++)
> +               names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
> +
> +       chip->names = (const char *const *)names;

Clever, however we are discussing adding a method for naming the lines
to the device tree bindings, please see these discussions for information.
Do not use this method plese.

There will be more review comments but I look forward to v2 as the first
step, using more library functions and cutting down the code a bit!

Yours,
Linus Walleij

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

* [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-15 14:56     ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-15 14:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

> Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family

Be a bit more verbose. Is this MIPS? ARM? How many pins does it have? Etc.

> CC: Ma Haijun <mahaijuns@gmail.com>
> CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

This driver has some way to go, but let's work on it!

> +config PINCTRL_OXNAS
> +       bool
> +       depends on OF
> +       select PINMUX
> +       select PINCONF

Why is it not using GENERIC_PINCONF?

> +       select GPIOLIB
> +       select OF_GPIO

I can already see that this driver should use
select GPIOLIB_IRQCHIP and the existing infrastructure
to manage chained IRQs in the gpiolib core.

The driver need to be rewritten for this: see other drivers
using GPIOLIB_IRQCHIP for examples, both GPIO and pin control
drivers use this so there are plenty of examples.

As a result the code will shrink quite a bit.

> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/io.h>
> +#include <linux/gpio.h>

You should only need to include <linux/gpio/driver.h>

> +#include <linux/pinctrl/machine.h>

Why?

> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +/* Since we request GPIOs from ourself */
> +#include <linux/pinctrl/consumer.h>

So why do you do this? Is this a copy/paste?

> +#include <linux/version.h>

This looks like something from a porting shim that brings this
same driver to a few different kernel versions. This include should
not be needed.

> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +#include "core.h"
> +
> +#define MAX_NB_GPIO_PER_BANK   32
> +#define MAX_GPIO_BANKS         2
> +
> +struct oxnas_gpio_chip {
> +       struct gpio_chip        chip;
> +       struct pinctrl_gpio_range range;
> +       void __iomem            *regbase;  /* GPIOA/B virtual address */
> +       struct irq_domain       *domain;   /* associated irq domain */

Should not be needed with GPIOLIB_IRQCHIP

> +#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip)

We nowadays use gpiochip_get_data() to get the state container pointer.
Use this along with gpiochip_add_data(), or even better:
devm_gpiochip_add_data()
which will be merged for v4.6.

> +static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS];

Is that really needed? Oh well let's see as we work on this.

> +static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev,
> +                       struct device_node *np,
> +                       struct pinctrl_map **map, unsigned *num_maps)
> +{

> +       /*
> +        * first find the group of this node and check if we need create
> +        * config maps for pins
> +        */
> +       grp = oxnas_pinctrl_find_group_by_name(info, np->name);
> +       if (!grp) {
> +               dev_err(info->dev, "unable to find group for node %s\n",
> +                       np->name);
> +               return -EINVAL;
> +       }
> +
> +       map_num += grp->npins;
> +       new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
> +                              GFP_KERNEL);
> +       if (!new_map)
> +               return -ENOMEM;
> +
> +       *map = new_map;
> +       *num_maps = map_num;

Ugh this looks hairy. Can you not use the utility functions from
pinctrl-utils.h with pinctrl_utils_reserve_map() etc?

> +static void oxnas_dt_free_map(struct pinctrl_dev *pctldev,
> +                               struct pinctrl_map *map, unsigned num_maps)
> +{
> +}

Really? You don't fool me. ;)

pinctrl_utils_dt_free_map() from pinctrl-utils.h should be your friend,
if you follow the pattern from other drivers.

> +static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info,
> +                                unsigned int bank)
> +{
> +       return gpio_chips[bank]->regbase;
> +}
> +
> +static inline int pin_to_bank(unsigned pin)
> +{
> +       return pin / MAX_NB_GPIO_PER_BANK;
> +}
> +
> +static unsigned pin_to_mask(unsigned int pin)
> +{
> +       return 1 << pin;
> +}

Those are a bit simplistic. The last one can be replaced by the
this inline:

+ include <linux/bitops.h>

- pin_to_mask(foo);
+ BIT(foo);

> +static int gpio_irq_type(struct irq_data *d, unsigned type)
> +{
> +       if ((type & IRQ_TYPE_EDGE_BOTH) == 0) {
> +               pr_warn("oxnas: Unsupported type for irq %d\n",
> +                       gpio_to_irq(d->irq));
> +               return -EINVAL;
> +       }
> +       /* seems no way to set trigger type without enable irq,
> +        * so leave it to unmask time
> +        */
> +
> +       return 0;
> +}

This will make your interrupt chip accept level IRQ types
which it obviously does not support.

> +static struct irq_chip gpio_irqchip = {
> +       .name           = "GPIO",
> +       .irq_disable    = gpio_irq_mask,
> +       .irq_mask       = gpio_irq_mask,
> +       .irq_unmask     = gpio_irq_unmask,
> +       .irq_set_type   = gpio_irq_type,
> +};

I think you should implement .irq_ack which will ACK the
IRQ before continuing with the IRQ handler.

> +static void gpio_irq_handler(struct irq_desc *desc)
> +{
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       struct irq_data *idata = irq_desc_get_irq_data(desc);
> +       struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata);
> +       void __iomem *pio = oxnas_gpio->regbase;
> +       unsigned long isr;
> +       int n;
> +
> +       chained_irq_enter(chip, desc);
> +       for (;;) {
> +               isr = readl_relaxed(pio + IRQ_PENDING);
> +               if (!isr)
> +                       break;
> +
> +               /* acks pending interrupts */
> +               writel_relaxed(isr, pio + IRQ_PENDING);

This should not be done here but in the .irq_ack() function that you
should implement in the irq chip.

See drivers/gpio/gpio-pl061.c for inspiration.

> + * This lock class tells lockdep that GPIO irqs are in a different
> + * category than their parents, so it won't report false recursion.
> + */
> +static struct lock_class_key gpio_lock_class;

This is also handled by GPIOLIB_IRQCHIP.

> +static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq,
> +                             irq_hw_number_t hw)
> +{
> +       struct oxnas_gpio_chip *oxnas_gpio = h->host_data;
> +
> +       irq_set_lockdep_class(virq, &gpio_lock_class);
> +
> +       irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq);

So you use handle_edge_irq() but do not implement .irq_ack(), that
looks wrong.

> +
> +       irq_set_chip_data(virq, oxnas_gpio);
> +
> +       return 0;
> +}

And this is also handled by GPIOLIB_IRQCHIP by the way.

> +static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d,
> +                                      struct device_node *ctrlr,
> +                                      const u32 *intspec,
> +                                      unsigned int intsize,
> +                                      irq_hw_number_t *out_hwirq,
> +                                      unsigned int *out_type)
> +{
> +       struct oxnas_gpio_chip *oxnas_gpio = d->host_data;
> +       int ret;
> +       int pin = oxnas_gpio->chip.base + intspec[0];
> +
> +       if (WARN_ON(intsize < 2))
> +               return -EINVAL;
> +       *out_hwirq = intspec[0];
> +       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
> +
> +       ret = gpio_request(pin, ctrlr->full_name);
> +       if (ret)
> +               return ret;

No, the IRQchip and gpiochip should be orthogonal.
The irqchip will mark lines as used for IRQ though.
Rely on GPIOLIB_IRQCHIP.

> +
> +       ret = gpio_direction_input(pin);
> +       if (ret)
> +               return ret;

Your irqchip code should set up the hardware for IRQ,
not the xlate function.

> +
> +       return 0;
> +}
> +
> +static struct irq_domain_ops oxnas_gpio_ops = {
> +       .map    = oxnas_gpio_irq_map,
> +       .xlate  = oxnas_gpio_irq_domain_xlate,
> +};

And all this goes away with GPIOLIB_IRQCHIP.

> +       names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
> +                            GFP_KERNEL);
> +
> +       if (!names) {
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       for (i = 0; i < chip->ngpio; i++)
> +               names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i);
> +
> +       chip->names = (const char *const *)names;

Clever, however we are discussing adding a method for naming the lines
to the device tree bindings, please see these discussions for information.
Do not use this method plese.

There will be more review comments but I look forward to v2 as the first
step, using more library functions and cutting down the code a bit!

Yours,
Linus Walleij

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

* Re: [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  2016-03-15 14:56     ` Linus Walleij
  (?)
@ 2016-03-16 15:00       ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-16 15:00 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, linux-gpio, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

On 03/15/2016 03:56 PM, Linus Walleij wrote:
> On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:
> 
>> Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family
> 
> Be a bit more verbose. Is this MIPS? ARM? How many pins does it have? Etc.
> 
>> CC: Ma Haijun <mahaijuns@gmail.com>
>> CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> This driver has some way to go, but let's work on it!

Hi Linus,

Thanks a lot for the review.
This driver was initially forked from the at91 driver by Jean-Christophe PLAGNIOL-VILLARD, I just
cleaned it up for upstreaming, but yes it must be rewritten.

I think I'll reboot over a clean base, could you give a reference driver I should follow ?
It's a very simple HW, it should be easy.
> 
> There will be more review comments but I look forward to v2 as the first
> step, using more library functions and cutting down the code a bit!

These first comments are precious !

Could I post a v2 separately for review ?

Thanks,
Neil

> 
> Yours,
> Linus Walleij
> 

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

* Re: [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-16 15:00       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-16 15:00 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-arm-kernel, linux-gpio, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

On 03/15/2016 03:56 PM, Linus Walleij wrote:
> On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:
> 
>> Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family
> 
> Be a bit more verbose. Is this MIPS? ARM? How many pins does it have? Etc.
> 
>> CC: Ma Haijun <mahaijuns@gmail.com>
>> CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> This driver has some way to go, but let's work on it!

Hi Linus,

Thanks a lot for the review.
This driver was initially forked from the at91 driver by Jean-Christophe PLAGNIOL-VILLARD, I just
cleaned it up for upstreaming, but yes it must be rewritten.

I think I'll reboot over a clean base, could you give a reference driver I should follow ?
It's a very simple HW, it should be easy.
> 
> There will be more review comments but I look forward to v2 as the first
> step, using more library functions and cutting down the code a bit!

These first comments are precious !

Could I post a v2 separately for review ?

Thanks,
Neil

> 
> Yours,
> Linus Walleij
> 

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

* [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-16 15:00       ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-16 15:00 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/15/2016 03:56 PM, Linus Walleij wrote:
> On Thu, Mar 3, 2016 at 12:40 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:
> 
>> Add pinctrl and gprio control support to PLX Technology OXNAS SoC Family
> 
> Be a bit more verbose. Is this MIPS? ARM? How many pins does it have? Etc.
> 
>> CC: Ma Haijun <mahaijuns@gmail.com>
>> CC: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> This driver has some way to go, but let's work on it!

Hi Linus,

Thanks a lot for the review.
This driver was initially forked from the at91 driver by Jean-Christophe PLAGNIOL-VILLARD, I just
cleaned it up for upstreaming, but yes it must be rewritten.

I think I'll reboot over a clean base, could you give a reference driver I should follow ?
It's a very simple HW, it should be easy.
> 
> There will be more review comments but I look forward to v2 as the first
> step, using more library functions and cutting down the code a bit!

These first comments are precious !

Could I post a v2 separately for review ?

Thanks,
Neil

> 
> Yours,
> Linus Walleij
> 

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

* Re: [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
  2016-03-16 15:00       ` Neil Armstrong
  (?)
@ 2016-03-17 14:49         ` Linus Walleij
  -1 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-17 14:49 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, linux-gpio, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

On Wed, Mar 16, 2016 at 4:00 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

> I think I'll reboot over a clean base, could you give a reference driver I should follow ?
> It's a very simple HW, it should be easy.

I would look at those merged lately, which has pin control
combined with GPIO and interrupts.

drivers/pinctrl/qcom is good but supports quite a lot of
subvariants so it may be hard to see what parts you really
need. But I think of those as a very nice drivers.

Yours,
Linus Walleij

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

* Re: [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-17 14:49         ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-17 14:49 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, linux-gpio, Ma Haijun,
	Jean-Christophe PLAGNIOL-VILLARD

On Wed, Mar 16, 2016 at 4:00 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

> I think I'll reboot over a clean base, could you give a reference driver I should follow ?
> It's a very simple HW, it should be easy.

I would look at those merged lately, which has pin control
combined with GPIO and interrupts.

drivers/pinctrl/qcom is good but supports quite a lot of
subvariants so it may be hard to see what parts you really
need. But I think of those as a very nice drivers.

Yours,
Linus Walleij

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

* [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver
@ 2016-03-17 14:49         ` Linus Walleij
  0 siblings, 0 replies; 208+ messages in thread
From: Linus Walleij @ 2016-03-17 14:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 16, 2016 at 4:00 PM, Neil Armstrong <narmstrong@baylibre.com> wrote:

> I think I'll reboot over a clean base, could you give a reference driver I should follow ?
> It's a very simple HW, it should be easy.

I would look at those merged lately, which has pin control
combined with GPIO and interrupts.

drivers/pinctrl/qcom is good but supports quite a lot of
subvariants so it may be hard to see what parts you really
need. But I think of those as a very nice drivers.

Yours,
Linus Walleij

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

* Re: [PATCH 04/17] clocksource: Add PLX Technology RPS Timer
  2016-03-03 11:39   ` Neil Armstrong
@ 2016-03-17 16:13     ` Daniel Lezcano
  -1 siblings, 0 replies; 208+ messages in thread
From: Daniel Lezcano @ 2016-03-17 16:13 UTC (permalink / raw)
  To: Neil Armstrong, linux-kernel, linux-arm-kernel, tglx; +Cc: Ma Haijun

Hi Neil,

On 03/03/2016 12:39 PM, Neil Armstrong wrote:
> Add clocksource and clockevent driver from dual RPS timer.

please elaborate the log: describe the timer, how it works, is there a 
pointer to doc, freq, etc ...

> CC: Ma Haijun <mahaijuns@gmail.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>   drivers/clocksource/Kconfig     |   6 +
>   drivers/clocksource/Makefile    |   1 +
>   drivers/clocksource/timer-rps.c | 249 ++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 256 insertions(+)
>   create mode 100644 drivers/clocksource/timer-rps.c
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 33db740..f79bc0f 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -276,6 +276,12 @@ config VF_PIT_TIMER
>   	help
>   	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
>
> +config CLKSRC_RPS_TIMER
> +	bool
> +	select CLKSRC_MMIO
> +	help
> +	  This enables support for the PLX Tech OXNAS RPS timers.
> +

Please check DIGICOLOR_TIMER or DW_APB_TIMER or ROCKCHIP_TIMER or 
ARMADA_370_XP_TIMER or ... config section and try to stick to the same 
pattern.

>   config SYS_SUPPORTS_SH_CMT
>           bool
>
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index dc2b899..120bc09 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
>   obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
>   obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
>   obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
> +obj-$(CONFIG_CLKSRC_RPS_TIMER)	+= timer-rps.o
>
>   obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
>   obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
> diff --git a/drivers/clocksource/timer-rps.c b/drivers/clocksource/timer-rps.c
> new file mode 100644
> index 0000000..79621b8
> --- /dev/null
> +++ b/drivers/clocksource/timer-rps.c
> @@ -0,0 +1,249 @@
> +/*
> + * drivers/clocksource/timer-rps.c
> + *
> + * Copyright (C) 2009 Oxford Semiconductor Ltd
> + * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/io.h>
> +#include <linux/clockchips.h>
> +#include <linux/clk.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/sched_clock.h>
> +
> +/* TIMER1 as tick
> + * TIMER2 as clocksource
> + */

Comment format:

/*
  * TIMER1 used as tick
  * TIMER2 used as clocksource
  */

> +enum {
> +	TIMER_LOAD = 0,
> +	TIMER_CURR = 4,
> +	TIMER_CTRL = 8,
> +	TIMER_CLRINT = 0xC,
> +
> +	TIMER_BITS = 24,
> +
> +	TIMER_MAX_VAL = (1 << TIMER_BITS) - 1,
> +
> +	TIMER_PERIODIC = (1 << 6),
> +	TIMER_ENABLE = (1 << 7),
> +
> +	TIMER_DIV1  = (0 << 2),
> +	TIMER_DIV16  = (1 << 2),
> +	TIMER_DIV256  = (2 << 2),
> +
> +	TIMER1_OFFSET = 0,
> +	TIMER2_OFFSET = 0x20,
> +};

What is the point of having this unorganized enum with duplicate values 
? and why TIMER_DIV1 = (0 << 2) ?

Replace by #define.

> +/* Clockevent */
> +
> +static unsigned long timer_period = HZ;
> +static unsigned timer_prescaler = 1;
> +static void __iomem *timer_base;

Encapsulate these variables into a structure and use container_of.

> +
> +static irqreturn_t rps_timer_irq(int irq, void *dev_id)
> +{
> +	struct clock_event_device *evt = dev_id;
> +
> +	iowrite32(0, timer_base + TIMER_CLRINT);
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void rps_timer_config(unsigned long period, unsigned periodic)
> +{
> +	uint32_t cfg = 0;
> +
> +	if (period)
> +		cfg |= TIMER_ENABLE;
> +
> +	if (periodic)
> +		cfg |= TIMER_PERIODIC;
> +
> +	switch (timer_prescaler) {
> +	case 1:
> +		cfg |= TIMER_DIV1;
> +		break;
> +	case 16:
> +		cfg |= TIMER_DIV16;
> +		break;
> +	case 256:
> +		cfg |= TIMER_DIV256;
> +		break;
> +	}

No direct value (1, 16, 256) but macros please.

> +	iowrite32(period, timer_base + TIMER_LOAD);
> +	iowrite32(cfg, timer_base + TIMER_CTRL);
> +}
> +
> +static int rps_timer_shutdown(struct clock_event_device *evt)
> +{
> +	if (!clockevent_state_periodic(evt))
> +		return 0;
> +
> +	rps_timer_config(0, 0);
> +
> +	return 0;
> +}
> +
> +static int rps_timer_set_periodic(struct clock_event_device *evt)
> +{
> +	rps_timer_config(timer_period, 1);
> +
> +	return 0;
> +}
> +
> +static int rps_timer_set_oneshot(struct clock_event_device *evt)
> +{
> +	rps_timer_config(timer_period, 0);
> +
> +	return 0;
> +}
> +
> +static int rps_timer_next_event(unsigned long delta,
> +				struct clock_event_device *evt)
> +{
> +	rps_timer_config(delta, 0);
> +
> +	return 0;
> +}
> +
> +static struct clock_event_device rps_clockevent = {
> +	.name = "rps",
> +	.features = CLOCK_EVT_FEAT_PERIODIC |
> +		    CLOCK_EVT_FEAT_ONESHOT,
> +	.tick_resume = rps_timer_shutdown,
> +	.set_state_shutdown = rps_timer_shutdown,
> +	.set_state_periodic = rps_timer_set_periodic,
> +	.set_state_oneshot = rps_timer_set_oneshot,
> +	.set_next_event = rps_timer_next_event,
> +	.rating = 200,
> +};
> +
> +static void __init rps_clockevent_init(void __iomem *base, ulong ref_rate,
> +				       int irq)
> +{
> +	timer_base = base;
> +
> +	/* Start with prescaler 1 */
> +	timer_prescaler = 1;
> +	timer_period = DIV_ROUND_UP(ref_rate, HZ);
> +
> +	if (timer_period > TIMER_MAX_VAL) {
> +		timer_prescaler = 16;
> +		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);

Using macro and bit shifting will be nicer.

> +	}
> +	if (timer_period > TIMER_MAX_VAL) {
> +		timer_prescaler = 256;
> +		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);
> +	}
> +	rps_clockevent.cpumask = cpu_possible_mask;
> +	rps_clockevent.irq = irq;

So if you are using such cpumask, I suggest you have a look at the 
DYNIRQ flag.

> +	clockevents_config_and_register(&rps_clockevent,
> +					ref_rate / timer_prescaler,
> +					1,
> +					TIMER_MAX_VAL);
> +
> +	pr_info("rps: Registered clock event rate %luHz prescaler %d period %lu\n",
> +			ref_rate,
> +			timer_prescaler,
> +			timer_period);
> +}
> +
> +/* Clocksource */
> +
> +static void __iomem *timer_curr;
> +
> +static u64 notrace rps_read_sched_clock(void)
> +{
> +	return ~readl_relaxed(timer_curr);
> +}
> +
> +static void __init rps_clocksource_init(void __iomem *base, ulong ref_rate)
> +{
> +	int ret;
> +	ulong clock_rate;
> +	/* use prescale 16 */
> +	clock_rate = ref_rate / 16;
> +
> +	iowrite32(TIMER_MAX_VAL, base + TIMER_LOAD);
> +	iowrite32(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16,
> +			base + TIMER_CTRL);
> +
> +	timer_curr = base + TIMER_CURR;
> +	sched_clock_register(rps_read_sched_clock, TIMER_BITS, clock_rate);
> +	ret = clocksource_mmio_init(base + TIMER_CURR, "rps_clocksource_timer",
> +					clock_rate, 250, TIMER_BITS,
> +					clocksource_mmio_readl_down);
> +	if (ret)
> +		panic("can't register clocksource\n");

No panic, just an error.

> +	pr_info("rps: Registered clocksource rate %luHz\n", clock_rate);
> +}
> +
> +static struct irqaction rps_timer_irqaction = {
> +	.name		= "rps_timer",
> +	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
> +	.handler	= rps_timer_irq,
> +	.dev_id		= &rps_clockevent,
> +};
> +
> +static void __init rps_timer_init(struct device_node *np)
> +{
> +	struct clk *refclk;
> +	unsigned long ref_rate;
> +	void __iomem *base;
> +	int irq, ret;
> +
> +	refclk = of_clk_get(np, 0);
> +
> +	if (IS_ERR(refclk) || clk_prepare_enable(refclk))
> +		panic("rps_timer_init: failed to get refclk\n");

no panic.

> +	ref_rate = clk_get_rate(refclk);
> +
> +	base = of_iomap(np, 0);
> +	if (!base)
> +		panic("rps_timer_init: failed to map io\n");
> +
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (irq < 0)
> +		panic("rps_timer_init: failed to parse IRQ\n");

if (!irq)
	no panic.

> +
> +	/* Disable timers */
> +	iowrite32(0, base + TIMER1_OFFSET + TIMER_CTRL);
> +	iowrite32(0, base + TIMER2_OFFSET + TIMER_CTRL);
> +	iowrite32(0, base + TIMER1_OFFSET + TIMER_LOAD);
> +	iowrite32(0, base + TIMER2_OFFSET + TIMER_LOAD);
> +	iowrite32(0, base + TIMER1_OFFSET + TIMER_CLRINT);
> +	iowrite32(0, base + TIMER2_OFFSET + TIMER_CLRINT);
> +
> +	rps_clocksource_init(base + TIMER2_OFFSET, ref_rate);
> +	rps_clockevent_init(base + TIMER1_OFFSET, ref_rate, irq);
> +
> +	ret = setup_irq(irq, &rps_timer_irqaction);

Replace setup_irq by request_irq.

> +	if (ret)
> +		panic("rps_timer_init: failed to request irq\n");
> +}
> +
> +CLOCKSOURCE_OF_DECLARE(nas782x, "plxtech,nas782x-rps-timer", rps_timer_init);


Thanks !

   -- Daniel


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

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

* [PATCH 04/17] clocksource: Add PLX Technology RPS Timer
@ 2016-03-17 16:13     ` Daniel Lezcano
  0 siblings, 0 replies; 208+ messages in thread
From: Daniel Lezcano @ 2016-03-17 16:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Neil,

On 03/03/2016 12:39 PM, Neil Armstrong wrote:
> Add clocksource and clockevent driver from dual RPS timer.

please elaborate the log: describe the timer, how it works, is there a 
pointer to doc, freq, etc ...

> CC: Ma Haijun <mahaijuns@gmail.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>   drivers/clocksource/Kconfig     |   6 +
>   drivers/clocksource/Makefile    |   1 +
>   drivers/clocksource/timer-rps.c | 249 ++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 256 insertions(+)
>   create mode 100644 drivers/clocksource/timer-rps.c
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 33db740..f79bc0f 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -276,6 +276,12 @@ config VF_PIT_TIMER
>   	help
>   	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
>
> +config CLKSRC_RPS_TIMER
> +	bool
> +	select CLKSRC_MMIO
> +	help
> +	  This enables support for the PLX Tech OXNAS RPS timers.
> +

Please check DIGICOLOR_TIMER or DW_APB_TIMER or ROCKCHIP_TIMER or 
ARMADA_370_XP_TIMER or ... config section and try to stick to the same 
pattern.

>   config SYS_SUPPORTS_SH_CMT
>           bool
>
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index dc2b899..120bc09 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
>   obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
>   obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
>   obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
> +obj-$(CONFIG_CLKSRC_RPS_TIMER)	+= timer-rps.o
>
>   obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
>   obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
> diff --git a/drivers/clocksource/timer-rps.c b/drivers/clocksource/timer-rps.c
> new file mode 100644
> index 0000000..79621b8
> --- /dev/null
> +++ b/drivers/clocksource/timer-rps.c
> @@ -0,0 +1,249 @@
> +/*
> + * drivers/clocksource/timer-rps.c
> + *
> + * Copyright (C) 2009 Oxford Semiconductor Ltd
> + * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/io.h>
> +#include <linux/clockchips.h>
> +#include <linux/clk.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/sched_clock.h>
> +
> +/* TIMER1 as tick
> + * TIMER2 as clocksource
> + */

Comment format:

/*
  * TIMER1 used as tick
  * TIMER2 used as clocksource
  */

> +enum {
> +	TIMER_LOAD = 0,
> +	TIMER_CURR = 4,
> +	TIMER_CTRL = 8,
> +	TIMER_CLRINT = 0xC,
> +
> +	TIMER_BITS = 24,
> +
> +	TIMER_MAX_VAL = (1 << TIMER_BITS) - 1,
> +
> +	TIMER_PERIODIC = (1 << 6),
> +	TIMER_ENABLE = (1 << 7),
> +
> +	TIMER_DIV1  = (0 << 2),
> +	TIMER_DIV16  = (1 << 2),
> +	TIMER_DIV256  = (2 << 2),
> +
> +	TIMER1_OFFSET = 0,
> +	TIMER2_OFFSET = 0x20,
> +};

What is the point of having this unorganized enum with duplicate values 
? and why TIMER_DIV1 = (0 << 2) ?

Replace by #define.

> +/* Clockevent */
> +
> +static unsigned long timer_period = HZ;
> +static unsigned timer_prescaler = 1;
> +static void __iomem *timer_base;

Encapsulate these variables into a structure and use container_of.

> +
> +static irqreturn_t rps_timer_irq(int irq, void *dev_id)
> +{
> +	struct clock_event_device *evt = dev_id;
> +
> +	iowrite32(0, timer_base + TIMER_CLRINT);
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void rps_timer_config(unsigned long period, unsigned periodic)
> +{
> +	uint32_t cfg = 0;
> +
> +	if (period)
> +		cfg |= TIMER_ENABLE;
> +
> +	if (periodic)
> +		cfg |= TIMER_PERIODIC;
> +
> +	switch (timer_prescaler) {
> +	case 1:
> +		cfg |= TIMER_DIV1;
> +		break;
> +	case 16:
> +		cfg |= TIMER_DIV16;
> +		break;
> +	case 256:
> +		cfg |= TIMER_DIV256;
> +		break;
> +	}

No direct value (1, 16, 256) but macros please.

> +	iowrite32(period, timer_base + TIMER_LOAD);
> +	iowrite32(cfg, timer_base + TIMER_CTRL);
> +}
> +
> +static int rps_timer_shutdown(struct clock_event_device *evt)
> +{
> +	if (!clockevent_state_periodic(evt))
> +		return 0;
> +
> +	rps_timer_config(0, 0);
> +
> +	return 0;
> +}
> +
> +static int rps_timer_set_periodic(struct clock_event_device *evt)
> +{
> +	rps_timer_config(timer_period, 1);
> +
> +	return 0;
> +}
> +
> +static int rps_timer_set_oneshot(struct clock_event_device *evt)
> +{
> +	rps_timer_config(timer_period, 0);
> +
> +	return 0;
> +}
> +
> +static int rps_timer_next_event(unsigned long delta,
> +				struct clock_event_device *evt)
> +{
> +	rps_timer_config(delta, 0);
> +
> +	return 0;
> +}
> +
> +static struct clock_event_device rps_clockevent = {
> +	.name = "rps",
> +	.features = CLOCK_EVT_FEAT_PERIODIC |
> +		    CLOCK_EVT_FEAT_ONESHOT,
> +	.tick_resume = rps_timer_shutdown,
> +	.set_state_shutdown = rps_timer_shutdown,
> +	.set_state_periodic = rps_timer_set_periodic,
> +	.set_state_oneshot = rps_timer_set_oneshot,
> +	.set_next_event = rps_timer_next_event,
> +	.rating = 200,
> +};
> +
> +static void __init rps_clockevent_init(void __iomem *base, ulong ref_rate,
> +				       int irq)
> +{
> +	timer_base = base;
> +
> +	/* Start with prescaler 1 */
> +	timer_prescaler = 1;
> +	timer_period = DIV_ROUND_UP(ref_rate, HZ);
> +
> +	if (timer_period > TIMER_MAX_VAL) {
> +		timer_prescaler = 16;
> +		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);

Using macro and bit shifting will be nicer.

> +	}
> +	if (timer_period > TIMER_MAX_VAL) {
> +		timer_prescaler = 256;
> +		timer_period = DIV_ROUND_UP(ref_rate / timer_prescaler, HZ);
> +	}
> +	rps_clockevent.cpumask = cpu_possible_mask;
> +	rps_clockevent.irq = irq;

So if you are using such cpumask, I suggest you have a look at the 
DYNIRQ flag.

> +	clockevents_config_and_register(&rps_clockevent,
> +					ref_rate / timer_prescaler,
> +					1,
> +					TIMER_MAX_VAL);
> +
> +	pr_info("rps: Registered clock event rate %luHz prescaler %d period %lu\n",
> +			ref_rate,
> +			timer_prescaler,
> +			timer_period);
> +}
> +
> +/* Clocksource */
> +
> +static void __iomem *timer_curr;
> +
> +static u64 notrace rps_read_sched_clock(void)
> +{
> +	return ~readl_relaxed(timer_curr);
> +}
> +
> +static void __init rps_clocksource_init(void __iomem *base, ulong ref_rate)
> +{
> +	int ret;
> +	ulong clock_rate;
> +	/* use prescale 16 */
> +	clock_rate = ref_rate / 16;
> +
> +	iowrite32(TIMER_MAX_VAL, base + TIMER_LOAD);
> +	iowrite32(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16,
> +			base + TIMER_CTRL);
> +
> +	timer_curr = base + TIMER_CURR;
> +	sched_clock_register(rps_read_sched_clock, TIMER_BITS, clock_rate);
> +	ret = clocksource_mmio_init(base + TIMER_CURR, "rps_clocksource_timer",
> +					clock_rate, 250, TIMER_BITS,
> +					clocksource_mmio_readl_down);
> +	if (ret)
> +		panic("can't register clocksource\n");

No panic, just an error.

> +	pr_info("rps: Registered clocksource rate %luHz\n", clock_rate);
> +}
> +
> +static struct irqaction rps_timer_irqaction = {
> +	.name		= "rps_timer",
> +	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
> +	.handler	= rps_timer_irq,
> +	.dev_id		= &rps_clockevent,
> +};
> +
> +static void __init rps_timer_init(struct device_node *np)
> +{
> +	struct clk *refclk;
> +	unsigned long ref_rate;
> +	void __iomem *base;
> +	int irq, ret;
> +
> +	refclk = of_clk_get(np, 0);
> +
> +	if (IS_ERR(refclk) || clk_prepare_enable(refclk))
> +		panic("rps_timer_init: failed to get refclk\n");

no panic.

> +	ref_rate = clk_get_rate(refclk);
> +
> +	base = of_iomap(np, 0);
> +	if (!base)
> +		panic("rps_timer_init: failed to map io\n");
> +
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (irq < 0)
> +		panic("rps_timer_init: failed to parse IRQ\n");

if (!irq)
	no panic.

> +
> +	/* Disable timers */
> +	iowrite32(0, base + TIMER1_OFFSET + TIMER_CTRL);
> +	iowrite32(0, base + TIMER2_OFFSET + TIMER_CTRL);
> +	iowrite32(0, base + TIMER1_OFFSET + TIMER_LOAD);
> +	iowrite32(0, base + TIMER2_OFFSET + TIMER_LOAD);
> +	iowrite32(0, base + TIMER1_OFFSET + TIMER_CLRINT);
> +	iowrite32(0, base + TIMER2_OFFSET + TIMER_CLRINT);
> +
> +	rps_clocksource_init(base + TIMER2_OFFSET, ref_rate);
> +	rps_clockevent_init(base + TIMER1_OFFSET, ref_rate, irq);
> +
> +	ret = setup_irq(irq, &rps_timer_irqaction);

Replace setup_irq by request_irq.

> +	if (ret)
> +		panic("rps_timer_init: failed to request irq\n");
> +}
> +
> +CLOCKSOURCE_OF_DECLARE(nas782x, "plxtech,nas782x-rps-timer", rps_timer_init);


Thanks !

   -- Daniel


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

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

* Re: [PATCH v2 01/18] clocksource: sp804: Add support for non-32bit width counter
  2016-03-09 10:24     ` Neil Armstrong
@ 2016-03-17 16:40       ` Daniel Lezcano
  -1 siblings, 0 replies; 208+ messages in thread
From: Daniel Lezcano @ 2016-03-17 16:40 UTC (permalink / raw)
  To: Neil Armstrong, linux-kernel, linux-arm-kernel, tglx, rmk+kernel,
	sudeep.holla

On 03/09/2016 11:24 AM, Neil Armstrong wrote:
> Some vendor variants can implement norrower counter width, add
> an optional DT property changing the clocksource width and the
> clockevent mask, but keeping 32bit as default for legacy interface.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>   drivers/clocksource/timer-sp804.c | 38 +++++++++++++++++++++++++++-----------
>   include/clocksource/timer-sp804.h | 11 ++++++-----
>   2 files changed, 33 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
> index 5f45b9a..8acf524 100644
> --- a/drivers/clocksource/timer-sp804.c
> +++ b/drivers/clocksource/timer-sp804.c
> @@ -80,7 +80,8 @@ void __init sp804_timer_disable(void __iomem *base)
>   void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   						     const char *name,
>   						     struct clk *clk,
> -						     int use_sched_clock)
> +						     int use_sched_clock,
> +						     unsigned width)
>   {
>   	long rate;
>
> @@ -93,6 +94,9 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   		}
>   	}
>
> +	if (!width || width > 32)
> +		width = 32;
> +

check comment below in the caller function.

>   	rate = sp804_get_clock_rate(clk);
>
>   	if (rate < 0)
> @@ -106,11 +110,11 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   		base + TIMER_CTRL);
>
>   	clocksource_mmio_init(base + TIMER_VALUE, name,
> -		rate, 200, 32, clocksource_mmio_readl_down);
> +		rate, 200, width, clocksource_mmio_readl_down);
>
>   	if (use_sched_clock) {
>   		sched_clock_base = base;
> -		sched_clock_register(sp804_read, 32, rate);
> +		sched_clock_register(sp804_read, width, rate);
>   	}
>   }
>
> @@ -186,7 +190,9 @@ static struct irqaction sp804_timer_irq = {
>   	.dev_id		= &sp804_clockevent,
>   };
>
> -void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
> +void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq,
> +				     struct clk *clk, const char *name,
> +				     unsigned width)
>   {
>   	struct clock_event_device *evt = &sp804_clockevent;
>   	long rate;
> @@ -199,6 +205,9 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
>   		return;
>   	}
>
> +	if (!width || width > 32)
> +		width = 32;

Check comment below in the caller function.

>   	rate = sp804_get_clock_rate(clk);
>   	if (rate < 0)
>   		return;
> @@ -212,7 +221,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
>   	writel(0, base + TIMER_CTRL);
>
>   	setup_irq(irq, &sp804_timer_irq);
> -	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
> +	clockevents_config_and_register(evt, rate, 0xf, GENMASK(width-1, 0));

This GENMASK is strange here. Nothing else than this ?

>   }
>
>   static void __init sp804_of_init(struct device_node *np)
> @@ -223,6 +232,7 @@ static void __init sp804_of_init(struct device_node *np)
>   	u32 irq_num = 0;
>   	struct clk *clk1, *clk2;
>   	const char *name = of_get_property(np, "compatible", NULL);
> +	u32 width = 32;
>
>   	base = of_iomap(np, 0);
>   	if (WARN_ON(!base))
> @@ -254,14 +264,19 @@ static void __init sp804_of_init(struct device_node *np)
>   	if (irq <= 0)
>   		goto err;
>
> +	/* Some vendor variants can have a different counter width */
> +	of_property_read_u32(np, "arm,timer-width", &width);
> +

Better to do the sanity check when the value is read.

Here, you can default to 32 if the width is 0 instead of initializing to 
32 then read the property and call __sp804_clockevents_init which in 
turn check zero or more and set it to 32 again.

>   	of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
>   	if (irq_num == 2) {
> -		__sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
> -		__sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
> +		__sp804_clockevents_init(base + TIMER_2_BASE, irq,
> +					 clk2, name, width);
> +		__sp804_clocksource_and_sched_clock_init(base, name,
> +							 clk1, 1, width);
>   	} else {
> -		__sp804_clockevents_init(base, irq, clk1 , name);
> +		__sp804_clockevents_init(base, irq, clk1, name, width);
>   		__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
> -							 name, clk2, 1);
> +							 name, clk2, 1, width);
>   	}
>   	initialized = true;
>
> @@ -293,13 +308,14 @@ static void __init integrator_cp_of_init(struct device_node *np)
>   		goto err;
>
>   	if (!init_count)
> -		__sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
> +		__sp804_clocksource_and_sched_clock_init(base, name,
> +							 clk, 0, 32);
>   	else {
>   		irq = irq_of_parse_and_map(np, 0);
>   		if (irq <= 0)
>   			goto err;
>
> -		__sp804_clockevents_init(base, irq, clk, name);
> +		__sp804_clockevents_init(base, irq, clk, name, 32);
>   	}
>
>   	init_count++;
> diff --git a/include/clocksource/timer-sp804.h b/include/clocksource/timer-sp804.h
> index 1f8a1ca..ad71fcb 100644
> --- a/include/clocksource/timer-sp804.h
> +++ b/include/clocksource/timer-sp804.h
> @@ -4,25 +4,26 @@
>   struct clk;
>
>   void __sp804_clocksource_and_sched_clock_init(void __iomem *,
> -					      const char *, struct clk *, int);
> +					      const char *, struct clk *,
> +					      int, unsigned);
>   void __sp804_clockevents_init(void __iomem *, unsigned int,
> -			      struct clk *, const char *);
> +			      struct clk *, const char *, unsigned);
>   void sp804_timer_disable(void __iomem *);
>
>   static inline void sp804_clocksource_init(void __iomem *base, const char *name)
>   {
> -	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0);
> +	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0, 32);
>   }
>
>   static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   							  const char *name)
>   {
> -	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1);
> +	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1, 32);
>   }
>
>   static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name)
>   {
> -	__sp804_clockevents_init(base, irq, NULL, name);
> +	__sp804_clockevents_init(base, irq, NULL, name, 32);
>
>   }
>   #endif
>


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

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

* [PATCH v2 01/18] clocksource: sp804: Add support for non-32bit width counter
@ 2016-03-17 16:40       ` Daniel Lezcano
  0 siblings, 0 replies; 208+ messages in thread
From: Daniel Lezcano @ 2016-03-17 16:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/09/2016 11:24 AM, Neil Armstrong wrote:
> Some vendor variants can implement norrower counter width, add
> an optional DT property changing the clocksource width and the
> clockevent mask, but keeping 32bit as default for legacy interface.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>   drivers/clocksource/timer-sp804.c | 38 +++++++++++++++++++++++++++-----------
>   include/clocksource/timer-sp804.h | 11 ++++++-----
>   2 files changed, 33 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
> index 5f45b9a..8acf524 100644
> --- a/drivers/clocksource/timer-sp804.c
> +++ b/drivers/clocksource/timer-sp804.c
> @@ -80,7 +80,8 @@ void __init sp804_timer_disable(void __iomem *base)
>   void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   						     const char *name,
>   						     struct clk *clk,
> -						     int use_sched_clock)
> +						     int use_sched_clock,
> +						     unsigned width)
>   {
>   	long rate;
>
> @@ -93,6 +94,9 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   		}
>   	}
>
> +	if (!width || width > 32)
> +		width = 32;
> +

check comment below in the caller function.

>   	rate = sp804_get_clock_rate(clk);
>
>   	if (rate < 0)
> @@ -106,11 +110,11 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   		base + TIMER_CTRL);
>
>   	clocksource_mmio_init(base + TIMER_VALUE, name,
> -		rate, 200, 32, clocksource_mmio_readl_down);
> +		rate, 200, width, clocksource_mmio_readl_down);
>
>   	if (use_sched_clock) {
>   		sched_clock_base = base;
> -		sched_clock_register(sp804_read, 32, rate);
> +		sched_clock_register(sp804_read, width, rate);
>   	}
>   }
>
> @@ -186,7 +190,9 @@ static struct irqaction sp804_timer_irq = {
>   	.dev_id		= &sp804_clockevent,
>   };
>
> -void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
> +void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq,
> +				     struct clk *clk, const char *name,
> +				     unsigned width)
>   {
>   	struct clock_event_device *evt = &sp804_clockevent;
>   	long rate;
> @@ -199,6 +205,9 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
>   		return;
>   	}
>
> +	if (!width || width > 32)
> +		width = 32;

Check comment below in the caller function.

>   	rate = sp804_get_clock_rate(clk);
>   	if (rate < 0)
>   		return;
> @@ -212,7 +221,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
>   	writel(0, base + TIMER_CTRL);
>
>   	setup_irq(irq, &sp804_timer_irq);
> -	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
> +	clockevents_config_and_register(evt, rate, 0xf, GENMASK(width-1, 0));

This GENMASK is strange here. Nothing else than this ?

>   }
>
>   static void __init sp804_of_init(struct device_node *np)
> @@ -223,6 +232,7 @@ static void __init sp804_of_init(struct device_node *np)
>   	u32 irq_num = 0;
>   	struct clk *clk1, *clk2;
>   	const char *name = of_get_property(np, "compatible", NULL);
> +	u32 width = 32;
>
>   	base = of_iomap(np, 0);
>   	if (WARN_ON(!base))
> @@ -254,14 +264,19 @@ static void __init sp804_of_init(struct device_node *np)
>   	if (irq <= 0)
>   		goto err;
>
> +	/* Some vendor variants can have a different counter width */
> +	of_property_read_u32(np, "arm,timer-width", &width);
> +

Better to do the sanity check when the value is read.

Here, you can default to 32 if the width is 0 instead of initializing to 
32 then read the property and call __sp804_clockevents_init which in 
turn check zero or more and set it to 32 again.

>   	of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
>   	if (irq_num == 2) {
> -		__sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
> -		__sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
> +		__sp804_clockevents_init(base + TIMER_2_BASE, irq,
> +					 clk2, name, width);
> +		__sp804_clocksource_and_sched_clock_init(base, name,
> +							 clk1, 1, width);
>   	} else {
> -		__sp804_clockevents_init(base, irq, clk1 , name);
> +		__sp804_clockevents_init(base, irq, clk1, name, width);
>   		__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
> -							 name, clk2, 1);
> +							 name, clk2, 1, width);
>   	}
>   	initialized = true;
>
> @@ -293,13 +308,14 @@ static void __init integrator_cp_of_init(struct device_node *np)
>   		goto err;
>
>   	if (!init_count)
> -		__sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
> +		__sp804_clocksource_and_sched_clock_init(base, name,
> +							 clk, 0, 32);
>   	else {
>   		irq = irq_of_parse_and_map(np, 0);
>   		if (irq <= 0)
>   			goto err;
>
> -		__sp804_clockevents_init(base, irq, clk, name);
> +		__sp804_clockevents_init(base, irq, clk, name, 32);
>   	}
>
>   	init_count++;
> diff --git a/include/clocksource/timer-sp804.h b/include/clocksource/timer-sp804.h
> index 1f8a1ca..ad71fcb 100644
> --- a/include/clocksource/timer-sp804.h
> +++ b/include/clocksource/timer-sp804.h
> @@ -4,25 +4,26 @@
>   struct clk;
>
>   void __sp804_clocksource_and_sched_clock_init(void __iomem *,
> -					      const char *, struct clk *, int);
> +					      const char *, struct clk *,
> +					      int, unsigned);
>   void __sp804_clockevents_init(void __iomem *, unsigned int,
> -			      struct clk *, const char *);
> +			      struct clk *, const char *, unsigned);
>   void sp804_timer_disable(void __iomem *);
>
>   static inline void sp804_clocksource_init(void __iomem *base, const char *name)
>   {
> -	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0);
> +	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0, 32);
>   }
>
>   static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   							  const char *name)
>   {
> -	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1);
> +	__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1, 32);
>   }
>
>   static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name)
>   {
> -	__sp804_clockevents_init(base, irq, NULL, name);
> +	__sp804_clockevents_init(base, irq, NULL, name, 32);
>
>   }
>   #endif
>


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 17:09       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:09 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, daniel.lezcano, tglx, rmk+kernel,
	sudeep.holla, devicetree

On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
> Add timer-width optional property to specify a different vendor
> specific timer counter bit-width.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> index 5cd8eee7..141e143 100644
> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> @@ -17,6 +17,8 @@ Optional properties:
>  - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
>  	specifies if the irq connection is for timer 1 or timer 2. A value of 1
>  	or 2 should be used.
> +- arm,timer-width: Should contain the width in number of bits of the counter,
> +	is considered by default 32 but can be changed for vendor variants.

That would not be an SP804 nor would the vendor be ARM in that case. So 
add a new compatible string for the vendor that decided to hack up ARM's 
IP block.

Rob

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 17:09       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:09 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
	tglx-hfZtesqFncYOwBW4kG4KsQ, rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ,
	sudeep.holla-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA

On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
> Add timer-width optional property to specify a different vendor
> specific timer counter bit-width.
> 
> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> index 5cd8eee7..141e143 100644
> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> @@ -17,6 +17,8 @@ Optional properties:
>  - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
>  	specifies if the irq connection is for timer 1 or timer 2. A value of 1
>  	or 2 should be used.
> +- arm,timer-width: Should contain the width in number of bits of the counter,
> +	is considered by default 32 but can be changed for vendor variants.

That would not be an SP804 nor would the vendor be ARM in that case. So 
add a new compatible string for the vendor that decided to hack up ARM's 
IP block.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 17:09       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
> Add timer-width optional property to specify a different vendor
> specific timer counter bit-width.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> index 5cd8eee7..141e143 100644
> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> @@ -17,6 +17,8 @@ Optional properties:
>  - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
>  	specifies if the irq connection is for timer 1 or timer 2. A value of 1
>  	or 2 should be used.
> +- arm,timer-width: Should contain the width in number of bits of the counter,
> +	is considered by default 32 but can be changed for vendor variants.

That would not be an SP804 nor would the vendor be ARM in that case. So 
add a new compatible string for the vendor that decided to hack up ARM's 
IP block.

Rob

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

* Re: [PATCH v2 04/18] dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible string
@ 2016-03-17 17:15       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:15 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, tglx, jason, marc.zyngier, devicetree

On Wed, Mar 09, 2016 at 11:24:06AM +0100, Neil Armstrong wrote:
> Under the OX810SE, this same controller is used as "Reference Peripheral
> Specification" Interrupt Controller, so add new compatible string.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> index c9cf605..2fe78d5 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> @@ -6,7 +6,7 @@ controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
>  instance can handle up to 32 interrupts.
>  
>  Required properties:
> -- compatible: "arm,versatile-fpga-irq"
> +- compatible: "arm,versatile-fpga-irq" or "arm,rps-irq"

Use a compatible string that reflects the actual implementation not a 
spec. The current string is a bad example as it already refers to 
multiple implementations.

Rob

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

* Re: [PATCH v2 04/18] dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible string
@ 2016-03-17 17:15       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:15 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	tglx-hfZtesqFncYOwBW4kG4KsQ, jason-NLaQJdtUoK4Be96aLqz0jA,
	marc.zyngier-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA

On Wed, Mar 09, 2016 at 11:24:06AM +0100, Neil Armstrong wrote:
> Under the OX810SE, this same controller is used as "Reference Peripheral
> Specification" Interrupt Controller, so add new compatible string.
> 
> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> ---
>  .../devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> index c9cf605..2fe78d5 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> @@ -6,7 +6,7 @@ controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
>  instance can handle up to 32 interrupts.
>  
>  Required properties:
> -- compatible: "arm,versatile-fpga-irq"
> +- compatible: "arm,versatile-fpga-irq" or "arm,rps-irq"

Use a compatible string that reflects the actual implementation not a 
spec. The current string is a bad example as it already refers to 
multiple implementations.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 04/18] dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible string
@ 2016-03-17 17:15       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:06AM +0100, Neil Armstrong wrote:
> Under the OX810SE, this same controller is used as "Reference Peripheral
> Specification" Interrupt Controller, so add new compatible string.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> index c9cf605..2fe78d5 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
> @@ -6,7 +6,7 @@ controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
>  instance can handle up to 32 interrupts.
>  
>  Required properties:
> -- compatible: "arm,versatile-fpga-irq"
> +- compatible: "arm,versatile-fpga-irq" or "arm,rps-irq"

Use a compatible string that reflects the actual implementation not a 
spec. The current string is a bad example as it already refers to 
multiple implementations.

Rob

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

* Re: [PATCH v2 05/18] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-17 17:15       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:15 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Wed, Mar 09, 2016 at 11:24:07AM +0100, Neil Armstrong wrote:
> Add PLX Technology vendor prefix.
> Fixed "pixdir" alphabetizing.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 05/18] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-17 17:15       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:15 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Wed, Mar 09, 2016 at 11:24:07AM +0100, Neil Armstrong wrote:
> Add PLX Technology vendor prefix.
> Fixed "pixdir" alphabetizing.
> 
> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 05/18] dt-bindings: vendor-prefixes: Add PLX Technology
@ 2016-03-17 17:15       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:07AM +0100, Neil Armstrong wrote:
> Add PLX Technology vendor prefix.
> Fixed "pixdir" alphabetizing.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 06/18] dt-bindings: Add Oxford Semiconductors to vendor prefixes
  2016-03-09 10:24     ` Neil Armstrong
@ 2016-03-17 17:16       ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:16 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Wed, Mar 09, 2016 at 11:24:08AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Rob Herring <robh@kernel.org>

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

* [PATCH v2 06/18] dt-bindings: Add Oxford Semiconductors to vendor prefixes
@ 2016-03-17 17:16       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:08AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 08/18] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-17 17:18       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:18 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, p.zabel, devicetree

On Wed, Mar 09, 2016 at 11:24:10AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/reset/plxtech,reset.txt    | 58 ++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 08/18] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-17 17:18       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:18 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Wed, Mar 09, 2016 at 11:24:10AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> ---
>  .../devicetree/bindings/reset/plxtech,reset.txt    | 58 ++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 08/18] dt-bindings: Add PLX Technology Reset Controller bindings
@ 2016-03-17 17:18       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:10AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/reset/plxtech,reset.txt    | 58 ++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/plxtech,reset.txt

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 10/18] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
  2016-03-09 10:24     ` Neil Armstrong
@ 2016-03-17 17:19       ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:19 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, linux-clk, devicetree

On Wed, Mar 09, 2016 at 11:24:12AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/clock/plxtech,stdclk.txt   | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt

Acked-by: Rob Herring <robh@kernel.org>

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

* [PATCH v2 10/18] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings
@ 2016-03-17 17:19       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:12AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/clock/plxtech,stdclk.txt   | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/plxtech,stdclk.txt

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 12/18] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
  2016-03-09 10:24     ` Neil Armstrong
@ 2016-03-17 17:25       ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:25 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel, linux-arm-kernel, linus.walleij, linux-gpio, devicetree

On Wed, Mar 09, 2016 at 11:24:14AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/gpio/gpio_oxnas.txt        |  27 ++++++
>  .../bindings/pinctrl/plxtech,pinctrl.txt           | 100 +++++++++++++++++++++
>  2 files changed, 127 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
> 
> diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
> new file mode 100644
> index 0000000..cbb03c4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
> @@ -0,0 +1,27 @@
> +PLX Technology OXNAS SoC GPIO Controller
> +==========================================
> +
> +Required properties:
> +- compatible: "oxsemi,ox810se-gpio".
> +- reg: Should contain GPIO controller registers location and length
> +- interrupts: Should be the port interrupt shared by all the pins.
> +- #gpio-cells: Should be two.  The first cell is the pin number and
> +  the second cell is used to specify optional parameters (currently
> +  unused).
> +- gpio-controller: Marks the device node as a GPIO controller.
> +
> +optional properties:
> +- #gpio-lines: Number of gpio if absent 32.
> +
> +
> +Example:
> +	gpio0: gpio@000000 {

Drop the leading 0s.

> +		compatible = "oxsemi,ox810se-gpio";
> +		reg = <0x000000 0x100000>;
> +		interrupts = <21>;
> +		#gpio-cells = <2>;
> +		gpio-controller;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		#gpio-lines = <32>;
> +	};
> diff --git a/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
> new file mode 100644
> index 0000000..0c5051a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
> @@ -0,0 +1,100 @@
> +PLX Technology OXNAS SoC Pinmux Controller
> +==========================================
> +
> +The OXNAS Pinmux Controller, enables the IC to share one PAD to several
> +functional blocks. The sharing is done by multiplexing the PAD input/output
> +signals. For each PAD there are up to 8 muxing options (called periph modes).
> +Since different modules require different PAD settings
> +(like pull up, keeper, etc) the contoller controls also the PAD settings
> +parameters.
> +
> +Please refer to pinctrl-bindings.txt in this directory for details of the
> +common pinctrl bindings used by client devices, including the meaning of the
> +phrase "pin configuration node".
> +
> +OXNAS pin configuration node is a node of a group of pins which can be
> +used for a specific device or function. This node represents both mux and config
> +of the pins in that group. The 'pins' selects the function mode(also named pin
> +mode) this pin can work on and the 'config' configures various pad settings
> +such as pull-up, multi drive, etc.
> +
> +Required properties for iomux controller:
> +- compatible: "oxsemi,ox810se-pinctrl"
> +- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
> +  configured in this periph mode. All the periph and bank need to be describe.
> +- plxtech,sys-ctrl: a phandle to the system controller syscon node
> +
> +How to create such array:
> +
> +Each column will represent the possible peripheral of the pinctrl
> +Each line will represent a pio bank
> +
> +For example :
> +Peripheral: 2 ( A and B)
> +Bank: 2 (A, B and C)
> +=>
> +
> +  /*    A         B     */
> +  0xffffffff 0xffc00c3b  /* pioA */
> +  0xffffffff 0x7fff3ccf  /* pioB */
> +
> +For each peripheral/bank we will descibe in a u32 if a pin can be
> +configured in it by putting 1 to the pin bit (1 << pin)
> +
> +Required properties for pin configuration node:
> +- plxtech,pins: 4 integers array, represents a group of pins mux and config
> +  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
> +  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
> +  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
> +
> +Bits used for CONFIG:
> + - None Yet
> +
> +Examples:
> +
> +pinctrl: pinctrl {
> +	compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +	ranges;
> +
> +	/* Regmap for sys registers */
> +	plxtech,sys-ctrl = <&sys>;
> +
> +	/* Default, all-open mux-map */
> +	plxtech,mux-mask = <
> +		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
> +		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
> +		 >;
> +
> +	uart0 {
> +		pinctrl_uart0: uart0 {
> +			plxtech,pins = <0 31 3 0
> +					0 32 3 0>;
> +		};
> +		pinctrl_uart0_modem: uart0_modem {
> +			plxtech,pins = <0 27 3 0
> +					0 28 3 0
> +					0 29 3 0
> +					0 30 3 0
> +					0 33 3 0
> +					0 34 3 0>;
> +		};
> +	};
> +};
> +
> +uart0: uart@200000 {

serial@200000

With those changes:

Acked-by: Rob Herring <robh@kernel.org>

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

* [PATCH v2 12/18] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings
@ 2016-03-17 17:25       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:14AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  .../devicetree/bindings/gpio/gpio_oxnas.txt        |  27 ++++++
>  .../bindings/pinctrl/plxtech,pinctrl.txt           | 100 +++++++++++++++++++++
>  2 files changed, 127 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
> 
> diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
> new file mode 100644
> index 0000000..cbb03c4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
> @@ -0,0 +1,27 @@
> +PLX Technology OXNAS SoC GPIO Controller
> +==========================================
> +
> +Required properties:
> +- compatible: "oxsemi,ox810se-gpio".
> +- reg: Should contain GPIO controller registers location and length
> +- interrupts: Should be the port interrupt shared by all the pins.
> +- #gpio-cells: Should be two.  The first cell is the pin number and
> +  the second cell is used to specify optional parameters (currently
> +  unused).
> +- gpio-controller: Marks the device node as a GPIO controller.
> +
> +optional properties:
> +- #gpio-lines: Number of gpio if absent 32.
> +
> +
> +Example:
> +	gpio0: gpio at 000000 {

Drop the leading 0s.

> +		compatible = "oxsemi,ox810se-gpio";
> +		reg = <0x000000 0x100000>;
> +		interrupts = <21>;
> +		#gpio-cells = <2>;
> +		gpio-controller;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +		#gpio-lines = <32>;
> +	};
> diff --git a/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
> new file mode 100644
> index 0000000..0c5051a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/plxtech,pinctrl.txt
> @@ -0,0 +1,100 @@
> +PLX Technology OXNAS SoC Pinmux Controller
> +==========================================
> +
> +The OXNAS Pinmux Controller, enables the IC to share one PAD to several
> +functional blocks. The sharing is done by multiplexing the PAD input/output
> +signals. For each PAD there are up to 8 muxing options (called periph modes).
> +Since different modules require different PAD settings
> +(like pull up, keeper, etc) the contoller controls also the PAD settings
> +parameters.
> +
> +Please refer to pinctrl-bindings.txt in this directory for details of the
> +common pinctrl bindings used by client devices, including the meaning of the
> +phrase "pin configuration node".
> +
> +OXNAS pin configuration node is a node of a group of pins which can be
> +used for a specific device or function. This node represents both mux and config
> +of the pins in that group. The 'pins' selects the function mode(also named pin
> +mode) this pin can work on and the 'config' configures various pad settings
> +such as pull-up, multi drive, etc.
> +
> +Required properties for iomux controller:
> +- compatible: "oxsemi,ox810se-pinctrl"
> +- plxtech,mux-mask: array of mask (periph per bank) to describe if a pin can be
> +  configured in this periph mode. All the periph and bank need to be describe.
> +- plxtech,sys-ctrl: a phandle to the system controller syscon node
> +
> +How to create such array:
> +
> +Each column will represent the possible peripheral of the pinctrl
> +Each line will represent a pio bank
> +
> +For example :
> +Peripheral: 2 ( A and B)
> +Bank: 2 (A, B and C)
> +=>
> +
> +  /*    A         B     */
> +  0xffffffff 0xffc00c3b  /* pioA */
> +  0xffffffff 0x7fff3ccf  /* pioB */
> +
> +For each peripheral/bank we will descibe in a u32 if a pin can be
> +configured in it by putting 1 to the pin bit (1 << pin)
> +
> +Required properties for pin configuration node:
> +- plxtech,pins: 4 integers array, represents a group of pins mux and config
> +  setting. The format is plxtech,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
> +  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
> +  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
> +
> +Bits used for CONFIG:
> + - None Yet
> +
> +Examples:
> +
> +pinctrl: pinctrl {
> +	compatible = "oxsemi,ox810se-pinctrl", "simple-bus";
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +	ranges;
> +
> +	/* Regmap for sys registers */
> +	plxtech,sys-ctrl = <&sys>;
> +
> +	/* Default, all-open mux-map */
> +	plxtech,mux-mask = <
> +		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
> +		 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
> +		 >;
> +
> +	uart0 {
> +		pinctrl_uart0: uart0 {
> +			plxtech,pins = <0 31 3 0
> +					0 32 3 0>;
> +		};
> +		pinctrl_uart0_modem: uart0_modem {
> +			plxtech,pins = <0 27 3 0
> +					0 28 3 0
> +					0 29 3 0
> +					0 30 3 0
> +					0 33 3 0
> +					0 34 3 0>;
> +		};
> +	};
> +};
> +
> +uart0: uart at 200000 {

serial at 200000

With those changes:

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
@ 2016-03-17 17:27       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:27 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: linux-kernel, linux-arm-kernel, devicetree

On Wed, Mar 09, 2016 at 11:24:18AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
>  1 file changed, 9 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
> new file mode 100644
> index 0000000..f6032d2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/oxnas.txt
> @@ -0,0 +1,9 @@
> +PLX Technology OXNAS SoCs Family device tree bindings
> +-------------------------------------------
> +
> +Boards with the OX810SE Soc SoC shall have the following properties:

s/Soc SoC/SoC/

> +  Required root node property:
> +    compatible: "oxsemi,ox810se"
> +
> +Board compatible values:
> +  - "wd,mbwe" (OX810SE)

Seems kind of generic. Only one version?

> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
@ 2016-03-17 17:27       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:27 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Wed, Mar 09, 2016 at 11:24:18AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
>  1 file changed, 9 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
> new file mode 100644
> index 0000000..f6032d2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/oxnas.txt
> @@ -0,0 +1,9 @@
> +PLX Technology OXNAS SoCs Family device tree bindings
> +-------------------------------------------
> +
> +Boards with the OX810SE Soc SoC shall have the following properties:

s/Soc SoC/SoC/

> +  Required root node property:
> +    compatible: "oxsemi,ox810se"
> +
> +Board compatible values:
> +  - "wd,mbwe" (OX810SE)

Seems kind of generic. Only one version?

> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
@ 2016-03-17 17:27       ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 17:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 09, 2016 at 11:24:18AM +0100, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
>  1 file changed, 9 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
> new file mode 100644
> index 0000000..f6032d2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/oxnas.txt
> @@ -0,0 +1,9 @@
> +PLX Technology OXNAS SoCs Family device tree bindings
> +-------------------------------------------
> +
> +Boards with the OX810SE Soc SoC shall have the following properties:

s/Soc SoC/SoC/

> +  Required root node property:
> +    compatible: "oxsemi,ox810se"
> +
> +Board compatible values:
> +  - "wd,mbwe" (OX810SE)

Seems kind of generic. Only one version?

> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
  2016-03-17 17:09       ` Rob Herring
@ 2016-03-17 18:06         ` Robin Murphy
  -1 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-17 18:06 UTC (permalink / raw)
  To: Rob Herring, Neil Armstrong
  Cc: devicetree, daniel.lezcano, linux-kernel, sudeep.holla,
	rmk+kernel, tglx, linux-arm-kernel

Hi Rob,

On 17/03/16 17:09, Rob Herring wrote:
> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>> Add timer-width optional property to specify a different vendor
>> specific timer counter bit-width.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>>   Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>> index 5cd8eee7..141e143 100644
>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>> @@ -17,6 +17,8 @@ Optional properties:
>>   - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
>>   	specifies if the irq connection is for timer 1 or timer 2. A value of 1
>>   	or 2 should be used.
>> +- arm,timer-width: Should contain the width in number of bits of the counter,
>> +	is considered by default 32 but can be changed for vendor variants.
>
> That would not be an SP804 nor would the vendor be ARM in that case. So
> add a new compatible string for the vendor that decided to hack up ARM's
> IP block.

By all accounts this is some ancient reference design[1] which later 
evolved _into_ the SP804, so that vendor would probably still be ARM ;)

A separate compatible string would indeed make more sense, though. Both 
semantically and in terms of letting the driver account for the 
differences automatically.

Robin.

[1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html

>
> Rob
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 18:06         ` Robin Murphy
  0 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-17 18:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

On 17/03/16 17:09, Rob Herring wrote:
> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>> Add timer-width optional property to specify a different vendor
>> specific timer counter bit-width.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>>   Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>> index 5cd8eee7..141e143 100644
>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>> @@ -17,6 +17,8 @@ Optional properties:
>>   - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
>>   	specifies if the irq connection is for timer 1 or timer 2. A value of 1
>>   	or 2 should be used.
>> +- arm,timer-width: Should contain the width in number of bits of the counter,
>> +	is considered by default 32 but can be changed for vendor variants.
>
> That would not be an SP804 nor would the vendor be ARM in that case. So
> add a new compatible string for the vendor that decided to hack up ARM's
> IP block.

By all accounts this is some ancient reference design[1] which later 
evolved _into_ the SP804, so that vendor would probably still be ARM ;)

A separate compatible string would indeed make more sense, though. Both 
semantically and in terms of letting the driver account for the 
differences automatically.

Robin.

[1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html

>
> Rob
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
  2016-03-17 18:06         ` Robin Murphy
  (?)
@ 2016-03-17 19:00           ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 19:00 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Neil Armstrong, devicetree, Daniel Lezcano, linux-kernel,
	Sudeep Holla, Russell King, Thomas Gleixner, linux-arm-kernel

On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Rob,
>
> On 17/03/16 17:09, Rob Herring wrote:
>>
>> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>>>
>>> Add timer-width optional property to specify a different vendor
>>> specific timer counter bit-width.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>> ---
>>>   Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>>   1 file changed, 2 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> index 5cd8eee7..141e143 100644
>>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> @@ -17,6 +17,8 @@ Optional properties:
>>>   - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line
>>> connected, this
>>>         specifies if the irq connection is for timer 1 or timer 2. A
>>> value of 1
>>>         or 2 should be used.
>>> +- arm,timer-width: Should contain the width in number of bits of the
>>> counter,
>>> +       is considered by default 32 but can be changed for vendor
>>> variants.
>>
>>
>> That would not be an SP804 nor would the vendor be ARM in that case. So
>> add a new compatible string for the vendor that decided to hack up ARM's
>> IP block.
>
>
> By all accounts this is some ancient reference design[1] which later evolved
> _into_ the SP804, so that vendor would probably still be ARM ;)

Right.

> A separate compatible string would indeed make more sense, though. Both
> semantically and in terms of letting the driver account for the differences
> automatically.
>
> Robin.
>
> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html

Humm, same as integrator timers perhaps?

Rob

>
>>
>> Rob
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 19:00           ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 19:00 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Neil Armstrong, devicetree, Daniel Lezcano, linux-kernel,
	Sudeep Holla, Russell King, Thomas Gleixner, linux-arm-kernel

On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Rob,
>
> On 17/03/16 17:09, Rob Herring wrote:
>>
>> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>>>
>>> Add timer-width optional property to specify a different vendor
>>> specific timer counter bit-width.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>> ---
>>>   Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>>   1 file changed, 2 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> index 5cd8eee7..141e143 100644
>>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> @@ -17,6 +17,8 @@ Optional properties:
>>>   - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line
>>> connected, this
>>>         specifies if the irq connection is for timer 1 or timer 2. A
>>> value of 1
>>>         or 2 should be used.
>>> +- arm,timer-width: Should contain the width in number of bits of the
>>> counter,
>>> +       is considered by default 32 but can be changed for vendor
>>> variants.
>>
>>
>> That would not be an SP804 nor would the vendor be ARM in that case. So
>> add a new compatible string for the vendor that decided to hack up ARM's
>> IP block.
>
>
> By all accounts this is some ancient reference design[1] which later evolved
> _into_ the SP804, so that vendor would probably still be ARM ;)

Right.

> A separate compatible string would indeed make more sense, though. Both
> semantically and in terms of letting the driver account for the differences
> automatically.
>
> Robin.
>
> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html

Humm, same as integrator timers perhaps?

Rob

>
>>
>> Rob
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 19:00           ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2016-03-17 19:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Rob,
>
> On 17/03/16 17:09, Rob Herring wrote:
>>
>> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>>>
>>> Add timer-width optional property to specify a different vendor
>>> specific timer counter bit-width.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>> ---
>>>   Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>>   1 file changed, 2 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> index 5cd8eee7..141e143 100644
>>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>> @@ -17,6 +17,8 @@ Optional properties:
>>>   - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line
>>> connected, this
>>>         specifies if the irq connection is for timer 1 or timer 2. A
>>> value of 1
>>>         or 2 should be used.
>>> +- arm,timer-width: Should contain the width in number of bits of the
>>> counter,
>>> +       is considered by default 32 but can be changed for vendor
>>> variants.
>>
>>
>> That would not be an SP804 nor would the vendor be ARM in that case. So
>> add a new compatible string for the vendor that decided to hack up ARM's
>> IP block.
>
>
> By all accounts this is some ancient reference design[1] which later evolved
> _into_ the SP804, so that vendor would probably still be ARM ;)

Right.

> A separate compatible string would indeed make more sense, though. Both
> semantically and in terms of letting the driver account for the differences
> automatically.
>
> Robin.
>
> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html

Humm, same as integrator timers perhaps?

Rob

>
>>
>> Rob
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 19:21             ` Robin Murphy
  0 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-17 19:21 UTC (permalink / raw)
  To: Rob Herring
  Cc: Neil Armstrong, devicetree, Daniel Lezcano, linux-kernel,
	Sudeep Holla, Russell King, Thomas Gleixner, linux-arm-kernel

On 17/03/16 19:00, Rob Herring wrote:
> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>> Hi Rob,
>>
>> On 17/03/16 17:09, Rob Herring wrote:
>>>
>>> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>>>>
>>>> Add timer-width optional property to specify a different vendor
>>>> specific timer counter bit-width.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>>> ---
>>>>    Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>>>    1 file changed, 2 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> index 5cd8eee7..141e143 100644
>>>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> @@ -17,6 +17,8 @@ Optional properties:
>>>>    - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line
>>>> connected, this
>>>>          specifies if the irq connection is for timer 1 or timer 2. A
>>>> value of 1
>>>>          or 2 should be used.
>>>> +- arm,timer-width: Should contain the width in number of bits of the
>>>> counter,
>>>> +       is considered by default 32 but can be changed for vendor
>>>> variants.
>>>
>>>
>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>> add a new compatible string for the vendor that decided to hack up ARM's
>>> IP block.
>>
>>
>> By all accounts this is some ancient reference design[1] which later evolved
>> _into_ the SP804, so that vendor would probably still be ARM ;)
>
> Right.
>
>> A separate compatible string would indeed make more sense, though. Both
>> semantically and in terms of letting the driver account for the differences
>> automatically.
>>
>> Robin.
>>
>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>
> Humm, same as integrator timers perhaps?

Having had a quick look, what the Integrator/AP manual describes 
certainly smells like the same basic block as the "AMBA Timer" - 16 bit 
counters and the same control register layout - albeit in a mutant 
triple-timer version with a bigger offset between each register set. 
Integrator/CP, on the other hand, looks much more SP804-like.

Robin.

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 19:21             ` Robin Murphy
  0 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-17 19:21 UTC (permalink / raw)
  To: Rob Herring
  Cc: Neil Armstrong, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Daniel Lezcano, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Sudeep Holla, Russell King, Thomas Gleixner,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 17/03/16 19:00, Rob Herring wrote:
> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> wrote:
>> Hi Rob,
>>
>> On 17/03/16 17:09, Rob Herring wrote:
>>>
>>> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>>>>
>>>> Add timer-width optional property to specify a different vendor
>>>> specific timer counter bit-width.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
>>>> ---
>>>>    Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>>>    1 file changed, 2 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> index 5cd8eee7..141e143 100644
>>>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> @@ -17,6 +17,8 @@ Optional properties:
>>>>    - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line
>>>> connected, this
>>>>          specifies if the irq connection is for timer 1 or timer 2. A
>>>> value of 1
>>>>          or 2 should be used.
>>>> +- arm,timer-width: Should contain the width in number of bits of the
>>>> counter,
>>>> +       is considered by default 32 but can be changed for vendor
>>>> variants.
>>>
>>>
>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>> add a new compatible string for the vendor that decided to hack up ARM's
>>> IP block.
>>
>>
>> By all accounts this is some ancient reference design[1] which later evolved
>> _into_ the SP804, so that vendor would probably still be ARM ;)
>
> Right.
>
>> A separate compatible string would indeed make more sense, though. Both
>> semantically and in terms of letting the driver account for the differences
>> automatically.
>>
>> Robin.
>>
>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>
> Humm, same as integrator timers perhaps?

Having had a quick look, what the Integrator/AP manual describes 
certainly smells like the same basic block as the "AMBA Timer" - 16 bit 
counters and the same control register layout - albeit in a mutant 
triple-timer version with a bigger offset between each register set. 
Integrator/CP, on the other hand, looks much more SP804-like.

Robin.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-17 19:21             ` Robin Murphy
  0 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-17 19:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 17/03/16 19:00, Rob Herring wrote:
> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>> Hi Rob,
>>
>> On 17/03/16 17:09, Rob Herring wrote:
>>>
>>> On Wed, Mar 09, 2016 at 11:24:04AM +0100, Neil Armstrong wrote:
>>>>
>>>> Add timer-width optional property to specify a different vendor
>>>> specific timer counter bit-width.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>>> ---
>>>>    Documentation/devicetree/bindings/timer/arm,sp804.txt | 2 ++
>>>>    1 file changed, 2 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> index 5cd8eee7..141e143 100644
>>>> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
>>>> @@ -17,6 +17,8 @@ Optional properties:
>>>>    - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line
>>>> connected, this
>>>>          specifies if the irq connection is for timer 1 or timer 2. A
>>>> value of 1
>>>>          or 2 should be used.
>>>> +- arm,timer-width: Should contain the width in number of bits of the
>>>> counter,
>>>> +       is considered by default 32 but can be changed for vendor
>>>> variants.
>>>
>>>
>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>> add a new compatible string for the vendor that decided to hack up ARM's
>>> IP block.
>>
>>
>> By all accounts this is some ancient reference design[1] which later evolved
>> _into_ the SP804, so that vendor would probably still be ARM ;)
>
> Right.
>
>> A separate compatible string would indeed make more sense, though. Both
>> semantically and in terms of letting the driver account for the differences
>> automatically.
>>
>> Robin.
>>
>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>
> Humm, same as integrator timers perhaps?

Having had a quick look, what the Integrator/AP manual describes 
certainly smells like the same basic block as the "AMBA Timer" - 16 bit 
counters and the same control register layout - albeit in a mutant 
triple-timer version with a bigger offset between each register set. 
Integrator/CP, on the other hand, looks much more SP804-like.

Robin.

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
  2016-03-17 19:21             ` Robin Murphy
  (?)
@ 2016-03-22  9:21               ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-22  9:21 UTC (permalink / raw)
  To: Robin Murphy, Rob Herring
  Cc: devicetree, Daniel Lezcano, linux-kernel, Sudeep Holla,
	Russell King, Thomas Gleixner, linux-arm-kernel

On 03/17/2016 08:21 PM, Robin Murphy wrote:
> On 17/03/16 19:00, Rob Herring wrote:
>> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>>> Hi Rob,
>>>
>>> On 17/03/16 17:09, Rob Herring wrote:
>>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>>> add a new compatible string for the vendor that decided to hack up ARM's
>>>> IP block.
>>>
>>>
>>> By all accounts this is some ancient reference design[1] which later evolved
>>> _into_ the SP804, so that vendor would probably still be ARM ;)
>>
>> Right.
>>
>>> A separate compatible string would indeed make more sense, though. Both
>>> semantically and in terms of letting the driver account for the differences
>>> automatically.
>>>
>>> Robin.
>>>
>>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>>
>> Humm, same as integrator timers perhaps?
> 
> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
> 
> Robin.
> 

Hi,

I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.

Thanks,
Neil

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-22  9:21               ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-22  9:21 UTC (permalink / raw)
  To: Robin Murphy, Rob Herring
  Cc: devicetree, Daniel Lezcano, linux-kernel, Sudeep Holla,
	Russell King, Thomas Gleixner, linux-arm-kernel

On 03/17/2016 08:21 PM, Robin Murphy wrote:
> On 17/03/16 19:00, Rob Herring wrote:
>> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>>> Hi Rob,
>>>
>>> On 17/03/16 17:09, Rob Herring wrote:
>>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>>> add a new compatible string for the vendor that decided to hack up ARM's
>>>> IP block.
>>>
>>>
>>> By all accounts this is some ancient reference design[1] which later evolved
>>> _into_ the SP804, so that vendor would probably still be ARM ;)
>>
>> Right.
>>
>>> A separate compatible string would indeed make more sense, though. Both
>>> semantically and in terms of letting the driver account for the differences
>>> automatically.
>>>
>>> Robin.
>>>
>>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>>
>> Humm, same as integrator timers perhaps?
> 
> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
> 
> Robin.
> 

Hi,

I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.

Thanks,
Neil

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-22  9:21               ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-22  9:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/17/2016 08:21 PM, Robin Murphy wrote:
> On 17/03/16 19:00, Rob Herring wrote:
>> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>>> Hi Rob,
>>>
>>> On 17/03/16 17:09, Rob Herring wrote:
>>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>>> add a new compatible string for the vendor that decided to hack up ARM's
>>>> IP block.
>>>
>>>
>>> By all accounts this is some ancient reference design[1] which later evolved
>>> _into_ the SP804, so that vendor would probably still be ARM ;)
>>
>> Right.
>>
>>> A separate compatible string would indeed make more sense, though. Both
>>> semantically and in terms of letting the driver account for the differences
>>> automatically.
>>>
>>> Robin.
>>>
>>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>>
>> Humm, same as integrator timers perhaps?
> 
> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
> 
> Robin.
> 

Hi,

I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.

Thanks,
Neil

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
  2016-03-22  9:21               ` Neil Armstrong
  (?)
@ 2016-03-22 12:02                 ` Robin Murphy
  -1 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-22 12:02 UTC (permalink / raw)
  To: Neil Armstrong, Rob Herring
  Cc: devicetree, Daniel Lezcano, linux-kernel, Sudeep Holla,
	Russell King, Thomas Gleixner, linux-arm-kernel

Hi Neil,

On 22/03/16 09:21, Neil Armstrong wrote:
> On 03/17/2016 08:21 PM, Robin Murphy wrote:
>> On 17/03/16 19:00, Rob Herring wrote:
>>> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>>>> Hi Rob,
>>>>
>>>> On 17/03/16 17:09, Rob Herring wrote:
>>>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>>>> add a new compatible string for the vendor that decided to hack up ARM's
>>>>> IP block.
>>>>
>>>>
>>>> By all accounts this is some ancient reference design[1] which later evolved
>>>> _into_ the SP804, so that vendor would probably still be ARM ;)
>>>
>>> Right.
>>>
>>>> A separate compatible string would indeed make more sense, though. Both
>>>> semantically and in terms of letting the driver account for the differences
>>>> automatically.
>>>>
>>>> Robin.
>>>>
>>>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>>>
>>> Humm, same as integrator timers perhaps?
>>
>> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
>>
>> Robin.
>>
>
> Hi,
>
> I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.

By "needs a specific register width" do you mean the OxSemi 
implementation will give a bus error on a 32-bit access and requires 
16-bit accessors? If so, I'd expect to see patch 1 changing readl()s to 
readw()s at least somewhere. Otherwise, if it's merely that the 
clocksource API needs to know the upper 16 bits of a word it reads are 
undefined, then since that's the standard behaviour I'd be inclined to 
add it to the driver as a canonical "arm,amba-timer" implementation, 
then have your implementation-specific compatible on top of that just in 
case.

Robin.

>
> Thanks,
> Neil
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-22 12:02                 ` Robin Murphy
  0 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-22 12:02 UTC (permalink / raw)
  To: Neil Armstrong, Rob Herring
  Cc: devicetree, Daniel Lezcano, linux-kernel, Sudeep Holla,
	Russell King, Thomas Gleixner, linux-arm-kernel

Hi Neil,

On 22/03/16 09:21, Neil Armstrong wrote:
> On 03/17/2016 08:21 PM, Robin Murphy wrote:
>> On 17/03/16 19:00, Rob Herring wrote:
>>> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>>>> Hi Rob,
>>>>
>>>> On 17/03/16 17:09, Rob Herring wrote:
>>>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>>>> add a new compatible string for the vendor that decided to hack up ARM's
>>>>> IP block.
>>>>
>>>>
>>>> By all accounts this is some ancient reference design[1] which later evolved
>>>> _into_ the SP804, so that vendor would probably still be ARM ;)
>>>
>>> Right.
>>>
>>>> A separate compatible string would indeed make more sense, though. Both
>>>> semantically and in terms of letting the driver account for the differences
>>>> automatically.
>>>>
>>>> Robin.
>>>>
>>>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>>>
>>> Humm, same as integrator timers perhaps?
>>
>> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
>>
>> Robin.
>>
>
> Hi,
>
> I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.

By "needs a specific register width" do you mean the OxSemi 
implementation will give a bus error on a 32-bit access and requires 
16-bit accessors? If so, I'd expect to see patch 1 changing readl()s to 
readw()s at least somewhere. Otherwise, if it's merely that the 
clocksource API needs to know the upper 16 bits of a word it reads are 
undefined, then since that's the standard behaviour I'd be inclined to 
add it to the driver as a canonical "arm,amba-timer" implementation, 
then have your implementation-specific compatible on top of that just in 
case.

Robin.

>
> Thanks,
> Neil
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-22 12:02                 ` Robin Murphy
  0 siblings, 0 replies; 208+ messages in thread
From: Robin Murphy @ 2016-03-22 12:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Neil,

On 22/03/16 09:21, Neil Armstrong wrote:
> On 03/17/2016 08:21 PM, Robin Murphy wrote:
>> On 17/03/16 19:00, Rob Herring wrote:
>>> On Thu, Mar 17, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>>>> Hi Rob,
>>>>
>>>> On 17/03/16 17:09, Rob Herring wrote:
>>>>> That would not be an SP804 nor would the vendor be ARM in that case. So
>>>>> add a new compatible string for the vendor that decided to hack up ARM's
>>>>> IP block.
>>>>
>>>>
>>>> By all accounts this is some ancient reference design[1] which later evolved
>>>> _into_ the SP804, so that vendor would probably still be ARM ;)
>>>
>>> Right.
>>>
>>>> A separate compatible string would indeed make more sense, though. Both
>>>> semantically and in terms of letting the driver account for the differences
>>>> automatically.
>>>>
>>>> Robin.
>>>>
>>>> [1]:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0170a/I350250.html
>>>
>>> Humm, same as integrator timers perhaps?
>>
>> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
>>
>> Robin.
>>
>
> Hi,
>
> I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.

By "needs a specific register width" do you mean the OxSemi 
implementation will give a bus error on a 32-bit access and requires 
16-bit accessors? If so, I'd expect to see patch 1 changing readl()s to 
readw()s at least somewhere. Otherwise, if it's merely that the 
clocksource API needs to know the upper 16 bits of a word it reads are 
undefined, then since that's the standard behaviour I'd be inclined to 
add it to the driver as a canonical "arm,amba-timer" implementation, 
then have your implementation-specific compatible on top of that just in 
case.

Robin.

>
> Thanks,
> Neil
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
  2016-03-22 12:02                 ` Robin Murphy
  (?)
@ 2016-03-22 14:29                   ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-22 14:29 UTC (permalink / raw)
  To: Robin Murphy, Rob Herring
  Cc: devicetree, Daniel Lezcano, linux-kernel, Sudeep Holla,
	Russell King, Thomas Gleixner, linux-arm-kernel

On 03/22/2016 01:02 PM, Robin Murphy wrote:
> Hi Neil,
>>>>
>>>> Humm, same as integrator timers perhaps?
>>>
>>> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
>>>
>>> Robin.
>>>
>>
>> Hi,
>>
>> I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.
> 
> By "needs a specific register width" do you mean the OxSemi implementation will give a bus error on a 32-bit access and requires 16-bit accessors? If so, I'd expect to see patch 1 changing readl()s to readw()s at least somewhere. Otherwise, if it's merely that the clocksource API needs to know the upper 16 bits of a word it reads are undefined, then since that's the standard behaviour I'd be inclined to add it to the driver as a canonical "arm,amba-timer" implementation, then have your implementation-specific compatible on top of that just in case.

No actually the bus access is 32bit but the counter is 24bit wide instead of 16bit, so the clocksource won't work and the system time will furiously drift. It's not the case of the clockevent since the delay fits in 24 bits.

It also seems is ignores the 32BIT config bit, so it seems based on the initial 16bit only reference design.

How do you think I should implement this ?

Neil

> Robin.
> 
>>
>> Thanks,
>> Neil
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> 

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

* Re: [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-22 14:29                   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-22 14:29 UTC (permalink / raw)
  To: Robin Murphy, Rob Herring
  Cc: devicetree, Daniel Lezcano, linux-kernel, Sudeep Holla,
	Russell King, Thomas Gleixner, linux-arm-kernel

On 03/22/2016 01:02 PM, Robin Murphy wrote:
> Hi Neil,
>>>>
>>>> Humm, same as integrator timers perhaps?
>>>
>>> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
>>>
>>> Robin.
>>>
>>
>> Hi,
>>
>> I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.
> 
> By "needs a specific register width" do you mean the OxSemi implementation will give a bus error on a 32-bit access and requires 16-bit accessors? If so, I'd expect to see patch 1 changing readl()s to readw()s at least somewhere. Otherwise, if it's merely that the clocksource API needs to know the upper 16 bits of a word it reads are undefined, then since that's the standard behaviour I'd be inclined to add it to the driver as a canonical "arm,amba-timer" implementation, then have your implementation-specific compatible on top of that just in case.

No actually the bus access is 32bit but the counter is 24bit wide instead of 16bit, so the clocksource won't work and the system time will furiously drift. It's not the case of the clockevent since the delay fits in 24 bits.

It also seems is ignores the 32BIT config bit, so it seems based on the initial 16bit only reference design.

How do you think I should implement this ?

Neil

> Robin.
> 
>>
>> Thanks,
>> Neil
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> 

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

* [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property
@ 2016-03-22 14:29                   ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-22 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/22/2016 01:02 PM, Robin Murphy wrote:
> Hi Neil,
>>>>
>>>> Humm, same as integrator timers perhaps?
>>>
>>> Having had a quick look, what the Integrator/AP manual describes certainly smells like the same basic block as the "AMBA Timer" - 16 bit counters and the same control register layout - albeit in a mutant triple-timer version with a bigger offset between each register set. Integrator/CP, on the other hand, looks much more SP804-like.
>>>
>>> Robin.
>>>
>>
>> Hi,
>>
>> I will switch to oxsemi,ox810se-rps-timer since it need a specific register width that will be handled by the driver.
> 
> By "needs a specific register width" do you mean the OxSemi implementation will give a bus error on a 32-bit access and requires 16-bit accessors? If so, I'd expect to see patch 1 changing readl()s to readw()s at least somewhere. Otherwise, if it's merely that the clocksource API needs to know the upper 16 bits of a word it reads are undefined, then since that's the standard behaviour I'd be inclined to add it to the driver as a canonical "arm,amba-timer" implementation, then have your implementation-specific compatible on top of that just in case.

No actually the bus access is 32bit but the counter is 24bit wide instead of 16bit, so the clocksource won't work and the system time will furiously drift. It's not the case of the clockevent since the delay fits in 24 bits.

It also seems is ignores the 32BIT config bit, so it seems based on the initial 16bit only reference design.

How do you think I should implement this ?

Neil

> Robin.
> 
>>
>> Thanks,
>> Neil
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> 

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

* Re: [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
  2016-03-17 17:27       ` Rob Herring
@ 2016-03-23  8:37         ` Neil Armstrong
  -1 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-23  8:37 UTC (permalink / raw)
  To: Rob Herring; +Cc: linux-kernel, linux-arm-kernel, devicetree

On 03/17/2016 06:27 PM, Rob Herring wrote:
> On Wed, Mar 09, 2016 at 11:24:18AM +0100, Neil Armstrong wrote:
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>>  Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
>> new file mode 100644
>> index 0000000..f6032d2
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/oxnas.txt
>> @@ -0,0 +1,9 @@
>> +PLX Technology OXNAS SoCs Family device tree bindings
>> +-------------------------------------------
>> +
>> +Boards with the OX810SE Soc SoC shall have the following properties:
> 
> s/Soc SoC/SoC/

OK
> 
>> +  Required root node property:
>> +    compatible: "oxsemi,ox810se"
>> +
>> +Board compatible values:
>> +  - "wd,mbwe" (OX810SE)
> 
> Seems kind of generic. Only one version?

There is a My Book World Edition II, which seems to be the same (they share the same firmware) but with two SATA ports, the original kernel does not make any differences between the two models.

I'm not aware of different versions and the firmware does not contain any specific code for different board revisions.

Neil

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

* [PATCH v2 16/18] dt-bindings: Add OXNAS bindings
@ 2016-03-23  8:37         ` Neil Armstrong
  0 siblings, 0 replies; 208+ messages in thread
From: Neil Armstrong @ 2016-03-23  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/17/2016 06:27 PM, Rob Herring wrote:
> On Wed, Mar 09, 2016 at 11:24:18AM +0100, Neil Armstrong wrote:
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>>  Documentation/devicetree/bindings/arm/oxnas.txt | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
>> new file mode 100644
>> index 0000000..f6032d2
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/oxnas.txt
>> @@ -0,0 +1,9 @@
>> +PLX Technology OXNAS SoCs Family device tree bindings
>> +-------------------------------------------
>> +
>> +Boards with the OX810SE Soc SoC shall have the following properties:
> 
> s/Soc SoC/SoC/

OK
> 
>> +  Required root node property:
>> +    compatible: "oxsemi,ox810se"
>> +
>> +Board compatible values:
>> +  - "wd,mbwe" (OX810SE)
> 
> Seems kind of generic. Only one version?

There is a My Book World Edition II, which seems to be the same (they share the same firmware) but with two SATA ports, the original kernel does not make any differences between the two models.

I'm not aware of different versions and the firmware does not contain any specific code for different board revisions.

Neil

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

end of thread, other threads:[~2016-03-23  8:38 UTC | newest]

Thread overview: 208+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-03 11:39 [PATCH 00/17] Add Initial support for PLX Technology OX810SE Neil Armstrong
2016-03-03 11:39 ` Neil Armstrong
2016-03-03 11:39 ` [PATCH 01/17] dt-bindings: vendor-prefixes: Add PLX Technology Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-03 15:02   ` Philipp Zabel
2016-03-03 15:02     ` Philipp Zabel
2016-03-05  4:29     ` Rob Herring
2016-03-05  4:29       ` Rob Herring
2016-03-07  9:55       ` Philipp Zabel
2016-03-07  9:55         ` Philipp Zabel
2016-03-03 11:39 ` [PATCH 02/17] irqchip: Add PLX Technology RPS IRQ Controller Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-03 13:01   ` Marc Zyngier
2016-03-03 13:01     ` Marc Zyngier
2016-03-03 13:08     ` Arnd Bergmann
2016-03-03 13:08       ` Arnd Bergmann
2016-03-03 13:36       ` Russell King - ARM Linux
2016-03-03 13:36         ` Russell King - ARM Linux
2016-03-03 17:32         ` Arnd Bergmann
2016-03-03 17:32           ` Arnd Bergmann
2016-03-03 15:32   ` Ma Haijun
2016-03-03 15:32     ` Ma Haijun
2016-03-03 16:56     ` Neil Armstrong
2016-03-03 16:56       ` Neil Armstrong
2016-03-03 17:17       ` Marc Zyngier
2016-03-03 17:17         ` Marc Zyngier
2016-03-04 11:10         ` Neil Armstrong
2016-03-04 11:10           ` Neil Armstrong
2016-03-03 11:39 ` [PATCH 03/17] dt-bindings: Add PLX Technology RPS IRQ Controller bindings Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-03 14:53   ` Andrew Lunn
2016-03-03 14:53     ` Andrew Lunn
2016-03-03 14:57     ` Neil Armstrong
2016-03-03 14:57       ` Neil Armstrong
2016-03-03 15:06       ` Andrew Lunn
2016-03-03 15:06         ` Andrew Lunn
2016-03-03 15:06         ` Andrew Lunn
2016-03-03 11:39 ` [PATCH 04/17] clocksource: Add PLX Technology RPS Timer Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-17 16:13   ` Daniel Lezcano
2016-03-17 16:13     ` Daniel Lezcano
2016-03-03 11:39 ` [PATCH 05/17] dt-bindings: Add PLX Technology RPS Timer bindings Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-03 11:39 ` [PATCH 06/17] reset: Add PLX Technology Reset Controller driver Neil Armstrong
2016-03-03 11:39   ` Neil Armstrong
2016-03-03 14:18   ` Philipp Zabel
2016-03-03 14:18     ` Philipp Zabel
2016-03-03 14:29     ` Neil Armstrong
2016-03-03 14:29       ` Neil Armstrong
2016-03-03 15:00       ` Philipp Zabel
2016-03-03 15:00         ` Philipp Zabel
2016-03-03 11:40 ` [PATCH 07/17] dt-bindings: Add PLX Technology Reset Controller bindings Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 14:21   ` Philipp Zabel
2016-03-03 14:21     ` Philipp Zabel
2016-03-03 14:24     ` Neil Armstrong
2016-03-03 14:24       ` Neil Armstrong
2016-03-03 14:24       ` Neil Armstrong
2016-03-03 14:31       ` Philipp Zabel
2016-03-03 14:31         ` Philipp Zabel
2016-03-03 11:40 ` [PATCH 08/17] clk: Add PLX Technology OXNAS Standard Clocks Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-04  2:25   ` Stephen Boyd
2016-03-04  2:25     ` Stephen Boyd
2016-03-07 11:24     ` Neil Armstrong
2016-03-07 11:24       ` Neil Armstrong
2016-03-03 11:40 ` [PATCH 09/17] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:40 ` [PATCH 10/17] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-15 14:56   ` Linus Walleij
2016-03-15 14:56     ` Linus Walleij
2016-03-15 14:56     ` Linus Walleij
2016-03-16 15:00     ` Neil Armstrong
2016-03-16 15:00       ` Neil Armstrong
2016-03-16 15:00       ` Neil Armstrong
2016-03-17 14:49       ` Linus Walleij
2016-03-17 14:49         ` Linus Walleij
2016-03-17 14:49         ` Linus Walleij
2016-03-03 11:40 ` [PATCH 11/17] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-15 14:30   ` Linus Walleij
2016-03-15 14:30     ` Linus Walleij
2016-03-15 14:30     ` Linus Walleij
2016-03-03 11:40 ` [PATCH 12/17] arm: Add new mach-oxnas Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:49   ` Russell King - ARM Linux
2016-03-03 11:49     ` Russell King - ARM Linux
2016-03-03 12:37     ` Neil Armstrong
2016-03-03 12:37       ` Neil Armstrong
2016-03-03 12:56   ` Arnd Bergmann
2016-03-03 12:56     ` Arnd Bergmann
2016-03-03 13:29     ` Russell King - ARM Linux
2016-03-03 13:29       ` Russell King - ARM Linux
2016-03-03 13:40       ` Arnd Bergmann
2016-03-03 13:40         ` Arnd Bergmann
2016-03-03 11:40 ` [PATCH 13/17] arm: Add build support for mach-oxnas Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:40 ` [PATCH 14/17] arm: boot: dts: Add PLX Technology OX810SE dtsi Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 12:15   ` Arnd Bergmann
2016-03-03 12:15     ` Arnd Bergmann
2016-03-03 13:39     ` Neil Armstrong
2016-03-03 13:39       ` Neil Armstrong
2016-03-03 13:39       ` Neil Armstrong
2016-03-03 11:40 ` [PATCH 15/17] dt-bindings: Add OXNAS bindings Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 11:40 ` [PATCH 16/17] dt-bindings: Add Western Digital to vendor prefixes Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-05  4:29   ` Rob Herring
2016-03-05  4:29     ` Rob Herring
2016-03-03 11:40 ` [PATCH 17/17] arm: boot: dts: Add Western Digital My Book World Edition device tree Neil Armstrong
2016-03-03 11:40   ` Neil Armstrong
2016-03-03 12:23 ` [PATCH 00/17] Add Initial support for PLX Technology OX810SE Arnd Bergmann
2016-03-03 12:23   ` Arnd Bergmann
2016-03-03 12:36   ` Neil Armstrong
2016-03-03 12:36     ` Neil Armstrong
2016-03-09 10:24 ` [PATCH v2 00/18] " Neil Armstrong
2016-03-09 10:24   ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 01/18] clocksource: sp804: Add support for non-32bit width counter Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 16:40     ` Daniel Lezcano
2016-03-17 16:40       ` Daniel Lezcano
2016-03-09 10:24   ` [PATCH v2 02/18] dt-bindings: timer: sp804: add timer-width property Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:09     ` Rob Herring
2016-03-17 17:09       ` Rob Herring
2016-03-17 17:09       ` Rob Herring
2016-03-17 18:06       ` Robin Murphy
2016-03-17 18:06         ` Robin Murphy
2016-03-17 19:00         ` Rob Herring
2016-03-17 19:00           ` Rob Herring
2016-03-17 19:00           ` Rob Herring
2016-03-17 19:21           ` Robin Murphy
2016-03-17 19:21             ` Robin Murphy
2016-03-17 19:21             ` Robin Murphy
2016-03-22  9:21             ` Neil Armstrong
2016-03-22  9:21               ` Neil Armstrong
2016-03-22  9:21               ` Neil Armstrong
2016-03-22 12:02               ` Robin Murphy
2016-03-22 12:02                 ` Robin Murphy
2016-03-22 12:02                 ` Robin Murphy
2016-03-22 14:29                 ` Neil Armstrong
2016-03-22 14:29                   ` Neil Armstrong
2016-03-22 14:29                   ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 03/18] irqchip: versatile-fpga: add new arm,rps-irq compatible Neil Armstrong
2016-03-09 10:24     ` [PATCH v2 03/18] irqchip: versatile-fpga: add new arm, rps-irq compatible Neil Armstrong
2016-03-15 11:47     ` [PATCH v2 03/18] irqchip: versatile-fpga: add new arm,rps-irq compatible Marc Zyngier
2016-03-15 11:47       ` Marc Zyngier
2016-03-09 10:24   ` [PATCH v2 04/18] dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq compatible string Neil Armstrong
2016-03-09 10:24     ` [PATCH v2 04/18] dt-bindings: irq: arm, versatile-fpga: add arm, rps-irq " Neil Armstrong
2016-03-17 17:15     ` [PATCH v2 04/18] dt-bindings: irq: arm,versatile-fpga: add arm,rps-irq " Rob Herring
2016-03-17 17:15       ` Rob Herring
2016-03-17 17:15       ` Rob Herring
2016-03-09 10:24   ` [PATCH v2 05/18] dt-bindings: vendor-prefixes: Add PLX Technology Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:15     ` Rob Herring
2016-03-17 17:15       ` Rob Herring
2016-03-17 17:15       ` Rob Herring
2016-03-09 10:24   ` [PATCH v2 06/18] dt-bindings: Add Oxford Semiconductors to vendor prefixes Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:16     ` Rob Herring
2016-03-17 17:16       ` Rob Herring
2016-03-09 10:24   ` [PATCH v2 07/18] reset: Add PLX Technology Reset Controller driver Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 08/18] dt-bindings: Add PLX Technology Reset Controller bindings Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:18     ` Rob Herring
2016-03-17 17:18       ` Rob Herring
2016-03-17 17:18       ` Rob Herring
2016-03-09 10:24   ` [PATCH v2 09/18] clk: Add PLX Technology OXNAS Standard Clocks Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 10/18] dt-bindings: Add PLX Technology OXNAS Standard Clocks bindings Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:19     ` Rob Herring
2016-03-17 17:19       ` Rob Herring
2016-03-09 10:24   ` [PATCH v2 11/18] pinctrl: Add PLX Technology OXNAS pinctrl and gpio driver Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-10 14:43     ` kbuild test robot
2016-03-10 14:43       ` kbuild test robot
2016-03-10 14:43       ` kbuild test robot
2016-03-09 10:24   ` [PATCH v2 12/18] dt-bindings: Add PLX Technology OXNAS pinctrl and gpio bindings Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:25     ` Rob Herring
2016-03-17 17:25       ` Rob Herring
2016-03-09 10:24   ` [PATCH v2 13/18] arm: Add new mach-oxnas Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 14/18] arm: Add build support for mach-oxnas Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 15/18] arm: boot: dts: Add PLX Technology OX810SE dtsi Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 16/18] dt-bindings: Add OXNAS bindings Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-17 17:27     ` Rob Herring
2016-03-17 17:27       ` Rob Herring
2016-03-17 17:27       ` Rob Herring
2016-03-23  8:37       ` Neil Armstrong
2016-03-23  8:37         ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 17/18] dt-bindings: Add Western Digital to vendor prefixes Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24   ` [PATCH v2 18/18] arm: boot: dts: Add Western Digital My Book World Edition device tree Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong
2016-03-09 10:24     ` Neil Armstrong

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.