From marc.zyngier at arm.com  Mon Aug  1 02:54:15 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon,  1 Aug 2016 10:54:15 +0100
Subject: [PATCH v2 1/2] clocksource/arm_arch_timer: Force per-CPU interrupt to
 be level-triggered
In-Reply-To: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>
References: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1470045256-9032-2-git-send-email-marc.zyngier@arm.com>

The ARM architected timer produces level-triggered interrupts (this
is mandated by the architecture). Unfortunately, a number of
device-trees get this wrong, and expose an edge-triggered interrupt.

Until now, this wasn't too much an issue, as the programming of the
trigger would fail (the corresponding PPI cannot be reconfigured),
and the kernel would be happy with this. But we're about to change
this, and trust DT a lot if the driver doesn't provide its own
trigger information. In that context, the timer breaks badly.

While we do need to fix the DTs, there is also some userspace out
there (kvmtool) that generates the same kind of broken DT on the
fly, and that will completely break with newer kernels.

As a safety measure, and to keep buggy software alive as well as
buying us some time to fix DTs all over the place, let's check
what trigger configuration has been given us by the firmware.
If this is not a level configuration, then we know that the
DT/ACPI configuration is bust, and we pick some defaults which
won't be worse than the existing setup.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 28bce3f..5770054 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -8,6 +8,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt)	"arm_arch_timer: " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void)
 		arch_timer_ppi[PHYS_NONSECURE_PPI]);
 }
 
+static u32 check_ppi_trigger(int irq)
+{
+	u32 flags = irq_get_trigger_type(irq);
+
+	if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
+		pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
+		pr_warn("WARNING: Please fix your firmware\n");
+		flags = IRQF_TRIGGER_LOW;
+	}
+
+	return flags;
+}
+
 static int arch_timer_starting_cpu(unsigned int cpu)
 {
 	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
+	u32 flags;
 
 	__arch_timer_setup(ARCH_CP15_TIMER, clk);
 
-	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
+	flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
+	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
 
-	if (arch_timer_has_nonsecure_ppi())
-		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
+	if (arch_timer_has_nonsecure_ppi()) {
+		flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]);
+		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags);
+	}
 
 	arch_counter_set_user_access();
 	if (evtstrm_enable)
-- 
2.1.4



From marc.zyngier at arm.com  Mon Aug  1 02:54:14 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon,  1 Aug 2016 10:54:14 +0100
Subject: [PATCH v2 0/2] Fix arch timer trigger
Message-ID: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>

Recent fixes in the IRQ layer (properly propagating the trigger
settings in the interrupt controler instead of silently failing)
uncovered a number of cases where DTs are describing the timer trigger
wrong (edge, while the interrupt is definitely level).

The result is a kernel that doesn't boot anymore (forever waiting for
an interrupt that can't trigger) or behave erratically (missing
interrupts).

This very small series addresses the issue in two ways:
(1) enforcing level triggered in the driver and spitting out a nastygram
so that the user can find out about the issue
(2) fix the existing issue by repainting the broken device trees.

(1) makes sure that a new kernel can run with an old DT, and (2)
addresses the issue properly.

Note that the two patches can be applied independently.

Tested on APM Mustang, which is one of the broken platforms.

Thanks,

	M.

* From v1:
  - Make GICv3-based platforms use the level triggered setting even if
  the HW actually precisly describes high or low settings.
  - Rebased on top of linux/master as of today.

Marc Zyngier (2):
  clocksource/arm_arch_timer: Force per-CPU interrupt to be
    level-triggered
  arm64: dts: Fix broken architected timer interrupt trigger

 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi  |  8 +++----
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  8 +++----
 arch/arm64/boot/dts/apm/apm-storm.dtsi             |  8 +++----
 arch/arm64/boot/dts/broadcom/ns2.dtsi              |  8 +++----
 arch/arm64/boot/dts/cavium/thunder-88xx.dtsi       |  8 +++----
 arch/arm64/boot/dts/exynos/exynos7.dtsi            |  8 +++----
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi     |  8 +++----
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     |  8 +++----
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi      |  8 +++----
 .../boot/dts/socionext/uniphier-ph1-ld20.dtsi      |  8 +++----
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi             |  8 +++----
 drivers/clocksource/arm_arch_timer.c               | 26 +++++++++++++++++++---
 12 files changed, 67 insertions(+), 47 deletions(-)

-- 
2.1.4



From marc.zyngier at arm.com  Mon Aug  1 02:54:16 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon,  1 Aug 2016 10:54:16 +0100
Subject: [PATCH v2 2/2] arm64: dts: Fix broken architected timer interrupt
 trigger
In-Reply-To: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>
References: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1470045256-9032-3-git-send-email-marc.zyngier@arm.com>

The ARM architected timer specification mandates that the interrupt
associated with each timer is level triggered (which corresponds to
the "counter >= comparator" condition).

A number of DTs are being remarkably creative, declaring the interrupt
to be edge triggered. A quick look at the TRM for the corresponding ARM
CPUs clearly shows that this is wrong, and I've corrected those.
For non-ARM designs (and in the absence of a publicly available TRM),
I've made them active low as well, which can't be completely wrong
as the GIC cannot disinguish between level low and level high.

The respective maintainers are of course welcome to prove me wrong.

While I was at it, I took the liberty to fix a couple of related issue,
such as some spurious affinity bits on ThunderX, and their complete
absence on ls1043a (both of which seem to be related to copy-pasting
from other DTs).

Acked-by: Duc Dang <dhdang at apm.com>
Acked-by: Carlo Caione <carlo at endlessm.com>
Acked-by: Michal Simek <michal.simek at xilinx.com>
Acked-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Acked-by: Dinh Nguyen <dinguyen at opensource.altera.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi    | 8 ++++----
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi          | 8 ++++----
 arch/arm64/boot/dts/apm/apm-storm.dtsi               | 8 ++++----
 arch/arm64/boot/dts/broadcom/ns2.dtsi                | 8 ++++----
 arch/arm64/boot/dts/cavium/thunder-88xx.dtsi         | 8 ++++----
 arch/arm64/boot/dts/exynos/exynos7.dtsi              | 8 ++++----
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi       | 8 ++++----
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi       | 8 ++++----
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi        | 8 ++++----
 arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi | 8 ++++----
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi               | 8 ++++----
 11 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index 445aa67..c2b9bcb 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -255,10 +255,10 @@
 		/* Local timer */
 		timer {
 			compatible = "arm,armv8-timer";
-			interrupts = <1 13 0xf01>,
-				     <1 14 0xf01>,
-				     <1 11 0xf01>,
-				     <1 10 0xf01>;
+			interrupts = <1 13 0xf08>,
+				     <1 14 0xf08>,
+				     <1 11 0xf08>,
+				     <1 10 0xf08>;
 		};
 
 		timer0: timer0 at ffc03000 {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..4d9d144 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -100,13 +100,13 @@
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 14
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 11
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
 	xtal: xtal-clk {
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index 6bf7cbe..010e961 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -110,10 +110,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 0 0xff01>,	/* Secure Phys IRQ */
-			     <1 13 0xff01>,	/* Non-secure Phys IRQ */
-			     <1 14 0xff01>,	/* Virt IRQ */
-			     <1 15 0xff01>;	/* Hyp IRQ */
+		interrupts = <1 0 0xff08>,	/* Secure Phys IRQ */
+			     <1 13 0xff08>,	/* Non-secure Phys IRQ */
+			     <1 14 0xff08>,	/* Virt IRQ */
+			     <1 15 0xff08>;	/* Hyp IRQ */
 		clock-frequency = <50000000>;
 	};
 
diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index 46b78fa..01b4ee9 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -88,13 +88,13 @@
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0xff) |
-			      IRQ_TYPE_EDGE_RISING)>,
+			      IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(0xff) |
-			      IRQ_TYPE_EDGE_RISING)>,
+			      IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(0xff) |
-			      IRQ_TYPE_EDGE_RISING)>,
+			      IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(0xff) |
-			      IRQ_TYPE_EDGE_RISING)>;
+			      IRQ_TYPE_LEVEL_LOW)>;
 	};
 
 	pmu {
diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
index 2eb9b22..04dc8a8 100644
--- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
+++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
@@ -354,10 +354,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 13 0xff01>,
-		             <1 14 0xff01>,
-		             <1 11 0xff01>,
-		             <1 10 0xff01>;
+		interrupts = <1 13 4>,
+		             <1 14 4>,
+		             <1 11 4>,
+		             <1 10 4>;
 	};
 
 	pmu {
diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi
index ca663df..1628315 100644
--- a/arch/arm64/boot/dts/exynos/exynos7.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi
@@ -473,10 +473,10 @@
 
 		timer {
 			compatible = "arm,armv8-timer";
-			interrupts = <1 13 0xff01>,
-				     <1 14 0xff01>,
-				     <1 11 0xff01>,
-				     <1 10 0xff01>;
+			interrupts = <1 13 0xff08>,
+				     <1 14 0xff08>,
+				     <1 11 0xff08>,
+				     <1 10 0xff08>;
 		};
 
 		pmu_system_controller: system-controller at 105c0000 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 6bd46c1..59b7b76 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -111,10 +111,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 13 0x1>, /* Physical Secure PPI */
-			     <1 14 0x1>, /* Physical Non-Secure PPI */
-			     <1 11 0x1>, /* Virtual PPI */
-			     <1 10 0x1>; /* Hypervisor PPI */
+		interrupts = <1 13 0xf08>, /* Physical Secure PPI */
+			     <1 14 0xf08>, /* Physical Non-Secure PPI */
+			     <1 11 0xf08>, /* Virtual PPI */
+			     <1 10 0xf08>; /* Hypervisor PPI */
 	};
 
 	pmu {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 3187c82..675c1ba 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -167,10 +167,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */
-			     <1 14 0x8>, /* Physical Non-Secure PPI, active-low */
-			     <1 11 0x8>, /* Virtual PPI, active-low */
-			     <1 10 0x8>; /* Hypervisor PPI, active-low */
+		interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
+			     <1 14 4>, /* Physical Non-Secure PPI, active-low */
+			     <1 11 4>, /* Virtual PPI, active-low */
+			     <1 10 4>; /* Hypervisor PPI, active-low */
 	};
 
 	pmu {
diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
index 20d256b..b1d6bb8 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
@@ -122,10 +122,10 @@
 
 			timer {
 				compatible = "arm,armv8-timer";
-				interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>,
-					     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>,
-					     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>,
-					     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+				interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+					     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+					     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+					     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 			};
 
 			odmi: odmi at 300000 {
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi
index 9532880..c6059aa 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi
@@ -127,10 +127,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 13 0xf01>,
-			     <1 14 0xf01>,
-			     <1 11 0xf01>,
-			     <1 10 0xf01>;
+		interrupts = <1 13 4>,
+			     <1 14 4>,
+			     <1 11 4>,
+			     <1 10 4>;
 	};
 
 	soc {
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index e595f22..3e2e51f 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -65,10 +65,10 @@
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupt-parent = <&gic>;
-		interrupts = <1 13 0xf01>,
-			     <1 14 0xf01>,
-			     <1 11 0xf01>,
-			     <1 10 0xf01>;
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
 	};
 
 	amba_apu {
-- 
2.1.4



From yamada.masahiro at socionext.com  Mon Aug  1 03:00:50 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Mon, 1 Aug 2016 19:00:50 +0900
Subject: [PATCH v2 2/2] arm64: dts: Fix broken architected timer interrupt
 trigger
In-Reply-To: <1470045256-9032-3-git-send-email-marc.zyngier@arm.com>
References: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>
 <1470045256-9032-3-git-send-email-marc.zyngier@arm.com>
Message-ID: <CAK7LNARVw+mDhHT2+WjDtHpBvsxauUQpRCJeNLrQxrj0Oo=hrQ@mail.gmail.com>

2016-08-01 18:54 GMT+09:00 Marc Zyngier <marc.zyngier at arm.com>:
> The ARM architected timer specification mandates that the interrupt
> associated with each timer is level triggered (which corresponds to
> the "counter >= comparator" condition).
>
> A number of DTs are being remarkably creative, declaring the interrupt
> to be edge triggered. A quick look at the TRM for the corresponding ARM
> CPUs clearly shows that this is wrong, and I've corrected those.
> For non-ARM designs (and in the absence of a publicly available TRM),
> I've made them active low as well, which can't be completely wrong
> as the GIC cannot disinguish between level low and level high.
>
> The respective maintainers are of course welcome to prove me wrong.
>
> While I was at it, I took the liberty to fix a couple of related issue,
> such as some spurious affinity bits on ThunderX, and their complete
> absence on ls1043a (both of which seem to be related to copy-pasting
> from other DTs).
>
> Acked-by: Duc Dang <dhdang at apm.com>
> Acked-by: Carlo Caione <carlo at endlessm.com>
> Acked-by: Michal Simek <michal.simek at xilinx.com>
> Acked-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Acked-by: Dinh Nguyen <dinguyen at opensource.altera.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi    | 8 ++++----
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi          | 8 ++++----
>  arch/arm64/boot/dts/apm/apm-storm.dtsi               | 8 ++++----
>  arch/arm64/boot/dts/broadcom/ns2.dtsi                | 8 ++++----
>  arch/arm64/boot/dts/cavium/thunder-88xx.dtsi         | 8 ++++----
>  arch/arm64/boot/dts/exynos/exynos7.dtsi              | 8 ++++----
>  arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi       | 8 ++++----
>  arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi       | 8 ++++----
>  arch/arm64/boot/dts/marvell/armada-ap806.dtsi        | 8 ++++----
>  arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi | 8 ++++----


For uniphier-ph1-ld20.dtsi,

Acked-by: Masahiro Yamada <yamada.masahiro at socionext.com>


Thank you!!


-- 
Best Regards
Masahiro Yamada


From khilman at baylibre.com  Tue Aug  2 14:40:11 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue,  2 Aug 2016 14:40:11 -0700
Subject: [PATCH] clk: gxbb: add MMC gate clocks, and expose for DT
Message-ID: <20160802214011.19077-1-khilman@baylibre.com>

Add the SD/eMMC gate clocks and expose them for use by DT.

While at it, also explose FCLK_DIV2 since this is one of the input
clocks to the mux internal to each of the SD/eMMC blocks.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
Applies on top of current clk-s905 branch.

 drivers/clk/meson/gxbb.c              | 9 +++++++++
 drivers/clk/meson/gxbb.h              | 7 +++++--
 include/dt-bindings/clock/gxbb-clkc.h | 4 ++++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 007b7157cf4b..4fc8e58feef9 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -581,6 +581,9 @@ static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17);
 static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18);
 static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19);
 static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23);
+static MESON_GATE(emmc_a, HHI_GCLK_MPEG0, 24);
+static MESON_GATE(emmc_b, HHI_GCLK_MPEG0, 25);
+static MESON_GATE(emmc_c, HHI_GCLK_MPEG0, 26);
 static MESON_GATE(spi, HHI_GCLK_MPEG0, 30);
 
 static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2);
@@ -746,6 +749,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
 		[CLKID_AO_AHB_BUS]	    = &gxbb_ao_ahb_bus.hw,
 		[CLKID_AO_IFACE]	    = &gxbb_ao_iface.hw,
 		[CLKID_AO_I2C]		    = &gxbb_ao_i2c.hw,
+		[CLKID_SD_EMMC_A]	    = &gxbb_emmc_a.hw,
+		[CLKID_SD_EMMC_B]	    = &gxbb_emmc_b.hw,
+		[CLKID_SD_EMMC_C]	    = &gxbb_emmc_c.hw,
 	},
 	.num = NR_CLKS,
 };
@@ -845,6 +851,9 @@ static struct clk_gate *gxbb_clk_gates[] = {
 	&gxbb_ao_ahb_bus,
 	&gxbb_ao_iface,
 	&gxbb_ao_i2c,
+	&gxbb_emmc_a,
+	&gxbb_emmc_b,
+	&gxbb_emmc_c,
 };
 
 static int gxbb_clkc_probe(struct platform_device *pdev)
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index a2adf3448b59..217df516de44 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -172,7 +172,7 @@
 /* CLKID_CPUCLK */
 #define CLKID_HDMI_PLL		  2
 #define CLKID_FIXED_PLL		  3
-#define CLKID_FCLK_DIV2		  4
+/* CLKID_FCLK_DIV2 */
 #define CLKID_FCLK_DIV3		  5
 #define CLKID_FCLK_DIV4		  6
 #define CLKID_FCLK_DIV5		  7
@@ -262,8 +262,11 @@
 #define CLKID_AO_AHB_BUS	  91
 #define CLKID_AO_IFACE		  92
 #define CLKID_AO_I2C		  93
+/* CLKID_SD_EMMC_A */
+/* CLKID_SD_EMMC_B */
+/* CLKID_SD_EMMC_C */
 
-#define NR_CLKS			  94
+#define NR_CLKS			  97
 
 /* include the CLKIDs that have been made part of the stable DT binding */
 #include <dt-bindings/clock/gxbb-clkc.h>
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index f889d80246cb..7d418643cdcc 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -6,7 +6,11 @@
 #define __GXBB_CLKC_H
 
 #define CLKID_CPUCLK		1
+#define CLKID_FCLK_DIV2		4
 #define CLKID_CLK81		12
 #define CLKID_ETH		36
+#define CLKID_SD_EMMC_A		94
+#define CLKID_SD_EMMC_B		95
+#define CLKID_SD_EMMC_C		96
 
 #endif /* __GXBB_CLKC_H */
-- 
2.9.0



From khilman at baylibre.com  Tue Aug  2 17:30:44 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue,  2 Aug 2016 17:30:44 -0700
Subject: [PATCH 1/2] ARM64: dts: meson-gxbb: add MMC support
Message-ID: <20160803003045.24980-1-khilman@baylibre.com>

Add binding and basic support for the SD/eMMC controller on Amlogic
S905/GXBB devices.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 .../devicetree/bindings/mmc/amlogic,meson-gxbb.txt | 29 +++++++++
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 74 ++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   | 71 +++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 30 ++++++++-
 4 files changed, 203 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt

diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
new file mode 100644
index 000000000000..2bfdf47018c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
@@ -0,0 +1,29 @@
+Amlogic SD / eMMC controller for S905/GXBB family SoCs
+
+The MMC 5.1 compliant host controller on Amlogic provides the
+interface for SD, eMMC and SDIO devices.
+
+This file documents the properties in addition to those available in
+the MMC core bindings, documented by mmc.txt.
+
+Required properties:
+- compatible : contains "amlogic,meson-gxbb"
+- clocks     : A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
+- clock-names: Should contain the following:
+	"core" - Main peripheral bus clock
+	"clkin0" - Parent clock of internal mux
+	"clkin1" - Other parent clock of internal mux
+  The driver has an interal mux clock which switches between clkin0 and clkin1 depending on the
+  clock rate requested by the MMC core.
+
+Example:
+
+	sd_emmc_a: mmc at 70000 {
+        	compatible = "amlogic,meson-gxbb-mmc";
+		reg = <0x0 0x70000 0x0 0x2000>;
+                interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+		clock-names = "core", "clkin0", "clkin1";
+		pinctrl-0 = <&emmc_pins>;
+	};
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 90a84c514d3d..a49f7f77eb34 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -73,6 +73,45 @@
 			default-state = "off";
 		};
 	};
+
+	mmc_iv: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "mmc-gpio-supply";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+		gpio-states = <0 1>;
+	
+		/*
+		 * Based on ODROID-C2 schematics:
+		 * signal name: IO_TF_3V3N_1V8, GPIOAO bit 3
+		 */
+		states = <3300000 0
+		          1800000 1>;
+	};
+
+	vcc1v8: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	vcc3v3: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 &uart_AO {
@@ -87,3 +126,38 @@
 	pinctrl-names = "default";
 };
 
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&mmc_iv>;
+	voltage-ranges = <1800 3300>;
+};
+
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&vcc3v3>;
+	vmmcq-sumpply = <&vcc1v8>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index f4f30f674b4c..63d95d136aec 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -57,6 +57,42 @@
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x40000000>;
 	};
+
+	mmc_iv: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "mmc-gpio-supply";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpio-states = <0 1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+		          3300000 1>;
+	};
+
+	vddio_boot: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	vcc_3v3: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 /* This UART is brought out to the DB9 connector */
@@ -72,3 +108,38 @@
 	pinctrl-names = "default";
 };
 
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&mmc_iv>;
+};
+
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&vcc_3v3>;
+	vmmcq-sumpply = <&vddio_boot>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 35c8b2beb05c..2e48fa1e0364 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -247,7 +247,8 @@
 					mux {
 						groups = "emmc_nand_d07",
 						       "emmc_cmd",
-						       "emmc_clk";
+						       "emmc_clk",
+						       "emmc_ds";
 						function = "emmc";
 					};
 				};
@@ -330,6 +331,33 @@
 			#address-cells = <2>;
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+
+			sd_emmc_a: mmc at 70000 {
+		        	compatible = "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x70000 0x0 0x2000>;
+		                interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+				clock-names = "core", "clkin0", "clkin1";
+				status = "disabled";
+			};
+
+			sd_emmc_b: mmc at 72000 {
+		        	compatible = "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x72000 0x0 0x2000>;
+				interrupts = < GIC_SPI 217 IRQ_TYPE_EDGE_RISING >;
+				clocks = <&clkc CLKID_SD_EMMC_B>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+				clock-names = "core", "clkin0", "clkin1";
+				status = "disabled";
+			};
+
+			sd_emmc_c: mmc at 74000 {
+		        	compatible = "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x74000 0x0 0x2000>;
+		                interrupts = < GIC_SPI 218 IRQ_TYPE_EDGE_RISING >;
+				clocks = <&clkc CLKID_SD_EMMC_C>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+				clock-names = "core", "clkin0", "clkin1";
+				status = "disabled";
+			};
 		};
 
 		ethmac: ethernet at c9410000 {
-- 
2.9.0



From khilman at baylibre.com  Tue Aug  2 17:30:45 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue,  2 Aug 2016 17:30:45 -0700
Subject: [PATCH 2/2] MMC: meson: inital support for GXBB platforms
In-Reply-To: <20160803003045.24980-1-khilman@baylibre.com>
References: <20160803003045.24980-1-khilman@baylibre.com>
Message-ID: <20160803003045.24980-2-khilman@baylibre.com>

Initial support for the SD/eMMC controller in the Amlogic S905/GXBB
family of SoCs.

Currently working for the SD and eMMC interfaces, but not yet tested for
SDIO.

Tested external SD card and internal eMMC on meson-gxbb-p200 and
meson-gxbb-odroidc2.

TODO items:
- take full advantage of DMA-like descriptors instead of bounce buffer
- add SDIO support
---
 drivers/mmc/host/Kconfig      |   7 +
 drivers/mmc/host/Makefile     |   1 +
 drivers/mmc/host/meson-gxbb.c | 909 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 917 insertions(+)
 create mode 100644 drivers/mmc/host/meson-gxbb.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 0aa484c10c0a..2363c0cee9cc 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -332,6 +332,13 @@ config MMC_SDHCI_IPROC
 
 	  If unsure, say N.
 
+config MMC_MESON_GXBB
+	tristate "Amlogic S905/GXBB SD/MMC Host Controller support"
+	depends on ARCH_MESON && MMC
+	help
+	  This selects support for the Amlogic SD/MMC Host Controller.
+	  If you have a controller with this interface, say Y here.
+
 config MMC_MOXART
 	tristate "MOXART SD/MMC Host Controller support"
 	depends on ARCH_MOXART && MMC
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index af918d261ff9..3e0de57f55b9 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
 obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
+obj-$(CONFIG_MMC_MESON_GXBB)	+= meson-gxbb.o
 obj-$(CONFIG_MMC_MOXART)	+= moxart-mmc.o
 obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mmc.o
 obj-$(CONFIG_MMC_USDHI6ROL0)	+= usdhi6rol0.o
diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
new file mode 100644
index 000000000000..ecf7b4d2d330
--- /dev/null
+++ b/drivers/mmc/host/meson-gxbb.c
@@ -0,0 +1,909 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Kevin Hilman <khilman at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Kevin Hilman <khilman at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define DRIVER_NAME "meson-gxbb-mmc"
+
+#define SD_EMMC_CLOCK 0x0
+#define   CLK_DIV_SHIFT 0
+#define   CLK_DIV_WIDTH 6
+#define   CLK_DIV_MASK (0x3f << CLK_DIV_SHIFT)
+#define   CLK_DIV_MAX 63
+#define   CLK_SRC_SHIFT 6
+#define   CLK_SRC_WIDTH 2
+#define   CLK_SRC_MASK (0x3 << CLK_SRC_SHIFT)
+#define   CLK_SRC_XTAL 0   /* external crystal */
+#define   CLK_SRC_XTAL_RATE 24000000
+#define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
+#define   CLK_SRC_PLL_RATE 1000000000
+#define   CLK_PHASE_SHIFT 8
+#define   CLK_PHASE_MASK (0x3 << CLK_PHASE_SHIFT)
+#define   CLK_PHASE_0 0
+#define   CLK_PHASE_90 1
+#define   CLK_PHASE_180 2
+#define   CLK_PHASE_270 3
+#define   CLK_ALWAYS_ON BIT(24)
+
+#define SD_EMMC_DElAY 0x4
+#define SD_EMMC_ADJUST 0x8
+#define SD_EMMC_CALOUT 0x10
+#define SD_EMMC_START 0x40
+#define   START_DESC_INIT BIT(0)
+#define   START_DESC_BUSY BIT(1)
+#define   START_DESC_ADDR_SHIFT 2
+#define   START_DESC_ADDR_MASK (~0x3)
+
+#define SD_EMMC_CFG 0x44
+#define   CFG_BUS_WIDTH_SHIFT 0
+#define   CFG_BUS_WIDTH_MASK (0x3 << CFG_BUS_WIDTH_SHIFT)
+#define   CFG_BUS_WIDTH_1 0x0
+#define   CFG_BUS_WIDTH_4 0x1
+#define   CFG_BUS_WIDTH_8 0x2
+#define   CFG_DDR BIT(2)
+#define   CFG_BLK_LEN_SHIFT 4
+#define   CFG_BLK_LEN_MASK (0xf << CFG_BLK_LEN_SHIFT)
+#define   CFG_RESP_TIMEOUT_SHIFT 8
+#define   CFG_RESP_TIMEOUT_MASK (0xf << CFG_RESP_TIMEOUT_SHIFT)
+#define   CFG_RC_CC_SHIFT 12
+#define   CFG_RC_CC_MASK (0xf << CFG_RC_CC_SHIFT)
+#define   CFG_STOP_CLOCK BIT(22)
+
+#define SD_EMMC_STATUS 0x48
+#define   STATUS_BUSY BIT(31)
+	
+#define SD_EMMC_IRQ_EN 0x4c
+#define   IRQ_EN_MASK 0x3fff
+#define   IRQ_RXD_ERR_SHIFT 0
+#define   IRQ_RXD_ERR_MASK 0xff	
+#define   IRQ_TXD_ERR BIT(8)
+#define   IRQ_DESC_ERR BIT(9)
+#define   IRQ_RESP_ERR BIT(10)
+#define   IRQ_RESP_TIMEOUT BIT(11)
+#define   IRQ_DESC_TIMEOUT BIT(12)
+#define   IRQ_END_OF_CHAIN BIT(13)
+#define   IRQ_RESP_STATUS BIT(14)
+#define   IRQ_SDIO BIT(15)
+
+#define SD_EMMC_CMD_CFG 0x50
+#define SD_EMMC_CMD_ARG 0x54
+#define SD_EMMC_CMD_DAT 0x58
+#define SD_EMMC_CMD_RSP 0x5c
+#define SD_EMMC_CMD_RSP1 0x60
+#define SD_EMMC_CMD_RSP2 0x64
+#define SD_EMMC_CMD_RSP3 0x68
+
+#define SD_EMMC_RXD 0x94
+#define SD_EMMC_TXD 0x94
+#define SD_EMMC_LAST_REG SD_EMMC_TXD
+
+#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
+#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
+#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
+#define MUX_CLK_NUM_PARENTS 2
+
+struct meson_host {
+	struct	device		*dev;
+	struct	mmc_host	*mmc;
+	struct	mmc_request	*mrq;
+	struct	mmc_command	*cmd;
+
+	spinlock_t lock;
+	void __iomem *regs;
+#ifdef USE_REGMAP
+	struct regmap *regmap;
+#endif
+	int irq;
+	u32 ocr_mask;
+	struct clk *core_clk;
+	struct clk_mux mux;
+	struct clk *mux_clk;
+	struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
+	unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
+
+	struct clk_divider cfg_div;
+	struct clk *cfg_div_clk;
+	
+	unsigned int bounce_buf_size;
+	void *bounce_buf;
+	dma_addr_t bounce_dma_addr;
+
+	unsigned long clk_rate;
+	unsigned long clk_src_rate;
+	unsigned short clk_src_div;
+};
+
+#define reg_read(host, offset) readl(host->regs + offset)
+#define reg_write(host, offset, val) writel(val, host->regs + offset)
+
+struct cmd_cfg {
+	union {
+		struct {
+			u32 length:9;
+			u32 block_mode:1;
+			u32 r1b:1;
+			u32 end_of_chain:1;
+			u32 timeout:4;
+			u32 no_resp:1;
+			u32 no_cmd:1;
+			u32 data_io:1;
+			u32 data_wr:1;
+			u32 resp_nocrc:1;
+			u32 resp_128:1;
+			u32 resp_num:1;
+			u32 data_num:1;
+			u32 cmd_index:6;
+			u32 error:1;
+			u32 owner:1;
+#define CFG_OWNER_CPU 1
+#define CFG_OWNER_MMC 0	
+		};
+		u32 val;
+	};
+};
+
+struct sd_emmc_desc {
+	struct cmd_cfg cmd_cfg;
+	u32 cmd_arg;
+	u32 cmd_data;
+	u32 cmd_resp;
+};
+#define CMD_DATA_MASK (~0x3)
+#define CMD_DATA_BIG_ENDIAN BIT(1)
+#define CMD_DATA_SRAM BIT(0)
+#define CMD_RESP_MASK (~0x1)
+#define CMD_RESP_SRAM BIT(0)
+
+static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
+{
+	struct mmc_host *mmc = host->mmc;
+	int ret = 0;
+	u32 cfg;
+
+	if (clk_rate) {
+		if (WARN_ON(clk_rate > mmc->f_max))
+			clk_rate = mmc->f_max;
+		else if (WARN_ON(clk_rate < mmc->f_min))
+			clk_rate = mmc->f_min;
+	}
+	
+	if (clk_rate == host->clk_rate)
+		return 0;
+	
+	/* stop clock */
+	cfg = reg_read(host, SD_EMMC_CFG);
+	if (!(cfg & CFG_STOP_CLOCK)) {
+		cfg |= CFG_STOP_CLOCK;
+		reg_write(host, SD_EMMC_CFG, cfg);
+	}
+	
+	dev_dbg(host->dev, "change clock rate %lu -> %lu\n", host->clk_rate, clk_rate);
+	ret = clk_set_rate(host->cfg_div_clk, clk_rate);
+	if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
+		dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
+			 clk_rate, clk_get_rate(host->cfg_div_clk), ret);
+	else
+		host->clk_rate = clk_rate;
+
+	/* (re)start clock, if non-zero */
+	if (clk_rate) {
+		cfg = reg_read(host, SD_EMMC_CFG);
+		cfg &= ~CFG_STOP_CLOCK;
+		reg_write(host, SD_EMMC_CFG, cfg);
+	}
+	
+	return ret;
+}
+
+static int meson_mmc_clk_init(struct meson_host *host)
+{
+	struct clk_init_data init;
+	char clk_name[32];
+	int i, ret = 0;
+	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+	unsigned int mux_parent_count = 0;
+	const char *clk_div_parents[1];
+	unsigned int f_min = UINT_MAX;
+	u32 clk_reg;
+
+	/* get the mux parents from DT */
+	for ( i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+		char name[16];
+		
+		snprintf(name, sizeof(name), "clkin%d", i);
+		host->mux_parent[i] = devm_clk_get(host->dev, name);
+		if (IS_ERR(host->mux_parent[i])) {
+			ret = PTR_ERR(host->mux_parent[i]);
+			if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
+				dev_err(host->dev, "Missing clock %s\n", name);
+			host->mux_parent[i] = NULL;
+			return ret;
+		} else {
+			host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
+			mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
+			mux_parent_count++;
+			if (host->mux_parent_rate[i] < f_min)
+				f_min = host->mux_parent_rate[i];
+		}
+	}
+
+	/* cacluate f_min based on available input clocks, and max divider value */
+	if (f_min != UINT_MAX)
+		f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
+	else
+		f_min = 4000000;  /* default min: 400 MHz */
+	host->mmc->f_min = f_min;
+	
+	/* create the mux */
+	snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
+	init.name = clk_name;
+	init.ops = &clk_mux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = mux_parent_names;
+	init.num_parents = mux_parent_count;
+	
+	host->mux.reg = host->regs + SD_EMMC_CLOCK;
+	host->mux.shift = CLK_SRC_SHIFT;
+	host->mux.mask = CLK_SRC_MASK >> CLK_SRC_SHIFT;  /* FIXME: fix *_MASK to not be shifted */
+	host->mux.flags = 0;
+	host->mux.table = NULL;
+	host->mux.hw.init = &init;
+		
+	host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(host->mux_clk)))
+		return PTR_ERR(host->mux_clk);
+	
+	/* create the divider */
+	snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
+	init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(host->mux_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
+	host->cfg_div.shift = CLK_DIV_SHIFT;
+	host->cfg_div.width = CLK_DIV_WIDTH;
+	host->cfg_div.hw.init = &init;
+	host->cfg_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
+
+	host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
+		return PTR_ERR(host->cfg_div_clk);
+	
+	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+	clk_reg = 0;
+	clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
+	clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
+	clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
+	reg_write(host, SD_EMMC_CLOCK, clk_reg);
+	
+	clk_prepare_enable(host->cfg_div_clk);
+	meson_mmc_clk_set(host, f_min);
+
+	return ret;
+}
+
+static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 bus_width;
+	u32 val, orig;
+	
+	/* 
+	 * GPIO regulator, only controls switching between 1v8 and 3v3, doesn't support
+	 * MMC_POWER_OFF, MMC_POWER_ON.
+	 */	 
+	switch (ios->power_mode) {
+	case MMC_POWER_UP:
+		if (!IS_ERR(mmc->supply.vmmc))
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
+	}
+
+	meson_mmc_clk_set(host, ios->clock);
+
+	/* Bus width */
+	val = reg_read(host, SD_EMMC_CFG);
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		bus_width = CFG_BUS_WIDTH_1;
+		break;
+	case MMC_BUS_WIDTH_4:
+		bus_width = CFG_BUS_WIDTH_4;
+		break;
+	case MMC_BUS_WIDTH_8:
+		bus_width = CFG_BUS_WIDTH_8;
+		break;
+	default:
+		dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n", ios->bus_width);
+		bus_width = CFG_BUS_WIDTH_4;
+		return;
+	}
+
+	val = reg_read(host, SD_EMMC_CFG);
+	orig = val;
+
+	val &= ~CFG_BUS_WIDTH_MASK;
+	val |= bus_width << CFG_BUS_WIDTH_SHIFT;
+
+	val &= ~CFG_BLK_LEN_MASK;
+	val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
+
+	val &= ~CFG_RESP_TIMEOUT_MASK;
+	val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
+	
+	val &= ~CFG_RC_CC_MASK;
+	val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
+	
+	reg_write(host, SD_EMMC_CFG, val);
+
+	if (val != orig)
+		dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
+			__func__, orig, val);
+
+	return;
+}
+
+static int meson_mmc_wait_busy(struct mmc_host *mmc, unsigned int timeout)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 status;
+	int i;
+	
+	for ( i = timeout; i > 0; i-- ) {
+		status = reg_read(host, SD_EMMC_STATUS);
+		if (!(status & STATUS_BUSY))
+			break;
+	};
+
+	return (timeout == 0);
+}
+
+static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct mmc_command *cmd = host->cmd;
+	
+	WARN_ON(host->mrq != mrq);
+	if (cmd && !cmd->error)
+		if (meson_mmc_wait_busy(mmc, 0xfffff))  /* FIXME: hard-coded value */
+			dev_warn(host->dev, "%s: timeout busy.\n", __func__);
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+	mmc_request_done(host->mmc, mrq);
+	
+	return 0;
+}
+
+static int meson_mmc_cmd_invalid(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	cmd->error = -EINVAL;
+	meson_mmc_request_done(mmc, cmd->mrq);
+
+	return -EINVAL;
+}
+
+static int meson_mmc_check_command(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	int ret = 0;
+	
+        if (true) {  /* FIXME: for SD card only */
+		if (cmd->opcode == SD_IO_SEND_OP_COND
+		    || cmd->opcode == SD_IO_RW_DIRECT
+		    || cmd->opcode == SD_IO_RW_EXTENDED) {
+			ret = meson_mmc_cmd_invalid(mmc, cmd);
+		}
+	}
+
+	return ret;
+}
+
+static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct sd_emmc_desc *desc, desc_tmp;
+	u32 cfg;
+	u8 blk_len;
+	unsigned int xfer_bytes = 0;
+
+	/* Setup descriptors */
+	dma_rmb();
+	desc = &desc_tmp;
+	memset(desc, 0, sizeof(struct sd_emmc_desc));
+
+	desc->cmd_cfg.cmd_index = cmd->opcode;
+	desc->cmd_cfg.owner = CFG_OWNER_CPU;
+	desc->cmd_arg = cmd->arg;
+	/* FIXME: hard-coded timeouts from vendor BSP */
+        if (!cmd->data)
+                /* 10uS based. 2^10 = 10mS for only cmd timeout */
+		desc->cmd_cfg.timeout = 0xa;
+	else
+		desc->cmd_cfg.timeout = 0xc;
+
+	/* Response */
+        if (cmd->flags & MMC_RSP_PRESENT) {
+		desc->cmd_cfg.no_resp = 0;
+                if (cmd->flags & MMC_RSP_136)
+			desc->cmd_cfg.resp_128 = 1;
+		desc->cmd_cfg.resp_num = 1;
+		desc->cmd_resp = 0;
+
+		if (!(cmd->flags & MMC_RSP_CRC))
+			desc->cmd_cfg.resp_nocrc = 1;
+		
+		if (cmd->flags & MMC_RSP_BUSY)
+			desc->cmd_cfg.r1b = 1;
+	} else {
+		desc->cmd_cfg.no_resp = 1;
+	}
+
+	/* data? */
+        if (cmd->data) {
+		desc->cmd_cfg.data_io = 1;
+		if (cmd->data->blocks > 1) {
+			desc->cmd_cfg.block_mode = 1;
+			desc->cmd_cfg.length = cmd->data->blocks;
+
+			/* check if block-size matches, if not update */
+			cfg = reg_read(host, SD_EMMC_CFG);
+			blk_len = (cfg & CFG_BLK_LEN_MASK) >> CFG_BLK_LEN_SHIFT;
+			if (blk_len != ilog2(cmd->data->blksz)) {
+				dev_warn(host->dev, "%s: update blk_len %d -> %d\n",
+					__func__, blk_len, ilog2(cmd->data->blksz));
+				blk_len = ilog2(cmd->data->blksz);
+				cfg &= ~CFG_BLK_LEN_MASK;
+				cfg |= blk_len << CFG_BLK_LEN_SHIFT;
+				reg_write(host, SD_EMMC_CFG, cfg);
+			}
+		} else {
+			desc->cmd_cfg.block_mode = 0;
+			desc->cmd_cfg.length = cmd->data->blksz;
+		}
+
+		cmd->data->bytes_xfered = 0;
+		xfer_bytes = cmd->data->blksz * cmd->data->blocks;
+		/* dev_dbg(host->dev, "%s: sg_len=%u, %s %u bytes\n", __func__, */
+		/* 	cmd->data->sg_len, cmd->data->flags & MMC_DATA_WRITE ? "WRITE" : "READ", xfer_bytes); */
+		if (cmd->data->flags & MMC_DATA_WRITE) {
+			desc->cmd_cfg.data_wr = 1;
+			WARN_ON(xfer_bytes > host->bounce_buf_size);
+			sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len, host->bounce_buf, xfer_bytes);
+			cmd->data->bytes_xfered = xfer_bytes;
+			dma_wmb();
+		} else {
+			desc->cmd_cfg.data_wr = 0;
+		}
+
+		if (xfer_bytes > 0) {
+			desc->cmd_cfg.data_num = 0;
+			desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
+		} else {
+			/* write data to data_addr */
+			desc->cmd_cfg.data_num = 1;
+			desc->cmd_data = 0;
+		}
+
+	} else {
+		desc->cmd_cfg.data_io = 0;
+
+                /* Current 10uS based. 2^10 = 10mS for only cmd timeout */
+		desc->cmd_cfg.timeout = 0xa;
+	}
+	
+	host->cmd = cmd;
+
+	/* Last descriptor */
+	desc->cmd_cfg.end_of_chain = 1;
+	reg_write(host, SD_EMMC_CMD_CFG, desc->cmd_cfg.val);
+	reg_write(host, SD_EMMC_CMD_DAT, desc->cmd_data);
+	reg_write(host, SD_EMMC_CMD_RSP, desc->cmd_resp);
+	wmb();
+	reg_write(host, SD_EMMC_CMD_ARG, desc->cmd_arg);  /* this triggers the cmd */
+}
+
+static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	
+	WARN_ON(host->mrq != NULL);
+
+	/* Stop execution */
+	reg_write(host, SD_EMMC_START, 0);
+
+	/* clear, ack, enable all interrupts */
+	reg_write(host, SD_EMMC_IRQ_EN, 0);
+	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
+	reg_write(host, SD_EMMC_IRQ_EN, IRQ_EN_MASK);
+
+	host->mrq = mrq;
+	
+	if (meson_mmc_check_command(mmc, mrq->cmd))
+		return;
+	
+	if (mrq->sbc)
+		meson_mmc_start_cmd(mmc, mrq->sbc);
+	else
+		meson_mmc_start_cmd(mmc, mrq->cmd);
+
+	return;
+}
+
+static int meson_mmc_read_response(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	
+	if (!cmd) {
+		dev_dbg(host->dev, "%s: NULL command.\n", __func__);
+		return -EINVAL;
+	}
+
+	if (cmd->flags & MMC_RSP_136) {
+		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP3);
+		cmd->resp[1] = reg_read(host, SD_EMMC_CMD_RSP2);
+		cmd->resp[2] = reg_read(host, SD_EMMC_CMD_RSP1);
+		cmd->resp[3] = reg_read(host, SD_EMMC_CMD_RSP);
+	} else if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP);
+	}
+	
+	return 0;
+}
+
+static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
+{
+	struct meson_host *host = dev_id;
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd;
+	u32 irq_en, status, raw_status;
+	irqreturn_t ret = IRQ_HANDLED;
+	
+	if (WARN_ON(!host))
+		return IRQ_NONE;
+
+	if (WARN_ON(!mrq))
+		return IRQ_NONE;
+
+	if (WARN_ON(!cmd))
+		return IRQ_NONE;
+
+	spin_lock(&host->lock);
+	irq_en = reg_read(host, SD_EMMC_IRQ_EN);
+	raw_status = reg_read(host, SD_EMMC_STATUS);
+	status = raw_status & irq_en;
+
+	if (!status) {
+		dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
+			 raw_status, irq_en);
+		ret = IRQ_NONE;
+		goto out;
+	}
+
+	cmd->error = 0;
+	if (status & IRQ_RXD_ERR_MASK) {
+		dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_TXD_ERR) {
+		dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_DESC_ERR)
+		dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
+	if (status & IRQ_RESP_ERR) {
+		dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_RESP_TIMEOUT) {
+		dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
+		cmd->error = -ETIMEDOUT;
+	}
+	if (status & IRQ_DESC_TIMEOUT) {
+		dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
+		cmd->error = -ETIMEDOUT;
+	}
+	if (status & IRQ_SDIO)
+		dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
+
+	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
+		ret = IRQ_WAKE_THREAD;
+	else  {
+		dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
+			 status, cmd->opcode, cmd->arg, cmd->flags, mrq->stop ? 1 : 0);
+		if (cmd->data) {
+			struct mmc_data *data = cmd->data;
+			dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)", data->blksz, data->blocks, data->flags,
+				 data->flags & MMC_DATA_WRITE ? "write" : "",
+				 data->flags & MMC_DATA_READ ? "read" : "");
+		}
+	}
+	
+out:
+	/* ack all (enabled) interrupts */
+	reg_write(host, SD_EMMC_STATUS, status);
+
+	if (ret == IRQ_HANDLED) {
+		meson_mmc_read_response(host->mmc, cmd);
+		meson_mmc_request_done(host->mmc, cmd->mrq);
+	}
+
+	spin_unlock(&host->lock);
+       	return ret;
+}
+
+static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
+{
+	struct meson_host *host = dev_id;
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data;
+	
+	unsigned int xfer_bytes;
+	int ret = IRQ_HANDLED;
+	
+	if (WARN_ON(!mrq))
+		ret = IRQ_NONE;
+
+	if (WARN_ON(!cmd))
+		ret = IRQ_NONE;
+
+	data = cmd->data;
+	if (data) {
+		xfer_bytes = data->blksz * data->blocks;
+		if (data->flags & MMC_DATA_READ) {
+			WARN_ON(xfer_bytes > host->bounce_buf_size);
+			sg_copy_from_buffer(data->sg, data->sg_len,
+					    host->bounce_buf, xfer_bytes);
+			data->bytes_xfered = xfer_bytes;
+		}
+	}
+		
+	meson_mmc_read_response(host->mmc, cmd);
+	if (!data || !data->stop || mrq->sbc)
+		meson_mmc_request_done(host->mmc, mrq);
+	else
+		meson_mmc_start_cmd(host->mmc, data->stop);
+	
+	return ret;
+}
+
+/* 
+ * NOTE: we only need this until the GPIO/pinctrl driver can handle
+ * interrupts.  For now, the MMC core will use this for polling.
+ */
+static int meson_mmc_get_cd(struct mmc_host *mmc)
+{
+	int status = mmc_gpio_get_cd(mmc);
+	
+	if (status == -ENOSYS)
+		return 1; /* assume present */
+	
+	return status;
+}
+
+static struct mmc_host_ops meson_mmc_ops = {
+	.request	= meson_mmc_request,
+	.set_ios	= meson_mmc_set_ios,
+	.get_cd         = meson_mmc_get_cd,
+};
+
+static int meson_mmc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct meson_host *host;
+	struct mmc_host *mmc;
+	int ret;
+	
+	mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, host);
+	
+	spin_lock_init(&host->lock);
+	
+	host->core_clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(host->core_clk)) {
+		ret = PTR_ERR(host->core_clk);
+		if (ret == -EPROBE_DEFER)
+			dev_dbg(&pdev->dev, "Missing core clock.  EPROBE_DEFER\n");
+		else
+			dev_err(&pdev->dev, "Unable to get core clk (ret=%d).\n", ret);
+		goto free_host;
+	}
+
+	/* Voltage supply */
+	mmc_of_parse_voltage(np, &host->ocr_mask);
+	ret = mmc_regulator_get_supply(mmc);
+	if (ret == -EPROBE_DEFER) {
+		dev_dbg(&pdev->dev, "Missing regulator: EPROBE_DEFER");
+		goto free_host;
+	}
+	
+	if (!mmc->ocr_avail)
+		mmc->ocr_avail = host->ocr_mask;
+	
+	ret = mmc_of_parse(mmc);
+	if (ret) {
+		dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
+		goto free_host;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV; 
+		goto free_host;
+	}
+	host->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->regs)) {
+		ret = PTR_ERR(host->regs);
+		goto free_host;
+	}
+	
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq == 0) {
+		dev_err(&pdev->dev, "failed to get interrupt resource.\n");
+		ret = -EINVAL;
+		goto free_host;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, host->irq,
+					meson_mmc_irq, meson_mmc_irq_thread,
+					IRQF_SHARED, DRIVER_NAME, host);
+	if (ret)
+		goto free_host;
+	
+	/* data bounce buffer */
+	host->bounce_buf_size = SZ_512K;
+	host->bounce_buf = dma_alloc_coherent(host->dev, host->bounce_buf_size,
+					      &host->bounce_dma_addr, GFP_KERNEL);
+	if (host->bounce_buf == NULL) {
+		dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
+		ret = -ENOMEM;
+		goto free_host;
+	}
+
+	clk_prepare_enable(host->core_clk);
+
+	ret = meson_mmc_clk_init(host);
+	if (ret)
+		goto free_host;
+
+	/* Stop execution */
+	reg_write(host, SD_EMMC_START, 0);
+
+	/* clear, ack, enable all interrupts */
+	reg_write(host, SD_EMMC_IRQ_EN, 0);
+	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
+	
+	mmc->ops = &meson_mmc_ops;
+	mmc_add_host(mmc);
+
+	return 0;
+
+free_host:
+	dev_dbg(host->dev, "Failed to probe: ret=%d\n", ret);
+	if (host->core_clk)
+		clk_disable_unprepare(host->core_clk);
+	mmc_free_host(mmc);
+	return ret;
+}
+
+static int meson_mmc_remove(struct platform_device *pdev)
+{
+	struct meson_host *host = dev_get_drvdata(&pdev->dev);
+	
+	if (WARN_ON(!host))
+		return 0;
+	
+	if (host->bounce_buf)
+		dma_free_coherent(host->dev, host->bounce_buf_size,
+				  host->bounce_buf, host->bounce_dma_addr);
+
+	if (host->cfg_div_clk)
+		clk_disable_unprepare(host->cfg_div_clk);
+	
+	if (host->core_clk)
+		clk_disable_unprepare(host->core_clk);
+
+	mmc_free_host(host->mmc);
+	return 0;
+}
+
+static const struct of_device_id meson_mmc_of_match[] = {
+	{
+		.compatible = "amlogic,meson-gxbb-mmc",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
+
+static struct platform_driver meson_mmc_driver = {	
+	.probe		= meson_mmc_probe,
+	.remove		= meson_mmc_remove,
+	.driver		= {
+		.name = DRIVER_NAME,
+		.of_match_table = of_match_ptr(meson_mmc_of_match),
+	},
+};
+
+module_platform_driver(meson_mmc_driver);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_DESCRIPTION("Amlogic S905/GXBB SD/eMMC driver");
+MODULE_AUTHOR("Kevin Hilman <khilman at baylibre.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+
-- 
2.9.0



From jh80.chung at samsung.com  Tue Aug  2 17:37:09 2016
From: jh80.chung at samsung.com (Jaehoon Chung)
Date: Wed, 03 Aug 2016 09:37:09 +0900
Subject: [PATCH 2/2] MMC: meson: inital support for GXBB platforms
In-Reply-To: <20160803003045.24980-2-khilman@baylibre.com>
References: <20160803003045.24980-1-khilman@baylibre.com>
 <CGME20160803003156epcas1p2473ed7677a97642c892baefa5dcffddd@epcas1p2.samsung.com>
 <20160803003045.24980-2-khilman@baylibre.com>
Message-ID: <57A13CB5.4000006@samsung.com>

Hi Kevin,

On 08/03/2016 09:30 AM, Kevin Hilman wrote:
> Initial support for the SD/eMMC controller in the Amlogic S905/GXBB
> family of SoCs.
> 
> Currently working for the SD and eMMC interfaces, but not yet tested for
> SDIO.
> 
> Tested external SD card and internal eMMC on meson-gxbb-p200 and
> meson-gxbb-odroidc2.

Before sending patch, run the checkpatch.pl for your patch.

Best Regards,
Jaehoon Chung

> 
> TODO items:
> - take full advantage of DMA-like descriptors instead of bounce buffer
> - add SDIO support
> ---
>  drivers/mmc/host/Kconfig      |   7 +
>  drivers/mmc/host/Makefile     |   1 +
>  drivers/mmc/host/meson-gxbb.c | 909 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 917 insertions(+)
>  create mode 100644 drivers/mmc/host/meson-gxbb.c
> 
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 0aa484c10c0a..2363c0cee9cc 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -332,6 +332,13 @@ config MMC_SDHCI_IPROC
>  
>  	  If unsure, say N.
>  
> +config MMC_MESON_GXBB
> +	tristate "Amlogic S905/GXBB SD/MMC Host Controller support"
> +	depends on ARCH_MESON && MMC
> +	help
> +	  This selects support for the Amlogic SD/MMC Host Controller.
> +	  If you have a controller with this interface, say Y here.
> +
>  config MMC_MOXART
>  	tristate "MOXART SD/MMC Host Controller support"
>  	depends on ARCH_MOXART && MMC
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index af918d261ff9..3e0de57f55b9 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
>  obj-$(CONFIG_MMC_VUB300)	+= vub300.o
>  obj-$(CONFIG_MMC_USHC)		+= ushc.o
>  obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
> +obj-$(CONFIG_MMC_MESON_GXBB)	+= meson-gxbb.o
>  obj-$(CONFIG_MMC_MOXART)	+= moxart-mmc.o
>  obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mmc.o
>  obj-$(CONFIG_MMC_USDHI6ROL0)	+= usdhi6rol0.o
> diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
> new file mode 100644
> index 000000000000..ecf7b4d2d330
> --- /dev/null
> +++ b/drivers/mmc/host/meson-gxbb.c
> @@ -0,0 +1,909 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman at baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman at baylibre.com>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/init.h>
> +#include <linux/device.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/ioport.h>
> +#include <linux/regmap.h>
> +#include <linux/spinlock.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/mmc/sdio.h>
> +#include <linux/mmc/slot-gpio.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +#define DRIVER_NAME "meson-gxbb-mmc"
> +
> +#define SD_EMMC_CLOCK 0x0
> +#define   CLK_DIV_SHIFT 0
> +#define   CLK_DIV_WIDTH 6
> +#define   CLK_DIV_MASK (0x3f << CLK_DIV_SHIFT)
> +#define   CLK_DIV_MAX 63
> +#define   CLK_SRC_SHIFT 6
> +#define   CLK_SRC_WIDTH 2
> +#define   CLK_SRC_MASK (0x3 << CLK_SRC_SHIFT)
> +#define   CLK_SRC_XTAL 0   /* external crystal */
> +#define   CLK_SRC_XTAL_RATE 24000000
> +#define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
> +#define   CLK_SRC_PLL_RATE 1000000000
> +#define   CLK_PHASE_SHIFT 8
> +#define   CLK_PHASE_MASK (0x3 << CLK_PHASE_SHIFT)
> +#define   CLK_PHASE_0 0
> +#define   CLK_PHASE_90 1
> +#define   CLK_PHASE_180 2
> +#define   CLK_PHASE_270 3
> +#define   CLK_ALWAYS_ON BIT(24)
> +
> +#define SD_EMMC_DElAY 0x4
> +#define SD_EMMC_ADJUST 0x8
> +#define SD_EMMC_CALOUT 0x10
> +#define SD_EMMC_START 0x40
> +#define   START_DESC_INIT BIT(0)
> +#define   START_DESC_BUSY BIT(1)
> +#define   START_DESC_ADDR_SHIFT 2
> +#define   START_DESC_ADDR_MASK (~0x3)
> +
> +#define SD_EMMC_CFG 0x44
> +#define   CFG_BUS_WIDTH_SHIFT 0
> +#define   CFG_BUS_WIDTH_MASK (0x3 << CFG_BUS_WIDTH_SHIFT)
> +#define   CFG_BUS_WIDTH_1 0x0
> +#define   CFG_BUS_WIDTH_4 0x1
> +#define   CFG_BUS_WIDTH_8 0x2
> +#define   CFG_DDR BIT(2)
> +#define   CFG_BLK_LEN_SHIFT 4
> +#define   CFG_BLK_LEN_MASK (0xf << CFG_BLK_LEN_SHIFT)
> +#define   CFG_RESP_TIMEOUT_SHIFT 8
> +#define   CFG_RESP_TIMEOUT_MASK (0xf << CFG_RESP_TIMEOUT_SHIFT)
> +#define   CFG_RC_CC_SHIFT 12
> +#define   CFG_RC_CC_MASK (0xf << CFG_RC_CC_SHIFT)
> +#define   CFG_STOP_CLOCK BIT(22)
> +
> +#define SD_EMMC_STATUS 0x48
> +#define   STATUS_BUSY BIT(31)
> +	
> +#define SD_EMMC_IRQ_EN 0x4c
> +#define   IRQ_EN_MASK 0x3fff
> +#define   IRQ_RXD_ERR_SHIFT 0
> +#define   IRQ_RXD_ERR_MASK 0xff	
> +#define   IRQ_TXD_ERR BIT(8)
> +#define   IRQ_DESC_ERR BIT(9)
> +#define   IRQ_RESP_ERR BIT(10)
> +#define   IRQ_RESP_TIMEOUT BIT(11)
> +#define   IRQ_DESC_TIMEOUT BIT(12)
> +#define   IRQ_END_OF_CHAIN BIT(13)
> +#define   IRQ_RESP_STATUS BIT(14)
> +#define   IRQ_SDIO BIT(15)
> +
> +#define SD_EMMC_CMD_CFG 0x50
> +#define SD_EMMC_CMD_ARG 0x54
> +#define SD_EMMC_CMD_DAT 0x58
> +#define SD_EMMC_CMD_RSP 0x5c
> +#define SD_EMMC_CMD_RSP1 0x60
> +#define SD_EMMC_CMD_RSP2 0x64
> +#define SD_EMMC_CMD_RSP3 0x68
> +
> +#define SD_EMMC_RXD 0x94
> +#define SD_EMMC_TXD 0x94
> +#define SD_EMMC_LAST_REG SD_EMMC_TXD
> +
> +#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
> +#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
> +#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
> +#define MUX_CLK_NUM_PARENTS 2
> +
> +struct meson_host {
> +	struct	device		*dev;
> +	struct	mmc_host	*mmc;
> +	struct	mmc_request	*mrq;
> +	struct	mmc_command	*cmd;
> +
> +	spinlock_t lock;
> +	void __iomem *regs;
> +#ifdef USE_REGMAP
> +	struct regmap *regmap;
> +#endif
> +	int irq;
> +	u32 ocr_mask;
> +	struct clk *core_clk;
> +	struct clk_mux mux;
> +	struct clk *mux_clk;
> +	struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
> +	unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
> +
> +	struct clk_divider cfg_div;
> +	struct clk *cfg_div_clk;
> +	
> +	unsigned int bounce_buf_size;
> +	void *bounce_buf;
> +	dma_addr_t bounce_dma_addr;
> +
> +	unsigned long clk_rate;
> +	unsigned long clk_src_rate;
> +	unsigned short clk_src_div;
> +};
> +
> +#define reg_read(host, offset) readl(host->regs + offset)
> +#define reg_write(host, offset, val) writel(val, host->regs + offset)
> +
> +struct cmd_cfg {
> +	union {
> +		struct {
> +			u32 length:9;
> +			u32 block_mode:1;
> +			u32 r1b:1;
> +			u32 end_of_chain:1;
> +			u32 timeout:4;
> +			u32 no_resp:1;
> +			u32 no_cmd:1;
> +			u32 data_io:1;
> +			u32 data_wr:1;
> +			u32 resp_nocrc:1;
> +			u32 resp_128:1;
> +			u32 resp_num:1;
> +			u32 data_num:1;
> +			u32 cmd_index:6;
> +			u32 error:1;
> +			u32 owner:1;
> +#define CFG_OWNER_CPU 1
> +#define CFG_OWNER_MMC 0	
> +		};
> +		u32 val;
> +	};
> +};
> +
> +struct sd_emmc_desc {
> +	struct cmd_cfg cmd_cfg;
> +	u32 cmd_arg;
> +	u32 cmd_data;
> +	u32 cmd_resp;
> +};
> +#define CMD_DATA_MASK (~0x3)
> +#define CMD_DATA_BIG_ENDIAN BIT(1)
> +#define CMD_DATA_SRAM BIT(0)
> +#define CMD_RESP_MASK (~0x1)
> +#define CMD_RESP_SRAM BIT(0)
> +
> +static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
> +{
> +	struct mmc_host *mmc = host->mmc;
> +	int ret = 0;
> +	u32 cfg;
> +
> +	if (clk_rate) {
> +		if (WARN_ON(clk_rate > mmc->f_max))
> +			clk_rate = mmc->f_max;
> +		else if (WARN_ON(clk_rate < mmc->f_min))
> +			clk_rate = mmc->f_min;
> +	}
> +	
> +	if (clk_rate == host->clk_rate)
> +		return 0;
> +	
> +	/* stop clock */
> +	cfg = reg_read(host, SD_EMMC_CFG);
> +	if (!(cfg & CFG_STOP_CLOCK)) {
> +		cfg |= CFG_STOP_CLOCK;
> +		reg_write(host, SD_EMMC_CFG, cfg);
> +	}
> +	
> +	dev_dbg(host->dev, "change clock rate %lu -> %lu\n", host->clk_rate, clk_rate);
> +	ret = clk_set_rate(host->cfg_div_clk, clk_rate);
> +	if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
> +		dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
> +			 clk_rate, clk_get_rate(host->cfg_div_clk), ret);
> +	else
> +		host->clk_rate = clk_rate;
> +
> +	/* (re)start clock, if non-zero */
> +	if (clk_rate) {
> +		cfg = reg_read(host, SD_EMMC_CFG);
> +		cfg &= ~CFG_STOP_CLOCK;
> +		reg_write(host, SD_EMMC_CFG, cfg);
> +	}
> +	
> +	return ret;
> +}
> +
> +static int meson_mmc_clk_init(struct meson_host *host)
> +{
> +	struct clk_init_data init;
> +	char clk_name[32];
> +	int i, ret = 0;
> +	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
> +	unsigned int mux_parent_count = 0;
> +	const char *clk_div_parents[1];
> +	unsigned int f_min = UINT_MAX;
> +	u32 clk_reg;
> +
> +	/* get the mux parents from DT */
> +	for ( i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
> +		char name[16];
> +		
> +		snprintf(name, sizeof(name), "clkin%d", i);
> +		host->mux_parent[i] = devm_clk_get(host->dev, name);
> +		if (IS_ERR(host->mux_parent[i])) {
> +			ret = PTR_ERR(host->mux_parent[i]);
> +			if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
> +				dev_err(host->dev, "Missing clock %s\n", name);
> +			host->mux_parent[i] = NULL;
> +			return ret;
> +		} else {
> +			host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
> +			mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
> +			mux_parent_count++;
> +			if (host->mux_parent_rate[i] < f_min)
> +				f_min = host->mux_parent_rate[i];
> +		}
> +	}
> +
> +	/* cacluate f_min based on available input clocks, and max divider value */
> +	if (f_min != UINT_MAX)
> +		f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
> +	else
> +		f_min = 4000000;  /* default min: 400 MHz */
> +	host->mmc->f_min = f_min;
> +	
> +	/* create the mux */
> +	snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
> +	init.name = clk_name;
> +	init.ops = &clk_mux_ops;
> +	init.flags = CLK_IS_BASIC;
> +	init.parent_names = mux_parent_names;
> +	init.num_parents = mux_parent_count;
> +	
> +	host->mux.reg = host->regs + SD_EMMC_CLOCK;
> +	host->mux.shift = CLK_SRC_SHIFT;
> +	host->mux.mask = CLK_SRC_MASK >> CLK_SRC_SHIFT;  /* FIXME: fix *_MASK to not be shifted */
> +	host->mux.flags = 0;
> +	host->mux.table = NULL;
> +	host->mux.hw.init = &init;
> +		
> +	host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(host->mux_clk)))
> +		return PTR_ERR(host->mux_clk);
> +	
> +	/* create the divider */
> +	snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
> +	init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
> +	clk_div_parents[0] = __clk_get_name(host->mux_clk);
> +	init.parent_names = clk_div_parents;
> +	init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +	host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
> +	host->cfg_div.shift = CLK_DIV_SHIFT;
> +	host->cfg_div.width = CLK_DIV_WIDTH;
> +	host->cfg_div.hw.init = &init;
> +	host->cfg_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
> +
> +	host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
> +		return PTR_ERR(host->cfg_div_clk);
> +	
> +	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> +	clk_reg = 0;
> +	clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
> +	clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
> +	clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
> +	reg_write(host, SD_EMMC_CLOCK, clk_reg);
> +	
> +	clk_prepare_enable(host->cfg_div_clk);
> +	meson_mmc_clk_set(host, f_min);
> +
> +	return ret;
> +}
> +
> +static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	u32 bus_width;
> +	u32 val, orig;
> +	
> +	/* 
> +	 * GPIO regulator, only controls switching between 1v8 and 3v3, doesn't support
> +	 * MMC_POWER_OFF, MMC_POWER_ON.
> +	 */	 
> +	switch (ios->power_mode) {
> +	case MMC_POWER_UP:
> +		if (!IS_ERR(mmc->supply.vmmc))
> +			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
> +	}
> +
> +	meson_mmc_clk_set(host, ios->clock);
> +
> +	/* Bus width */
> +	val = reg_read(host, SD_EMMC_CFG);
> +	switch (ios->bus_width) {
> +	case MMC_BUS_WIDTH_1:
> +		bus_width = CFG_BUS_WIDTH_1;
> +		break;
> +	case MMC_BUS_WIDTH_4:
> +		bus_width = CFG_BUS_WIDTH_4;
> +		break;
> +	case MMC_BUS_WIDTH_8:
> +		bus_width = CFG_BUS_WIDTH_8;
> +		break;
> +	default:
> +		dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n", ios->bus_width);
> +		bus_width = CFG_BUS_WIDTH_4;
> +		return;
> +	}
> +
> +	val = reg_read(host, SD_EMMC_CFG);
> +	orig = val;
> +
> +	val &= ~CFG_BUS_WIDTH_MASK;
> +	val |= bus_width << CFG_BUS_WIDTH_SHIFT;
> +
> +	val &= ~CFG_BLK_LEN_MASK;
> +	val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
> +
> +	val &= ~CFG_RESP_TIMEOUT_MASK;
> +	val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
> +	
> +	val &= ~CFG_RC_CC_MASK;
> +	val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
> +	
> +	reg_write(host, SD_EMMC_CFG, val);
> +
> +	if (val != orig)
> +		dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
> +			__func__, orig, val);
> +
> +	return;
> +}
> +
> +static int meson_mmc_wait_busy(struct mmc_host *mmc, unsigned int timeout)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	u32 status;
> +	int i;
> +	
> +	for ( i = timeout; i > 0; i-- ) {
> +		status = reg_read(host, SD_EMMC_STATUS);
> +		if (!(status & STATUS_BUSY))
> +			break;
> +	};
> +
> +	return (timeout == 0);
> +}
> +
> +static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	struct mmc_command *cmd = host->cmd;
> +	
> +	WARN_ON(host->mrq != mrq);
> +	if (cmd && !cmd->error)
> +		if (meson_mmc_wait_busy(mmc, 0xfffff))  /* FIXME: hard-coded value */
> +			dev_warn(host->dev, "%s: timeout busy.\n", __func__);
> +
> +	host->mrq = NULL;
> +	host->cmd = NULL;
> +	mmc_request_done(host->mmc, mrq);
> +	
> +	return 0;
> +}
> +
> +static int meson_mmc_cmd_invalid(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +	cmd->error = -EINVAL;
> +	meson_mmc_request_done(mmc, cmd->mrq);
> +
> +	return -EINVAL;
> +}
> +
> +static int meson_mmc_check_command(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +	int ret = 0;
> +	
> +        if (true) {  /* FIXME: for SD card only */
> +		if (cmd->opcode == SD_IO_SEND_OP_COND
> +		    || cmd->opcode == SD_IO_RW_DIRECT
> +		    || cmd->opcode == SD_IO_RW_EXTENDED) {
> +			ret = meson_mmc_cmd_invalid(mmc, cmd);
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	struct sd_emmc_desc *desc, desc_tmp;
> +	u32 cfg;
> +	u8 blk_len;
> +	unsigned int xfer_bytes = 0;
> +
> +	/* Setup descriptors */
> +	dma_rmb();
> +	desc = &desc_tmp;
> +	memset(desc, 0, sizeof(struct sd_emmc_desc));
> +
> +	desc->cmd_cfg.cmd_index = cmd->opcode;
> +	desc->cmd_cfg.owner = CFG_OWNER_CPU;
> +	desc->cmd_arg = cmd->arg;
> +	/* FIXME: hard-coded timeouts from vendor BSP */
> +        if (!cmd->data)
> +                /* 10uS based. 2^10 = 10mS for only cmd timeout */
> +		desc->cmd_cfg.timeout = 0xa;
> +	else
> +		desc->cmd_cfg.timeout = 0xc;
> +
> +	/* Response */
> +        if (cmd->flags & MMC_RSP_PRESENT) {
> +		desc->cmd_cfg.no_resp = 0;
> +                if (cmd->flags & MMC_RSP_136)
> +			desc->cmd_cfg.resp_128 = 1;
> +		desc->cmd_cfg.resp_num = 1;
> +		desc->cmd_resp = 0;
> +
> +		if (!(cmd->flags & MMC_RSP_CRC))
> +			desc->cmd_cfg.resp_nocrc = 1;
> +		
> +		if (cmd->flags & MMC_RSP_BUSY)
> +			desc->cmd_cfg.r1b = 1;
> +	} else {
> +		desc->cmd_cfg.no_resp = 1;
> +	}
> +
> +	/* data? */
> +        if (cmd->data) {
> +		desc->cmd_cfg.data_io = 1;
> +		if (cmd->data->blocks > 1) {
> +			desc->cmd_cfg.block_mode = 1;
> +			desc->cmd_cfg.length = cmd->data->blocks;
> +
> +			/* check if block-size matches, if not update */
> +			cfg = reg_read(host, SD_EMMC_CFG);
> +			blk_len = (cfg & CFG_BLK_LEN_MASK) >> CFG_BLK_LEN_SHIFT;
> +			if (blk_len != ilog2(cmd->data->blksz)) {
> +				dev_warn(host->dev, "%s: update blk_len %d -> %d\n",
> +					__func__, blk_len, ilog2(cmd->data->blksz));
> +				blk_len = ilog2(cmd->data->blksz);
> +				cfg &= ~CFG_BLK_LEN_MASK;
> +				cfg |= blk_len << CFG_BLK_LEN_SHIFT;
> +				reg_write(host, SD_EMMC_CFG, cfg);
> +			}
> +		} else {
> +			desc->cmd_cfg.block_mode = 0;
> +			desc->cmd_cfg.length = cmd->data->blksz;
> +		}
> +
> +		cmd->data->bytes_xfered = 0;
> +		xfer_bytes = cmd->data->blksz * cmd->data->blocks;
> +		/* dev_dbg(host->dev, "%s: sg_len=%u, %s %u bytes\n", __func__, */
> +		/* 	cmd->data->sg_len, cmd->data->flags & MMC_DATA_WRITE ? "WRITE" : "READ", xfer_bytes); */
> +		if (cmd->data->flags & MMC_DATA_WRITE) {
> +			desc->cmd_cfg.data_wr = 1;
> +			WARN_ON(xfer_bytes > host->bounce_buf_size);
> +			sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len, host->bounce_buf, xfer_bytes);
> +			cmd->data->bytes_xfered = xfer_bytes;
> +			dma_wmb();
> +		} else {
> +			desc->cmd_cfg.data_wr = 0;
> +		}
> +
> +		if (xfer_bytes > 0) {
> +			desc->cmd_cfg.data_num = 0;
> +			desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
> +		} else {
> +			/* write data to data_addr */
> +			desc->cmd_cfg.data_num = 1;
> +			desc->cmd_data = 0;
> +		}
> +
> +	} else {
> +		desc->cmd_cfg.data_io = 0;
> +
> +                /* Current 10uS based. 2^10 = 10mS for only cmd timeout */
> +		desc->cmd_cfg.timeout = 0xa;
> +	}
> +	
> +	host->cmd = cmd;
> +
> +	/* Last descriptor */
> +	desc->cmd_cfg.end_of_chain = 1;
> +	reg_write(host, SD_EMMC_CMD_CFG, desc->cmd_cfg.val);
> +	reg_write(host, SD_EMMC_CMD_DAT, desc->cmd_data);
> +	reg_write(host, SD_EMMC_CMD_RSP, desc->cmd_resp);
> +	wmb();
> +	reg_write(host, SD_EMMC_CMD_ARG, desc->cmd_arg);  /* this triggers the cmd */
> +}
> +
> +static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	
> +	WARN_ON(host->mrq != NULL);
> +
> +	/* Stop execution */
> +	reg_write(host, SD_EMMC_START, 0);
> +
> +	/* clear, ack, enable all interrupts */
> +	reg_write(host, SD_EMMC_IRQ_EN, 0);
> +	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
> +	reg_write(host, SD_EMMC_IRQ_EN, IRQ_EN_MASK);
> +
> +	host->mrq = mrq;
> +	
> +	if (meson_mmc_check_command(mmc, mrq->cmd))
> +		return;
> +	
> +	if (mrq->sbc)
> +		meson_mmc_start_cmd(mmc, mrq->sbc);
> +	else
> +		meson_mmc_start_cmd(mmc, mrq->cmd);
> +
> +	return;
> +}
> +
> +static int meson_mmc_read_response(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	
> +	if (!cmd) {
> +		dev_dbg(host->dev, "%s: NULL command.\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (cmd->flags & MMC_RSP_136) {
> +		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP3);
> +		cmd->resp[1] = reg_read(host, SD_EMMC_CMD_RSP2);
> +		cmd->resp[2] = reg_read(host, SD_EMMC_CMD_RSP1);
> +		cmd->resp[3] = reg_read(host, SD_EMMC_CMD_RSP);
> +	} else if (cmd->flags & MMC_RSP_PRESENT) {
> +		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP);
> +	}
> +	
> +	return 0;
> +}
> +
> +static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
> +{
> +	struct meson_host *host = dev_id;
> +	struct mmc_request *mrq = host->mrq;
> +	struct mmc_command *cmd = host->cmd;
> +	u32 irq_en, status, raw_status;
> +	irqreturn_t ret = IRQ_HANDLED;
> +	
> +	if (WARN_ON(!host))
> +		return IRQ_NONE;
> +
> +	if (WARN_ON(!mrq))
> +		return IRQ_NONE;
> +
> +	if (WARN_ON(!cmd))
> +		return IRQ_NONE;
> +
> +	spin_lock(&host->lock);
> +	irq_en = reg_read(host, SD_EMMC_IRQ_EN);
> +	raw_status = reg_read(host, SD_EMMC_STATUS);
> +	status = raw_status & irq_en;
> +
> +	if (!status) {
> +		dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
> +			 raw_status, irq_en);
> +		ret = IRQ_NONE;
> +		goto out;
> +	}
> +
> +	cmd->error = 0;
> +	if (status & IRQ_RXD_ERR_MASK) {
> +		dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
> +		cmd->error = -EILSEQ;
> +	}
> +	if (status & IRQ_TXD_ERR) {
> +		dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
> +		cmd->error = -EILSEQ;
> +	}
> +	if (status & IRQ_DESC_ERR)
> +		dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
> +	if (status & IRQ_RESP_ERR) {
> +		dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
> +		cmd->error = -EILSEQ;
> +	}
> +	if (status & IRQ_RESP_TIMEOUT) {
> +		dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
> +		cmd->error = -ETIMEDOUT;
> +	}
> +	if (status & IRQ_DESC_TIMEOUT) {
> +		dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
> +		cmd->error = -ETIMEDOUT;
> +	}
> +	if (status & IRQ_SDIO)
> +		dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
> +
> +	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
> +		ret = IRQ_WAKE_THREAD;
> +	else  {
> +		dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
> +			 status, cmd->opcode, cmd->arg, cmd->flags, mrq->stop ? 1 : 0);
> +		if (cmd->data) {
> +			struct mmc_data *data = cmd->data;
> +			dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)", data->blksz, data->blocks, data->flags,
> +				 data->flags & MMC_DATA_WRITE ? "write" : "",
> +				 data->flags & MMC_DATA_READ ? "read" : "");
> +		}
> +	}
> +	
> +out:
> +	/* ack all (enabled) interrupts */
> +	reg_write(host, SD_EMMC_STATUS, status);
> +
> +	if (ret == IRQ_HANDLED) {
> +		meson_mmc_read_response(host->mmc, cmd);
> +		meson_mmc_request_done(host->mmc, cmd->mrq);
> +	}
> +
> +	spin_unlock(&host->lock);
> +       	return ret;
> +}
> +
> +static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
> +{
> +	struct meson_host *host = dev_id;
> +	struct mmc_request *mrq = host->mrq;
> +	struct mmc_command *cmd = host->cmd;
> +	struct mmc_data *data;
> +	
> +	unsigned int xfer_bytes;
> +	int ret = IRQ_HANDLED;
> +	
> +	if (WARN_ON(!mrq))
> +		ret = IRQ_NONE;
> +
> +	if (WARN_ON(!cmd))
> +		ret = IRQ_NONE;
> +
> +	data = cmd->data;
> +	if (data) {
> +		xfer_bytes = data->blksz * data->blocks;
> +		if (data->flags & MMC_DATA_READ) {
> +			WARN_ON(xfer_bytes > host->bounce_buf_size);
> +			sg_copy_from_buffer(data->sg, data->sg_len,
> +					    host->bounce_buf, xfer_bytes);
> +			data->bytes_xfered = xfer_bytes;
> +		}
> +	}
> +		
> +	meson_mmc_read_response(host->mmc, cmd);
> +	if (!data || !data->stop || mrq->sbc)
> +		meson_mmc_request_done(host->mmc, mrq);
> +	else
> +		meson_mmc_start_cmd(host->mmc, data->stop);
> +	
> +	return ret;
> +}
> +
> +/* 
> + * NOTE: we only need this until the GPIO/pinctrl driver can handle
> + * interrupts.  For now, the MMC core will use this for polling.
> + */
> +static int meson_mmc_get_cd(struct mmc_host *mmc)
> +{
> +	int status = mmc_gpio_get_cd(mmc);
> +	
> +	if (status == -ENOSYS)
> +		return 1; /* assume present */
> +	
> +	return status;
> +}
> +
> +static struct mmc_host_ops meson_mmc_ops = {
> +	.request	= meson_mmc_request,
> +	.set_ios	= meson_mmc_set_ios,
> +	.get_cd         = meson_mmc_get_cd,
> +};
> +
> +static int meson_mmc_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct resource *res;
> +	struct meson_host *host;
> +	struct mmc_host *mmc;
> +	int ret;
> +	
> +	mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
> +	if (!mmc)
> +		return -ENOMEM;
> +	host = mmc_priv(mmc);
> +	host->mmc = mmc;
> +	host->dev = &pdev->dev;
> +	dev_set_drvdata(&pdev->dev, host);
> +	
> +	spin_lock_init(&host->lock);
> +	
> +	host->core_clk = devm_clk_get(&pdev->dev, "core");
> +	if (IS_ERR(host->core_clk)) {
> +		ret = PTR_ERR(host->core_clk);
> +		if (ret == -EPROBE_DEFER)
> +			dev_dbg(&pdev->dev, "Missing core clock.  EPROBE_DEFER\n");
> +		else
> +			dev_err(&pdev->dev, "Unable to get core clk (ret=%d).\n", ret);
> +		goto free_host;
> +	}
> +
> +	/* Voltage supply */
> +	mmc_of_parse_voltage(np, &host->ocr_mask);
> +	ret = mmc_regulator_get_supply(mmc);
> +	if (ret == -EPROBE_DEFER) {
> +		dev_dbg(&pdev->dev, "Missing regulator: EPROBE_DEFER");
> +		goto free_host;
> +	}
> +	
> +	if (!mmc->ocr_avail)
> +		mmc->ocr_avail = host->ocr_mask;
> +	
> +	ret = mmc_of_parse(mmc);
> +	if (ret) {
> +		dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
> +		goto free_host;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		ret = -ENODEV; 
> +		goto free_host;
> +	}
> +	host->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(host->regs)) {
> +		ret = PTR_ERR(host->regs);
> +		goto free_host;
> +	}
> +	
> +	host->irq = platform_get_irq(pdev, 0);
> +	if (host->irq == 0) {
> +		dev_err(&pdev->dev, "failed to get interrupt resource.\n");
> +		ret = -EINVAL;
> +		goto free_host;
> +	}
> +
> +	ret = devm_request_threaded_irq(&pdev->dev, host->irq,
> +					meson_mmc_irq, meson_mmc_irq_thread,
> +					IRQF_SHARED, DRIVER_NAME, host);
> +	if (ret)
> +		goto free_host;
> +	
> +	/* data bounce buffer */
> +	host->bounce_buf_size = SZ_512K;
> +	host->bounce_buf = dma_alloc_coherent(host->dev, host->bounce_buf_size,
> +					      &host->bounce_dma_addr, GFP_KERNEL);
> +	if (host->bounce_buf == NULL) {
> +		dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
> +		ret = -ENOMEM;
> +		goto free_host;
> +	}
> +
> +	clk_prepare_enable(host->core_clk);
> +
> +	ret = meson_mmc_clk_init(host);
> +	if (ret)
> +		goto free_host;
> +
> +	/* Stop execution */
> +	reg_write(host, SD_EMMC_START, 0);
> +
> +	/* clear, ack, enable all interrupts */
> +	reg_write(host, SD_EMMC_IRQ_EN, 0);
> +	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
> +	
> +	mmc->ops = &meson_mmc_ops;
> +	mmc_add_host(mmc);
> +
> +	return 0;
> +
> +free_host:
> +	dev_dbg(host->dev, "Failed to probe: ret=%d\n", ret);
> +	if (host->core_clk)
> +		clk_disable_unprepare(host->core_clk);
> +	mmc_free_host(mmc);
> +	return ret;
> +}
> +
> +static int meson_mmc_remove(struct platform_device *pdev)
> +{
> +	struct meson_host *host = dev_get_drvdata(&pdev->dev);
> +	
> +	if (WARN_ON(!host))
> +		return 0;
> +	
> +	if (host->bounce_buf)
> +		dma_free_coherent(host->dev, host->bounce_buf_size,
> +				  host->bounce_buf, host->bounce_dma_addr);
> +
> +	if (host->cfg_div_clk)
> +		clk_disable_unprepare(host->cfg_div_clk);
> +	
> +	if (host->core_clk)
> +		clk_disable_unprepare(host->core_clk);
> +
> +	mmc_free_host(host->mmc);
> +	return 0;
> +}
> +
> +static const struct of_device_id meson_mmc_of_match[] = {
> +	{
> +		.compatible = "amlogic,meson-gxbb-mmc",
> +	},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
> +
> +static struct platform_driver meson_mmc_driver = {	
> +	.probe		= meson_mmc_probe,
> +	.remove		= meson_mmc_remove,
> +	.driver		= {
> +		.name = DRIVER_NAME,
> +		.of_match_table = of_match_ptr(meson_mmc_of_match),
> +	},
> +};
> +
> +module_platform_driver(meson_mmc_driver);
> +
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_DESCRIPTION("Amlogic S905/GXBB SD/eMMC driver");
> +MODULE_AUTHOR("Kevin Hilman <khilman at baylibre.com>");
> +MODULE_LICENSE("Dual BSD/GPL");
> +
> 



From wagi at monom.org  Wed Aug  3 05:03:07 2016
From: wagi at monom.org (Daniel Wagner)
Date: Wed,  3 Aug 2016 14:03:07 +0200
Subject: [PATCH v0 0/4] Use complete() instead of complete_all()
Message-ID: <1470225791-16613-1-git-send-email-wagi@monom.org>

From: Daniel Wagner <daniel.wagner at bmw-carit.de>

Hi,

Using complete_all() is not wrong per se but it suggest that there
might be more than one reader. For -rt I am reviewing all
complete_all() users and would like to leave only the real ones in the
tree. The main problem for -rt about complete_all() is that it can be
uses inside IRQ context and that can lead to unbounded amount work
inside the interrupt handler. That is a no no for -rt.

The patches grouped per subsystem and in small batches to allow
reviewing. Unfortanatly I am not so good in coming up with unique
commit message, so please bear with me in that regard. I could also
squash them together, although each patch containts a very short
reasoning why there is only one waiter. Let me know what you rather
prefer. One patch which updates all complete_all() users or those 4
patches with some reasoning.

It is only test compiled because I don't have the all the hardware.

cheers,
daniel

Daniel Wagner (4):
  i2c: bcm-iproc: Use complete() instead of complete_all()
  i2c: bcm-kona: Use complete() instead of complete_all()
  i2c: brcmstb: Use complete() instead of complete_all()
  i2c: meson: Use complete() instead of complete_all()

 drivers/i2c/busses/i2c-bcm-iproc.c | 2 +-
 drivers/i2c/busses/i2c-bcm-kona.c  | 2 +-
 drivers/i2c/busses/i2c-brcmstb.c   | 2 +-
 drivers/i2c/busses/i2c-meson.c     | 6 +++---
 4 files changed, 6 insertions(+), 6 deletions(-)

-- 
2.7.4


From wagi at monom.org  Wed Aug  3 05:03:09 2016
From: wagi at monom.org (Daniel Wagner)
Date: Wed,  3 Aug 2016 14:03:09 +0200
Subject: [PATCH v0 2/4] i2c: bcm-kona: Use complete() instead of complete_all()
In-Reply-To: <1470225791-16613-1-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
Message-ID: <1470225791-16613-3-git-send-email-wagi@monom.org>

From: Daniel Wagner <daniel.wagner at bmw-carit.de>

There is only one waiter for the completion, therefore there
is no need to use complete_all(). Let's make that clear by
using complete() instead of complete_all().

The usage pattern of the completion is:

bcm_kona_send_i2c_cmd()
  reinit_completion()
  ...
  bcm_kona_i2c_send_cmd_to_ctrl()
  ...
  wait_for_completion_timeout()

Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>
---
 drivers/i2c/busses/i2c-bcm-kona.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
index ac9f476..f987432 100644
--- a/drivers/i2c/busses/i2c-bcm-kona.c
+++ b/drivers/i2c/busses/i2c-bcm-kona.c
@@ -229,7 +229,7 @@ static irqreturn_t bcm_kona_i2c_isr(int irq, void *devid)
 		       dev->base + TXFCR_OFFSET);
 
 	writel(status & ~ISR_RESERVED_MASK, dev->base + ISR_OFFSET);
-	complete_all(&dev->done);
+	complete(&dev->done);
 
 	return IRQ_HANDLED;
 }
-- 
2.7.4


From wagi at monom.org  Wed Aug  3 05:03:08 2016
From: wagi at monom.org (Daniel Wagner)
Date: Wed,  3 Aug 2016 14:03:08 +0200
Subject: [PATCH v0 1/4] i2c: bcm-iproc: Use complete() instead of
 complete_all()
In-Reply-To: <1470225791-16613-1-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
Message-ID: <1470225791-16613-2-git-send-email-wagi@monom.org>

From: Daniel Wagner <daniel.wagner at bmw-carit.de>

There is only one waiter for the completion, therefore there
is no need to use complete_all(). Let's make that clear by
using complete() instead of complete_all().

The usage pattern of the completion is:

bcm_iproc_i2c_xfer_single_msg()
  reinit_completion()
  ...
  (activate the transfer)
  ...
  wait_for_completion_timeout()

Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>
---
 drivers/i2c/busses/i2c-bcm-iproc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index 19c8438..95f7cac 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -158,7 +158,7 @@ static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data)
 
 	if (status & BIT(IS_M_START_BUSY_SHIFT)) {
 		iproc_i2c->xfer_is_done = 1;
-		complete_all(&iproc_i2c->done);
+		complete(&iproc_i2c->done);
 	}
 
 	writel(status, iproc_i2c->base + IS_OFFSET);
-- 
2.7.4


From wagi at monom.org  Wed Aug  3 05:03:10 2016
From: wagi at monom.org (Daniel Wagner)
Date: Wed,  3 Aug 2016 14:03:10 +0200
Subject: [PATCH v0 3/4] i2c: brcmstb: Use complete() instead of complete_all()
In-Reply-To: <1470225791-16613-1-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
Message-ID: <1470225791-16613-4-git-send-email-wagi@monom.org>

From: Daniel Wagner <daniel.wagner at bmw-carit.de>

There is only one waiter for the completion, therefore there
is no need to use complete_all(). Let's make that clear by
using complete() instead of complete_all().

The usage pattern of the completion is:

brcmstb_send_i2c_cmd()
  reinit_completion()
  ...
  /* initiate transfer by setting iic_enable */
  ...
  brcmstb_i2c_wait_for_completion()

Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>
---
 drivers/i2c/busses/i2c-brcmstb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 6a8cfc1..ab4ff96 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -228,7 +228,7 @@ static irqreturn_t brcmstb_i2c_isr(int irq, void *devid)
 		return IRQ_NONE;
 
 	brcmstb_i2c_enable_disable_irq(dev, INT_DISABLE);
-	complete_all(&dev->done);
+	complete(&dev->done);
 
 	dev_dbg(dev->device, "isr handled");
 	return IRQ_HANDLED;
-- 
2.7.4


From wagi at monom.org  Wed Aug  3 05:03:11 2016
From: wagi at monom.org (Daniel Wagner)
Date: Wed,  3 Aug 2016 14:03:11 +0200
Subject: [PATCH v0 4/4] i2c: meson: Use complete() instead of complete_all()
In-Reply-To: <1470225791-16613-1-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
Message-ID: <1470225791-16613-5-git-send-email-wagi@monom.org>

From: Daniel Wagner <daniel.wagner at bmw-carit.de>

There is only one waiter for the completion, therefore there
is no need to use complete_all(). Let's make that clear by
using complete() instead of complete_all().

The usage pattern of the completion is:

meson_i2c_xfer_msg()
  reinit_completion()
  ...
  /* Start the transfer */
  ...
  wait_for_completion_timeout()

Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>
---
 drivers/i2c/busses/i2c-meson.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 71d3929..76e2898 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -211,7 +211,7 @@ static void meson_i2c_stop(struct meson_i2c *i2c)
 		meson_i2c_add_token(i2c, TOKEN_STOP);
 	} else {
 		i2c->state = STATE_IDLE;
-		complete_all(&i2c->done);
+		complete(&i2c->done);
 	}
 }
 
@@ -238,7 +238,7 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
 		dev_dbg(i2c->dev, "error bit set\n");
 		i2c->error = -ENXIO;
 		i2c->state = STATE_IDLE;
-		complete_all(&i2c->done);
+		complete(&i2c->done);
 		goto out;
 	}
 
@@ -269,7 +269,7 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
 		break;
 	case STATE_STOP:
 		i2c->state = STATE_IDLE;
-		complete_all(&i2c->done);
+		complete(&i2c->done);
 		break;
 	case STATE_IDLE:
 		break;
-- 
2.7.4


From khilman at baylibre.com  Wed Aug  3 08:27:48 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 3 Aug 2016 08:27:48 -0700
Subject: [PATCH 2/2] MMC: meson: inital support for GXBB platforms
In-Reply-To: <57A13CB5.4000006@samsung.com>
References: <20160803003045.24980-1-khilman@baylibre.com>
 <CGME20160803003156epcas1p2473ed7677a97642c892baefa5dcffddd@epcas1p2.samsung.com>
 <20160803003045.24980-2-khilman@baylibre.com> <57A13CB5.4000006@samsung.com>
Message-ID: <CAOi56cXq2Vqz+7xT1J7NO01cV7HwMt=U-_7NPwEFf1D01R2VXQ@mail.gmail.com>

On Tue, Aug 2, 2016 at 5:37 PM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
> Hi Kevin,
>
> On 08/03/2016 09:30 AM, Kevin Hilman wrote:
>> Initial support for the SD/eMMC controller in the Amlogic S905/GXBB
>> family of SoCs.
>>
>> Currently working for the SD and eMMC interfaces, but not yet tested for
>> SDIO.
>>
>> Tested external SD card and internal eMMC on meson-gxbb-p200 and
>> meson-gxbb-odroidc2.
>
> Before sending patch, run the checkpatch.pl for your patch.

Yes, sorry about that.  This patch was sent prematurely.

Kevin


From kdasu.kdev at gmail.com  Wed Aug  3 09:00:23 2016
From: kdasu.kdev at gmail.com (Kamal Dasu)
Date: Wed, 3 Aug 2016 12:00:23 -0400
Subject: [PATCH v0 3/4] i2c: brcmstb: Use complete() instead of
 complete_all()
In-Reply-To: <1470225791-16613-4-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
 <1470225791-16613-4-git-send-email-wagi@monom.org>
Message-ID: <CAC=U0a07p0Dx1UAme0=4b5DWpbVZvqk2nSN_TCXCGtVQM=U=Yw@mail.gmail.com>

LGTM

On Wed, Aug 3, 2016 at 8:03 AM, Daniel Wagner <wagi at monom.org> wrote:
> From: Daniel Wagner <daniel.wagner at bmw-carit.de>
>
> There is only one waiter for the completion, therefore there
> is no need to use complete_all(). Let's make that clear by
> using complete() instead of complete_all().
>
> The usage pattern of the completion is:
>
> brcmstb_send_i2c_cmd()
>   reinit_completion()
>   ...
>   /* initiate transfer by setting iic_enable */
>   ...
>   brcmstb_i2c_wait_for_completion()
>
> Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>

Reviewed-by: Kamal Dasu <kdasu.kdev at gmail.com>

> ---
>  drivers/i2c/busses/i2c-brcmstb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
> index 6a8cfc1..ab4ff96 100644
> --- a/drivers/i2c/busses/i2c-brcmstb.c
> +++ b/drivers/i2c/busses/i2c-brcmstb.c
> @@ -228,7 +228,7 @@ static irqreturn_t brcmstb_i2c_isr(int irq, void *devid)
>                 return IRQ_NONE;
>
>         brcmstb_i2c_enable_disable_irq(dev, INT_DISABLE);
> -       complete_all(&dev->done);
> +       complete(&dev->done);
>
>         dev_dbg(dev->device, "isr handled");
>         return IRQ_HANDLED;
> --
> 2.7.4


From ray.jui at broadcom.com  Wed Aug  3 09:36:10 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Wed, 3 Aug 2016 09:36:10 -0700
Subject: [PATCH v0 1/4] i2c: bcm-iproc: Use complete() instead of
 complete_all()
In-Reply-To: <1470225791-16613-2-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
 <1470225791-16613-2-git-send-email-wagi@monom.org>
Message-ID: <32341d5e-a3a1-368e-8319-67b95bb7ade8@broadcom.com>

Hi Daniel,

On 8/3/2016 5:03 AM, Daniel Wagner wrote:
> From: Daniel Wagner <daniel.wagner at bmw-carit.de>
>
> There is only one waiter for the completion, therefore there
> is no need to use complete_all(). Let's make that clear by
> using complete() instead of complete_all().
>
> The usage pattern of the completion is:
>
> bcm_iproc_i2c_xfer_single_msg()
>   reinit_completion()
>   ...
>   (activate the transfer)
>   ...
>   wait_for_completion_timeout()
>
> Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>
> ---
>  drivers/i2c/busses/i2c-bcm-iproc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
> index 19c8438..95f7cac 100644
> --- a/drivers/i2c/busses/i2c-bcm-iproc.c
> +++ b/drivers/i2c/busses/i2c-bcm-iproc.c
> @@ -158,7 +158,7 @@ static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data)
>
>  	if (status & BIT(IS_M_START_BUSY_SHIFT)) {
>  		iproc_i2c->xfer_is_done = 1;
> -		complete_all(&iproc_i2c->done);
> +		complete(&iproc_i2c->done);
>  	}
>
>  	writel(status, iproc_i2c->base + IS_OFFSET);
>

Yes each time there's only one waiter invoked from the main transfer 
routine 'bcm_iproc_i2c_xfer_single_msg'.

This change looks good to me, thanks!

Acked-by: Ray Jui <ray.jui at broadcom.com>


From ray.jui at broadcom.com  Wed Aug  3 09:38:11 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Wed, 3 Aug 2016 09:38:11 -0700
Subject: [PATCH v0 2/4] i2c: bcm-kona: Use complete() instead of
 complete_all()
In-Reply-To: <1470225791-16613-3-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
 <1470225791-16613-3-git-send-email-wagi@monom.org>
Message-ID: <f47779be-5e1e-cbf2-b590-fdd9a0e80917@broadcom.com>

Hi Daniel,

On 8/3/2016 5:03 AM, Daniel Wagner wrote:
> From: Daniel Wagner <daniel.wagner at bmw-carit.de>
>
> There is only one waiter for the completion, therefore there
> is no need to use complete_all(). Let's make that clear by
> using complete() instead of complete_all().
>
> The usage pattern of the completion is:
>
> bcm_kona_send_i2c_cmd()
>   reinit_completion()
>   ...
>   bcm_kona_i2c_send_cmd_to_ctrl()
>   ...
>   wait_for_completion_timeout()
>
> Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>
> ---
>  drivers/i2c/busses/i2c-bcm-kona.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
> index ac9f476..f987432 100644
> --- a/drivers/i2c/busses/i2c-bcm-kona.c
> +++ b/drivers/i2c/busses/i2c-bcm-kona.c
> @@ -229,7 +229,7 @@ static irqreturn_t bcm_kona_i2c_isr(int irq, void *devid)
>  		       dev->base + TXFCR_OFFSET);
>
>  	writel(status & ~ISR_RESERVED_MASK, dev->base + ISR_OFFSET);
> -	complete_all(&dev->done);
> +	complete(&dev->done);
>
>  	return IRQ_HANDLED;
>  }
>

This change looks good me! Thanks.

Acked-by: Ray Jui <ray.jui at broadcom.com>


From khilman at baylibre.com  Wed Aug  3 15:13:41 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 3 Aug 2016 15:13:41 -0700
Subject: [PATCH 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <20160803003045.24980-1-khilman@baylibre.com>
References: <20160803003045.24980-1-khilman@baylibre.com>
Message-ID: <CAOi56cUABXzQ=iXF0xxc4ZSVWyCdTes0_9raGtzJC-_1yMnVsQ@mail.gmail.com>

On Tue, Aug 2, 2016 at 5:30 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Add binding and basic support for the SD/eMMC controller on Amlogic
> S905/GXBB devices.
>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Oops, please disregard.  Sent due to a missing "--dry-run" with
git-send-email. :(

Kevin


From khilman at baylibre.com  Wed Aug  3 16:18:42 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed,  3 Aug 2016 16:18:42 -0700
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
Message-ID: <20160803231843.23012-1-khilman@baylibre.com>

Add binding and basic support for the SD/eMMC controller on Amlogic
S905/GXBB devices.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 .../devicetree/bindings/mmc/amlogic,meson-gxbb.txt | 29 +++++++++
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 74 ++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   | 71 +++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 36 ++++++++++-
 4 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt

diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
new file mode 100644
index 000000000000..2bfdf47018c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
@@ -0,0 +1,29 @@
+Amlogic SD / eMMC controller for S905/GXBB family SoCs
+
+The MMC 5.1 compliant host controller on Amlogic provides the
+interface for SD, eMMC and SDIO devices.
+
+This file documents the properties in addition to those available in
+the MMC core bindings, documented by mmc.txt.
+
+Required properties:
+- compatible : contains "amlogic,meson-gxbb"
+- clocks     : A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
+- clock-names: Should contain the following:
+	"core" - Main peripheral bus clock
+	"clkin0" - Parent clock of internal mux
+	"clkin1" - Other parent clock of internal mux
+  The driver has an interal mux clock which switches between clkin0 and clkin1 depending on the
+  clock rate requested by the MMC core.
+
+Example:
+
+	sd_emmc_a: mmc at 70000 {
+        	compatible = "amlogic,meson-gxbb-mmc";
+		reg = <0x0 0x70000 0x0 0x2000>;
+                interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+		clock-names = "core", "clkin0", "clkin1";
+		pinctrl-0 = <&emmc_pins>;
+	};
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 90a84c514d3d..f41d8fe5c706 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -73,6 +73,45 @@
 			default-state = "off";
 		};
 	};
+
+	mmc_iv: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "mmc-gpio-supply";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+		gpio-states = <0 1>;
+
+		/*
+		 * Based on ODROID-C2 schematics:
+		 * signal name: IO_TF_3V3N_1V8, GPIOAO bit 3
+		 */
+		states = <3300000 0
+			  1800000 1>;
+	};
+
+	vcc1v8: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	vcc3v3: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 &uart_AO {
@@ -87,3 +126,38 @@
 	pinctrl-names = "default";
 };
 
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&mmc_iv>;
+	voltage-ranges = <1800 3300>;
+};
+
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&vcc3v3>;
+	vmmcq-sumpply = <&vcc1v8>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index f4f30f674b4c..77698815943a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -57,6 +57,42 @@
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x40000000>;
 	};
+
+	mmc_iv: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "mmc-gpio-supply";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpio-states = <0 1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+			  3300000 1>;
+	};
+
+	vddio_boot: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	vcc_3v3: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 /* This UART is brought out to the DB9 connector */
@@ -72,3 +108,38 @@
 	pinctrl-names = "default";
 };
 
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&mmc_iv>;
+};
+
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&vcc_3v3>;
+	vmmcq-sumpply = <&vddio_boot>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 35c8b2beb05c..2c200f96467c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -247,7 +247,8 @@
 					mux {
 						groups = "emmc_nand_d07",
 						       "emmc_cmd",
-						       "emmc_clk";
+						       "emmc_clk",
+						       "emmc_ds";
 						function = "emmc";
 					};
 				};
@@ -330,6 +331,39 @@
 			#address-cells = <2>;
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+
+			sd_emmc_a: mmc at 70000 {
+				compatible = "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x70000 0x0 0x2000>;
+				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&clkc CLKID_SD_EMMC_A>,
+					 <&xtal>,
+					 <&clkc CLKID_FCLK_DIV2>;
+				clock-names = "core", "clkin0", "clkin1";
+				status = "disabled";
+			};
+
+			sd_emmc_b: mmc at 72000 {
+				compatible = "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x72000 0x0 0x2000>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&clkc CLKID_SD_EMMC_B>,
+					 <&xtal>,
+					 <&clkc CLKID_FCLK_DIV2>;
+				clock-names = "core", "clkin0", "clkin1";
+				status = "disabled";
+			};
+
+			sd_emmc_c: mmc at 74000 {
+				compatible = "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x74000 0x0 0x2000>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&clkc CLKID_SD_EMMC_C>,
+					 <&xtal>,
+					 <&clkc CLKID_FCLK_DIV2>;
+				clock-names = "core", "clkin0", "clkin1";
+				status = "disabled";
+			};
 		};
 
 		ethmac: ethernet at c9410000 {
-- 
2.9.0



From khilman at baylibre.com  Wed Aug  3 16:18:43 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed,  3 Aug 2016 16:18:43 -0700
Subject: [PATCH v2 2/2] MMC: meson: initial support for GXBB platforms
In-Reply-To: <20160803231843.23012-1-khilman@baylibre.com>
References: <20160803231843.23012-1-khilman@baylibre.com>
Message-ID: <20160803231843.23012-2-khilman@baylibre.com>

Initial support for the SD/eMMC controller in the Amlogic S905/GXBB
family of SoCs.

Currently working for the SD and eMMC interfaces, but not yet tested
for SDIO.

Tested external SD card and internal eMMC on meson-gxbb-p200 and
meson-gxbb-odroidc2.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 MAINTAINERS                   |   1 +
 drivers/mmc/host/Kconfig      |  10 +
 drivers/mmc/host/Makefile     |   1 +
 drivers/mmc/host/meson-gxbb.c | 918 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 930 insertions(+)
 create mode 100644 drivers/mmc/host/meson-gxbb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7304d2e37a98..3762e46811f3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -972,6 +972,7 @@ F:	arch/arm/mach-meson/
 F:	arch/arm/boot/dts/meson*
 F:	arch/arm64/boot/dts/amlogic/
 F: 	drivers/pinctrl/meson/
+F:      drivers/mmc/host/meson*
 N:	meson
 
 ARM/Annapurna Labs ALPINE ARCHITECTURE
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 0aa484c10c0a..4c3d091f7548 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -332,6 +332,16 @@ config MMC_SDHCI_IPROC
 
 	  If unsure, say N.
 
+config MMC_MESON_GXBB
+	tristate "Amlogic S905/GXBB SD/MMC Host Controller support"
+	depends on ARCH_MESON && MMC
+	help
+	  This selects support for the Amlogic SD/MMC Host Controller
+	  found on the S905/GXBB family of SoCs.  This controller is
+	  MMC 5.1 compliant and support SD, eMMC and SDIO interfaces.
+
+	  If you have a controller with this interface, say Y here.
+
 config MMC_MOXART
 	tristate "MOXART SD/MMC Host Controller support"
 	depends on ARCH_MOXART && MMC
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index af918d261ff9..3e0de57f55b9 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
 obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
+obj-$(CONFIG_MMC_MESON_GXBB)	+= meson-gxbb.o
 obj-$(CONFIG_MMC_MOXART)	+= moxart-mmc.o
 obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mmc.o
 obj-$(CONFIG_MMC_USDHI6ROL0)	+= usdhi6rol0.o
diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
new file mode 100644
index 000000000000..10eac41cf31a
--- /dev/null
+++ b/drivers/mmc/host/meson-gxbb.c
@@ -0,0 +1,918 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Kevin Hilman <khilman at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Kevin Hilman <khilman at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define DRIVER_NAME "meson-gxbb-mmc"
+
+#define SD_EMMC_CLOCK 0x0
+#define   CLK_DIV_SHIFT 0
+#define   CLK_DIV_WIDTH 6
+#define   CLK_DIV_MASK 0x3f
+#define   CLK_DIV_MAX 63
+#define   CLK_SRC_SHIFT 6
+#define   CLK_SRC_WIDTH 2
+#define   CLK_SRC_MASK 0x3
+#define   CLK_SRC_XTAL 0   /* external crystal */
+#define   CLK_SRC_XTAL_RATE 24000000
+#define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
+#define   CLK_SRC_PLL_RATE 1000000000
+#define   CLK_PHASE_SHIFT 8
+#define   CLK_PHASE_MASK 0x3
+#define   CLK_PHASE_0 0
+#define   CLK_PHASE_90 1
+#define   CLK_PHASE_180 2
+#define   CLK_PHASE_270 3
+#define   CLK_ALWAYS_ON BIT(24)
+
+#define SD_EMMC_DElAY 0x4
+#define SD_EMMC_ADJUST 0x8
+#define SD_EMMC_CALOUT 0x10
+#define SD_EMMC_START 0x40
+#define   START_DESC_INIT BIT(0)
+#define   START_DESC_BUSY BIT(1)
+#define   START_DESC_ADDR_SHIFT 2
+#define   START_DESC_ADDR_MASK (~0x3)
+
+#define SD_EMMC_CFG 0x44
+#define   CFG_BUS_WIDTH_SHIFT 0
+#define   CFG_BUS_WIDTH_MASK 0x3
+#define   CFG_BUS_WIDTH_1 0x0
+#define   CFG_BUS_WIDTH_4 0x1
+#define   CFG_BUS_WIDTH_8 0x2
+#define   CFG_DDR BIT(2)
+#define   CFG_BLK_LEN_SHIFT 4
+#define   CFG_BLK_LEN_MASK 0xf
+#define   CFG_RESP_TIMEOUT_SHIFT 8
+#define   CFG_RESP_TIMEOUT_MASK 0xf
+#define   CFG_RC_CC_SHIFT 12
+#define   CFG_RC_CC_MASK 0xf
+#define   CFG_STOP_CLOCK BIT(22)
+#define   CFG_CLK_ALWAYS_ON BIT(18)
+#define   CFG_AUTO_CLK BIT(23)
+
+#define SD_EMMC_STATUS 0x48
+#define   STATUS_BUSY BIT(31)
+
+#define SD_EMMC_IRQ_EN 0x4c
+#define   IRQ_EN_MASK 0x3fff
+#define   IRQ_RXD_ERR_SHIFT 0
+#define   IRQ_RXD_ERR_MASK 0xff
+#define   IRQ_TXD_ERR BIT(8)
+#define   IRQ_DESC_ERR BIT(9)
+#define   IRQ_RESP_ERR BIT(10)
+#define   IRQ_RESP_TIMEOUT BIT(11)
+#define   IRQ_DESC_TIMEOUT BIT(12)
+#define   IRQ_END_OF_CHAIN BIT(13)
+#define   IRQ_RESP_STATUS BIT(14)
+#define   IRQ_SDIO BIT(15)
+
+#define SD_EMMC_CMD_CFG 0x50
+#define SD_EMMC_CMD_ARG 0x54
+#define SD_EMMC_CMD_DAT 0x58
+#define SD_EMMC_CMD_RSP 0x5c
+#define SD_EMMC_CMD_RSP1 0x60
+#define SD_EMMC_CMD_RSP2 0x64
+#define SD_EMMC_CMD_RSP3 0x68
+
+#define SD_EMMC_RXD 0x94
+#define SD_EMMC_TXD 0x94
+#define SD_EMMC_LAST_REG SD_EMMC_TXD
+
+#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
+#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
+#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
+#define MUX_CLK_NUM_PARENTS 2
+
+struct meson_host {
+	struct	device		*dev;
+	struct	mmc_host	*mmc;
+	struct	mmc_request	*mrq;
+	struct	mmc_command	*cmd;
+
+	spinlock_t lock;
+	void __iomem *regs;
+#ifdef USE_REGMAP
+	struct regmap *regmap;
+#endif
+	int irq;
+	u32 ocr_mask;
+	struct clk *core_clk;
+	struct clk_mux mux;
+	struct clk *mux_clk;
+	struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
+	unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
+
+	struct clk_divider cfg_div;
+	struct clk *cfg_div_clk;
+
+	unsigned int bounce_buf_size;
+	void *bounce_buf;
+	dma_addr_t bounce_dma_addr;
+
+	unsigned long clk_rate;
+	unsigned long clk_src_rate;
+	unsigned short clk_src_div;
+};
+
+#define reg_read(host, offset) readl(host->regs + offset)
+#define reg_write(host, offset, val) writel(val, host->regs + offset)
+
+struct cmd_cfg {
+	union {
+		struct {
+			u32 length:9;
+			u32 block_mode:1;
+			u32 r1b:1;
+			u32 end_of_chain:1;
+			u32 timeout:4; /* 2^timeout msec */
+			u32 no_resp:1;
+			u32 no_cmd:1;
+			u32 data_io:1;
+			u32 data_wr:1;
+			u32 resp_nocrc:1;
+			u32 resp_128:1;
+			u32 resp_num:1;
+			u32 data_num:1;
+			u32 cmd_index:6;
+			u32 error:1;
+			u32 owner:1;
+#define CFG_OWNER_CPU 1
+#define CFG_OWNER_MMC 0
+		};
+		u32 val;
+	};
+};
+
+struct sd_emmc_desc {
+	struct cmd_cfg cmd_cfg;
+	u32 cmd_arg;
+	u32 cmd_data;
+	u32 cmd_resp;
+};
+#define CMD_DATA_MASK (~0x3)
+#define CMD_DATA_BIG_ENDIAN BIT(1)
+#define CMD_DATA_SRAM BIT(0)
+#define CMD_RESP_MASK (~0x1)
+#define CMD_RESP_SRAM BIT(0)
+
+static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
+{
+	struct mmc_host *mmc = host->mmc;
+	int ret = 0;
+	u32 cfg;
+
+	if (clk_rate) {
+		if (WARN_ON(clk_rate > mmc->f_max))
+			clk_rate = mmc->f_max;
+		else if (WARN_ON(clk_rate < mmc->f_min))
+			clk_rate = mmc->f_min;
+	}
+
+	if (clk_rate == host->clk_rate)
+		return 0;
+
+	/* stop clock */
+	cfg = reg_read(host, SD_EMMC_CFG);
+	if (!(cfg & CFG_STOP_CLOCK)) {
+		cfg |= CFG_STOP_CLOCK;
+		reg_write(host, SD_EMMC_CFG, cfg);
+	}
+
+	dev_dbg(host->dev, "change clock rate %lu -> %lu\n",
+		host->clk_rate, clk_rate);
+	ret = clk_set_rate(host->cfg_div_clk, clk_rate);
+	if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
+		dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
+			 clk_rate, clk_get_rate(host->cfg_div_clk), ret);
+	else
+		host->clk_rate = clk_rate;
+
+	/* (re)start clock, if non-zero */
+	if (clk_rate) {
+		cfg = reg_read(host, SD_EMMC_CFG);
+		cfg &= ~CFG_STOP_CLOCK;
+		reg_write(host, SD_EMMC_CFG, cfg);
+	}
+
+	return ret;
+}
+
+static int meson_mmc_clk_init(struct meson_host *host)
+{
+	struct clk_init_data init;
+	char clk_name[32];
+	int i, ret = 0;
+	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+	unsigned int mux_parent_count = 0;
+	const char *clk_div_parents[1];
+	unsigned int f_min = UINT_MAX;
+	u32 clk_reg, cfg;
+
+	/* get the mux parents from DT */
+	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+		char name[16];
+
+		snprintf(name, sizeof(name), "clkin%d", i);
+		host->mux_parent[i] = devm_clk_get(host->dev, name);
+		if (IS_ERR(host->mux_parent[i])) {
+			ret = PTR_ERR(host->mux_parent[i]);
+			if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
+				dev_err(host->dev, "Missing clock %s\n", name);
+			host->mux_parent[i] = NULL;
+			return ret;
+		}
+
+		host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
+		mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
+		mux_parent_count++;
+		if (host->mux_parent_rate[i] < f_min)
+			f_min = host->mux_parent_rate[i];
+	}
+
+	/* cacluate f_min based on input clocks, and max divider value */
+	if (f_min != UINT_MAX)
+		f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
+	else
+		f_min = 4000000;  /* default min: 400 MHz */
+	host->mmc->f_min = f_min;
+
+	/* create the mux */
+	snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
+	init.name = clk_name;
+	init.ops = &clk_mux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = mux_parent_names;
+	init.num_parents = mux_parent_count;
+
+	host->mux.reg = host->regs + SD_EMMC_CLOCK;
+	host->mux.shift = CLK_SRC_SHIFT;
+	host->mux.mask = CLK_SRC_MASK;
+	host->mux.flags = 0;
+	host->mux.table = NULL;
+	host->mux.hw.init = &init;
+
+	host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(host->mux_clk)))
+		return PTR_ERR(host->mux_clk);
+
+	/* create the divider */
+	snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
+	init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(host->mux_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
+	host->cfg_div.shift = CLK_DIV_SHIFT;
+	host->cfg_div.width = CLK_DIV_WIDTH;
+	host->cfg_div.hw.init = &init;
+	host->cfg_div.flags = CLK_DIVIDER_ONE_BASED |
+		CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
+
+	host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
+		return PTR_ERR(host->cfg_div_clk);
+
+	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+	clk_reg = 0;
+	clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
+	clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
+	clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
+	clk_reg &= ~CLK_ALWAYS_ON;
+	reg_write(host, SD_EMMC_CLOCK, clk_reg);
+
+	clk_prepare_enable(host->cfg_div_clk);
+
+	/* Ensure clock starts in "auto" mode, not "always on" */
+	cfg = reg_read(host, SD_EMMC_CFG);
+	cfg &= ~CFG_CLK_ALWAYS_ON;
+	cfg |= CFG_AUTO_CLK;
+	reg_write(host, SD_EMMC_CFG, cfg);
+
+	meson_mmc_clk_set(host, f_min);
+
+	return ret;
+}
+
+static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 bus_width;
+	u32 val, orig;
+
+	/*
+	 * GPIO regulator, only controls switching between 1v8 and
+	 * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON.
+	 */
+	switch (ios->power_mode) {
+	case MMC_POWER_UP:
+		if (!IS_ERR(mmc->supply.vmmc))
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
+	}
+
+	meson_mmc_clk_set(host, ios->clock);
+
+	/* Bus width */
+	val = reg_read(host, SD_EMMC_CFG);
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		bus_width = CFG_BUS_WIDTH_1;
+		break;
+	case MMC_BUS_WIDTH_4:
+		bus_width = CFG_BUS_WIDTH_4;
+		break;
+	case MMC_BUS_WIDTH_8:
+		bus_width = CFG_BUS_WIDTH_8;
+		break;
+	default:
+		dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n",
+			ios->bus_width);
+		bus_width = CFG_BUS_WIDTH_4;
+		return;
+	}
+
+	val = reg_read(host, SD_EMMC_CFG);
+	orig = val;
+
+	val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT);
+	val |= bus_width << CFG_BUS_WIDTH_SHIFT;
+
+	val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+	val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
+
+	val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT);
+	val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
+
+	val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT);
+	val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
+
+	reg_write(host, SD_EMMC_CFG, val);
+
+	if (val != orig)
+		dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
+			__func__, orig, val);
+}
+
+static int meson_mmc_wait_busy(struct mmc_host *mmc, unsigned int timeout)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 status;
+	int i;
+
+	for (i = timeout; i > 0; i--) {
+		status = reg_read(host, SD_EMMC_STATUS);
+		if (!(status & STATUS_BUSY))
+			break;
+	};
+
+	return (timeout == 0);
+}
+
+static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct mmc_command *cmd = host->cmd;
+	unsigned int loops = 0xfffff;
+
+	WARN_ON(host->mrq != mrq);
+	if (cmd && !cmd->error)
+		if (meson_mmc_wait_busy(mmc, loops))
+			dev_warn(host->dev, "%s: timeout busy.\n", __func__);
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+	mmc_request_done(host->mmc, mrq);
+
+	return 0;
+}
+
+static int meson_mmc_cmd_invalid(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	cmd->error = -EINVAL;
+	meson_mmc_request_done(mmc, cmd->mrq);
+
+	return -EINVAL;
+}
+
+static int meson_mmc_check_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	int ret = 0;
+
+	/* FIXME: needs update for SDIO support */
+	if (cmd->opcode == SD_IO_SEND_OP_COND
+	    || cmd->opcode == SD_IO_RW_DIRECT
+	    || cmd->opcode == SD_IO_RW_EXTENDED) {
+		ret = meson_mmc_cmd_invalid(mmc, cmd);
+	}
+
+	return ret;
+}
+
+static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct sd_emmc_desc *desc, desc_tmp;
+	u32 cfg;
+	u8 blk_len;
+	unsigned int xfer_bytes = 0;
+
+	/* Setup descriptors */
+	dma_rmb();
+	desc = &desc_tmp;
+	memset(desc, 0, sizeof(struct sd_emmc_desc));
+
+	desc->cmd_cfg.cmd_index = cmd->opcode;
+	desc->cmd_cfg.owner = CFG_OWNER_CPU;
+	desc->cmd_arg = cmd->arg;
+
+	/* Response */
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		desc->cmd_cfg.no_resp = 0;
+		if (cmd->flags & MMC_RSP_136)
+			desc->cmd_cfg.resp_128 = 1;
+		desc->cmd_cfg.resp_num = 1;
+		desc->cmd_resp = 0;
+
+		if (!(cmd->flags & MMC_RSP_CRC))
+			desc->cmd_cfg.resp_nocrc = 1;
+
+		if (cmd->flags & MMC_RSP_BUSY)
+			desc->cmd_cfg.r1b = 1;
+	} else {
+		desc->cmd_cfg.no_resp = 1;
+	}
+
+	/* data? */
+	if (cmd->data) {
+		desc->cmd_cfg.data_io = 1;
+		if (cmd->data->blocks > 1) {
+			desc->cmd_cfg.block_mode = 1;
+			desc->cmd_cfg.length = cmd->data->blocks;
+
+			/* check if block-size matches, if not update */
+			cfg = reg_read(host, SD_EMMC_CFG);
+			blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+			blk_len >>= CFG_BLK_LEN_SHIFT;
+			if (blk_len != ilog2(cmd->data->blksz)) {
+				dev_warn(host->dev, "%s: update blk_len %d -> %d\n",
+					__func__, blk_len,
+					 ilog2(cmd->data->blksz));
+				blk_len = ilog2(cmd->data->blksz);
+				cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+				cfg |= blk_len << CFG_BLK_LEN_SHIFT;
+				reg_write(host, SD_EMMC_CFG, cfg);
+			}
+		} else {
+			desc->cmd_cfg.block_mode = 0;
+			desc->cmd_cfg.length = cmd->data->blksz;
+		}
+
+		cmd->data->bytes_xfered = 0;
+		xfer_bytes = cmd->data->blksz * cmd->data->blocks;
+		if (cmd->data->flags & MMC_DATA_WRITE) {
+			desc->cmd_cfg.data_wr = 1;
+			WARN_ON(xfer_bytes > host->bounce_buf_size);
+			sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len,
+					  host->bounce_buf, xfer_bytes);
+			cmd->data->bytes_xfered = xfer_bytes;
+			dma_wmb();
+		} else {
+			desc->cmd_cfg.data_wr = 0;
+		}
+
+		if (xfer_bytes > 0) {
+			desc->cmd_cfg.data_num = 0;
+			desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
+		} else {
+			/* write data to data_addr */
+			desc->cmd_cfg.data_num = 1;
+			desc->cmd_data = 0;
+		}
+
+		desc->cmd_cfg.timeout = 12; /* 2^x msecs */
+	} else {
+		desc->cmd_cfg.data_io = 0;
+		desc->cmd_cfg.timeout = 10; /* 2^x msecs */
+	}
+
+	host->cmd = cmd;
+
+	/* Last descriptor */
+	desc->cmd_cfg.end_of_chain = 1;
+	reg_write(host, SD_EMMC_CMD_CFG, desc->cmd_cfg.val);
+	reg_write(host, SD_EMMC_CMD_DAT, desc->cmd_data);
+	reg_write(host, SD_EMMC_CMD_RSP, desc->cmd_resp);
+	wmb(); /* ensure descriptor is written before kicked */
+	reg_write(host, SD_EMMC_CMD_ARG, desc->cmd_arg);
+}
+
+static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != NULL);
+
+	/* Stop execution */
+	reg_write(host, SD_EMMC_START, 0);
+
+	/* clear, ack, enable all interrupts */
+	reg_write(host, SD_EMMC_IRQ_EN, 0);
+	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
+	reg_write(host, SD_EMMC_IRQ_EN, IRQ_EN_MASK);
+
+	host->mrq = mrq;
+
+	if (meson_mmc_check_cmd(mmc, mrq->cmd))
+		return;
+
+	if (mrq->sbc)
+		meson_mmc_start_cmd(mmc, mrq->sbc);
+	else
+		meson_mmc_start_cmd(mmc, mrq->cmd);
+}
+
+static int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct meson_host *host = mmc_priv(mmc);
+
+	if (!cmd) {
+		dev_dbg(host->dev, "%s: NULL command.\n", __func__);
+		return -EINVAL;
+	}
+
+	if (cmd->flags & MMC_RSP_136) {
+		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP3);
+		cmd->resp[1] = reg_read(host, SD_EMMC_CMD_RSP2);
+		cmd->resp[2] = reg_read(host, SD_EMMC_CMD_RSP1);
+		cmd->resp[3] = reg_read(host, SD_EMMC_CMD_RSP);
+	} else if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP);
+	}
+
+	return 0;
+}
+
+static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
+{
+	struct meson_host *host = dev_id;
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd;
+	u32 irq_en, status, raw_status;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	if (WARN_ON(!host))
+		return IRQ_NONE;
+
+	if (WARN_ON(!mrq))
+		return IRQ_NONE;
+
+	if (WARN_ON(!cmd))
+		return IRQ_NONE;
+
+	spin_lock(&host->lock);
+	irq_en = reg_read(host, SD_EMMC_IRQ_EN);
+	raw_status = reg_read(host, SD_EMMC_STATUS);
+	status = raw_status & irq_en;
+
+	if (!status) {
+		dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
+			 raw_status, irq_en);
+		ret = IRQ_NONE;
+		goto out;
+	}
+
+	cmd->error = 0;
+	if (status & IRQ_RXD_ERR_MASK) {
+		dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_TXD_ERR) {
+		dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_DESC_ERR)
+		dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
+	if (status & IRQ_RESP_ERR) {
+		dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_RESP_TIMEOUT) {
+		dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
+		cmd->error = -ETIMEDOUT;
+	}
+	if (status & IRQ_DESC_TIMEOUT) {
+		dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
+		cmd->error = -ETIMEDOUT;
+	}
+	if (status & IRQ_SDIO)
+		dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
+
+	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
+		ret = IRQ_WAKE_THREAD;
+	else  {
+		dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
+			 status, cmd->opcode, cmd->arg,
+			 cmd->flags, mrq->stop ? 1 : 0);
+		if (cmd->data) {
+			struct mmc_data *data = cmd->data;
+
+			dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)",
+				 data->blksz, data->blocks, data->flags,
+				 data->flags & MMC_DATA_WRITE ? "write" : "",
+				 data->flags & MMC_DATA_READ ? "read" : "");
+		}
+	}
+
+out:
+	/* ack all (enabled) interrupts */
+	reg_write(host, SD_EMMC_STATUS, status);
+
+	if (ret == IRQ_HANDLED) {
+		meson_mmc_read_resp(host->mmc, cmd);
+		meson_mmc_request_done(host->mmc, cmd->mrq);
+	}
+
+	spin_unlock(&host->lock);
+	return ret;
+}
+
+static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
+{
+	struct meson_host *host = dev_id;
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data;
+
+	unsigned int xfer_bytes;
+	int ret = IRQ_HANDLED;
+
+	if (WARN_ON(!mrq))
+		ret = IRQ_NONE;
+
+	if (WARN_ON(!cmd))
+		ret = IRQ_NONE;
+
+	data = cmd->data;
+	if (data) {
+		xfer_bytes = data->blksz * data->blocks;
+		if (data->flags & MMC_DATA_READ) {
+			WARN_ON(xfer_bytes > host->bounce_buf_size);
+			sg_copy_from_buffer(data->sg, data->sg_len,
+					    host->bounce_buf, xfer_bytes);
+			data->bytes_xfered = xfer_bytes;
+		}
+	}
+
+	meson_mmc_read_resp(host->mmc, cmd);
+	if (!data || !data->stop || mrq->sbc)
+		meson_mmc_request_done(host->mmc, mrq);
+	else
+		meson_mmc_start_cmd(host->mmc, data->stop);
+
+	return ret;
+}
+
+/*
+ * NOTE: we only need this until the GPIO/pinctrl driver can handle
+ * interrupts.  For now, the MMC core will use this for polling.
+ */
+static int meson_mmc_get_cd(struct mmc_host *mmc)
+{
+	int status = mmc_gpio_get_cd(mmc);
+
+	if (status == -ENOSYS)
+		return 1; /* assume present */
+
+	return status;
+}
+
+static struct mmc_host_ops meson_mmc_ops = {
+	.request	= meson_mmc_request,
+	.set_ios	= meson_mmc_set_ios,
+	.get_cd         = meson_mmc_get_cd,
+};
+
+static int meson_mmc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct meson_host *host;
+	struct mmc_host *mmc;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, host);
+
+	spin_lock_init(&host->lock);
+
+	host->core_clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(host->core_clk)) {
+		ret = PTR_ERR(host->core_clk);
+		if (ret == -EPROBE_DEFER)
+			dev_dbg(&pdev->dev,
+				"Missing core clock.  EPROBE_DEFER\n");
+		else
+			dev_err(&pdev->dev,
+				"Unable to get core clk (ret=%d).\n", ret);
+		goto free_host;
+	}
+
+	/* Voltage supply */
+	mmc_of_parse_voltage(np, &host->ocr_mask);
+	ret = mmc_regulator_get_supply(mmc);
+	if (ret == -EPROBE_DEFER) {
+		dev_dbg(&pdev->dev, "Missing regulator: EPROBE_DEFER");
+		goto free_host;
+	}
+
+	if (!mmc->ocr_avail)
+		mmc->ocr_avail = host->ocr_mask;
+
+	ret = mmc_of_parse(mmc);
+	if (ret) {
+		dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
+		goto free_host;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV;
+		goto free_host;
+	}
+	host->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->regs)) {
+		ret = PTR_ERR(host->regs);
+		goto free_host;
+	}
+
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq == 0) {
+		dev_err(&pdev->dev, "failed to get interrupt resource.\n");
+		ret = -EINVAL;
+		goto free_host;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, host->irq,
+					meson_mmc_irq, meson_mmc_irq_thread,
+					IRQF_SHARED, DRIVER_NAME, host);
+	if (ret)
+		goto free_host;
+
+	/* data bounce buffer */
+	host->bounce_buf_size = SZ_512K;
+	host->bounce_buf =
+		dma_alloc_coherent(host->dev, host->bounce_buf_size,
+				   &host->bounce_dma_addr, GFP_KERNEL);
+	if (host->bounce_buf == NULL) {
+		dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
+		ret = -ENOMEM;
+		goto free_host;
+	}
+
+	clk_prepare_enable(host->core_clk);
+
+	ret = meson_mmc_clk_init(host);
+	if (ret)
+		goto free_host;
+
+	/* Stop execution */
+	reg_write(host, SD_EMMC_START, 0);
+
+	/* clear, ack, enable all interrupts */
+	reg_write(host, SD_EMMC_IRQ_EN, 0);
+	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
+
+	mmc->ops = &meson_mmc_ops;
+	mmc_add_host(mmc);
+
+	return 0;
+
+free_host:
+	dev_dbg(host->dev, "Failed to probe: ret=%d\n", ret);
+	if (host->core_clk)
+		clk_disable_unprepare(host->core_clk);
+	mmc_free_host(mmc);
+	return ret;
+}
+
+static int meson_mmc_remove(struct platform_device *pdev)
+{
+	struct meson_host *host = dev_get_drvdata(&pdev->dev);
+
+	if (WARN_ON(!host))
+		return 0;
+
+	if (host->bounce_buf)
+		dma_free_coherent(host->dev, host->bounce_buf_size,
+				  host->bounce_buf, host->bounce_dma_addr);
+
+	if (host->cfg_div_clk)
+		clk_disable_unprepare(host->cfg_div_clk);
+
+	if (host->core_clk)
+		clk_disable_unprepare(host->core_clk);
+
+	mmc_free_host(host->mmc);
+	return 0;
+}
+
+static const struct of_device_id meson_mmc_of_match[] = {
+	{
+		.compatible = "amlogic,meson-gxbb-mmc",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
+
+static struct platform_driver meson_mmc_driver = {
+	.probe		= meson_mmc_probe,
+	.remove		= meson_mmc_remove,
+	.driver		= {
+		.name = DRIVER_NAME,
+		.of_match_table = of_match_ptr(meson_mmc_of_match),
+	},
+};
+
+module_platform_driver(meson_mmc_driver);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_DESCRIPTION("Amlogic S905/GXBB SD/eMMC driver");
+MODULE_AUTHOR("Kevin Hilman <khilman at baylibre.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+
-- 
2.9.0



From khilman at baylibre.com  Wed Aug  3 17:25:29 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 3 Aug 2016 17:25:29 -0700
Subject: [PATCH v2 0/4] pwm: Add Amlogic Meson SoC PWM Controller
In-Reply-To: <1468142645-4360-1-git-send-email-narmstrong@baylibre.com>
References: <1468142645-4360-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <CAOi56cVGRpSeAVwaATkx8Q2wz9hxocq6095opJQZucfDML2wSg@mail.gmail.com>

Hi Thierry,

On Sun, Jul 10, 2016 at 2:27 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> Add support for the PWM controller found in Amlogic Meson SoCs.
> This controller provides a dual PWM output with 4 selectable clock source
> and a two level divider to achieve a better PWM range.
>
> Currently Meson8b and GXBB SoCs are supported.
>
> Changes since v1 at http://lkml.kernel.org/r/1466173784-15625-1-git-send-email-narmstrong at baylibre.com :
> - fix meson8b dtsi

Gentle reminder ping on this series.

Thanks,

Kevin


From khilman at baylibre.com  Wed Aug  3 17:27:32 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 03 Aug 2016 17:27:32 -0700
Subject: [PATCH v3 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <7hbn237aw7.fsf@baylibre.com> (Kevin Hilman's message of "Mon, 11
 Jul 2016 21:12:08 -0700")
References: <1468141867-4172-1-git-send-email-narmstrong@baylibre.com>
 <1468141867-4172-4-git-send-email-narmstrong@baylibre.com>
 <578271D3.4080704@roeck-us.net> <7hbn237aw7.fsf@baylibre.com>
Message-ID: <m2bn19qsy3.fsf@baylibre.com>

Hi Guenter,

Kevin Hilman <khilman at baylibre.com> writes:

> Guenter Roeck <linux at roeck-us.net> writes:
>
>> On 07/10/2016 02:11 AM, Neil Armstrong wrote:
>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>
>> Reviewed-by: Guenter Roeck <linux at roeck-us.net>
>>
>> Would this go in through one of the arm trees ?
>
> You can take the driver through the watchdog tree, but I'll take the DT
> stuff through the amlogic tree (and submit via arm-soc).  
>
> However, with your ack, and since this is a brand new driver, I could
> take the driver as well.  Just let me know your preference.

ping... do you have a prefernce here?

Thanks,

Kevin


From khilman at baylibre.com  Wed Aug  3 17:29:13 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 3 Aug 2016 17:29:13 -0700
Subject: [PATCH v3 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <m2bn19qsy3.fsf@baylibre.com>
References: <1468141867-4172-1-git-send-email-narmstrong@baylibre.com>
 <1468141867-4172-4-git-send-email-narmstrong@baylibre.com>
 <578271D3.4080704@roeck-us.net> <7hbn237aw7.fsf@baylibre.com>
 <m2bn19qsy3.fsf@baylibre.com>
Message-ID: <CAOi56cUQaFKYu2jNP0AuLOSNnNramu+DNPc+PH7K0gHDZMf+zA@mail.gmail.com>

On Wed, Aug 3, 2016 at 5:27 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Hi Guenter,
>
> Kevin Hilman <khilman at baylibre.com> writes:
>
>> Guenter Roeck <linux at roeck-us.net> writes:
>>
>>> On 07/10/2016 02:11 AM, Neil Armstrong wrote:
>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>
>>> Reviewed-by: Guenter Roeck <linux at roeck-us.net>
>>>
>>> Would this go in through one of the arm trees ?
>>
>> You can take the driver through the watchdog tree, but I'll take the DT
>> stuff through the amlogic tree (and submit via arm-soc).
>>
>> However, with your ack, and since this is a brand new driver, I could
>> take the driver as well.  Just let me know your preference.
>
> ping... do you have a prefernce here?
>

Oops, just noticed Wim already picked these up.

Ignore me,

Kevin


From jh80.chung at samsung.com  Wed Aug  3 23:48:50 2016
From: jh80.chung at samsung.com (Jaehoon Chung)
Date: Thu, 04 Aug 2016 15:48:50 +0900
Subject: [U-Boot,1/2] mmc: Add Amlogic Meson driver
In-Reply-To: <1463056902-8533-2-git-send-email-carlo@caione.org>
References: <1463056902-8533-2-git-send-email-carlo@caione.org>
Message-ID: <a0c08bbd-1ff6-3234-6daf-e732de8347b7@samsung.com>

Hi Carlo

On 05/12/2016 09:41 PM, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> This is a port / rewrite of the Amlogic driver shipped whithin the
> Amlogic SDK for the Meson GXBaby (S905) SoC.

s/whithin/within

And If you want to apply this patch, could you resend the patch on lates u-boot?

> 
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  arch/arm/include/asm/arch-meson/sd_emmc.h | 109 +++++++++++
>  drivers/mmc/Makefile                      |   1 +
>  drivers/mmc/meson_mmc.c                   | 305 ++++++++++++++++++++++++++++++
>  3 files changed, 415 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-meson/sd_emmc.h
>  create mode 100644 drivers/mmc/meson_mmc.c
> 
> diff --git a/arch/arm/include/asm/arch-meson/sd_emmc.h b/arch/arm/include/asm/arch-meson/sd_emmc.h
> new file mode 100644
> index 0000000..6781dca
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-meson/sd_emmc.h
> @@ -0,0 +1,109 @@
> +/*
> + * (C) Copyright 2016 Carlo Caione <carlo at caione.org>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef __SD_EMMC_H__
> +#define __SD_EMMC_H__
> +
> +#include <mmc.h>
> +
> +#define SDIO_PORT_A			0
> +#define SDIO_PORT_B			1
> +#define SDIO_PORT_C			2
> +
> +#define SD_EMMC_BASE_A			0xd0070000
> +#define SD_EMMC_BASE_B			0xd0072000
> +#define SD_EMMC_BASE_C			0xd0074000
> +
> +#define SD_IRQ_ALL			0x3fff
> +
> +#define SD_EMMC_CLKSRC_24M		24000000
> +#define SD_EMMC_CLKSRC_DIV2		1000000000

Is it right? 1GHz?

> +
> +#define CLK_DIV				0
> +#define CLK_SRC				6
> +#define CLK_CO_PHASE			8
> +#define CLK_ALWAYS_ON			24

Are these for shifting?

> +
> +#define ADDR_USE_PING_BUF		BIT(1)
> +
> +#define SD_EMMC_RXD_ERROR		BIT(0)
> +#define SD_EMMC_TXD_ERROR		BIT(1)
> +#define SD_EMMC_DESC_ERROR		BIT(2)
> +#define SD_EMMC_RESP_CRC_ERROR		BIT(3)
> +#define SD_EMMC_RESP_TIMEOUT_ERROR	BIT(4)
> +#define SD_EMMC_DESC_TIMEOUT_ERROR	BIT(5)
> +
> +#define CFG_BUS_WIDTH			0
> +#define CFG_BUS_WIDTH_MASK		(0x3 << 0)
> +#define CFG_BL_LEN			4
> +#define CFG_BL_LEN_MASK			(0xf << 4)
> +#define CFG_RESP_TIMEOUT		8
> +#define CFG_RESP_TIMEOUT_MASK		(0xf << 8)
> +#define CFG_RC_CC			12
> +#define CFG_RC_CC_MASK			(0xf << 12)
> +
> +#define STATUS_RXD_ERR_MASK		0xff
> +#define STATUS_TXD_ERR			BIT(8)
> +#define STATUS_DESC_ERR			BIT(9)
> +#define STATUS_RESP_ERR			BIT(10)
> +#define STATUS_RESP_TIMEOUT		BIT(11)
> +#define STATUS_DESC_TIMEOUT		BIT(12)
> +#define STATUS_END_OF_CHAIN		BIT(13)
> +
> +#define CMD_CFG_LENGTH_MASK		0x1ff
> +#define CMD_CFG_CMD_INDEX		24
> +#define CMD_CFG_BLOCK_MODE		BIT(9)
> +#define CMD_CFG_R1B			BIT(10)
> +#define CMD_CFG_END_OF_CHAIN		BIT(11)
> +#define CMD_CFG_NO_RESP			BIT(16)
> +#define CMD_CFG_DATA_IO			BIT(18)
> +#define CMD_CFG_DATA_WR			BIT(19)
> +#define CMD_CFG_RESP_NOCRC		BIT(20)
> +#define CMD_CFG_RESP_128		BIT(21)
> +#define CMD_CFG_OWNER			BIT(31)

Add the description for which register.
e,g
/* GCLOCK register */
#define ...

> +
> +struct meson_mmc_regs {
> +	uint32_t gclock;
> +	uint32_t gdelay;
> +	uint32_t gadjust;
> +	uint32_t reserved_0c;
> +	uint32_t gcalout;
> +	uint32_t reserved_14[11];
> +	uint32_t gstart;
> +	uint32_t gcfg;
> +	uint32_t gstatus;
> +	uint32_t girq_en;
> +	uint32_t gcmd_cfg;
> +	uint32_t gcmd_arg;
> +	uint32_t gcmd_dat;
> +	uint32_t gcmd_rsp0;
> +	uint32_t gcmd_rsp1;
> +	uint32_t gcmd_rsp2;
> +	uint32_t gcmd_rsp3;
> +	uint32_t reserved_6c;
> +	uint32_t gcurr_cfg;
> +	uint32_t gcurr_arg;
> +	uint32_t gcurr_dat;
> +	uint32_t gcurr_rsp;
> +	uint32_t gnext_cfg;
> +	uint32_t gnext_arg;
> +	uint32_t gnext_dat;
> +	uint32_t gnext_rsp;
> +	uint32_t grxd;
> +	uint32_t gtxd;
> +	uint32_t reserved_98[90];
> +	uint32_t gdesc[128];
> +	uint32_t gping[128];
> +	uint32_t gpong[128];
> +};

Don't use this style..Use the define.
It's difficult to debug..devloper don't know which offset is used before calculating.
And add the descriptions..

> +
> +struct meson_mmc_platdata {
> +	struct mmc_config cfg;
> +	struct meson_mmc_regs *sd_emmc_reg;
> +	char *w_buf;
> +};
> +
> +#endif
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 585aaf3..08ac9ba 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o
>  obj-$(CONFIG_GENERIC_MMC) += mmc.o
>  obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
>  obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
> +obj-$(CONFIG_MMC_MESON) += meson_mmc.o
>  obj-$(CONFIG_MMC_SPI) += mmc_spi.o
>  obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
>  obj-$(CONFIG_MV_SDHCI) += mv_sdhci.o
> diff --git a/drivers/mmc/meson_mmc.c b/drivers/mmc/meson_mmc.c
> new file mode 100644
> index 0000000..af224ec
> --- /dev/null
> +++ b/drivers/mmc/meson_mmc.c
> @@ -0,0 +1,305 @@
> +/*
> + * (C) Copyright 2016 Carlo Caione <carlo at caione.org>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <malloc.h>
> +#include <mmc.h>
> +#include <asm/io.h>
> +#include <asm/arch/sd_emmc.h>
> +#include <dm/device.h>
> +
> +static void meson_mmc_config_clock(struct mmc *mmc,
> +				   struct meson_mmc_regs *meson_mmc_reg)
> +{
> +	uint32_t meson_mmc_clk = 0;
> +	unsigned int clk, clk_src, clk_div;
> +
> +	if (mmc->clock > 12000000) {
> +		clk = SD_EMMC_CLKSRC_DIV2;
> +		clk_src = 1;
> +	} else {
> +		clk = SD_EMMC_CLKSRC_24M;
> +		clk_src = 0;
> +	}
> +	clk_div = clk / mmc->clock;
> +
> +	if (mmc->clock < mmc->cfg->f_min)
> +		mmc->clock = mmc->cfg->f_min;
> +	if (mmc->clock > mmc->cfg->f_max)
> +		mmc->clock = mmc->cfg->f_max;

In mmc_set_clock(), mmc->clock is already assigned..
Doesn't need this.

> +
> +	/* Keep the clock always on */
> +	meson_mmc_clk |= (1 << CLK_ALWAYS_ON);
> +
> +	/* 180 phase */
> +	meson_mmc_clk |= (2 << CLK_CO_PHASE);

Don't use the magic number, what do 1 and 2 mean?

> +
> +	/* clock settings */
> +	meson_mmc_clk |= (clk_src << CLK_SRC);
> +	meson_mmc_clk |= (clk_div << CLK_DIV);

How many bits do use for clk_div? bit[0:11]?

> +
> +	writel(meson_mmc_clk, &meson_mmc_reg->gclock);
> +}
> +
> +static void meson_mmc_set_ios(struct mmc *mmc)
> +{
> +	struct meson_mmc_platdata *pdata;
> +	struct meson_mmc_regs *meson_mmc_reg;
> +	unsigned int bus_width;
> +	uint32_t meson_mmc_cfg = 0;
> +
> +	pdata = mmc->priv;
> +	meson_mmc_reg = pdata->sd_emmc_reg;
> +
> +	meson_mmc_config_clock(mmc, meson_mmc_reg);
> +
> +	meson_mmc_cfg = readl(&meson_mmc_reg->gcfg);
> +
> +	if (mmc->bus_width == 1)
> +		bus_width = 0;
> +	else
> +		bus_width = mmc->bus_width / 4;
> +
> +	/* 1-bit mode */
> +	meson_mmc_cfg &= ~CFG_BUS_WIDTH_MASK;
> +	meson_mmc_cfg |= (bus_width << CFG_BUS_WIDTH);
> +
> +	/* 512 bytes block lenght */
> +	meson_mmc_cfg &= ~CFG_BL_LEN_MASK;
> +	meson_mmc_cfg |= (9 << CFG_BL_LEN);
> +
> +	/* Response timeout 256 clk */
> +	meson_mmc_cfg &= ~CFG_RESP_TIMEOUT_MASK;
> +	meson_mmc_cfg |= (7 << CFG_RESP_TIMEOUT);
> +
> +	/* Command-command gap 1024 clk */
> +	meson_mmc_cfg &= ~CFG_RC_CC_MASK;
> +	meson_mmc_cfg |= (4 << CFG_RC_CC);

Ditto...what are 9, 7, 4?
Don't use the magic number in entire your codes.

> +
> +	writel(meson_mmc_cfg, &meson_mmc_reg->gcfg);
> +
> +	return;

not needs "return"

> +}
> +
> +static int meson_mmc_init(struct mmc *mmc)
> +{
> +	mmc_set_clock(mmc, 400000);
> +
> +	return 0;
> +}
> +
> +static void meson_mmc_setup_cmd(struct mmc *mmc, struct mmc_data *data,
> +				struct mmc_cmd *cmd,
> +				struct meson_mmc_regs *meson_mmc_reg)
> +{
> +	uint32_t meson_mmc_cmd = 0;
> +
> +	meson_mmc_cmd = ((0x80 | cmd->cmdidx) << CMD_CFG_CMD_INDEX);
> +
> +	if (cmd->resp_type & MMC_RSP_PRESENT) {
> +		if (cmd->resp_type & MMC_RSP_136)
> +			meson_mmc_cmd |= CMD_CFG_RESP_128;
> +
> +		if (cmd->resp_type & MMC_RSP_BUSY)
> +			meson_mmc_cmd |= CMD_CFG_R1B;

There is no case with MMC_RSP_136 and MMC_RSP_BUSY together.

> +
> +		if (!(cmd->resp_type & MMC_RSP_CRC))
> +			meson_mmc_cmd |= CMD_CFG_RESP_NOCRC;
> +	} else {
> +		meson_mmc_cmd |= CMD_CFG_NO_RESP;
> +	}
> +
> +	if (data) {
> +		meson_mmc_cmd |= CMD_CFG_DATA_IO;
> +
> +		if (data->flags == MMC_DATA_WRITE)
> +			meson_mmc_cmd |= CMD_CFG_DATA_WR;
> +
> +		if (data->blocks > 1) {
> +			meson_mmc_cmd |= CMD_CFG_BLOCK_MODE;
> +			meson_mmc_cmd |= data->blocks;
> +		} else {
> +			meson_mmc_cmd |= (data->blocksize & CMD_CFG_LENGTH_MASK);
> +		}
> +	}
> +
> +	meson_mmc_cmd |= CMD_CFG_OWNER;
> +	meson_mmc_cmd |= CMD_CFG_END_OF_CHAIN;
> +
> +	writel(meson_mmc_cmd, &meson_mmc_reg->gcmd_cfg);
> +
> +	return;
> +}
> +
> +static void meson_mmc_setup_addr(struct mmc *mmc, struct mmc_data *data,
> +				 struct meson_mmc_regs *meson_mmc_reg)
> +{
> +	struct meson_mmc_platdata *pdata;
> +	unsigned int data_size = 0;
> +	uint32_t meson_mmc_data_addr = 0;
> +
> +	pdata = mmc->priv;
> +
> +	if (data) {
> +		data_size = data->blocks * data->blocksize;
> +
> +		if (data->flags == MMC_DATA_READ) {
> +			if (data_size < 0x200) {
> +				meson_mmc_data_addr = (ulong) meson_mmc_reg->gping;
> +				meson_mmc_data_addr |= ADDR_USE_PING_BUF;
> +			} else {
> +				invalidate_dcache_range((ulong) data->dest,
> +							(ulong) (data->dest + data_size));
> +				meson_mmc_data_addr = (ulong) data->dest;
> +			}
> +		}
> +
> +		if (data->flags == MMC_DATA_WRITE) {

data->flags is only two..MMC_DATA_WRITE ..otherwise MMC_DATA_READ.

> +			pdata->w_buf = calloc(data_size, sizeof(char));
> +			memcpy(pdata->w_buf, data->src, data_size);
> +			flush_dcache_range((ulong) pdata->w_buf,
> +					   (ulong) (pdata->w_buf + data_size));
> +			meson_mmc_data_addr = (ulong) pdata->w_buf;
> +		}
> +	}
> +
> +	writel(meson_mmc_data_addr, &meson_mmc_reg->gcmd_dat);
> +
> +	return;
> +}
> +
> +static void meson_mmc_read_response(struct mmc *mmc, struct mmc_data *data,
> +				    struct mmc_cmd *cmd,
> +				    struct meson_mmc_regs *meson_mmc_reg)
> +{
> +	unsigned int data_size = 0;
> +
> +	if (data) {
> +		data_size = data->blocks * data->blocksize;
> +		if ((data_size < 0x200) && (data->flags == MMC_DATA_READ))
> +			memcpy(data->dest, (const void *)meson_mmc_reg->gping, data_size);
> +	}
> +
> +	if (cmd->resp_type & MMC_RSP_136) {
> +		cmd->response[0] = readl(&meson_mmc_reg->gcmd_rsp3);
> +		cmd->response[1] = readl(&meson_mmc_reg->gcmd_rsp2);
> +		cmd->response[2] = readl(&meson_mmc_reg->gcmd_rsp1);
> +		cmd->response[3] = readl(&meson_mmc_reg->gcmd_rsp0);
> +	} else {
> +		cmd->response[0] = readl(&meson_mmc_reg->gcmd_rsp0);
> +	}
> +}
> +
> +static int meson_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> +			      struct mmc_data *data)
> +{
> +	struct meson_mmc_platdata *pdata;
> +	struct meson_mmc_regs *meson_mmc_reg;
> +	uint32_t meson_mmc_irq = 0;
> +	int ret = 0;
> +
> +	pdata = mmc->priv;
> +	meson_mmc_reg = pdata->sd_emmc_reg;
> +
> +	meson_mmc_setup_cmd(mmc, data, cmd, meson_mmc_reg);
> +	meson_mmc_setup_addr(mmc, data, meson_mmc_reg);
> +
> +	writel(SD_IRQ_ALL, &meson_mmc_reg->gstatus);
> +	writel(cmd->cmdarg, &meson_mmc_reg->gcmd_arg);
> +
> +	while (1) {
> +		meson_mmc_irq = readl(&meson_mmc_reg->gstatus);
> +		if (meson_mmc_irq & STATUS_END_OF_CHAIN)
> +			break;
> +	}

I don't like this style...potential infinte loop.

> +
> +	if (meson_mmc_irq & STATUS_RXD_ERR_MASK)
> +		ret |= SD_EMMC_RXD_ERROR;
> +	if (meson_mmc_irq & STATUS_TXD_ERR)
> +		ret |= SD_EMMC_TXD_ERROR;
> +	if (meson_mmc_irq & STATUS_DESC_ERR)
> +		ret |= SD_EMMC_DESC_ERROR;
> +	if (meson_mmc_irq & STATUS_RESP_ERR)
> +		ret |= SD_EMMC_RESP_CRC_ERROR;
> +	if (meson_mmc_irq & STATUS_RESP_TIMEOUT)
> +		ret |= SD_EMMC_RESP_TIMEOUT_ERROR;
> +	if (meson_mmc_irq & STATUS_DESC_TIMEOUT)
> +		ret |= SD_EMMC_DESC_TIMEOUT_ERROR;

What are these ret values? Do you use the your specific error values?

> +
> +	meson_mmc_read_response(mmc, data, cmd, meson_mmc_reg);
> +
> +	if (data && data->flags == MMC_DATA_WRITE)
> +		free(pdata->w_buf);
> +
> +	if (ret) {
> +		if (meson_mmc_irq & STATUS_RESP_TIMEOUT)
> +			return TIMEOUT;

Strange this..why return at here...not above?

Best Regards,
Jaehoon Chung

> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct mmc_ops meson_mmc_ops = {
> +	.send_cmd	= meson_mmc_send_cmd,
> +	.set_ios	= meson_mmc_set_ios,
> +	.init		= meson_mmc_init,
> +};
> +
> +static int meson_mmc_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct meson_mmc_platdata *pdata = dev->platdata;
> +	fdt_addr_t addr;
> +
> +	addr = dev_get_addr(dev);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	pdata->sd_emmc_reg = (struct meson_mmc_regs *)addr;
> +
> +	return 0;
> +}
> +
> +static int meson_mmc_probe(struct udevice *dev)
> +{
> +	struct meson_mmc_platdata *pdata = dev->platdata;
> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +	struct mmc *mmc;
> +	struct mmc_config *cfg;
> +
> +	cfg = &pdata->cfg;
> +	cfg->ops = &meson_mmc_ops;
> +
> +	cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
> +			MMC_VDD_31_32 | MMC_VDD_165_195;
> +	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
> +			 MMC_MODE_HS_52MHz | MMC_MODE_HS;
> +	cfg->f_min = 400000;
> +	cfg->f_max = 50000000;
> +	cfg->b_max = 256;
> +
> +	mmc = mmc_create(cfg, pdata);
> +	if (!mmc)
> +		return -ENOMEM;
> +
> +	upriv->mmc = mmc;
> +	return 0;
> +}
> +
> +static const struct udevice_id meson_mmc_match[] = {
> +	{ .compatible = "amlogic,meson-mmc" },
> +	{ /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(meson_mmc) = {
> +	.name = "meson_mmc",
> +	.id = UCLASS_MMC,
> +	.of_match = meson_mmc_match,
> +	.probe = meson_mmc_probe,
> +	.ofdata_to_platdata = meson_mmc_ofdata_to_platdata,
> +	.platdata_auto_alloc_size = sizeof(struct meson_mmc_platdata),
> +};
> 



From linus.walleij at linaro.org  Thu Aug  4 01:10:23 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 4 Aug 2016 10:10:23 +0200
Subject: [PATCH] pinctrl: meson: Drop pinctrl_unregister for devm_
 registered device
In-Reply-To: <1469544718-32001-1-git-send-email-weiyj.lk@gmail.com>
References: <1469544718-32001-1-git-send-email-weiyj.lk@gmail.com>
Message-ID: <CACRpkdZutfsuRn9_QfsF6dzMWNyQp-Enic7MiibxkzV-dS24Vg@mail.gmail.com>

On Tue, Jul 26, 2016 at 4:51 PM, Wei Yongjun <weiyj.lk at gmail.com> wrote:

> It's not necessary to unregister pin controller device registered
> with devm_pinctrl_register() and using pinctrl_unregister() leads
> to a double free.
>
> This is detected by Coccinelle semantic patch.
>
> Signed-off-by: Wei Yongjun <weiyj.lk at gmail.com>

Patch applied for fixes with Dmitry's and Kevin's tags.

Yours,
Linus Walleij


From robh at kernel.org  Thu Aug  4 11:15:56 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 4 Aug 2016 13:15:56 -0500
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <20160803231843.23012-1-khilman@baylibre.com>
References: <20160803231843.23012-1-khilman@baylibre.com>
Message-ID: <20160804181556.GA13000@rob-hp-laptop>

On Wed, Aug 03, 2016 at 04:18:42PM -0700, Kevin Hilman wrote:
> Add binding and basic support for the SD/eMMC controller on Amlogic
> S905/GXBB devices.
> 
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>
> ---
>  .../devicetree/bindings/mmc/amlogic,meson-gxbb.txt | 29 +++++++++
>  .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 74 ++++++++++++++++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   | 71 +++++++++++++++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 36 ++++++++++-
>  4 files changed, 209 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
> 
> diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
> new file mode 100644
> index 000000000000..2bfdf47018c5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
> @@ -0,0 +1,29 @@
> +Amlogic SD / eMMC controller for S905/GXBB family SoCs
> +
> +The MMC 5.1 compliant host controller on Amlogic provides the
> +interface for SD, eMMC and SDIO devices.
> +
> +This file documents the properties in addition to those available in
> +the MMC core bindings, documented by mmc.txt.
> +
> +Required properties:
> +- compatible : contains "amlogic,meson-gxbb"
> +- clocks     : A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
> +- clock-names: Should contain the following:
> +	"core" - Main peripheral bus clock
> +	"clkin0" - Parent clock of internal mux
> +	"clkin1" - Other parent clock of internal mux
> +  The driver has an interal mux clock which switches between clkin0 and clkin1 depending on the
> +  clock rate requested by the MMC core.
> +
> +Example:
> +
> +	sd_emmc_a: mmc at 70000 {
> +        	compatible = "amlogic,meson-gxbb-mmc";
> +		reg = <0x0 0x70000 0x0 0x2000>;
> +                interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
> +		clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
> +		clock-names = "core", "clkin0", "clkin1";
> +		pinctrl-0 = <&emmc_pins>;
> +	};
> +
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
> index 90a84c514d3d..f41d8fe5c706 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
> @@ -73,6 +73,45 @@
>  			default-state = "off";
>  		};
>  	};
> +
> +	mmc_iv: gpio-regulator {
> +		compatible = "regulator-gpio";
> +
> +		regulator-name = "mmc-gpio-supply";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <3300000>;
> +
> +		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
> +		gpio-states = <0 1>;
> +
> +		/*
> +		 * Based on ODROID-C2 schematics:
> +		 * signal name: IO_TF_3V3N_1V8, GPIOAO bit 3
> +		 */
> +		states = <3300000 0
> +			  1800000 1>;

There are multiple things wrong in this node based on the regulator-gpio 
documentation.

> +	};
> +
> +	vcc1v8: regulator {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VCC1V8";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +		regulator-always-on;
> +	};
> +
> +	vcc3v3: regulator {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VCC3V3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		regulator-always-on;
> +	};
> +
> +	emmc_pwrseq: emmc-pwrseq {
> +		compatible = "mmc-pwrseq-emmc";
> +		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
> +	};
>  };
>  
>  &uart_AO {
> @@ -87,3 +126,38 @@
>  	pinctrl-names = "default";
>  };
>  
> +&sd_emmc_b {
> +	status = "okay";
> +	pinctrl-0 = <&sdcard_pins>;
> +	pinctrl-names = "default";
> +
> +	bus-width = <4>;
> +	cap-sd-highspeed;
> +	max-frequency = <100000000>;
> +
> +	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
> +	cd-inverted;
> +
> +	vmmc-supply = <&mmc_iv>;
> +	voltage-ranges = <1800 3300>;
> +};
> +
> +&sd_emmc_c {
> +	status = "okay";
> +	pinctrl-0 = <&emmc_pins>;
> +	pinctrl-names = "default";
> +
> +	bus-width = <8>;
> +	cap-sd-highspeed;
> +	max-frequency = <200000000>;
> +	non-removable;
> +	disable-wp;
> +	cap-mmc-highspeed;
> +	mmc-ddr-1_8v;
> +	mmc-hs200-1_8v;
> +
> +	mmc-pwrseq = <&emmc_pwrseq>;
> +	voltage-ranges = <1800 3300>;
> +	vmmc-supply = <&vcc3v3>;
> +	vmmcq-sumpply = <&vcc1v8>;
> +};
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
> index f4f30f674b4c..77698815943a 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
> @@ -57,6 +57,42 @@
>  		device_type = "memory";
>  		reg = <0x0 0x0 0x0 0x40000000>;
>  	};
> +
> +	mmc_iv: gpio-regulator {
> +		compatible = "regulator-gpio";
> +
> +		regulator-name = "mmc-gpio-supply";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <3300000>;
> +
> +		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
> +		gpio-states = <0 1>;
> +
> +		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
> +		states = <1800000 0
> +			  3300000 1>;
> +	};
> +
> +	vddio_boot: regulator {
[...]
> +	vcc_3v3: regulator {

This won't even compile as you have the same node name twice.

> +		compatible = "regulator-fixed";
> +		regulator-name = "VCC_3V3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		regulator-always-on;
> +	};
> +
> +	emmc_pwrseq: emmc-pwrseq {
> +		compatible = "mmc-pwrseq-emmc";
> +		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
> +	};
>  };
>  
>  /* This UART is brought out to the DB9 connector */
> @@ -72,3 +108,38 @@
>  	pinctrl-names = "default";
>  };
>  
> +&sd_emmc_b {
> +	status = "okay";
> +	pinctrl-0 = <&sdcard_pins>;
> +	pinctrl-names = "default";
> +
> +	bus-width = <4>;
> +	cap-sd-highspeed;
> +	max-frequency = <100000000>;
> +
> +	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
> +	cd-inverted;
> +
> +	voltage-ranges = <1800 3300>;
> +	vmmc-supply = <&mmc_iv>;
> +};
> +
> +&sd_emmc_c {
> +	status = "okay";
> +	pinctrl-0 = <&emmc_pins>;
> +	pinctrl-names = "default";
> +
> +	bus-width = <8>;
> +	cap-sd-highspeed;
> +	cap-mmc-highspeed;
> +	max-frequency = <200000000>;
> +	non-removable;
> +	disable-wp;
> +	mmc-ddr-1_8v;
> +	mmc-hs200-1_8v;
> +
> +	mmc-pwrseq = <&emmc_pwrseq>;
> +	voltage-ranges = <1800 3300>;
> +	vmmc-supply = <&vcc_3v3>;
> +	vmmcq-sumpply = <&vddio_boot>;
> +};
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> index 35c8b2beb05c..2c200f96467c 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> @@ -247,7 +247,8 @@
>  					mux {
>  						groups = "emmc_nand_d07",
>  						       "emmc_cmd",
> -						       "emmc_clk";
> +						       "emmc_clk",
> +						       "emmc_ds";
>  						function = "emmc";
>  					};
>  				};
> @@ -330,6 +331,39 @@
>  			#address-cells = <2>;
>  			#size-cells = <2>;
>  			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
> +
> +			sd_emmc_a: mmc at 70000 {
> +				compatible = "amlogic,meson-gxbb-mmc";
> +				reg = <0x0 0x70000 0x0 0x2000>;
> +				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
> +				clocks = <&clkc CLKID_SD_EMMC_A>,
> +					 <&xtal>,
> +					 <&clkc CLKID_FCLK_DIV2>;
> +				clock-names = "core", "clkin0", "clkin1";
> +				status = "disabled";
> +			};
> +
> +			sd_emmc_b: mmc at 72000 {
> +				compatible = "amlogic,meson-gxbb-mmc";
> +				reg = <0x0 0x72000 0x0 0x2000>;
> +				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
> +				clocks = <&clkc CLKID_SD_EMMC_B>,
> +					 <&xtal>,
> +					 <&clkc CLKID_FCLK_DIV2>;
> +				clock-names = "core", "clkin0", "clkin1";
> +				status = "disabled";
> +			};
> +
> +			sd_emmc_c: mmc at 74000 {
> +				compatible = "amlogic,meson-gxbb-mmc";
> +				reg = <0x0 0x74000 0x0 0x2000>;
> +				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
> +				clocks = <&clkc CLKID_SD_EMMC_C>,
> +					 <&xtal>,
> +					 <&clkc CLKID_FCLK_DIV2>;
> +				clock-names = "core", "clkin0", "clkin1";
> +				status = "disabled";
> +			};
>  		};
>  
>  		ethmac: ethernet at c9410000 {
> -- 
> 2.9.0
> 
> --
> 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


From khilman at baylibre.com  Thu Aug  4 15:58:55 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 04 Aug 2016 15:58:55 -0700
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <20160804181556.GA13000@rob-hp-laptop> (Rob Herring's message of
 "Thu, 4 Aug 2016 13:15:56 -0500")
References: <20160803231843.23012-1-khilman@baylibre.com>
 <20160804181556.GA13000@rob-hp-laptop>
Message-ID: <m2oa58nntc.fsf@baylibre.com>

Hi Rob,

Rob Herring <robh at kernel.org> writes:

> On Wed, Aug 03, 2016 at 04:18:42PM -0700, Kevin Hilman wrote:
>> Add binding and basic support for the SD/eMMC controller on Amlogic
>> S905/GXBB devices.
>> 
>> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

[...]

>> +	mmc_iv: gpio-regulator {
>> +		compatible = "regulator-gpio";
>> +
>> +		regulator-name = "mmc-gpio-supply";
>> +		regulator-min-microvolt = <1800000>;
>> +		regulator-max-microvolt = <3300000>;
>> +
>> +		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
>> +		gpio-states = <0 1>;
>> +
>> +		/*
>> +		 * Based on ODROID-C2 schematics:
>> +		 * signal name: IO_TF_3V3N_1V8, GPIOAO bit 3
>> +		 */
>> +		states = <3300000 0
>> +			  1800000 1>;
>
> There are multiple things wrong in this node based on the regulator-gpio 
> documentation.

I see I got the property name wrong, and the number of elements wrong,
and this fixes those issues:

-               gpio-states = <0 1>;
+               gpios-states = <0>;

By "multiple", did you mean more than those 2?  If so, I'm not seeing
what else is wrong.

[...]

>> +	mmc_iv: gpio-regulator {
>> +		compatible = "regulator-gpio";
>> +
>> +		regulator-name = "mmc-gpio-supply";
>> +		regulator-min-microvolt = <1800000>;
>> +		regulator-max-microvolt = <3300000>;
>> +
>> +		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
>> +		gpio-states = <0 1>;
>> +
>> +		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
>> +		states = <1800000 0
>> +			  3300000 1>;
>> +	};
>> +
>> +	vddio_boot: regulator {
> [...]
>> +	vcc_3v3: regulator {
>
> This won't even compile as you have the same node name twice.

Oops, it's wrong indeed, but in fact, it does compile, otherwise I
would've caught that..  Even if I remove the labels, it still compiles.
Interesting.

Anyways, I'll make those unique node-names in the next spin.

Thanks for the review,

Kevin



From robh at kernel.org  Thu Aug  4 19:45:05 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 4 Aug 2016 21:45:05 -0500
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <m2oa58nntc.fsf@baylibre.com>
References: <20160803231843.23012-1-khilman@baylibre.com>
 <20160804181556.GA13000@rob-hp-laptop>
 <m2oa58nntc.fsf@baylibre.com>
Message-ID: <CAL_JsqK18UPAUFCqfN7TJqz4AoLBbNA7fOgeQXqPES06fuhgFQ@mail.gmail.com>

+dtc list

On Thu, Aug 4, 2016 at 5:58 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Hi Rob,
>
> Rob Herring <robh at kernel.org> writes:
>
>> On Wed, Aug 03, 2016 at 04:18:42PM -0700, Kevin Hilman wrote:
>>> Add binding and basic support for the SD/eMMC controller on Amlogic
>>> S905/GXBB devices.
>>>
>>> Signed-off-by: Kevin Hilman <khilman at baylibre.com>
>
> [...]
>
>>> +    mmc_iv: gpio-regulator {
>>> +            compatible = "regulator-gpio";
>>> +
>>> +            regulator-name = "mmc-gpio-supply";
>>> +            regulator-min-microvolt = <1800000>;
>>> +            regulator-max-microvolt = <3300000>;
>>> +
>>> +            gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
>>> +            gpio-states = <0 1>;
>>> +
>>> +            /*
>>> +             * Based on ODROID-C2 schematics:
>>> +             * signal name: IO_TF_3V3N_1V8, GPIOAO bit 3
>>> +             */
>>> +            states = <3300000 0
>>> +                      1800000 1>;
>>
>> There are multiple things wrong in this node based on the regulator-gpio
>> documentation.
>
> I see I got the property name wrong, and the number of elements wrong,
> and this fixes those issues:
>
> -               gpio-states = <0 1>;
> +               gpios-states = <0>;
>
> By "multiple", did you mean more than those 2?  If so, I'm not seeing
> what else is wrong.

I was thinking it needed an enable-gpio property, but now I see that
is separate from "gpios".

> [...]
>
>>> +    mmc_iv: gpio-regulator {
>>> +            compatible = "regulator-gpio";
>>> +
>>> +            regulator-name = "mmc-gpio-supply";
>>> +            regulator-min-microvolt = <1800000>;
>>> +            regulator-max-microvolt = <3300000>;
>>> +
>>> +            gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
>>> +            gpio-states = <0 1>;
>>> +
>>> +            /* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
>>> +            states = <1800000 0
>>> +                      3300000 1>;
>>> +    };
>>> +
>>> +    vddio_boot: regulator {
>> [...]
>>> +    vcc_3v3: regulator {
>>
>> This won't even compile as you have the same node name twice.
>
> Oops, it's wrong indeed, but in fact, it does compile, otherwise I
> would've caught that..  Even if I remove the labels, it still compiles.
> Interesting.

Humm, news to me. I will have to do some testing unless the dtc folks
have any insight.

Rob


From tim.kryger at gmail.com  Thu Aug  4 21:16:24 2016
From: tim.kryger at gmail.com (Tim Kryger)
Date: Thu, 4 Aug 2016 21:16:24 -0700
Subject: [PATCH v0 2/4] i2c: bcm-kona: Use complete() instead of
 complete_all()
In-Reply-To: <1470225791-16613-3-git-send-email-wagi@monom.org>
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
 <1470225791-16613-3-git-send-email-wagi@monom.org>
Message-ID: <CAD7vxxLCtN1+vTj5_XL5N-w4YXcj=1jUj5PxQvFUzVT_E0m7ug@mail.gmail.com>

On Wed, Aug 3, 2016 at 5:03 AM, Daniel Wagner <wagi at monom.org> wrote:
> From: Daniel Wagner <daniel.wagner at bmw-carit.de>
>
> There is only one waiter for the completion, therefore there
> is no need to use complete_all(). Let's make that clear by
> using complete() instead of complete_all().
>
> The usage pattern of the completion is:
>
> bcm_kona_send_i2c_cmd()
>   reinit_completion()
>   ...
>   bcm_kona_i2c_send_cmd_to_ctrl()
>   ...
>   wait_for_completion_timeout()
>
> Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>

Reviewed-by: Tim Kryger <tim.kryger at gmail.com>

> ---
>  drivers/i2c/busses/i2c-bcm-kona.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
> index ac9f476..f987432 100644
> --- a/drivers/i2c/busses/i2c-bcm-kona.c
> +++ b/drivers/i2c/busses/i2c-bcm-kona.c
> @@ -229,7 +229,7 @@ static irqreturn_t bcm_kona_i2c_isr(int irq, void *devid)
>                        dev->base + TXFCR_OFFSET);
>
>         writel(status & ~ISR_RESERVED_MASK, dev->base + ISR_OFFSET);
> -       complete_all(&dev->done);
> +       complete(&dev->done);
>
>         return IRQ_HANDLED;
>  }
> --
> 2.7.4
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From khilman at baylibre.com  Fri Aug  5 08:22:13 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri, 05 Aug 2016 08:22:13 -0700
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <20160805034623.GA1883@excalibur.cnev.de> (Karsten Merker's
 message of "Fri, 5 Aug 2016 05:46:23 +0200")
References: <20160803231843.23012-1-khilman@baylibre.com>
 <20160805034623.GA1883@excalibur.cnev.de>
Message-ID: <m2fuqjmeai.fsf@baylibre.com>

Karsten Merker <merker at debian.org> writes:

> On Wed, Aug 03, 2016 at 04:18:42PM -0700, Kevin Hilman wrote:
>
>> Add binding and basic support for the SD/eMMC controller on Amlogic
>> S905/GXBB devices.
>> 
>> Signed-off-by: Kevin Hilman <khilman at baylibre.com>
>> ---
>>  .../devicetree/bindings/mmc/amlogic,meson-gxbb.txt | 29 +++++++++
>>  .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 74 ++++++++++++++++++++++
>>  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   | 71 +++++++++++++++++++++
>>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 36 ++++++++++-
>>  4 files changed, 209 insertions(+), 1 deletion(-)
>>  create mode 100644 Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
>> 
>> diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
>> new file mode 100644
>> index 000000000000..2bfdf47018c5
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gxbb.txt
>> @@ -0,0 +1,29 @@
>> +Amlogic SD / eMMC controller for S905/GXBB family SoCs
>> +
>> +The MMC 5.1 compliant host controller on Amlogic provides the
>> +interface for SD, eMMC and SDIO devices.
>> +
>> +This file documents the properties in addition to those available in
>> +the MMC core bindings, documented by mmc.txt.
>> +
>> +Required properties:
>> +- compatible : contains "amlogic,meson-gxbb"
>
> I assume that should be "amlogic,meson-gxbb-mmc" instead of
> "amlogic,meson-gxbb", shouldn't it?

Correct, thanks for the review.

Kevin


From afaerber at suse.de  Sun Aug  7 08:49:36 2016
From: afaerber at suse.de (=?UTF-8?Q?Andreas_F=c3=a4rber?=)
Date: Sun, 7 Aug 2016 17:49:36 +0200
Subject: [U-Boot] [PATCH 1/2] mmc: Add Amlogic Meson driver
In-Reply-To: <CAOQ7t2Y6zoYfD88-tSCS78=zON-nr8FbU1nOkoDQz3a1FnTy5Q@mail.gmail.com>
References: <1463056902-8533-1-git-send-email-carlo@caione.org>
 <1463056902-8533-2-git-send-email-carlo@caione.org>
 <m2lh3e2hrb.fsf@baylibre.com>
 <CAOQ7t2Y6zoYfD88-tSCS78=zON-nr8FbU1nOkoDQz3a1FnTy5Q@mail.gmail.com>
Message-ID: <09851bc9-e463-06cb-fcb7-5cbd93724148@suse.de>

Am 13.05.2016 um 15:53 schrieb Carlo Caione:
> [...] but since it is really unlikely that we will
> ever see a U-Boot port for the Meson8b I stuck with that.

Why do you consider that so unlikely? Please don't make such assumptions
for design decisions.

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N?rnberg)


From khilman at baylibre.com  Sun Aug  7 22:54:59 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sun, 7 Aug 2016 22:54:59 -0700
Subject: [PATCH v3 0/4] Add Meson 8b / GXBB support to the IR driver
In-Reply-To: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
References: <20160626210622.5257-1-martin.blumenstingl@googlemail.com>
 <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
Message-ID: <CAOi56cV=mELtvUVAB8M=x6abfjQ-8dBj4HH8Xieuv14g8ppgWA@mail.gmail.com>

Hi Martin,

On Tue, Jun 28, 2016 at 12:17 PM, Martin Blumenstingl
<martin.blumenstingl at googlemail.com> wrote:
> Newer Amlogic platforms (Meson 8b and GXBB) use a slightly different
> register layout for their Infrared Remoete Controller. The decoder mode
> is now configured in another register. Without the changes to the
> meson-ir driver we are simply getting incorrect "durations" reported
> from the hardware (because the hardware is not in time measurement aka
> software decode mode).
>
> This problem was also noticed by some people trying to use this on an
> ODROID-C1 and ODROID-C2 - the workaround there (probably because the
> datasheets were not publicy available yet at that time) was to switch
> to ir_raw_event_store_edge (which leaves it up to the kernel to measure
> the duration of a pulse). See [0] and [1] for the corresponding
> patches.

I tried this on meson-gxbb-p200 and I'm not seeing any button press
events with evtest or ir-keytable when using the Amlogic remote that
came with the board.  Below is the register dump you requested on IRC:

[    1.068347] Registered IR keymap rc-empty
[    1.072422] input: meson-ir as
/devices/platform/soc/c8100000.aobus/c8100580.ir/rc/rc0/input0
[    1.080814] rc rc0: meson-ir as
/devices/platform/soc/c8100000.aobus/c8100580.ir/rc/rc0
[    1.088839] input: MCE IR Keyboard/Mouse (meson-ir) as
/devices/virtual/input/input1
[    1.096519] rc rc0: lirc_dev: driver ir-lirc-codec (meson-ir)
registered at minor = 0
[    1.104119] meson-ir c8100580.ir: receiver initialized
[    1.109172] IR: reg 0x00 = 0x01d801ac
[    1.112795] IR: reg 0x04 = 0x00f800ca
[    1.116416] IR: reg 0x08 = 0x007a0066
[    1.120037] IR: reg 0x0c = 0x0044002c
[    1.123660] IR: reg 0x10 = 0x70fa0009
[    1.127278] IR: reg 0x14 = 0x00000000
[    1.130907] IR: reg 0x18 = 0x08915c00
[    1.134527] IR: reg 0x1c = 0x00009f44
[    1.138152] IR: reg 0x20 = 0x00000002

Kevin


From weiyj.lk at gmail.com  Mon Aug  8 06:55:20 2016
From: weiyj.lk at gmail.com (Wei Yongjun)
Date: Mon,  8 Aug 2016 13:55:20 +0000
Subject: [PATCH -next] clk: gxbb: use builtin_platform_driver to simplify the
 code
Message-ID: <1470664520-9604-1-git-send-email-weiyj.lk@gmail.com>

Use the builtin_platform_driver() macro to make the code simpler.

Signed-off-by: Wei Yongjun <weiyj.lk at gmail.com>
---
 drivers/clk/meson/gxbb.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 8e36d22..b736277 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -946,8 +946,4 @@ static struct platform_driver gxbb_driver = {
 	},
 };
 
-static int __init gxbb_clkc_init(void)
-{
-	return platform_driver_register(&gxbb_driver);
-}
-device_initcall(gxbb_clkc_init);
+builtin_platform_driver(gxbb_driver);





From narmstrong at baylibre.com  Tue Aug  9 01:52:14 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 10:52:14 +0200
Subject: [PATCH 0/3] Add Platform MHU mailbox driver for Amlogic GXBB
Message-ID: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>

In order to support Mailbox links for the Amlogic GXBB SoC, add a generic
platform MHU driver based on arm_mhu.c.

This patchset follows a RFC thread along the GXBB SCPI support at :
http://lkml.kernel.org/r/1466503374-28841-1-git-send-email-narmstrong at baylibre.com
And specific MHU discussions at :
http://lkml.kernel.org/r/CABb+yY3HqJG2+GMWCWF9PomxobrwWGZ=TZe5NvXPcHMDdLhkcQ at mail.gmail.com

Changes since RFC v2 :
 - Rename to platform_mhu
 - Sync all link functions with arm_mhu

Neil Armstrong (3):
  mailbox: Add Platform Message-Handling-Unit variant driver
  dt-bindings: mailbox: Add Amlogic Meson MHU Bindings
  ARM64: dts: meson-gxbb: Add Meson MHU Node

 .../devicetree/bindings/mailbox/meson-mhu.txt      |  33 ++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   8 +
 drivers/mailbox/Kconfig                            |  10 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/platform_mhu.c                     | 203 +++++++++++++++++++++
 5 files changed, 256 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/meson-mhu.txt
 create mode 100644 drivers/mailbox/platform_mhu.c

-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 01:52:16 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 10:52:16 +0200
Subject: [PATCH 2/3] dt-bindings: mailbox: Add Amlogic Meson MHU Bindings
In-Reply-To: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
References: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470732737-18391-3-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../devicetree/bindings/mailbox/meson-mhu.txt      | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/meson-mhu.txt

diff --git a/Documentation/devicetree/bindings/mailbox/meson-mhu.txt b/Documentation/devicetree/bindings/mailbox/meson-mhu.txt
new file mode 100644
index 0000000..4a80b44
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/meson-mhu.txt
@@ -0,0 +1,33 @@
+Amlogic Meson MHU Mailbox Driver
+================================
+
+The Amlogic's Meson SoCs Message-Handling-Unit (MHU) is a mailbox controller
+that has 2 independent channels/links to communicate with remote processor(s).
+MHU links are hardwired on a platform. A link raises interrupt for any
+received data. However, there is no specified way of knowing if the sent
+data has been read by the remote. This driver assumes the sender polls
+STAT register and the remote clears it after having read the data.
+
+Mailbox Device Node:
+====================
+
+Required properties:
+--------------------
+- compatible:		Shall be "amlogic,meson-gxbb-mhu"
+- reg:			Contains the mailbox register address range (base
+			address and length)
+- #mbox-cells		Shall be 1 - the index of the channel needed.
+- interrupts:		Contains the interrupt information corresponding to
+			each of the 2 links of MHU.
+
+Example:
+--------
+
+	mailbox: mailbox at c883c400 {
+		#mbox-cells = <1>;
+		compatible = "amlogic,meson-gxbb-mhu";
+		reg = <0 0xc883c400 0 0x4c>;
+		interrupts = <0 209 IRQ_TYPE_EDGE_RISING>,
+			   <0 210 IRQ_TYPE_EDGE_RISING>;
+		#mbox-cells = <1>;
+	};
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 01:52:15 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 10:52:15 +0200
Subject: [PATCH 1/3] mailbox: Add Platform Message-Handling-Unit variant driver
In-Reply-To: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
References: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470732737-18391-2-git-send-email-narmstrong@baylibre.com>

Add Message-Handling-Unit driver for platform variants as mailbox controller.
Actually, only the Amlogic Meson GXBB SoC MHU is supported.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/mailbox/Kconfig        |  10 ++
 drivers/mailbox/Makefile       |   2 +
 drivers/mailbox/platform_mhu.c | 203 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 215 insertions(+)
 create mode 100644 drivers/mailbox/platform_mhu.c

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 97c3729..4cc93c6 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -15,6 +15,16 @@ config ARM_MHU
 	  The controller has 3 mailbox channels, the last of which can be
 	  used in Secure mode only.
 
+config PLATFORM_MHU
+	tristate "Platform MHU Mailbox"
+	depends on OF
+	depends on HAS_IOMEM
+	help
+	  Say Y here if you want to build a platform specific variant MHU
+	  controller driver.
+	  The controller has a maximum of 3 mailbox channels, the last of
+	  which can be used in Secure mode only.
+
 config PL320_MBOX
 	bool "ARM PL320 Mailbox"
 	depends on ARM_AMBA
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 66c38e3..ace6fed 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_MAILBOX_TEST)	+= mailbox-test.o
 
 obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
 
+obj-$(CONFIG_PLATFORM_MHU)	+= platform_mhu.o
+
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
diff --git a/drivers/mailbox/platform_mhu.c b/drivers/mailbox/platform_mhu.c
new file mode 100644
index 0000000..d657a50
--- /dev/null
+++ b/drivers/mailbox/platform_mhu.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 BayLibre SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ * Heavily based on arm_mhu.c from :
+ * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Jassi Brar <jaswinder.singh at linaro.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * 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/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mailbox_controller.h>
+
+#define INTR_SET_OFS	0x0
+#define INTR_STAT_OFS	0x4
+#define INTR_CLR_OFS	0x8
+
+#define MHU_LP_OFFSET	0x10
+#define MHU_HP_OFFSET	0x1c
+
+#define TX_REG_OFFSET	0x24
+
+#define MHU_CHANS	2
+
+struct platform_mhu_link {
+	unsigned int irq;
+	void __iomem *tx_reg;
+	void __iomem *rx_reg;
+};
+
+struct platform_mhu {
+	void __iomem *base;
+	struct platform_mhu_link mlink[MHU_CHANS];
+	struct mbox_chan chan[MHU_CHANS];
+	struct mbox_controller mbox;
+};
+
+static irqreturn_t platform_mhu_rx_interrupt(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 val;
+
+	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
+	if (!val)
+		return IRQ_NONE;
+
+	mbox_chan_received_data(chan, (void *)&val);
+
+	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
+
+	return IRQ_HANDLED;
+}
+
+static bool platform_mhu_last_tx_done(struct mbox_chan *chan)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+
+	return (val == 0);
+}
+
+static int platform_mhu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 *arg = data;
+
+	writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);
+
+	return 0;
+}
+
+static int platform_mhu_startup(struct mbox_chan *chan)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 val;
+	int ret;
+
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
+
+	ret = request_irq(mlink->irq, platform_mhu_rx_interrupt,
+			  IRQF_SHARED, "platform_mhu_link", chan);
+	if (ret) {
+		dev_err(chan->mbox->dev,
+			"Unable to acquire IRQ %d\n", mlink->irq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void platform_mhu_shutdown(struct mbox_chan *chan)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+
+	free_irq(mlink->irq, chan);
+}
+
+static const struct mbox_chan_ops platform_mhu_ops = {
+	.send_data = platform_mhu_send_data,
+	.startup = platform_mhu_startup,
+	.shutdown = platform_mhu_shutdown,
+	.last_tx_done = platform_mhu_last_tx_done,
+};
+
+static int platform_mhu_probe(struct platform_device *pdev)
+{
+	int i, err;
+	struct platform_mhu *mhu;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int platform_mhu_reg[MHU_CHANS] = {MHU_LP_OFFSET, MHU_HP_OFFSET};
+
+	/* Allocate memory for device */
+	mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
+	if (!mhu)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mhu->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mhu->base)) {
+		dev_err(dev, "ioremap failed\n");
+		return PTR_ERR(mhu->base);
+	}
+
+	for (i = 0; i < MHU_CHANS; i++) {
+		mhu->chan[i].con_priv = &mhu->mlink[i];
+		mhu->mlink[i].irq = platform_get_irq(pdev, i);
+		if (mhu->mlink[i].irq < 0) {
+			dev_err(dev, "failed to get irq%d\n", i);
+			return mhu->mlink[i].irq;
+		}
+		mhu->mlink[i].rx_reg = mhu->base + platform_mhu_reg[i];
+		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET;
+	}
+
+	mhu->mbox.dev = dev;
+	mhu->mbox.chans = &mhu->chan[0];
+	mhu->mbox.num_chans = MHU_CHANS;
+	mhu->mbox.ops = &platform_mhu_ops;
+	mhu->mbox.txdone_irq = false;
+	mhu->mbox.txdone_poll = true;
+	mhu->mbox.txpoll_period = 1;
+
+	platform_set_drvdata(pdev, mhu);
+
+	err = mbox_controller_register(&mhu->mbox);
+	if (err) {
+		dev_err(dev, "Failed to register mailboxes %d\n", err);
+		return err;
+	}
+
+	dev_info(dev, "Platform MHU Mailbox registered\n");
+	return 0;
+}
+
+static int platform_mhu_remove(struct platform_device *pdev)
+{
+	struct platform_mhu *mhu = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mhu->mbox);
+
+	return 0;
+}
+
+static const struct of_device_id platform_mhu_dt_ids[] = {
+	{ .compatible = "amlogic,meson-gxbb-mhu", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, platform_mhu_dt_ids);
+
+static struct platform_driver platform_mhu_driver = {
+	.probe	= platform_mhu_probe,
+	.remove	= platform_mhu_remove,
+	.driver = {
+		.name = "platform-mhu",
+		.of_match_table	= platform_mhu_dt_ids,
+	},
+};
+
+module_platform_driver(platform_mhu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:platform-mhu");
+MODULE_DESCRIPTION("Platform MHU Driver");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 01:52:17 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 10:52:17 +0200
Subject: [PATCH 3/3] ARM64: dts: meson-gxbb: Add Meson MHU Node
In-Reply-To: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
References: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470732737-18391-4-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..dfd2ff7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -321,6 +321,14 @@
 				#clock-cells = <1>;
 				reg = <0x0 0x0 0x0 0x3db>;
 			};
+
+			mailbox: mailbox at 400 {
+				compatible = "amlogic,meson-gxbb-mhu";
+				reg = <0 0x400 0 0x4c>;
+				interrupts = <0 209 IRQ_TYPE_EDGE_RISING>,
+					     <0 210 IRQ_TYPE_EDGE_RISING>;
+				#mbox-cells = <1>;
+			};
 		};
 
 		apb: apb at d0000000 {
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 02:13:25 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 11:13:25 +0200
Subject: [PATCH 0/3] clk: Add Meson GXBB Always-On Reset + Clocks
Message-ID: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>

The Amlogic Meson GXBB SoC has an Always-On part that contains pairs on
clocks and reset controls in a single memory mapped control register.
Add a separate clocks and reset node with the corresponding driver
exporting clock nodes and a reset controller.

Neil Armstrong (3):
  clk: meson: Add GXBB AO Clock and Reset controller driver
  dt-bindings: clock: reset: Add GXBB AO Clock and Reset Bindings
  ARM64: dts: meson-gxbb: Add GXBB AO Clock and Reset node

 .../bindings/clock/amlogic,gxbb-aoclkc.txt         |  45 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   9 +
 drivers/clk/meson/Makefile                         |   2 +-
 drivers/clk/meson/gxbb-aoclk.c                     | 203 +++++++++++++++++++++
 include/dt-bindings/clock/gxbb-aoclkc.h            |  66 +++++++
 include/dt-bindings/reset/gxbb-aoclkc.h            |  66 +++++++
 6 files changed, 390 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
 create mode 100644 drivers/clk/meson/gxbb-aoclk.c
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h

-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 02:13:27 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 11:13:27 +0200
Subject: [PATCH 2/3] dt-bindings: clock: reset: Add GXBB AO Clock and Reset
 Bindings
In-Reply-To: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470734008-18849-3-git-send-email-narmstrong@baylibre.com>

Add documentations and dt-bindings headers for the AO clock and reset
controller.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../bindings/clock/amlogic,gxbb-aoclkc.txt         | 45 +++++++++++++++
 include/dt-bindings/clock/gxbb-aoclkc.h            | 66 ++++++++++++++++++++++
 include/dt-bindings/reset/gxbb-aoclkc.h            | 66 ++++++++++++++++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
new file mode 100644
index 0000000..a55d31b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
@@ -0,0 +1,45 @@
+* Amlogic GXBB AO Clock and Reset Unit
+
+The Amlogic GXBB AO clock controller generates and supplies clock to various
+controllers within the Always-On part of the SoC.
+
+Required Properties:
+
+- compatible: should be "amlogic,gxbb-aoclkc"
+- reg: physical base address of the clock controller and length of memory
+       mapped region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/gxbb-aoclkc.h header and can be
+used in device tree sources.
+
+- #reset-cells: should be 1.
+
+Each reset is assigned an identifier and client nodes can use this identifier
+to specify the reset which they consume. All available resets are defined as
+preprocessor macros in the dt-bindings/reset/gxbb-aoclkc.h header and can be
+used in device tree sources.
+
+Example: AO Clock controller node:
+
+	clkc_AO: clock-controller at 040 {
+		compatible = "amlogic,gxbb-aoclkc";
+		reg = <0x0 0x040 0x0 0x4>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock and reset generated
+  by the clock controller:
+
+	uart_AO: serial at 4c0 {
+		compatible = "amlogic,meson-uart";
+		reg = <0x4c0 0x14>;
+		interrupts = <0 90 1>;
+		clocks = <&clkc_AO CLKID_AO_UART1>;
+		resets = <&clkc_AO RESET_AO_UART1>;
+		status = "disabled";
+	};
diff --git a/include/dt-bindings/clock/gxbb-aoclkc.h b/include/dt-bindings/clock/gxbb-aoclkc.h
new file mode 100644
index 0000000..3175148
--- /dev/null
+++ b/include/dt-bindings/clock/gxbb-aoclkc.h
@@ -0,0 +1,66 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
+#define DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
+
+#define CLKID_AO_REMOTE		0
+#define CLKID_AO_I2C_MASTER	1
+#define CLKID_AO_I2C_SLAVE	2
+#define CLKID_AO_UART1		3
+#define CLKID_AO_UART2		4
+#define CLKID_AO_IR_BLASTER	5
+
+#endif
diff --git a/include/dt-bindings/reset/gxbb-aoclkc.h b/include/dt-bindings/reset/gxbb-aoclkc.h
new file mode 100644
index 0000000..9e3fd60
--- /dev/null
+++ b/include/dt-bindings/reset/gxbb-aoclkc.h
@@ -0,0 +1,66 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
+#define DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
+
+#define RESET_AO_REMOTE		0
+#define RESET_AO_I2C_MASTER	1
+#define RESET_AO_I2C_SLAVE	2
+#define RESET_AO_UART1		3
+#define RESET_AO_UART2		4
+#define RESET_AO_IR_BLASTER	5
+
+#endif
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 02:13:26 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 11:13:26 +0200
Subject: [PATCH 1/3] clk: meson: Add GXBB AO Clock and Reset controller driver
In-Reply-To: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>

Adds a Clock and Reset controller driver for the Always-On part
of the Amlogic Meson GXBB SoC.

It exports paired Clocks and Resets lines that will be used by
peripherals in the Always-On subsystem.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/clk/meson/Makefile     |   2 +-
 drivers/clk/meson/gxbb-aoclk.c | 203 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 204 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/meson/gxbb-aoclk.c

diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 197e401..d4cd4a3 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o
-obj-$(CONFIG_COMMON_CLK_GXBB)	 += gxbb.o
+obj-$(CONFIG_COMMON_CLK_GXBB)	 += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
new file mode 100644
index 0000000..56a9186
--- /dev/null
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -0,0 +1,203 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/module.h>
+#include <dt-bindings/clock/gxbb-aoclkc.h>
+#include <dt-bindings/reset/gxbb-aoclkc.h>
+
+static DEFINE_SPINLOCK(clk_lock);
+
+struct gxbb_aoclk_reset_controller {
+	struct reset_controller_dev reset;
+	unsigned int *data;
+	void __iomem *base;
+};
+
+static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	struct gxbb_aoclk_reset_controller *reset =
+		container_of(rcdev, struct gxbb_aoclk_reset_controller, reset);
+
+	writel(BIT(reset->data[id]), reset->base);
+
+	return 0;
+}
+
+static const struct reset_control_ops gxbb_aoclk_reset_ops = {
+	.reset = gxbb_aoclk_do_reset,
+};
+
+#define GXBB_AO_GATE(_name, _bit)					\
+static struct clk_gate _name##_ao = {					\
+	.reg = (void __iomem *)0,					\
+	.bit_idx = (_bit),						\
+	.lock = &clk_lock,						\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = #_name "_ao",					\
+		.ops = &clk_gate_ops,					\
+		.parent_names = (const char *[]){ "clk81" },		\
+		.num_parents = 1,					\
+		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
+	},								\
+}
+
+GXBB_AO_GATE(remote, 0);
+GXBB_AO_GATE(i2c_master, 1);
+GXBB_AO_GATE(i2c_slave, 2);
+GXBB_AO_GATE(uart1, 3);
+GXBB_AO_GATE(uart2, 5);
+GXBB_AO_GATE(ir_blaster, 6);
+
+static unsigned int gxbb_aoclk_reset[] = {
+	[RESET_AO_REMOTE] = 16,
+	[RESET_AO_I2C_MASTER] = 18,
+	[RESET_AO_I2C_SLAVE] = 19,
+	[RESET_AO_UART1] = 17,
+	[RESET_AO_UART2] = 22,
+	[RESET_AO_IR_BLASTER] = 23,
+};
+
+static struct clk_gate *gxbb_aoclk_gate[] = {
+	[CLKID_AO_REMOTE] = &remote_ao,
+	[CLKID_AO_I2C_MASTER] = &i2c_master_ao,
+	[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
+	[CLKID_AO_UART1] = &uart1_ao,
+	[CLKID_AO_UART2] = &uart2_ao,
+	[CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
+};
+
+static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
+	.hws = {
+		[CLKID_AO_REMOTE] = &remote_ao.hw,
+		[CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw,
+		[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao.hw,
+		[CLKID_AO_UART1] = &uart1_ao.hw,
+		[CLKID_AO_UART2] = &uart2_ao.hw,
+		[CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
+	},
+	.num = ARRAY_SIZE(gxbb_aoclk_gate),
+};
+
+static int gxbb_aoclkc_probe(struct platform_device *pdev)
+{
+	void __iomem *base;
+	int ret, clkid;
+	struct device *dev = &pdev->dev;
+	struct gxbb_aoclk_reset_controller *rstc;
+
+	rstc = devm_kzalloc(dev, sizeof(rstc), GFP_KERNEL);
+	if (!rstc)
+		return -ENOMEM;
+
+	/*  Generic clocks */
+	base = of_iomap(dev->of_node, 0);
+	if (!base) {
+		pr_err("%s: Unable to map clk base\n", __func__);
+		return -ENXIO;
+	}
+
+	/* Reset Controller */
+	rstc->base = base;
+	rstc->data = gxbb_aoclk_reset;
+	rstc->reset.ops = &gxbb_aoclk_reset_ops;
+	rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset);
+	rstc->reset.of_node = dev->of_node;
+	ret = devm_reset_controller_register(dev, &rstc->reset);
+
+	/*
+	 * Populate base address and register all clks
+	 */
+	for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) {
+		gxbb_aoclk_gate[clkid]->reg = base;
+
+		ret = devm_clk_hw_register(dev,
+					gxbb_aoclk_onecell_data.hws[clkid]);
+		if (ret)
+			goto iounmap;
+	}
+
+	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+			&gxbb_aoclk_onecell_data);
+
+iounmap:
+	iounmap(base);
+	return ret;
+}
+
+static const struct of_device_id gxbb_aoclkc_match_table[] = {
+	{ .compatible = "amlogic,gxbb-aoclkc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
+
+static struct platform_driver gxbb_aoclkc_driver = {
+	.probe		= gxbb_aoclkc_probe,
+	.driver		= {
+		.name	= "gxbb-aoclkc",
+		.of_match_table = gxbb_aoclkc_match_table,
+	},
+};
+
+module_platform_driver(gxbb_aoclkc_driver);
+
+MODULE_DESCRIPTION("AmLogic Meson GXBB AO Clock Controller Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:gxbb-aoclkc");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 02:13:28 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 11:13:28 +0200
Subject: [PATCH 3/3] ARM64: dts: meson-gxbb: Add GXBB AO Clock and Reset node
In-Reply-To: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470734008-18849-4-git-send-email-narmstrong@baylibre.com>

Add the AO clock controller node for the AmLogic GXBB SoC.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..c81e1ab 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -45,6 +45,8 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
 #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
+#include <dt-bindings/clock/gxbb-aoclkc.h>
+#include <dt-bindings/reset/gxbb-aoclkc.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -205,6 +207,13 @@
 				};
 			};
 
+			clkc_AO: clock-controller at 040 {
+				compatible = "amlogic,gxbb-aoclkc";
+				reg = <0x0 0x00040 0x0 0x4>;
+				#clock-cells = <1>;
+				#reset-cells = <1>;
+			};
+
 			uart_AO: serial at 4c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x004c0 0x0 0x14>;
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:14 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:14 +0200
Subject: [RFC PATCH v3 0/8] scpi: Add SCPI registry to handle legacy protocol
Message-ID: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>

This patchset aims to support the legacy SCPI firmware implementation that was
delivered as early technology preview for the JUNO platform.

Finally a stable, maintained and public implementation for the SCPI protocol
has been upstreamed part of the JUNO support and it is the recommended way
of implementing SCP communication on ARMv8 platforms.

The Amlogic GXBB platform is using this legacy protocol, as the RK3368 & RK3399
platforms. Only the GXBB example is provided here, but it's unclear if other
Amlogic ARMv8 based SoCs uses this legacy procotol.

In order to support the legacy protocol :
 - Move the scpi_get_ops to a thin registry layer
 - Change the arm_scpi.c to use the registry layer
 - Add a separate config option to build the registry layer
 - Add the legacy SCPI driver based on the new implementation
 - For example, add the Amlogic GXBB MHU and SCPI DT cpufreq & sensors nodes

Changes since RFC v2 at https://lkml.org/lkml/2016/6/21/324 :
 - Moved MHU to a separate patchset posted at http://lkml.kernel.org/r/1470732737-18391-1-git-send-email-narmstrong at baylibre.com
 - Added a vendor send_message callback into scpi_ops to implement vendor commands
 - Implement EXT commands on arm scpi as vendor send_command
 - Added Rockchip variant mailbox handling

Initial RFC discution tread can be found at https://lkml.org/lkml/2016/5/26/111

@Sudeep: I know you wished I merged the legacy into the arm_scpi, but can you take a look at the vendor extension and how I implemented the rockchip mailbox handling ?

Neil Armstrong (8):
  firmware: Add a SCPI registry to handle multiple implementations
  firmware: scpi: Switch arm_scpi to use new registry
  scpi: Add vendor_send_message to enable access to vendor commands
  firmware: arm_scpi: Enable vendor_send_message as ext commands
  firmware: Add legacy SCPI protocol driver
  dt-bindings: arm: Update arm,scpi bindings with Meson GXBB SCPI
  ARM64: dts: meson-gxbb: Add SRAM node
  ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes

 Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++
 drivers/firmware/Kconfig                           |  24 +
 drivers/firmware/Makefile                          |   2 +
 drivers/firmware/arm_scpi.c                        |  40 +-
 drivers/firmware/legacy_scpi.c                     | 710 +++++++++++++++++++++
 drivers/firmware/scpi.c                            |  94 +++
 include/linux/scpi_protocol.h                      |  20 +-
 8 files changed, 928 insertions(+), 15 deletions(-)
 create mode 100644 drivers/firmware/legacy_scpi.c
 create mode 100644 drivers/firmware/scpi.c

-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:16 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:16 +0200
Subject: [RFC PATCH v3 2/8] firmware: scpi: Switch arm_scpi to use new registry
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470738562-20026-3-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 4388937..c6d6528 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -162,7 +162,6 @@ struct scpi_drvinfo {
 	u32 firmware_version;
 	int num_chans;
 	atomic_t next_chan;
-	struct scpi_ops *scpi_ops;
 	struct scpi_chan *channels;
 	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
 };
@@ -580,12 +579,6 @@ static struct scpi_ops scpi_ops = {
 	.device_set_power_state = scpi_device_set_power_state,
 };
 
-struct scpi_ops *get_scpi_ops(void)
-{
-	return scpi_info ? scpi_info->scpi_ops : NULL;
-}
-EXPORT_SYMBOL_GPL(get_scpi_ops);
-
 static int scpi_init_versions(struct scpi_drvinfo *info)
 {
 	int ret;
@@ -769,7 +762,10 @@ err:
 		  FW_REV_MAJOR(scpi_info->firmware_version),
 		  FW_REV_MINOR(scpi_info->firmware_version),
 		  FW_REV_PATCH(scpi_info->firmware_version));
-	scpi_info->scpi_ops = &scpi_ops;
+
+	ret = devm_scpi_ops_register(dev, &scpi_ops);
+	if (ret)
+		return ret;
 
 	ret = sysfs_create_groups(&dev->kobj, versions_groups);
 	if (ret)
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:15 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:15 +0200
Subject: [RFC PATCH v3 1/8] firmware: Add a SCPI registry to handle multiple
 implementations
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470738562-20026-2-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/Kconfig      |  4 ++
 drivers/firmware/Makefile     |  1 +
 drivers/firmware/scpi.c       | 94 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/scpi_protocol.h | 15 ++++++-
 4 files changed, 113 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/scpi.c

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 0e22f24..ff85511 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -8,9 +8,13 @@ menu "Firmware Drivers"
 config ARM_PSCI_FW
 	bool
 
+config SCPI_FW
+	bool
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on MAILBOX
+	select SCPI_FW
 	help
 	  System Control and Power Interface (SCPI) Message Protocol is
 	  defined for the purpose of communication between the Application
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 44a59dc..968197f 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the linux kernel.
 #
 obj-$(CONFIG_ARM_PSCI_FW)	+= psci.o
+obj-$(CONFIG_SCPI_FW)		+= scpi.o
 obj-$(CONFIG_ARM_SCPI_PROTOCOL)	+= arm_scpi.o
 obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o
 obj-$(CONFIG_DMI)		+= dmi_scan.o
diff --git a/drivers/firmware/scpi.c b/drivers/firmware/scpi.c
new file mode 100644
index 0000000..87a559a
--- /dev/null
+++ b/drivers/firmware/scpi.c
@@ -0,0 +1,94 @@
+/*
+ * System Control and Power Interface (SCPI) Message Protocol registry
+ *
+ * SCPI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Copyright (C) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at 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/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/scpi_protocol.h>
+#include <linux/spinlock.h>
+
+static struct scpi_ops *g_ops;
+
+struct scpi_ops *get_scpi_ops(void)
+{
+	return g_ops;
+}
+EXPORT_SYMBOL_GPL(get_scpi_ops);
+
+int scpi_ops_register(struct scpi_ops *ops)
+{
+	if (!ops)
+		return -EINVAL;
+
+	if (g_ops)
+		return -EEXIST;
+
+	g_ops = ops;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(scpi_ops_register);
+
+void scpi_ops_unregister(struct scpi_ops *ops)
+{
+	if (g_ops == ops)
+		g_ops = NULL;
+}
+EXPORT_SYMBOL_GPL(scpi_ops_unregister);
+
+static void devm_scpi_ops_unregister(struct device *dev, void *res)
+{
+	scpi_ops_unregister(*(struct scpi_ops **)res);
+}
+
+int devm_scpi_ops_register(struct device *dev,
+				struct scpi_ops *ops)
+{
+	struct scpi_ops **rcops;
+	int ret;
+
+	rcops = devres_alloc(devm_scpi_ops_unregister, sizeof(*ops),
+			     GFP_KERNEL);
+	if (!rcops)
+		return -ENOMEM;
+
+	ret = scpi_ops_register(ops);
+	if (!ret) {
+		*rcops = ops;
+		devres_add(dev, rcops);
+	} else
+		devres_free(rcops);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_scpi_ops_register);
diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h
index dc5f989..8e21e3a 100644
--- a/include/linux/scpi_protocol.h
+++ b/include/linux/scpi_protocol.h
@@ -74,8 +74,21 @@ struct scpi_ops {
 	int (*device_set_power_state)(u16, u8);
 };
 
-#if IS_REACHABLE(CONFIG_ARM_SCPI_PROTOCOL)
+#if IS_REACHABLE(CONFIG_SCPI_FW)
 struct scpi_ops *get_scpi_ops(void);
+int scpi_ops_register(struct scpi_ops *drv);
+void scpi_ops_unregister(struct scpi_ops *drv);
+int devm_scpi_ops_register(struct device *dev, struct scpi_ops *drv);
 #else
 static inline struct scpi_ops *get_scpi_ops(void) { return NULL; }
+
+static inline int scpi_ops_register(struct scpi_ops *drv) { return -ENOTSUPP; }
+
+static inline void scpi_ops_unregister(struct scpi_ops *drv) { }
+
+static inline int devm_scpi_ops_register(struct device *dev,
+					 struct scpi_ops *drv)
+{
+	return -ENOTSUPP;
+}
 #endif
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:17 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:17 +0200
Subject: [RFC PATCH v3 3/8] scpi: Add vendor_send_message to enable access to
 vendor commands
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470738562-20026-4-git-send-email-narmstrong@baylibre.com>

Adds an optional vendor_send_message to the scpi to enable sending
vendor platform specific commands to the SCP firmware.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 include/linux/scpi_protocol.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h
index 8e21e3a..dd5d81d 100644
--- a/include/linux/scpi_protocol.h
+++ b/include/linux/scpi_protocol.h
@@ -58,6 +58,8 @@ struct scpi_sensor_info {
  *	OPP is an index to the list return by @dvfs_get_info
  * @dvfs_get_info: returns the DVFS capabilities of the given power
  *	domain. It includes the OPP list and the latency information
+ * @vendor_send_message: vendor specific message sending, arg can specify
+ *	a scpi implementation specific argument
  */
 struct scpi_ops {
 	u32 (*get_version)(void);
@@ -72,6 +74,9 @@ struct scpi_ops {
 	int (*sensor_get_value)(u16, u64 *);
 	int (*device_get_power_state)(u16);
 	int (*device_set_power_state)(u16, u8);
+	int (*vendor_send_message)(u8 cmd, unsigned long arg,
+				   void *tx_buf, unsigned int tx_len,
+				   void *rx_buf, unsigned int rx_len);
 };
 
 #if IS_REACHABLE(CONFIG_SCPI_FW)
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:18 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:18 +0200
Subject: [RFC PATCH v3 4/8] firmware: arm_scpi: Enable vendor_send_message as
 ext commands
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470738562-20026-5-git-send-email-narmstrong@baylibre.com>

Implement official SCPI external commands with the newly introduced
vendor_send_message in ops.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index c6d6528..7290182 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -46,6 +46,8 @@
 
 #define CMD_ID_SHIFT		0
 #define CMD_ID_MASK		0x7f
+#define CMD_SET_SHIFT		7
+#define CMD_SET_MASK		0x1
 #define CMD_TOKEN_ID_SHIFT	8
 #define CMD_TOKEN_ID_MASK	0xff
 #define CMD_DATA_SIZE_SHIFT	16
@@ -53,6 +55,10 @@
 #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
 	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
+#define PACK_EXT_SCPI_CMD(cmd_id, tx_sz)		\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
+	(CMD_SET_MASK << CMD_SET_SHIFT) |		\
+	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
 #define ADD_SCPI_TOKEN(cmd, token)			\
 	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
 
@@ -343,8 +349,8 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
 	mutex_unlock(&ch->xfers_lock);
 }
 
-static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
-			     void *rx_buf, unsigned int rx_len)
+static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+			       void *rx_buf, unsigned int rx_len, bool extn)
 {
 	int ret;
 	u8 chan;
@@ -359,7 +365,8 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 		return -ENOMEM;
 
 	msg->slot = BIT(SCPI_SLOT);
-	msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	msg->cmd = extn ? PACK_EXT_SCPI_CMD(cmd, tx_len) :
+			  PACK_SCPI_CMD(cmd, tx_len);
 	msg->tx_buf = tx_buf;
 	msg->tx_len = tx_len;
 	msg->rx_buf = rx_buf;
@@ -384,6 +391,20 @@ out:
 	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
 }
 
+static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+			     void *rx_buf, unsigned int rx_len)
+{
+	return __scpi_send_message(cmd, tx_buf, tx_len, rx_buf, rx_len, false);
+}
+
+static int scpi_ext_send_message(u8 cmd, unsigned long arg,
+				 void *tx_buf, unsigned int tx_len,
+				 void *rx_buf, unsigned int rx_len)
+{
+	return __scpi_send_message(cmd, tx_buf, tx_len, rx_buf, rx_len, true);
+}
+
+
 static u32 scpi_get_version(void)
 {
 	return scpi_info->protocol_version;
@@ -577,6 +598,7 @@ static struct scpi_ops scpi_ops = {
 	.sensor_get_value = scpi_sensor_get_value,
 	.device_get_power_state = scpi_device_get_power_state,
 	.device_set_power_state = scpi_device_set_power_state,
+	.vendor_send_message = scpi_ext_send_message,
 };
 
 static int scpi_init_versions(struct scpi_drvinfo *info)
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:20 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:20 +0200
Subject: [RFC PATCH v3 6/8] dt-bindings: arm: Update arm,
 scpi bindings with Meson GXBB SCPI
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470738562-20026-7-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
index faa4b44..04bc171 100644
--- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -7,7 +7,7 @@ by Linux to initiate various system control and power operations.
 
 Required properties:
 
-- compatible : should be "arm,scpi"
+- compatible : should be "arm,scpi" or "amlogic,meson-gxbb-scpi"
 - mboxes: List of phandle and mailbox channel specifiers
 	  All the channels reserved by remote SCP firmware for use by
 	  SCPI message protocol should be specified in any order
@@ -60,7 +60,8 @@ A small area of SRAM is reserved for SCPI communication between application
 processors and SCP.
 
 Required properties:
-- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
+- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno,
+		or "amlogic,meson-gxbb-sram" for Amlogic GXBB SoC.
 
 The rest of the properties should follow the generic mmio-sram description
 found in ../../sram/sram.txt
@@ -70,7 +71,8 @@ Each sub-node represents the reserved area for SCPI.
 Required sub-node properties:
 - reg : The base offset and size of the reserved area with the SRAM
 - compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
-	       shared memory on Juno platforms
+	       shared memory on Juno platforms or
+	       "amlogic,meson-gxbb-scp-shmem" for Amlogic GXBB SoC.
 
 Sensor bindings for the sensors based on SCPI Message Protocol
 --------------------------------------------------------------
-- 
2.7.0



From narmstrong at baylibre.com  Tue Aug  9 03:29:19 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue,  9 Aug 2016 12:29:19 +0200
Subject: [RFC PATCH v3 5/8] firmware: Add legacy SCPI protocol driver
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1470738562-20026-6-git-send-email-narmstrong@baylibre.com>

Add legacy protocol driver for an early published SCPI implementation
by supporting old command indexes and structure.
This driver also supports vendor messages and rockchip specific
mailbox data structure for message passing to SCP.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/Kconfig       |  20 ++
 drivers/firmware/Makefile      |   1 +
 drivers/firmware/legacy_scpi.c | 710 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 731 insertions(+)
 create mode 100644 drivers/firmware/legacy_scpi.c

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index ff85511..f6226b7 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,26 @@ config ARM_SCPI_POWER_DOMAIN
 	  This enables support for the SCPI power domains which can be
 	  enabled or disabled via the SCP firmware
 
+config LEGACY_SCPI_PROTOCOL
+	bool "Legacy System Control and Power Interface (SCPI) Message Protocol"
+	default y if ARCH_MESON
+	select SCPI_FW
+	help
+	  System Control and Power Interface (SCPI) Message Protocol is
+	  defined for the purpose of communication between the Application
+	  Cores(AP) and the System Control Processor(SCP). The MHU peripheral
+	  provides a mechanism for inter-processor communication between SCP
+	  and AP.
+
+	  SCP controls most of the power managament on the Application
+	  Processors. It offers control and management of: the core/cluster
+	  power states, various power domain DVFS including the core/cluster,
+	  certain system clocks configuration, thermal sensors and many
+	  others.
+
+	  This protocol library provides interface for all the client drivers
+	  making use of the features offered by the legacy SCP protocol.
+
 config EDD
 	tristate "BIOS Enhanced Disk Drive calls determine boot disk"
 	depends on X86
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 968197f..46ed784 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_ARM_PSCI_FW)	+= psci.o
 obj-$(CONFIG_SCPI_FW)		+= scpi.o
 obj-$(CONFIG_ARM_SCPI_PROTOCOL)	+= arm_scpi.o
 obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o
+obj-$(CONFIG_LEGACY_SCPI_PROTOCOL) += legacy_scpi.o
 obj-$(CONFIG_DMI)		+= dmi_scan.o
 obj-$(CONFIG_DMI_SYSFS)		+= dmi-sysfs.o
 obj-$(CONFIG_EDD)		+= edd.o
diff --git a/drivers/firmware/legacy_scpi.c b/drivers/firmware/legacy_scpi.c
new file mode 100644
index 0000000..e7d7462
--- /dev/null
+++ b/drivers/firmware/legacy_scpi.c
@@ -0,0 +1,710 @@
+/*
+ * Legacy System Control and Power Interface (SCPI) Message Protocol driver
+ *
+ * SCPI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Heavily based on arm_scpi.c from :
+ * Copyright (C) 2015 ARM 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/>.
+ */
+
+/*
+ * DISCLAIMER
+ *
+ * This SCPI implementation is based on a technology preview release
+ * and new ARMv8 SoCs implementations should use the standard SCPI
+ * implementation as defined in the ARM DUI 0922G and implemented
+ * in the arm_scpi.c driver.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitmap.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/printk.h>
+#include <linux/scpi_protocol.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/spinlock.h>
+
+#define CMD_ID_SHIFT		0
+#define CMD_ID_MASK		0x7f
+#define CMD_SENDER_ID_SHIFT	8
+#define CMD_SENDER_ID_MASK	0xff
+#define CMD_DATA_SIZE_SHIFT	20
+#define CMD_DATA_SIZE_MASK	0x1ff
+#define PACK_SCPI_CMD(cmd_id, sender, tx_sz)				\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |			\
+	(((sender) & CMD_SENDER_ID_MASK) << CMD_SENDER_ID_SHIFT) |	\
+	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
+
+#define CMD_SIZE(cmd)	(((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
+#define CMD_UNIQ_MASK	(CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
+#define CMD_XTRACT_UNIQ(cmd)	((cmd) & CMD_UNIQ_MASK)
+
+#define MAX_DVFS_DOMAINS	3
+#define MAX_DVFS_OPPS		16
+#define DVFS_LATENCY(hdr)	(le32_to_cpu(hdr) >> 16)
+#define DVFS_OPP_COUNT(hdr)	((le32_to_cpu(hdr) >> 8) & 0xff)
+
+#define MAX_RX_TIMEOUT          (msecs_to_jiffies(30))
+
+enum legacy_scpi_error_codes {
+	SCPI_SUCCESS = 0, /* Success */
+	SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
+	SCPI_ERR_ALIGN = 2, /* Invalid alignment */
+	SCPI_ERR_SIZE = 3, /* Invalid size */
+	SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
+	SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
+	SCPI_ERR_RANGE = 6, /* Value out of range */
+	SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
+	SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
+	SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
+	SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
+	SCPI_ERR_DEVICE = 11, /* Device error */
+	SCPI_ERR_BUSY = 12, /* Device busy */
+	SCPI_ERR_MAX
+};
+
+enum legacy_scpi_client_id {
+	SCPI_CL_NONE,
+	SCPI_CL_CLOCKS,
+	SCPI_CL_DVFS,
+	SCPI_CL_POWER,
+	SCPI_CL_THERMAL,
+	SCPI_MAX,
+};
+
+enum legacy_scpi_std_cmd {
+	SCPI_CMD_INVALID		= 0x00,
+	SCPI_CMD_SCPI_READY		= 0x01,
+	SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
+	SCPI_CMD_EVENT			= 0x03,
+	SCPI_CMD_SET_CSS_PWR_STATE	= 0x04,
+	SCPI_CMD_GET_CSS_PWR_STATE	= 0x05,
+	SCPI_CMD_CFG_PWR_STATE_STAT	= 0x06,
+	SCPI_CMD_GET_PWR_STATE_STAT	= 0x07,
+	SCPI_CMD_SYS_PWR_STATE		= 0x08,
+	SCPI_CMD_L2_READY		= 0x09,
+	SCPI_CMD_SET_AP_TIMER		= 0x0a,
+	SCPI_CMD_CANCEL_AP_TIME		= 0x0b,
+	SCPI_CMD_DVFS_CAPABILITIES	= 0x0c,
+	SCPI_CMD_GET_DVFS_INFO		= 0x0d,
+	SCPI_CMD_SET_DVFS		= 0x0e,
+	SCPI_CMD_GET_DVFS		= 0x0f,
+	SCPI_CMD_GET_DVFS_STAT		= 0x10,
+	SCPI_CMD_SET_RTC		= 0x11,
+	SCPI_CMD_GET_RTC		= 0x12,
+	SCPI_CMD_CLOCK_CAPABILITIES	= 0x13,
+	SCPI_CMD_SET_CLOCK_INDEX	= 0x14,
+	SCPI_CMD_SET_CLOCK_VALUE	= 0x15,
+	SCPI_CMD_GET_CLOCK_VALUE	= 0x16,
+	SCPI_CMD_PSU_CAPABILITIES	= 0x17,
+	SCPI_CMD_SET_PSU		= 0x18,
+	SCPI_CMD_GET_PSU		= 0x19,
+	SCPI_CMD_SENSOR_CAPABILITIES	= 0x1a,
+	SCPI_CMD_SENSOR_INFO		= 0x1b,
+	SCPI_CMD_SENSOR_VALUE		= 0x1c,
+	SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x1d,
+	SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x1e,
+	SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1f,
+	SCPI_CMD_COUNT
+};
+
+struct legacy_scpi_xfer {
+	u32 cmd;
+	u32 status;
+	const void *tx_buf;
+	void *rx_buf;
+	unsigned int tx_len;
+	unsigned int rx_len;
+	struct completion done;
+	void *vendor_msg;
+};
+
+struct legacy_scpi_chan {
+	struct mbox_client cl;
+	struct mbox_chan *chan;
+	void __iomem *tx_payload;
+	void __iomem *rx_payload;
+	struct mutex xfers_lock;
+	struct legacy_scpi_xfer t;
+	void *vendor_data;
+};
+
+struct legacy_scpi_ops {
+	int (*init)(struct device *dev, struct legacy_scpi_chan *chan);
+	int (*prepare)(struct legacy_scpi_chan *chan, unsigned long arg);
+};
+
+struct legacy_scpi_drvinfo {
+	int num_chans;
+	struct legacy_scpi_chan *channels;
+	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
+	const struct legacy_scpi_ops *ops;
+};
+
+/*
+ * The SCP firmware only executes in little-endian mode, so any buffers
+ * shared through SCPI should have their contents converted to little-endian
+ */
+struct legacy_scpi_shared_mem {
+	__le32 status;
+	u8 payload[0];
+} __packed;
+
+struct scp_capabilities {
+	__le32 protocol_version;
+	__le32 event_version;
+	__le32 platform_version;
+	__le32 commands[4];
+} __packed;
+
+struct clk_get_info {
+	__le16 id;
+	__le16 flags;
+	__le32 min_rate;
+	__le32 max_rate;
+	u8 name[20];
+} __packed;
+
+struct clk_get_value {
+	__le32 rate;
+} __packed;
+
+struct clk_set_value {
+	__le32 rate;
+	__le16 id;
+	__le16 reserved;
+} __packed;
+
+struct dvfs_info {
+	__le32 header;
+	struct {
+		__le32 freq;
+		__le32 m_volt;
+	} opps[MAX_DVFS_OPPS];
+} __packed;
+
+struct dvfs_get {
+	u8 index;
+} __packed;
+
+struct dvfs_set {
+	u8 domain;
+	u8 index;
+} __packed;
+
+struct sensor_capabilities {
+	__le16 sensors;
+} __packed;
+
+struct sensor_info {
+	__le16 sensor_id;
+	u8 class;
+	u8 trigger_type;
+	char name[20];
+};
+
+struct sensor_value {
+	__le32 val;
+} __packed;
+
+static struct legacy_scpi_drvinfo *legacy_scpi_info;
+
+static int legacy_scpi_linux_errmap[SCPI_ERR_MAX] = {
+	/* better than switch case as long as return value is continuous */
+	0, /* SCPI_SUCCESS */
+	-EINVAL, /* SCPI_ERR_PARAM */
+	-ENOEXEC, /* SCPI_ERR_ALIGN */
+	-EMSGSIZE, /* SCPI_ERR_SIZE */
+	-EINVAL, /* SCPI_ERR_HANDLER */
+	-EACCES, /* SCPI_ERR_ACCESS */
+	-ERANGE, /* SCPI_ERR_RANGE */
+	-ETIMEDOUT, /* SCPI_ERR_TIMEOUT */
+	-ENOMEM, /* SCPI_ERR_NOMEM */
+	-EINVAL, /* SCPI_ERR_PWRSTATE */
+	-EOPNOTSUPP, /* SCPI_ERR_SUPPORT */
+	-EIO, /* SCPI_ERR_DEVICE */
+	-EBUSY, /* SCPI_ERR_BUSY */
+};
+
+static inline int legacy_scpi_to_linux_errno(int errno)
+{
+	if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
+		return legacy_scpi_linux_errmap[errno];
+	return -EIO;
+}
+
+static void legacy_scpi_handle_remote_msg(struct mbox_client *c, void *msg)
+{
+	struct legacy_scpi_chan *ch =
+		container_of(c, struct legacy_scpi_chan, cl);
+	struct legacy_scpi_shared_mem *mem = ch->rx_payload;
+	unsigned int len;
+
+	len = ch->t.rx_len;
+
+	ch->t.status = le32_to_cpu(mem->status);
+	if (len)
+		memcpy_fromio(ch->t.rx_buf, mem->payload, len);
+
+	complete(&ch->t.done);
+}
+
+static void legacy_scpi_tx_prepare(struct mbox_client *c, void *msg)
+{
+	struct legacy_scpi_chan *ch =
+		container_of(c, struct legacy_scpi_chan, cl);
+
+	if (ch->t.tx_buf && ch->t.tx_len)
+		memcpy_toio(ch->tx_payload, ch->t.tx_buf, ch->t.tx_len);
+}
+
+static int high_priority_cmds[] = {
+	SCPI_CMD_GET_CSS_PWR_STATE,
+	SCPI_CMD_CFG_PWR_STATE_STAT,
+	SCPI_CMD_GET_PWR_STATE_STAT,
+	SCPI_CMD_SET_DVFS,
+	SCPI_CMD_GET_DVFS,
+	SCPI_CMD_SET_RTC,
+	SCPI_CMD_GET_RTC,
+	SCPI_CMD_SET_CLOCK_INDEX,
+	SCPI_CMD_SET_CLOCK_VALUE,
+	SCPI_CMD_GET_CLOCK_VALUE,
+	SCPI_CMD_SET_PSU,
+	SCPI_CMD_GET_PSU,
+	SCPI_CMD_SENSOR_CFG_PERIODIC,
+	SCPI_CMD_SENSOR_CFG_BOUNDS,
+};
+
+static int legacy_scpi_get_chan(u8 cmd)
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(high_priority_cmds); idx++)
+		if (cmd == high_priority_cmds[idx])
+			return 1;
+
+	return 0;
+}
+
+/* Rockchip SoCs needs a special structure as a message */
+
+struct rockchip_scpi_xfer {
+	u32 cmd;
+	int rx_size;
+};
+
+static int rockchip_init(struct device *dev, struct legacy_scpi_chan *chan)
+{
+	chan->vendor_data = devm_kmalloc(dev,
+					 sizeof(struct rockchip_scpi_xfer),
+					 GFP_KERNEL);
+	if (!chan->vendor_data)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int rockchip_prepare(struct legacy_scpi_chan *chan,
+				    unsigned long arg)
+{
+	struct legacy_scpi_xfer *msg = &chan->t;
+	struct rockchip_scpi_xfer *xfer = chan->vendor_data;
+
+	xfer->cmd = msg->cmd;
+	xfer->rx_size = msg->rx_len;
+
+	msg->vendor_msg = xfer;
+
+	return 0;
+}
+
+static int legacy_scpi_send_message(u8 cmd, unsigned long arg,
+				void *tx_buf, unsigned int tx_len,
+				void *rx_buf, unsigned int rx_len)
+{
+	int ret;
+	u8 chan;
+	struct legacy_scpi_xfer *msg;
+	struct legacy_scpi_chan *legacy_scpi_chan;
+
+	chan = legacy_scpi_get_chan(cmd);
+	legacy_scpi_chan = legacy_scpi_info->channels + chan;
+
+	msg = &legacy_scpi_chan->t;
+
+	mutex_lock(&legacy_scpi_chan->xfers_lock);
+
+	msg->cmd = PACK_SCPI_CMD(cmd, arg, tx_len);
+	msg->tx_buf = tx_buf;
+	msg->tx_len = tx_len;
+	msg->rx_buf = rx_buf;
+	msg->rx_len = rx_len;
+	init_completion(&msg->done);
+
+	/* Call the prepare hook to eventually set the vendor_msg */
+	if (legacy_scpi_info->ops &&
+	    legacy_scpi_info->ops->prepare) {
+		ret = legacy_scpi_info->ops->prepare(legacy_scpi_chan, arg);
+		if (ret) {
+			mutex_unlock(&legacy_scpi_chan->xfers_lock);
+			return ret;
+		}
+	} else
+		msg->vendor_msg = &msg->cmd;
+
+	ret = mbox_send_message(legacy_scpi_chan->chan, msg->vendor_msg);
+	if (ret < 0)
+		goto out;
+
+	if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
+		ret = -ETIMEDOUT;
+	else
+		/* first status word */
+		ret = msg->status;
+out:
+	mutex_unlock(&legacy_scpi_chan->xfers_lock);
+
+	/* SCPI error codes > 0, translate them to Linux scale*/
+	return ret > 0 ? legacy_scpi_to_linux_errno(ret) : ret;
+}
+
+static u32 legacy_scpi_get_version(void)
+{
+	return 1; /* v0.1 */
+}
+
+static unsigned long legacy_scpi_clk_get_val(u16 clk_id)
+{
+	int ret;
+	struct clk_get_value clk;
+	__le16 le_clk_id = cpu_to_le16(clk_id);
+
+	ret = legacy_scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE,
+				SCPI_CL_CLOCKS,
+				&le_clk_id, sizeof(le_clk_id),
+				&clk, sizeof(clk));
+
+	return ret ? ret : le32_to_cpu(clk.rate);
+}
+
+static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+	int stat;
+	struct clk_set_value clk = {
+		.id = cpu_to_le16(clk_id),
+		.rate = cpu_to_le32(rate)
+	};
+
+	return legacy_scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE,
+				SCPI_CL_CLOCKS,
+				&clk, sizeof(clk),
+				&stat, sizeof(stat));
+}
+
+static int legacy_scpi_dvfs_get_idx(u8 domain)
+{
+	int ret;
+	struct dvfs_get dvfs;
+
+	ret = legacy_scpi_send_message(SCPI_CMD_GET_DVFS, SCPI_CL_DVFS,
+				&domain, sizeof(domain),
+				&dvfs, sizeof(dvfs));
+
+	return ret ? ret : dvfs.index;
+}
+
+static int legacy_scpi_dvfs_set_idx(u8 domain, u8 index)
+{
+	int stat;
+	struct dvfs_set dvfs = {domain, index};
+
+	return legacy_scpi_send_message(SCPI_CMD_SET_DVFS, SCPI_CL_DVFS,
+				&dvfs, sizeof(dvfs),
+				&stat, sizeof(stat));
+}
+
+static struct scpi_dvfs_info *legacy_scpi_dvfs_get_info(u8 domain)
+{
+	struct scpi_dvfs_info *info;
+	struct scpi_opp *opp;
+	struct dvfs_info buf;
+	int ret, i;
+
+	if (domain >= MAX_DVFS_DOMAINS)
+		return ERR_PTR(-EINVAL);
+
+	if (legacy_scpi_info->dvfs[domain])	/* data already populated */
+		return legacy_scpi_info->dvfs[domain];
+
+	ret = legacy_scpi_send_message(SCPI_CMD_GET_DVFS_INFO, SCPI_CL_DVFS,
+				&domain, sizeof(domain),
+				&buf, sizeof(buf));
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return ERR_PTR(-ENOMEM);
+
+	info->count = DVFS_OPP_COUNT(buf.header);
+	info->latency = DVFS_LATENCY(buf.header) * 1000; /* uS to nS */
+
+	info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL);
+	if (!info->opps) {
+		kfree(info);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0, opp = info->opps; i < info->count; i++, opp++) {
+		opp->freq = le32_to_cpu(buf.opps[i].freq);
+		opp->m_volt = le32_to_cpu(buf.opps[i].m_volt);
+	}
+
+	legacy_scpi_info->dvfs[domain] = info;
+	return info;
+}
+
+static int legacy_scpi_sensor_get_capability(u16 *sensors)
+{
+	struct sensor_capabilities cap_buf;
+	int ret;
+
+	ret = legacy_scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES,
+				SCPI_CL_THERMAL, NULL, 0, &cap_buf,
+				sizeof(cap_buf));
+	if (!ret)
+		*sensors = le16_to_cpu(cap_buf.sensors);
+
+	return ret;
+}
+
+static int legacy_scpi_sensor_get_info(u16 sensor_id,
+				     struct scpi_sensor_info *info)
+{
+	__le16 id = cpu_to_le16(sensor_id);
+	struct sensor_info _info;
+	int ret;
+
+	ret = legacy_scpi_send_message(SCPI_CMD_SENSOR_INFO, SCPI_CL_THERMAL,
+				&id, sizeof(id),
+				&_info, sizeof(_info));
+	if (!ret) {
+		memcpy(info, &_info, sizeof(*info));
+		info->sensor_id = le16_to_cpu(_info.sensor_id);
+	}
+
+	return ret;
+}
+
+static int legacy_scpi_sensor_get_value(u16 sensor, u64 *val)
+{
+	__le16 id = cpu_to_le16(sensor);
+	struct sensor_value buf;
+	int ret;
+
+	ret = legacy_scpi_send_message(SCPI_CMD_SENSOR_VALUE, SCPI_CL_THERMAL,
+				&id, sizeof(id),
+				&buf, sizeof(buf));
+	if (!ret)
+		*val = (u64)le32_to_cpu(buf.val);
+
+	return ret;
+}
+
+static struct scpi_ops legacy_scpi_ops = {
+	.get_version = legacy_scpi_get_version,
+	.clk_get_val = legacy_scpi_clk_get_val,
+	.clk_set_val = legacy_scpi_clk_set_val,
+	.dvfs_get_idx = legacy_scpi_dvfs_get_idx,
+	.dvfs_set_idx = legacy_scpi_dvfs_set_idx,
+	.dvfs_get_info = legacy_scpi_dvfs_get_info,
+	.sensor_get_capability = legacy_scpi_sensor_get_capability,
+	.sensor_get_info = legacy_scpi_sensor_get_info,
+	.sensor_get_value = legacy_scpi_sensor_get_value,
+	.vendor_send_message = legacy_scpi_send_message,
+};
+
+static void legacy_scpi_free_channels(struct device *dev,
+				struct legacy_scpi_chan *pchan, int count)
+{
+	int i;
+
+	for (i = 0; i < count && pchan->chan; i++, pchan++)
+		mbox_free_channel(pchan->chan);
+}
+
+static int legacy_scpi_remove(struct platform_device *pdev)
+{
+	int i;
+	struct device *dev = &pdev->dev;
+	struct legacy_scpi_drvinfo *info = platform_get_drvdata(pdev);
+
+	/* stop exporting SCPI ops */
+	legacy_scpi_info = NULL;
+
+	of_platform_depopulate(dev);
+	legacy_scpi_free_channels(dev, info->channels, info->num_chans);
+	platform_set_drvdata(pdev, NULL);
+
+	for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) {
+		kfree(info->dvfs[i]->opps);
+		kfree(info->dvfs[i]);
+	}
+
+	return 0;
+}
+
+static const struct legacy_scpi_ops scpi_rockchip_ops = {
+	.init = rockchip_init,
+	.prepare = rockchip_prepare,
+};
+
+static const struct of_device_id legacy_scpi_of_match[] = {
+	{.compatible = "amlogic,meson-gxbb-scpi"},
+	{.compatible = "rockchip,rk3368-scpi", .data = &scpi_rockchip_ops},
+	{.compatible = "rockchip,rk3399-scpi", .data = &scpi_rockchip_ops},
+	{ /* sentinel */ },
+};
+
+static int legacy_scpi_probe(struct platform_device *pdev)
+{
+	int count, idx, ret;
+	struct resource res;
+	struct legacy_scpi_chan *legacy_scpi_chan;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct of_device_id *match;
+	const struct legacy_scpi_ops *ops;
+
+	match = of_match_device(legacy_scpi_of_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	ops = match->data;
+
+	legacy_scpi_info = devm_kzalloc(dev, sizeof(*legacy_scpi_info),
+					GFP_KERNEL);
+	if (!legacy_scpi_info)
+		return -ENOMEM;
+
+	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+	if (count < 0) {
+		dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
+		return -ENODEV;
+	}
+
+	legacy_scpi_chan = devm_kcalloc(dev, count,
+				sizeof(*legacy_scpi_chan), GFP_KERNEL);
+	if (!legacy_scpi_chan)
+		return -ENOMEM;
+
+	for (idx = 0; idx < count; idx++) {
+		resource_size_t size;
+		struct legacy_scpi_chan *pchan = legacy_scpi_chan + idx;
+		struct mbox_client *cl = &pchan->cl;
+		struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
+
+		if (of_address_to_resource(shmem, 0, &res)) {
+			dev_err(dev, "failed to get SCPI payload mem resource\n");
+			ret = -EINVAL;
+			goto err;
+		}
+
+		size = resource_size(&res);
+
+		pchan->rx_payload = devm_ioremap(dev, res.start, size);
+		if (!pchan->rx_payload) {
+			dev_err(dev, "failed to ioremap SCPI payload\n");
+			ret = -EADDRNOTAVAIL;
+			goto err;
+		}
+		pchan->tx_payload = pchan->rx_payload + (size >> 1);
+
+		if (ops && ops->init) {
+			ret = ops->init(dev, pchan);
+			if (ret)
+				goto err;
+		}
+
+		cl->dev = dev;
+		cl->rx_callback = legacy_scpi_handle_remote_msg;
+		cl->tx_prepare = legacy_scpi_tx_prepare;
+		cl->tx_block = true;
+		cl->tx_tout = 20;
+		cl->knows_txdone = false; /* controller can't ack */
+
+		mutex_init(&pchan->xfers_lock);
+
+		pchan->chan = mbox_request_channel(cl, idx);
+		if (!IS_ERR(pchan->chan))
+			continue;
+		else
+			ret = PTR_ERR(pchan->chan);
+err:
+		legacy_scpi_free_channels(dev, legacy_scpi_chan, idx);
+		legacy_scpi_info = NULL;
+		return ret;
+	}
+
+	legacy_scpi_info->ops = ops;
+	legacy_scpi_info->channels = legacy_scpi_chan;
+	legacy_scpi_info->num_chans = count;
+	platform_set_drvdata(pdev, legacy_scpi_info);
+
+	ret = devm_scpi_ops_register(dev, &legacy_scpi_ops);
+	if (ret)
+		return ret;
+
+	return of_platform_populate(dev->of_node, NULL, NULL, dev);
+}
+
+MODULE_DEVICE_TABLE(of, legacy_scpi_of_match);
+
+static struct platform_driver legacy_scpi_driver = {
+	.driver = {
+		.name = "legacy-scpi",
+		.of_match_table = legacy_scpi_of_match,
+	},
+	.probe = legacy_scpi_probe,
+	.remove = legacy_scpi_remove,
+};
+module_platform_driver(legacy_scpi_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla at arm.com>");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_DESCRIPTION("ARM Legacy SCPI mailbox protocol driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.0



From wsa-dev at sang-engineering.com  Tue Aug  9 04:36:16 2016
From: wsa-dev at sang-engineering.com (Wolfram Sang)
Date: Tue,  9 Aug 2016 13:36:16 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
Message-ID: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>

Since v4.8-rc1, the I2C core will print detailed information when adding an I2C
adapter fails. So, drivers can skip this now.

I am still undecided if I apply this as a single patch or break it out. But for
reviewing, avoiding the patch bomb is probably a good thing.

Should go via subsystem tree, I'd think.

Wolfram Sang (1):
  i2c: don't print error when adding adapter fails

 drivers/i2c/busses/i2c-amd756.c         | 5 +----
 drivers/i2c/busses/i2c-at91.c           | 2 --
 drivers/i2c/busses/i2c-axxia.c          | 8 +-------
 drivers/i2c/busses/i2c-bcm-iproc.c      | 8 +-------
 drivers/i2c/busses/i2c-bcm-kona.c       | 4 +---
 drivers/i2c/busses/i2c-bfin-twi.c       | 4 +---
 drivers/i2c/busses/i2c-brcmstb.c        | 4 +---
 drivers/i2c/busses/i2c-cadence.c        | 4 +---
 drivers/i2c/busses/i2c-cpm.c            | 4 +---
 drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +---
 drivers/i2c/busses/i2c-davinci.c        | 4 +---
 drivers/i2c/busses/i2c-diolan-u2c.c     | 4 +---
 drivers/i2c/busses/i2c-dln2.c           | 4 +---
 drivers/i2c/busses/i2c-efm32.c          | 1 -
 drivers/i2c/busses/i2c-exynos5.c        | 4 +---
 drivers/i2c/busses/i2c-hix5hd2.c        | 4 +---
 drivers/i2c/busses/i2c-i801.c           | 1 -
 drivers/i2c/busses/i2c-ibm_iic.c        | 4 +---
 drivers/i2c/busses/i2c-img-scb.c        | 4 +---
 drivers/i2c/busses/i2c-imx.c            | 4 +---
 drivers/i2c/busses/i2c-isch.c           | 4 +---
 drivers/i2c/busses/i2c-ismt.c           | 4 +---
 drivers/i2c/busses/i2c-jz4780.c         | 4 +---
 drivers/i2c/busses/i2c-lpc2k.c          | 4 +---
 drivers/i2c/busses/i2c-meson.c          | 1 -
 drivers/i2c/busses/i2c-mpc.c            | 4 +---
 drivers/i2c/busses/i2c-mt65xx.c         | 4 +---
 drivers/i2c/busses/i2c-mxs.c            | 1 -
 drivers/i2c/busses/i2c-nforce2.c        | 1 -
 drivers/i2c/busses/i2c-nomadik.c        | 4 +---
 drivers/i2c/busses/i2c-ocores.c         | 4 +---
 drivers/i2c/busses/i2c-octeon.c         | 4 +---
 drivers/i2c/busses/i2c-omap.c           | 4 +---
 drivers/i2c/busses/i2c-piix4.c          | 1 -
 drivers/i2c/busses/i2c-pmcmsp.c         | 4 +---
 drivers/i2c/busses/i2c-pnx.c            | 4 +---
 drivers/i2c/busses/i2c-puv3.c           | 5 +----
 drivers/i2c/busses/i2c-pxa.c            | 4 +---
 drivers/i2c/busses/i2c-rcar.c           | 4 +---
 drivers/i2c/busses/i2c-riic.c           | 4 +---
 drivers/i2c/busses/i2c-rk3x.c           | 4 +---
 drivers/i2c/busses/i2c-s3c2410.c        | 1 -
 drivers/i2c/busses/i2c-sh7760.c         | 4 +---
 drivers/i2c/busses/i2c-sh_mobile.c      | 1 -
 drivers/i2c/busses/i2c-sirf.c           | 4 +---
 drivers/i2c/busses/i2c-st.c             | 4 +---
 drivers/i2c/busses/i2c-stu300.c         | 5 +----
 drivers/i2c/busses/i2c-tegra.c          | 4 +---
 drivers/i2c/busses/i2c-uniphier-f.c     | 7 +------
 drivers/i2c/busses/i2c-uniphier.c       | 7 +------
 drivers/i2c/busses/i2c-wmt.c            | 4 +---
 drivers/i2c/busses/i2c-xgene-slimpro.c  | 1 -
 drivers/i2c/busses/i2c-xiic.c           | 1 -
 drivers/i2c/busses/i2c-xlp9xx.c         | 4 +---
 drivers/i2c/busses/i2c-xlr.c            | 4 +---
 55 files changed, 44 insertions(+), 161 deletions(-)

-- 
2.8.1



From wsa-dev at sang-engineering.com  Tue Aug  9 04:36:17 2016
From: wsa-dev at sang-engineering.com (Wolfram Sang)
Date: Tue,  9 Aug 2016 13:36:17 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>

The core will do this for us now.

Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
---
 drivers/i2c/busses/i2c-amd756.c         | 5 +----
 drivers/i2c/busses/i2c-at91.c           | 2 --
 drivers/i2c/busses/i2c-axxia.c          | 8 +-------
 drivers/i2c/busses/i2c-bcm-iproc.c      | 8 +-------
 drivers/i2c/busses/i2c-bcm-kona.c       | 4 +---
 drivers/i2c/busses/i2c-bfin-twi.c       | 4 +---
 drivers/i2c/busses/i2c-brcmstb.c        | 4 +---
 drivers/i2c/busses/i2c-cadence.c        | 4 +---
 drivers/i2c/busses/i2c-cpm.c            | 4 +---
 drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +---
 drivers/i2c/busses/i2c-davinci.c        | 4 +---
 drivers/i2c/busses/i2c-diolan-u2c.c     | 4 +---
 drivers/i2c/busses/i2c-dln2.c           | 4 +---
 drivers/i2c/busses/i2c-efm32.c          | 1 -
 drivers/i2c/busses/i2c-exynos5.c        | 4 +---
 drivers/i2c/busses/i2c-hix5hd2.c        | 4 +---
 drivers/i2c/busses/i2c-i801.c           | 1 -
 drivers/i2c/busses/i2c-ibm_iic.c        | 4 +---
 drivers/i2c/busses/i2c-img-scb.c        | 4 +---
 drivers/i2c/busses/i2c-imx.c            | 4 +---
 drivers/i2c/busses/i2c-isch.c           | 4 +---
 drivers/i2c/busses/i2c-ismt.c           | 4 +---
 drivers/i2c/busses/i2c-jz4780.c         | 4 +---
 drivers/i2c/busses/i2c-lpc2k.c          | 4 +---
 drivers/i2c/busses/i2c-meson.c          | 1 -
 drivers/i2c/busses/i2c-mpc.c            | 4 +---
 drivers/i2c/busses/i2c-mt65xx.c         | 4 +---
 drivers/i2c/busses/i2c-mxs.c            | 1 -
 drivers/i2c/busses/i2c-nforce2.c        | 1 -
 drivers/i2c/busses/i2c-nomadik.c        | 4 +---
 drivers/i2c/busses/i2c-ocores.c         | 4 +---
 drivers/i2c/busses/i2c-octeon.c         | 4 +---
 drivers/i2c/busses/i2c-omap.c           | 4 +---
 drivers/i2c/busses/i2c-piix4.c          | 1 -
 drivers/i2c/busses/i2c-pmcmsp.c         | 4 +---
 drivers/i2c/busses/i2c-pnx.c            | 4 +---
 drivers/i2c/busses/i2c-puv3.c           | 5 +----
 drivers/i2c/busses/i2c-pxa.c            | 4 +---
 drivers/i2c/busses/i2c-rcar.c           | 4 +---
 drivers/i2c/busses/i2c-riic.c           | 4 +---
 drivers/i2c/busses/i2c-rk3x.c           | 4 +---
 drivers/i2c/busses/i2c-s3c2410.c        | 1 -
 drivers/i2c/busses/i2c-sh7760.c         | 4 +---
 drivers/i2c/busses/i2c-sh_mobile.c      | 1 -
 drivers/i2c/busses/i2c-sirf.c           | 4 +---
 drivers/i2c/busses/i2c-st.c             | 4 +---
 drivers/i2c/busses/i2c-stu300.c         | 5 +----
 drivers/i2c/busses/i2c-tegra.c          | 4 +---
 drivers/i2c/busses/i2c-uniphier-f.c     | 7 +------
 drivers/i2c/busses/i2c-uniphier.c       | 7 +------
 drivers/i2c/busses/i2c-wmt.c            | 4 +---
 drivers/i2c/busses/i2c-xgene-slimpro.c  | 1 -
 drivers/i2c/busses/i2c-xiic.c           | 1 -
 drivers/i2c/busses/i2c-xlp9xx.c         | 4 +---
 drivers/i2c/busses/i2c-xlr.c            | 4 +---
 55 files changed, 44 insertions(+), 161 deletions(-)

diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 6c7113d990f882..274908cd1fdeab 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -378,11 +378,8 @@ static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		 amd756_ioport);
 
 	error = i2c_add_adapter(&amd756_smbus);
-	if (error) {
-		dev_err(&pdev->dev,
-			"Adapter registration failed, module not inserted\n");
+	if (error)
 		goto out_err;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index f23372669f770f..03a519d29616d7 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -1118,8 +1118,6 @@ static int at91_twi_probe(struct platform_device *pdev)
 
 	rc = i2c_add_numbered_adapter(&dev->adapter);
 	if (rc) {
-		dev_err(dev->dev, "Adapter %s registration failed\n",
-			dev->adapter.name);
 		clk_disable_unprepare(dev->clk);
 
 		pm_runtime_disable(dev->dev);
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index c335cc7852f94e..d3bcaf4ab095d0 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -558,13 +558,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, idev);
 
-	ret = i2c_add_adapter(&idev->adapter);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add adapter\n");
-		return ret;
-	}
-
-	return 0;
+	return i2c_add_adapter(&idev->adapter);
 }
 
 static int axxia_i2c_remove(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index 19c843828fe2ca..8e3477f9297eda 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
 	adap->dev.parent = &pdev->dev;
 	adap->dev.of_node = pdev->dev.of_node;
 
-	ret = i2c_add_adapter(adap);
-	if (ret) {
-		dev_err(iproc_i2c->device, "failed to add adapter\n");
-		return ret;
-	}
-
-	return 0;
+	return i2c_add_adapter(adap);
 }
 
 static int bcm_iproc_i2c_remove(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
index ac9f47679c3a4b..a5c9098507896b 100644
--- a/drivers/i2c/busses/i2c-bcm-kona.c
+++ b/drivers/i2c/busses/i2c-bcm-kona.c
@@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev)
 	adap->dev.of_node = pdev->dev.of_node;
 
 	rc = i2c_add_adapter(adap);
-	if (rc) {
-		dev_err(dev->device, "failed to add adapter\n");
+	if (rc)
 		return rc;
-	}
 
 	dev_info(dev->device, "device registered successfully\n");
 
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 025686d4164058..29d00c4f7824c2 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -685,10 +685,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
 	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
 
 	rc = i2c_add_numbered_adapter(p_adap);
-	if (rc < 0) {
-		dev_err(&pdev->dev, "Can't add i2c adapter!\n");
+	if (rc < 0)
 		goto out_error;
-	}
 
 	platform_set_drvdata(pdev, iface);
 
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 3f5a4d71d3bf32..bc5c176e984aea 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -648,10 +648,8 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
 	adap->dev.parent = &pdev->dev;
 	adap->dev.of_node = pdev->dev.of_node;
 	rc = i2c_add_adapter(adap);
-	if (rc) {
-		dev_err(dev->device, "failed to add adapter\n");
+	if (rc)
 		goto probe_errorout;
-	}
 
 	dev_info(dev->device, "%s@%dhz registered in %s mode\n",
 		 int_name ? int_name : " ", dev->clk_freq_hz,
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 90bbd9f9dd8f77..1cc1e79e958d56 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -963,10 +963,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
 	}
 
 	ret = i2c_add_adapter(&id->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
+	if (ret < 0)
 		goto err_clk_dis;
-	}
 
 	/*
 	 * Cadence I2C controller has a bug wherein it generates
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index ee57c1e865e271..d89bde2c5da256 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -665,10 +665,8 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
 	cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
 	result = i2c_add_numbered_adapter(&cpm->adap);
 
-	if (result < 0) {
-		dev_err(&ofdev->dev, "Unable to register with I2C\n");
+	if (result < 0)
 		goto out_shut;
-	}
 
 	dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
 		cpm->adap.name);
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index a0d95ff682ae12..cf334a9ec22cb7 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -281,10 +281,8 @@ static int ec_i2c_probe(struct platform_device *pdev)
 	bus->adap.retries = I2C_MAX_RETRIES;
 
 	err = i2c_add_adapter(&bus->adap);
-	if (err) {
-		dev_err(dev, "cannot register i2c adapter\n");
+	if (err)
 		return err;
-	}
 	platform_set_drvdata(pdev, bus);
 
 	return err;
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index a8bdcb5292f5b3..9e7ef5cf5d495d 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -846,10 +846,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 
 	adap->nr = pdev->id;
 	r = i2c_add_numbered_adapter(adap);
-	if (r) {
-		dev_err(&pdev->dev, "failure adding adapter\n");
+	if (r)
 		goto err_unuse_clocks;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c
index b19a310bf9b3e8..f718ee4e3332fe 100644
--- a/drivers/i2c/busses/i2c-diolan-u2c.c
+++ b/drivers/i2c/busses/i2c-diolan-u2c.c
@@ -487,10 +487,8 @@ static int diolan_u2c_probe(struct usb_interface *interface,
 
 	/* and finally attach to i2c layer */
 	ret = i2c_add_adapter(&dev->adapter);
-	if (ret < 0) {
-		dev_err(&interface->dev, "failed to add I2C adapter\n");
+	if (ret < 0)
 		goto error_free;
-	}
 
 	dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
 
diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c
index f2eb4f76591fbe..8acda2aa15583c 100644
--- a/drivers/i2c/busses/i2c-dln2.c
+++ b/drivers/i2c/busses/i2c-dln2.c
@@ -228,10 +228,8 @@ static int dln2_i2c_probe(struct platform_device *pdev)
 
 	/* and finally attach to i2c layer */
 	ret = i2c_add_adapter(&dln2->adapter);
-	if (ret < 0) {
-		dev_err(dev, "failed to add I2C adapter: %d\n", ret);
+	if (ret < 0)
 		goto out_disable;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
index e253598d764c0d..aa336ba89aa3fe 100644
--- a/drivers/i2c/busses/i2c-efm32.c
+++ b/drivers/i2c/busses/i2c-efm32.c
@@ -438,7 +438,6 @@ static int efm32_i2c_probe(struct platform_device *pdev)
 
 	ret = i2c_add_adapter(&ddata->adapter);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret);
 		free_irq(ddata->irq, ddata);
 
 err_disable_clk:
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index c0e3ada028763d..bea607149972d4 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -796,10 +796,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
 	exynos5_i2c_reset(i2c);
 
 	ret = i2c_add_adapter(&i2c->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+	if (ret < 0)
 		goto err_clk;
-	}
 
 	platform_set_drvdata(pdev, i2c);
 
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index 7c6966434ee7b9..ae7f3180f7e887 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -478,10 +478,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
 	pm_runtime_enable(priv->dev);
 
 	ret = i2c_add_adapter(&priv->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+	if (ret < 0)
 		goto err_runtime;
-	}
 
 	return ret;
 
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 5ef9b733d153fa..22a0ed4de80da0 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -1613,7 +1613,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		"SMBus I801 adapter at %04lx", priv->smba);
 	err = i2c_add_adapter(&priv->adapter);
 	if (err) {
-		dev_err(&dev->dev, "Failed to add SMBus adapter\n");
 		i801_acpi_remove(priv);
 		return err;
 	}
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index cdaa7be2cd1b94..412b91d255ad1d 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -751,10 +751,8 @@ static int iic_probe(struct platform_device *ofdev)
 	adap->timeout = HZ;
 
 	ret = i2c_add_adapter(adap);
-	if (ret  < 0) {
-		dev_err(&ofdev->dev, "failed to register i2c adapter\n");
+	if (ret  < 0)
 		goto error_cleanup;
-	}
 
 	dev_info(&ofdev->dev, "using %s mode\n",
 		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index ea20425b697217..db8e8b40569d98 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -1394,10 +1394,8 @@ static int img_i2c_probe(struct platform_device *pdev)
 		goto disable_clk;
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to add adapter\n");
+	if (ret < 0)
 		goto disable_clk;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 1844bc9f7cd5a2..cb11eee9567318 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1129,10 +1129,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
 
 	/* Add I2C adapter */
 	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "registration failed\n");
+	if (ret < 0)
 		goto rpm_disable;
-	}
 
 	pm_runtime_mark_last_busy(&pdev->dev);
 	pm_runtime_put_autosuspend(&pdev->dev);
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index c2f25f19d76f9b..0cf1379f4e8091 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -288,10 +288,8 @@ static int smbus_sch_probe(struct platform_device *dev)
 		"SMBus SCH adapter at %04x", sch_smba);
 
 	retval = i2c_add_adapter(&sch_adapter);
-	if (retval) {
-		dev_err(&dev->dev, "Couldn't register adapter!\n");
+	if (retval)
 		sch_smba = 0;
-	}
 
 	return retval;
 }
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
index 1c870771009840..f573448d213216 100644
--- a/drivers/i2c/busses/i2c-ismt.c
+++ b/drivers/i2c/busses/i2c-ismt.c
@@ -922,10 +922,8 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		return err;
 
 	err = i2c_add_adapter(&priv->adapter);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
+	if (err)
 		return -ENODEV;
-	}
 	return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
index cd9872594fe2a0..b8ea62105f42c9 100644
--- a/drivers/i2c/busses/i2c-jz4780.c
+++ b/drivers/i2c/busses/i2c-jz4780.c
@@ -798,10 +798,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
 		goto err;
 
 	ret = i2c_add_adapter(&i2c->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to add bus\n");
+	if (ret < 0)
 		goto err;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c
index 586a15205e61de..9b1fef455a895d 100644
--- a/drivers/i2c/busses/i2c-lpc2k.c
+++ b/drivers/i2c/busses/i2c-lpc2k.c
@@ -432,10 +432,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
 	i2c->adap.dev.of_node = pdev->dev.of_node;
 
 	ret = i2c_add_adapter(&i2c->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to add adapter!\n");
+	if (ret < 0)
 		goto fail_clk;
-	}
 
 	dev_info(&pdev->dev, "LPC2K I2C adapter\n");
 
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 71d3929adf54ed..102d2b91771f35 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -453,7 +453,6 @@ static int meson_i2c_probe(struct platform_device *pdev)
 
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "can't register adapter\n");
 		clk_unprepare(i2c->clk);
 		return ret;
 	}
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 48ecffecc0eda3..565a49a0c56410 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -737,10 +737,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
 
 	result = i2c_add_adapter(&i2c->adap);
-	if (result < 0) {
-		dev_err(i2c->dev, "failed to add adapter\n");
+	if (result < 0)
 		goto fail_add;
-	}
 
 	return result;
 
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index d9373e60be8ae3..4a7d9bc2142ba3 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -786,10 +786,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
 
 	i2c_set_adapdata(&i2c->adap, i2c);
 	ret = i2c_add_adapter(&i2c->adap);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
+	if (ret)
 		return ret;
-	}
 
 	platform_set_drvdata(pdev, i2c);
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 033846cdf26622..5738556b6aac20 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -868,7 +868,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
 	i2c_set_adapdata(adap, i2c);
 	err = i2c_add_numbered_adapter(adap);
 	if (err) {
-		dev_err(dev, "Failed to add adapter (%d)\n", err);
 		writel(MXS_I2C_CTRL0_SFTRST,
 				i2c->regs + MXS_I2C_CTRL0_SET);
 		return err;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 42fcc9458432f8..374b35e7e450ce 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -366,7 +366,6 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
 
 	error = i2c_add_adapter(&smbus->adapter);
 	if (error) {
-		dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
 		release_region(smbus->base, smbus->size);
 		return error;
 	}
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index bcd17e8cbcb4b3..da6609d628487b 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -1046,10 +1046,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
 		 adap->name, dev->virtbase);
 
 	ret = i2c_add_adapter(adap);
-	if (ret) {
-		dev_err(&adev->dev, "failed to add adapter\n");
+	if (ret)
 		goto err_no_adap;
-	}
 
 	pm_runtime_put(&adev->dev);
 
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index dfa7a4b4a91d78..92692349d0c328 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -492,10 +492,8 @@ static int ocores_i2c_probe(struct platform_device *pdev)
 
 	/* add i2c adapter to i2c tree */
 	ret = i2c_add_adapter(&i2c->adap);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add adapter\n");
+	if (ret)
 		return ret;
-	}
 
 	/* add in known devices to the bus */
 	if (pdata) {
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 30ae35146723a4..b75d2da79b27c5 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -1213,10 +1213,8 @@ static int octeon_i2c_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, i2c);
 
 	result = i2c_add_adapter(&i2c->adap);
-	if (result < 0) {
-		dev_err(i2c->dev, "failed to add adapter\n");
+	if (result < 0)
 		goto out;
-	}
 	dev_info(i2c->dev, "probed\n");
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ab1279b8e2407a..c7da0c42baeefa 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1425,10 +1425,8 @@ omap_i2c_probe(struct platform_device *pdev)
 	/* i2c device drivers may be active on return from add_adapter() */
 	adap->nr = pdev->id;
 	r = i2c_add_numbered_adapter(adap);
-	if (r) {
-		dev_err(omap->dev, "failure adding adapter\n");
+	if (r)
 		goto err_unuse_clocks;
-	}
 
 	dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
 		 major, minor, omap->speed);
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 23d1c167b5d752..c2268cdf38e823 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -694,7 +694,6 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
 
 	retval = i2c_add_adapter(adap);
 	if (retval) {
-		dev_err(&dev->dev, "Couldn't register adapter!\n");
 		kfree(adapdata);
 		kfree(adap);
 		release_region(smba, SMBIOSIZE);
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 2c40edbf6224eb..217c78711d6501 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -329,10 +329,8 @@ static int pmcmsptwi_probe(struct platform_device *pldev)
 	i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
 
 	rc = i2c_add_adapter(&pmcmsptwi_adapter);
-	if (rc) {
-		dev_err(&pldev->dev, "Unable to register I2C adapter\n");
+	if (rc)
 		goto ret_unmap;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 7ea67aa46fb730..fd5f9d2bf6d94e 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
 
 	/* Register this adapter with the I2C subsystem */
 	ret = i2c_add_numbered_adapter(&alg_data->adapter);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
+	if (ret < 0)
 		goto out_clock;
-	}
 
 	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
 		alg_data->adapter.name, res->start, alg_data->irq);
diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
index 82b6f02544dae7..0c8b1571886d5b 100644
--- a/drivers/i2c/busses/i2c-puv3.c
+++ b/drivers/i2c/busses/i2c-puv3.c
@@ -212,11 +212,8 @@ static int puv3_i2c_probe(struct platform_device *pdev)
 
 	adapter->nr = pdev->id;
 	rc = i2c_add_numbered_adapter(adapter);
-	if (rc) {
-		dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
-				adapter->name);
+	if (rc)
 		goto fail_add_adapter;
-	}
 
 	dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
 	return 0;
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 0d351954db02b9..e28b825b043378 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1292,10 +1292,8 @@ static int i2c_pxa_probe(struct platform_device *dev)
 #endif
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
-	if (ret < 0) {
-		dev_err(&dev->dev, "failed to add bus: %d\n", ret);
+	if (ret < 0)
 		goto ereqirq;
-	}
 
 	platform_set_drvdata(dev, i2c);
 
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 52407f3c9e1cce..400e344704d273 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -875,10 +875,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, priv);
 
 	ret = i2c_add_numbered_adapter(adap);
-	if (ret < 0) {
-		dev_err(dev, "reg adap failed: %d\n", ret);
+	if (ret < 0)
 		goto out_pm_disable;
-	}
 
 	dev_info(dev, "probed\n");
 
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index d7e3af67154373..6263ea82d6ac3b 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -383,10 +383,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
 
 
 	ret = i2c_add_adapter(adap);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add adapter\n");
+	if (ret)
 		return ret;
-	}
 
 	platform_set_drvdata(pdev, riic);
 
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 2bc8b01153d619..3b87afe82f6394 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -1303,10 +1303,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	rk3x_i2c_adapt_div(i2c, clk_rate);
 
 	ret = i2c_add_adapter(&i2c->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not register adapter\n");
+	if (ret < 0)
 		goto err_clk_notifier;
-	}
 
 	dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);
 
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 38dc1cacfd8bba..499af26e736e7e 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1215,7 +1215,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
 		pm_runtime_disable(&pdev->dev);
 		s3c24xx_i2c_deregister_cpufreq(i2c);
 		clk_unprepare(i2c->clk);
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 24968384b4014f..c2005c789d2b09 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -510,10 +510,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
 	}
 
 	ret = i2c_add_numbered_adapter(&id->adap);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
+	if (ret < 0)
 		goto out4;
-	}
 
 	platform_set_drvdata(pdev, id);
 
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 6fb3e264599229..50f276e8d17967 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -981,7 +981,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
 	ret = i2c_add_numbered_adapter(adap);
 	if (ret < 0) {
 		sh_mobile_i2c_release_dma(pd);
-		dev_err(&dev->dev, "cannot add numbered adapter\n");
 		return ret;
 	}
 
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index 792a42bdd335b9..95e81d0f72b4d2 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -387,10 +387,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
 		writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
 
 	err = i2c_add_numbered_adapter(adap);
-	if (err < 0) {
-		dev_err(&pdev->dev, "Can't add new i2c adapter\n");
+	if (err < 0)
 		goto out;
-	}
 
 	clk_disable(clk);
 
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index 944ec420508487..1371547ce1a3a8 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -874,10 +874,8 @@ static int st_i2c_probe(struct platform_device *pdev)
 	init_completion(&i2c_dev->complete);
 
 	ret = i2c_add_adapter(adap);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add adapter\n");
+	if (ret)
 		return ret;
-	}
 
 	platform_set_drvdata(pdev, i2c_dev);
 
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 460c134832ac30..dc63236b45b216 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -920,11 +920,8 @@ static int stu300_probe(struct platform_device *pdev)
 
 	/* i2c device drivers may be active on return from add_adapter() */
 	ret = i2c_add_numbered_adapter(adap);
-	if (ret) {
-		dev_err(&pdev->dev, "failure adding ST Micro DDC "
-		       "I2C adapter\n");
+	if (ret)
 		return ret;
-	}
 
 	platform_set_drvdata(pdev, dev);
 	dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index b126dbaa47e370..d9979da11485ae 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -932,10 +932,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
 
 	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
+	if (ret)
 		goto disable_div_clk;
-	}
 
 	return 0;
 
diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
index aeead0d27d1007..64318e69089439 100644
--- a/drivers/i2c/busses/i2c-uniphier-f.c
+++ b/drivers/i2c/busses/i2c-uniphier-f.c
@@ -550,15 +550,10 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
 	}
 
 	ret = i2c_add_adapter(&priv->adap);
-	if (ret) {
-		dev_err(dev, "failed to add I2C adapter\n");
-		goto err;
-	}
-
-err:
 	if (ret)
 		clk_disable_unprepare(priv->clk);
 
+ err:
 	return ret;
 }
 
diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
index 475a5eb514e215..94f64cccfdef08 100644
--- a/drivers/i2c/busses/i2c-uniphier.c
+++ b/drivers/i2c/busses/i2c-uniphier.c
@@ -407,15 +407,10 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
 	}
 
 	ret = i2c_add_adapter(&priv->adap);
-	if (ret) {
-		dev_err(dev, "failed to add I2C adapter\n");
-		goto err;
-	}
-
-err:
 	if (ret)
 		clk_disable_unprepare(priv->clk);
 
+ err:
 	return ret;
 }
 
diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
index e1e3a85596c562..fbd0fd59f31239 100644
--- a/drivers/i2c/busses/i2c-wmt.c
+++ b/drivers/i2c/busses/i2c-wmt.c
@@ -432,10 +432,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
 	}
 
 	err = i2c_add_adapter(adap);
-	if (err) {
-		dev_err(&pdev->dev, "failed to add adapter\n");
+	if (err)
 		return err;
-	}
 
 	platform_set_drvdata(pdev, i2c_dev);
 
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
index 4233f5695352fd..263685c7a51287 100644
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -418,7 +418,6 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
 	i2c_set_adapdata(adapter, ctx);
 	rc = i2c_add_adapter(adapter);
 	if (rc) {
-		dev_err(&pdev->dev, "Adapter registeration failed\n");
 		mbox_free_channel(ctx->mbox_chan);
 		return rc;
 	}
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 74f54f2f471fa7..66bce3b311a199 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -804,7 +804,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
 	/* add i2c adapter to i2c tree */
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret) {
-		dev_err(&pdev->dev, "Failed to add adapter\n");
 		xiic_deinit(i2c);
 		goto err_clk_dis;
 	}
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index 55a7bef1b2e1df..2a972ed7aa0df1 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -400,10 +400,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
 	i2c_set_adapdata(&priv->adapter, priv);
 
 	err = i2c_add_adapter(&priv->adapter);
-	if (err) {
-		dev_err(&pdev->dev, "failed to add I2C adapter!\n");
+	if (err)
 		return err;
-	}
 
 	platform_set_drvdata(pdev, priv);
 	dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
index 613c3a4f2c5142..0968f59b6df586 100644
--- a/drivers/i2c/busses/i2c-xlr.c
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -432,10 +432,8 @@ static int xlr_i2c_probe(struct platform_device *pdev)
 
 	i2c_set_adapdata(&priv->adap, priv);
 	ret = i2c_add_numbered_adapter(&priv->adap);
-	if (ret < 0) {
-		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
+	if (ret < 0)
 		return ret;
-	}
 
 	platform_set_drvdata(pdev, priv);
 	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
-- 
2.8.1



From peter at korsgaard.com  Tue Aug  9 04:48:03 2016
From: peter at korsgaard.com (Peter Korsgaard)
Date: Tue, 09 Aug 2016 13:48:03 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
 (Wolfram Sang's message of "Tue, 9 Aug 2016 13:36:17 +0200")
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <87vaza2mfg.fsf@dell.be.48ers.dk>

>>>>> "Wolfram" == Wolfram Sang <wsa-dev at sang-engineering.com> writes:

 > The core will do this for us now.
 > Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
 > ---
 >  drivers/i2c/busses/i2c-ocores.c         | 4 +---

For i2c-ocores.c:

Acked-by: Peter Korsgaard <peter at korsgaard.com>

-- 
Bye, Peter Korsgaard


From grygorii.strashko at ti.com  Tue Aug  9 04:47:03 2016
From: grygorii.strashko at ti.com (Grygorii Strashko)
Date: Tue, 9 Aug 2016 14:47:03 +0300
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <e4e906fe-1362-1199-de42-a16b58800de6@ti.com>

On 08/09/2016 02:36 PM, Wolfram Sang wrote:
> The core will do this for us now.
>
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---

For:
>  drivers/i2c/busses/i2c-davinci.c        | 4 +---
>  drivers/i2c/busses/i2c-omap.c           | 4 +---

Reviewed-by: Grygorii Strashko <grygorii.strashko at ti.com>


-- 
regards,
-grygorii


From u.kleine-koenig at pengutronix.de  Tue Aug  9 04:57:40 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Tue, 9 Aug 2016 13:57:40 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <20160809115740.GA5528@pengutronix.de>

Hello Wolfram,

On Tue, Aug 09, 2016 at 01:36:17PM +0200, Wolfram Sang wrote:
> The core will do this for us now.

Would be nice to point out the relevant commit that changed the core in
the commit log.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From heiko at sntech.de  Tue Aug  9 05:13:11 2016
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Tue, 09 Aug 2016 14:13:11 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <5423570.keugkegXM3@diego>

Am Dienstag, 9. August 2016, 13:36:17 schrieb Wolfram Sang:
> The core will do this for us now.
> 
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---

[...]

> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 2bc8b01153d619..3b87afe82f6394 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -1303,10 +1303,8 @@ static int rk3x_i2c_probe(struct platform_device
> *pdev) rk3x_i2c_adapt_div(i2c, clk_rate);
> 
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Could not register adapter\n");
> +	if (ret < 0)
>  		goto err_clk_notifier;
> -	}
> 
>  	dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);

for Rockchip
Acked-by: Heiko Stuebner <heiko at sntech.de>


From thierry.reding at gmail.com  Tue Aug  9 05:58:46 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 9 Aug 2016 14:58:46 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <20160809125846.GA17535@ulmo.ba.sec>

On Tue, Aug 09, 2016 at 01:36:17PM +0200, Wolfram Sang wrote:
[...]
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index b126dbaa47e370..d9979da11485ae 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -932,10 +932,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
>  	i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
>  
>  	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
> +	if (ret)
>  		goto disable_div_clk;
> -	}
>  
>  	return 0;
>  

Acked-by: Thierry Reding <treding at nvidia.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20160809/e1459211/attachment.sig>

From nhorman at tuxdriver.com  Tue Aug  9 05:55:22 2016
From: nhorman at tuxdriver.com (Neil Horman)
Date: Tue, 9 Aug 2016 08:55:22 -0400
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <20160809125522.GA15676@hmsreliant.think-freely.org>

On Tue, Aug 09, 2016 at 01:36:17PM +0200, Wolfram Sang wrote:
> The core will do this for us now.
> 
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---
>  drivers/i2c/busses/i2c-amd756.c         | 5 +----
>  drivers/i2c/busses/i2c-at91.c           | 2 --
>  drivers/i2c/busses/i2c-axxia.c          | 8 +-------
>  drivers/i2c/busses/i2c-bcm-iproc.c      | 8 +-------
>  drivers/i2c/busses/i2c-bcm-kona.c       | 4 +---
>  drivers/i2c/busses/i2c-bfin-twi.c       | 4 +---
>  drivers/i2c/busses/i2c-brcmstb.c        | 4 +---
>  drivers/i2c/busses/i2c-cadence.c        | 4 +---
>  drivers/i2c/busses/i2c-cpm.c            | 4 +---
>  drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +---
>  drivers/i2c/busses/i2c-davinci.c        | 4 +---
>  drivers/i2c/busses/i2c-diolan-u2c.c     | 4 +---
>  drivers/i2c/busses/i2c-dln2.c           | 4 +---
>  drivers/i2c/busses/i2c-efm32.c          | 1 -
>  drivers/i2c/busses/i2c-exynos5.c        | 4 +---
>  drivers/i2c/busses/i2c-hix5hd2.c        | 4 +---
>  drivers/i2c/busses/i2c-i801.c           | 1 -
>  drivers/i2c/busses/i2c-ibm_iic.c        | 4 +---
>  drivers/i2c/busses/i2c-img-scb.c        | 4 +---
>  drivers/i2c/busses/i2c-imx.c            | 4 +---
>  drivers/i2c/busses/i2c-isch.c           | 4 +---
>  drivers/i2c/busses/i2c-ismt.c           | 4 +---
>  drivers/i2c/busses/i2c-jz4780.c         | 4 +---
>  drivers/i2c/busses/i2c-lpc2k.c          | 4 +---
>  drivers/i2c/busses/i2c-meson.c          | 1 -
>  drivers/i2c/busses/i2c-mpc.c            | 4 +---
>  drivers/i2c/busses/i2c-mt65xx.c         | 4 +---
>  drivers/i2c/busses/i2c-mxs.c            | 1 -
>  drivers/i2c/busses/i2c-nforce2.c        | 1 -
>  drivers/i2c/busses/i2c-nomadik.c        | 4 +---
>  drivers/i2c/busses/i2c-ocores.c         | 4 +---
>  drivers/i2c/busses/i2c-octeon.c         | 4 +---
>  drivers/i2c/busses/i2c-omap.c           | 4 +---
>  drivers/i2c/busses/i2c-piix4.c          | 1 -
>  drivers/i2c/busses/i2c-pmcmsp.c         | 4 +---
>  drivers/i2c/busses/i2c-pnx.c            | 4 +---
>  drivers/i2c/busses/i2c-puv3.c           | 5 +----
>  drivers/i2c/busses/i2c-pxa.c            | 4 +---
>  drivers/i2c/busses/i2c-rcar.c           | 4 +---
>  drivers/i2c/busses/i2c-riic.c           | 4 +---
>  drivers/i2c/busses/i2c-rk3x.c           | 4 +---
>  drivers/i2c/busses/i2c-s3c2410.c        | 1 -
>  drivers/i2c/busses/i2c-sh7760.c         | 4 +---
>  drivers/i2c/busses/i2c-sh_mobile.c      | 1 -
>  drivers/i2c/busses/i2c-sirf.c           | 4 +---
>  drivers/i2c/busses/i2c-st.c             | 4 +---
>  drivers/i2c/busses/i2c-stu300.c         | 5 +----
>  drivers/i2c/busses/i2c-tegra.c          | 4 +---
>  drivers/i2c/busses/i2c-uniphier-f.c     | 7 +------
>  drivers/i2c/busses/i2c-uniphier.c       | 7 +------
>  drivers/i2c/busses/i2c-wmt.c            | 4 +---
>  drivers/i2c/busses/i2c-xgene-slimpro.c  | 1 -
>  drivers/i2c/busses/i2c-xiic.c           | 1 -
>  drivers/i2c/busses/i2c-xlp9xx.c         | 4 +---
>  drivers/i2c/busses/i2c-xlr.c            | 4 +---
>  55 files changed, 44 insertions(+), 161 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
> index 6c7113d990f882..274908cd1fdeab 100644
> --- a/drivers/i2c/busses/i2c-amd756.c
> +++ b/drivers/i2c/busses/i2c-amd756.c
> @@ -378,11 +378,8 @@ static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  		 amd756_ioport);
>  
>  	error = i2c_add_adapter(&amd756_smbus);
> -	if (error) {
> -		dev_err(&pdev->dev,
> -			"Adapter registration failed, module not inserted\n");
> +	if (error)
>  		goto out_err;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
> index f23372669f770f..03a519d29616d7 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -1118,8 +1118,6 @@ static int at91_twi_probe(struct platform_device *pdev)
>  
>  	rc = i2c_add_numbered_adapter(&dev->adapter);
>  	if (rc) {
> -		dev_err(dev->dev, "Adapter %s registration failed\n",
> -			dev->adapter.name);
>  		clk_disable_unprepare(dev->clk);
>  
>  		pm_runtime_disable(dev->dev);
> diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
> index c335cc7852f94e..d3bcaf4ab095d0 100644
> --- a/drivers/i2c/busses/i2c-axxia.c
> +++ b/drivers/i2c/busses/i2c-axxia.c
> @@ -558,13 +558,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, idev);
>  
> -	ret = i2c_add_adapter(&idev->adapter);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> -		return ret;
> -	}
> -
> -	return 0;
> +	return i2c_add_adapter(&idev->adapter);
>  }
>  
>  static int axxia_i2c_remove(struct platform_device *pdev)
> diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
> index 19c843828fe2ca..8e3477f9297eda 100644
> --- a/drivers/i2c/busses/i2c-bcm-iproc.c
> +++ b/drivers/i2c/busses/i2c-bcm-iproc.c
> @@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
>  	adap->dev.parent = &pdev->dev;
>  	adap->dev.of_node = pdev->dev.of_node;
>  
> -	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(iproc_i2c->device, "failed to add adapter\n");
> -		return ret;
> -	}
> -
> -	return 0;
> +	return i2c_add_adapter(adap);
>  }
>  
>  static int bcm_iproc_i2c_remove(struct platform_device *pdev)
> diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
> index ac9f47679c3a4b..a5c9098507896b 100644
> --- a/drivers/i2c/busses/i2c-bcm-kona.c
> +++ b/drivers/i2c/busses/i2c-bcm-kona.c
> @@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev)
>  	adap->dev.of_node = pdev->dev.of_node;
>  
>  	rc = i2c_add_adapter(adap);
> -	if (rc) {
> -		dev_err(dev->device, "failed to add adapter\n");
> +	if (rc)
>  		return rc;
> -	}
>  
>  	dev_info(dev->device, "device registered successfully\n");
>  
> diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
> index 025686d4164058..29d00c4f7824c2 100644
> --- a/drivers/i2c/busses/i2c-bfin-twi.c
> +++ b/drivers/i2c/busses/i2c-bfin-twi.c
> @@ -685,10 +685,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
>  	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
>  
>  	rc = i2c_add_numbered_adapter(p_adap);
> -	if (rc < 0) {
> -		dev_err(&pdev->dev, "Can't add i2c adapter!\n");
> +	if (rc < 0)
>  		goto out_error;
> -	}
>  
>  	platform_set_drvdata(pdev, iface);
>  
> diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
> index 3f5a4d71d3bf32..bc5c176e984aea 100644
> --- a/drivers/i2c/busses/i2c-brcmstb.c
> +++ b/drivers/i2c/busses/i2c-brcmstb.c
> @@ -648,10 +648,8 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
>  	adap->dev.parent = &pdev->dev;
>  	adap->dev.of_node = pdev->dev.of_node;
>  	rc = i2c_add_adapter(adap);
> -	if (rc) {
> -		dev_err(dev->device, "failed to add adapter\n");
> +	if (rc)
>  		goto probe_errorout;
> -	}
>  
>  	dev_info(dev->device, "%s@%dhz registered in %s mode\n",
>  		 int_name ? int_name : " ", dev->clk_freq_hz,
> diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
> index 90bbd9f9dd8f77..1cc1e79e958d56 100644
> --- a/drivers/i2c/busses/i2c-cadence.c
> +++ b/drivers/i2c/busses/i2c-cadence.c
> @@ -963,10 +963,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_adapter(&id->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
> +	if (ret < 0)
>  		goto err_clk_dis;
> -	}
>  
>  	/*
>  	 * Cadence I2C controller has a bug wherein it generates
> diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
> index ee57c1e865e271..d89bde2c5da256 100644
> --- a/drivers/i2c/busses/i2c-cpm.c
> +++ b/drivers/i2c/busses/i2c-cpm.c
> @@ -665,10 +665,8 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
>  	cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
>  	result = i2c_add_numbered_adapter(&cpm->adap);
>  
> -	if (result < 0) {
> -		dev_err(&ofdev->dev, "Unable to register with I2C\n");
> +	if (result < 0)
>  		goto out_shut;
> -	}
>  
>  	dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
>  		cpm->adap.name);
> diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> index a0d95ff682ae12..cf334a9ec22cb7 100644
> --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> @@ -281,10 +281,8 @@ static int ec_i2c_probe(struct platform_device *pdev)
>  	bus->adap.retries = I2C_MAX_RETRIES;
>  
>  	err = i2c_add_adapter(&bus->adap);
> -	if (err) {
> -		dev_err(dev, "cannot register i2c adapter\n");
> +	if (err)
>  		return err;
> -	}
>  	platform_set_drvdata(pdev, bus);
>  
>  	return err;
> diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
> index a8bdcb5292f5b3..9e7ef5cf5d495d 100644
> --- a/drivers/i2c/busses/i2c-davinci.c
> +++ b/drivers/i2c/busses/i2c-davinci.c
> @@ -846,10 +846,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
>  
>  	adap->nr = pdev->id;
>  	r = i2c_add_numbered_adapter(adap);
> -	if (r) {
> -		dev_err(&pdev->dev, "failure adding adapter\n");
> +	if (r)
>  		goto err_unuse_clocks;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c
> index b19a310bf9b3e8..f718ee4e3332fe 100644
> --- a/drivers/i2c/busses/i2c-diolan-u2c.c
> +++ b/drivers/i2c/busses/i2c-diolan-u2c.c
> @@ -487,10 +487,8 @@ static int diolan_u2c_probe(struct usb_interface *interface,
>  
>  	/* and finally attach to i2c layer */
>  	ret = i2c_add_adapter(&dev->adapter);
> -	if (ret < 0) {
> -		dev_err(&interface->dev, "failed to add I2C adapter\n");
> +	if (ret < 0)
>  		goto error_free;
> -	}
>  
>  	dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
>  
> diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c
> index f2eb4f76591fbe..8acda2aa15583c 100644
> --- a/drivers/i2c/busses/i2c-dln2.c
> +++ b/drivers/i2c/busses/i2c-dln2.c
> @@ -228,10 +228,8 @@ static int dln2_i2c_probe(struct platform_device *pdev)
>  
>  	/* and finally attach to i2c layer */
>  	ret = i2c_add_adapter(&dln2->adapter);
> -	if (ret < 0) {
> -		dev_err(dev, "failed to add I2C adapter: %d\n", ret);
> +	if (ret < 0)
>  		goto out_disable;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
> index e253598d764c0d..aa336ba89aa3fe 100644
> --- a/drivers/i2c/busses/i2c-efm32.c
> +++ b/drivers/i2c/busses/i2c-efm32.c
> @@ -438,7 +438,6 @@ static int efm32_i2c_probe(struct platform_device *pdev)
>  
>  	ret = i2c_add_adapter(&ddata->adapter);
>  	if (ret) {
> -		dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret);
>  		free_irq(ddata->irq, ddata);
>  
>  err_disable_clk:
> diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
> index c0e3ada028763d..bea607149972d4 100644
> --- a/drivers/i2c/busses/i2c-exynos5.c
> +++ b/drivers/i2c/busses/i2c-exynos5.c
> @@ -796,10 +796,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
>  	exynos5_i2c_reset(i2c);
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
> +	if (ret < 0)
>  		goto err_clk;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c);
>  
> diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
> index 7c6966434ee7b9..ae7f3180f7e887 100644
> --- a/drivers/i2c/busses/i2c-hix5hd2.c
> +++ b/drivers/i2c/busses/i2c-hix5hd2.c
> @@ -478,10 +478,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
>  	pm_runtime_enable(priv->dev);
>  
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
> +	if (ret < 0)
>  		goto err_runtime;
> -	}
>  
>  	return ret;
>  
> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
> index 5ef9b733d153fa..22a0ed4de80da0 100644
> --- a/drivers/i2c/busses/i2c-i801.c
> +++ b/drivers/i2c/busses/i2c-i801.c
> @@ -1613,7 +1613,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  		"SMBus I801 adapter at %04lx", priv->smba);
>  	err = i2c_add_adapter(&priv->adapter);
>  	if (err) {
> -		dev_err(&dev->dev, "Failed to add SMBus adapter\n");
>  		i801_acpi_remove(priv);
>  		return err;
>  	}
> diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
> index cdaa7be2cd1b94..412b91d255ad1d 100644
> --- a/drivers/i2c/busses/i2c-ibm_iic.c
> +++ b/drivers/i2c/busses/i2c-ibm_iic.c
> @@ -751,10 +751,8 @@ static int iic_probe(struct platform_device *ofdev)
>  	adap->timeout = HZ;
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret  < 0) {
> -		dev_err(&ofdev->dev, "failed to register i2c adapter\n");
> +	if (ret  < 0)
>  		goto error_cleanup;
> -	}
>  
>  	dev_info(&ofdev->dev, "using %s mode\n",
>  		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
> diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
> index ea20425b697217..db8e8b40569d98 100644
> --- a/drivers/i2c/busses/i2c-img-scb.c
> +++ b/drivers/i2c/busses/i2c-img-scb.c
> @@ -1394,10 +1394,8 @@ static int img_i2c_probe(struct platform_device *pdev)
>  		goto disable_clk;
>  
>  	ret = i2c_add_numbered_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> +	if (ret < 0)
>  		goto disable_clk;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index 1844bc9f7cd5a2..cb11eee9567318 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -1129,10 +1129,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
>  
>  	/* Add I2C adapter */
>  	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "registration failed\n");
> +	if (ret < 0)
>  		goto rpm_disable;
> -	}
>  
>  	pm_runtime_mark_last_busy(&pdev->dev);
>  	pm_runtime_put_autosuspend(&pdev->dev);
> diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
> index c2f25f19d76f9b..0cf1379f4e8091 100644
> --- a/drivers/i2c/busses/i2c-isch.c
> +++ b/drivers/i2c/busses/i2c-isch.c
> @@ -288,10 +288,8 @@ static int smbus_sch_probe(struct platform_device *dev)
>  		"SMBus SCH adapter at %04x", sch_smba);
>  
>  	retval = i2c_add_adapter(&sch_adapter);
> -	if (retval) {
> -		dev_err(&dev->dev, "Couldn't register adapter!\n");
> +	if (retval)
>  		sch_smba = 0;
> -	}
>  
>  	return retval;
>  }
> diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
> index 1c870771009840..f573448d213216 100644
> --- a/drivers/i2c/busses/i2c-ismt.c
> +++ b/drivers/i2c/busses/i2c-ismt.c
> @@ -922,10 +922,8 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  		return err;
>  
>  	err = i2c_add_adapter(&priv->adapter);
> -	if (err) {
> -		dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
> +	if (err)
>  		return -ENODEV;
> -	}
>  	return 0;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
> index cd9872594fe2a0..b8ea62105f42c9 100644
> --- a/drivers/i2c/busses/i2c-jz4780.c
> +++ b/drivers/i2c/busses/i2c-jz4780.c
> @@ -798,10 +798,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
>  		goto err;
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Failed to add bus\n");
> +	if (ret < 0)
>  		goto err;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c
> index 586a15205e61de..9b1fef455a895d 100644
> --- a/drivers/i2c/busses/i2c-lpc2k.c
> +++ b/drivers/i2c/busses/i2c-lpc2k.c
> @@ -432,10 +432,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
>  	i2c->adap.dev.of_node = pdev->dev.of_node;
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add adapter!\n");
> +	if (ret < 0)
>  		goto fail_clk;
> -	}
>  
>  	dev_info(&pdev->dev, "LPC2K I2C adapter\n");
>  
> diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
> index 71d3929adf54ed..102d2b91771f35 100644
> --- a/drivers/i2c/busses/i2c-meson.c
> +++ b/drivers/i2c/busses/i2c-meson.c
> @@ -453,7 +453,6 @@ static int meson_i2c_probe(struct platform_device *pdev)
>  
>  	ret = i2c_add_adapter(&i2c->adap);
>  	if (ret < 0) {
> -		dev_err(&pdev->dev, "can't register adapter\n");
>  		clk_unprepare(i2c->clk);
>  		return ret;
>  	}
> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
> index 48ecffecc0eda3..565a49a0c56410 100644
> --- a/drivers/i2c/busses/i2c-mpc.c
> +++ b/drivers/i2c/busses/i2c-mpc.c
> @@ -737,10 +737,8 @@ static int fsl_i2c_probe(struct platform_device *op)
>  	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
>  
>  	result = i2c_add_adapter(&i2c->adap);
> -	if (result < 0) {
> -		dev_err(i2c->dev, "failed to add adapter\n");
> +	if (result < 0)
>  		goto fail_add;
> -	}
>  
>  	return result;
>  
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index d9373e60be8ae3..4a7d9bc2142ba3 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -786,10 +786,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
>  
>  	i2c_set_adapdata(&i2c->adap, i2c);
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c);
>  
> diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> index 033846cdf26622..5738556b6aac20 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -868,7 +868,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
>  	i2c_set_adapdata(adap, i2c);
>  	err = i2c_add_numbered_adapter(adap);
>  	if (err) {
> -		dev_err(dev, "Failed to add adapter (%d)\n", err);
>  		writel(MXS_I2C_CTRL0_SFTRST,
>  				i2c->regs + MXS_I2C_CTRL0_SET);
>  		return err;
> diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
> index 42fcc9458432f8..374b35e7e450ce 100644
> --- a/drivers/i2c/busses/i2c-nforce2.c
> +++ b/drivers/i2c/busses/i2c-nforce2.c
> @@ -366,7 +366,6 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
>  
>  	error = i2c_add_adapter(&smbus->adapter);
>  	if (error) {
> -		dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
>  		release_region(smbus->base, smbus->size);
>  		return error;
>  	}
> diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
> index bcd17e8cbcb4b3..da6609d628487b 100644
> --- a/drivers/i2c/busses/i2c-nomadik.c
> +++ b/drivers/i2c/busses/i2c-nomadik.c
> @@ -1046,10 +1046,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
>  		 adap->name, dev->virtbase);
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(&adev->dev, "failed to add adapter\n");
> +	if (ret)
>  		goto err_no_adap;
> -	}
>  
>  	pm_runtime_put(&adev->dev);
>  
> diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
> index dfa7a4b4a91d78..92692349d0c328 100644
> --- a/drivers/i2c/busses/i2c-ocores.c
> +++ b/drivers/i2c/busses/i2c-ocores.c
> @@ -492,10 +492,8 @@ static int ocores_i2c_probe(struct platform_device *pdev)
>  
>  	/* add i2c adapter to i2c tree */
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	/* add in known devices to the bus */
>  	if (pdata) {
> diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
> index 30ae35146723a4..b75d2da79b27c5 100644
> --- a/drivers/i2c/busses/i2c-octeon.c
> +++ b/drivers/i2c/busses/i2c-octeon.c
> @@ -1213,10 +1213,8 @@ static int octeon_i2c_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, i2c);
>  
>  	result = i2c_add_adapter(&i2c->adap);
> -	if (result < 0) {
> -		dev_err(i2c->dev, "failed to add adapter\n");
> +	if (result < 0)
>  		goto out;
> -	}
>  	dev_info(i2c->dev, "probed\n");
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index ab1279b8e2407a..c7da0c42baeefa 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -1425,10 +1425,8 @@ omap_i2c_probe(struct platform_device *pdev)
>  	/* i2c device drivers may be active on return from add_adapter() */
>  	adap->nr = pdev->id;
>  	r = i2c_add_numbered_adapter(adap);
> -	if (r) {
> -		dev_err(omap->dev, "failure adding adapter\n");
> +	if (r)
>  		goto err_unuse_clocks;
> -	}
>  
>  	dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
>  		 major, minor, omap->speed);
> diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
> index 23d1c167b5d752..c2268cdf38e823 100644
> --- a/drivers/i2c/busses/i2c-piix4.c
> +++ b/drivers/i2c/busses/i2c-piix4.c
> @@ -694,7 +694,6 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
>  
>  	retval = i2c_add_adapter(adap);
>  	if (retval) {
> -		dev_err(&dev->dev, "Couldn't register adapter!\n");
>  		kfree(adapdata);
>  		kfree(adap);
>  		release_region(smba, SMBIOSIZE);
> diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
> index 2c40edbf6224eb..217c78711d6501 100644
> --- a/drivers/i2c/busses/i2c-pmcmsp.c
> +++ b/drivers/i2c/busses/i2c-pmcmsp.c
> @@ -329,10 +329,8 @@ static int pmcmsptwi_probe(struct platform_device *pldev)
>  	i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
>  
>  	rc = i2c_add_adapter(&pmcmsptwi_adapter);
> -	if (rc) {
> -		dev_err(&pldev->dev, "Unable to register I2C adapter\n");
> +	if (rc)
>  		goto ret_unmap;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
> index 7ea67aa46fb730..fd5f9d2bf6d94e 100644
> --- a/drivers/i2c/busses/i2c-pnx.c
> +++ b/drivers/i2c/busses/i2c-pnx.c
> @@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
>  
>  	/* Register this adapter with the I2C subsystem */
>  	ret = i2c_add_numbered_adapter(&alg_data->adapter);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
> +	if (ret < 0)
>  		goto out_clock;
> -	}
>  
>  	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
>  		alg_data->adapter.name, res->start, alg_data->irq);
> diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
> index 82b6f02544dae7..0c8b1571886d5b 100644
> --- a/drivers/i2c/busses/i2c-puv3.c
> +++ b/drivers/i2c/busses/i2c-puv3.c
> @@ -212,11 +212,8 @@ static int puv3_i2c_probe(struct platform_device *pdev)
>  
>  	adapter->nr = pdev->id;
>  	rc = i2c_add_numbered_adapter(adapter);
> -	if (rc) {
> -		dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
> -				adapter->name);
> +	if (rc)
>  		goto fail_add_adapter;
> -	}
>  
>  	dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
>  	return 0;
> diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
> index 0d351954db02b9..e28b825b043378 100644
> --- a/drivers/i2c/busses/i2c-pxa.c
> +++ b/drivers/i2c/busses/i2c-pxa.c
> @@ -1292,10 +1292,8 @@ static int i2c_pxa_probe(struct platform_device *dev)
>  #endif
>  
>  	ret = i2c_add_numbered_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&dev->dev, "failed to add bus: %d\n", ret);
> +	if (ret < 0)
>  		goto ereqirq;
> -	}
>  
>  	platform_set_drvdata(dev, i2c);
>  
> diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
> index 52407f3c9e1cce..400e344704d273 100644
> --- a/drivers/i2c/busses/i2c-rcar.c
> +++ b/drivers/i2c/busses/i2c-rcar.c
> @@ -875,10 +875,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, priv);
>  
>  	ret = i2c_add_numbered_adapter(adap);
> -	if (ret < 0) {
> -		dev_err(dev, "reg adap failed: %d\n", ret);
> +	if (ret < 0)
>  		goto out_pm_disable;
> -	}
>  
>  	dev_info(dev, "probed\n");
>  
> diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
> index d7e3af67154373..6263ea82d6ac3b 100644
> --- a/drivers/i2c/busses/i2c-riic.c
> +++ b/drivers/i2c/busses/i2c-riic.c
> @@ -383,10 +383,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
>  
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, riic);
>  
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 2bc8b01153d619..3b87afe82f6394 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -1303,10 +1303,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>  	rk3x_i2c_adapt_div(i2c, clk_rate);
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Could not register adapter\n");
> +	if (ret < 0)
>  		goto err_clk_notifier;
> -	}
>  
>  	dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);
>  
> diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
> index 38dc1cacfd8bba..499af26e736e7e 100644
> --- a/drivers/i2c/busses/i2c-s3c2410.c
> +++ b/drivers/i2c/busses/i2c-s3c2410.c
> @@ -1215,7 +1215,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
>  
>  	ret = i2c_add_numbered_adapter(&i2c->adap);
>  	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
>  		pm_runtime_disable(&pdev->dev);
>  		s3c24xx_i2c_deregister_cpufreq(i2c);
>  		clk_unprepare(i2c->clk);
> diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
> index 24968384b4014f..c2005c789d2b09 100644
> --- a/drivers/i2c/busses/i2c-sh7760.c
> +++ b/drivers/i2c/busses/i2c-sh7760.c
> @@ -510,10 +510,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_numbered_adapter(&id->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
> +	if (ret < 0)
>  		goto out4;
> -	}
>  
>  	platform_set_drvdata(pdev, id);
>  
> diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
> index 6fb3e264599229..50f276e8d17967 100644
> --- a/drivers/i2c/busses/i2c-sh_mobile.c
> +++ b/drivers/i2c/busses/i2c-sh_mobile.c
> @@ -981,7 +981,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
>  	ret = i2c_add_numbered_adapter(adap);
>  	if (ret < 0) {
>  		sh_mobile_i2c_release_dma(pd);
> -		dev_err(&dev->dev, "cannot add numbered adapter\n");
>  		return ret;
>  	}
>  
> diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
> index 792a42bdd335b9..95e81d0f72b4d2 100644
> --- a/drivers/i2c/busses/i2c-sirf.c
> +++ b/drivers/i2c/busses/i2c-sirf.c
> @@ -387,10 +387,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
>  		writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
>  
>  	err = i2c_add_numbered_adapter(adap);
> -	if (err < 0) {
> -		dev_err(&pdev->dev, "Can't add new i2c adapter\n");
> +	if (err < 0)
>  		goto out;
> -	}
>  
>  	clk_disable(clk);
>  
> diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
> index 944ec420508487..1371547ce1a3a8 100644
> --- a/drivers/i2c/busses/i2c-st.c
> +++ b/drivers/i2c/busses/i2c-st.c
> @@ -874,10 +874,8 @@ static int st_i2c_probe(struct platform_device *pdev)
>  	init_completion(&i2c_dev->complete);
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c_dev);
>  
> diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
> index 460c134832ac30..dc63236b45b216 100644
> --- a/drivers/i2c/busses/i2c-stu300.c
> +++ b/drivers/i2c/busses/i2c-stu300.c
> @@ -920,11 +920,8 @@ static int stu300_probe(struct platform_device *pdev)
>  
>  	/* i2c device drivers may be active on return from add_adapter() */
>  	ret = i2c_add_numbered_adapter(adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failure adding ST Micro DDC "
> -		       "I2C adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, dev);
>  	dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index b126dbaa47e370..d9979da11485ae 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -932,10 +932,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
>  	i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
>  
>  	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
> +	if (ret)
>  		goto disable_div_clk;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
> index aeead0d27d1007..64318e69089439 100644
> --- a/drivers/i2c/busses/i2c-uniphier-f.c
> +++ b/drivers/i2c/busses/i2c-uniphier-f.c
> @@ -550,15 +550,10 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret) {
> -		dev_err(dev, "failed to add I2C adapter\n");
> -		goto err;
> -	}
> -
> -err:
>  	if (ret)
>  		clk_disable_unprepare(priv->clk);
>  
> + err:
>  	return ret;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
> index 475a5eb514e215..94f64cccfdef08 100644
> --- a/drivers/i2c/busses/i2c-uniphier.c
> +++ b/drivers/i2c/busses/i2c-uniphier.c
> @@ -407,15 +407,10 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret) {
> -		dev_err(dev, "failed to add I2C adapter\n");
> -		goto err;
> -	}
> -
> -err:
>  	if (ret)
>  		clk_disable_unprepare(priv->clk);
>  
> + err:
>  	return ret;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
> index e1e3a85596c562..fbd0fd59f31239 100644
> --- a/drivers/i2c/busses/i2c-wmt.c
> +++ b/drivers/i2c/busses/i2c-wmt.c
> @@ -432,10 +432,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	err = i2c_add_adapter(adap);
> -	if (err) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> +	if (err)
>  		return err;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c_dev);
>  
> diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
> index 4233f5695352fd..263685c7a51287 100644
> --- a/drivers/i2c/busses/i2c-xgene-slimpro.c
> +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
> @@ -418,7 +418,6 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
>  	i2c_set_adapdata(adapter, ctx);
>  	rc = i2c_add_adapter(adapter);
>  	if (rc) {
> -		dev_err(&pdev->dev, "Adapter registeration failed\n");
>  		mbox_free_channel(ctx->mbox_chan);
>  		return rc;
>  	}
> diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
> index 74f54f2f471fa7..66bce3b311a199 100644
> --- a/drivers/i2c/busses/i2c-xiic.c
> +++ b/drivers/i2c/busses/i2c-xiic.c
> @@ -804,7 +804,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
>  	/* add i2c adapter to i2c tree */
>  	ret = i2c_add_adapter(&i2c->adap);
>  	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add adapter\n");
>  		xiic_deinit(i2c);
>  		goto err_clk_dis;
>  	}
> diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
> index 55a7bef1b2e1df..2a972ed7aa0df1 100644
> --- a/drivers/i2c/busses/i2c-xlp9xx.c
> +++ b/drivers/i2c/busses/i2c-xlp9xx.c
> @@ -400,10 +400,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
>  	i2c_set_adapdata(&priv->adapter, priv);
>  
>  	err = i2c_add_adapter(&priv->adapter);
> -	if (err) {
> -		dev_err(&pdev->dev, "failed to add I2C adapter!\n");
> +	if (err)
>  		return err;
> -	}
>  
>  	platform_set_drvdata(pdev, priv);
>  	dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
> diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
> index 613c3a4f2c5142..0968f59b6df586 100644
> --- a/drivers/i2c/busses/i2c-xlr.c
> +++ b/drivers/i2c/busses/i2c-xlr.c
> @@ -432,10 +432,8 @@ static int xlr_i2c_probe(struct platform_device *pdev)
>  
>  	i2c_set_adapdata(&priv->adap, priv);
>  	ret = i2c_add_numbered_adapter(&priv->adap);
> -	if (ret < 0) {
> -		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
> +	if (ret < 0)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, priv);
>  	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
> -- 
> 2.8.1
> 
> 
Acked-by: Neil Horman <nhorman at tuxdriver.com>



From linux at roeck-us.net  Tue Aug  9 06:31:40 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 9 Aug 2016 06:31:40 -0700
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <32d25618-83f6-b876-07b0-adb988516173@roeck-us.net>

On 08/09/2016 04:36 AM, Wolfram Sang wrote:
> The core will do this for us now.
>
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---
[ ... ]

> diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
> index aeead0d27d1007..64318e69089439 100644
> --- a/drivers/i2c/busses/i2c-uniphier-f.c
> +++ b/drivers/i2c/busses/i2c-uniphier-f.c
> @@ -550,15 +550,10 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
>  	}
>
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret) {
> -		dev_err(dev, "failed to add I2C adapter\n");
> -		goto err;
> -	}
> -
> -err:
>  	if (ret)
>  		clk_disable_unprepare(priv->clk);
>
> + err:

You sure about that one ? It leaves the clock enabled in some of the error paths.

>  	return ret;
>  }
>
> diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
> index 475a5eb514e215..94f64cccfdef08 100644
> --- a/drivers/i2c/busses/i2c-uniphier.c
> +++ b/drivers/i2c/busses/i2c-uniphier.c
> @@ -407,15 +407,10 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
>  	}
>
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret) {
> -		dev_err(dev, "failed to add I2C adapter\n");
> -		goto err;
> -	}
> -
> -err:
>  	if (ret)
>  		clk_disable_unprepare(priv->clk);
>
> + err:

Same as above.

Note: I dropped all individuals from Cc:; my mailer refused to accept the reply because there
were too many.

Guenter

>  	return ret;
>  }
>



From wsa at the-dreams.de  Tue Aug  9 06:59:52 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Tue, 9 Aug 2016 15:59:52 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <20160809115740.GA5528@pengutronix.de>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
 <20160809115740.GA5528@pengutronix.de>
Message-ID: <20160809135952.GA1666@katana>

On Tue, Aug 09, 2016 at 01:57:40PM +0200, Uwe Kleine-K?nig wrote:
> Hello Wolfram,
> 
> On Tue, Aug 09, 2016 at 01:36:17PM +0200, Wolfram Sang wrote:
> > The core will do this for us now.
> 
> Would be nice to point out the relevant commit that changed the core in
> the commit log.

I agree, but it was a series of commits[1] so I skipped that idea.

[1] http://www.spinics.net/lists/linux-i2c/msg25496.html

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20160809/42837514/attachment.sig>

From wsa at the-dreams.de  Tue Aug  9 07:39:15 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Tue, 9 Aug 2016 16:39:15 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <32d25618-83f6-b876-07b0-adb988516173@roeck-us.net>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
 <32d25618-83f6-b876-07b0-adb988516173@roeck-us.net>
Message-ID: <20160809143915.GB1666@katana>


> >@@ -550,15 +550,10 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
> > 	}
> >
> > 	ret = i2c_add_adapter(&priv->adap);
> >-	if (ret) {
> >-		dev_err(dev, "failed to add I2C adapter\n");
> >-		goto err;
> >-	}
> >-
> >-err:
> > 	if (ret)
> > 		clk_disable_unprepare(priv->clk);
> >
> >+ err:
> 
> You sure about that one ? It leaves the clock enabled in some of the error paths.

Uh, ehrm, where is the brown paper bag? Thanks, Guenter!

> Note: I dropped all individuals from Cc:; my mailer refused to accept the reply because there
> were too many.

Yes, the disadvantage of not breaking out.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20160809/67eee6cf/attachment.sig>

From ray.jui at broadcom.com  Tue Aug  9 09:15:41 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Tue, 9 Aug 2016 09:15:41 -0700
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <1fc84a39-733e-5867-1f74-26a5076b18fc@broadcom.com>

Hi Wolfram,

On 8/9/2016 4:36 AM, Wolfram Sang wrote:
> The core will do this for us now.
>
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>

[...]

> diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
> index 19c843828fe2ca..8e3477f9297eda 100644
> --- a/drivers/i2c/busses/i2c-bcm-iproc.c
> +++ b/drivers/i2c/busses/i2c-bcm-iproc.c
> @@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
>  	adap->dev.parent = &pdev->dev;
>  	adap->dev.of_node = pdev->dev.of_node;
>
> -	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(iproc_i2c->device, "failed to add adapter\n");
> -		return ret;
> -	}
> -
> -	return 0;
> +	return i2c_add_adapter(adap);
>  }
>
>  static int bcm_iproc_i2c_remove(struct platform_device *pdev)
> diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
> index ac9f47679c3a4b..a5c9098507896b 100644
> --- a/drivers/i2c/busses/i2c-bcm-kona.c
> +++ b/drivers/i2c/busses/i2c-bcm-kona.c
> @@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev)
>  	adap->dev.of_node = pdev->dev.of_node;
>
>  	rc = i2c_add_adapter(adap);
> -	if (rc) {
> -		dev_err(dev->device, "failed to add adapter\n");
> +	if (rc)
>  		return rc;
> -	}
>
>  	dev_info(dev->device, "device registered successfully\n");
>

For both i2c-bcm-iproc.c and i2c-bcm-kona.c:

Acked-by: Ray Jui <ray.jui at broadcom.com>

Thanks,

Ray



From vz at mleia.com  Tue Aug  9 09:36:55 2016
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Tue, 9 Aug 2016 19:36:55 +0300
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <a8dd593f-a38e-9661-22f3-ca5e5dfe53c4@mleia.com>

On 09.08.2016 14:36, Wolfram Sang wrote:
> The core will do this for us now.
> 
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---

For 

>  drivers/i2c/busses/i2c-pnx.c            | 4 +---

[snip]

> diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
> index 7ea67aa46fb730..fd5f9d2bf6d94e 100644
> --- a/drivers/i2c/busses/i2c-pnx.c
> +++ b/drivers/i2c/busses/i2c-pnx.c
> @@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
>  
>  	/* Register this adapter with the I2C subsystem */
>  	ret = i2c_add_numbered_adapter(&alg_data->adapter);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
> +	if (ret < 0)
>  		goto out_clock;
> -	}
>  
>  	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
>  		alg_data->adapter.name, res->start, alg_data->irq);

Acked-by: Vladimir Zapolskiy <vz at mleia.com>

--
With best wishes,
Vladimir


From manabian at gmail.com  Tue Aug  9 09:45:54 2016
From: manabian at gmail.com (Joachim Eastwood)
Date: Tue, 9 Aug 2016 18:45:54 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <CAGhQ9VwJk1WZ2cB6Ag3HXfWEwe1GC-G9L2TWem+Lf5moLDx9uQ@mail.gmail.com>

On 9 August 2016 at 13:36, Wolfram Sang <wsa-dev at sang-engineering.com> wrote:
> Since v4.8-rc1, the I2C core will print detailed information when adding an I2C
> adapter fails. So, drivers can skip this now.
>
> I am still undecided if I apply this as a single patch or break it out. But for
> reviewing, avoiding the patch bomb is probably a good thing.
>
> Should go via subsystem tree, I'd think.
>
> Wolfram Sang (1):
>   i2c: don't print error when adding adapter fails


For
>  drivers/i2c/busses/i2c-lpc2k.c          | 4 +---

Acked-by: Joachim Eastwood <manabian at gmail.com>


regards,
Joachim Eastwood


From Sonic.Zhang at analog.com  Tue Aug  9 19:56:18 2016
From: Sonic.Zhang at analog.com (Zhang, Sonic)
Date: Wed, 10 Aug 2016 02:56:18 +0000
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <20160809125522.GA15676@hmsreliant.think-freely.org>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
 <20160809125522.GA15676@hmsreliant.think-freely.org>
Message-ID: <B168F8A49F4BCF4C84FD23DA5F6363EE80AC7AAE@NWD2MBX7.ad.analog.com>

For i2c-bfin-twi.c

Acked-by: Sonic Zhang <sonic.zhang at analog.com>


Sonic
-----Original Message-----
From: Neil Horman [mailto:nhorman at tuxdriver.com] 
Sent: Tuesday, August 09, 2016 8:55 PM
To: Wolfram Sang
Cc: linux-kernel at vger.kernel.org; linux-i2c at vger.kernel.org; Jean Delvare; Wolfram Sang; Ludovic Desroches; Ray Jui; Scott Branden; Jon Mason; bcm-kernel-feedback-list at broadcom.com; Florian Fainelli; Zhang, Sonic; Brian Norris; Gregory Fong; Michal Simek; S?ren Brinkmann; Jochen Friedrich; Sekhar Nori; Kevin Hilman; Guenter Roeck; Uwe Kleine-K?nig; Kukjin Kim; Krzysztof Kozlowski; Seth Heasley; Joachim Eastwood; Carlo Caione; Alessandro Rubini; Linus Walleij; Peter Korsgaard; Tony Lindgren; Vladimir Zapolskiy; Sylvain Lemieux; Guan Xuetao; Heiko Stuebner; Barry Song; Patrice Chotard; Laxman Dewangan; Stephen Warren; Thierry Reding; Alexandre Courbot; Masahiro Yamada; Tony Prisk; linux-arm-kernel at lists.infradead.org; adi-buildroot-devel at lists.sourceforge.net; linuxppc-dev at lists.ozlabs.org; linux-samsung-soc at vger.kernel.org; linux-amlogic at lists.infradead.org; linux-omap at vger.kernel.org; linux-rockchip at lists.infradead.org; kernel at stlinux.com; linux-tegra at vger.kernel.org
Subject: Re: [PATCH] i2c: don't print error when adding adapter fails

On Tue, Aug 09, 2016 at 01:36:17PM +0200, Wolfram Sang wrote:
> The core will do this for us now.
> 
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---
>  drivers/i2c/busses/i2c-amd756.c         | 5 +----
>  drivers/i2c/busses/i2c-at91.c           | 2 --
>  drivers/i2c/busses/i2c-axxia.c          | 8 +-------
>  drivers/i2c/busses/i2c-bcm-iproc.c      | 8 +-------
>  drivers/i2c/busses/i2c-bcm-kona.c       | 4 +---
>  drivers/i2c/busses/i2c-bfin-twi.c       | 4 +---
>  drivers/i2c/busses/i2c-brcmstb.c        | 4 +---
>  drivers/i2c/busses/i2c-cadence.c        | 4 +---
>  drivers/i2c/busses/i2c-cpm.c            | 4 +---
>  drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +---
>  drivers/i2c/busses/i2c-davinci.c        | 4 +---
>  drivers/i2c/busses/i2c-diolan-u2c.c     | 4 +---
>  drivers/i2c/busses/i2c-dln2.c           | 4 +---
>  drivers/i2c/busses/i2c-efm32.c          | 1 -
>  drivers/i2c/busses/i2c-exynos5.c        | 4 +---
>  drivers/i2c/busses/i2c-hix5hd2.c        | 4 +---
>  drivers/i2c/busses/i2c-i801.c           | 1 -
>  drivers/i2c/busses/i2c-ibm_iic.c        | 4 +---
>  drivers/i2c/busses/i2c-img-scb.c        | 4 +---
>  drivers/i2c/busses/i2c-imx.c            | 4 +---
>  drivers/i2c/busses/i2c-isch.c           | 4 +---
>  drivers/i2c/busses/i2c-ismt.c           | 4 +---
>  drivers/i2c/busses/i2c-jz4780.c         | 4 +---
>  drivers/i2c/busses/i2c-lpc2k.c          | 4 +---
>  drivers/i2c/busses/i2c-meson.c          | 1 -
>  drivers/i2c/busses/i2c-mpc.c            | 4 +---
>  drivers/i2c/busses/i2c-mt65xx.c         | 4 +---
>  drivers/i2c/busses/i2c-mxs.c            | 1 -
>  drivers/i2c/busses/i2c-nforce2.c        | 1 -
>  drivers/i2c/busses/i2c-nomadik.c        | 4 +---
>  drivers/i2c/busses/i2c-ocores.c         | 4 +---
>  drivers/i2c/busses/i2c-octeon.c         | 4 +---
>  drivers/i2c/busses/i2c-omap.c           | 4 +---
>  drivers/i2c/busses/i2c-piix4.c          | 1 -
>  drivers/i2c/busses/i2c-pmcmsp.c         | 4 +---
>  drivers/i2c/busses/i2c-pnx.c            | 4 +---
>  drivers/i2c/busses/i2c-puv3.c           | 5 +----
>  drivers/i2c/busses/i2c-pxa.c            | 4 +---
>  drivers/i2c/busses/i2c-rcar.c           | 4 +---
>  drivers/i2c/busses/i2c-riic.c           | 4 +---
>  drivers/i2c/busses/i2c-rk3x.c           | 4 +---
>  drivers/i2c/busses/i2c-s3c2410.c        | 1 -
>  drivers/i2c/busses/i2c-sh7760.c         | 4 +---
>  drivers/i2c/busses/i2c-sh_mobile.c      | 1 -
>  drivers/i2c/busses/i2c-sirf.c           | 4 +---
>  drivers/i2c/busses/i2c-st.c             | 4 +---
>  drivers/i2c/busses/i2c-stu300.c         | 5 +----
>  drivers/i2c/busses/i2c-tegra.c          | 4 +---
>  drivers/i2c/busses/i2c-uniphier-f.c     | 7 +------
>  drivers/i2c/busses/i2c-uniphier.c       | 7 +------
>  drivers/i2c/busses/i2c-wmt.c            | 4 +---
>  drivers/i2c/busses/i2c-xgene-slimpro.c  | 1 -
>  drivers/i2c/busses/i2c-xiic.c           | 1 -
>  drivers/i2c/busses/i2c-xlp9xx.c         | 4 +---
>  drivers/i2c/busses/i2c-xlr.c            | 4 +---
>  55 files changed, 44 insertions(+), 161 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-amd756.c 
> b/drivers/i2c/busses/i2c-amd756.c index 6c7113d990f882..274908cd1fdeab 
> 100644
> --- a/drivers/i2c/busses/i2c-amd756.c
> +++ b/drivers/i2c/busses/i2c-amd756.c
> @@ -378,11 +378,8 @@ static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  		 amd756_ioport);
>  
>  	error = i2c_add_adapter(&amd756_smbus);
> -	if (error) {
> -		dev_err(&pdev->dev,
> -			"Adapter registration failed, module not inserted\n");
> +	if (error)
>  		goto out_err;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-at91.c 
> b/drivers/i2c/busses/i2c-at91.c index f23372669f770f..03a519d29616d7 
> 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -1118,8 +1118,6 @@ static int at91_twi_probe(struct platform_device 
> *pdev)
>  
>  	rc = i2c_add_numbered_adapter(&dev->adapter);
>  	if (rc) {
> -		dev_err(dev->dev, "Adapter %s registration failed\n",
> -			dev->adapter.name);
>  		clk_disable_unprepare(dev->clk);
>  
>  		pm_runtime_disable(dev->dev);
> diff --git a/drivers/i2c/busses/i2c-axxia.c 
> b/drivers/i2c/busses/i2c-axxia.c index c335cc7852f94e..d3bcaf4ab095d0 
> 100644
> --- a/drivers/i2c/busses/i2c-axxia.c
> +++ b/drivers/i2c/busses/i2c-axxia.c
> @@ -558,13 +558,7 @@ static int axxia_i2c_probe(struct platform_device 
> *pdev)
>  
>  	platform_set_drvdata(pdev, idev);
>  
> -	ret = i2c_add_adapter(&idev->adapter);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> -		return ret;
> -	}
> -
> -	return 0;
> +	return i2c_add_adapter(&idev->adapter);
>  }
>  
>  static int axxia_i2c_remove(struct platform_device *pdev) diff --git 
> a/drivers/i2c/busses/i2c-bcm-iproc.c 
> b/drivers/i2c/busses/i2c-bcm-iproc.c
> index 19c843828fe2ca..8e3477f9297eda 100644
> --- a/drivers/i2c/busses/i2c-bcm-iproc.c
> +++ b/drivers/i2c/busses/i2c-bcm-iproc.c
> @@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
>  	adap->dev.parent = &pdev->dev;
>  	adap->dev.of_node = pdev->dev.of_node;
>  
> -	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(iproc_i2c->device, "failed to add adapter\n");
> -		return ret;
> -	}
> -
> -	return 0;
> +	return i2c_add_adapter(adap);
>  }
>  
>  static int bcm_iproc_i2c_remove(struct platform_device *pdev) diff 
> --git a/drivers/i2c/busses/i2c-bcm-kona.c 
> b/drivers/i2c/busses/i2c-bcm-kona.c
> index ac9f47679c3a4b..a5c9098507896b 100644
> --- a/drivers/i2c/busses/i2c-bcm-kona.c
> +++ b/drivers/i2c/busses/i2c-bcm-kona.c
> @@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev)
>  	adap->dev.of_node = pdev->dev.of_node;
>  
>  	rc = i2c_add_adapter(adap);
> -	if (rc) {
> -		dev_err(dev->device, "failed to add adapter\n");
> +	if (rc)
>  		return rc;
> -	}
>  
>  	dev_info(dev->device, "device registered successfully\n");
>  
> diff --git a/drivers/i2c/busses/i2c-bfin-twi.c 
> b/drivers/i2c/busses/i2c-bfin-twi.c
> index 025686d4164058..29d00c4f7824c2 100644
> --- a/drivers/i2c/busses/i2c-bfin-twi.c
> +++ b/drivers/i2c/busses/i2c-bfin-twi.c
> @@ -685,10 +685,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
>  	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
>  
>  	rc = i2c_add_numbered_adapter(p_adap);
> -	if (rc < 0) {
> -		dev_err(&pdev->dev, "Can't add i2c adapter!\n");
> +	if (rc < 0)
>  		goto out_error;
> -	}
>  
>  	platform_set_drvdata(pdev, iface);
>  
> diff --git a/drivers/i2c/busses/i2c-brcmstb.c 
> b/drivers/i2c/busses/i2c-brcmstb.c
> index 3f5a4d71d3bf32..bc5c176e984aea 100644
> --- a/drivers/i2c/busses/i2c-brcmstb.c
> +++ b/drivers/i2c/busses/i2c-brcmstb.c
> @@ -648,10 +648,8 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
>  	adap->dev.parent = &pdev->dev;
>  	adap->dev.of_node = pdev->dev.of_node;
>  	rc = i2c_add_adapter(adap);
> -	if (rc) {
> -		dev_err(dev->device, "failed to add adapter\n");
> +	if (rc)
>  		goto probe_errorout;
> -	}
>  
>  	dev_info(dev->device, "%s@%dhz registered in %s mode\n",
>  		 int_name ? int_name : " ", dev->clk_freq_hz, diff --git 
> a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
> index 90bbd9f9dd8f77..1cc1e79e958d56 100644
> --- a/drivers/i2c/busses/i2c-cadence.c
> +++ b/drivers/i2c/busses/i2c-cadence.c
> @@ -963,10 +963,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_adapter(&id->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
> +	if (ret < 0)
>  		goto err_clk_dis;
> -	}
>  
>  	/*
>  	 * Cadence I2C controller has a bug wherein it generates diff --git 
> a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 
> ee57c1e865e271..d89bde2c5da256 100644
> --- a/drivers/i2c/busses/i2c-cpm.c
> +++ b/drivers/i2c/busses/i2c-cpm.c
> @@ -665,10 +665,8 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
>  	cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
>  	result = i2c_add_numbered_adapter(&cpm->adap);
>  
> -	if (result < 0) {
> -		dev_err(&ofdev->dev, "Unable to register with I2C\n");
> +	if (result < 0)
>  		goto out_shut;
> -	}
>  
>  	dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
>  		cpm->adap.name);
> diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c 
> b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> index a0d95ff682ae12..cf334a9ec22cb7 100644
> --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> @@ -281,10 +281,8 @@ static int ec_i2c_probe(struct platform_device *pdev)
>  	bus->adap.retries = I2C_MAX_RETRIES;
>  
>  	err = i2c_add_adapter(&bus->adap);
> -	if (err) {
> -		dev_err(dev, "cannot register i2c adapter\n");
> +	if (err)
>  		return err;
> -	}
>  	platform_set_drvdata(pdev, bus);
>  
>  	return err;
> diff --git a/drivers/i2c/busses/i2c-davinci.c 
> b/drivers/i2c/busses/i2c-davinci.c
> index a8bdcb5292f5b3..9e7ef5cf5d495d 100644
> --- a/drivers/i2c/busses/i2c-davinci.c
> +++ b/drivers/i2c/busses/i2c-davinci.c
> @@ -846,10 +846,8 @@ static int davinci_i2c_probe(struct 
> platform_device *pdev)
>  
>  	adap->nr = pdev->id;
>  	r = i2c_add_numbered_adapter(adap);
> -	if (r) {
> -		dev_err(&pdev->dev, "failure adding adapter\n");
> +	if (r)
>  		goto err_unuse_clocks;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c 
> b/drivers/i2c/busses/i2c-diolan-u2c.c
> index b19a310bf9b3e8..f718ee4e3332fe 100644
> --- a/drivers/i2c/busses/i2c-diolan-u2c.c
> +++ b/drivers/i2c/busses/i2c-diolan-u2c.c
> @@ -487,10 +487,8 @@ static int diolan_u2c_probe(struct usb_interface 
> *interface,
>  
>  	/* and finally attach to i2c layer */
>  	ret = i2c_add_adapter(&dev->adapter);
> -	if (ret < 0) {
> -		dev_err(&interface->dev, "failed to add I2C adapter\n");
> +	if (ret < 0)
>  		goto error_free;
> -	}
>  
>  	dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
>  
> diff --git a/drivers/i2c/busses/i2c-dln2.c 
> b/drivers/i2c/busses/i2c-dln2.c index f2eb4f76591fbe..8acda2aa15583c 
> 100644
> --- a/drivers/i2c/busses/i2c-dln2.c
> +++ b/drivers/i2c/busses/i2c-dln2.c
> @@ -228,10 +228,8 @@ static int dln2_i2c_probe(struct platform_device 
> *pdev)
>  
>  	/* and finally attach to i2c layer */
>  	ret = i2c_add_adapter(&dln2->adapter);
> -	if (ret < 0) {
> -		dev_err(dev, "failed to add I2C adapter: %d\n", ret);
> +	if (ret < 0)
>  		goto out_disable;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-efm32.c 
> b/drivers/i2c/busses/i2c-efm32.c index e253598d764c0d..aa336ba89aa3fe 
> 100644
> --- a/drivers/i2c/busses/i2c-efm32.c
> +++ b/drivers/i2c/busses/i2c-efm32.c
> @@ -438,7 +438,6 @@ static int efm32_i2c_probe(struct platform_device 
> *pdev)
>  
>  	ret = i2c_add_adapter(&ddata->adapter);
>  	if (ret) {
> -		dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret);
>  		free_irq(ddata->irq, ddata);
>  
>  err_disable_clk:
> diff --git a/drivers/i2c/busses/i2c-exynos5.c 
> b/drivers/i2c/busses/i2c-exynos5.c
> index c0e3ada028763d..bea607149972d4 100644
> --- a/drivers/i2c/busses/i2c-exynos5.c
> +++ b/drivers/i2c/busses/i2c-exynos5.c
> @@ -796,10 +796,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
>  	exynos5_i2c_reset(i2c);
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
> +	if (ret < 0)
>  		goto err_clk;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c);
>  
> diff --git a/drivers/i2c/busses/i2c-hix5hd2.c 
> b/drivers/i2c/busses/i2c-hix5hd2.c
> index 7c6966434ee7b9..ae7f3180f7e887 100644
> --- a/drivers/i2c/busses/i2c-hix5hd2.c
> +++ b/drivers/i2c/busses/i2c-hix5hd2.c
> @@ -478,10 +478,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
>  	pm_runtime_enable(priv->dev);
>  
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
> +	if (ret < 0)
>  		goto err_runtime;
> -	}
>  
>  	return ret;
>  
> diff --git a/drivers/i2c/busses/i2c-i801.c 
> b/drivers/i2c/busses/i2c-i801.c index 5ef9b733d153fa..22a0ed4de80da0 
> 100644
> --- a/drivers/i2c/busses/i2c-i801.c
> +++ b/drivers/i2c/busses/i2c-i801.c
> @@ -1613,7 +1613,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  		"SMBus I801 adapter at %04lx", priv->smba);
>  	err = i2c_add_adapter(&priv->adapter);
>  	if (err) {
> -		dev_err(&dev->dev, "Failed to add SMBus adapter\n");
>  		i801_acpi_remove(priv);
>  		return err;
>  	}
> diff --git a/drivers/i2c/busses/i2c-ibm_iic.c 
> b/drivers/i2c/busses/i2c-ibm_iic.c
> index cdaa7be2cd1b94..412b91d255ad1d 100644
> --- a/drivers/i2c/busses/i2c-ibm_iic.c
> +++ b/drivers/i2c/busses/i2c-ibm_iic.c
> @@ -751,10 +751,8 @@ static int iic_probe(struct platform_device *ofdev)
>  	adap->timeout = HZ;
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret  < 0) {
> -		dev_err(&ofdev->dev, "failed to register i2c adapter\n");
> +	if (ret  < 0)
>  		goto error_cleanup;
> -	}
>  
>  	dev_info(&ofdev->dev, "using %s mode\n",
>  		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); diff 
> --git a/drivers/i2c/busses/i2c-img-scb.c 
> b/drivers/i2c/busses/i2c-img-scb.c
> index ea20425b697217..db8e8b40569d98 100644
> --- a/drivers/i2c/busses/i2c-img-scb.c
> +++ b/drivers/i2c/busses/i2c-img-scb.c
> @@ -1394,10 +1394,8 @@ static int img_i2c_probe(struct platform_device *pdev)
>  		goto disable_clk;
>  
>  	ret = i2c_add_numbered_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> +	if (ret < 0)
>  		goto disable_clk;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-imx.c 
> b/drivers/i2c/busses/i2c-imx.c index 1844bc9f7cd5a2..cb11eee9567318 
> 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -1129,10 +1129,8 @@ static int i2c_imx_probe(struct platform_device 
> *pdev)
>  
>  	/* Add I2C adapter */
>  	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "registration failed\n");
> +	if (ret < 0)
>  		goto rpm_disable;
> -	}
>  
>  	pm_runtime_mark_last_busy(&pdev->dev);
>  	pm_runtime_put_autosuspend(&pdev->dev);
> diff --git a/drivers/i2c/busses/i2c-isch.c 
> b/drivers/i2c/busses/i2c-isch.c index c2f25f19d76f9b..0cf1379f4e8091 
> 100644
> --- a/drivers/i2c/busses/i2c-isch.c
> +++ b/drivers/i2c/busses/i2c-isch.c
> @@ -288,10 +288,8 @@ static int smbus_sch_probe(struct platform_device *dev)
>  		"SMBus SCH adapter at %04x", sch_smba);
>  
>  	retval = i2c_add_adapter(&sch_adapter);
> -	if (retval) {
> -		dev_err(&dev->dev, "Couldn't register adapter!\n");
> +	if (retval)
>  		sch_smba = 0;
> -	}
>  
>  	return retval;
>  }
> diff --git a/drivers/i2c/busses/i2c-ismt.c 
> b/drivers/i2c/busses/i2c-ismt.c index 1c870771009840..f573448d213216 
> 100644
> --- a/drivers/i2c/busses/i2c-ismt.c
> +++ b/drivers/i2c/busses/i2c-ismt.c
> @@ -922,10 +922,8 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  		return err;
>  
>  	err = i2c_add_adapter(&priv->adapter);
> -	if (err) {
> -		dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
> +	if (err)
>  		return -ENODEV;
> -	}
>  	return 0;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-jz4780.c 
> b/drivers/i2c/busses/i2c-jz4780.c index cd9872594fe2a0..b8ea62105f42c9 
> 100644
> --- a/drivers/i2c/busses/i2c-jz4780.c
> +++ b/drivers/i2c/busses/i2c-jz4780.c
> @@ -798,10 +798,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
>  		goto err;
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Failed to add bus\n");
> +	if (ret < 0)
>  		goto err;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-lpc2k.c 
> b/drivers/i2c/busses/i2c-lpc2k.c index 586a15205e61de..9b1fef455a895d 
> 100644
> --- a/drivers/i2c/busses/i2c-lpc2k.c
> +++ b/drivers/i2c/busses/i2c-lpc2k.c
> @@ -432,10 +432,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
>  	i2c->adap.dev.of_node = pdev->dev.of_node;
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add adapter!\n");
> +	if (ret < 0)
>  		goto fail_clk;
> -	}
>  
>  	dev_info(&pdev->dev, "LPC2K I2C adapter\n");
>  
> diff --git a/drivers/i2c/busses/i2c-meson.c 
> b/drivers/i2c/busses/i2c-meson.c index 71d3929adf54ed..102d2b91771f35 
> 100644
> --- a/drivers/i2c/busses/i2c-meson.c
> +++ b/drivers/i2c/busses/i2c-meson.c
> @@ -453,7 +453,6 @@ static int meson_i2c_probe(struct platform_device 
> *pdev)
>  
>  	ret = i2c_add_adapter(&i2c->adap);
>  	if (ret < 0) {
> -		dev_err(&pdev->dev, "can't register adapter\n");
>  		clk_unprepare(i2c->clk);
>  		return ret;
>  	}
> diff --git a/drivers/i2c/busses/i2c-mpc.c 
> b/drivers/i2c/busses/i2c-mpc.c index 48ecffecc0eda3..565a49a0c56410 
> 100644
> --- a/drivers/i2c/busses/i2c-mpc.c
> +++ b/drivers/i2c/busses/i2c-mpc.c
> @@ -737,10 +737,8 @@ static int fsl_i2c_probe(struct platform_device *op)
>  	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
>  
>  	result = i2c_add_adapter(&i2c->adap);
> -	if (result < 0) {
> -		dev_err(i2c->dev, "failed to add adapter\n");
> +	if (result < 0)
>  		goto fail_add;
> -	}
>  
>  	return result;
>  
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> b/drivers/i2c/busses/i2c-mt65xx.c index d9373e60be8ae3..4a7d9bc2142ba3 
> 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -786,10 +786,8 @@ static int mtk_i2c_probe(struct platform_device 
> *pdev)
>  
>  	i2c_set_adapdata(&i2c->adap, i2c);
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c);
>  
> diff --git a/drivers/i2c/busses/i2c-mxs.c 
> b/drivers/i2c/busses/i2c-mxs.c index 033846cdf26622..5738556b6aac20 
> 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -868,7 +868,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
>  	i2c_set_adapdata(adap, i2c);
>  	err = i2c_add_numbered_adapter(adap);
>  	if (err) {
> -		dev_err(dev, "Failed to add adapter (%d)\n", err);
>  		writel(MXS_I2C_CTRL0_SFTRST,
>  				i2c->regs + MXS_I2C_CTRL0_SET);
>  		return err;
> diff --git a/drivers/i2c/busses/i2c-nforce2.c 
> b/drivers/i2c/busses/i2c-nforce2.c
> index 42fcc9458432f8..374b35e7e450ce 100644
> --- a/drivers/i2c/busses/i2c-nforce2.c
> +++ b/drivers/i2c/busses/i2c-nforce2.c
> @@ -366,7 +366,6 @@ static int nforce2_probe_smb(struct pci_dev *dev, 
> int bar, int alt_reg,
>  
>  	error = i2c_add_adapter(&smbus->adapter);
>  	if (error) {
> -		dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
>  		release_region(smbus->base, smbus->size);
>  		return error;
>  	}
> diff --git a/drivers/i2c/busses/i2c-nomadik.c 
> b/drivers/i2c/busses/i2c-nomadik.c
> index bcd17e8cbcb4b3..da6609d628487b 100644
> --- a/drivers/i2c/busses/i2c-nomadik.c
> +++ b/drivers/i2c/busses/i2c-nomadik.c
> @@ -1046,10 +1046,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
>  		 adap->name, dev->virtbase);
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(&adev->dev, "failed to add adapter\n");
> +	if (ret)
>  		goto err_no_adap;
> -	}
>  
>  	pm_runtime_put(&adev->dev);
>  
> diff --git a/drivers/i2c/busses/i2c-ocores.c 
> b/drivers/i2c/busses/i2c-ocores.c index dfa7a4b4a91d78..92692349d0c328 
> 100644
> --- a/drivers/i2c/busses/i2c-ocores.c
> +++ b/drivers/i2c/busses/i2c-ocores.c
> @@ -492,10 +492,8 @@ static int ocores_i2c_probe(struct 
> platform_device *pdev)
>  
>  	/* add i2c adapter to i2c tree */
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	/* add in known devices to the bus */
>  	if (pdata) {
> diff --git a/drivers/i2c/busses/i2c-octeon.c 
> b/drivers/i2c/busses/i2c-octeon.c index 30ae35146723a4..b75d2da79b27c5 
> 100644
> --- a/drivers/i2c/busses/i2c-octeon.c
> +++ b/drivers/i2c/busses/i2c-octeon.c
> @@ -1213,10 +1213,8 @@ static int octeon_i2c_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, i2c);
>  
>  	result = i2c_add_adapter(&i2c->adap);
> -	if (result < 0) {
> -		dev_err(i2c->dev, "failed to add adapter\n");
> +	if (result < 0)
>  		goto out;
> -	}
>  	dev_info(i2c->dev, "probed\n");
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-omap.c 
> b/drivers/i2c/busses/i2c-omap.c index ab1279b8e2407a..c7da0c42baeefa 
> 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -1425,10 +1425,8 @@ omap_i2c_probe(struct platform_device *pdev)
>  	/* i2c device drivers may be active on return from add_adapter() */
>  	adap->nr = pdev->id;
>  	r = i2c_add_numbered_adapter(adap);
> -	if (r) {
> -		dev_err(omap->dev, "failure adding adapter\n");
> +	if (r)
>  		goto err_unuse_clocks;
> -	}
>  
>  	dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
>  		 major, minor, omap->speed);
> diff --git a/drivers/i2c/busses/i2c-piix4.c 
> b/drivers/i2c/busses/i2c-piix4.c index 23d1c167b5d752..c2268cdf38e823 
> 100644
> --- a/drivers/i2c/busses/i2c-piix4.c
> +++ b/drivers/i2c/busses/i2c-piix4.c
> @@ -694,7 +694,6 @@ static int piix4_add_adapter(struct pci_dev *dev, 
> unsigned short smba,
>  
>  	retval = i2c_add_adapter(adap);
>  	if (retval) {
> -		dev_err(&dev->dev, "Couldn't register adapter!\n");
>  		kfree(adapdata);
>  		kfree(adap);
>  		release_region(smba, SMBIOSIZE);
> diff --git a/drivers/i2c/busses/i2c-pmcmsp.c 
> b/drivers/i2c/busses/i2c-pmcmsp.c index 2c40edbf6224eb..217c78711d6501 
> 100644
> --- a/drivers/i2c/busses/i2c-pmcmsp.c
> +++ b/drivers/i2c/busses/i2c-pmcmsp.c
> @@ -329,10 +329,8 @@ static int pmcmsptwi_probe(struct platform_device *pldev)
>  	i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
>  
>  	rc = i2c_add_adapter(&pmcmsptwi_adapter);
> -	if (rc) {
> -		dev_err(&pldev->dev, "Unable to register I2C adapter\n");
> +	if (rc)
>  		goto ret_unmap;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-pnx.c 
> b/drivers/i2c/busses/i2c-pnx.c index 7ea67aa46fb730..fd5f9d2bf6d94e 
> 100644
> --- a/drivers/i2c/busses/i2c-pnx.c
> +++ b/drivers/i2c/busses/i2c-pnx.c
> @@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device 
> *pdev)
>  
>  	/* Register this adapter with the I2C subsystem */
>  	ret = i2c_add_numbered_adapter(&alg_data->adapter);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
> +	if (ret < 0)
>  		goto out_clock;
> -	}
>  
>  	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
>  		alg_data->adapter.name, res->start, alg_data->irq); diff --git 
> a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c index 
> 82b6f02544dae7..0c8b1571886d5b 100644
> --- a/drivers/i2c/busses/i2c-puv3.c
> +++ b/drivers/i2c/busses/i2c-puv3.c
> @@ -212,11 +212,8 @@ static int puv3_i2c_probe(struct platform_device 
> *pdev)
>  
>  	adapter->nr = pdev->id;
>  	rc = i2c_add_numbered_adapter(adapter);
> -	if (rc) {
> -		dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
> -				adapter->name);
> +	if (rc)
>  		goto fail_add_adapter;
> -	}
>  
>  	dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
>  	return 0;
> diff --git a/drivers/i2c/busses/i2c-pxa.c 
> b/drivers/i2c/busses/i2c-pxa.c index 0d351954db02b9..e28b825b043378 
> 100644
> --- a/drivers/i2c/busses/i2c-pxa.c
> +++ b/drivers/i2c/busses/i2c-pxa.c
> @@ -1292,10 +1292,8 @@ static int i2c_pxa_probe(struct platform_device 
> *dev)  #endif
>  
>  	ret = i2c_add_numbered_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&dev->dev, "failed to add bus: %d\n", ret);
> +	if (ret < 0)
>  		goto ereqirq;
> -	}
>  
>  	platform_set_drvdata(dev, i2c);
>  
> diff --git a/drivers/i2c/busses/i2c-rcar.c 
> b/drivers/i2c/busses/i2c-rcar.c index 52407f3c9e1cce..400e344704d273 
> 100644
> --- a/drivers/i2c/busses/i2c-rcar.c
> +++ b/drivers/i2c/busses/i2c-rcar.c
> @@ -875,10 +875,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, priv);
>  
>  	ret = i2c_add_numbered_adapter(adap);
> -	if (ret < 0) {
> -		dev_err(dev, "reg adap failed: %d\n", ret);
> +	if (ret < 0)
>  		goto out_pm_disable;
> -	}
>  
>  	dev_info(dev, "probed\n");
>  
> diff --git a/drivers/i2c/busses/i2c-riic.c 
> b/drivers/i2c/busses/i2c-riic.c index d7e3af67154373..6263ea82d6ac3b 
> 100644
> --- a/drivers/i2c/busses/i2c-riic.c
> +++ b/drivers/i2c/busses/i2c-riic.c
> @@ -383,10 +383,8 @@ static int riic_i2c_probe(struct platform_device 
> *pdev)
>  
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, riic);
>  
> diff --git a/drivers/i2c/busses/i2c-rk3x.c 
> b/drivers/i2c/busses/i2c-rk3x.c index 2bc8b01153d619..3b87afe82f6394 
> 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -1303,10 +1303,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>  	rk3x_i2c_adapt_div(i2c, clk_rate);
>  
>  	ret = i2c_add_adapter(&i2c->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Could not register adapter\n");
> +	if (ret < 0)
>  		goto err_clk_notifier;
> -	}
>  
>  	dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", 
> i2c->regs);
>  
> diff --git a/drivers/i2c/busses/i2c-s3c2410.c 
> b/drivers/i2c/busses/i2c-s3c2410.c
> index 38dc1cacfd8bba..499af26e736e7e 100644
> --- a/drivers/i2c/busses/i2c-s3c2410.c
> +++ b/drivers/i2c/busses/i2c-s3c2410.c
> @@ -1215,7 +1215,6 @@ static int s3c24xx_i2c_probe(struct 
> platform_device *pdev)
>  
>  	ret = i2c_add_numbered_adapter(&i2c->adap);
>  	if (ret < 0) {
> -		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
>  		pm_runtime_disable(&pdev->dev);
>  		s3c24xx_i2c_deregister_cpufreq(i2c);
>  		clk_unprepare(i2c->clk);
> diff --git a/drivers/i2c/busses/i2c-sh7760.c 
> b/drivers/i2c/busses/i2c-sh7760.c index 24968384b4014f..c2005c789d2b09 
> 100644
> --- a/drivers/i2c/busses/i2c-sh7760.c
> +++ b/drivers/i2c/busses/i2c-sh7760.c
> @@ -510,10 +510,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_numbered_adapter(&id->adap);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
> +	if (ret < 0)
>  		goto out4;
> -	}
>  
>  	platform_set_drvdata(pdev, id);
>  
> diff --git a/drivers/i2c/busses/i2c-sh_mobile.c 
> b/drivers/i2c/busses/i2c-sh_mobile.c
> index 6fb3e264599229..50f276e8d17967 100644
> --- a/drivers/i2c/busses/i2c-sh_mobile.c
> +++ b/drivers/i2c/busses/i2c-sh_mobile.c
> @@ -981,7 +981,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
>  	ret = i2c_add_numbered_adapter(adap);
>  	if (ret < 0) {
>  		sh_mobile_i2c_release_dma(pd);
> -		dev_err(&dev->dev, "cannot add numbered adapter\n");
>  		return ret;
>  	}
>  
> diff --git a/drivers/i2c/busses/i2c-sirf.c 
> b/drivers/i2c/busses/i2c-sirf.c index 792a42bdd335b9..95e81d0f72b4d2 
> 100644
> --- a/drivers/i2c/busses/i2c-sirf.c
> +++ b/drivers/i2c/busses/i2c-sirf.c
> @@ -387,10 +387,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
>  		writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
>  
>  	err = i2c_add_numbered_adapter(adap);
> -	if (err < 0) {
> -		dev_err(&pdev->dev, "Can't add new i2c adapter\n");
> +	if (err < 0)
>  		goto out;
> -	}
>  
>  	clk_disable(clk);
>  
> diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c 
> index 944ec420508487..1371547ce1a3a8 100644
> --- a/drivers/i2c/busses/i2c-st.c
> +++ b/drivers/i2c/busses/i2c-st.c
> @@ -874,10 +874,8 @@ static int st_i2c_probe(struct platform_device *pdev)
>  	init_completion(&i2c_dev->complete);
>  
>  	ret = i2c_add_adapter(adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c_dev);
>  
> diff --git a/drivers/i2c/busses/i2c-stu300.c 
> b/drivers/i2c/busses/i2c-stu300.c index 460c134832ac30..dc63236b45b216 
> 100644
> --- a/drivers/i2c/busses/i2c-stu300.c
> +++ b/drivers/i2c/busses/i2c-stu300.c
> @@ -920,11 +920,8 @@ static int stu300_probe(struct platform_device 
> *pdev)
>  
>  	/* i2c device drivers may be active on return from add_adapter() */
>  	ret = i2c_add_numbered_adapter(adap);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failure adding ST Micro DDC "
> -		       "I2C adapter\n");
> +	if (ret)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, dev);
>  	dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n", diff --git 
> a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c 
> index b126dbaa47e370..d9979da11485ae 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -932,10 +932,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
>  	i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
>  
>  	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
> +	if (ret)
>  		goto disable_div_clk;
> -	}
>  
>  	return 0;
>  
> diff --git a/drivers/i2c/busses/i2c-uniphier-f.c 
> b/drivers/i2c/busses/i2c-uniphier-f.c
> index aeead0d27d1007..64318e69089439 100644
> --- a/drivers/i2c/busses/i2c-uniphier-f.c
> +++ b/drivers/i2c/busses/i2c-uniphier-f.c
> @@ -550,15 +550,10 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret) {
> -		dev_err(dev, "failed to add I2C adapter\n");
> -		goto err;
> -	}
> -
> -err:
>  	if (ret)
>  		clk_disable_unprepare(priv->clk);
>  
> + err:
>  	return ret;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-uniphier.c 
> b/drivers/i2c/busses/i2c-uniphier.c
> index 475a5eb514e215..94f64cccfdef08 100644
> --- a/drivers/i2c/busses/i2c-uniphier.c
> +++ b/drivers/i2c/busses/i2c-uniphier.c
> @@ -407,15 +407,10 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	ret = i2c_add_adapter(&priv->adap);
> -	if (ret) {
> -		dev_err(dev, "failed to add I2C adapter\n");
> -		goto err;
> -	}
> -
> -err:
>  	if (ret)
>  		clk_disable_unprepare(priv->clk);
>  
> + err:
>  	return ret;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-wmt.c 
> b/drivers/i2c/busses/i2c-wmt.c index e1e3a85596c562..fbd0fd59f31239 
> 100644
> --- a/drivers/i2c/busses/i2c-wmt.c
> +++ b/drivers/i2c/busses/i2c-wmt.c
> @@ -432,10 +432,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
>  	}
>  
>  	err = i2c_add_adapter(adap);
> -	if (err) {
> -		dev_err(&pdev->dev, "failed to add adapter\n");
> +	if (err)
>  		return err;
> -	}
>  
>  	platform_set_drvdata(pdev, i2c_dev);
>  
> diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c 
> b/drivers/i2c/busses/i2c-xgene-slimpro.c
> index 4233f5695352fd..263685c7a51287 100644
> --- a/drivers/i2c/busses/i2c-xgene-slimpro.c
> +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
> @@ -418,7 +418,6 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
>  	i2c_set_adapdata(adapter, ctx);
>  	rc = i2c_add_adapter(adapter);
>  	if (rc) {
> -		dev_err(&pdev->dev, "Adapter registeration failed\n");
>  		mbox_free_channel(ctx->mbox_chan);
>  		return rc;
>  	}
> diff --git a/drivers/i2c/busses/i2c-xiic.c 
> b/drivers/i2c/busses/i2c-xiic.c index 74f54f2f471fa7..66bce3b311a199 
> 100644
> --- a/drivers/i2c/busses/i2c-xiic.c
> +++ b/drivers/i2c/busses/i2c-xiic.c
> @@ -804,7 +804,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
>  	/* add i2c adapter to i2c tree */
>  	ret = i2c_add_adapter(&i2c->adap);
>  	if (ret) {
> -		dev_err(&pdev->dev, "Failed to add adapter\n");
>  		xiic_deinit(i2c);
>  		goto err_clk_dis;
>  	}
> diff --git a/drivers/i2c/busses/i2c-xlp9xx.c 
> b/drivers/i2c/busses/i2c-xlp9xx.c index 55a7bef1b2e1df..2a972ed7aa0df1 
> 100644
> --- a/drivers/i2c/busses/i2c-xlp9xx.c
> +++ b/drivers/i2c/busses/i2c-xlp9xx.c
> @@ -400,10 +400,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
>  	i2c_set_adapdata(&priv->adapter, priv);
>  
>  	err = i2c_add_adapter(&priv->adapter);
> -	if (err) {
> -		dev_err(&pdev->dev, "failed to add I2C adapter!\n");
> +	if (err)
>  		return err;
> -	}
>  
>  	platform_set_drvdata(pdev, priv);
>  	dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr); diff 
> --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c 
> index 613c3a4f2c5142..0968f59b6df586 100644
> --- a/drivers/i2c/busses/i2c-xlr.c
> +++ b/drivers/i2c/busses/i2c-xlr.c
> @@ -432,10 +432,8 @@ static int xlr_i2c_probe(struct platform_device 
> *pdev)
>  
>  	i2c_set_adapdata(&priv->adap, priv);
>  	ret = i2c_add_numbered_adapter(&priv->adap);
> -	if (ret < 0) {
> -		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
> +	if (ret < 0)
>  		return ret;
> -	}
>  
>  	platform_set_drvdata(pdev, priv);
>  	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
> --
> 2.8.1
> 
> 
Acked-by: Neil Horman <nhorman at tuxdriver.com>




From ludovic.desroches at atmel.com  Tue Aug  9 23:17:15 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Wed, 10 Aug 2016 08:17:15 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <20160810061715.GH12809@odux.rfo.atmel.com>

On Tue, Aug 09, 2016 at 01:36:17PM +0200, Wolfram Sang wrote:
> The core will do this for us now.
> 
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---

[...]

>  drivers/i2c/busses/i2c-at91.c           | 2 --

Acked-by: Ludovic Desroches <ludovic.desroches at atmel.com>

[...]

> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
> index f23372669f770f..03a519d29616d7 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -1118,8 +1118,6 @@ static int at91_twi_probe(struct platform_device *pdev)
>  
>  	rc = i2c_add_numbered_adapter(&dev->adapter);
>  	if (rc) {
> -		dev_err(dev->dev, "Adapter %s registration failed\n",
> -			dev->adapter.name);
>  		clk_disable_unprepare(dev->clk);
>  
>  		pm_runtime_disable(dev->dev);


From patrice.chotard at st.com  Tue Aug  9 23:50:31 2016
From: patrice.chotard at st.com (Patrice Chotard)
Date: Wed, 10 Aug 2016 08:50:31 +0200
Subject: [STLinux Kernel] [PATCH] i2c: don't print error when adding
 adapter fails
In-Reply-To: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <dda2b522-0257-17c7-1332-cbc026b74603@st.com>

On 08/09/2016 01:36 PM, Wolfram Sang wrote:
> Since v4.8-rc1, the I2C core will print detailed information when adding an I2C
> adapter fails. So, drivers can skip this now.
>
> I am still undecided if I apply this as a single patch or break it out. But for
> reviewing, avoiding the patch bomb is probably a good thing.
>
> Should go via subsystem tree, I'd think.
>
> Wolfram Sang (1):
>   i2c: don't print error when adding adapter fails
>
>  drivers/i2c/busses/i2c-st.c             | 4 +---
>

For i2c-st.c

Acked-by: Patrice Chotard <patrice.chotard at st.com>

Thanks


From k.kozlowski at samsung.com  Wed Aug 10 01:32:00 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 10 Aug 2016 10:32:00 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <35fd8f31-2fa1-7220-8ed9-13bad638fe6f@samsung.com>

On 08/09/2016 01:36 PM, Wolfram Sang wrote:
> The core will do this for us now.
> 
> Signed-off-by: Wolfram Sang <wsa-dev at sang-engineering.com>
> ---

(...)

>  drivers/i2c/busses/i2c-exynos5.c        | 4 +---
>  drivers/i2c/busses/i2c-s3c2410.c        | 1 -

For Exynos and S3C2410:
Acked-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof


From ldewangan at nvidia.com  Wed Aug 10 01:34:57 2016
From: ldewangan at nvidia.com (Laxman Dewangan)
Date: Wed, 10 Aug 2016 14:04:57 +0530
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
 <1470742581-12971-2-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <57AAE731.8090603@nvidia.com>


On Tuesday 09 August 2016 05:06 PM, Wolfram Sang wrote:
> The core will do this for us now.
>
For i2c-tegra.c

Acked-by: Laxman Dewangan <ldewangan at nvidia.com>



From frank.wang at rock-chips.com  Wed Aug 10 03:19:59 2016
From: frank.wang at rock-chips.com (Frank Wang)
Date: Wed, 10 Aug 2016 18:19:59 +0800
Subject: [RFC PATCH v3 0/8] scpi: Add SCPI registry to handle legacy
 protocol
In-Reply-To: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <d7f260f8-5e1a-a16a-fed9-2f6d8aa8f28f@rock-chips.com>

Hi Neil,

On 2016/8/9 18:29, Neil Armstrong wrote:
> This patchset aims to support the legacy SCPI firmware implementation that
> was
> delivered as early technology preview for the JUNO platform.
>
> Finally a stable, maintained and public implementation for the SCPI protocol
> has been upstreamed part of the JUNO support and it is the recommended way
> of implementing SCP communication on ARMv8 platforms.
>
> The Amlogic GXBB platform is using this legacy protocol, as the RK3368 &
> RK3399
> platforms. Only the GXBB example is provided here, but it's unclear if other
> Amlogic ARMv8 based SoCs uses this legacy procotol.
>
> In order to support the legacy protocol :
>   - Move the scpi_get_ops to a thin registry layer
>   - Change the arm_scpi.c to use the registry layer
>   - Add a separate config option to build the registry layer
>   - Add the legacy SCPI driver based on the new implementation
>   - For example, add the Amlogic GXBB MHU and SCPI DT cpufreq & sensors nodes
>
> Changes since RFC v2 at https://lkml.org/lkml/2016/6/21/324 :
>   - Moved MHU to a separate patchset posted at
> http://lkml.kernel.org/r/1470732737-18391-1-git-send-email-narmstrong at baylib
> re.com
>   - Added a vendor send_message callback into scpi_ops to implement vendor
> commands
>   - Implement EXT commands on arm scpi as vendor send_command
>   - Added Rockchip variant mailbox handling

Two questions,

1. For legacy_scpi, I saw you have implemented .vendor_send_message api, 
however, it seems that does not distinguish standard and extended 
command, so it may be misleading if the vendor send out a non-standard 
command from their own driver module.

2. For arm_scpi, it have already distinguished standard and extended 
command, but unfortunately, there was no rockchip_scpi_xfer structure 
something like in legacy_scpi driver, so if some vendor (just like 
Rockchip :-)) wanna switch the driver from legacy_scpi to arm_scpi, 
maybe this is a bit problem, how do you think?


BR.
Frank

> Initial RFC discution tread can be found at
> https://lkml.org/lkml/2016/5/26/111
>
> @Sudeep: I know you wished I merged the legacy into the arm_scpi, but can
> you take a look at the vendor extension and how I implemented the rockchip
> mailbox handling ?
>
> Neil Armstrong (8):
>    firmware: Add a SCPI registry to handle multiple implementations
>    firmware: scpi: Switch arm_scpi to use new registry
>    scpi: Add vendor_send_message to enable access to vendor commands
>    firmware: arm_scpi: Enable vendor_send_message as ext commands
>    firmware: Add legacy SCPI protocol driver
>    dt-bindings: arm: Update arm,scpi bindings with Meson GXBB SCPI
>    ARM64: dts: meson-gxbb: Add SRAM node
>    ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes
>
>   Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
>   arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++
>   drivers/firmware/Kconfig                           |  24 +
>   drivers/firmware/Makefile                          |   2 +
>   drivers/firmware/arm_scpi.c                        |  40 +-
>   drivers/firmware/legacy_scpi.c                     | 710
> +++++++++++++++++++++
>   drivers/firmware/scpi.c                            |  94 +++
>   include/linux/scpi_protocol.h                      |  20 +-
>   8 files changed, 928 insertions(+), 15 deletions(-)
>   create mode 100644 drivers/firmware/legacy_scpi.c
>   create mode 100644 drivers/firmware/scpi.c
>




From robh at kernel.org  Wed Aug 10 13:44:37 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 10 Aug 2016 15:44:37 -0500
Subject: [PATCH 2/3] dt-bindings: mailbox: Add Amlogic Meson MHU Bindings
In-Reply-To: <1470732737-18391-3-git-send-email-narmstrong@baylibre.com>
References: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
 <1470732737-18391-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160810204437.GA13003@rob-hp-laptop>

On Tue, Aug 09, 2016 at 10:52:16AM +0200, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  .../devicetree/bindings/mailbox/meson-mhu.txt      | 33 ++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/meson-mhu.txt

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


From robh at kernel.org  Wed Aug 10 14:40:54 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 10 Aug 2016 16:40:54 -0500
Subject: [PATCH 2/3] dt-bindings: clock: reset: Add GXBB AO Clock and
 Reset Bindings
In-Reply-To: <1470734008-18849-3-git-send-email-narmstrong@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
 <1470734008-18849-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160810214054.GA14766@rob-hp-laptop>

On Tue, Aug 09, 2016 at 11:13:27AM +0200, Neil Armstrong wrote:
> Add documentations and dt-bindings headers for the AO clock and reset
> controller.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  .../bindings/clock/amlogic,gxbb-aoclkc.txt         | 45 +++++++++++++++
>  include/dt-bindings/clock/gxbb-aoclkc.h            | 66 ++++++++++++++++++++++
>  include/dt-bindings/reset/gxbb-aoclkc.h            | 66 ++++++++++++++++++++++
>  3 files changed, 177 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
>  create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
>  create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h

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


From narmstrong at baylibre.com  Thu Aug 11 01:35:53 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 11 Aug 2016 10:35:53 +0200
Subject: [RFC PATCH v3 0/8] scpi: Add SCPI registry to handle legacy
 protocol
In-Reply-To: <d7f260f8-5e1a-a16a-fed9-2f6d8aa8f28f@rock-chips.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
 <d7f260f8-5e1a-a16a-fed9-2f6d8aa8f28f@rock-chips.com>
Message-ID: <c5b3fcb1-368c-5be6-fe71-1f2d444b83e0@baylibre.com>

Hi Frank,

On 08/10/2016 12:19 PM, Frank Wang wrote:
> Hi Neil,
> 
> On 2016/8/9 18:29, Neil Armstrong wrote:

[...]

>>
>> Changes since RFC v2 at https://lkml.org/lkml/2016/6/21/324 :
>>   - Moved MHU to a separate patchset posted at
>> http://lkml.kernel.org/r/1470732737-18391-1-git-send-email-narmstrong at baylib
>> re.com
>>   - Added a vendor send_message callback into scpi_ops to implement vendor
>> commands
>>   - Implement EXT commands on arm scpi as vendor send_command
>>   - Added Rockchip variant mailbox handling
> 
> Two questions,
> 
> 1. For legacy_scpi, I saw you have implemented .vendor_send_message api, however, it seems that does not distinguish standard and extended command, so it may be misleading if the vendor send out a non-standard command from their own driver module.

Actually, the vendor_send_message is for non-standard command, and since it's vendor code is should be specific to the platform and won't have any effect on other platforms.
DDR and other rockchip specific command shoudl go through this API.
The legacy_scpi code does not distinguish standard and extended command since nothing was made into the protocol for this.

> 
> 2. For arm_scpi, it have already distinguished standard and extended command, but unfortunately, there was no rockchip_scpi_xfer structure something like in legacy_scpi driver, so if some vendor (just like Rockchip :-)) wanna switch the driver from legacy_scpi to arm_scpi, maybe this is a bit problem, how do you think?

Yes, it could be added the same way it was added to legacy_scpi, Sudeep made the assumption it would work with any mailbox controller, but since the mailbox framework does not make any assumption about the data type between the controller and the client, such adaptation is necessary.

Neil
> 
> BR.
> Frank
> 
>> Initial RFC discution tread can be found at
>> https://lkml.org/lkml/2016/5/26/111
>>
>> @Sudeep: I know you wished I merged the legacy into the arm_scpi, but can
>> you take a look at the vendor extension and how I implemented the rockchip
>> mailbox handling ?
>>
>> Neil Armstrong (8):
>>    firmware: Add a SCPI registry to handle multiple implementations
>>    firmware: scpi: Switch arm_scpi to use new registry
>>    scpi: Add vendor_send_message to enable access to vendor commands
>>    firmware: arm_scpi: Enable vendor_send_message as ext commands
>>    firmware: Add legacy SCPI protocol driver
>>    dt-bindings: arm: Update arm,scpi bindings with Meson GXBB SCPI
>>    ARM64: dts: meson-gxbb: Add SRAM node
>>    ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes
>>
>>   Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
>>   arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++
>>   drivers/firmware/Kconfig                           |  24 +
>>   drivers/firmware/Makefile                          |   2 +
>>   drivers/firmware/arm_scpi.c                        |  40 +-
>>   drivers/firmware/legacy_scpi.c                     | 710
>> +++++++++++++++++++++
>>   drivers/firmware/scpi.c                            |  94 +++
>>   include/linux/scpi_protocol.h                      |  20 +-
>>   8 files changed, 928 insertions(+), 15 deletions(-)
>>   create mode 100644 drivers/firmware/legacy_scpi.c
>>   create mode 100644 drivers/firmware/scpi.c
>>
> 
> 



From narmstrong at baylibre.com  Thu Aug 11 09:15:31 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 11 Aug 2016 18:15:31 +0200
Subject: [PATCH 1/3] mailbox: Add Platform Message-Handling-Unit variant
 driver
In-Reply-To: <1470732737-18391-2-git-send-email-narmstrong@baylibre.com>
References: <1470732737-18391-1-git-send-email-narmstrong@baylibre.com>
 <1470732737-18391-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <c21f4740-47bb-8c4b-f18e-8db801ee7fc3@baylibre.com>

On 08/09/2016 10:52 AM, Neil Armstrong wrote:
> Add Message-Handling-Unit driver for platform variants as mailbox controller.
> Actually, only the Amlogic Meson GXBB SoC MHU is supported.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/mailbox/Kconfig        |  10 ++
>  drivers/mailbox/Makefile       |   2 +
>  drivers/mailbox/platform_mhu.c | 203 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 215 insertions(+)
>  create mode 100644 drivers/mailbox/platform_mhu.c
> 
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index 97c3729..4cc93c6 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -15,6 +15,16 @@ config ARM_MHU
>  	  The controller has 3 mailbox channels, the last of which can be
>  	  used in Secure mode only.
>  
> +config PLATFORM_MHU
> +	tristate "Platform MHU Mailbox"
> +	depends on OF
> +	depends on HAS_IOMEM
> +	help
> +	  Say Y here if you want to build a platform specific variant MHU
> +	  controller driver.
> +	  The controller has a maximum of 3 mailbox channels, the last of
> +	  which can be used in Secure mode only.
> +
>  config PL320_MBOX
>  	bool "ARM PL320 Mailbox"
>  	depends on ARM_AMBA
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index 66c38e3..ace6fed 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -6,6 +6,8 @@ obj-$(CONFIG_MAILBOX_TEST)	+= mailbox-test.o
>  
>  obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
>  
> +obj-$(CONFIG_PLATFORM_MHU)	+= platform_mhu.o
> +
>  obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
>  
>  obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
> diff --git a/drivers/mailbox/platform_mhu.c b/drivers/mailbox/platform_mhu.c
> new file mode 100644
> index 0000000..d657a50
> --- /dev/null
> +++ b/drivers/mailbox/platform_mhu.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright (C) 2016 BayLibre SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + * Heavily based on arm_mhu.c from :
> + * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
> + * Copyright (C) 2015 Linaro Ltd.
> + * Author: Jassi Brar <jaswinder.singh at linaro.org>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, version 2 of the License.
> + *
> + * 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/interrupt.h>
> +#include <linux/spinlock.h>
> +#include <linux/mutex.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/mailbox_controller.h>
> +
> +#define INTR_SET_OFS	0x0
> +#define INTR_STAT_OFS	0x4
> +#define INTR_CLR_OFS	0x8
> +
> +#define MHU_LP_OFFSET	0x10
> +#define MHU_HP_OFFSET	0x1c
> +
> +#define TX_REG_OFFSET	0x24
> +
> +#define MHU_CHANS	2
> +
> +struct platform_mhu_link {
> +	unsigned int irq;

This should be a signed integer.... I will repost.

> +	void __iomem *tx_reg;
> +	void __iomem *rx_reg;
> +};
> +

[...]



From sboyd at codeaurora.org  Fri Aug 12 18:29:10 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 12 Aug 2016 18:29:10 -0700
Subject: [PATCH 1/3] clk: meson: Add GXBB AO Clock and Reset controller
 driver
In-Reply-To: <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
 <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160813012910.GT361@codeaurora.org>

On 08/09, Neil Armstrong wrote:
> diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
> new file mode 100644
> index 0000000..56a9186
> --- /dev/null
> +++ b/drivers/clk/meson/gxbb-aoclk.c
> @@ -0,0 +1,203 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/clk.h>

Is this include used?

> +#include <linux/clk-provider.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/module.h>
> +#include <dt-bindings/clock/gxbb-aoclkc.h>
> +#include <dt-bindings/reset/gxbb-aoclkc.h>
> +
> +static DEFINE_SPINLOCK(clk_lock);

gxbb_clk_lock?

> +
> +struct gxbb_aoclk_reset_controller {
> +	struct reset_controller_dev reset;
> +	unsigned int *data;
> +	void __iomem *base;
> +};
> +
> +static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
> +			       unsigned long id)
> +{
> +	struct gxbb_aoclk_reset_controller *reset =
> +		container_of(rcdev, struct gxbb_aoclk_reset_controller, reset);
> +
> +	writel(BIT(reset->data[id]), reset->base);
> +
> +	return 0;
> +}
> +
> +static const struct reset_control_ops gxbb_aoclk_reset_ops = {
> +	.reset = gxbb_aoclk_do_reset,
> +};
> +
> +#define GXBB_AO_GATE(_name, _bit)					\
> +static struct clk_gate _name##_ao = {					\
> +	.reg = (void __iomem *)0,					\
> +	.bit_idx = (_bit),						\
> +	.lock = &clk_lock,						\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = #_name "_ao",					\
> +		.ops = &clk_gate_ops,					\
> +		.parent_names = (const char *[]){ "clk81" },		\
> +		.num_parents = 1,					\
> +		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
> +	},								\
> +}
> +
> +GXBB_AO_GATE(remote, 0);
> +GXBB_AO_GATE(i2c_master, 1);
> +GXBB_AO_GATE(i2c_slave, 2);
> +GXBB_AO_GATE(uart1, 3);
> +GXBB_AO_GATE(uart2, 5);
> +GXBB_AO_GATE(ir_blaster, 6);
> +
> +static unsigned int gxbb_aoclk_reset[] = {
> +	[RESET_AO_REMOTE] = 16,
> +	[RESET_AO_I2C_MASTER] = 18,
> +	[RESET_AO_I2C_SLAVE] = 19,
> +	[RESET_AO_UART1] = 17,
> +	[RESET_AO_UART2] = 22,
> +	[RESET_AO_IR_BLASTER] = 23,
> +};
> +
> +static struct clk_gate *gxbb_aoclk_gate[] = {
> +	[CLKID_AO_REMOTE] = &remote_ao,
> +	[CLKID_AO_I2C_MASTER] = &i2c_master_ao,
> +	[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
> +	[CLKID_AO_UART1] = &uart1_ao,
> +	[CLKID_AO_UART2] = &uart2_ao,
> +	[CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
> +};
> +
> +static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {

can this be const?

> +	.hws = {
> +		[CLKID_AO_REMOTE] = &remote_ao.hw,
> +		[CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw,
> +		[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao.hw,
> +		[CLKID_AO_UART1] = &uart1_ao.hw,
> +		[CLKID_AO_UART2] = &uart2_ao.hw,
> +		[CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
> +	},
> +	.num = ARRAY_SIZE(gxbb_aoclk_gate),
> +};
> +
> +static int gxbb_aoclkc_probe(struct platform_device *pdev)
> +{
> +	void __iomem *base;
> +	int ret, clkid;
> +	struct device *dev = &pdev->dev;
> +	struct gxbb_aoclk_reset_controller *rstc;
> +
> +	rstc = devm_kzalloc(dev, sizeof(rstc), GFP_KERNEL);
> +	if (!rstc)
> +		return -ENOMEM;
> +
> +	/*  Generic clocks */
> +	base = of_iomap(dev->of_node, 0);

use devm_ioremap_resource() please and platform APIs to get the
ioresource.

> +	if (!base) {
> +		pr_err("%s: Unable to map clk base\n", __func__);

We don't need error prints here with devm_ioremap_resource().

> +		return -ENXIO;
> +	}
> +
> +	/* Reset Controller */
> +	rstc->base = base;
> +	rstc->data = gxbb_aoclk_reset;
> +	rstc->reset.ops = &gxbb_aoclk_reset_ops;
> +	rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset);
> +	rstc->reset.of_node = dev->of_node;
> +	ret = devm_reset_controller_register(dev, &rstc->reset);
> +
> +	/*
> +	 * Populate base address and register all clks
> +	 */
> +	for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) {
> +		gxbb_aoclk_gate[clkid]->reg = base;
> +
> +		ret = devm_clk_hw_register(dev,
> +					gxbb_aoclk_onecell_data.hws[clkid]);
> +		if (ret)
> +			goto iounmap;
> +	}
> +
> +	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
> +			&gxbb_aoclk_onecell_data);
> +
> +iounmap:
> +	iounmap(base);
> +	return ret;
> +}
> +
> +static const struct of_device_id gxbb_aoclkc_match_table[] = {
> +	{ .compatible = "amlogic,gxbb-aoclkc" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
> +
> +static struct platform_driver gxbb_aoclkc_driver = {
> +	.probe		= gxbb_aoclkc_probe,

No remove means leak of iomem mapping.
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


From b.galvani at gmail.com  Sat Aug 13 10:41:18 2016
From: b.galvani at gmail.com (Beniamino Galvani)
Date: Sat, 13 Aug 2016 19:41:18 +0200
Subject: [PATCH] pinctrl: meson: get rid of unneeded domain structures
Message-ID: <1471110078-5946-1-git-send-email-b.galvani@gmail.com>

The driver originally supported more domains (register ranges) per
pinctrl device, but since commit 9dab1868ec0d ("pinctrl: amlogic: Make
driver independent from two-domain configuration") each device gets
assigned a single domain and we instantiate multiple pinctrl devices
in the DT.

Therefore, now the 'meson_domain' and 'meson_domain_data' structures
don't have any reason to exist and can be removed to make the model
simpler to understand. This commit doesn't change behavior.

Tested on a Odroid-C2.

Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c |  24 +---
 drivers/pinctrl/meson/pinctrl-meson.c      | 222 +++++++++++------------------
 drivers/pinctrl/meson/pinctrl-meson.h      |  52 ++-----
 drivers/pinctrl/meson/pinctrl-meson8.c     |  24 +---
 drivers/pinctrl/meson/pinctrl-meson8b.c    |  24 +---
 5 files changed, 118 insertions(+), 228 deletions(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index cb4d6ad..233c9c8 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -556,38 +556,28 @@ static struct meson_bank meson_gxbb_aobus_banks[] = {
 	BANK("AO",   PIN(GPIOAO_0, 0),  PIN(GPIOAO_13, 0), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
 };
 
-static struct meson_domain_data meson_gxbb_periphs_domain_data = {
+struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
 	.name		= "periphs-banks",
-	.banks		= meson_gxbb_periphs_banks,
-	.num_banks	= ARRAY_SIZE(meson_gxbb_periphs_banks),
 	.pin_base	= 14,
-	.num_pins	= 120,
-};
-
-static struct meson_domain_data meson_gxbb_aobus_domain_data = {
-	.name		= "aobus-banks",
-	.banks		= meson_gxbb_aobus_banks,
-	.num_banks	= ARRAY_SIZE(meson_gxbb_aobus_banks),
-	.pin_base	= 0,
-	.num_pins	= 14,
-};
-
-struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
 	.pins		= meson_gxbb_periphs_pins,
 	.groups		= meson_gxbb_periphs_groups,
 	.funcs		= meson_gxbb_periphs_functions,
-	.domain_data	= &meson_gxbb_periphs_domain_data,
+	.banks		= meson_gxbb_periphs_banks,
 	.num_pins	= ARRAY_SIZE(meson_gxbb_periphs_pins),
 	.num_groups	= ARRAY_SIZE(meson_gxbb_periphs_groups),
 	.num_funcs	= ARRAY_SIZE(meson_gxbb_periphs_functions),
+	.num_banks	= ARRAY_SIZE(meson_gxbb_periphs_banks),
 };
 
 struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data = {
+	.name		= "aobus-banks",
+	.pin_base	= 0,
 	.pins		= meson_gxbb_aobus_pins,
 	.groups		= meson_gxbb_aobus_groups,
 	.funcs		= meson_gxbb_aobus_functions,
-	.domain_data	= &meson_gxbb_aobus_domain_data,
+	.banks		= meson_gxbb_aobus_banks,
 	.num_pins	= ARRAY_SIZE(meson_gxbb_aobus_pins),
 	.num_groups	= ARRAY_SIZE(meson_gxbb_aobus_groups),
 	.num_funcs	= ARRAY_SIZE(meson_gxbb_aobus_functions),
+	.num_banks	= ARRAY_SIZE(meson_gxbb_aobus_banks),
 };
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 11623c6..9678599 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -21,9 +21,8 @@
  * domain which can't be powered off; the bank also uses a set of
  * registers different from the other banks.
  *
- * For each of the two power domains (regular and always-on) there are
- * 4 different register ranges that control the following properties
- * of the pins:
+ * For each pin controller there are 4 different register ranges that
+ * control the following properties of the pins:
  *  1) pin muxing
  *  2) pull enable/disable
  *  3) pull up/down
@@ -33,8 +32,8 @@
  * direction are the same and thus there are only 3 register ranges.
  *
  * Every pinmux group can be enabled by a specific bit in the first
- * register range of the domain; when all groups for a given pin are
- * disabled the pin acts as a GPIO.
+ * register range; when all groups for a given pin are disabled the
+ * pin acts as a GPIO.
  *
  * For the pull and GPIO configuration every bank uses a contiguous
  * set of bits in the register sets described above; the same register
@@ -66,21 +65,21 @@
 /**
  * meson_get_bank() - find the bank containing a given pin
  *
- * @domain:	the domain containing the pin
+ * @pc:		the pinctrl instance
  * @pin:	the pin number
  * @bank:	the found bank
  *
  * Return:	0 on success, a negative value on error
  */
-static int meson_get_bank(struct meson_domain *domain, unsigned int pin,
+static int meson_get_bank(struct meson_pinctrl *pc, unsigned int pin,
 			  struct meson_bank **bank)
 {
 	int i;
 
-	for (i = 0; i < domain->data->num_banks; i++) {
-		if (pin >= domain->data->banks[i].first &&
-		    pin <= domain->data->banks[i].last) {
-			*bank = &domain->data->banks[i];
+	for (i = 0; i < pc->data->num_banks; i++) {
+		if (pin >= pc->data->banks[i].first &&
+		    pin <= pc->data->banks[i].last) {
+			*bank = &pc->data->banks[i];
 			return 0;
 		}
 	}
@@ -89,33 +88,6 @@ static int meson_get_bank(struct meson_domain *domain, unsigned int pin,
 }
 
 /**
- * meson_get_domain_and_bank() - find domain and bank containing a given pin
- *
- * @pc:		Meson pin controller device
- * @pin:	the pin number
- * @domain:	the found domain
- * @bank:	the found bank
- *
- * Return:	0 on success, a negative value on error
- */
-static int meson_get_domain_and_bank(struct meson_pinctrl *pc, unsigned int pin,
-				     struct meson_domain **domain,
-				     struct meson_bank **bank)
-{
-	struct meson_domain *d;
-
-	d = pc->domain;
-
-	if (pin >= d->data->pin_base &&
-	    pin < d->data->pin_base + d->data->num_pins) {
-		*domain = d;
-		return meson_get_bank(d, pin, bank);
-	}
-
-	return -EINVAL;
-}
-
-/**
  * meson_calc_reg_and_bit() - calculate register and bit for a pin
  *
  * @bank:	the bank containing the pin
@@ -190,7 +162,6 @@ static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc,
 					   unsigned int pin, int sel_group)
 {
 	struct meson_pmx_group *group;
-	struct meson_domain *domain;
 	int i, j;
 
 	for (i = 0; i < pc->data->num_groups; i++) {
@@ -201,8 +172,7 @@ static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc,
 		for (j = 0; j < group->num_pins; j++) {
 			if (group->pins[j] == pin) {
 				/* We have found a group using the pin */
-				domain = pc->domain;
-				regmap_update_bits(domain->reg_mux,
+				regmap_update_bits(pc->reg_mux,
 						   group->reg * 4,
 						   BIT(group->bit), 0);
 			}
@@ -216,7 +186,6 @@ static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num,
 	struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
 	struct meson_pmx_func *func = &pc->data->funcs[func_num];
 	struct meson_pmx_group *group = &pc->data->groups[group_num];
-	struct meson_domain *domain = pc->domain;
 	int i, ret = 0;
 
 	dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
@@ -231,7 +200,7 @@ static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num,
 
 	/* Function 0 (GPIO) doesn't need any additional setting */
 	if (func_num)
-		ret = regmap_update_bits(domain->reg_mux, group->reg * 4,
+		ret = regmap_update_bits(pc->reg_mux, group->reg * 4,
 					 BIT(group->bit), BIT(group->bit));
 
 	return ret;
@@ -287,14 +256,13 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
 			     unsigned long *configs, unsigned num_configs)
 {
 	struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
-	struct meson_domain *domain;
 	struct meson_bank *bank;
 	enum pin_config_param param;
 	unsigned int reg, bit;
 	int i, ret;
 	u16 arg;
 
-	ret = meson_get_domain_and_bank(pc, pin, &domain, &bank);
+	ret = meson_get_bank(pc, pin, &bank);
 	if (ret)
 		return ret;
 
@@ -307,7 +275,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
 			dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
 
 			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
-			ret = regmap_update_bits(domain->reg_pull, reg,
+			ret = regmap_update_bits(pc->reg_pull, reg,
 						 BIT(bit), 0);
 			if (ret)
 				return ret;
@@ -317,13 +285,13 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
 
 			meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
 					       &reg, &bit);
-			ret = regmap_update_bits(domain->reg_pullen, reg,
+			ret = regmap_update_bits(pc->reg_pullen, reg,
 						 BIT(bit), BIT(bit));
 			if (ret)
 				return ret;
 
 			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
-			ret = regmap_update_bits(domain->reg_pull, reg,
+			ret = regmap_update_bits(pc->reg_pull, reg,
 						 BIT(bit), BIT(bit));
 			if (ret)
 				return ret;
@@ -333,13 +301,13 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
 
 			meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
 					       &reg, &bit);
-			ret = regmap_update_bits(domain->reg_pullen, reg,
+			ret = regmap_update_bits(pc->reg_pullen, reg,
 						 BIT(bit), BIT(bit));
 			if (ret)
 				return ret;
 
 			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
-			ret = regmap_update_bits(domain->reg_pull, reg,
+			ret = regmap_update_bits(pc->reg_pull, reg,
 						 BIT(bit), 0);
 			if (ret)
 				return ret;
@@ -354,18 +322,17 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
 
 static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
 {
-	struct meson_domain *domain;
 	struct meson_bank *bank;
 	unsigned int reg, bit, val;
 	int ret, conf;
 
-	ret = meson_get_domain_and_bank(pc, pin, &domain, &bank);
+	ret = meson_get_bank(pc, pin, &bank);
 	if (ret)
 		return ret;
 
 	meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit);
 
-	ret = regmap_read(domain->reg_pullen, reg, &val);
+	ret = regmap_read(pc->reg_pullen, reg, &val);
 	if (ret)
 		return ret;
 
@@ -374,7 +341,7 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
 	} else {
 		meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
 
-		ret = regmap_read(domain->reg_pull, reg, &val);
+		ret = regmap_read(pc->reg_pull, reg, &val);
 		if (ret)
 			return ret;
 
@@ -452,82 +419,82 @@ static int meson_gpio_request(struct gpio_chip *chip, unsigned gpio)
 
 static void meson_gpio_free(struct gpio_chip *chip, unsigned gpio)
 {
-	struct meson_domain *domain = gpiochip_get_data(chip);
+	struct meson_pinctrl *pc = gpiochip_get_data(chip);
 
-	pinctrl_free_gpio(domain->data->pin_base + gpio);
+	pinctrl_free_gpio(pc->data->pin_base + gpio);
 }
 
 static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 {
-	struct meson_domain *domain = gpiochip_get_data(chip);
+	struct meson_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned int reg, bit, pin;
 	struct meson_bank *bank;
 	int ret;
 
-	pin = domain->data->pin_base + gpio;
-	ret = meson_get_bank(domain, pin, &bank);
+	pin = pc->data->pin_base + gpio;
+	ret = meson_get_bank(pc, pin, &bank);
 	if (ret)
 		return ret;
 
 	meson_calc_reg_and_bit(bank, pin, REG_DIR, &reg, &bit);
 
-	return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), BIT(bit));
+	return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit));
 }
 
 static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
 				       int value)
 {
-	struct meson_domain *domain = gpiochip_get_data(chip);
+	struct meson_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned int reg, bit, pin;
 	struct meson_bank *bank;
 	int ret;
 
-	pin = domain->data->pin_base + gpio;
-	ret = meson_get_bank(domain, pin, &bank);
+	pin = pc->data->pin_base + gpio;
+	ret = meson_get_bank(pc, pin, &bank);
 	if (ret)
 		return ret;
 
 	meson_calc_reg_and_bit(bank, pin, REG_DIR, &reg, &bit);
-	ret = regmap_update_bits(domain->reg_gpio, reg, BIT(bit), 0);
+	ret = regmap_update_bits(pc->reg_gpio, reg, BIT(bit), 0);
 	if (ret)
 		return ret;
 
 	meson_calc_reg_and_bit(bank, pin, REG_OUT, &reg, &bit);
-	return regmap_update_bits(domain->reg_gpio, reg, BIT(bit),
+	return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
 				  value ? BIT(bit) : 0);
 }
 
 static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
 {
-	struct meson_domain *domain = gpiochip_get_data(chip);
+	struct meson_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned int reg, bit, pin;
 	struct meson_bank *bank;
 	int ret;
 
-	pin = domain->data->pin_base + gpio;
-	ret = meson_get_bank(domain, pin, &bank);
+	pin = pc->data->pin_base + gpio;
+	ret = meson_get_bank(pc, pin, &bank);
 	if (ret)
 		return;
 
 	meson_calc_reg_and_bit(bank, pin, REG_OUT, &reg, &bit);
-	regmap_update_bits(domain->reg_gpio, reg, BIT(bit),
+	regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
 			   value ? BIT(bit) : 0);
 }
 
 static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
 {
-	struct meson_domain *domain = gpiochip_get_data(chip);
+	struct meson_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned int reg, bit, val, pin;
 	struct meson_bank *bank;
 	int ret;
 
-	pin = domain->data->pin_base + gpio;
-	ret = meson_get_bank(domain, pin, &bank);
+	pin = pc->data->pin_base + gpio;
+	ret = meson_get_bank(pc, pin, &bank);
 	if (ret)
 		return ret;
 
 	meson_calc_reg_and_bit(bank, pin, REG_IN, &reg, &bit);
-	regmap_read(domain->reg_gpio, reg, &val);
+	regmap_read(pc->reg_gpio, reg, &val);
 
 	return !!(val & BIT(bit));
 }
@@ -562,35 +529,32 @@ static const struct of_device_id meson_pinctrl_dt_match[] = {
 
 static int meson_gpiolib_register(struct meson_pinctrl *pc)
 {
-	struct meson_domain *domain;
 	int ret;
 
-	domain = pc->domain;
-
-	domain->chip.label = domain->data->name;
-	domain->chip.parent = pc->dev;
-	domain->chip.request = meson_gpio_request;
-	domain->chip.free = meson_gpio_free;
-	domain->chip.direction_input = meson_gpio_direction_input;
-	domain->chip.direction_output = meson_gpio_direction_output;
-	domain->chip.get = meson_gpio_get;
-	domain->chip.set = meson_gpio_set;
-	domain->chip.base = domain->data->pin_base;
-	domain->chip.ngpio = domain->data->num_pins;
-	domain->chip.can_sleep = false;
-	domain->chip.of_node = domain->of_node;
-	domain->chip.of_gpio_n_cells = 2;
-
-	ret = gpiochip_add_data(&domain->chip, domain);
+	pc->chip.label = pc->data->name;
+	pc->chip.parent = pc->dev;
+	pc->chip.request = meson_gpio_request;
+	pc->chip.free = meson_gpio_free;
+	pc->chip.direction_input = meson_gpio_direction_input;
+	pc->chip.direction_output = meson_gpio_direction_output;
+	pc->chip.get = meson_gpio_get;
+	pc->chip.set = meson_gpio_set;
+	pc->chip.base = pc->data->pin_base;
+	pc->chip.ngpio = pc->data->num_pins;
+	pc->chip.can_sleep = false;
+	pc->chip.of_node = pc->of_node;
+	pc->chip.of_gpio_n_cells = 2;
+
+	ret = gpiochip_add_data(&pc->chip, pc);
 	if (ret) {
 		dev_err(pc->dev, "can't add gpio chip %s\n",
-			domain->data->name);
+			pc->data->name);
 		goto fail;
 	}
 
-	ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev),
-				     0, domain->data->pin_base,
-				     domain->chip.ngpio);
+	ret = gpiochip_add_pin_range(&pc->chip, dev_name(pc->dev),
+				     0, pc->data->pin_base,
+				     pc->chip.ngpio);
 	if (ret) {
 		dev_err(pc->dev, "can't add pin range\n");
 		goto fail;
@@ -598,7 +562,7 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
 
 	return 0;
 fail:
-	gpiochip_remove(&pc->domain->chip);
+	gpiochip_remove(&pc->chip);
 
 	return ret;
 }
@@ -637,58 +601,46 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
 static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
 				  struct device_node *node)
 {
-	struct device_node *np;
-	struct meson_domain *domain;
-	int num_domains = 0;
+	struct device_node *np, *gpio_np = NULL;
 
 	for_each_child_of_node(node, np) {
 		if (!of_find_property(np, "gpio-controller", NULL))
 			continue;
-		num_domains++;
+		if (gpio_np) {
+			dev_err(pc->dev, "multiple gpio nodes\n");
+			return -EINVAL;
+		}
+		gpio_np = np;
 	}
 
-	if (num_domains != 1) {
-		dev_err(pc->dev, "wrong number of subnodes\n");
+	if (!gpio_np) {
+		dev_err(pc->dev, "no gpio node found\n");
 		return -EINVAL;
 	}
 
-	pc->domain = devm_kzalloc(pc->dev, sizeof(struct meson_domain), GFP_KERNEL);
-	if (!pc->domain)
-		return -ENOMEM;
-
-	domain = pc->domain;
-	domain->data = pc->data->domain_data;
-
-	for_each_child_of_node(node, np) {
-		if (!of_find_property(np, "gpio-controller", NULL))
-			continue;
-
-		domain->of_node = np;
+	pc->of_node = gpio_np;
 
-		domain->reg_mux = meson_map_resource(pc, np, "mux");
-		if (IS_ERR(domain->reg_mux)) {
-			dev_err(pc->dev, "mux registers not found\n");
-			return PTR_ERR(domain->reg_mux);
-		}
-
-		domain->reg_pull = meson_map_resource(pc, np, "pull");
-		if (IS_ERR(domain->reg_pull)) {
-			dev_err(pc->dev, "pull registers not found\n");
-			return PTR_ERR(domain->reg_pull);
-		}
+	pc->reg_mux = meson_map_resource(pc, gpio_np, "mux");
+	if (IS_ERR(pc->reg_mux)) {
+		dev_err(pc->dev, "mux registers not found\n");
+		return PTR_ERR(pc->reg_mux);
+	}
 
-		domain->reg_pullen = meson_map_resource(pc, np, "pull-enable");
-		/* Use pull region if pull-enable one is not present */
-		if (IS_ERR(domain->reg_pullen))
-			domain->reg_pullen = domain->reg_pull;
+	pc->reg_pull = meson_map_resource(pc, gpio_np, "pull");
+	if (IS_ERR(pc->reg_pull)) {
+		dev_err(pc->dev, "pull registers not found\n");
+		return PTR_ERR(pc->reg_pull);
+	}
 
-		domain->reg_gpio = meson_map_resource(pc, np, "gpio");
-		if (IS_ERR(domain->reg_gpio)) {
-			dev_err(pc->dev, "gpio registers not found\n");
-			return PTR_ERR(domain->reg_gpio);
-		}
+	pc->reg_pullen = meson_map_resource(pc, gpio_np, "pull-enable");
+	/* Use pull region if pull-enable one is not present */
+	if (IS_ERR(pc->reg_pullen))
+		pc->reg_pullen = pc->reg_pull;
 
-		break;
+	pc->reg_gpio = meson_map_resource(pc, gpio_np, "gpio");
+	if (IS_ERR(pc->reg_gpio)) {
+		dev_err(pc->dev, "gpio registers not found\n");
+		return PTR_ERR(pc->reg_gpio);
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index d89442e..98b5080 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -95,54 +95,17 @@ struct meson_bank {
 	struct meson_reg_desc regs[NUM_REG];
 };
 
-/**
- * struct meson_domain_data - domain platform data
- *
- * @name:	name of the domain
- * @banks:	set of banks belonging to the domain
- * @num_banks:	number of banks in the domain
- */
-struct meson_domain_data {
-	const char *name;
-	struct meson_bank *banks;
-	unsigned int num_banks;
-	unsigned int pin_base;
-	unsigned int num_pins;
-};
-
-/**
- * struct meson_domain
- *
- * @reg_mux:	registers for mux settings
- * @reg_pullen:	registers for pull-enable settings
- * @reg_pull:	registers for pull settings
- * @reg_gpio:	registers for gpio settings
- * @chip:	gpio chip associated with the domain
- * @data;	platform data for the domain
- * @node:	device tree node for the domain
- *
- * A domain represents a set of banks controlled by the same set of
- * registers.
- */
-struct meson_domain {
-	struct regmap *reg_mux;
-	struct regmap *reg_pullen;
-	struct regmap *reg_pull;
-	struct regmap *reg_gpio;
-
-	struct gpio_chip chip;
-	struct meson_domain_data *data;
-	struct device_node *of_node;
-};
-
 struct meson_pinctrl_data {
+	const char *name;
 	const struct pinctrl_pin_desc *pins;
 	struct meson_pmx_group *groups;
 	struct meson_pmx_func *funcs;
-	struct meson_domain_data *domain_data;
+	unsigned int pin_base;
 	unsigned int num_pins;
 	unsigned int num_groups;
 	unsigned int num_funcs;
+	struct meson_bank *banks;
+	unsigned int num_banks;
 };
 
 struct meson_pinctrl {
@@ -150,7 +113,12 @@ struct meson_pinctrl {
 	struct pinctrl_dev *pcdev;
 	struct pinctrl_desc desc;
 	struct meson_pinctrl_data *data;
-	struct meson_domain *domain;
+	struct regmap *reg_mux;
+	struct regmap *reg_pullen;
+	struct regmap *reg_pull;
+	struct regmap *reg_gpio;
+	struct gpio_chip chip;
+	struct device_node *of_node;
 };
 
 #define PIN(x, b)	(b + x)
diff --git a/drivers/pinctrl/meson/pinctrl-meson8.c b/drivers/pinctrl/meson/pinctrl-meson8.c
index 32de191..07f1cb2 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8.c
@@ -931,38 +931,28 @@ static struct meson_bank meson8_aobus_banks[] = {
 	BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
 };
 
-static struct meson_domain_data meson8_cbus_domain_data = {
+struct meson_pinctrl_data meson8_cbus_pinctrl_data = {
 	.name		= "cbus-banks",
-	.banks		= meson8_cbus_banks,
-	.num_banks	= ARRAY_SIZE(meson8_cbus_banks),
 	.pin_base	= 0,
-	.num_pins	= 120,
-};
-
-static struct meson_domain_data meson8_aobus_domain_data = {
-	.name		= "ao-bank",
-	.banks		= meson8_aobus_banks,
-	.num_banks	= ARRAY_SIZE(meson8_aobus_banks),
-	.pin_base	= 120,
-	.num_pins	= 16,
-};
-
-struct meson_pinctrl_data meson8_cbus_pinctrl_data = {
 	.pins		= meson8_cbus_pins,
 	.groups		= meson8_cbus_groups,
 	.funcs		= meson8_cbus_functions,
-	.domain_data	= &meson8_cbus_domain_data,
+	.banks		= meson8_cbus_banks,
 	.num_pins	= ARRAY_SIZE(meson8_cbus_pins),
 	.num_groups	= ARRAY_SIZE(meson8_cbus_groups),
 	.num_funcs	= ARRAY_SIZE(meson8_cbus_functions),
+	.num_banks	= ARRAY_SIZE(meson8_cbus_banks),
 };
 
 struct meson_pinctrl_data meson8_aobus_pinctrl_data = {
+	.name		= "ao-bank",
+	.pin_base	= 120,
 	.pins		= meson8_aobus_pins,
 	.groups		= meson8_aobus_groups,
 	.funcs		= meson8_aobus_functions,
-	.domain_data	= &meson8_aobus_domain_data,
+	.banks		= meson8_aobus_banks,
 	.num_pins	= ARRAY_SIZE(meson8_aobus_pins),
 	.num_groups	= ARRAY_SIZE(meson8_aobus_groups),
 	.num_funcs	= ARRAY_SIZE(meson8_aobus_functions),
+	.num_banks	= ARRAY_SIZE(meson8_aobus_banks),
 };
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index 874f2ed..76f077f 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -896,38 +896,28 @@ static struct meson_bank meson8b_aobus_banks[] = {
 	BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
 };
 
-static struct meson_domain_data meson8b_cbus_domain_data = {
+struct meson_pinctrl_data meson8b_cbus_pinctrl_data = {
 	.name		= "cbus-banks",
-	.banks		= meson8b_cbus_banks,
-	.num_banks	= ARRAY_SIZE(meson8b_cbus_banks),
 	.pin_base	= 0,
-	.num_pins	= 130,
-};
-
-static struct meson_domain_data meson8b_aobus_domain_data = {
-	.name		= "aobus-banks",
-	.banks		= meson8b_aobus_banks,
-	.num_banks	= ARRAY_SIZE(meson8b_aobus_banks),
-	.pin_base	= 130,
-	.num_pins	= 16,
-};
-
-struct meson_pinctrl_data meson8b_cbus_pinctrl_data = {
 	.pins		= meson8b_cbus_pins,
 	.groups		= meson8b_cbus_groups,
 	.funcs		= meson8b_cbus_functions,
-	.domain_data	= &meson8b_cbus_domain_data,
+	.banks		= meson8b_cbus_banks,
 	.num_pins	= ARRAY_SIZE(meson8b_cbus_pins),
 	.num_groups	= ARRAY_SIZE(meson8b_cbus_groups),
 	.num_funcs	= ARRAY_SIZE(meson8b_cbus_functions),
+	.num_banks	= ARRAY_SIZE(meson8b_cbus_banks),
 };
 
 struct meson_pinctrl_data meson8b_aobus_pinctrl_data = {
+	.name		= "aobus-banks",
+	.pin_base	= 130,
 	.pins		= meson8b_aobus_pins,
 	.groups		= meson8b_aobus_groups,
 	.funcs		= meson8b_aobus_functions,
-	.domain_data	= &meson8b_aobus_domain_data,
+	.banks		= meson8b_aobus_banks,
 	.num_pins	= ARRAY_SIZE(meson8b_aobus_pins),
 	.num_groups	= ARRAY_SIZE(meson8b_aobus_groups),
 	.num_funcs	= ARRAY_SIZE(meson8b_aobus_functions),
+	.num_banks	= ARRAY_SIZE(meson8b_aobus_banks),
 };
-- 
2.7.4



From svlasic at gmail.com  Sat Aug 13 10:54:19 2016
From: svlasic at gmail.com (Stanislav Vlasic)
Date: Sat, 13 Aug 2016 19:54:19 +0200
Subject: Meson8 platform on aml 3.14.29 kernel
Message-ID: <CADYw_JJr8P0k38BjoWv4fL=T8gk6qO7ox8g7Xn0dQhWSMbyMPg@mail.gmail.com>

Hi guys,

I'm aware that this board is not for questions like this, but give me
a chance... :)

Here's situation.

I have latest amlogic kernel sources for 9xx platform (kernel is
20160701). There are some indicators in code that initially they did
some testing with 3.14 kernel on S812 at least (there's dts in source
tree, as well as defconfig).

What I want to do is try to bring up official aml 3.14 kernel to M8xx
currently for only one reason - to bring their official release of
Android Marshmallow on it.

Did anyone tried that? Or another question. How bringing up aml to
mainline is going? Is there plan to port amports as well?

Some weeks ago I successfully booted latest kernel on my p200 based
board. I would help with development but when it comes to kernel
porting and development, it's not really my thing. Something small on
kernel level I can do but...

If I can help in any other way, feel free to tell :)

Regards,
Stane1983


From drieschel at yahoo.de  Sat Aug 13 12:39:08 2016
From: drieschel at yahoo.de (Immanuel Klinkenberg)
Date: Sat, 13 Aug 2016 21:39:08 +0200
Subject: Meson8 platform on aml 3.14.29 kernel
In-Reply-To: <CADYw_JJr8P0k38BjoWv4fL=T8gk6qO7ox8g7Xn0dQhWSMbyMPg@mail.gmail.com>
References: <CADYw_JJr8P0k38BjoWv4fL=T8gk6qO7ox8g7Xn0dQhWSMbyMPg@mail.gmail.com>
Message-ID: <609701db-6741-4cd2-fe08-38435de87669@yahoo.de>

Hello,

that would be very interesting for the LibreELEC project, too. Because a
single kernel could be used for all Amlogic arm and aarch64 SoC
platforms. I am not a kernel expert but I would like to support this.


Best,
drieschel

Am 13.08.2016 um 19:54 schrieb Stanislav Vlasic:
> Hi guys,
>
> I'm aware that this board is not for questions like this, but give me
> a chance... :)
>
> Here's situation.
>
> I have latest amlogic kernel sources for 9xx platform (kernel is
> 20160701). There are some indicators in code that initially they did
> some testing with 3.14 kernel on S812 at least (there's dts in source
> tree, as well as defconfig).
>
> What I want to do is try to bring up official aml 3.14 kernel to M8xx
> currently for only one reason - to bring their official release of
> Android Marshmallow on it.
>
> Did anyone tried that? Or another question. How bringing up aml to
> mainline is going? Is there plan to port amports as well?
>
> Some weeks ago I successfully booted latest kernel on my p200 based
> board. I would help with development but when it comes to kernel
> porting and development, it's not really my thing. Something small on
> kernel level I can do but...
>
> If I can help in any other way, feel free to tell :)
>
> Regards,
> Stane1983
>
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic



---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren gepr?ft.
https://www.avast.com/antivirus



From lkp at intel.com  Sat Aug 13 22:25:40 2016
From: lkp at intel.com (kbuild test robot)
Date: Sun, 14 Aug 2016 13:25:40 +0800
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <20160803231843.23012-1-khilman@baylibre.com>
Message-ID: <201608141319.AeQlvjsy%fengguang.wu@intel.com>

Hi Kevin,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.8-rc1 next-20160812]
[cannot apply to ulf.hansson-mmc/next robh/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Kevin-Hilman/ARM64-dts-meson-gxbb-add-MMC-support/20160804-072056
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 5.4.0-6) 5.4.0 20160609
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

>> Error: arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi:338.21-22 syntax error
>> FATAL ERROR: Unable to parse input tree

---
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: 29377 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20160814/37296eba/attachment.obj>

From wsa at the-dreams.de  Sun Aug 14 15:17:20 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Mon, 15 Aug 2016 00:17:20 +0200
Subject: [PATCH] i2c: don't print error when adding adapter fails
In-Reply-To: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
References: <1470742581-12971-1-git-send-email-wsa-dev@sang-engineering.com>
Message-ID: <20160814221719.GA10501@katana>

On Tue, Aug 09, 2016 at 01:36:16PM +0200, Wolfram Sang wrote:
> Since v4.8-rc1, the I2C core will print detailed information when adding an I2C
> adapter fails. So, drivers can skip this now.
> 
> I am still undecided if I apply this as a single patch or break it out. But for
> reviewing, avoiding the patch bomb is probably a good thing.
> 
> Should go via subsystem tree, I'd think.
> 
> Wolfram Sang (1):
>   i2c: don't print error when adding adapter fails
> 

Applied to for-next, thanks!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20160815/1ec8f886/attachment.sig>

From paul.gortmaker at windriver.com  Sun Aug 14 17:08:57 2016
From: paul.gortmaker at windriver.com (Paul Gortmaker)
Date: Sun, 14 Aug 2016 20:08:57 -0400
Subject: [PATCH 1/3] clk: meson: Add GXBB AO Clock and Reset controller
 driver
In-Reply-To: <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
 <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CAP=VYLphcuq16vDueOOJ6anrW-ifYAK+1ijSjkGbxw48+m4xrw@mail.gmail.com>

On Tue, Aug 9, 2016 at 5:13 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> Adds a Clock and Reset controller driver for the Always-On part
> of the Amlogic Meson GXBB SoC.
>
> It exports paired Clocks and Resets lines that will be used by
> peripherals in the Always-On subsystem.

[...]

> +static const struct of_device_id gxbb_aoclkc_match_table[] = {
> +       { .compatible = "amlogic,gxbb-aoclkc" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
> +
> +static struct platform_driver gxbb_aoclkc_driver = {
> +       .probe          = gxbb_aoclkc_probe,
> +       .driver         = {
> +               .name   = "gxbb-aoclkc",
> +               .of_match_table = gxbb_aoclkc_match_table,
> +       },
> +};
> +
> +module_platform_driver(gxbb_aoclkc_driver);
> +
> +MODULE_DESCRIPTION("AmLogic Meson GXBB AO Clock Controller Driver");
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_ALIAS("platform:gxbb-aoclkc");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");

Since this driver is controlled by a bool Kconfig, you can dump the module.h
include and all the MODULE_<xyz> tags above.

Or, if there is a genuine use case for it to be modular, then make it tristate?

Thanks,
Paul.


From sudeep.holla at arm.com  Mon Aug 15 06:35:24 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Mon, 15 Aug 2016 14:35:24 +0100
Subject: [RFC PATCH v3 5/8] firmware: Add legacy SCPI protocol driver
In-Reply-To: <1470738562-20026-6-git-send-email-narmstrong@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
 <1470738562-20026-6-git-send-email-narmstrong@baylibre.com>
Message-ID: <cea12544-6dfd-55d4-7c85-68290c720515@arm.com>

Hi Neil,

On 09/08/16 11:29, Neil Armstrong wrote:
> Add legacy protocol driver for an early published SCPI implementation
> by supporting old command indexes and structure.
> This driver also supports vendor messages and rockchip specific
> mailbox data structure for message passing to SCP.
>

Sorry for the delay but I expected some attempts to reduce the
duplication of code we have here. I really don't like the duplication of
the code. As I mentioned earlier it can be reduced. I see lot of scope
for that and I see that you made zero attempts since v2.

> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/firmware/Kconfig       |  20 ++
>  drivers/firmware/Makefile      |   1 +
>  drivers/firmware/legacy_scpi.c | 710 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 731 insertions(+)
>  create mode 100644 drivers/firmware/legacy_scpi.c
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index ff85511..f6226b7 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -40,6 +40,26 @@ config ARM_SCPI_POWER_DOMAIN
>  	  This enables support for the SCPI power domains which can be
>  	  enabled or disabled via the SCP firmware
>
> +config LEGACY_SCPI_PROTOCOL
> +	bool "Legacy System Control and Power Interface (SCPI) Message Protocol"
> +	default y if ARCH_MESON
> +	select SCPI_FW
> +	help
> +	  System Control and Power Interface (SCPI) Message Protocol is
> +	  defined for the purpose of communication between the Application
> +	  Cores(AP) and the System Control Processor(SCP). The MHU peripheral
> +	  provides a mechanism for inter-processor communication between SCP
> +	  and AP.
> +
> +	  SCP controls most of the power managament on the Application
> +	  Processors. It offers control and management of: the core/cluster
> +	  power states, various power domain DVFS including the core/cluster,
> +	  certain system clocks configuration, thermal sensors and many
> +	  others.
> +
> +	  This protocol library provides interface for all the client drivers
> +	  making use of the features offered by the legacy SCP protocol.
> +

Why do we need this ? If we plan to enable this in defconfig, I would
rather not introduce this as it serves nothing extra over the
compatible. We need runtime check for this with DT compatibles.


[...]


> +enum legacy_scpi_client_id {
> +	SCPI_CL_NONE,
> +	SCPI_CL_CLOCKS,
> +	SCPI_CL_DVFS,
> +	SCPI_CL_POWER,
> +	SCPI_CL_THERMAL,
> +	SCPI_MAX,
> +};
> +

As I said before these values were introduced by me initially and I
reckon firmware doesn't depend on that. Have you really tested dropping
them ? This must go as they are useless and we now have tokens which are
much better.

I will stop here and ask why can't you start with simple change like
below ? Then we can add or re-define the structures/enums when
absolutely needed. Please don't just copy the entire driver and make
changes where-ever needed or please try to adapt to the new driver and
try to deviate as less as required by the firmware.

Regards,
Sudeep

--->8

diff --git i/drivers/firmware/arm_scpi.c w/drivers/firmware/arm_scpi.c
index 438893762076..b394ffb5939c 100644
--- i/drivers/firmware/arm_scpi.c
+++ w/drivers/firmware/arm_scpi.c
@@ -82,6 +82,9 @@

  #define MAX_RX_TIMEOUT		(msecs_to_jiffies(30))

+typedef int (*scpi_send_msg_func)(u8 cmd, void *tx_buf, unsigned int 
tx_len,
+				  void *rx_buf, unsigned int rx_len);
+
  enum scpi_error_codes {
  	SCPI_SUCCESS = 0, /* Success */
  	SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
@@ -162,6 +165,7 @@ struct scpi_drvinfo {
  	u32 firmware_version;
  	int num_chans;
  	atomic_t next_chan;
+	scpi_send_msg_func send_msg;
  	struct scpi_ops *scpi_ops;
  	struct scpi_chan *channels;
  	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
@@ -397,8 +401,8 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, 
unsigned long *max)
  	struct clk_get_info clk;
  	__le16 le_clk_id = cpu_to_le16(clk_id);

-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
-				sizeof(le_clk_id), &clk, sizeof(clk));
+	ret = scpi_info->send_msg(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
+				  sizeof(le_clk_id), &clk, sizeof(clk));
  	if (!ret) {
  		*min = le32_to_cpu(clk.min_rate);
  		*max = le32_to_cpu(clk.max_rate);
@@ -412,8 +416,8 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
  	struct clk_get_value clk;
  	__le16 le_clk_id = cpu_to_le16(clk_id);

-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
-				sizeof(le_clk_id), &clk, sizeof(clk));
+	ret = scpi_info->send_msg(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+				  sizeof(le_clk_id), &clk, sizeof(clk));
  	return ret ? ret : le32_to_cpu(clk.rate);
  }

@@ -425,8 +429,8 @@ static int scpi_clk_set_val(u16 clk_id, unsigned 
long rate)
  		.rate = cpu_to_le32(rate)
  	};

-	return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
-				 &stat, sizeof(stat));
+	return scpi_info->send_msg(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+				   &stat, sizeof(stat));
  }

  static int scpi_dvfs_get_idx(u8 domain)
@@ -434,8 +438,8 @@ static int scpi_dvfs_get_idx(u8 domain)
  	int ret;
  	u8 dvfs_idx;

-	ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
-				&dvfs_idx, sizeof(dvfs_idx));
+	ret = scpi_info->send_msg(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
+				  &dvfs_idx, sizeof(dvfs_idx));
  	return ret ? ret : dvfs_idx;
  }

@@ -444,8 +448,8 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
  	int stat;
  	struct dvfs_set dvfs = {domain, index};

-	return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
-				 &stat, sizeof(stat));
+	return scpi_info->send_msg(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
+				   &stat, sizeof(stat));
  }

  static int opp_cmp_func(const void *opp1, const void *opp2)
@@ -468,8 +472,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 
domain)
  	if (scpi_info->dvfs[domain])	/* data already populated */
  		return scpi_info->dvfs[domain];

-	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
-				&buf, sizeof(buf));
+	ret = scpi_info->send_msg(SCPI_CMD_GET_DVFS_INFO, &domain,
+				  sizeof(domain), &buf, sizeof(buf));

  	if (ret)
  		return ERR_PTR(ret);
@@ -503,8 +507,8 @@ static int scpi_sensor_get_capability(u16 *sensors)
  	struct sensor_capabilities cap_buf;
  	int ret;

-	ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
-				sizeof(cap_buf));
+	ret = scpi_info->send_msg(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0,
+				  &cap_buf, sizeof(cap_buf));
  	if (!ret)
  		*sensors = le16_to_cpu(cap_buf.sensors);

@@ -517,8 +521,8 @@ static int scpi_sensor_get_info(u16 sensor_id, 
struct scpi_sensor_info *info)
  	struct _scpi_sensor_info _info;
  	int ret;

-	ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
-				&_info, sizeof(_info));
+	ret = scpi_info->send_msg(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+				  &_info, sizeof(_info));
  	if (!ret) {
  		memcpy(info, &_info, sizeof(*info));
  		info->sensor_id = le16_to_cpu(_info.sensor_id);
@@ -533,8 +537,8 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
  	struct sensor_value buf;
  	int ret;

-	ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
-				&buf, sizeof(buf));
+	ret = scpi_info->send_msg(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
+				  &buf, sizeof(buf));
  	if (!ret)
  		*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
  			le32_to_cpu(buf.lo_val);
@@ -548,8 +552,8 @@ static int scpi_device_get_power_state(u16 dev_id)
  	u8 pstate;
  	__le16 id = cpu_to_le16(dev_id);

-	ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
-				sizeof(id), &pstate, sizeof(pstate));
+	ret = scpi_info->send_msg(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
+				  sizeof(id), &pstate, sizeof(pstate));
  	return ret ? ret : pstate;
  }

@@ -561,8 +565,8 @@ static int scpi_device_set_power_state(u16 dev_id, 
u8 pstate)
  		.pstate = pstate,
  	};

-	return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
-				 sizeof(dev_set), &stat, sizeof(stat));
+	return scpi_info->send_msg(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
+				   sizeof(dev_set), &stat, sizeof(stat));
  }

  static struct scpi_ops scpi_ops = {
@@ -591,8 +595,8 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
  	int ret;
  	struct scp_capabilities caps;

-	ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
-				&caps, sizeof(caps));
+	ret = scpi_info->send_msg(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+				  &caps, sizeof(caps));
  	if (!ret) {
  		info->protocol_version = le32_to_cpu(caps.protocol_version);
  		info->firmware_version = le32_to_cpu(caps.platform_version);
@@ -681,6 +685,14 @@ static int scpi_alloc_xfer_list(struct device *dev, 
struct scpi_chan *ch)
  	return 0;
  }

+static const struct of_device_id scpi_of_match[] = {
+	{.compatible = "arm,scpi", .data = scpi_send_message},
+	{.compatible = "arm,scpi-legacy", .data = scpi_send_message},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, scpi_of_match);
+
  static int scpi_probe(struct platform_device *pdev)
  {
  	int count, idx, ret;
@@ -688,11 +700,15 @@ static int scpi_probe(struct platform_device *pdev)
  	struct scpi_chan *scpi_chan;
  	struct device *dev = &pdev->dev;
  	struct device_node *np = dev->of_node;
+	const struct of_device_id *match;

  	scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
  	if (!scpi_info)
  		return -ENOMEM;

+	match = of_match_device(scpi_of_match, dev);
+	scpi_info->send_msg = match->data;
+
  	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
  	if (count < 0) {
  		dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -778,13 +794,6 @@ static int scpi_probe(struct platform_device *pdev)
  	return of_platform_populate(dev->of_node, NULL, NULL, dev);
  }

-static const struct of_device_id scpi_of_match[] = {
-	{.compatible = "arm,scpi"},
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, scpi_of_match);
-
  static struct platform_driver scpi_driver = {
  	.driver = {
  		.name = "scpi_protocol",


From martin.blumenstingl at googlemail.com  Mon Aug 15 06:38:08 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 15:38:08 +0200
Subject: [PATCH 0/3] eMMC, SD-card and ethernet support for Vega S95 boards
In-Reply-To: <20160625163446.7245-1-martin.blumenstingl@googlemail.com>
References: <20160625163446.7245-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815133811.19646-1-martin.blumenstingl@googlemail.com>

This adds support for the internal eMMC, the SD-card slot and ethernet on
all Tronsmart S95 Vega boards.
There are some S95 Vega Meta clones out there where the bootloader does
not configure the ethernet registers correctly, leading to non-working
ethernet. This will be fixed in a separate series. Boards which are not
suffering from broken bootloaders have fully working ethernet.

Changes since the RFC:
- added eMMC support
- renamed fixed 3V3 regulator so it can be re-used for eMMC

Martin Blumenstingl (3):
  ARM64: dts: amlogic: SD card support for all Tronsmart Vega S95
    devices
  ARM64: dts: amlogic: eMMC support for all Tronsmart Vega S95 devices
  ARM64: dts: amlogic: enable ethernet on all Tronsmart Vega S95 devices

 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      | 67 ++++++++++++++++++++++
 1 file changed, 67 insertions(+)

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 06:38:11 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 15:38:11 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: enable ethernet on all Tronsmart
 Vega S95 devices
In-Reply-To: <20160815133811.19646-1-martin.blumenstingl@googlemail.com>
References: <20160625163446.7245-1-martin.blumenstingl@googlemail.com>
 <20160815133811.19646-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815133811.19646-4-martin.blumenstingl@googlemail.com>

All of these have a Realtek Gbit RGMII PHY.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Tested-by: Andreas F?rber <afaerber at suse.de>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index af2e38e..5f50109 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -86,6 +86,12 @@
 
 };
 
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+};
+
 &sd_emmc_b {
 	status = "okay";
 	pinctrl-0 = <&sdcard_pins>;
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 06:38:09 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 15:38:09 +0200
Subject: [PATCH 1/3] ARM64: dts: amlogic: SD card support for all Tronsmart
 Vega S95 devices
In-Reply-To: <20160815133811.19646-1-martin.blumenstingl@googlemail.com>
References: <20160625163446.7245-1-martin.blumenstingl@googlemail.com>
 <20160815133811.19646-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815133811.19646-2-martin.blumenstingl@googlemail.com>

sd_emmc_b is routed to the SD-card. Unlike p20x there is no GPIO
regulator, meaning it only supports 3.3V (which seems to be hard-wired).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Tested-by: Andreas F?rber <afaerber at suse.de>
---
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 54bb7c7..4572ce2 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -52,6 +52,16 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	vcc_3v3: regulator at 0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "VCC3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		regulator-always-on;
+	};
 };
 
 &uart_AO {
@@ -60,3 +70,19 @@
 	pinctrl-names = "default";
 
 };
+
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vcc_3v3>;
+	voltage-ranges = <3300 3300>;
+};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 06:38:10 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 15:38:10 +0200
Subject: [PATCH 2/3] ARM64: dts: amlogic: eMMC support for all Tronsmart Vega
 S95 devices
In-Reply-To: <20160815133811.19646-1-martin.blumenstingl@googlemail.com>
References: <20160625163446.7245-1-martin.blumenstingl@googlemail.com>
 <20160815133811.19646-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815133811.19646-3-martin.blumenstingl@googlemail.com>

This adds eMMC support for all Tronsmart Vega S95 devices using
sd_emmc_c. This is implemented similar to the p20x boards (meaning it
uses fixed regulators).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 4572ce2..af2e38e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -62,6 +62,21 @@
 
 		regulator-always-on;
 	};
+
+	vcc_1v8: regulator at 1 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "VCC1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+
+		regulator-always-on;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 &uart_AO {
@@ -86,3 +101,23 @@
 	vmmc-supply = <&vcc_3v3>;
 	voltage-ranges = <3300 3300>;
 };
+
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	voltage-ranges = <1800 3300>;
+	vmmc-supply = <&vcc_3v3>;
+	vmmcq-sumpply = <&vcc_1v8>;
+};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 09:40:57 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 18:40:57 +0200
Subject: [PATCH 0/3] ARM64: meson: Meson8b and GXBB DWMAC glue driver
In-Reply-To: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
References: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>

This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.

Changes compared to the RFC version:
- switch from syscon / regmap to assigning the corresponding register
  region directly to the driver (like meson6-dwmac does it)
- dropped "fix_mac_speed" callback since the reference driver does not
  implement it (I could not test if it is required due to lack of
  hardware)
- switch to common clock framework now that we know what bits 5:4
  (mux clock), 6:5 (250MHz divider) and 10 (configurable 5 or 10
  divider) are used for
- Removed dts property "amlogic,mp2-clock" because it is now part of
  the clocks which are registered by the glue driver
- Removed dts properties "amlogic,enable-tx-phy-ref-clk" and
  "amlogic,tx-delay" because it seems we can guess them based on the
  phy-mode (the original Amlogic dts files only supply two different
  values: one value for the internal RMII PHY and another one for the
  external RGMII Gbit PHY).
  If required we can extend the code in the future to make these
  configurable.
- This means that the only Meson8b / GXBB specific part of the binding
  is the clkin0 (FCLK_DIV2) clock, as it's needed for the mux clock.
  Everything else is auto-detected based on the phy-mode (which is
  already mandatory in stmmac).

I have successfully tested this on a Vega S95 Meta clone which comes
with a "broken" bootloader (which programs the ethernet registers to
"Fast Ethernet / RGMII" mode, while the board has a Realtek Gbit PHY).
Before this series stmmac was detected, I got a network interface but
no traffic was flowing.

Due to lack of hardware I could not test this on a device which uses
the internal RMII (Fast Ethernet) PHY.


Martin Blumenstingl (3):
  net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
  net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
  ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver

 .../devicetree/bindings/net/meson-dwmac.txt        |  43 ++-
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   7 +-
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 327 +++++++++++++++++++++
 4 files changed, 367 insertions(+), 12 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 09:41:00 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 18:41:00 +0200
Subject: [PATCH 3/3] ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver
In-Reply-To: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
References: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815164100.27766-4-martin.blumenstingl@googlemail.com>

The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.

No changes are required to the board dts files because the only
required configuration option is the phy-mode, which had to be
configured correctly before as well.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 2c200f9..f8cf16e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -367,13 +367,14 @@
 		};
 
 		ethmac: ethernet at c9410000 {
-			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+			compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
 			reg = <0x0 0xc9410000 0x0 0x10000
 			       0x0 0xc8834540 0x0 0x4>;
 			interrupts = <0 8 1>;
 			interrupt-names = "macirq";
-			clocks = <&clkc CLKID_ETH>;
-			clock-names = "stmmaceth";
+			clocks = <&clkc CLKID_ETH>,
+				 <&clkc CLKID_FCLK_DIV2>;
+			clock-names = "stmmaceth", "clkin0";
 			phy-mode = "rgmii";
 			status = "disabled";
 		};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 09:40:58 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 18:40:58 +0200
Subject: [PATCH 1/3] net: dt-bindings: Document the new Meson8b and GXBB DWMAC
 bindings
In-Reply-To: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
References: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815164100.27766-2-martin.blumenstingl@googlemail.com>

This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 .../devicetree/bindings/net/meson-dwmac.txt        | 43 ++++++++++++++++++----
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/meson-dwmac.txt b/Documentation/devicetree/bindings/net/meson-dwmac.txt
index ec633d7..8db6899 100644
--- a/Documentation/devicetree/bindings/net/meson-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/meson-dwmac.txt
@@ -1,18 +1,31 @@
 * Amlogic Meson DWMAC Ethernet controller
 
 The device inherits all the properties of the dwmac/stmmac devices
-described in the file net/stmmac.txt with the following changes.
+described in the file stmmac.txt in the current directory with the
+following changes.
 
-Required properties:
+Required properties on all platforms:
 
-- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"
-	      and any applicable more detailed version number
-	      described in net/stmmac.txt
+- compatible:	Depending on the platform this should be one of:
+			- "amlogic,meson6-dwmac"
+			- "amlogic,meson8b-dwmac"
+			- "amlogic,meson-gxbb-dwmac"
+		Additionally "snps,dwmac" and any applicable more
+		detailed version number described in net/stmmac.txt
+		should be used.
 
-- reg: should contain a register range for the dwmac controller and
-       another one for the Amlogic specific configuration
+- reg:	The first register range should be the one of the DWMAC
+	controller. The second range is is for the Amlogic specific
+	configuration (for example the PRG_ETHERNET register range
+	on Meson8b and newer)
 
-Example:
+Required properties on Meson8b and newer:
+- clock-names:	Should contain the following:
+		- "stmmaceth" - see stmmac.txt
+		- "clkin0" - parent clock of internal mux (usually FCLK_DIV2)
+
+
+Example for Meson6:
 
 	ethmac: ethernet at c9410000 {
 		compatible = "amlogic,meson6-dwmac", "snps,dwmac";
@@ -23,3 +36,17 @@ Example:
 		clocks = <&clk81>;
 		clock-names = "stmmaceth";
 	}
+
+Example for GXBB:
+	ethmac: ethernet at c9410000 {
+		compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+		reg = <0x0 0xc9410000 0x0 0x10000>,
+			<0x0 0xc8834540 0x0 0x8>;
+		interrupts = <0 8 1>;
+		interrupt-names = "macirq";
+		clocks = <&clkc CLKID_ETH>,
+				<&clkc CLKID_FCLK_DIV2>;
+		clock-names = "stmmaceth", "clkin0";
+		phy-mode = "rgmii";
+		status = "disabled";
+	};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 09:40:59 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 18:40:59 +0200
Subject: [PATCH 2/3] net: stmmac: add a glue driver for the Amlogic Meson 8b /
 GXBB DWMAC
In-Reply-To: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
References: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160815164100.27766-3-martin.blumenstingl@googlemail.com>

The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.

In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.

Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 327 +++++++++++++++++++++
 2 files changed, 328 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 0fb362d..79e5d0c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -9,7 +9,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 obj-$(CONFIG_STMMAC_PLATFORM)	+= stmmac-platform.o
 obj-$(CONFIG_DWMAC_IPQ806X)	+= dwmac-ipq806x.o
 obj-$(CONFIG_DWMAC_LPC18XX)	+= dwmac-lpc18xx.o
-obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o
+obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o dwmac-meson8b.o
 obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-socfpga.o
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
new file mode 100644
index 0000000..0d4e152
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -0,0 +1,327 @@
+/*
+ * Amlogic Meson S805/S905 DWMAC glue layer
+ *
+ * Copyright (C) 20016 Martin Blumenstingl <martin.blumenstingl at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/clk-provider.h>
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_net.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+#define PRG_ETH0			0x0
+
+#define PRG_ETH0_RGMII_MODE		BIT(0)
+
+/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
+#define PRG_ETH0_CLK_M250_SEL_SHIFT	4
+#define PRG_ETH0_CLK_M250_SEL_MASK	GENMASK(4, 4)
+
+#define PRG_ETH0_TXDLY_SHIFT		5
+#define PRG_ETH0_TXDLY_MASK		GENMASK(6, 5)
+#define PRG_ETH0_TXDLY_OFF		(0x0 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_QUARTER		(0x1 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_HALF		(0x2 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_THREE_QUARTERS	(0x3 << PRG_ETH0_TXDLY_SHIFT)
+
+/* divider for the result of m250_sel */
+#define PRG_ETH0_CLK_M250_DIV_SHIFT	7
+#define PRG_ETH0_CLK_M250_DIV_WIDTH	3
+
+/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */
+#define PRG_ETH0_CLK_M25_DIV_SHIFT	10
+#define PRG_ETH0_CLK_M25_DIV_WIDTH	1
+
+#define PRG_ETH0_INVERTED_RMII_CLK	BIT(11)
+#define PRG_ETH0_TX_AND_PHY_REF_CLK	BIT(12)
+
+#define MUX_CLK_NUM_PARENTS		2
+
+struct meson8b_dwmac {
+	struct platform_device	*pdev;
+
+	void __iomem		*regs;
+
+	phy_interface_t		phy_mode;
+
+	struct clk_mux		m250_mux;
+	struct clk		*m250_mux_clk;
+	struct clk		*m250_mux_parent[MUX_CLK_NUM_PARENTS];
+
+	struct clk_divider	m250_div;
+	struct clk		*m250_div_clk;
+
+	struct clk_divider	m25_div;
+	struct clk		*m25_div_clk;
+};
+
+static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
+				    u32 mask, u32 value)
+{
+	u32 data;
+
+	data = readl(dwmac->regs + reg);
+	data &= ~mask;
+	data |= (value & mask);
+
+	writel(data, dwmac->regs + reg);
+}
+
+static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
+{
+	struct clk_init_data init;
+	int i, ret;
+	struct device *dev = &dwmac->pdev->dev;
+	char clk_name[32];
+	const char *clk_div_parents[1];
+	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+	unsigned int mux_parent_count = 0;
+	static struct clk_div_table clk_25m_div_table[] = {
+		{ .val = 0, .div = 5 },
+		{ .val = 1, .div = 10 },
+		{ /* sentinel */ },
+	};
+
+	/* get the mux parents from DT */
+	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+		char name[16];
+
+		snprintf(name, sizeof(name), "clkin%d", i);
+		dwmac->m250_mux_parent[i] = devm_clk_get(dev, name);
+		if (IS_ERR(dwmac->m250_mux_parent[i])) {
+			/* NOTE: the second clock (MP2) is unused on all known
+			 * boards, thus we're making it optional here.
+			 */
+			if (i > 0)
+				continue;
+
+			ret = PTR_ERR(dwmac->m250_mux_parent[i]);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Missing clock %s\n", name);
+			dwmac->m250_mux_parent[i] = NULL;
+			return ret;
+		}
+
+		mux_parent_names[i] =
+			__clk_get_name(dwmac->m250_mux_parent[i]);
+		mux_parent_count++;
+	}
+
+	/* create the m250_mux */
+	snprintf(clk_name, sizeof(clk_name), "%s#m250_sel", dev_name(dev));
+	init.name = clk_name;
+	init.ops = &clk_mux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = mux_parent_names;
+	init.num_parents = mux_parent_count;
+
+	dwmac->m250_mux.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
+	dwmac->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
+	dwmac->m250_mux.flags = 0;
+	dwmac->m250_mux.table = NULL;
+	dwmac->m250_mux.hw.init = &init;
+
+	dwmac->m250_mux_clk = devm_clk_register(dev, &dwmac->m250_mux.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))
+		return PTR_ERR(dwmac->m250_mux_clk);
+
+	/* create the m250_div */
+	snprintf(clk_name, sizeof(clk_name), "%s#m250_div", dev_name(dev));
+	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(dwmac->m250_mux_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	dwmac->m250_div.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
+	dwmac->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
+	dwmac->m250_div.hw.init = &init;
+	dwmac->m250_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+
+	dwmac->m250_div_clk = devm_clk_register(dev, &dwmac->m250_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))
+		return PTR_ERR(dwmac->m250_div_clk);
+
+	/* create the m25_div */
+	snprintf(clk_name, sizeof(clk_name), "%s#m25_div", dev_name(dev));
+	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(dwmac->m250_div_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	dwmac->m25_div.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m25_div.shift = PRG_ETH0_CLK_M25_DIV_SHIFT;
+	dwmac->m25_div.width = PRG_ETH0_CLK_M25_DIV_WIDTH;
+	dwmac->m25_div.table = clk_25m_div_table;
+	dwmac->m25_div.hw.init = &init;
+	dwmac->m25_div.flags = CLK_DIVIDER_ALLOW_ZERO;
+
+	dwmac->m25_div_clk = devm_clk_register(dev, &dwmac->m25_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))
+		return PTR_ERR(dwmac->m25_div_clk);
+
+	return 0;
+}
+
+static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
+{
+	int ret;
+	unsigned long clk_rate;
+
+	switch (dwmac->phy_mode) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		/* Generate a 25MHz clock for the PHY */
+		clk_rate = 25 * 1000 * 1000;
+
+		/* enable RGMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
+					PRG_ETH0_RGMII_MODE);
+
+		/* only relevant for RMII mode -> disable in RGMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+					PRG_ETH0_INVERTED_RMII_CLK, 0);
+
+		/* TX clock delay - all known boards use a 1/4 cycle delay */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+					PRG_ETH0_TXDLY_QUARTER);
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
+		/* Use the rate of the mux clock for the internal RMII PHY */
+		clk_rate = clk_get_rate(dwmac->m250_mux_clk);
+
+		/* disable RGMII mode -> enables RMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
+					0);
+
+		/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+					PRG_ETH0_INVERTED_RMII_CLK,
+					PRG_ETH0_INVERTED_RMII_CLK);
+
+		/* TX clock delay cannot be configured in RMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+					0);
+
+		break;
+
+	default:
+		dev_err(&dwmac->pdev->dev, "unsupported phy-mode %s\n",
+			phy_modes(dwmac->phy_mode));
+		return -EINVAL;
+	}
+
+	ret = clk_prepare_enable(dwmac->m25_div_clk);
+	if (ret) {
+		dev_err(&dwmac->pdev->dev, "failed to enable the PHY clock\n");
+		return ret;
+	}
+
+	ret = clk_set_rate(dwmac->m25_div_clk, clk_rate);
+	if (ret) {
+		clk_disable_unprepare(dwmac->m25_div_clk);
+
+		dev_err(&dwmac->pdev->dev, "failed to set PHY clock\n");
+		return ret;
+	}
+
+	/* enable TX_CLK and PHY_REF_CLK generator */
+	meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
+				PRG_ETH0_TX_AND_PHY_REF_CLK);
+
+	return 0;
+}
+
+static int meson8b_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct resource *res;
+	struct meson8b_dwmac *dwmac;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return PTR_ERR(plat_dat);
+
+	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+	if (!dwmac)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -ENODEV;
+
+	dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dwmac->regs))
+		return PTR_ERR(dwmac->regs);
+
+	dwmac->pdev = pdev;
+	dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
+	if (dwmac->phy_mode < 0) {
+		dev_err(&pdev->dev, "missing phy-mode property\n");
+		return -EINVAL;
+	}
+
+	ret = meson8b_init_clk(dwmac);
+	if (ret)
+		return ret;
+
+	ret = meson8b_init_prg_eth(dwmac);
+	if (ret)
+		return ret;
+
+	plat_dat->bsp_priv = dwmac;
+
+	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+}
+
+static const struct of_device_id meson8b_dwmac_match[] = {
+	{ .compatible = "amlogic,meson8b-dwmac" },
+	{ .compatible = "amlogic,meson-gxbb-dwmac" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
+
+static struct platform_driver meson8b_dwmac_driver = {
+	.probe  = meson8b_dwmac_probe,
+	.remove = stmmac_pltfr_remove,
+	.driver = {
+		.name           = "meson8b-dwmac",
+		.pm		= &stmmac_pltfr_pm_ops,
+		.of_match_table = meson8b_dwmac_match,
+	},
+};
+module_platform_driver(meson8b_dwmac_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl at googlemail.com>");
+MODULE_DESCRIPTION("Amlogic Meson S805/S905 DWMAC glue layer");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Mon Aug 15 09:55:30 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 18:55:30 +0200
Subject: [PATCH v2 1/4] pwm: Add support for Meson PWM Controller
In-Reply-To: <1468142645-4360-2-git-send-email-narmstrong@baylibre.com>
References: <1468142645-4360-1-git-send-email-narmstrong@baylibre.com>
 <1468142645-4360-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CAFBinCAXJ_POd9=UhL8vM6_sXXgVMgSZCwDKosLSzW2++ZmTQQ@mail.gmail.com>

On Sun, Jul 10, 2016 at 11:24 AM, Neil Armstrong
<narmstrong at baylibre.com> wrote:
> Add support for the PWM controller found in the Amlogic SoCs.
> This driver supports the Meson8b and GXBB SoCs.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/pwm/Kconfig     |   9 +
>  drivers/pwm/Makefile    |   1 +
>  drivers/pwm/pwm-meson.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 501 insertions(+)
>  create mode 100644 drivers/pwm/pwm-meson.c
>
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index c182efc..cad5286 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -245,6 +245,15 @@ config PWM_LPSS_PLATFORM
>           To compile this driver as a module, choose M here: the module
>           will be called pwm-lpss-platform.
>
> +config PWM_MESON
> +       tristate "Amlogic Meson PWM driver"
> +       depends on ARCH_MESON
> +       help
> +         The platform driver for Amlogic Meson PWM controller.
> +
> +         To compile this driver as a module, choose M here: the module
> +         will be called pwm-meson.
> +
>  config PWM_MTK_DISP
>         tristate "MediaTek display PWM driver"
>         depends on ARCH_MEDIATEK || COMPILE_TEST
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index dd35bc1..3c8843e 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_PWM_LPC32XX)     += pwm-lpc32xx.o
>  obj-$(CONFIG_PWM_LPSS)         += pwm-lpss.o
>  obj-$(CONFIG_PWM_LPSS_PCI)     += pwm-lpss-pci.o
>  obj-$(CONFIG_PWM_LPSS_PLATFORM)        += pwm-lpss-platform.o
> +obj-$(CONFIG_PWM_MESON)                += pwm-meson.o
>  obj-$(CONFIG_PWM_MTK_DISP)     += pwm-mtk-disp.o
>  obj-$(CONFIG_PWM_MXS)          += pwm-mxs.o
>  obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
> diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
> new file mode 100644
> index 0000000..9e7ecf5
> --- /dev/null
> +++ b/drivers/pwm/pwm-meson.c
> @@ -0,0 +1,491 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + * Copyright (C) 2014 Amlogic, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + * Copyright (C) 2014 Amlogic, Inc.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/pwm.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/of.h>
> +
> +#define REG_PWM_A      0x0
> +#define REG_PWM_B      0x4
> +#define PWM_HIGH_SHIFT 16
> +
> +#define REG_MISC_AB    0x8
> +#define MISC_B_CLK_EN  BIT(23)
> +#define MISC_A_CLK_EN  BIT(15)
> +#define MISC_CLK_DIV_MASK      0x7f
> +#define MISC_B_CLK_DIV_SHIFT   16
> +#define MISC_A_CLK_DIV_SHIFT   8
> +#define MISC_B_CLK_SEL_SHIFT   6
> +#define MISC_A_CLK_SEL_SHIFT   4
> +#define MISC_CLK_SEL_WIDTH     2
> +#define MISC_B_EN      BIT(1)
> +#define MISC_A_EN      BIT(0)
> +
> +#define PWM_NUM                2
> +
> +static const unsigned int mux_reg_shifts[PWM_NUM] = {
> +       MISC_A_CLK_SEL_SHIFT, MISC_B_CLK_SEL_SHIFT
> +};
> +
> +static const char * const pwm_parents[] = {
> +       "xtal", "vid_pll", "fclk_div4", "fclk_div3", NULL
> +};
> +
> +enum pwm_channel {
> +       PWM_A = 0,
> +       PWM_B,
> +};
> +
> +struct meson_pwm_channel {
> +       unsigned int pwm_hi;
> +       unsigned int pwm_lo;
> +       u8 pwm_pre_div;
> +       int period;
> +       int duty;
> +};
> +
> +struct meson_pwm_chip {
> +       struct platform_device *pdev;
> +       struct pwm_chip chip;
> +       void __iomem *base;
> +       u8 inverter_mask;
> +       spinlock_t lock;
> +       struct clk *clk_parents[PWM_NUM];
> +       struct clk_mux mux[PWM_NUM];
> +       struct clk *clk[PWM_NUM];
> +};
> +
> +#define to_meson_pwm_chip(chip) \
> +       container_of(chip, struct meson_pwm_chip, chip)
> +
> +static int meson_pwm_calc(struct meson_pwm_chip *chip,
> +                              struct meson_pwm_channel *pwm_chan,
> +                              unsigned int id,
> +                              int duty_ns, unsigned int period_ns)
> +{
> +       unsigned int pwm_pre_div;
> +       unsigned int pwm_cnt;
> +       unsigned int pwm_duty_cnt;
> +       unsigned long fin_freq = -1;
> +       unsigned long fin_ns;
> +       unsigned int i = 0;
> +
> +       if (duty_ns > period_ns)
> +               return -EINVAL;
> +
> +       switch (id) {
> +       case PWM_A:
> +               fin_freq = clk_get_rate(chip->clk[0]);
> +               break;
> +       case PWM_B:
> +               fin_freq = clk_get_rate(chip->clk[1]);
> +               break;
> +       }
> +       if (fin_freq <= 0) {
> +               dev_err(chip->chip.dev, "invalid source clock frequency\n");
> +               return -EINVAL;
> +       }
> +       dev_dbg(chip->chip.dev, "fin_freq: %luHz\n", fin_freq);
> +       fin_ns = NSEC_PER_SEC / fin_freq;
> +
> +       /* Calc pre_div with the period */
> +       for (i = 0; i < MISC_CLK_DIV_MASK; i++) {
> +               pwm_pre_div = i;
according to the public (S905) datasheet the hardware wants "value
+1": "Selects the divider (N+1) for the PWM A clock"
so shouldn't this be pwm_pre_div = i + 1?
all your calculations below are already adding 1 to pwm_pre_div, but
pwm_pre_div is directly written to the hardware register in
meson_pwm_config()

> +               pwm_cnt = DIV_ROUND_CLOSEST(period_ns,
> +                               fin_ns * (pwm_pre_div + 1));
> +               dev_dbg(chip->chip.dev, "fin_ns=%lu pre_div=%d cnt=%d\n",
> +                               fin_ns, pwm_pre_div, pwm_cnt);
> +               if (pwm_cnt <= 0xffff)
> +                       break;
> +       }
> +       if (i == MISC_CLK_DIV_MASK) {
> +               dev_err(chip->chip.dev, "Unable to get period pre_div");
> +               return -EINVAL;
> +       }
> +       dev_dbg(chip->chip.dev, "period_ns=%d pre_div=%d pwm_cnt=%d\n",
> +               period_ns, pwm_pre_div, pwm_cnt);
> +
> +       if (duty_ns == period_ns) {
> +               pwm_chan->pwm_pre_div = pwm_pre_div;
> +               pwm_chan->pwm_hi = pwm_cnt;
> +               pwm_chan->pwm_lo = 0;
> +       } else if (duty_ns == 0) {
> +               pwm_chan->pwm_pre_div = pwm_pre_div;
> +               pwm_chan->pwm_hi = 0;
> +               pwm_chan->pwm_lo = pwm_cnt;
> +       } else {
> +               /* Then check is we can have the duty with the same pre_div */
> +               pwm_duty_cnt = DIV_ROUND_CLOSEST(duty_ns,
> +                                       fin_ns * (pwm_pre_div + 1));
> +               if (pwm_cnt > 0xffff) {
> +                       dev_err(chip->chip.dev, "Unable to get duty period, differences are too high");
> +                       return -EINVAL;
> +               }
> +               dev_dbg(chip->chip.dev, "duty_ns=%d pre_div=%d pwm_cnt=%d\n",
> +                       duty_ns, pwm_pre_div, pwm_duty_cnt);
> +
> +               pwm_chan->pwm_pre_div = pwm_pre_div;
> +               pwm_chan->pwm_hi = pwm_duty_cnt;
> +               pwm_chan->pwm_lo = pwm_cnt - pwm_chan->pwm_hi;
> +       }
> +
> +       return 0;
> +}
> +
> +static int meson_pwm_request(struct pwm_chip *chip,
> +                                 struct pwm_device *pwm)
> +{
> +       struct meson_pwm_channel *pwm_chan;
> +
> +       pwm_chan = devm_kzalloc(chip->dev, sizeof(*pwm_chan), GFP_KERNEL);
> +       if (!pwm_chan)
> +               return -ENOMEM;
> +
> +       pwm_set_chip_data(pwm, pwm_chan);
> +
> +       return 0;
> +}
> +
> +static void meson_pwm_free(struct pwm_chip *chip,
> +                               struct pwm_device *pwm)
> +{
> +       devm_kfree(chip->dev, pwm_get_chip_data(pwm));
> +       pwm_set_chip_data(pwm, NULL);
> +}
> +
> +static int meson_pwm_enable(struct pwm_chip *chip,
> +                                struct pwm_device *pwm)
> +{
> +       struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
> +       unsigned int id = pwm->hwpwm;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&pwm_data->lock, flags);
> +       switch (id) {
> +       case PWM_A:
> +               writel(readl(pwm_data->base + REG_MISC_AB) | MISC_A_EN,
> +                       pwm_data->base + REG_MISC_AB);
> +               break;
> +
> +       case PWM_B:
> +               writel(readl(pwm_data->base + REG_MISC_AB) | MISC_B_EN,
> +                       pwm_data->base + REG_MISC_AB);
> +               break;
> +
> +       default:
> +               break;
> +       }
> +       spin_unlock_irqrestore(&pwm_data->lock, flags);
> +
> +       return 0;
> +}
> +
> +static void meson_pwm_disable(struct pwm_chip *chip,
> +                                  struct pwm_device *pwm)
> +{
> +       struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
> +       unsigned int id = pwm->hwpwm;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&pwm_data->lock, flags);
> +       switch (id) {
> +       case PWM_A:
> +               writel(readl(pwm_data->base + REG_MISC_AB) & ~MISC_A_EN,
> +                       pwm_data->base + REG_MISC_AB);
> +               break;
> +
> +       case PWM_B:
> +               writel(readl(pwm_data->base + REG_MISC_AB) & ~MISC_B_EN,
> +                       pwm_data->base + REG_MISC_AB);
> +               break;
> +
> +       default:
> +               break;
> +       }
> +       spin_unlock_irqrestore(&pwm_data->lock, flags);
> +}
> +
> +static int meson_pwm_config(struct pwm_chip *chip,
> +                                struct pwm_device *pwm,
> +                                int duty_ns,
> +                                int period_ns)
> +{
> +       struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
> +       struct meson_pwm_channel *pwm_chan = pwm_get_chip_data(pwm);
> +       unsigned int id = pwm->hwpwm;
> +       int ret;
> +
> +       if ((~(pwm_data->inverter_mask >> id) & 0x1))
> +               duty_ns = period_ns - duty_ns;
> +
> +       if (period_ns == pwm_chan->period && duty_ns == pwm_chan->duty)
> +               return 0;
> +
> +       ret = meson_pwm_calc(pwm_data, pwm_chan, id, duty_ns, period_ns);
> +       if (ret) {
> +               dev_err(chip->dev, "error while calculating pwm parameters\n");
> +               return ret;
> +       }
> +
> +       switch (id) {
> +       case PWM_A:
> +               writel((readl(pwm_data->base + REG_MISC_AB) &
> +                       ~(MISC_CLK_DIV_MASK << MISC_A_CLK_DIV_SHIFT)) |
> +                       ((pwm_chan->pwm_pre_div << MISC_A_CLK_DIV_SHIFT) |
> +                        MISC_A_CLK_EN),
> +                       pwm_data->base + REG_MISC_AB);
> +
> +               writel((pwm_chan->pwm_hi << PWM_HIGH_SHIFT) |
> +                      (pwm_chan->pwm_lo),
> +                      pwm_data->base + REG_PWM_A);
> +               break;
> +
> +       case PWM_B:
> +               writel((readl(pwm_data->base + REG_MISC_AB) &
> +                       ~(MISC_CLK_DIV_MASK << MISC_B_CLK_DIV_SHIFT)) |
> +                       ((pwm_chan->pwm_pre_div << MISC_B_CLK_DIV_SHIFT) |
> +                        MISC_B_CLK_EN),
> +                       pwm_data->base + REG_MISC_AB);
> +
> +               writel((pwm_chan->pwm_hi << PWM_HIGH_SHIFT) |
> +                      (pwm_chan->pwm_lo),
> +                      pwm_data->base + REG_PWM_B);
> +               break;
> +
> +       default:
> +               break;
> +       }
> +
> +       pwm_chan->period = period_ns;
> +       pwm_chan->duty = duty_ns;
> +
> +       return 0;
> +}
> +
> +static int meson_pwm_set_polarity(struct pwm_chip *chip,
> +                                   struct pwm_device *pwm,
> +                                   enum pwm_polarity polarity)
> +{
> +       struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
> +       struct meson_pwm_channel *pwm_chan = pwm_get_chip_data(pwm);
> +       bool invert = (polarity == PWM_POLARITY_NORMAL);
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&pwm_data->lock, flags);
> +
> +       if (invert)
> +               pwm_data->inverter_mask |= BIT(pwm->hwpwm);
> +       else
> +               pwm_data->inverter_mask &= ~BIT(pwm->hwpwm);
> +
> +       meson_pwm_config(chip, pwm, pwm_chan->duty, pwm_chan->period);
> +
> +       spin_unlock_irqrestore(&pwm_data->lock, flags);
> +
> +       return 0;
> +}
> +
> +static const struct pwm_ops meson_pwm_ops = {
> +       .request        = meson_pwm_request,
> +       .free           = meson_pwm_free,
> +       .enable         = meson_pwm_enable,
> +       .disable        = meson_pwm_disable,
> +       .config         = meson_pwm_config,
> +       .set_polarity   = meson_pwm_set_polarity,
> +       .owner          = THIS_MODULE,
> +};
> +
> +static const struct of_device_id meson_pwm_matches[] = {
> +       { .compatible = "amlogic,meson8b-pwm", },
> +       { .compatible = "amlogic,meson-gxbb-pwm", },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, meson_pwm_matches);
> +
> +static int meson_pwm_mux_init(struct meson_pwm_chip *chip)
> +{
> +       struct device *dev = &chip->pdev->dev;
> +       struct clk_init_data init;
> +       char clk_name[255];
> +       int ret;
> +       int i;
> +
> +       for (i = 0 ; i < PWM_NUM ; ++i) {
> +               sprintf(clk_name, "%s#mux%d",
> +                               of_node_full_name(dev->of_node), i);
> +
> +               init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
> +               init.ops = &clk_mux_ops;
> +               init.flags = CLK_IS_BASIC;
> +               init.parent_names = pwm_parents;
> +               init.num_parents = 1 << MISC_CLK_SEL_WIDTH;
> +
> +               chip->mux[i].reg = chip->base + REG_MISC_AB;
> +               chip->mux[i].shift = mux_reg_shifts[i];
> +               chip->mux[i].mask = BIT(MISC_CLK_SEL_WIDTH) - 1;
> +               chip->mux[i].flags = 0;
> +               chip->mux[i].lock = &chip->lock;
> +               chip->mux[i].table = NULL;
> +               chip->mux[i].hw.init = &init;
> +
> +               chip->clk[i] = devm_clk_register(dev, &chip->mux[i].hw);
> +               if (IS_ERR(chip->clk[i])) {
> +                       dev_err(dev, "Failed to register %s\n", clk_name);
> +                       return PTR_ERR(chip->clk[i]);
> +               }
> +
> +               if (chip->clk_parents[i]) {
> +                       ret = clk_set_parent(chip->clk[i],
> +                                            chip->clk_parents[i]);
> +                       if (ret) {
> +                               dev_err(dev, "Failed to set %s parent\n",
> +                                       clk_name);
> +                               return ret;
> +                       }
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int meson_pwm_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct meson_pwm_chip *chip;
> +       struct resource *res;
> +       int ret;
> +
> +       chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
> +       if (chip == NULL)
> +               return -ENOMEM;
> +
> +       chip->pdev = pdev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       chip->base = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(chip->base))
> +               return PTR_ERR(chip->base);
> +
> +       chip->clk_parents[0] = devm_clk_get(dev, "clkin0");
> +       if (IS_ERR(chip->clk_parents[0])) {
> +               if (PTR_ERR(chip->clk_parents[0]) == -EPROBE_DEFER)
> +                       return PTR_ERR(chip->clk_parents[0]);
> +               chip->clk_parents[0] = NULL;
> +       }
> +
> +       chip->clk_parents[1] = devm_clk_get(dev, "clkin1");
> +       if (IS_ERR(chip->clk_parents[1])) {
> +               if (PTR_ERR(chip->clk_parents[1]) == -EPROBE_DEFER)
> +                       return PTR_ERR(chip->clk_parents[1]);
> +               chip->clk_parents[1] = NULL;
> +       }
> +
> +       ret = meson_pwm_mux_init(chip);
> +       if (ret)
> +               return ret;
> +
> +       clk_prepare_enable(chip->clk[0]);
> +       clk_prepare_enable(chip->clk[1]);
> +
> +       chip->chip.dev = dev;
> +       chip->chip.ops = &meson_pwm_ops;
> +       chip->chip.base = -1;
> +       chip->chip.npwm = PWM_NUM;
> +       chip->chip.of_xlate = of_pwm_xlate_with_flags;
> +       chip->chip.of_pwm_n_cells = 3;
> +       chip->inverter_mask = BIT(PWM_NUM) - 1;
> +
> +       ret = pwmchip_add(&chip->chip);
> +       if (ret < 0) {
> +               dev_err(dev, "failed to register PWM chip\n");
> +               return ret;
> +       }
> +
> +       platform_set_drvdata(pdev, chip);
> +
> +       return 0;
> +}
> +
> +static int meson_pwm_remove(struct platform_device *pdev)
> +{
> +       struct meson_pwm_chip *chip = platform_get_drvdata(pdev);
> +
> +       return pwmchip_remove(&chip->chip);
> +}
> +
> +static struct platform_driver meson_pwm_driver = {
> +       .driver         = {
> +               .name   = "meson-pwm",
> +               .of_match_table = of_match_ptr(meson_pwm_matches),
> +       },
> +       .probe          = meson_pwm_probe,
> +       .remove         = meson_pwm_remove,
> +};
> +module_platform_driver(meson_pwm_driver);
> +
> +MODULE_ALIAS("platform:meson-pwm");
> +MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
> +MODULE_LICENSE("Dual BSD/GPL");
> --
> 2.7.0
>
>
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic


From khilman at baylibre.com  Mon Aug 15 10:38:44 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 15 Aug 2016 12:38:44 -0500
Subject: [PATCH] clk: gxbb: add MMC gate clocks, and expose for DT
In-Reply-To: <20160802214011.19077-1-khilman@baylibre.com> (Kevin Hilman's
 message of "Tue, 2 Aug 2016 14:40:11 -0700")
References: <20160802214011.19077-1-khilman@baylibre.com>
Message-ID: <m2twem9bkr.fsf@baylibre.com>

Kevin Hilman <khilman at baylibre.com> writes:

> Add the SD/eMMC gate clocks and expose them for use by DT.
>
> While at it, also explose FCLK_DIV2 since this is one of the input
> clocks to the mux internal to each of the SD/eMMC blocks.
>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Gentle reminder ping.

> ---
> Applies on top of current clk-s905 branch.
>
>  drivers/clk/meson/gxbb.c              | 9 +++++++++
>  drivers/clk/meson/gxbb.h              | 7 +++++--
>  include/dt-bindings/clock/gxbb-clkc.h | 4 ++++
>  3 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 007b7157cf4b..4fc8e58feef9 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -581,6 +581,9 @@ static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17);
>  static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18);
>  static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19);
>  static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23);
> +static MESON_GATE(emmc_a, HHI_GCLK_MPEG0, 24);
> +static MESON_GATE(emmc_b, HHI_GCLK_MPEG0, 25);
> +static MESON_GATE(emmc_c, HHI_GCLK_MPEG0, 26);
>  static MESON_GATE(spi, HHI_GCLK_MPEG0, 30);
>  
>  static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2);
> @@ -746,6 +749,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
>  		[CLKID_AO_AHB_BUS]	    = &gxbb_ao_ahb_bus.hw,
>  		[CLKID_AO_IFACE]	    = &gxbb_ao_iface.hw,
>  		[CLKID_AO_I2C]		    = &gxbb_ao_i2c.hw,
> +		[CLKID_SD_EMMC_A]	    = &gxbb_emmc_a.hw,
> +		[CLKID_SD_EMMC_B]	    = &gxbb_emmc_b.hw,
> +		[CLKID_SD_EMMC_C]	    = &gxbb_emmc_c.hw,
>  	},
>  	.num = NR_CLKS,
>  };
> @@ -845,6 +851,9 @@ static struct clk_gate *gxbb_clk_gates[] = {
>  	&gxbb_ao_ahb_bus,
>  	&gxbb_ao_iface,
>  	&gxbb_ao_i2c,
> +	&gxbb_emmc_a,
> +	&gxbb_emmc_b,
> +	&gxbb_emmc_c,
>  };
>  
>  static int gxbb_clkc_probe(struct platform_device *pdev)
> diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
> index a2adf3448b59..217df516de44 100644
> --- a/drivers/clk/meson/gxbb.h
> +++ b/drivers/clk/meson/gxbb.h
> @@ -172,7 +172,7 @@
>  /* CLKID_CPUCLK */
>  #define CLKID_HDMI_PLL		  2
>  #define CLKID_FIXED_PLL		  3
> -#define CLKID_FCLK_DIV2		  4
> +/* CLKID_FCLK_DIV2 */
>  #define CLKID_FCLK_DIV3		  5
>  #define CLKID_FCLK_DIV4		  6
>  #define CLKID_FCLK_DIV5		  7
> @@ -262,8 +262,11 @@
>  #define CLKID_AO_AHB_BUS	  91
>  #define CLKID_AO_IFACE		  92
>  #define CLKID_AO_I2C		  93
> +/* CLKID_SD_EMMC_A */
> +/* CLKID_SD_EMMC_B */
> +/* CLKID_SD_EMMC_C */
>  
> -#define NR_CLKS			  94
> +#define NR_CLKS			  97
>  
>  /* include the CLKIDs that have been made part of the stable DT binding */
>  #include <dt-bindings/clock/gxbb-clkc.h>
> diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
> index f889d80246cb..7d418643cdcc 100644
> --- a/include/dt-bindings/clock/gxbb-clkc.h
> +++ b/include/dt-bindings/clock/gxbb-clkc.h
> @@ -6,7 +6,11 @@
>  #define __GXBB_CLKC_H
>  
>  #define CLKID_CPUCLK		1
> +#define CLKID_FCLK_DIV2		4
>  #define CLKID_CLK81		12
>  #define CLKID_ETH		36
> +#define CLKID_SD_EMMC_A		94
> +#define CLKID_SD_EMMC_B		95
> +#define CLKID_SD_EMMC_C		96
>  
>  #endif /* __GXBB_CLKC_H */


From martin.blumenstingl at googlemail.com  Mon Aug 15 11:40:08 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 15 Aug 2016 20:40:08 +0200
Subject: [PATCH] clk: gxbb: add MMC gate clocks, and expose for DT
In-Reply-To: <20160802214011.19077-1-khilman@baylibre.com>
References: <20160802214011.19077-1-khilman@baylibre.com>
Message-ID: <CAFBinCDaow3au1an8yKbVV3qNkzpjXsFOD-cUdRT+KOm-FGVJg@mail.gmail.com>

On Tue, Aug 2, 2016 at 11:40 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Add the SD/eMMC gate clocks and expose them for use by DT.
>
> While at it, also explose FCLK_DIV2 since this is one of the input
> clocks to the mux internal to each of the SD/eMMC blocks.
>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>
my Meson8b / GXBB DWMAC glue series needs this as well.
This worked fine during my tests, so:

Tested-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

> ---
> Applies on top of current clk-s905 branch.
>
>  drivers/clk/meson/gxbb.c              | 9 +++++++++
>  drivers/clk/meson/gxbb.h              | 7 +++++--
>  include/dt-bindings/clock/gxbb-clkc.h | 4 ++++
>  3 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 007b7157cf4b..4fc8e58feef9 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -581,6 +581,9 @@ static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17);
>  static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18);
>  static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19);
>  static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23);
> +static MESON_GATE(emmc_a, HHI_GCLK_MPEG0, 24);
> +static MESON_GATE(emmc_b, HHI_GCLK_MPEG0, 25);
> +static MESON_GATE(emmc_c, HHI_GCLK_MPEG0, 26);
>  static MESON_GATE(spi, HHI_GCLK_MPEG0, 30);
>
>  static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2);
> @@ -746,6 +749,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
>                 [CLKID_AO_AHB_BUS]          = &gxbb_ao_ahb_bus.hw,
>                 [CLKID_AO_IFACE]            = &gxbb_ao_iface.hw,
>                 [CLKID_AO_I2C]              = &gxbb_ao_i2c.hw,
> +               [CLKID_SD_EMMC_A]           = &gxbb_emmc_a.hw,
> +               [CLKID_SD_EMMC_B]           = &gxbb_emmc_b.hw,
> +               [CLKID_SD_EMMC_C]           = &gxbb_emmc_c.hw,
>         },
>         .num = NR_CLKS,
>  };
> @@ -845,6 +851,9 @@ static struct clk_gate *gxbb_clk_gates[] = {
>         &gxbb_ao_ahb_bus,
>         &gxbb_ao_iface,
>         &gxbb_ao_i2c,
> +       &gxbb_emmc_a,
> +       &gxbb_emmc_b,
> +       &gxbb_emmc_c,
>  };
>
>  static int gxbb_clkc_probe(struct platform_device *pdev)
> diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
> index a2adf3448b59..217df516de44 100644
> --- a/drivers/clk/meson/gxbb.h
> +++ b/drivers/clk/meson/gxbb.h
> @@ -172,7 +172,7 @@
>  /* CLKID_CPUCLK */
>  #define CLKID_HDMI_PLL           2
>  #define CLKID_FIXED_PLL                  3
> -#define CLKID_FCLK_DIV2                  4
> +/* CLKID_FCLK_DIV2 */
>  #define CLKID_FCLK_DIV3                  5
>  #define CLKID_FCLK_DIV4                  6
>  #define CLKID_FCLK_DIV5                  7
> @@ -262,8 +262,11 @@
>  #define CLKID_AO_AHB_BUS         91
>  #define CLKID_AO_IFACE           92
>  #define CLKID_AO_I2C             93
> +/* CLKID_SD_EMMC_A */
> +/* CLKID_SD_EMMC_B */
> +/* CLKID_SD_EMMC_C */
>
> -#define NR_CLKS                          94
> +#define NR_CLKS                          97
>
>  /* include the CLKIDs that have been made part of the stable DT binding */
>  #include <dt-bindings/clock/gxbb-clkc.h>
> diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
> index f889d80246cb..7d418643cdcc 100644
> --- a/include/dt-bindings/clock/gxbb-clkc.h
> +++ b/include/dt-bindings/clock/gxbb-clkc.h
> @@ -6,7 +6,11 @@
>  #define __GXBB_CLKC_H
>
>  #define CLKID_CPUCLK           1
> +#define CLKID_FCLK_DIV2                4
>  #define CLKID_CLK81            12
>  #define CLKID_ETH              36
> +#define CLKID_SD_EMMC_A                94
> +#define CLKID_SD_EMMC_B                95
> +#define CLKID_SD_EMMC_C                96
>
>  #endif /* __GXBB_CLKC_H */
> --
> 2.9.0
>
>
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic


From khilman at baylibre.com  Mon Aug 15 13:40:21 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 15 Aug 2016 13:40:21 -0700
Subject: [PATCH v3 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <CAOi56cUQaFKYu2jNP0AuLOSNnNramu+DNPc+PH7K0gHDZMf+zA@mail.gmail.com>
 (Kevin Hilman's message of "Wed, 3 Aug 2016 17:29:13 -0700")
References: <1468141867-4172-1-git-send-email-narmstrong@baylibre.com>
 <1468141867-4172-4-git-send-email-narmstrong@baylibre.com>
 <578271D3.4080704@roeck-us.net> <7hbn237aw7.fsf@baylibre.com>
 <m2bn19qsy3.fsf@baylibre.com>
 <CAOi56cUQaFKYu2jNP0AuLOSNnNramu+DNPc+PH7K0gHDZMf+zA@mail.gmail.com>
Message-ID: <7hinv1ahqi.fsf@baylibre.com>

Kevin Hilman <khilman at baylibre.com> writes:

> On Wed, Aug 3, 2016 at 5:27 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>> Hi Guenter,
>>
>> Kevin Hilman <khilman at baylibre.com> writes:
>>
>>> Guenter Roeck <linux at roeck-us.net> writes:
>>>
>>>> On 07/10/2016 02:11 AM, Neil Armstrong wrote:
>>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>>
>>>> Reviewed-by: Guenter Roeck <linux at roeck-us.net>
>>>>
>>>> Would this go in through one of the arm trees ?
>>>
>>> You can take the driver through the watchdog tree, but I'll take the DT
>>> stuff through the amlogic tree (and submit via arm-soc).
>>>
>>> However, with your ack, and since this is a brand new driver, I could
>>> take the driver as well.  Just let me know your preference.
>>
>> ping... do you have a prefernce here?
>>
>
> Oops, just noticed Wim already picked these up.
>

Strange, seems that Wim picked up patches 1 & 3, but this one was missed.  I'll
queue this for the arm-soc tree.

Kevin


From sboyd at codeaurora.org  Mon Aug 15 14:29:58 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 15 Aug 2016 14:29:58 -0700
Subject: [PATCH -next] clk: gxbb: use builtin_platform_driver to simplify
 the code
In-Reply-To: <1470664520-9604-1-git-send-email-weiyj.lk@gmail.com>
References: <1470664520-9604-1-git-send-email-weiyj.lk@gmail.com>
Message-ID: <20160815212958.GF361@codeaurora.org>

On 08/08, Wei Yongjun wrote:
> Use the builtin_platform_driver() macro to make the code simpler.
> 
> Signed-off-by: Wei Yongjun <weiyj.lk at gmail.com>
> ---

Applied to clk-next

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


From khilman at baylibre.com  Mon Aug 15 14:33:02 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 15 Aug 2016 16:33:02 -0500
Subject: [PATCH v2 1/2] ARM64: dts: meson-gxbb: add MMC support
In-Reply-To: <201608141319.AeQlvjsy%fengguang.wu@intel.com> (kbuild test
 robot's message of "Sun, 14 Aug 2016 13:25:40 +0800")
References: <201608141319.AeQlvjsy%fengguang.wu@intel.com>
Message-ID: <m2fuq5afap.fsf@baylibre.com>

kbuild test robot <lkp at intel.com> writes:

> Hi Kevin,
>
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.8-rc1 next-20160812]
> [cannot apply to ulf.hansson-mmc/next robh/for-next]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url:    https://github.com/0day-ci/linux/commits/Kevin-Hilman/ARM64-dts-meson-gxbb-add-MMC-support/20160804-072056
> config: arm64-defconfig (attached as .config)
> compiler: aarch64-linux-gnu-gcc (Debian 5.4.0-6) 5.4.0 20160609
> reproduce:
>         wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=arm64 
>
> All errors (new ones prefixed by >>):
>
>>> Error: arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi:338.21-22 syntax error
>>> FATAL ERROR: Unable to parse input tree

This is due to a clock dependency[1] which is in the process of being
queued in the clock tree.

Kevin

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/446650.html


From sboyd at codeaurora.org  Mon Aug 15 15:48:36 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 15 Aug 2016 15:48:36 -0700
Subject: [PATCH] clk: gxbb: add MMC gate clocks, and expose for DT
In-Reply-To: <20160802214011.19077-1-khilman@baylibre.com>
References: <20160802214011.19077-1-khilman@baylibre.com>
Message-ID: <20160815224836.GS361@codeaurora.org>

On 08/02, Kevin Hilman wrote:
> Add the SD/eMMC gate clocks and expose them for use by DT.
> 
> While at it, also explose FCLK_DIV2 since this is one of the input
> clocks to the mux internal to each of the SD/eMMC blocks.
> 
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>
> ---

Applied to clk-meson-gxbb and merged into clk-next.

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


From khilman at baylibre.com  Mon Aug 15 15:57:59 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 15 Aug 2016 17:57:59 -0500
Subject: [PATCH] pinctrl: meson: get rid of unneeded domain structures
In-Reply-To: <1471110078-5946-1-git-send-email-b.galvani@gmail.com> (Beniamino
 Galvani's message of "Sat, 13 Aug 2016 19:41:18 +0200")
References: <1471110078-5946-1-git-send-email-b.galvani@gmail.com>
Message-ID: <m2a8gdabd4.fsf@baylibre.com>

Beniamino Galvani <b.galvani at gmail.com> writes:

> The driver originally supported more domains (register ranges) per
> pinctrl device, but since commit 9dab1868ec0d ("pinctrl: amlogic: Make
> driver independent from two-domain configuration") each device gets
> assigned a single domain and we instantiate multiple pinctrl devices
> in the DT.
>
> Therefore, now the 'meson_domain' and 'meson_domain_data' structures
> don't have any reason to exist and can be removed to make the model
> simpler to understand. This commit doesn't change behavior.
>
> Tested on a Odroid-C2.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>

Looks good and boot tested on meson-gxbb-p200:

Acked-by: Kevin Hilman <khilman at baylibre.com>
Tested-by: Kevin Hilman <khilman at baylibre.com>

Kevin


From linux at roeck-us.net  Mon Aug 15 18:51:38 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 15 Aug 2016 18:51:38 -0700
Subject: [PATCH v3 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <7hinv1ahqi.fsf@baylibre.com>
References: <1468141867-4172-1-git-send-email-narmstrong@baylibre.com>
 <1468141867-4172-4-git-send-email-narmstrong@baylibre.com>
 <578271D3.4080704@roeck-us.net> <7hbn237aw7.fsf@baylibre.com>
 <m2bn19qsy3.fsf@baylibre.com>
 <CAOi56cUQaFKYu2jNP0AuLOSNnNramu+DNPc+PH7K0gHDZMf+zA@mail.gmail.com>
 <7hinv1ahqi.fsf@baylibre.com>
Message-ID: <9cfa549e-1979-cb42-bfe1-1ef347dd3a9a@roeck-us.net>

On 08/15/2016 01:40 PM, Kevin Hilman wrote:
> Kevin Hilman <khilman at baylibre.com> writes:
>
>> On Wed, Aug 3, 2016 at 5:27 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>>> Hi Guenter,
>>>
>>> Kevin Hilman <khilman at baylibre.com> writes:
>>>
>>>> Guenter Roeck <linux at roeck-us.net> writes:
>>>>
>>>>> On 07/10/2016 02:11 AM, Neil Armstrong wrote:
>>>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>>>
>>>>> Reviewed-by: Guenter Roeck <linux at roeck-us.net>
>>>>>
>>>>> Would this go in through one of the arm trees ?
>>>>
>>>> You can take the driver through the watchdog tree, but I'll take the DT
>>>> stuff through the amlogic tree (and submit via arm-soc).
>>>>
>>>> However, with your ack, and since this is a brand new driver, I could
>>>> take the driver as well.  Just let me know your preference.
>>>
>>> ping... do you have a prefernce here?
>>>
>>
>> Oops, just noticed Wim already picked these up.
>>
>
> Strange, seems that Wim picked up patches 1 & 3, but this one was missed.  I'll
> queue this for the arm-soc tree.
>

I got a number of requests from arm maintainers to not pick up devicetree changes
for arch/arm, so for my part I usually leave those alone.

Guenter



From narmstrong at baylibre.com  Tue Aug 16 02:41:51 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 16 Aug 2016 11:41:51 +0200
Subject: [RFC PATCH v3 5/8] firmware: Add legacy SCPI protocol driver
In-Reply-To: <cea12544-6dfd-55d4-7c85-68290c720515@arm.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
 <1470738562-20026-6-git-send-email-narmstrong@baylibre.com>
 <cea12544-6dfd-55d4-7c85-68290c720515@arm.com>
Message-ID: <9b1d633e-6215-23c5-6cc2-bc64d104aa0a@baylibre.com>

On 08/15/2016 03:35 PM, Sudeep Holla wrote:
> Hi Neil,
> 
> On 09/08/16 11:29, Neil Armstrong wrote:
>> Add legacy protocol driver for an early published SCPI implementation
>> by supporting old command indexes and structure.
>> This driver also supports vendor messages and rockchip specific
>> mailbox data structure for message passing to SCP.
>>
> 

Hi Sudeep,

> Sorry for the delay but I expected some attempts to reduce the
> duplication of code we have here. I really don't like the duplication of
> the code. As I mentioned earlier it can be reduced. I see lot of scope
> for that and I see that you made zero attempts since v2.

Yes, this post is an intermediate RFC to show to rockchip guys how I could implement support
for their vendor commands, the next RFC will certainly merge the two drivers with minimal code
duplication.

> 
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/firmware/Kconfig       |  20 ++
>>  drivers/firmware/Makefile      |   1 +
>>  drivers/firmware/legacy_scpi.c | 710 +++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 731 insertions(+)
>>  create mode 100644 drivers/firmware/legacy_scpi.c
>>
>> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
>> index ff85511..f6226b7 100644
>> --- a/drivers/firmware/Kconfig
>> +++ b/drivers/firmware/Kconfig
>> @@ -40,6 +40,26 @@ config ARM_SCPI_POWER_DOMAIN
>>        This enables support for the SCPI power domains which can be
>>        enabled or disabled via the SCP firmware
>>
>> +config LEGACY_SCPI_PROTOCOL
>> +    bool "Legacy System Control and Power Interface (SCPI) Message Protocol"
>> +    default y if ARCH_MESON
>> +    select SCPI_FW
>> +    help
>> +      System Control and Power Interface (SCPI) Message Protocol is
>> +      defined for the purpose of communication between the Application
>> +      Cores(AP) and the System Control Processor(SCP). The MHU peripheral
>> +      provides a mechanism for inter-processor communication between SCP
>> +      and AP.
>> +
>> +      SCP controls most of the power managament on the Application
>> +      Processors. It offers control and management of: the core/cluster
>> +      power states, various power domain DVFS including the core/cluster,
>> +      certain system clocks configuration, thermal sensors and many
>> +      others.
>> +
>> +      This protocol library provides interface for all the client drivers
>> +      making use of the features offered by the legacy SCP protocol.
>> +
> 
> Why do we need this ? If we plan to enable this in defconfig, I would
> rather not introduce this as it serves nothing extra over the
> compatible. We need runtime check for this with DT compatibles.
> 
> 
> [...]
> 
> 
>> +enum legacy_scpi_client_id {
>> +    SCPI_CL_NONE,
>> +    SCPI_CL_CLOCKS,
>> +    SCPI_CL_DVFS,
>> +    SCPI_CL_POWER,
>> +    SCPI_CL_THERMAL,
>> +    SCPI_MAX,
>> +};
>> +
> 
> As I said before these values were introduced by me initially and I
> reckon firmware doesn't depend on that. Have you really tested dropping
> them ? This must go as they are useless and we now have tokens which are
> much better.

I am not sure, I'm currently waiting for Amlogic's SCPI FW specification to be sure
these are not needed at all, in the meantime I will still implement them.

> 
> I will stop here and ask why can't you start with simple change like
> below ? Then we can add or re-define the structures/enums when
> absolutely needed. Please don't just copy the entire driver and make
> changes where-ever needed or please try to adapt to the new driver and
> try to deviate as less as required by the firmware.

It will be done in RFC v4.


> Regards,
> Sudeep

Thanks,
Neil

> 
> --->8
> 
> diff --git i/drivers/firmware/arm_scpi.c w/drivers/firmware/arm_scpi.c
> index 438893762076..b394ffb5939c 100644
> --- i/drivers/firmware/arm_scpi.c
> +++ w/drivers/firmware/arm_scpi.c
> @@ -82,6 +82,9 @@
> 
>  #define MAX_RX_TIMEOUT        (msecs_to_jiffies(30))
> 
> +typedef int (*scpi_send_msg_func)(u8 cmd, void *tx_buf, unsigned int tx_len,
> +                  void *rx_buf, unsigned int rx_len);
> +
>  enum scpi_error_codes {
>      SCPI_SUCCESS = 0, /* Success */
>      SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
> @@ -162,6 +165,7 @@ struct scpi_drvinfo {
>      u32 firmware_version;
>      int num_chans;
>      atomic_t next_chan;
> +    scpi_send_msg_func send_msg;
>      struct scpi_ops *scpi_ops;
>      struct scpi_chan *channels;
>      struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
> @@ -397,8 +401,8 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
>      struct clk_get_info clk;
>      __le16 le_clk_id = cpu_to_le16(clk_id);
> 
> -    ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
> -                sizeof(le_clk_id), &clk, sizeof(clk));
> +    ret = scpi_info->send_msg(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
> +                  sizeof(le_clk_id), &clk, sizeof(clk));
>      if (!ret) {
>          *min = le32_to_cpu(clk.min_rate);
>          *max = le32_to_cpu(clk.max_rate);
> @@ -412,8 +416,8 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
>      struct clk_get_value clk;
>      __le16 le_clk_id = cpu_to_le16(clk_id);
> 
> -    ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
> -                sizeof(le_clk_id), &clk, sizeof(clk));
> +    ret = scpi_info->send_msg(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
> +                  sizeof(le_clk_id), &clk, sizeof(clk));
>      return ret ? ret : le32_to_cpu(clk.rate);
>  }
> 
> @@ -425,8 +429,8 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>          .rate = cpu_to_le32(rate)
>      };
> 
> -    return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
> -                 &stat, sizeof(stat));
> +    return scpi_info->send_msg(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
> +                   &stat, sizeof(stat));
>  }
> 
>  static int scpi_dvfs_get_idx(u8 domain)
> @@ -434,8 +438,8 @@ static int scpi_dvfs_get_idx(u8 domain)
>      int ret;
>      u8 dvfs_idx;
> 
> -    ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
> -                &dvfs_idx, sizeof(dvfs_idx));
> +    ret = scpi_info->send_msg(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
> +                  &dvfs_idx, sizeof(dvfs_idx));
>      return ret ? ret : dvfs_idx;
>  }
> 
> @@ -444,8 +448,8 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
>      int stat;
>      struct dvfs_set dvfs = {domain, index};
> 
> -    return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
> -                 &stat, sizeof(stat));
> +    return scpi_info->send_msg(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
> +                   &stat, sizeof(stat));
>  }
> 
>  static int opp_cmp_func(const void *opp1, const void *opp2)
> @@ -468,8 +472,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
>      if (scpi_info->dvfs[domain])    /* data already populated */
>          return scpi_info->dvfs[domain];
> 
> -    ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
> -                &buf, sizeof(buf));
> +    ret = scpi_info->send_msg(SCPI_CMD_GET_DVFS_INFO, &domain,
> +                  sizeof(domain), &buf, sizeof(buf));
> 
>      if (ret)
>          return ERR_PTR(ret);
> @@ -503,8 +507,8 @@ static int scpi_sensor_get_capability(u16 *sensors)
>      struct sensor_capabilities cap_buf;
>      int ret;
> 
> -    ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
> -                sizeof(cap_buf));
> +    ret = scpi_info->send_msg(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0,
> +                  &cap_buf, sizeof(cap_buf));
>      if (!ret)
>          *sensors = le16_to_cpu(cap_buf.sensors);
> 
> @@ -517,8 +521,8 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
>      struct _scpi_sensor_info _info;
>      int ret;
> 
> -    ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
> -                &_info, sizeof(_info));
> +    ret = scpi_info->send_msg(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
> +                  &_info, sizeof(_info));
>      if (!ret) {
>          memcpy(info, &_info, sizeof(*info));
>          info->sensor_id = le16_to_cpu(_info.sensor_id);
> @@ -533,8 +537,8 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
>      struct sensor_value buf;
>      int ret;
> 
> -    ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
> -                &buf, sizeof(buf));
> +    ret = scpi_info->send_msg(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
> +                  &buf, sizeof(buf));
>      if (!ret)
>          *val = (u64)le32_to_cpu(buf.hi_val) << 32 |
>              le32_to_cpu(buf.lo_val);
> @@ -548,8 +552,8 @@ static int scpi_device_get_power_state(u16 dev_id)
>      u8 pstate;
>      __le16 id = cpu_to_le16(dev_id);
> 
> -    ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
> -                sizeof(id), &pstate, sizeof(pstate));
> +    ret = scpi_info->send_msg(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
> +                  sizeof(id), &pstate, sizeof(pstate));
>      return ret ? ret : pstate;
>  }
> 
> @@ -561,8 +565,8 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
>          .pstate = pstate,
>      };
> 
> -    return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
> -                 sizeof(dev_set), &stat, sizeof(stat));
> +    return scpi_info->send_msg(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
> +                   sizeof(dev_set), &stat, sizeof(stat));
>  }
> 
>  static struct scpi_ops scpi_ops = {
> @@ -591,8 +595,8 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
>      int ret;
>      struct scp_capabilities caps;
> 
> -    ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
> -                &caps, sizeof(caps));
> +    ret = scpi_info->send_msg(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
> +                  &caps, sizeof(caps));
>      if (!ret) {
>          info->protocol_version = le32_to_cpu(caps.protocol_version);
>          info->firmware_version = le32_to_cpu(caps.platform_version);
> @@ -681,6 +685,14 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
>      return 0;
>  }
> 
> +static const struct of_device_id scpi_of_match[] = {
> +    {.compatible = "arm,scpi", .data = scpi_send_message},
> +    {.compatible = "arm,scpi-legacy", .data = scpi_send_message},
> +    {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, scpi_of_match);
> +
>  static int scpi_probe(struct platform_device *pdev)
>  {
>      int count, idx, ret;
> @@ -688,11 +700,15 @@ static int scpi_probe(struct platform_device *pdev)
>      struct scpi_chan *scpi_chan;
>      struct device *dev = &pdev->dev;
>      struct device_node *np = dev->of_node;
> +    const struct of_device_id *match;
> 
>      scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
>      if (!scpi_info)
>          return -ENOMEM;
> 
> +    match = of_match_device(scpi_of_match, dev);
> +    scpi_info->send_msg = match->data;
> +
>      count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
>      if (count < 0) {
>          dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
> @@ -778,13 +794,6 @@ static int scpi_probe(struct platform_device *pdev)
>      return of_platform_populate(dev->of_node, NULL, NULL, dev);
>  }
> 
> -static const struct of_device_id scpi_of_match[] = {
> -    {.compatible = "arm,scpi"},
> -    {},
> -};
> -
> -MODULE_DEVICE_TABLE(of, scpi_of_match);
> -
>  static struct platform_driver scpi_driver = {
>      .driver = {
>          .name = "scpi_protocol",



From b.galvani at gmail.com  Tue Aug 16 02:49:46 2016
From: b.galvani at gmail.com (Beniamino Galvani)
Date: Tue, 16 Aug 2016 11:49:46 +0200
Subject: [PATCH 0/4] Amlogic Meson pinctrl driver for u-boot
Message-ID: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>

Hi,

these patches add a pinctrl driver for Meson GXBB and enable
Ethernet support through the device tree.

Beniamino Galvani (4):
  pinctrl: generic: scan for "pins" and "groups" properties in sub-nodes
  arm: dts: update DTS files for meson-gxbb and odroid-c2
  pinctrl: add driver for meson-gxbb pin controller
  meson: odroid-c2: enable Ethernet support through the device tree

 arch/arm/dts/meson-gxbb-odroidc2.dts               |  19 +
 arch/arm/dts/meson-gxbb.dtsi                       | 170 +++++++-
 arch/arm/include/asm/arch-meson/gxbb.h             |   3 -
 board/amlogic/odroid-c2/odroid-c2.c                |  13 -
 configs/odroid-c2_defconfig                        |   3 +
 drivers/net/designware.c                           |   1 +
 drivers/pinctrl/Kconfig                            |   1 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/meson/Kconfig                      |  11 +
 drivers/pinctrl/meson/Makefile                     |   6 +
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c         | 432 +++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.c              | 179 +++++++++
 drivers/pinctrl/meson/pinctrl-meson.h              |  74 ++++
 drivers/pinctrl/pinctrl-generic.c                  |   6 +-
 include/dt-bindings/gpio/meson-gxbb-gpio.h         | 154 ++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 ++++++++++
 16 files changed, 1264 insertions(+), 19 deletions(-)
 create mode 100644 drivers/pinctrl/meson/Kconfig
 create mode 100644 drivers/pinctrl/meson/Makefile
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson.c
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson.h
 create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

-- 
2.7.4



From b.galvani at gmail.com  Tue Aug 16 02:49:50 2016
From: b.galvani at gmail.com (Beniamino Galvani)
Date: Tue, 16 Aug 2016 11:49:50 +0200
Subject: [PATCH 4/4] meson: odroid-c2: enable Ethernet support through the
 device tree
In-Reply-To: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
Message-ID: <1471340990-16247-5-git-send-email-b.galvani@gmail.com>

Remove the device definition from board file, update the driver with
the new compatible property and update config with necessary options.

Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
---
 arch/arm/include/asm/arch-meson/gxbb.h |  3 ---
 board/amlogic/odroid-c2/odroid-c2.c    | 13 -------------
 configs/odroid-c2_defconfig            |  3 +++
 drivers/net/designware.c               |  1 +
 4 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/arch/arm/include/asm/arch-meson/gxbb.h b/arch/arm/include/asm/arch-meson/gxbb.h
index f90f632..ce41349 100644
--- a/arch/arm/include/asm/arch-meson/gxbb.h
+++ b/arch/arm/include/asm/arch-meson/gxbb.h
@@ -20,9 +20,6 @@
 #define GXBB_GPIO_IN(n)		GXBB_PERIPHS_ADDR(_GXBB_GPIO_OFF(n) + 1)
 #define GXBB_GPIO_OUT(n)	GXBB_PERIPHS_ADDR(_GXBB_GPIO_OFF(n) + 2)
 
-/* Pinmux registers 0 to 12 */
-#define GXBB_PINMUX(n)		GXBB_PERIPHS_ADDR(0x2c + (n))
-
 #define GXBB_ETH_REG_0		GXBB_PERIPHS_ADDR(0x50)
 #define GXBB_ETH_REG_1		GXBB_PERIPHS_ADDR(0x51)
 
diff --git a/board/amlogic/odroid-c2/odroid-c2.c b/board/amlogic/odroid-c2/odroid-c2.c
index bd72100..b61daaa 100644
--- a/board/amlogic/odroid-c2/odroid-c2.c
+++ b/board/amlogic/odroid-c2/odroid-c2.c
@@ -21,24 +21,11 @@ int board_init(void)
 	return 0;
 }
 
-static const struct eth_pdata gxbb_eth_pdata = {
-	.iobase = GXBB_ETH_BASE,
-	.phy_interface = PHY_INTERFACE_MODE_RGMII,
-};
-
-U_BOOT_DEVICE(meson_eth) = {
-	.name = "eth_designware",
-	.platdata = &gxbb_eth_pdata,
-};
-
 int misc_init_r(void)
 {
 	u8 mac_addr[EFUSE_MAC_SIZE];
 	ssize_t len;
 
-	/* Select Ethernet function */
-	setbits_le32(GXBB_PINMUX(6), 0x3fff);
-
 	/* Set RGMII mode */
 	setbits_le32(GXBB_ETH_REG_0, GXBB_ETH_REG_0_PHY_INTF |
 				     GXBB_ETH_REG_0_TX_PHASE(1) |
diff --git a/configs/odroid-c2_defconfig b/configs/odroid-c2_defconfig
index 808bbc2..3e9ef68 100644
--- a/configs/odroid-c2_defconfig
+++ b/configs/odroid-c2_defconfig
@@ -14,6 +14,9 @@ CONFIG_HUSH_PARSER=y
 CONFIG_OF_CONTROL=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_MESON_GXBB=y
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_UART_MESON=y
 CONFIG_DEBUG_UART_BASE=0xc81004c0
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 8ba72e3..9e6d726 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -737,6 +737,7 @@ static int designware_eth_ofdata_to_platdata(struct udevice *dev)
 static const struct udevice_id designware_eth_ids[] = {
 	{ .compatible = "allwinner,sun7i-a20-gmac" },
 	{ .compatible = "altr,socfpga-stmmac" },
+	{ .compatible = "amlogic,meson6-dwmac" },
 	{ }
 };
 
-- 
2.7.4



From b.galvani at gmail.com  Tue Aug 16 02:49:47 2016
From: b.galvani at gmail.com (Beniamino Galvani)
Date: Tue, 16 Aug 2016 11:49:47 +0200
Subject: [PATCH 1/4] pinctrl: generic: scan for "pins" and "groups" properties
 in sub-nodes
In-Reply-To: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
Message-ID: <1471340990-16247-2-git-send-email-b.galvani@gmail.com>

In cases where the pins and groups definitions are in a sub-node, as:

	uart_a {
		mux {
			groups = "uart_tx_a", "uart_rx_a";
			function = "uart_a";
		};
	};

pinctrl_generic_set_state_subnode() returns an error for the top-level
node and pinctrl_generic_set_state() fails. Instead, return success so
that the child nodes are tried.

Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
---
 drivers/pinctrl/pinctrl-generic.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
index e86b72a..baff40f 100644
--- a/drivers/pinctrl/pinctrl-generic.c
+++ b/drivers/pinctrl/pinctrl-generic.c
@@ -312,8 +312,10 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
 		is_group = true;
 		strings_count = fdt_count_strings(fdt, node,
 						  subnode_target_type);
-		if (strings_count < 0)
-			return -EINVAL;
+		if (strings_count < 0) {
+			/* skip this node; may contain config child nodes */
+			return 0;
+		}
 	}
 
 	for (i = 0; i < strings_count; i++) {
-- 
2.7.4



From b.galvani at gmail.com  Tue Aug 16 02:49:48 2016
From: b.galvani at gmail.com (Beniamino Galvani)
Date: Tue, 16 Aug 2016 11:49:48 +0200
Subject: [PATCH 2/4] arm: dts: update DTS files for meson-gxbb and odroid-c2
In-Reply-To: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
Message-ID: <1471340990-16247-3-git-send-email-b.galvani@gmail.com>

Import DTS files and dt-bindings includes from Linux 4.8-rc1.

Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
---
 arch/arm/dts/meson-gxbb-odroidc2.dts               |  19 ++
 arch/arm/dts/meson-gxbb.dtsi                       | 170 ++++++++++++++++-
 include/dt-bindings/gpio/meson-gxbb-gpio.h         | 154 +++++++++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
 4 files changed, 552 insertions(+), 1 deletion(-)
 create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

diff --git a/arch/arm/dts/meson-gxbb-odroidc2.dts b/arch/arm/dts/meson-gxbb-odroidc2.dts
index 653c2fa..79bee64 100644
--- a/arch/arm/dts/meson-gxbb-odroidc2.dts
+++ b/arch/arm/dts/meson-gxbb-odroidc2.dts
@@ -45,6 +45,7 @@
 /dts-v1/;
 
 #include "meson-gxbb.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	compatible = "hardkernel,odroid-c2", "amlogic,meson-gxbb";
@@ -62,8 +63,26 @@
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		blue {
+			label = "c2:blue:alive";
+			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
 };
 
 &uart_AO {
 	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
 };
diff --git a/arch/arm/dts/meson-gxbb.dtsi b/arch/arm/dts/meson-gxbb.dtsi
index 832815d..e502c24 100644
--- a/arch/arm/dts/meson-gxbb.dtsi
+++ b/arch/arm/dts/meson-gxbb.dtsi
@@ -43,6 +43,8 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -129,13 +131,35 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
 
+			reset: reset-controller at 4404 {
+				compatible = "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
 			uart_A: serial at 84c0 {
 				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x084c0 0x0 0x14>;
+				reg = <0x0 0x84c0 0x0 0x14>;
 				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			uart_B: serial at 84dc {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84dc 0x0 0x14>;
+				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_C: serial at 8700 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x8700 0x0 0x14>;
+				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
 		};
 
 		gic: interrupt-controller at c4301000 {
@@ -158,6 +182,29 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
 
+			pinctrl_aobus: pinctrl at 14 {
+				compatible = "amlogic,meson-gxbb-aobus-pinctrl";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges;
+
+				gpio_ao: bank at 14 {
+					reg = <0x0 0x00014 0x0 0x8>,
+					      <0x0 0x0002c 0x0 0x4>,
+					      <0x0 0x00024 0x0 0x8>;
+					reg-names = "mux", "pull", "gpio";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				uart_ao_a_pins: uart_ao_a {
+					mux {
+						groups = "uart_tx_ao_a", "uart_rx_ao_a";
+						function = "uart_ao";
+					};
+				};
+			};
+
 			uart_AO: serial at 4c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x004c0 0x0 0x14>;
@@ -167,6 +214,115 @@
 			};
 		};
 
+		periphs: periphs at c8834000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8834000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
+
+			rng {
+				compatible = "amlogic,meson-rng";
+				reg = <0x0 0x0 0x0 0x4>;
+			};
+
+			pinctrl_periphs: pinctrl at 4b0 {
+				compatible = "amlogic,meson-gxbb-periphs-pinctrl";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges;
+
+				gpio: bank at 4b0 {
+					reg = <0x0 0x004b0 0x0 0x28>,
+					      <0x0 0x004e8 0x0 0x14>,
+					      <0x0 0x00120 0x0 0x14>,
+					      <0x0 0x00430 0x0 0x40>;
+					reg-names = "mux", "pull", "pull-enable", "gpio";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				emmc_pins: emmc {
+					mux {
+						groups = "emmc_nand_d07",
+						       "emmc_cmd",
+						       "emmc_clk";
+						function = "emmc";
+					};
+				};
+
+				sdcard_pins: sdcard {
+					mux {
+						groups = "sdcard_d0",
+						       "sdcard_d1",
+						       "sdcard_d2",
+						       "sdcard_d3",
+						       "sdcard_cmd",
+						       "sdcard_clk";
+						function = "sdcard";
+					};
+				};
+
+				uart_a_pins: uart_a {
+					mux {
+						groups = "uart_tx_a",
+						       "uart_rx_a";
+						function = "uart_a";
+					};
+				};
+
+				uart_b_pins: uart_b {
+					mux {
+						groups = "uart_tx_b",
+						       "uart_rx_b";
+						function = "uart_b";
+					};
+				};
+
+				uart_c_pins: uart_c {
+					mux {
+						groups = "uart_tx_c",
+						       "uart_rx_c";
+						function = "uart_c";
+					};
+				};
+
+				eth_pins: eth_c {
+					mux {
+						groups = "eth_mdio",
+						       "eth_mdc",
+						       "eth_clk_rx_clk",
+						       "eth_rx_dv",
+						       "eth_rxd0",
+						       "eth_rxd1",
+						       "eth_rxd2",
+						       "eth_rxd3",
+						       "eth_rgmii_tx_clk",
+						       "eth_tx_en",
+						       "eth_txd0",
+						       "eth_txd1",
+						       "eth_txd2",
+						       "eth_txd3";
+						function = "eth";
+					};
+				};
+			};
+		};
+
+		hiubus: hiubus at c883c000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc883c000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
+
+			clkc: clock-controller at 0 {
+				compatible = "amlogic,gxbb-clkc";
+				#clock-cells = <1>;
+				reg = <0x0 0x0 0x0 0x3db>;
+			};
+		};
+
 		apb: apb at d0000000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xd0000000 0x0 0x200000>;
@@ -174,5 +330,17 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
 		};
+
+		ethmac: ethernet at c9410000 {
+			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+			reg = <0x0 0xc9410000 0x0 0x10000
+			       0x0 0xc8834540 0x0 0x4>;
+			interrupts = <0 8 1>;
+			interrupt-names = "macirq";
+			clocks = <&xtal>;
+			clock-names = "stmmaceth";
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
 	};
 };
diff --git a/include/dt-bindings/gpio/meson-gxbb-gpio.h b/include/dt-bindings/gpio/meson-gxbb-gpio.h
new file mode 100644
index 0000000..58654fd
--- /dev/null
+++ b/include/dt-bindings/gpio/meson-gxbb-gpio.h
@@ -0,0 +1,154 @@
+/*
+ * GPIO definitions for Amlogic Meson GXBB SoCs
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DT_BINDINGS_MESON_GXBB_GPIO_H
+#define _DT_BINDINGS_MESON_GXBB_GPIO_H
+
+#define	GPIOAO_0	0
+#define	GPIOAO_1	1
+#define	GPIOAO_2	2
+#define	GPIOAO_3	3
+#define	GPIOAO_4	4
+#define	GPIOAO_5	5
+#define	GPIOAO_6	6
+#define	GPIOAO_7	7
+#define	GPIOAO_8	8
+#define	GPIOAO_9	9
+#define	GPIOAO_10	10
+#define	GPIOAO_11	11
+#define	GPIOAO_12	12
+#define	GPIOAO_13	13
+
+#define	GPIOZ_0		0
+#define	GPIOZ_1		1
+#define	GPIOZ_2		2
+#define	GPIOZ_3		3
+#define	GPIOZ_4		4
+#define	GPIOZ_5		5
+#define	GPIOZ_6		6
+#define	GPIOZ_7		7
+#define	GPIOZ_8		8
+#define	GPIOZ_9		9
+#define	GPIOZ_10	10
+#define	GPIOZ_11	11
+#define	GPIOZ_12	12
+#define	GPIOZ_13	13
+#define	GPIOZ_14	14
+#define	GPIOZ_15	15
+#define	GPIOH_0		16
+#define	GPIOH_1		17
+#define	GPIOH_2		18
+#define	GPIOH_3		19
+#define	BOOT_0		20
+#define	BOOT_1		21
+#define	BOOT_2		22
+#define	BOOT_3		23
+#define	BOOT_4		24
+#define	BOOT_5		25
+#define	BOOT_6		26
+#define	BOOT_7		27
+#define	BOOT_8		28
+#define	BOOT_9		29
+#define	BOOT_10		30
+#define	BOOT_11		31
+#define	BOOT_12		32
+#define	BOOT_13		33
+#define	BOOT_14		34
+#define	BOOT_15		35
+#define	BOOT_16		36
+#define	BOOT_17		37
+#define	CARD_0		38
+#define	CARD_1		39
+#define	CARD_2		40
+#define	CARD_3		41
+#define	CARD_4		42
+#define	CARD_5		43
+#define	CARD_6		44
+#define	GPIODV_0	45
+#define	GPIODV_1	46
+#define	GPIODV_2	47
+#define	GPIODV_3	48
+#define	GPIODV_4	49
+#define	GPIODV_5	50
+#define	GPIODV_6	51
+#define	GPIODV_7	52
+#define	GPIODV_8	53
+#define	GPIODV_9	54
+#define	GPIODV_10	55
+#define	GPIODV_11	56
+#define	GPIODV_12	57
+#define	GPIODV_13	58
+#define	GPIODV_14	59
+#define	GPIODV_15	60
+#define	GPIODV_16	61
+#define	GPIODV_17	62
+#define	GPIODV_18	63
+#define	GPIODV_19	64
+#define	GPIODV_20	65
+#define	GPIODV_21	66
+#define	GPIODV_22	67
+#define	GPIODV_23	68
+#define	GPIODV_24	69
+#define	GPIODV_25	70
+#define	GPIODV_26	71
+#define	GPIODV_27	72
+#define	GPIODV_28	73
+#define	GPIODV_29	74
+#define	GPIOY_0		75
+#define	GPIOY_1		76
+#define	GPIOY_2		77
+#define	GPIOY_3		78
+#define	GPIOY_4		79
+#define	GPIOY_5		80
+#define	GPIOY_6		81
+#define	GPIOY_7		82
+#define	GPIOY_8		83
+#define	GPIOY_9		84
+#define	GPIOY_10	85
+#define	GPIOY_11	86
+#define	GPIOY_12	87
+#define	GPIOY_13	88
+#define	GPIOY_14	89
+#define	GPIOY_15	90
+#define	GPIOY_16	91
+#define	GPIOX_0		92
+#define	GPIOX_1		93
+#define	GPIOX_2		94
+#define	GPIOX_3		95
+#define	GPIOX_4		96
+#define	GPIOX_5		97
+#define	GPIOX_6		98
+#define	GPIOX_7		99
+#define	GPIOX_8		100
+#define	GPIOX_9		101
+#define	GPIOX_10	102
+#define	GPIOX_11	103
+#define	GPIOX_12	104
+#define	GPIOX_13	105
+#define	GPIOX_14	106
+#define	GPIOX_15	107
+#define	GPIOX_16	108
+#define	GPIOX_17	109
+#define	GPIOX_18	110
+#define	GPIOX_19	111
+#define	GPIOX_20	112
+#define	GPIOX_21	113
+#define	GPIOX_22	114
+#define	GPIOCLK_0	115
+#define	GPIOCLK_1	116
+#define	GPIOCLK_2	117
+#define	GPIOCLK_3	118
+#define	GPIO_TEST_N	119
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
new file mode 100644
index 0000000..524d607
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
@@ -0,0 +1,210 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+
+/*	RESET0					*/
+#define RESET_HIU			0
+/*					1	*/
+#define RESET_DOS_RESET			2
+#define RESET_DDR_TOP			3
+#define RESET_DCU_RESET			4
+#define RESET_VIU			5
+#define RESET_AIU			6
+#define RESET_VID_PLL_DIV		7
+/*					8	*/
+#define RESET_PMUX			9
+#define RESET_VENC			10
+#define RESET_ASSIST			11
+#define RESET_AFIFO2			12
+#define RESET_VCBUS			13
+/*					14	*/
+/*					15	*/
+#define RESET_GIC			16
+#define RESET_CAPB3_DECODE		17
+#define RESET_NAND_CAPB3		18
+#define RESET_HDMITX_CAPB3		19
+#define RESET_MALI_CAPB3		20
+#define RESET_DOS_CAPB3			21
+#define RESET_SYS_CPU_CAPB3		22
+#define RESET_CBUS_CAPB3		23
+#define RESET_AHB_CNTL			24
+#define RESET_AHB_DATA			25
+#define RESET_VCBUS_CLK81		26
+#define RESET_MMC			27
+#define RESET_MIPI_0			28
+#define RESET_MIPI_1			29
+#define RESET_MIPI_2			30
+#define RESET_MIPI_3			31
+/*	RESET1					*/
+#define RESET_CPPM			32
+#define RESET_DEMUX			33
+#define RESET_USB_OTG			34
+#define RESET_DDR			35
+#define RESET_AO_RESET			36
+#define RESET_BT656			37
+#define RESET_AHB_SRAM			38
+/*					39	*/
+#define RESET_PARSER			40
+#define RESET_BLKMV			41
+#define RESET_ISA			42
+#define RESET_ETHERNET			43
+#define RESET_SD_EMMC_A			44
+#define RESET_SD_EMMC_B			45
+#define RESET_SD_EMMC_C			46
+#define RESET_ROM_BOOT			47
+#define RESET_SYS_CPU_0			48
+#define RESET_SYS_CPU_1			49
+#define RESET_SYS_CPU_2			50
+#define RESET_SYS_CPU_3			51
+#define RESET_SYS_CPU_CORE_0		52
+#define RESET_SYS_CPU_CORE_1		53
+#define RESET_SYS_CPU_CORE_2		54
+#define RESET_SYS_CPU_CORE_3		55
+#define RESET_SYS_PLL_DIV		56
+#define RESET_SYS_CPU_AXI		57
+#define RESET_SYS_CPU_L2		58
+#define RESET_SYS_CPU_P			59
+#define RESET_SYS_CPU_MBIST		60
+/*					61	*/
+/*					62	*/
+/*					63	*/
+/*	RESET2					*/
+#define RESET_VD_RMEM			64
+#define RESET_AUDIN			65
+#define RESET_HDMI_TX			66
+/*					67	*/
+/*					68	*/
+/*					69	*/
+#define RESET_GE2D			70
+#define RESET_PARSER_REG		71
+#define RESET_PARSER_FETCH		72
+#define RESET_PARSER_CTL		73
+#define RESET_PARSER_TOP		74
+/*					75	*/
+/*					76	*/
+#define RESET_AO_CPU_RESET		77
+#define RESET_MALI			78
+#define RESET_HDMI_SYSTEM_RESET		79
+/*					80-95	*/
+/*	RESET3					*/
+#define RESET_RING_OSCILLATOR		96
+#define RESET_SYS_CPU			97
+#define RESET_EFUSE			98
+#define RESET_SYS_CPU_BVCI		99
+#define RESET_AIFIFO			100
+#define RESET_TVFE			101
+#define RESET_AHB_BRIDGE_CNTL		102
+/*					103	*/
+#define RESET_AUDIO_DAC			104
+#define RESET_DEMUX_TOP			105
+#define RESET_DEMUX_DES			106
+#define RESET_DEMUX_S2P_0		107
+#define RESET_DEMUX_S2P_1		108
+#define RESET_DEMUX_RESET_0		109
+#define RESET_DEMUX_RESET_1		110
+#define RESET_DEMUX_RESET_2		111
+/*					112-127	*/
+/*	RESET4					*/
+/*					128	*/
+/*					129	*/
+/*					130	*/
+/*					131	*/
+#define RESET_DVIN_RESET		132
+#define RESET_RDMA			133
+#define RESET_VENCI			134
+#define RESET_VENCP			135
+/*					136	*/
+#define RESET_VDAC			137
+#define RESET_RTC			138
+/*					139	*/
+#define RESET_VDI6			140
+#define RESET_VENCL			141
+#define RESET_I2C_MASTER_2		142
+#define RESET_I2C_MASTER_1		143
+/*					144-159	*/
+/*	RESET5					*/
+/*					160-191	*/
+/*	RESET6					*/
+#define RESET_PERIPHS_GENERAL		192
+#define RESET_PERIPHS_SPICC		193
+#define RESET_PERIPHS_SMART_CARD	194
+#define RESET_PERIPHS_SAR_ADC		195
+#define RESET_PERIPHS_I2C_MASTER_0	196
+#define RESET_SANA			197
+/*					198	*/
+#define RESET_PERIPHS_STREAM_INTERFACE	199
+#define RESET_PERIPHS_SDIO		200
+#define RESET_PERIPHS_UART_0		201
+#define RESET_PERIPHS_UART_1_2		202
+#define RESET_PERIPHS_ASYNC_0		203
+#define RESET_PERIPHS_ASYNC_1		204
+#define RESET_PERIPHS_SPI_0		205
+#define RESET_PERIPHS_SDHC		206
+#define RESET_UART_SLIP			207
+/*					208-223	*/
+/*	RESET7					*/
+#define RESET_USB_DDR_0			224
+#define RESET_USB_DDR_1			225
+#define RESET_USB_DDR_2			226
+#define RESET_USB_DDR_3			227
+/*					228	*/
+#define RESET_DEVICE_MMC_ARB		229
+/*					230	*/
+#define RESET_VID_LOCK			231
+#define RESET_A9_DMC_PIPEL		232
+/*					233-255	*/
+
+#endif
-- 
2.7.4



From b.galvani at gmail.com  Tue Aug 16 02:49:49 2016
From: b.galvani at gmail.com (Beniamino Galvani)
Date: Tue, 16 Aug 2016 11:49:49 +0200
Subject: [PATCH 3/4] pinctrl: add driver for meson-gxbb pin controller
In-Reply-To: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
Message-ID: <1471340990-16247-4-git-send-email-b.galvani@gmail.com>

Add a pin controller driver for Meson GXBB adapted from Linux kernel.

Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
---
 drivers/pinctrl/Kconfig                    |   1 +
 drivers/pinctrl/Makefile                   |   1 +
 drivers/pinctrl/meson/Kconfig              |  11 +
 drivers/pinctrl/meson/Makefile             |   6 +
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 432 +++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.c      | 179 ++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.h      |  74 +++++
 7 files changed, 704 insertions(+)
 create mode 100644 drivers/pinctrl/meson/Kconfig
 create mode 100644 drivers/pinctrl/meson/Makefile
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson.c
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson.h

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 2972dba..c0c7153 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -161,6 +161,7 @@ config PIC32_PINCTRL
 
 endif
 
+source "drivers/pinctrl/meson/Kconfig"
 source "drivers/pinctrl/nxp/Kconfig"
 source "drivers/pinctrl/uniphier/Kconfig"
 source "drivers/pinctrl/exynos/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 7f94681..62340f5 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_PINCTRL_SANDBOX)	+= pinctrl-sandbox.o
 obj-$(CONFIG_PINCTRL_UNIPHIER)	+= uniphier/
 obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
+obj-$(CONFIG_PINCTRL_MESON)	+= meson/
diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
new file mode 100644
index 0000000..c3e6901
--- /dev/null
+++ b/drivers/pinctrl/meson/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_MESON
+
+config PINCTRL_MESON
+	depends on PINCTRL_GENERIC
+	bool
+
+config PINCTRL_MESON_GXBB
+	bool "Amlogic Meson GXBB SoC pinctrl driver"
+	select PINCTRL_MESON
+
+endif
diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
new file mode 100644
index 0000000..6dde4bc
--- /dev/null
+++ b/drivers/pinctrl/meson/Makefile
@@ -0,0 +1,6 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y					+= pinctrl-meson.o
+obj-$(CONFIG_PINCTRL_MESON_GXBB)	+= pinctrl-meson-gxbb.o
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
new file mode 100644
index 0000000..a0a7de5
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -0,0 +1,432 @@
+/*
+ * (C) Copyright 2016 - Beniamino Galvani <b.galvani at gmail.com>
+ *
+ * Based on code from Linux kernel:
+ *   Copyright (C) 2016 Endless Mobile, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+#include <dt-bindings/gpio/meson-gxbb-gpio.h>
+
+#include "pinctrl-meson.h"
+
+#define EE_OFF	14
+
+static const unsigned int emmc_nand_d07_pins[] = {
+	PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF),
+	PIN(BOOT_3, EE_OFF), PIN(BOOT_4, EE_OFF), PIN(BOOT_5, EE_OFF),
+	PIN(BOOT_6, EE_OFF), PIN(BOOT_7, EE_OFF),
+};
+static const unsigned int emmc_clk_pins[] = { PIN(BOOT_8, EE_OFF) };
+static const unsigned int emmc_cmd_pins[] = { PIN(BOOT_10, EE_OFF) };
+static const unsigned int emmc_ds_pins[] = { PIN(BOOT_15, EE_OFF) };
+
+static const unsigned int sdcard_d0_pins[] = { PIN(CARD_1, EE_OFF) };
+static const unsigned int sdcard_d1_pins[] = { PIN(CARD_0, EE_OFF) };
+static const unsigned int sdcard_d2_pins[] = { PIN(CARD_5, EE_OFF) };
+static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
+static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
+static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
+
+static const unsigned int uart_tx_a_pins[]	= { PIN(GPIOX_12, EE_OFF) };
+static const unsigned int uart_rx_a_pins[]	= { PIN(GPIOX_13, EE_OFF) };
+static const unsigned int uart_cts_a_pins[]	= { PIN(GPIOX_14, EE_OFF) };
+static const unsigned int uart_rts_a_pins[]	= { PIN(GPIOX_15, EE_OFF) };
+
+static const unsigned int uart_tx_b_pins[]	= { PIN(GPIODV_24, EE_OFF) };
+static const unsigned int uart_rx_b_pins[]	= { PIN(GPIODV_25, EE_OFF) };
+static const unsigned int uart_cts_b_pins[]	= { PIN(GPIODV_26, EE_OFF) };
+static const unsigned int uart_rts_b_pins[]	= { PIN(GPIODV_27, EE_OFF) };
+
+static const unsigned int uart_tx_c_pins[]	= { PIN(GPIOY_13, EE_OFF) };
+static const unsigned int uart_rx_c_pins[]	= { PIN(GPIOY_14, EE_OFF) };
+static const unsigned int uart_cts_c_pins[]	= { PIN(GPIOX_11, EE_OFF) };
+static const unsigned int uart_rts_c_pins[]	= { PIN(GPIOX_12, EE_OFF) };
+
+static const unsigned int eth_mdio_pins[]	= { PIN(GPIOZ_0, EE_OFF) };
+static const unsigned int eth_mdc_pins[]	= { PIN(GPIOZ_1, EE_OFF) };
+static const unsigned int eth_clk_rx_clk_pins[]	= { PIN(GPIOZ_2, EE_OFF) };
+static const unsigned int eth_rx_dv_pins[]	= { PIN(GPIOZ_3, EE_OFF) };
+static const unsigned int eth_rxd0_pins[]	= { PIN(GPIOZ_4, EE_OFF) };
+static const unsigned int eth_rxd1_pins[]	= { PIN(GPIOZ_5, EE_OFF) };
+static const unsigned int eth_rxd2_pins[]	= { PIN(GPIOZ_6, EE_OFF) };
+static const unsigned int eth_rxd3_pins[]	= { PIN(GPIOZ_7, EE_OFF) };
+static const unsigned int eth_rgmii_tx_clk_pins[] = { PIN(GPIOZ_8, EE_OFF) };
+static const unsigned int eth_tx_en_pins[]	= { PIN(GPIOZ_9, EE_OFF) };
+static const unsigned int eth_txd0_pins[]	= { PIN(GPIOZ_10, EE_OFF) };
+static const unsigned int eth_txd1_pins[]	= { PIN(GPIOZ_11, EE_OFF) };
+static const unsigned int eth_txd2_pins[]	= { PIN(GPIOZ_12, EE_OFF) };
+static const unsigned int eth_txd3_pins[]	= { PIN(GPIOZ_13, EE_OFF) };
+
+static const unsigned int uart_tx_ao_a_pins[]	= { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_a_pins[]	= { PIN(GPIOAO_1, 0) };
+static const unsigned int uart_cts_ao_a_pins[]	= { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_a_pins[]	= { PIN(GPIOAO_3, 0) };
+static const unsigned int uart_tx_ao_b_pins[]	= { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_b_pins[]	= { PIN(GPIOAO_1, 0),
+						    PIN(GPIOAO_5, 0) };
+static const unsigned int uart_cts_ao_b_pins[]	= { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_b_pins[]	= { PIN(GPIOAO_3, 0) };
+
+static const unsigned int i2c_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
+static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
+static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
+static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
+
+static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
+	GPIO_GROUP(GPIOZ_0, EE_OFF),
+	GPIO_GROUP(GPIOZ_1, EE_OFF),
+	GPIO_GROUP(GPIOZ_2, EE_OFF),
+	GPIO_GROUP(GPIOZ_3, EE_OFF),
+	GPIO_GROUP(GPIOZ_4, EE_OFF),
+	GPIO_GROUP(GPIOZ_5, EE_OFF),
+	GPIO_GROUP(GPIOZ_6, EE_OFF),
+	GPIO_GROUP(GPIOZ_7, EE_OFF),
+	GPIO_GROUP(GPIOZ_8, EE_OFF),
+	GPIO_GROUP(GPIOZ_9, EE_OFF),
+	GPIO_GROUP(GPIOZ_10, EE_OFF),
+	GPIO_GROUP(GPIOZ_11, EE_OFF),
+	GPIO_GROUP(GPIOZ_12, EE_OFF),
+	GPIO_GROUP(GPIOZ_13, EE_OFF),
+	GPIO_GROUP(GPIOZ_14, EE_OFF),
+	GPIO_GROUP(GPIOZ_15, EE_OFF),
+
+	GPIO_GROUP(GPIOH_0, EE_OFF),
+	GPIO_GROUP(GPIOH_1, EE_OFF),
+	GPIO_GROUP(GPIOH_2, EE_OFF),
+	GPIO_GROUP(GPIOH_3, EE_OFF),
+
+	GPIO_GROUP(BOOT_0, EE_OFF),
+	GPIO_GROUP(BOOT_1, EE_OFF),
+	GPIO_GROUP(BOOT_2, EE_OFF),
+	GPIO_GROUP(BOOT_3, EE_OFF),
+	GPIO_GROUP(BOOT_4, EE_OFF),
+	GPIO_GROUP(BOOT_5, EE_OFF),
+	GPIO_GROUP(BOOT_6, EE_OFF),
+	GPIO_GROUP(BOOT_7, EE_OFF),
+	GPIO_GROUP(BOOT_8, EE_OFF),
+	GPIO_GROUP(BOOT_9, EE_OFF),
+	GPIO_GROUP(BOOT_10, EE_OFF),
+	GPIO_GROUP(BOOT_11, EE_OFF),
+	GPIO_GROUP(BOOT_12, EE_OFF),
+	GPIO_GROUP(BOOT_13, EE_OFF),
+	GPIO_GROUP(BOOT_14, EE_OFF),
+	GPIO_GROUP(BOOT_15, EE_OFF),
+	GPIO_GROUP(BOOT_16, EE_OFF),
+	GPIO_GROUP(BOOT_17, EE_OFF),
+
+	GPIO_GROUP(CARD_0, EE_OFF),
+	GPIO_GROUP(CARD_1, EE_OFF),
+	GPIO_GROUP(CARD_2, EE_OFF),
+	GPIO_GROUP(CARD_3, EE_OFF),
+	GPIO_GROUP(CARD_4, EE_OFF),
+	GPIO_GROUP(CARD_5, EE_OFF),
+	GPIO_GROUP(CARD_6, EE_OFF),
+
+	GPIO_GROUP(GPIODV_0, EE_OFF),
+	GPIO_GROUP(GPIODV_1, EE_OFF),
+	GPIO_GROUP(GPIODV_2, EE_OFF),
+	GPIO_GROUP(GPIODV_3, EE_OFF),
+	GPIO_GROUP(GPIODV_4, EE_OFF),
+	GPIO_GROUP(GPIODV_5, EE_OFF),
+	GPIO_GROUP(GPIODV_6, EE_OFF),
+	GPIO_GROUP(GPIODV_7, EE_OFF),
+	GPIO_GROUP(GPIODV_8, EE_OFF),
+	GPIO_GROUP(GPIODV_9, EE_OFF),
+	GPIO_GROUP(GPIODV_10, EE_OFF),
+	GPIO_GROUP(GPIODV_11, EE_OFF),
+	GPIO_GROUP(GPIODV_12, EE_OFF),
+	GPIO_GROUP(GPIODV_13, EE_OFF),
+	GPIO_GROUP(GPIODV_14, EE_OFF),
+	GPIO_GROUP(GPIODV_15, EE_OFF),
+	GPIO_GROUP(GPIODV_16, EE_OFF),
+	GPIO_GROUP(GPIODV_17, EE_OFF),
+	GPIO_GROUP(GPIODV_19, EE_OFF),
+	GPIO_GROUP(GPIODV_20, EE_OFF),
+	GPIO_GROUP(GPIODV_21, EE_OFF),
+	GPIO_GROUP(GPIODV_22, EE_OFF),
+	GPIO_GROUP(GPIODV_23, EE_OFF),
+	GPIO_GROUP(GPIODV_24, EE_OFF),
+	GPIO_GROUP(GPIODV_25, EE_OFF),
+	GPIO_GROUP(GPIODV_26, EE_OFF),
+	GPIO_GROUP(GPIODV_27, EE_OFF),
+	GPIO_GROUP(GPIODV_28, EE_OFF),
+	GPIO_GROUP(GPIODV_29, EE_OFF),
+
+	GPIO_GROUP(GPIOY_0, EE_OFF),
+	GPIO_GROUP(GPIOY_1, EE_OFF),
+	GPIO_GROUP(GPIOY_2, EE_OFF),
+	GPIO_GROUP(GPIOY_3, EE_OFF),
+	GPIO_GROUP(GPIOY_4, EE_OFF),
+	GPIO_GROUP(GPIOY_5, EE_OFF),
+	GPIO_GROUP(GPIOY_6, EE_OFF),
+	GPIO_GROUP(GPIOY_7, EE_OFF),
+	GPIO_GROUP(GPIOY_8, EE_OFF),
+	GPIO_GROUP(GPIOY_9, EE_OFF),
+	GPIO_GROUP(GPIOY_10, EE_OFF),
+	GPIO_GROUP(GPIOY_11, EE_OFF),
+	GPIO_GROUP(GPIOY_12, EE_OFF),
+	GPIO_GROUP(GPIOY_13, EE_OFF),
+	GPIO_GROUP(GPIOY_14, EE_OFF),
+	GPIO_GROUP(GPIOY_15, EE_OFF),
+	GPIO_GROUP(GPIOY_16, EE_OFF),
+
+	GPIO_GROUP(GPIOX_0, EE_OFF),
+	GPIO_GROUP(GPIOX_1, EE_OFF),
+	GPIO_GROUP(GPIOX_2, EE_OFF),
+	GPIO_GROUP(GPIOX_3, EE_OFF),
+	GPIO_GROUP(GPIOX_4, EE_OFF),
+	GPIO_GROUP(GPIOX_5, EE_OFF),
+	GPIO_GROUP(GPIOX_6, EE_OFF),
+	GPIO_GROUP(GPIOX_7, EE_OFF),
+	GPIO_GROUP(GPIOX_8, EE_OFF),
+	GPIO_GROUP(GPIOX_9, EE_OFF),
+	GPIO_GROUP(GPIOX_10, EE_OFF),
+	GPIO_GROUP(GPIOX_11, EE_OFF),
+	GPIO_GROUP(GPIOX_12, EE_OFF),
+	GPIO_GROUP(GPIOX_13, EE_OFF),
+	GPIO_GROUP(GPIOX_14, EE_OFF),
+	GPIO_GROUP(GPIOX_15, EE_OFF),
+	GPIO_GROUP(GPIOX_16, EE_OFF),
+	GPIO_GROUP(GPIOX_17, EE_OFF),
+	GPIO_GROUP(GPIOX_18, EE_OFF),
+	GPIO_GROUP(GPIOX_19, EE_OFF),
+	GPIO_GROUP(GPIOX_20, EE_OFF),
+	GPIO_GROUP(GPIOX_21, EE_OFF),
+	GPIO_GROUP(GPIOX_22, EE_OFF),
+
+	GPIO_GROUP(GPIOCLK_0, EE_OFF),
+	GPIO_GROUP(GPIOCLK_1, EE_OFF),
+	GPIO_GROUP(GPIOCLK_2, EE_OFF),
+	GPIO_GROUP(GPIOCLK_3, EE_OFF),
+
+	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+
+	/* Bank X */
+	GROUP(uart_tx_a,	4,	13),
+	GROUP(uart_rx_a,	4,	12),
+	GROUP(uart_cts_a,	4,	11),
+	GROUP(uart_rts_a,	4,	10),
+
+	/* Bank Y */
+	GROUP(uart_cts_c,	1,	19),
+	GROUP(uart_rts_c,	1,	18),
+	GROUP(uart_tx_c,	1,	17),
+	GROUP(uart_rx_c,	1,	16),
+
+	/* Bank Z */
+	GROUP(eth_mdio,		6,	1),
+	GROUP(eth_mdc,		6,	0),
+	GROUP(eth_clk_rx_clk,	6,	13),
+	GROUP(eth_rx_dv,	6,	12),
+	GROUP(eth_rxd0,		6,	11),
+	GROUP(eth_rxd1,		6,	10),
+	GROUP(eth_rxd2,		6,	9),
+	GROUP(eth_rxd3,		6,	8),
+	GROUP(eth_rgmii_tx_clk,	6,	7),
+	GROUP(eth_tx_en,	6,	6),
+	GROUP(eth_txd0,		6,	5),
+	GROUP(eth_txd1,		6,	4),
+	GROUP(eth_txd2,		6,	3),
+	GROUP(eth_txd3,		6,	2),
+
+	/* Bank DV */
+	GROUP(uart_tx_b,	2,	29),
+	GROUP(uart_rx_b,	2,	28),
+	GROUP(uart_cts_b,	2,	27),
+	GROUP(uart_rts_b,	2,	26),
+
+	/* Bank BOOT */
+	GROUP(emmc_nand_d07,	4,	30),
+	GROUP(emmc_clk,		4,	18),
+	GROUP(emmc_cmd,		4,	19),
+	GROUP(emmc_ds,		4,	31),
+
+	/* Bank CARD */
+	GROUP(sdcard_d1,	2,	14),
+	GROUP(sdcard_d0,	2,	15),
+	GROUP(sdcard_d3,	2,	12),
+	GROUP(sdcard_d2,	2,	13),
+	GROUP(sdcard_cmd,	2,	10),
+	GROUP(sdcard_clk,	2,	11),
+};
+
+static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
+	GPIO_GROUP(GPIOAO_0, 0),
+	GPIO_GROUP(GPIOAO_1, 0),
+	GPIO_GROUP(GPIOAO_2, 0),
+	GPIO_GROUP(GPIOAO_3, 0),
+	GPIO_GROUP(GPIOAO_4, 0),
+	GPIO_GROUP(GPIOAO_5, 0),
+	GPIO_GROUP(GPIOAO_6, 0),
+	GPIO_GROUP(GPIOAO_7, 0),
+	GPIO_GROUP(GPIOAO_8, 0),
+	GPIO_GROUP(GPIOAO_9, 0),
+	GPIO_GROUP(GPIOAO_10, 0),
+	GPIO_GROUP(GPIOAO_11, 0),
+	GPIO_GROUP(GPIOAO_12, 0),
+	GPIO_GROUP(GPIOAO_13, 0),
+
+	/* bank AO */
+	GROUP(uart_tx_ao_b,	0,	26),
+	GROUP(uart_rx_ao_b,	0,	25),
+	GROUP(uart_tx_ao_a,	0,	12),
+	GROUP(uart_rx_ao_a,	0,	11),
+	GROUP(uart_cts_ao_a,	0,	10),
+	GROUP(uart_rts_ao_a,	0,	9),
+	GROUP(uart_cts_ao_b,	0,	8),
+	GROUP(uart_rts_ao_b,	0,	7),
+	GROUP(i2c_sck_ao,	0,	6),
+	GROUP(i2c_sda_ao,	0,	5),
+	GROUP(i2c_slave_sck_ao, 0,	2),
+	GROUP(i2c_slave_sda_ao, 0,	1),
+};
+
+static const char * const gpio_periphs_groups[] = {
+	"GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4",
+	"GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9",
+	"GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14",
+	"GPIOZ_15",
+
+	"GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3",
+
+	"BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4",
+	"BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
+	"BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
+	"BOOT_15", "BOOT_16", "BOOT_17",
+
+	"CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4",
+	"CARD_5", "CARD_6",
+
+	"GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4",
+	"GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9",
+	"GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14",
+	"GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19",
+	"GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24",
+	"GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29",
+
+	"GPIOY_0", "GPIOY_1", "GPIOY_2", "GPIOY_3", "GPIOY_4",
+	"GPIOY_5", "GPIOY_6", "GPIOY_7", "GPIOY_8", "GPIOY_9",
+	"GPIOY_10", "GPIOY_11", "GPIOY_12", "GPIOY_13", "GPIOY_14",
+	"GPIOY_15", "GPIOY_16",
+
+	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+	"GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19",
+	"GPIOX_20", "GPIOX_21", "GPIOX_22",
+
+	"GPIO_TEST_N",
+};
+
+static const char * const emmc_groups[] = {
+	"emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds",
+};
+
+static const char * const sdcard_groups[] = {
+	"sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3",
+	"sdcard_cmd", "sdcard_clk",
+};
+
+static const char * const uart_a_groups[] = {
+	"uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a",
+};
+
+static const char * const uart_b_groups[] = {
+	"uart_tx_b", "uart_rx_b", "uart_cts_b", "uart_rts_b",
+};
+
+static const char * const uart_c_groups[] = {
+	"uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c",
+};
+
+static const char * const eth_groups[] = {
+	"eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv",
+	"eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3",
+	"eth_rgmii_tx_clk", "eth_tx_en",
+	"eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
+};
+
+static const char * const gpio_aobus_groups[] = {
+	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
+	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
+	"GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13",
+};
+
+static const char * const uart_ao_groups[] = {
+	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a",
+};
+
+static const char * const uart_ao_b_groups[] = {
+	"uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b",
+};
+
+static const char * const i2c_ao_groups[] = {
+	"i2c_sdk_ao", "i2c_sda_ao",
+};
+
+static const char * const i2c_slave_ao_groups[] = {
+	"i2c_slave_sdk_ao", "i2c_slave_sda_ao",
+};
+
+static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
+	FUNCTION(gpio_periphs),
+	FUNCTION(emmc),
+	FUNCTION(sdcard),
+	FUNCTION(uart_a),
+	FUNCTION(uart_b),
+	FUNCTION(uart_c),
+	FUNCTION(eth),
+};
+
+static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
+	FUNCTION(gpio_aobus),
+	FUNCTION(uart_ao),
+	FUNCTION(uart_ao_b),
+	FUNCTION(i2c_ao),
+	FUNCTION(i2c_slave_ao),
+};
+
+struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
+	.name		= "periphs-banks",
+	.pin_base	= 14,
+	.groups		= meson_gxbb_periphs_groups,
+	.funcs		= meson_gxbb_periphs_functions,
+	.num_pins	= 120,
+	.num_groups	= ARRAY_SIZE(meson_gxbb_periphs_groups),
+	.num_funcs	= ARRAY_SIZE(meson_gxbb_periphs_functions),
+};
+
+struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data = {
+	.name		= "aobus-banks",
+	.pin_base	= 0,
+	.groups		= meson_gxbb_aobus_groups,
+	.funcs		= meson_gxbb_aobus_functions,
+	.num_pins	= 14,
+	.num_groups	= ARRAY_SIZE(meson_gxbb_aobus_groups),
+	.num_funcs	= ARRAY_SIZE(meson_gxbb_aobus_functions),
+};
+
+static const struct udevice_id meson_gxbb_pinctrl_match[] = {
+	{
+		.compatible = "amlogic,meson-gxbb-periphs-pinctrl",
+		.data = (ulong)&meson_gxbb_periphs_pinctrl_data,
+	},
+	{
+		.compatible = "amlogic,meson-gxbb-aobus-pinctrl",
+		.data = (ulong)&meson_gxbb_aobus_pinctrl_data,
+	},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(meson_gxbb_pinctrl) = {
+	.name = "meson-gxbb-pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = of_match_ptr(meson_gxbb_pinctrl_match),
+	.probe = meson_pinctrl_probe,
+	.priv_auto_alloc_size = sizeof(struct meson_pinctrl),
+	.ops = &meson_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
new file mode 100644
index 0000000..d21a3dd
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -0,0 +1,179 @@
+/*
+ * (C) Copyright 2016 - Beniamino Galvani <b.galvani at gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+#include <fdt_support.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#include "pinctrl-meson.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char *meson_pinctrl_dummy_name = "_dummy";
+
+static int meson_pinctrl_get_groups_count(struct udevice *dev)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+
+	return priv->data->num_groups;
+}
+
+static const char *meson_pinctrl_get_group_name(struct udevice *dev,
+						unsigned selector)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+
+	if (!priv->data->groups[selector].name)
+		return meson_pinctrl_dummy_name;
+
+	return priv->data->groups[selector].name;
+}
+
+static int meson_pinmux_get_functions_count(struct udevice *dev)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+
+	return priv->data->num_funcs;
+}
+
+static const char *meson_pinmux_get_function_name(struct udevice *dev,
+						  unsigned selector)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+
+	return priv->data->funcs[selector].name;
+}
+
+static void meson_pinmux_disable_other_groups(struct meson_pinctrl *priv,
+					      unsigned int pin, int sel_group)
+{
+	struct meson_pmx_group *group;
+	void __iomem *addr;
+	int i, j;
+
+	for (i = 0; i < priv->data->num_groups; i++) {
+		group = &priv->data->groups[i];
+		if (group->is_gpio || i == sel_group)
+			continue;
+
+		for (j = 0; j < group->num_pins; j++) {
+			if (group->pins[j] == pin) {
+				/* We have found a group using the pin */
+				debug("pinmux: disabling %s\n", group->name);
+				addr = priv->reg_mux + group->reg * 4;
+				writel(readl(addr) & ~BIT(group->bit), addr);
+			}
+		}
+	}
+}
+
+static int meson_pinmux_group_set(struct udevice *dev,
+				  unsigned group_selector,
+				  unsigned func_selector)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+	const struct meson_pmx_group *group;
+	const struct meson_pmx_func *func;
+	void __iomem *addr;
+	int i;
+
+	group = &priv->data->groups[group_selector];
+	func = &priv->data->funcs[func_selector];
+
+	debug("pinmux: set group %s func %s\n", group->name, func->name);
+
+	/*
+	 * Disable groups using the same pins.
+	 * The selected group is not disabled to avoid glitches.
+	 */
+	for (i = 0; i < group->num_pins; i++) {
+		meson_pinmux_disable_other_groups(priv,
+						  group->pins[i],
+						  group_selector);
+	}
+
+	/* Function 0 (GPIO) doesn't need any additional setting */
+	if (func_selector) {
+		addr = priv->reg_mux + group->reg * 4;
+		writel(readl(addr) | BIT(group->bit), addr);
+	}
+
+	return 0;
+}
+
+const struct pinctrl_ops meson_pinctrl_ops = {
+	.get_groups_count = meson_pinctrl_get_groups_count,
+	.get_group_name = meson_pinctrl_get_group_name,
+	.get_functions_count = meson_pinmux_get_functions_count,
+	.get_function_name = meson_pinmux_get_function_name,
+	.pinmux_group_set = meson_pinmux_group_set,
+	.set_state = pinctrl_generic_set_state,
+};
+
+static fdt_addr_t parse_address(int offset, const char *name, int na, int ns)
+{
+	int index, len = 0;
+	const fdt32_t *reg;
+
+	index = fdt_find_string(gd->fdt_blob, offset, "reg-names", name);
+	if (index < 0)
+		return FDT_ADDR_T_NONE;
+
+	reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
+	if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns))))
+		return FDT_ADDR_T_NONE;
+
+	reg += index * (na + ns);
+
+	return fdt_translate_address((void *)gd->fdt_blob, offset, reg);
+}
+
+int meson_pinctrl_probe(struct udevice *dev)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+	int node, gpio = -1, len;
+	int na, ns;
+
+	na = fdt_address_cells(gd->fdt_blob, dev->parent->of_offset);
+	if (na < 1) {
+		debug("bad #address-cells\n");
+		return -EINVAL;
+	}
+
+	ns = fdt_size_cells(gd->fdt_blob, dev->parent->of_offset);
+	if (ns < 1) {
+		debug("bad #size-cells\n");
+		return -EINVAL;
+	}
+
+	fdt_for_each_subnode(gd->fdt_blob, node, dev->of_offset) {
+		if (fdt_getprop(gd->fdt_blob, node, "gpio-controller", &len)) {
+			gpio = node;
+			break;
+		}
+	}
+
+	if (!gpio) {
+		debug("gpio node not found\n");
+		return -EINVAL;
+	}
+
+	addr = parse_address(gpio, "mux", na, ns);
+	if (addr == FDT_ADDR_T_NONE) {
+		debug("mux not found\n");
+		return -EINVAL;
+	}
+
+	priv->reg_mux = (void __iomem *)addr;
+	priv->data = (struct meson_pinctrl_data *)dev_get_driver_data(dev);
+
+	return 0;
+}
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
new file mode 100644
index 0000000..4127a60
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2016 - Beniamino Galvani <b.galvani at gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __PINCTRL_MESON_H__
+#define __PINCTRL_MESON_H__
+
+#include <linux/types.h>
+
+struct meson_pmx_group {
+	const char *name;
+	const unsigned int *pins;
+	unsigned int num_pins;
+	bool is_gpio;
+	unsigned int reg;
+	unsigned int bit;
+};
+
+struct meson_pmx_func {
+	const char *name;
+	const char * const *groups;
+	unsigned int num_groups;
+};
+
+struct meson_pinctrl_data {
+	const char *name;
+	struct meson_pmx_group *groups;
+	struct meson_pmx_func *funcs;
+	unsigned int pin_base;
+	unsigned int num_pins;
+	unsigned int num_groups;
+	unsigned int num_funcs;
+};
+
+struct meson_pinctrl {
+	struct meson_pinctrl_data *data;
+	void __iomem *reg_mux;
+};
+
+#define PIN(x, b)	(b + x)
+
+#define GROUP(grp, r, b)						\
+	{								\
+		.name = #grp,						\
+		.pins = grp ## _pins,					\
+		.num_pins = ARRAY_SIZE(grp ## _pins),			\
+		.reg = r,						\
+		.bit = b,						\
+	 }
+
+#define GPIO_GROUP(gpio, b)						\
+	{								\
+		.name = #gpio,						\
+		.pins = (const unsigned int[]){ PIN(gpio, b) },		\
+		.num_pins = 1,						\
+		.is_gpio = true,					\
+	 }
+
+#define FUNCTION(fn)							\
+	{								\
+		.name = #fn,						\
+		.groups = fn ## _groups,				\
+		.num_groups = ARRAY_SIZE(fn ## _groups),		\
+	}
+
+#define MESON_PIN(x, b) PINCTRL_PIN(PIN(x, b), #x)
+
+extern const struct pinctrl_ops meson_pinctrl_ops;
+
+int meson_pinctrl_probe(struct udevice *dev);
+
+#endif /* __PINCTRL_MESON_H__ */
-- 
2.7.4



From sudeep.holla at arm.com  Tue Aug 16 02:58:19 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 16 Aug 2016 10:58:19 +0100
Subject: [RFC PATCH v3 5/8] firmware: Add legacy SCPI protocol driver
In-Reply-To: <9b1d633e-6215-23c5-6cc2-bc64d104aa0a@baylibre.com>
References: <1470738562-20026-1-git-send-email-narmstrong@baylibre.com>
 <1470738562-20026-6-git-send-email-narmstrong@baylibre.com>
 <cea12544-6dfd-55d4-7c85-68290c720515@arm.com>
 <9b1d633e-6215-23c5-6cc2-bc64d104aa0a@baylibre.com>
Message-ID: <23fef94e-cebf-06c6-9ed1-c6a1d26df7ad@arm.com>

Hi Neil,

On 16/08/16 10:41, Neil Armstrong wrote:
> On 08/15/2016 03:35 PM, Sudeep Holla wrote:
>> Hi Neil,
>>
>> On 09/08/16 11:29, Neil Armstrong wrote:
>>> Add legacy protocol driver for an early published SCPI implementation
>>> by supporting old command indexes and structure.
>>> This driver also supports vendor messages and rockchip specific
>>> mailbox data structure for message passing to SCP.
>>>
>>
>
> Hi Sudeep,
>
>> Sorry for the delay but I expected some attempts to reduce the
>> duplication of code we have here. I really don't like the duplication of
>> the code. As I mentioned earlier it can be reduced. I see lot of scope
>> for that and I see that you made zero attempts since v2.
>
> Yes, this post is an intermediate RFC to show to rockchip guys how I
> could implement supportfor their vendor commands, the next RFC will
> certainly merge the two  drivers with minimal code duplication.
>

Ah sorry for the comment then, I didn't realize that. I missed those
discussions.

>>> +enum legacy_scpi_client_id {
>>> +    SCPI_CL_NONE,
>>> +    SCPI_CL_CLOCKS,
>>> +    SCPI_CL_DVFS,
>>> +    SCPI_CL_POWER,
>>> +    SCPI_CL_THERMAL,
>>> +    SCPI_MAX,
>>> +};
>>> +
>>
>> As I said before these values were introduced by me initially and I
>> reckon firmware doesn't depend on that. Have you really tested dropping
>> them ? This must go as they are useless and we now have tokens which are
>> much better.
>
> I am not sure, I'm currently waiting for Amlogic's SCPI FW specification to be sure
> these are not needed at all, in the meantime I will still implement them.
>

Just change and give it a spin on your board. The initial spec mentions
that the SCP should return this as is as sent by the requester. I
thought of this grouping initially and then found certain limitations
and went with token which is bit more useful compared to this after some
review.

>>
>> I will stop here and ask why can't you start with simple change like
>> below ? Then we can add or re-define the structures/enums when
>> absolutely needed. Please don't just copy the entire driver and make
>> changes where-ever needed or please try to adapt to the new driver and
>> try to deviate as less as required by the firmware.
>
> It will be done in RFC v4.
>

Cool, thanks. I will try to review ASAP, so that we can target v4.9

-- 
Regards,
Sudeep


From khilman at baylibre.com  Tue Aug 16 06:10:56 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 16 Aug 2016 08:10:56 -0500
Subject: [PATCH v3 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <9cfa549e-1979-cb42-bfe1-1ef347dd3a9a@roeck-us.net> (Guenter
 Roeck's message of "Mon, 15 Aug 2016 18:51:38 -0700")
References: <1468141867-4172-1-git-send-email-narmstrong@baylibre.com>
 <1468141867-4172-4-git-send-email-narmstrong@baylibre.com>
 <578271D3.4080704@roeck-us.net> <7hbn237aw7.fsf@baylibre.com>
 <m2bn19qsy3.fsf@baylibre.com>
 <CAOi56cUQaFKYu2jNP0AuLOSNnNramu+DNPc+PH7K0gHDZMf+zA@mail.gmail.com>
 <7hinv1ahqi.fsf@baylibre.com>
 <9cfa549e-1979-cb42-bfe1-1ef347dd3a9a@roeck-us.net>
Message-ID: <m2wpjg97vj.fsf@baylibre.com>

Guenter Roeck <linux at roeck-us.net> writes:

> On 08/15/2016 01:40 PM, Kevin Hilman wrote:
>> Kevin Hilman <khilman at baylibre.com> writes:
>>
>>> On Wed, Aug 3, 2016 at 5:27 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>>>> Hi Guenter,
>>>>
>>>> Kevin Hilman <khilman at baylibre.com> writes:
>>>>
>>>>> Guenter Roeck <linux at roeck-us.net> writes:
>>>>>
>>>>>> On 07/10/2016 02:11 AM, Neil Armstrong wrote:
>>>>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>>>>
>>>>>> Reviewed-by: Guenter Roeck <linux at roeck-us.net>
>>>>>>
>>>>>> Would this go in through one of the arm trees ?
>>>>>
>>>>> You can take the driver through the watchdog tree, but I'll take the DT
>>>>> stuff through the amlogic tree (and submit via arm-soc).
>>>>>
>>>>> However, with your ack, and since this is a brand new driver, I could
>>>>> take the driver as well.  Just let me know your preference.
>>>>
>>>> ping... do you have a prefernce here?
>>>>
>>>
>>> Oops, just noticed Wim already picked these up.
>>>
>>
>> Strange, seems that Wim picked up patches 1 & 3, but this one was missed.  I'll
>> queue this for the arm-soc tree.
>>
>
> I got a number of requests from arm maintainers to not pick up devicetree changes
> for arch/arm, so for my part I usually leave those alone.

Yeah, that's the normal way, but Wim replied to the cover letter saying
he would pick up all three, so I got a bit confused.

Anyways, not a big deal.  I'll take it from here.

Kevin


From khilman at baylibre.com  Tue Aug 16 06:12:45 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 16 Aug 2016 08:12:45 -0500
Subject: [PATCH v0 4/4] i2c: meson: Use complete() instead of
 complete_all()
In-Reply-To: <1470225791-16613-5-git-send-email-wagi@monom.org> (Daniel
 Wagner's message of "Wed, 3 Aug 2016 14:03:11 +0200")
References: <1470225791-16613-1-git-send-email-wagi@monom.org>
 <1470225791-16613-5-git-send-email-wagi@monom.org>
Message-ID: <m2shu497si.fsf@baylibre.com>

Daniel Wagner <wagi at monom.org> writes:

> From: Daniel Wagner <daniel.wagner at bmw-carit.de>
>
> There is only one waiter for the completion, therefore there
> is no need to use complete_all(). Let's make that clear by
> using complete() instead of complete_all().
>
> The usage pattern of the completion is:
>
> meson_i2c_xfer_msg()
>   reinit_completion()
>   ...
>   /* Start the transfer */
>   ...
>   wait_for_completion_timeout()
>
> Signed-off-by: Daniel Wagner <daniel.wagner at bmw-carit.de>

Acked-by: Kevin Hilman <khilman at baylibre.com>


From khilman at baylibre.com  Tue Aug 16 06:20:00 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 16 Aug 2016 08:20:00 -0500
Subject: [PATCH v2 0/4] pwm: Add Amlogic Meson SoC PWM Controller
In-Reply-To: <CAOi56cVGRpSeAVwaATkx8Q2wz9hxocq6095opJQZucfDML2wSg@mail.gmail.com>
References: <1468142645-4360-1-git-send-email-narmstrong@baylibre.com>
 <CAOi56cVGRpSeAVwaATkx8Q2wz9hxocq6095opJQZucfDML2wSg@mail.gmail.com>
Message-ID: <CAOi56cWRwc28RcRopLpRiFLX-rft-KfgMZHwDGFG3f6tJ_8kYw@mail.gmail.com>

On Wed, Aug 3, 2016 at 7:25 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Hi Thierry,
>
> On Sun, Jul 10, 2016 at 2:27 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>> Add support for the PWM controller found in Amlogic Meson SoCs.
>> This controller provides a dual PWM output with 4 selectable clock source
>> and a two level divider to achieve a better PWM range.
>>
>> Currently Meson8b and GXBB SoCs are supported.
>>
>> Changes since v1 at http://lkml.kernel.org/r/1466173784-15625-1-git-send-email-narmstrong at baylibre.com :
>> - fix meson8b dtsi
>
> Gentle reminder ping on this series.
>

One more... :)


From narmstrong at baylibre.com  Tue Aug 16 06:34:35 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 16 Aug 2016 15:34:35 +0200
Subject: [PATCH 1/3] clk: meson: Add GXBB AO Clock and Reset controller
 driver
In-Reply-To: <20160813012910.GT361@codeaurora.org>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
 <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
 <20160813012910.GT361@codeaurora.org>
Message-ID: <16163435-1310-043d-804f-3bb1fd33cff4@baylibre.com>

Hi Stephen,

On 08/13/2016 03:29 AM, Stephen Boyd wrote:
> On 08/09, Neil Armstrong wrote:
>> diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
>> new file mode 100644
>> index 0000000..56a9186
>> --- /dev/null
>> +++ b/drivers/clk/meson/gxbb-aoclk.c
>> @@ -0,0 +1,203 @@

[...]

>> + */
>> +#include <linux/clk.h>
> 
> Is this include used?

No !

> 
>> +#include <linux/clk-provider.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset-controller.h>
>> +#include <linux/module.h>
>> +#include <dt-bindings/clock/gxbb-aoclkc.h>
>> +#include <dt-bindings/reset/gxbb-aoclkc.h>
>> +
>> +static DEFINE_SPINLOCK(clk_lock);
> 
> gxbb_clk_lock?

Renamed into gxbb_aoclk_lock for sake of clarity

> 
>> +
>> +struct gxbb_aoclk_reset_controller {
>> +	struct reset_controller_dev reset;
>> +	unsigned int *data;
>> +	void __iomem *base;
>> +};
>> +

[...]

>> +
>> +static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
> 
> can this be const?

It would be awesome, but it will be discarded by of_clk_add_hw_provider :

drivers/clk/meson/gxbb-aoclk.c:176:4: warning: passing argument 3 of 'of_clk_add_hw_provider' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
    &gxbb_aoclk_onecell_data);

In file included from drivers/clk/meson/gxbb-aoclk.c:55:0:
./include/linux/clk-provider.h:788:5: note: expected 'void *' but argument is of type 'const struct clk_hw_onecell_data *'
 int of_clk_add_hw_provider(struct device_node *np,

> 
>> +	.hws = {
>> +		[CLKID_AO_REMOTE] = &remote_ao.hw,
>> +		[CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw,
>> +		[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao.hw,
>> +		[CLKID_AO_UART1] = &uart1_ao.hw,
>> +		[CLKID_AO_UART2] = &uart2_ao.hw,
>> +		[CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
>> +	},
>> +	.num = ARRAY_SIZE(gxbb_aoclk_gate),
>> +};
>> +
>> +static int gxbb_aoclkc_probe(struct platform_device *pdev)
>> +{
>> +	void __iomem *base;
>> +	int ret, clkid;
>> +	struct device *dev = &pdev->dev;
>> +	struct gxbb_aoclk_reset_controller *rstc;
>> +
>> +	rstc = devm_kzalloc(dev, sizeof(rstc), GFP_KERNEL);
>> +	if (!rstc)
>> +		return -ENOMEM;
>> +
>> +	/*  Generic clocks */
>> +	base = of_iomap(dev->of_node, 0);
> 
> use devm_ioremap_resource() please and platform APIs to get the
> ioresource.

Done.

> 
>> +	if (!base) {
>> +		pr_err("%s: Unable to map clk base\n", __func__);
> 
> We don't need error prints here with devm_ioremap_resource().
> 
>> +		return -ENXIO;
>> +	}
>> +
>> +	/* Reset Controller */
>> +	rstc->base = base;
>> +	rstc->data = gxbb_aoclk_reset;
>> +	rstc->reset.ops = &gxbb_aoclk_reset_ops;
>> +	rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset);
>> +	rstc->reset.of_node = dev->of_node;
>> +	ret = devm_reset_controller_register(dev, &rstc->reset);
>> +
>> +	/*
>> +	 * Populate base address and register all clks
>> +	 */
>> +	for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) {
>> +		gxbb_aoclk_gate[clkid]->reg = base;
>> +
>> +		ret = devm_clk_hw_register(dev,
>> +					gxbb_aoclk_onecell_data.hws[clkid]);
>> +		if (ret)
>> +			goto iounmap;
>> +	}
>> +
>> +	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
>> +			&gxbb_aoclk_onecell_data);
>> +
>> +iounmap:
>> +	iounmap(base);
>> +	return ret;
>> +}
>> +
>> +static const struct of_device_id gxbb_aoclkc_match_table[] = {
>> +	{ .compatible = "amlogic,gxbb-aoclkc" },
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
>> +
>> +static struct platform_driver gxbb_aoclkc_driver = {
>> +	.probe		= gxbb_aoclkc_probe,
> 
> No remove means leak of iomem mapping.
> 

It will be non-modular, so no need of remove. The MODULE_* macros and module.h include will be removed like other clk drivers (gxbb and oxnas for instance).

Thanks,
Neil




From narmstrong at baylibre.com  Tue Aug 16 06:35:09 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 16 Aug 2016 15:35:09 +0200
Subject: [PATCH 1/3] clk: meson: Add GXBB AO Clock and Reset controller
 driver
In-Reply-To: <CAP=VYLphcuq16vDueOOJ6anrW-ifYAK+1ijSjkGbxw48+m4xrw@mail.gmail.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
 <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
 <CAP=VYLphcuq16vDueOOJ6anrW-ifYAK+1ijSjkGbxw48+m4xrw@mail.gmail.com>
Message-ID: <5529118a-63f0-cb54-f6a4-305603da168f@baylibre.com>

On 08/15/2016 02:08 AM, Paul Gortmaker wrote:
> On Tue, Aug 9, 2016 at 5:13 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>> Adds a Clock and Reset controller driver for the Always-On part
>> of the Amlogic Meson GXBB SoC.
>>
>> It exports paired Clocks and Resets lines that will be used by
>> peripherals in the Always-On subsystem.
> 
> [...]
> 
>> +static const struct of_device_id gxbb_aoclkc_match_table[] = {
>> +       { .compatible = "amlogic,gxbb-aoclkc" },
>> +       { }
>> +};
>> +MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
>> +
>> +static struct platform_driver gxbb_aoclkc_driver = {
>> +       .probe          = gxbb_aoclkc_probe,
>> +       .driver         = {
>> +               .name   = "gxbb-aoclkc",
>> +               .of_match_table = gxbb_aoclkc_match_table,
>> +       },
>> +};
>> +
>> +module_platform_driver(gxbb_aoclkc_driver);
>> +
>> +MODULE_DESCRIPTION("AmLogic Meson GXBB AO Clock Controller Driver");
>> +MODULE_LICENSE("Dual BSD/GPL");
>> +MODULE_ALIAS("platform:gxbb-aoclkc");
>> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
> 
> Since this driver is controlled by a bool Kconfig, you can dump the module.h
> include and all the MODULE_<xyz> tags above.
> 
> Or, if there is a genuine use case for it to be modular, then make it tristate?
> 
> Thanks,
> Paul.
> 

It will be non-modular.

Thanks,
Neil


From narmstrong at baylibre.com  Tue Aug 16 06:50:18 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 16 Aug 2016 15:50:18 +0200
Subject: [PATCH v2 1/4] pwm: Add support for Meson PWM Controller
In-Reply-To: <CAFBinCAXJ_POd9=UhL8vM6_sXXgVMgSZCwDKosLSzW2++ZmTQQ@mail.gmail.com>
References: <1468142645-4360-1-git-send-email-narmstrong@baylibre.com>
 <1468142645-4360-2-git-send-email-narmstrong@baylibre.com>
 <CAFBinCAXJ_POd9=UhL8vM6_sXXgVMgSZCwDKosLSzW2++ZmTQQ@mail.gmail.com>
Message-ID: <ad674bac-885b-e975-dd4c-d7ae11789d5a@baylibre.com>

Hi Martin,

On 08/15/2016 06:55 PM, Martin Blumenstingl wrote:
> On Sun, Jul 10, 2016 at 11:24 AM, Neil Armstrong

[...]

>> +static int meson_pwm_calc(struct meson_pwm_chip *chip,
>> +                              struct meson_pwm_channel *pwm_chan,
>> +                              unsigned int id,
>> +                              int duty_ns, unsigned int period_ns)
>> +{
>> +       unsigned int pwm_pre_div;
>> +       unsigned int pwm_cnt;
>> +       unsigned int pwm_duty_cnt;
>> +       unsigned long fin_freq = -1;
>> +       unsigned long fin_ns;
>> +       unsigned int i = 0;
>> +
>> +       if (duty_ns > period_ns)
>> +               return -EINVAL;
>> +
>> +       switch (id) {
>> +       case PWM_A:
>> +               fin_freq = clk_get_rate(chip->clk[0]);
>> +               break;
>> +       case PWM_B:
>> +               fin_freq = clk_get_rate(chip->clk[1]);
>> +               break;
>> +       }
>> +       if (fin_freq <= 0) {
>> +               dev_err(chip->chip.dev, "invalid source clock frequency\n");
>> +               return -EINVAL;
>> +       }
>> +       dev_dbg(chip->chip.dev, "fin_freq: %luHz\n", fin_freq);
>> +       fin_ns = NSEC_PER_SEC / fin_freq;
>> +
>> +       /* Calc pre_div with the period */
>> +       for (i = 0; i < MISC_CLK_DIV_MASK; i++) {
>> +               pwm_pre_div = i;
> according to the public (S905) datasheet the hardware wants "value
> +1": "Selects the divider (N+1) for the PWM A clock"
> so shouldn't this be pwm_pre_div = i + 1?
> all your calculations below are already adding 1 to pwm_pre_div, but
> pwm_pre_div is directly written to the hardware register in
> meson_pwm_config()

You misread the datasheet, usually the phrase :
"PWM_A_CLK_DIV: Selects the divider (N+1) for the PWM A clock"

Means, the divider that will be applied will be "N + 1", N is the value written in the register.

This is why we start from 0 and for the following calculation, I add +1 :
>> +               pwm_cnt = DIV_ROUND_CLOSEST(period_ns,
>> +                               fin_ns * (pwm_pre_div + 1));

This behavior was also present in the original vendor's driver.

>> +               dev_dbg(chip->chip.dev, "fin_ns=%lu pre_div=%d cnt=%d\n",
>> +                               fin_ns, pwm_pre_div, pwm_cnt);
>> +               if (pwm_cnt <= 0xffff)
>> +                       break;
>> +       }
>> +       if (i == MISC_CLK_DIV_MASK) {
>> +               dev_err(chip->chip.dev, "Unable to get period pre_div");
>> +               return -EINVAL;
>> +       }
>> +       dev_dbg(chip->chip.dev, "period_ns=%d pre_div=%d pwm_cnt=%d\n",
>> +               period_ns, pwm_pre_div, pwm_cnt);
>> +
>> +       if (duty_ns == period_ns) {
>> +               pwm_chan->pwm_pre_div = pwm_pre_div;
>> +               pwm_chan->pwm_hi = pwm_cnt;
>> +               pwm_chan->pwm_lo = 0;
>> +       } else if (duty_ns == 0) {
>> +               pwm_chan->pwm_pre_div = pwm_pre_div;
>> +               pwm_chan->pwm_hi = 0;
>> +               pwm_chan->pwm_lo = pwm_cnt;
>> +       } else {
>> +               /* Then check is we can have the duty with the same pre_div */
>> +               pwm_duty_cnt = DIV_ROUND_CLOSEST(duty_ns,
>> +                                       fin_ns * (pwm_pre_div + 1));
>> +               if (pwm_cnt > 0xffff) {
>> +                       dev_err(chip->chip.dev, "Unable to get duty period, differences are too high");
>> +                       return -EINVAL;
>> +               }
>> +               dev_dbg(chip->chip.dev, "duty_ns=%d pre_div=%d pwm_cnt=%d\n",
>> +                       duty_ns, pwm_pre_div, pwm_duty_cnt);
>> +
>> +               pwm_chan->pwm_pre_div = pwm_pre_div;
>> +               pwm_chan->pwm_hi = pwm_duty_cnt;
>> +               pwm_chan->pwm_lo = pwm_cnt - pwm_chan->pwm_hi;
>> +       }
>> +
>> +       return 0;
>> +}

Neil



From robh at kernel.org  Tue Aug 16 07:25:40 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 16 Aug 2016 09:25:40 -0500
Subject: [PATCH 1/3] net: dt-bindings: Document the new Meson8b and GXBB
 DWMAC bindings
In-Reply-To: <20160815164100.27766-2-martin.blumenstingl@googlemail.com>
References: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-2-martin.blumenstingl@googlemail.com>
Message-ID: <20160816142540.GA1332@rob-hp-laptop>

On Mon, Aug 15, 2016 at 06:40:58PM +0200, Martin Blumenstingl wrote:
> This patch adds the documentation for the DWMAC ethernet controller
> found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
> The main difference between the Meson6 glue is that different registers
> (with different layout) are used.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> ---
>  .../devicetree/bindings/net/meson-dwmac.txt        | 43 ++++++++++++++++++----
>  1 file changed, 35 insertions(+), 8 deletions(-)

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


From sboyd at codeaurora.org  Tue Aug 16 10:29:45 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Tue, 16 Aug 2016 10:29:45 -0700
Subject: [PATCH 1/3] clk: meson: Add GXBB AO Clock and Reset controller
 driver
In-Reply-To: <16163435-1310-043d-804f-3bb1fd33cff4@baylibre.com>
References: <1470734008-18849-1-git-send-email-narmstrong@baylibre.com>
 <1470734008-18849-2-git-send-email-narmstrong@baylibre.com>
 <20160813012910.GT361@codeaurora.org>
 <16163435-1310-043d-804f-3bb1fd33cff4@baylibre.com>
Message-ID: <20160816172945.GZ361@codeaurora.org>

On 08/16, Neil Armstrong wrote:
> On 08/13/2016 03:29 AM, Stephen Boyd wrote:
> > On 08/09, Neil Armstrong wrote:
> 
> >> +
> >> +static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
> > 
> > can this be const?
> 
> It would be awesome, but it will be discarded by of_clk_add_hw_provider :

Ok, right.

> >> +iounmap:
> >> +	iounmap(base);
> >> +	return ret;
> >> +}
> >> +
> >> +static const struct of_device_id gxbb_aoclkc_match_table[] = {
> >> +	{ .compatible = "amlogic,gxbb-aoclkc" },
> >> +	{ }
> >> +};
> >> +MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
> >> +
> >> +static struct platform_driver gxbb_aoclkc_driver = {
> >> +	.probe		= gxbb_aoclkc_probe,
> > 
> > No remove means leak of iomem mapping.

And OF provider registration.

> > 
> 
> It will be non-modular, so no need of remove. The MODULE_* macros and module.h include will be removed like other clk drivers (gxbb and oxnas for instance).

Ok make sure to remove sysfs unbinding then.

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


From khilman at baylibre.com  Wed Aug 17 19:15:03 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 17 Aug 2016 21:15:03 -0500
Subject: [PATCH v3 0/4] Amlogic: Meson: Add reset controller
In-Reply-To: <1464853333.3307.1.camel@pengutronix.de>
References: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
 <1464853333.3307.1.camel@pengutronix.de>
Message-ID: <CAOi56cV4uUkx+H4fKjFESOs_Kc0p0x5XfAQjtTNQJRjCQmAtGg@mail.gmail.com>

Hi Philipp,

On Thu, Jun 2, 2016 at 2:42 AM, Philipp Zabel <p.zabel at pengutronix.de> wrote:
> Hi Neil,
>
> Am Montag, den 30.05.2016, 15:27 +0200 schrieb Neil Armstrong:
>> Patchset to add and enable the reset controller driver on Meson SoCs platforms.
>>
>> This reset controller has up to 256 reset lines with reset pulse generation only,
>> so the assert and deassert calls are not available.
>>
>> Depends on the patch :
>>  - "reset: add devm_reset_controller_register API" [1]
>>
>> Changes since v2 at http://lkml.kernel.org/r/1464169758-26975-1-git-send-email-narmstrong at baylibre.com :
>> - Get back __iomem in _reset() callback
>> - Get rid of MODULE_ALIAS
>>
>> Changes since v1 at http://lkml.kernel.org/r/1463732875-23141-1-git-send-email-narmstrong at baylibre.com :
>> - Remove _gxbb_ in names
>> - Depends build on ARCH_MESON only
>> - Add meson8b compatible and bindings
>> - Re-indent dt-bindings headers
>> - Switch to devm_ reset controller register
>> - Remove platform "remove" callback
>> - Update Dual BSD/GPL file headers
>>
>> Changes since the RFC at http://lkml.kernel.org/r/1463148012-25988-1-git-send-email-narmstrong at baylibre.com :
>> - Fix register mapping and bit defines in bindings header
>> - Remove assert and unassert calls
>> - Fix missing __iomem
>>
>> [1] https://patchwork.kernel.org/patch/8988471/
>>
>> Neil Armstrong (4):
>>   reset: Add support for the Amlogic Meson SoC Reset Controller
>>   dt-bindings: reset: Add bindings for the Meson SoC Reset Controller
>
> I've applied these two patches to the reset/next branch.
>

I'm just noticing now that these didn't make it into v4.8-rc1.  Was
there reason for that?

Kevin


From khilman at baylibre.com  Wed Aug 17 19:28:56 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 17 Aug 2016 21:28:56 -0500
Subject: [PATCH v3 0/4] Amlogic: Meson: Add reset controller
In-Reply-To: <CAOi56cV4uUkx+H4fKjFESOs_Kc0p0x5XfAQjtTNQJRjCQmAtGg@mail.gmail.com>
References: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
 <1464853333.3307.1.camel@pengutronix.de>
 <CAOi56cV4uUkx+H4fKjFESOs_Kc0p0x5XfAQjtTNQJRjCQmAtGg@mail.gmail.com>
Message-ID: <CAOi56cUcNSrvNdH6OCXWLJb+jW_jUFWyTMBnrN7nQ=jsRTE7bw@mail.gmail.com>

On Wed, Aug 17, 2016 at 9:15 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Hi Philipp,
>
> On Thu, Jun 2, 2016 at 2:42 AM, Philipp Zabel <p.zabel at pengutronix.de> wrote:
>> Hi Neil,
>>
>> Am Montag, den 30.05.2016, 15:27 +0200 schrieb Neil Armstrong:
>>> Patchset to add and enable the reset controller driver on Meson SoCs platforms.
>>>
>>> This reset controller has up to 256 reset lines with reset pulse generation only,
>>> so the assert and deassert calls are not available.
>>>
>>> Depends on the patch :
>>>  - "reset: add devm_reset_controller_register API" [1]
>>>
>>> Changes since v2 at http://lkml.kernel.org/r/1464169758-26975-1-git-send-email-narmstrong at baylibre.com :
>>> - Get back __iomem in _reset() callback
>>> - Get rid of MODULE_ALIAS
>>>
>>> Changes since v1 at http://lkml.kernel.org/r/1463732875-23141-1-git-send-email-narmstrong at baylibre.com :
>>> - Remove _gxbb_ in names
>>> - Depends build on ARCH_MESON only
>>> - Add meson8b compatible and bindings
>>> - Re-indent dt-bindings headers
>>> - Switch to devm_ reset controller register
>>> - Remove platform "remove" callback
>>> - Update Dual BSD/GPL file headers
>>>
>>> Changes since the RFC at http://lkml.kernel.org/r/1463148012-25988-1-git-send-email-narmstrong at baylibre.com :
>>> - Fix register mapping and bit defines in bindings header
>>> - Remove assert and unassert calls
>>> - Fix missing __iomem
>>>
>>> [1] https://patchwork.kernel.org/patch/8988471/
>>>
>>> Neil Armstrong (4):
>>>   reset: Add support for the Amlogic Meson SoC Reset Controller
>>>   dt-bindings: reset: Add bindings for the Meson SoC Reset Controller
>>
>> I've applied these two patches to the reset/next branch.
>>
>
> I'm just noticing now that these didn't make it into v4.8-rc1.  Was
> there reason for that?

Doh, nevermind, I'm blind (and was looking at the wrong tree.)   I see them now.

Kevin


From sjg at chromium.org  Wed Aug 17 20:44:32 2016
From: sjg at chromium.org (Simon Glass)
Date: Wed, 17 Aug 2016 21:44:32 -0600
Subject: [PATCH 2/4] arm: dts: update DTS files for meson-gxbb and
 odroid-c2
In-Reply-To: <1471340990-16247-3-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
 <1471340990-16247-3-git-send-email-b.galvani@gmail.com>
Message-ID: <CAPnjgZ0E6i+rCaq-_aGJCFn1KTHfwwpK=kQaD=nAj3-O_o+4Ug@mail.gmail.com>

On 16 August 2016 at 03:49, Beniamino Galvani <b.galvani at gmail.com> wrote:
> Import DTS files and dt-bindings includes from Linux 4.8-rc1.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
> ---
>  arch/arm/dts/meson-gxbb-odroidc2.dts               |  19 ++
>  arch/arm/dts/meson-gxbb.dtsi                       | 170 ++++++++++++++++-
>  include/dt-bindings/gpio/meson-gxbb-gpio.h         | 154 +++++++++++++++
>  .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
>  4 files changed, 552 insertions(+), 1 deletion(-)
>  create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h
>  create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

Reviewed-by: Simon Glass <sjg at chromium.org>


From sjg at chromium.org  Wed Aug 17 20:44:35 2016
From: sjg at chromium.org (Simon Glass)
Date: Wed, 17 Aug 2016 21:44:35 -0600
Subject: [PATCH 1/4] pinctrl: generic: scan for "pins" and "groups"
 properties in sub-nodes
In-Reply-To: <1471340990-16247-2-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
 <1471340990-16247-2-git-send-email-b.galvani@gmail.com>
Message-ID: <CAPnjgZ3jRtWwxdQaDFsQY-d_K6wYNgHOp9mjectcDp==e5F0Yg@mail.gmail.com>

On 16 August 2016 at 03:49, Beniamino Galvani <b.galvani at gmail.com> wrote:
> In cases where the pins and groups definitions are in a sub-node, as:
>
>         uart_a {
>                 mux {
>                         groups = "uart_tx_a", "uart_rx_a";
>                         function = "uart_a";
>                 };
>         };
>
> pinctrl_generic_set_state_subnode() returns an error for the top-level
> node and pinctrl_generic_set_state() fails. Instead, return success so
> that the child nodes are tried.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
> ---
>  drivers/pinctrl/pinctrl-generic.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)

Reviewed-by: Simon Glass <sjg at chromium.org>

Masahiro, are you happy with this change?

We really need some pinctrl tests.

>
> diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
> index e86b72a..baff40f 100644
> --- a/drivers/pinctrl/pinctrl-generic.c
> +++ b/drivers/pinctrl/pinctrl-generic.c
> @@ -312,8 +312,10 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
>                 is_group = true;
>                 strings_count = fdt_count_strings(fdt, node,
>                                                   subnode_target_type);
> -               if (strings_count < 0)
> -                       return -EINVAL;
> +               if (strings_count < 0) {
> +                       /* skip this node; may contain config child nodes */
> +                       return 0;
> +               }
>         }
>
>         for (i = 0; i < strings_count; i++) {
> --
> 2.7.4
>

Regards,
Simon


From sjg at chromium.org  Wed Aug 17 20:44:39 2016
From: sjg at chromium.org (Simon Glass)
Date: Wed, 17 Aug 2016 21:44:39 -0600
Subject: [PATCH 3/4] pinctrl: add driver for meson-gxbb pin controller
In-Reply-To: <1471340990-16247-4-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
 <1471340990-16247-4-git-send-email-b.galvani@gmail.com>
Message-ID: <CAPnjgZ1xodtCYyaR7O5KgKqzTbRkMg+76S3jnmRoTQGp26Zm=A@mail.gmail.com>

On 16 August 2016 at 03:49, Beniamino Galvani <b.galvani at gmail.com> wrote:
> Add a pin controller driver for Meson GXBB adapted from Linux kernel.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
> ---
>  drivers/pinctrl/Kconfig                    |   1 +
>  drivers/pinctrl/Makefile                   |   1 +
>  drivers/pinctrl/meson/Kconfig              |  11 +
>  drivers/pinctrl/meson/Makefile             |   6 +
>  drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 432 +++++++++++++++++++++++++++++
>  drivers/pinctrl/meson/pinctrl-meson.c      | 179 ++++++++++++
>  drivers/pinctrl/meson/pinctrl-meson.h      |  74 +++++
>  7 files changed, 704 insertions(+)
>  create mode 100644 drivers/pinctrl/meson/Kconfig
>  create mode 100644 drivers/pinctrl/meson/Makefile
>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson.c
>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson.h

Reviewed-by: Simon Glass <sjg at chromium.org>


From sjg at chromium.org  Wed Aug 17 20:44:42 2016
From: sjg at chromium.org (Simon Glass)
Date: Wed, 17 Aug 2016 21:44:42 -0600
Subject: [PATCH 4/4] meson: odroid-c2: enable Ethernet support through the
 device tree
In-Reply-To: <1471340990-16247-5-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
 <1471340990-16247-5-git-send-email-b.galvani@gmail.com>
Message-ID: <CAPnjgZ2tiuvJKd2dE6nuitSNFosX36x2KD4ZN4V7+S=StwgnBw@mail.gmail.com>

On 16 August 2016 at 03:49, Beniamino Galvani <b.galvani at gmail.com> wrote:
> Remove the device definition from board file, update the driver with
> the new compatible property and update config with necessary options.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
> ---
>  arch/arm/include/asm/arch-meson/gxbb.h |  3 ---
>  board/amlogic/odroid-c2/odroid-c2.c    | 13 -------------
>  configs/odroid-c2_defconfig            |  3 +++
>  drivers/net/designware.c               |  1 +
>  4 files changed, 4 insertions(+), 16 deletions(-)

Reviewed-by: Simon Glass <sjg at chromium.org>


From narmstrong at baylibre.com  Thu Aug 18 03:08:45 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:08:45 +0200
Subject: [PATCH v2 0/3] clk: Add Meson GXBB Always-On Reset + Clocks
Message-ID: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>

The Amlogic Meson GXBB SoC has an Always-On part that contains pairs on
clocks and reset controls in a single memory mapped control register.
Add a separate clocks and reset node with the corresponding driver
exporting clock nodes and a reset controller.

Changes since v1 at http://lkml.kernel.org/r/1470734008-18849-1-git-send-email-narmstrong at baylibre.com :
 - Make non-modular
 - Remove clk.h and include init.h instead of module.h
 - Use devm_ioremap_resource instead of of_iomap
 - Rename driver spinlock 

Neil Armstrong (3):
  clk: meson: Add GXBB AO Clock and Reset controller driver
  dt-bindings: clock: reset: Add GXBB AO Clock and Reset Bindings
  ARM64: dts: meson-gxbb: Add GXBB AO Clock and Reset node

 .../bindings/clock/amlogic,gxbb-aoclkc.txt         |  45 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   9 +
 drivers/clk/meson/Makefile                         |   2 +-
 drivers/clk/meson/gxbb-aoclk.c                     | 192 +++++++++++++++++++++
 include/dt-bindings/clock/gxbb-aoclkc.h            |  66 +++++++
 include/dt-bindings/reset/gxbb-aoclkc.h            |  66 +++++++
 6 files changed, 379 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
 create mode 100644 drivers/clk/meson/gxbb-aoclk.c
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h

-- 
2.7.0



From narmstrong at baylibre.com  Thu Aug 18 03:08:46 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:08:46 +0200
Subject: [PATCH v2 1/3] clk: meson: Add GXBB AO Clock and Reset controller
 driver
In-Reply-To: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471514928-3341-2-git-send-email-narmstrong@baylibre.com>

Adds a Clock and Reset controller driver for the Always-On part
of the Amlogic Meson GXBB SoC.

It exports paired Clocks and Resets lines that will be used by
peripherals in the Always-On subsystem.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/clk/meson/Makefile     |   2 +-
 drivers/clk/meson/gxbb-aoclk.c | 192 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 193 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/meson/gxbb-aoclk.c

diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 197e401..d4cd4a3 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o
-obj-$(CONFIG_COMMON_CLK_GXBB)	 += gxbb.o
+obj-$(CONFIG_COMMON_CLK_GXBB)	 += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
new file mode 100644
index 0000000..b989e4a
--- /dev/null
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -0,0 +1,192 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/init.h>
+#include <dt-bindings/clock/gxbb-aoclkc.h>
+#include <dt-bindings/reset/gxbb-aoclkc.h>
+
+static DEFINE_SPINLOCK(gxbb_aoclk_lock);
+
+struct gxbb_aoclk_reset_controller {
+	struct reset_controller_dev reset;
+	unsigned int *data;
+	void __iomem *base;
+};
+
+static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	struct gxbb_aoclk_reset_controller *reset =
+		container_of(rcdev, struct gxbb_aoclk_reset_controller, reset);
+
+	writel(BIT(reset->data[id]), reset->base);
+
+	return 0;
+}
+
+static const struct reset_control_ops gxbb_aoclk_reset_ops = {
+	.reset = gxbb_aoclk_do_reset,
+};
+
+#define GXBB_AO_GATE(_name, _bit)					\
+static struct clk_gate _name##_ao = {					\
+	.reg = (void __iomem *)0,					\
+	.bit_idx = (_bit),						\
+	.lock = &gxbb_aoclk_lock,						\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = #_name "_ao",					\
+		.ops = &clk_gate_ops,					\
+		.parent_names = (const char *[]){ "clk81" },		\
+		.num_parents = 1,					\
+		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
+	},								\
+}
+
+GXBB_AO_GATE(remote, 0);
+GXBB_AO_GATE(i2c_master, 1);
+GXBB_AO_GATE(i2c_slave, 2);
+GXBB_AO_GATE(uart1, 3);
+GXBB_AO_GATE(uart2, 5);
+GXBB_AO_GATE(ir_blaster, 6);
+
+static unsigned int gxbb_aoclk_reset[] = {
+	[RESET_AO_REMOTE] = 16,
+	[RESET_AO_I2C_MASTER] = 18,
+	[RESET_AO_I2C_SLAVE] = 19,
+	[RESET_AO_UART1] = 17,
+	[RESET_AO_UART2] = 22,
+	[RESET_AO_IR_BLASTER] = 23,
+};
+
+static struct clk_gate *gxbb_aoclk_gate[] = {
+	[CLKID_AO_REMOTE] = &remote_ao,
+	[CLKID_AO_I2C_MASTER] = &i2c_master_ao,
+	[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
+	[CLKID_AO_UART1] = &uart1_ao,
+	[CLKID_AO_UART2] = &uart2_ao,
+	[CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
+};
+
+static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
+	.hws = {
+		[CLKID_AO_REMOTE] = &remote_ao.hw,
+		[CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw,
+		[CLKID_AO_I2C_SLAVE] = &i2c_slave_ao.hw,
+		[CLKID_AO_UART1] = &uart1_ao.hw,
+		[CLKID_AO_UART2] = &uart2_ao.hw,
+		[CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
+	},
+	.num = ARRAY_SIZE(gxbb_aoclk_gate),
+};
+
+static int gxbb_aoclkc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *base;
+	int ret, clkid;
+	struct device *dev = &pdev->dev;
+	struct gxbb_aoclk_reset_controller *rstc;
+
+	rstc = devm_kzalloc(dev, sizeof(rstc), GFP_KERNEL);
+	if (!rstc)
+		return -ENOMEM;
+
+	/* Generic clocks */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	/* Reset Controller */
+	rstc->base = base;
+	rstc->data = gxbb_aoclk_reset;
+	rstc->reset.ops = &gxbb_aoclk_reset_ops;
+	rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset);
+	rstc->reset.of_node = dev->of_node;
+	ret = devm_reset_controller_register(dev, &rstc->reset);
+
+	/*
+	 * Populate base address and register all clks
+	 */
+	for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) {
+		gxbb_aoclk_gate[clkid]->reg = base;
+
+		ret = devm_clk_hw_register(dev,
+					gxbb_aoclk_onecell_data.hws[clkid]);
+		if (ret)
+			return ret;
+	}
+
+	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+			&gxbb_aoclk_onecell_data);
+}
+
+static const struct of_device_id gxbb_aoclkc_match_table[] = {
+	{ .compatible = "amlogic,gxbb-aoclkc" },
+	{ }
+};
+
+static struct platform_driver gxbb_aoclkc_driver = {
+	.probe		= gxbb_aoclkc_probe,
+	.driver		= {
+		.name	= "gxbb-aoclkc",
+		.of_match_table = gxbb_aoclkc_match_table,
+	},
+};
+
+builtin_platform_driver(gxbb_aoclkc_driver);
-- 
2.7.0



From narmstrong at baylibre.com  Thu Aug 18 03:08:48 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:08:48 +0200
Subject: [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add GXBB AO Clock and Reset
 node
In-Reply-To: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471514928-3341-4-git-send-email-narmstrong@baylibre.com>

Add the AO clock controller node for the AmLogic GXBB SoC.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..c81e1ab 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -45,6 +45,8 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
 #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
+#include <dt-bindings/clock/gxbb-aoclkc.h>
+#include <dt-bindings/reset/gxbb-aoclkc.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -205,6 +207,13 @@
 				};
 			};
 
+			clkc_AO: clock-controller at 040 {
+				compatible = "amlogic,gxbb-aoclkc";
+				reg = <0x0 0x00040 0x0 0x4>;
+				#clock-cells = <1>;
+				#reset-cells = <1>;
+			};
+
 			uart_AO: serial at 4c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x004c0 0x0 0x14>;
-- 
2.7.0



From narmstrong at baylibre.com  Thu Aug 18 03:08:47 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:08:47 +0200
Subject: [PATCH v2 2/3] dt-bindings: clock: reset: Add GXBB AO Clock and Reset
 Bindings
In-Reply-To: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471514928-3341-3-git-send-email-narmstrong@baylibre.com>

Add documentations and dt-bindings headers for the AO clock and reset
controller.

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../bindings/clock/amlogic,gxbb-aoclkc.txt         | 45 +++++++++++++++
 include/dt-bindings/clock/gxbb-aoclkc.h            | 66 ++++++++++++++++++++++
 include/dt-bindings/reset/gxbb-aoclkc.h            | 66 ++++++++++++++++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
new file mode 100644
index 0000000..a55d31b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
@@ -0,0 +1,45 @@
+* Amlogic GXBB AO Clock and Reset Unit
+
+The Amlogic GXBB AO clock controller generates and supplies clock to various
+controllers within the Always-On part of the SoC.
+
+Required Properties:
+
+- compatible: should be "amlogic,gxbb-aoclkc"
+- reg: physical base address of the clock controller and length of memory
+       mapped region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/gxbb-aoclkc.h header and can be
+used in device tree sources.
+
+- #reset-cells: should be 1.
+
+Each reset is assigned an identifier and client nodes can use this identifier
+to specify the reset which they consume. All available resets are defined as
+preprocessor macros in the dt-bindings/reset/gxbb-aoclkc.h header and can be
+used in device tree sources.
+
+Example: AO Clock controller node:
+
+	clkc_AO: clock-controller at 040 {
+		compatible = "amlogic,gxbb-aoclkc";
+		reg = <0x0 0x040 0x0 0x4>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock and reset generated
+  by the clock controller:
+
+	uart_AO: serial at 4c0 {
+		compatible = "amlogic,meson-uart";
+		reg = <0x4c0 0x14>;
+		interrupts = <0 90 1>;
+		clocks = <&clkc_AO CLKID_AO_UART1>;
+		resets = <&clkc_AO RESET_AO_UART1>;
+		status = "disabled";
+	};
diff --git a/include/dt-bindings/clock/gxbb-aoclkc.h b/include/dt-bindings/clock/gxbb-aoclkc.h
new file mode 100644
index 0000000..3175148
--- /dev/null
+++ b/include/dt-bindings/clock/gxbb-aoclkc.h
@@ -0,0 +1,66 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
+#define DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
+
+#define CLKID_AO_REMOTE		0
+#define CLKID_AO_I2C_MASTER	1
+#define CLKID_AO_I2C_SLAVE	2
+#define CLKID_AO_UART1		3
+#define CLKID_AO_UART2		4
+#define CLKID_AO_IR_BLASTER	5
+
+#endif
diff --git a/include/dt-bindings/reset/gxbb-aoclkc.h b/include/dt-bindings/reset/gxbb-aoclkc.h
new file mode 100644
index 0000000..9e3fd60
--- /dev/null
+++ b/include/dt-bindings/reset/gxbb-aoclkc.h
@@ -0,0 +1,66 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
+#define DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
+
+#define RESET_AO_REMOTE		0
+#define RESET_AO_I2C_MASTER	1
+#define RESET_AO_I2C_SLAVE	2
+#define RESET_AO_UART1		3
+#define RESET_AO_UART2		4
+#define RESET_AO_IR_BLASTER	5
+
+#endif
-- 
2.7.0



From narmstrong at baylibre.com  Thu Aug 18 03:10:24 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:24 +0200
Subject: [PATCH v2 0/3] Add Platform MHU mailbox driver for Amlogic GXBB
Message-ID: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>

In order to support Mailbox links for the Amlogic GXBB SoC, add a generic
platform MHU driver based on arm_mhu.c.

This patchset follows a RFC thread along the GXBB SCPI support at :
http://lkml.kernel.org/r/1466503374-28841-1-git-send-email-narmstrong at baylibre.com
And specific MHU discussions at :
http://lkml.kernel.org/r/CABb+yY3HqJG2+GMWCWF9PomxobrwWGZ=TZe5NvXPcHMDdLhkcQ at mail.gmail.com

Changes since v1 at http://lkml.kernel.org/r/1470732737-18391-1-git-send-email-narmstrong at baylibre.com :
 - Fix irq to signed to detect platform_get_irq() failures
 - Introduced back the secure channel
 - Fixed indexes

Changes since RFC v2 :
 - Rename to platform_mhu
 - Sync all link functions with arm_mhu

Neil Armstrong (3):
  mailbox: Add Platform Message-Handling-Unit variant driver
  dt-bindings: mailbox: Add Amlogic Meson MHU Bindings
  ARM64: dts: meson-gxbb: Add Meson MHU Node

 .../devicetree/bindings/mailbox/meson-mhu.txt      |  34 ++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   9 +
 drivers/mailbox/Kconfig                            |  10 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/platform_mhu.c                     | 205 +++++++++++++++++++++
 5 files changed, 260 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/meson-mhu.txt
 create mode 100644 drivers/mailbox/platform_mhu.c

-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:25 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:25 +0200
Subject: [PATCH v2 1/3] mailbox: Add Platform Message-Handling-Unit variant
 driver
In-Reply-To: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>
References: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515027-3543-2-git-send-email-narmstrong@baylibre.com>

Add Message-Handling-Unit driver for platform variants as mailbox controller.
Actually, only the Amlogic Meson GXBB SoC MHU is supported.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/mailbox/Kconfig        |  10 ++
 drivers/mailbox/Makefile       |   2 +
 drivers/mailbox/platform_mhu.c | 205 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 217 insertions(+)
 create mode 100644 drivers/mailbox/platform_mhu.c

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 97c3729..4cc93c6 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -15,6 +15,16 @@ config ARM_MHU
 	  The controller has 3 mailbox channels, the last of which can be
 	  used in Secure mode only.
 
+config PLATFORM_MHU
+	tristate "Platform MHU Mailbox"
+	depends on OF
+	depends on HAS_IOMEM
+	help
+	  Say Y here if you want to build a platform specific variant MHU
+	  controller driver.
+	  The controller has a maximum of 3 mailbox channels, the last of
+	  which can be used in Secure mode only.
+
 config PL320_MBOX
 	bool "ARM PL320 Mailbox"
 	depends on ARM_AMBA
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 66c38e3..ace6fed 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_MAILBOX_TEST)	+= mailbox-test.o
 
 obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
 
+obj-$(CONFIG_PLATFORM_MHU)	+= platform_mhu.o
+
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
diff --git a/drivers/mailbox/platform_mhu.c b/drivers/mailbox/platform_mhu.c
new file mode 100644
index 0000000..e13201a
--- /dev/null
+++ b/drivers/mailbox/platform_mhu.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2016 BayLibre SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ * Synchronised with arm_mhu.c from :
+ * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Jassi Brar <jaswinder.singh at linaro.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * 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/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mailbox_controller.h>
+
+#define INTR_SET_OFS	0x0
+#define INTR_STAT_OFS	0x4
+#define INTR_CLR_OFS	0x8
+
+#define MHU_SEC_OFFSET	0x0
+#define MHU_LP_OFFSET	0xc
+#define MHU_HP_OFFSET	0x18
+#define TX_REG_OFFSET	0x24
+
+#define MHU_CHANS	3
+
+struct platform_mhu_link {
+	int irq;
+	void __iomem *tx_reg;
+	void __iomem *rx_reg;
+};
+
+struct platform_mhu {
+	void __iomem *base;
+	struct platform_mhu_link mlink[MHU_CHANS];
+	struct mbox_chan chan[MHU_CHANS];
+	struct mbox_controller mbox;
+};
+
+static irqreturn_t platform_mhu_rx_interrupt(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 val;
+
+	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
+	if (!val)
+		return IRQ_NONE;
+
+	mbox_chan_received_data(chan, (void *)&val);
+
+	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
+
+	return IRQ_HANDLED;
+}
+
+static bool platform_mhu_last_tx_done(struct mbox_chan *chan)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+
+	return (val == 0);
+}
+
+static int platform_mhu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 *arg = data;
+
+	writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);
+
+	return 0;
+}
+
+static int platform_mhu_startup(struct mbox_chan *chan)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+	u32 val;
+	int ret;
+
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
+
+	ret = request_irq(mlink->irq, platform_mhu_rx_interrupt,
+			  IRQF_SHARED, "platform_mhu_link", chan);
+	if (ret) {
+		dev_err(chan->mbox->dev,
+			"Unable to acquire IRQ %d\n", mlink->irq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void platform_mhu_shutdown(struct mbox_chan *chan)
+{
+	struct platform_mhu_link *mlink = chan->con_priv;
+
+	free_irq(mlink->irq, chan);
+}
+
+static const struct mbox_chan_ops platform_mhu_ops = {
+	.send_data = platform_mhu_send_data,
+	.startup = platform_mhu_startup,
+	.shutdown = platform_mhu_shutdown,
+	.last_tx_done = platform_mhu_last_tx_done,
+};
+
+static int platform_mhu_probe(struct platform_device *pdev)
+{
+	int i, err;
+	struct platform_mhu *mhu;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int platform_mhu_reg[MHU_CHANS] = {
+		MHU_SEC_OFFSET, MHU_LP_OFFSET, MHU_HP_OFFSET
+	};
+
+	/* Allocate memory for device */
+	mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
+	if (!mhu)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mhu->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mhu->base)) {
+		dev_err(dev, "ioremap failed\n");
+		return PTR_ERR(mhu->base);
+	}
+
+	for (i = 0; i < MHU_CHANS; i++) {
+		mhu->chan[i].con_priv = &mhu->mlink[i];
+		mhu->mlink[i].irq = platform_get_irq(pdev, i);
+		if (mhu->mlink[i].irq < 0) {
+			dev_err(dev, "failed to get irq%d\n", i);
+			return mhu->mlink[i].irq;
+		}
+		mhu->mlink[i].rx_reg = mhu->base + platform_mhu_reg[i];
+		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET;
+	}
+
+	mhu->mbox.dev = dev;
+	mhu->mbox.chans = &mhu->chan[0];
+	mhu->mbox.num_chans = MHU_CHANS;
+	mhu->mbox.ops = &platform_mhu_ops;
+	mhu->mbox.txdone_irq = false;
+	mhu->mbox.txdone_poll = true;
+	mhu->mbox.txpoll_period = 1;
+
+	platform_set_drvdata(pdev, mhu);
+
+	err = mbox_controller_register(&mhu->mbox);
+	if (err) {
+		dev_err(dev, "Failed to register mailboxes %d\n", err);
+		return err;
+	}
+
+	dev_info(dev, "Platform MHU Mailbox registered\n");
+	return 0;
+}
+
+static int platform_mhu_remove(struct platform_device *pdev)
+{
+	struct platform_mhu *mhu = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mhu->mbox);
+
+	return 0;
+}
+
+static const struct of_device_id platform_mhu_dt_ids[] = {
+	{ .compatible = "amlogic,meson-gxbb-mhu", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, platform_mhu_dt_ids);
+
+static struct platform_driver platform_mhu_driver = {
+	.probe	= platform_mhu_probe,
+	.remove	= platform_mhu_remove,
+	.driver = {
+		.name = "platform-mhu",
+		.of_match_table	= platform_mhu_dt_ids,
+	},
+};
+
+module_platform_driver(platform_mhu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:platform-mhu");
+MODULE_DESCRIPTION("Platform MHU Driver");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:53 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:53 +0200
Subject: [PATCH 00/13] scpi: Add support for legacy SCPI protocol
Message-ID: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>

This patchset aims to support the legacy SCPI firmware implementation that was
delivered as early technology preview for the JUNO platform.

Finally a stable, maintained and public implementation for the SCPI protocol
has been upstreamed part of the JUNO support and it is the recommended way
of implementing SCP communication on ARMv8 platforms.

The Amlogic GXBB platform is using this legacy protocol, as the RK3368 & RK3399
platforms.

This patchset add support for the legacy protocol in the arm_scpi.c file,
avoiding code duplication.

Last RFC discution tread can be found at : https://lkml.org/lkml/2016/8/9/210

The first patch is here to provide vendor commands on the official SCPI protocol,
it can be delayed to another patchset.

Patches 8 & 9 are only here to demo how Rockchip support could be implemented, these
patches should be delayed to a rockchip specific patchset.

The last patch depends on the "Platform MHU" dtsi patch.

Neil Armstrong (13):
  scpi: Add vendor_send_message to enable access to vendor commands
  scpi: Add alternative legacy structures and macros
  scpi: Add legacy send, prepare and handle remote functions
  scpi: Add legacy SCP functions calling legacy_scpi_send_message
  scpi: move of_match table before probe functions
  scpi: add priv_scpi_ops and fill legacy structure
  scpi: ignore init_versions failure if reported not supported
  scpi: add a vendor_msg mechanism in case the mailbox message differs
  scpi: implement rockchip support via the vendor_msg mechanism
  scpi: grow MAX_DVFS_OPPS to 16 entries
  dt-bindings: Add support for Amlogic GXBB SCPI Interface
  ARM64: dts: meson-gxbb: Add SRAM node
  ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes

 Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++
 drivers/firmware/arm_scpi.c                        | 455 ++++++++++++++++++++-
 include/linux/scpi_protocol.h                      |   4 +
 4 files changed, 490 insertions(+), 22 deletions(-)

-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:54 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:54 +0200
Subject: [PATCH 01/13] scpi: Add vendor_send_message to enable access to
 vendor commands
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-2-git-send-email-narmstrong@baylibre.com>

Adds an optional vendor_send_message to the scpi to enable sending
vendor platform specific commands to the SCP firmware.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c   | 26 +++++++++++++++++++++++---
 include/linux/scpi_protocol.h |  4 ++++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 4388937..403783a 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -46,6 +46,8 @@
 
 #define CMD_ID_SHIFT		0
 #define CMD_ID_MASK		0x7f
+#define CMD_SET_SHIFT		7
+#define CMD_SET_MASK		0x1
 #define CMD_TOKEN_ID_SHIFT	8
 #define CMD_TOKEN_ID_MASK	0xff
 #define CMD_DATA_SIZE_SHIFT	16
@@ -53,6 +55,10 @@
 #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
 	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
+#define PACK_EXT_SCPI_CMD(cmd_id, tx_sz)		\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
+	(CMD_SET_MASK << CMD_SET_SHIFT) |		\
+	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
 #define ADD_SCPI_TOKEN(cmd, token)			\
 	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
 
@@ -344,8 +350,8 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
 	mutex_unlock(&ch->xfers_lock);
 }
 
-static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
-			     void *rx_buf, unsigned int rx_len)
+static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+			       void *rx_buf, unsigned int rx_len, bool extn)
 {
 	int ret;
 	u8 chan;
@@ -360,7 +366,8 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 		return -ENOMEM;
 
 	msg->slot = BIT(SCPI_SLOT);
-	msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	msg->cmd = extn ? PACK_EXT_SCPI_CMD(cmd, tx_len) :
+			  PACK_SCPI_CMD(cmd, tx_len);
 	msg->tx_buf = tx_buf;
 	msg->tx_len = tx_len;
 	msg->rx_buf = rx_buf;
@@ -385,6 +392,18 @@ out:
 	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
 }
 
+static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+			     void *rx_buf, unsigned int rx_len)
+{
+	return __scpi_send_message(cmd, tx_buf, tx_len, rx_buf, rx_len, false);
+}
+
+static int scpi_ext_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+				 void *rx_buf, unsigned int rx_len)
+{
+	return __scpi_send_message(cmd, tx_buf, tx_len, rx_buf, rx_len, true);
+}
+
 static u32 scpi_get_version(void)
 {
 	return scpi_info->protocol_version;
@@ -578,6 +597,7 @@ static struct scpi_ops scpi_ops = {
 	.sensor_get_value = scpi_sensor_get_value,
 	.device_get_power_state = scpi_device_get_power_state,
 	.device_set_power_state = scpi_device_set_power_state,
+	.vendor_send_message = scpi_ext_send_message,
 };
 
 struct scpi_ops *get_scpi_ops(void)
diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h
index dc5f989..2b68581 100644
--- a/include/linux/scpi_protocol.h
+++ b/include/linux/scpi_protocol.h
@@ -58,6 +58,8 @@ struct scpi_sensor_info {
  *	OPP is an index to the list return by @dvfs_get_info
  * @dvfs_get_info: returns the DVFS capabilities of the given power
  *	domain. It includes the OPP list and the latency information
+ * @vendor_send_message: vendor specific message sending, arg can specify
+ *	a scpi implementation specific argument
  */
 struct scpi_ops {
 	u32 (*get_version)(void);
@@ -72,6 +74,8 @@ struct scpi_ops {
 	int (*sensor_get_value)(u16, u64 *);
 	int (*device_get_power_state)(u16);
 	int (*device_set_power_state)(u16, u8);
+	int (*vendor_send_message)(u8 cmd, void *tx_buf, unsigned int tx_len,
+				   void *rx_buf, unsigned int rx_len);
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCPI_PROTOCOL)
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:59 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:59 +0200
Subject: [PATCH 06/13] scpi: add priv_scpi_ops and fill legacy structure
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-7-git-send-email-narmstrong@baylibre.com>

In order to use the legacy functions variants, add a new priv_scpi_ops
structure that will contain the internal alterne functions and then use these
alternate call in the probe function.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 68 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 64 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index b0d911b..3fe39fe 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -213,6 +213,7 @@ struct scpi_drvinfo {
 	struct scpi_ops *scpi_ops;
 	struct scpi_chan *channels;
 	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
+	const struct priv_scpi_ops *ops;
 };
 
 /*
@@ -299,6 +300,17 @@ struct dev_pstate_set {
 	u8 pstate;
 } __packed;
 
+struct priv_scpi_ops {
+	/* Internal Specific Ops */
+	void (*handle_remote_msg)(struct mbox_client *c, void *msg);
+	void (*tx_prepare)(struct mbox_client *c, void *msg);
+	/* Message Specific Ops */
+	int (*init_versions)(struct scpi_drvinfo *info);
+	int (*dvfs_get_info)(u8 domain, struct dvfs_info *buf);
+	/* System wide Ops */
+	struct scpi_ops *scpi_ops;
+};
+
 static struct scpi_drvinfo *scpi_info;
 
 static int scpi_linux_errmap[SCPI_ERR_MAX] = {
@@ -695,9 +707,12 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
 	if (scpi_info->dvfs[domain])	/* data already populated */
 		return scpi_info->dvfs[domain];
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
+	if (scpi_info->ops && scpi_info->ops->dvfs_get_info)
+		ret = scpi_info->ops->dvfs_get_info(domain, &buf);
+	else
+		ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO,
+					&domain, sizeof(domain),
 				&buf, sizeof(buf));
-
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -855,6 +870,22 @@ static struct scpi_ops scpi_ops = {
 	.vendor_send_message = scpi_ext_send_message,
 };
 
+static struct scpi_ops legacy_scpi_ops = {
+	.get_version = scpi_get_version,
+	.clk_get_range = NULL,
+	.clk_get_val = legacy_scpi_clk_get_val,
+	.clk_set_val = legacy_scpi_clk_set_val,
+	.dvfs_get_idx = legacy_scpi_dvfs_get_idx,
+	.dvfs_set_idx = legacy_scpi_dvfs_set_idx,
+	.dvfs_get_info = scpi_dvfs_get_info,
+	.sensor_get_capability = legacy_scpi_sensor_get_capability,
+	.sensor_get_info = legacy_scpi_sensor_get_info,
+	.sensor_get_value = legacy_scpi_sensor_get_value,
+	.device_get_power_state = NULL,
+	.device_set_power_state = NULL,
+	.vendor_send_message = legacy_scpi_send_message,
+};
+
 struct scpi_ops *get_scpi_ops(void)
 {
 	return scpi_info ? scpi_info->scpi_ops : NULL;
@@ -972,8 +1003,17 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
 	return 0;
 }
 
+static const struct priv_scpi_ops scpi_legacy_ops = {
+	.handle_remote_msg = legacy_scpi_handle_remote_msg,
+	.tx_prepare = legacy_scpi_tx_prepare,
+	.init_versions = legacy_scpi_init_versions,
+	.dvfs_get_info = legacy_scpi_dvfs_get_info,
+	.scpi_ops = &legacy_scpi_ops,
+};
+
 static const struct of_device_id scpi_of_match[] = {
 	{.compatible = "arm,scpi"},
+	{.compatible = "amlogic,meson-gxbb-scpi", .data = &scpi_legacy_ops},
 	{},
 };
 
@@ -986,11 +1026,18 @@ static int scpi_probe(struct platform_device *pdev)
 	struct scpi_chan *scpi_chan;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	const struct of_device_id *match;
+
+	match = of_match_device(scpi_of_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
 
 	scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
 	if (!scpi_info)
 		return -ENOMEM;
 
+	scpi_info->ops = match->data;
+
 	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
 	if (count < 0) {
 		dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -1023,7 +1070,13 @@ static int scpi_probe(struct platform_device *pdev)
 		pchan->tx_payload = pchan->rx_payload + (size >> 1);
 
 		cl->dev = dev;
-		cl->rx_callback = scpi_handle_remote_msg;
+		if (scpi_info->ops && scpi_info->ops->handle_remote_msg)
+			cl->rx_callback = scpi_info->ops->handle_remote_msg;
+		else
+			cl->rx_callback = scpi_handle_remote_msg;
+		if (scpi_info->ops && scpi_info->ops->tx_prepare)
+			cl->tx_prepare = scpi_info->ops->tx_prepare;
+		else
 		cl->tx_prepare = scpi_tx_prepare;
 		cl->tx_block = true;
 		cl->tx_tout = 20;
@@ -1054,6 +1107,9 @@ err:
 	scpi_info->num_chans = count;
 	platform_set_drvdata(pdev, scpi_info);
 
+	if (scpi_info->ops && scpi_info->ops->init_versions)
+		ret = scpi_info->ops->init_versions(scpi_info);
+	else
 	ret = scpi_init_versions(scpi_info);
 	if (ret) {
 		dev_err(dev, "incorrect or no SCP firmware found\n");
@@ -1067,7 +1123,11 @@ err:
 		  FW_REV_MAJOR(scpi_info->firmware_version),
 		  FW_REV_MINOR(scpi_info->firmware_version),
 		  FW_REV_PATCH(scpi_info->firmware_version));
-	scpi_info->scpi_ops = &scpi_ops;
+
+	if (scpi_info->ops && scpi_info->ops->scpi_ops)
+		scpi_info->scpi_ops = scpi_info->ops->scpi_ops;
+	else
+		scpi_info->scpi_ops = &scpi_ops;
 
 	ret = sysfs_create_groups(&dev->kobj, versions_groups);
 	if (ret)
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:01 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:01 +0200
Subject: [PATCH 08/13] scpi: add a vendor_msg mechanism in case the mailbox
 message differs
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-9-git-send-email-narmstrong@baylibre.com>

In case the mailbox message pointer must contain a specific structure.
add a mechanism to override the pointer sent to the mailbox by a
vendor specific data initialized by a vendor speficic function.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index d3be4c5..275feef 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -189,6 +189,7 @@ struct scpi_xfer {
 	unsigned int rx_len;
 	struct list_head node;
 	struct completion done;
+	void *vendor_msg;
 };
 
 struct scpi_chan {
@@ -203,6 +204,7 @@ struct scpi_chan {
 	struct mutex xfers_lock;
 	u8 token;
 	struct scpi_xfer *t;
+	void *vendor_data;
 };
 
 struct scpi_drvinfo {
@@ -302,6 +304,8 @@ struct dev_pstate_set {
 
 struct priv_scpi_ops {
 	/* Internal Specific Ops */
+	int (*init)(struct device *dev, struct scpi_chan *chan);
+	int (*prepare)(struct scpi_chan *chan);
 	void (*handle_remote_msg)(struct mbox_client *c, void *msg);
 	void (*tx_prepare)(struct mbox_client *c, void *msg);
 	/* Message Specific Ops */
@@ -498,7 +502,18 @@ static int legacy_scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 	init_completion(&msg->done);
 	scpi_chan->t = msg;
 
-	ret = mbox_send_message(scpi_chan->chan, &msg->cmd);
+	/* Call the prepare hook to eventually set the vendor_msg */
+	if (scpi_info->ops &&
+	    scpi_info->ops->prepare) {
+		ret = scpi_info->ops->prepare(scpi_chan);
+		if (ret) {
+			mutex_unlock(&scpi_chan->xfers_lock);
+			return ret;
+		}
+	} else
+		msg->vendor_msg = &msg->cmd;
+
+	ret = mbox_send_message(scpi_chan->chan, msg->vendor_msg);
 	if (ret < 0)
 		goto out;
 
@@ -1069,6 +1084,12 @@ static int scpi_probe(struct platform_device *pdev)
 		}
 		pchan->tx_payload = pchan->rx_payload + (size >> 1);
 
+		if (scpi_info->ops && scpi_info->ops->init) {
+			ret = scpi_info->ops->init(dev, pchan);
+			if (ret)
+				goto err;
+		}
+
 		cl->dev = dev;
 		if (scpi_info->ops && scpi_info->ops->handle_remote_msg)
 			cl->rx_callback = scpi_info->ops->handle_remote_msg;
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:03 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:03 +0200
Subject: [PATCH 10/13] scpi: grow MAX_DVFS_OPPS to 16 entries
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-11-git-send-email-narmstrong@baylibre.com>

Since Amlogic SoCs reports more than 8 OPPs per domains, grow the structure
size to 16.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index d73db7c..699bed7 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -74,7 +74,7 @@
 #define SCPI_SLOT		0
 
 #define MAX_DVFS_DOMAINS	8
-#define MAX_DVFS_OPPS		8
+#define MAX_DVFS_OPPS		16
 #define DVFS_LATENCY(hdr)	(le32_to_cpu(hdr) >> 16)
 #define DVFS_OPP_COUNT(hdr)	((le32_to_cpu(hdr) >> 8) & 0xff)
 
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:05 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:05 +0200
Subject: [PATCH 12/13] ARM64: dts: meson-gxbb: Add SRAM node
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-13-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index bdbf6e7..2748007 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -124,6 +124,15 @@
 		#size-cells = <2>;
 		ranges;
 
+		sram: sram at c8000000 {
+			compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+			reg = <0x0 0xc8000000 0x0 0x14000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x0 0xc8000000 0x14000>;
+		};
+
 		cbus: cbus at c1100000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xc1100000 0x0 0x100000>;
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:06 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:06 +0200
Subject: [PATCH 13/13] ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors
 Nodes
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-14-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 36 +++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 2748007..257845a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -61,6 +61,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x0>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 
 		cpu1: cpu at 1 {
@@ -68,6 +69,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x1>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 
 		cpu2: cpu at 2 {
@@ -75,6 +77,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x2>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 
 		cpu3: cpu at 3 {
@@ -82,6 +85,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x3>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 	};
 
@@ -99,6 +103,28 @@
 		method = "smc";
 	};
 
+	scpi {
+		compatible = "amlogic,meson-gxbb-scpi";
+		mboxes = <&mailbox 1 &mailbox 2>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+
+		clocks {
+			compatible = "arm,scpi-clocks";
+
+			scpi_dvfs: scpi_clocks at 0 {
+				compatible = "arm,scpi-dvfs-clocks";
+				#clock-cells = <1>;
+				clock-indices = <0>;
+				clock-output-names = "vcpu";
+			};
+		};
+
+		scpi_sensors: sensors {
+			compatible = "arm,scpi-sensors";
+			#thermal-sensor-cells = <1>;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
@@ -131,6 +157,16 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x0 0xc8000000 0x14000>;
+
+			cpu_scp_lpri: scp-shmem at 0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13000 0x400>;
+			};
+
+			cpu_scp_hpri: scp-shmem at 200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13400 0x400>;
+			};
 		};
 
 		cbus: cbus at c1100000 {
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:02 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:02 +0200
Subject: [PATCH 09/13] scpi: implement rockchip support via the vendor_msg
 mechanism
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-10-git-send-email-narmstrong@baylibre.com>

In order to support the Rockchip legacy procotol, implement the vendor
mailbox specific functions and add ops to the of_match table.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 275feef..d73db7c 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -455,6 +455,37 @@ static int legacy_scpi_get_chan(u8 cmd)
 	return 0;
 }
 
+/* Rockchip SoCs needs a special structure as a message */
+
+struct rockchip_scpi_xfer {
+	u32 cmd;
+	int rx_size;
+};
+
+static int rockchip_init(struct device *dev, struct scpi_chan *chan)
+{
+	chan->vendor_data = devm_kmalloc(dev,
+					 sizeof(struct rockchip_scpi_xfer),
+					 GFP_KERNEL);
+	if (!chan->vendor_data)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int rockchip_prepare(struct scpi_chan *chan)
+{
+	struct scpi_xfer *msg = chan->t;
+	struct rockchip_scpi_xfer *xfer = chan->vendor_data;
+
+	xfer->cmd = msg->cmd;
+	xfer->rx_size = msg->rx_len;
+
+	msg->vendor_msg = xfer;
+
+	return 0;
+}
+
 static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
 {
 	struct scpi_xfer *t;
@@ -1026,9 +1057,21 @@ static const struct priv_scpi_ops scpi_legacy_ops = {
 	.scpi_ops = &legacy_scpi_ops,
 };
 
+static const struct priv_scpi_ops scpi_rockchip_ops = {
+	.init = rockchip_init,
+	.prepare = rockchip_prepare,
+	.handle_remote_msg = legacy_scpi_handle_remote_msg,
+	.tx_prepare = legacy_scpi_tx_prepare,
+	.init_versions = legacy_scpi_init_versions,
+	.dvfs_get_info = legacy_scpi_dvfs_get_info,
+	.scpi_ops = &legacy_scpi_ops,
+};
+
 static const struct of_device_id scpi_of_match[] = {
 	{.compatible = "arm,scpi"},
 	{.compatible = "amlogic,meson-gxbb-scpi", .data = &scpi_legacy_ops},
+	{.compatible = "rockchip,rk3368-scpi", .data = &scpi_rockchip_ops},
+	{.compatible = "rockchip,rk3399-scpi", .data = &scpi_rockchip_ops},
 	{},
 };
 
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:56 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:56 +0200
Subject: [PATCH 03/13] scpi: Add legacy send,
 prepare and handle remote functions
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-4-git-send-email-narmstrong@baylibre.com>

In order to support the legacy SCPI procotol, add specific message_send,
prepare_tx and handle_remote functions since the legacy procotol
do not support message queuing and does not store the command word in the
tx_payload data.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 0bb6134..50b1297 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -202,6 +202,7 @@ struct scpi_chan {
 	spinlock_t rx_lock; /* locking for the rx pending list */
 	struct mutex xfers_lock;
 	u8 token;
+	struct scpi_xfer *t;
 };
 
 struct scpi_drvinfo {
@@ -364,6 +365,23 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
 	scpi_process_cmd(ch, cmd);
 }
 
+static void legacy_scpi_handle_remote_msg(struct mbox_client *c, void *__msg)
+{
+	struct scpi_chan *ch =
+		container_of(c, struct scpi_chan, cl);
+	struct legacy_scpi_shared_mem *mem = ch->rx_payload;
+	unsigned int len;
+
+	len = ch->t->rx_len;
+
+	ch->t->status = le32_to_cpu(mem->status);
+
+	if (len)
+		memcpy_fromio(ch->t->rx_buf, mem->payload, len);
+
+	complete(&ch->t->done);
+}
+
 static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 {
 	unsigned long flags;
@@ -384,6 +402,15 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 	mem->command = cpu_to_le32(t->cmd);
 }
 
+static void legacy_scpi_tx_prepare(struct mbox_client *c, void *__msg)
+{
+	struct scpi_chan *ch =
+		container_of(c, struct scpi_chan, cl);
+
+	if (ch->t->tx_buf && ch->t->tx_len)
+		memcpy_toio(ch->tx_payload, ch->t->tx_buf, ch->t->tx_len);
+}
+
 static int legacy_high_priority_cmds[] = {
 	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
 	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
@@ -434,6 +461,48 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
 	mutex_unlock(&ch->xfers_lock);
 }
 
+static int legacy_scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+				void *rx_buf, unsigned int rx_len)
+{
+	int ret;
+	u8 chan;
+	struct scpi_xfer *msg;
+	struct scpi_chan *scpi_chan;
+
+	chan = legacy_scpi_get_chan(cmd);
+	scpi_chan = scpi_info->channels + chan;
+
+	msg = get_scpi_xfer(scpi_chan);
+	if (!msg)
+		return -ENOMEM;
+
+	mutex_lock(&scpi_chan->xfers_lock);
+
+	msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
+	msg->tx_buf = tx_buf;
+	msg->tx_len = tx_len;
+	msg->rx_buf = rx_buf;
+	msg->rx_len = rx_len;
+	init_completion(&msg->done);
+	scpi_chan->t = msg;
+
+	ret = mbox_send_message(scpi_chan->chan, &msg->cmd);
+	if (ret < 0)
+		goto out;
+
+	if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
+		ret = -ETIMEDOUT;
+	else
+		/* first status word */
+		ret = msg->status;
+out:
+	mutex_unlock(&scpi_chan->xfers_lock);
+
+	put_scpi_xfer(msg, scpi_chan);
+	/* SCPI error codes > 0, translate them to Linux scale*/
+	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
+}
+
 static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 			       void *rx_buf, unsigned int rx_len, bool extn)
 {
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:00 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:00 +0200
Subject: [PATCH 07/13] scpi: ignore init_versions failure if reported not
 supported
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>

In Amlogic GXBB Legacy SCPI, the LEGACY_SCPI_CMD_SCPI_CAPABILITIES report
as SCPI_ERR_SUPPORT, so do not fail if this command is not supported.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 3fe39fe..d3be4c5 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -1111,12 +1111,13 @@ err:
 		ret = scpi_info->ops->init_versions(scpi_info);
 	else
 	ret = scpi_init_versions(scpi_info);
-	if (ret) {
+	if (ret && ret != -EOPNOTSUPP) {
 		dev_err(dev, "incorrect or no SCP firmware found\n");
 		scpi_remove(pdev);
 		return ret;
 	}
 
+	if (ret != -EOPNOTSUPP) {
 	_dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
 		  PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
 		  PROTOCOL_REV_MINOR(scpi_info->protocol_version),
@@ -1124,15 +1125,16 @@ err:
 		  FW_REV_MINOR(scpi_info->firmware_version),
 		  FW_REV_PATCH(scpi_info->firmware_version));
 
+		ret = sysfs_create_groups(&dev->kobj, versions_groups);
+		if (ret)
+			dev_err(dev, "unable to create sysfs version group\n");
+	}
+
 	if (scpi_info->ops && scpi_info->ops->scpi_ops)
 		scpi_info->scpi_ops = scpi_info->ops->scpi_ops;
 	else
 		scpi_info->scpi_ops = &scpi_ops;
 
-	ret = sysfs_create_groups(&dev->kobj, versions_groups);
-	if (ret)
-		dev_err(dev, "unable to create sysfs version group\n");
-
 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
 }
 
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:26 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:26 +0200
Subject: [PATCH v2 2/3] dt-bindings: mailbox: Add Amlogic Meson MHU Bindings
In-Reply-To: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>
References: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515027-3543-3-git-send-email-narmstrong@baylibre.com>

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../devicetree/bindings/mailbox/meson-mhu.txt      | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/meson-mhu.txt

diff --git a/Documentation/devicetree/bindings/mailbox/meson-mhu.txt b/Documentation/devicetree/bindings/mailbox/meson-mhu.txt
new file mode 100644
index 0000000..a530310
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/meson-mhu.txt
@@ -0,0 +1,34 @@
+Amlogic Meson MHU Mailbox Driver
+================================
+
+The Amlogic's Meson SoCs Message-Handling-Unit (MHU) is a mailbox controller
+that has 3 independent channels/links to communicate with remote processor(s).
+MHU links are hardwired on a platform. A link raises interrupt for any
+received data. However, there is no specified way of knowing if the sent
+data has been read by the remote. This driver assumes the sender polls
+STAT register and the remote clears it after having read the data.
+
+Mailbox Device Node:
+====================
+
+Required properties:
+--------------------
+- compatible:		Shall be "amlogic,meson-gxbb-mhu"
+- reg:			Contains the mailbox register address range (base
+			address and length)
+- #mbox-cells		Shall be 1 - the index of the channel needed.
+- interrupts:		Contains the interrupt information corresponding to
+			each of the 2 links of MHU.
+
+Example:
+--------
+
+	mailbox: mailbox at c883c404 {
+		#mbox-cells = <1>;
+		compatible = "amlogic,meson-gxbb-mhu";
+		reg = <0 0xc883c404 0 0x4c>;
+		interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
+			     <0 209 IRQ_TYPE_EDGE_RISING>,
+			     <0 210 IRQ_TYPE_EDGE_RISING>;
+		#mbox-cells = <1>;
+	};
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:11:04 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:11:04 +0200
Subject: [PATCH 11/13] dt-bindings: Add support for Amlogic GXBB SCPI Interface
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-12-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
index faa4b44..04bc171 100644
--- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -7,7 +7,7 @@ by Linux to initiate various system control and power operations.
 
 Required properties:
 
-- compatible : should be "arm,scpi"
+- compatible : should be "arm,scpi" or "amlogic,meson-gxbb-scpi"
 - mboxes: List of phandle and mailbox channel specifiers
 	  All the channels reserved by remote SCP firmware for use by
 	  SCPI message protocol should be specified in any order
@@ -60,7 +60,8 @@ A small area of SRAM is reserved for SCPI communication between application
 processors and SCP.
 
 Required properties:
-- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
+- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno,
+		or "amlogic,meson-gxbb-sram" for Amlogic GXBB SoC.
 
 The rest of the properties should follow the generic mmio-sram description
 found in ../../sram/sram.txt
@@ -70,7 +71,8 @@ Each sub-node represents the reserved area for SCPI.
 Required sub-node properties:
 - reg : The base offset and size of the reserved area with the SRAM
 - compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
-	       shared memory on Juno platforms
+	       shared memory on Juno platforms or
+	       "amlogic,meson-gxbb-scp-shmem" for Amlogic GXBB SoC.
 
 Sensor bindings for the sensors based on SCPI Message Protocol
 --------------------------------------------------------------
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:58 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:58 +0200
Subject: [PATCH 05/13] scpi: move of_match table before probe functions
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-6-git-send-email-narmstrong@baylibre.com>

Move the of_match table to prapre adding new compatible strings, with
match data in order to be used by the probe function.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index bb9965f..b0d911b 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -972,6 +972,13 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
 	return 0;
 }
 
+static const struct of_device_id scpi_of_match[] = {
+	{.compatible = "arm,scpi"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, scpi_of_match);
+
 static int scpi_probe(struct platform_device *pdev)
 {
 	int count, idx, ret;
@@ -1069,13 +1076,6 @@ err:
 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
 }
 
-static const struct of_device_id scpi_of_match[] = {
-	{.compatible = "arm,scpi"},
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, scpi_of_match);
-
 static struct platform_driver scpi_driver = {
 	.driver = {
 		.name = "scpi_protocol",
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:57 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:57 +0200
Subject: [PATCH 04/13] scpi: Add legacy SCP functions calling
 legacy_scpi_send_message
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-5-git-send-email-narmstrong@baylibre.com>

In order to support legacy SCP functions from kernel-wide driver, add legacy
functions using the legacy command enums and calling legacy_scpi_send_message.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 118 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 50b1297..bb9965f 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -578,6 +578,8 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
 	return ret;
 }
 
+/* scpi_clk_get_range not available for legacy */
+
 static unsigned long scpi_clk_get_val(u16 clk_id)
 {
 	int ret;
@@ -589,6 +591,18 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
 	return ret ? ret : le32_to_cpu(clk.rate);
 }
 
+static unsigned long legacy_scpi_clk_get_val(u16 clk_id)
+{
+	int ret;
+	struct clk_get_value clk;
+	__le16 le_clk_id = cpu_to_le16(clk_id);
+
+	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+				       &le_clk_id, sizeof(le_clk_id),
+				       &clk, sizeof(clk));
+	return ret ? ret : le32_to_cpu(clk.rate);
+}
+
 static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
 {
 	int stat;
@@ -601,6 +615,19 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
 				 &stat, sizeof(stat));
 }
 
+static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+	int stat;
+	struct legacy_clk_set_value clk = {
+		.id = cpu_to_le16(clk_id),
+		.rate = cpu_to_le32(rate)
+	};
+
+	return legacy_scpi_send_message(LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+					&clk, sizeof(clk),
+					&stat, sizeof(stat));
+}
+
 static int scpi_dvfs_get_idx(u8 domain)
 {
 	int ret;
@@ -611,6 +638,17 @@ static int scpi_dvfs_get_idx(u8 domain)
 	return ret ? ret : dvfs_idx;
 }
 
+static int legacy_scpi_dvfs_get_idx(u8 domain)
+{
+	int ret;
+	u8 dvfs_idx;
+
+	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_GET_DVFS,
+				       &domain, sizeof(domain),
+				       &dvfs_idx, sizeof(dvfs_idx));
+	return ret ? ret : dvfs_idx;
+}
+
 static int scpi_dvfs_set_idx(u8 domain, u8 index)
 {
 	int stat;
@@ -620,6 +658,16 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
 				 &stat, sizeof(stat));
 }
 
+static int legacy_scpi_dvfs_set_idx(u8 domain, u8 index)
+{
+	int stat;
+	struct dvfs_set dvfs = {domain, index};
+
+	return legacy_scpi_send_message(LEGACY_SCPI_CMD_SET_DVFS,
+					&dvfs, sizeof(dvfs),
+					&stat, sizeof(stat));
+}
+
 static int opp_cmp_func(const void *opp1, const void *opp2)
 {
 	const struct scpi_opp *t1 = opp1, *t2 = opp2;
@@ -627,6 +675,13 @@ static int opp_cmp_func(const void *opp1, const void *opp2)
 	return t1->freq - t2->freq;
 }
 
+static int legacy_scpi_dvfs_get_info(u8 domain, struct dvfs_info *buf)
+{
+	return legacy_scpi_send_message(LEGACY_SCPI_CMD_GET_DVFS_INFO,
+					&domain, sizeof(domain),
+					buf, sizeof(*buf));
+}
+
 static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
 {
 	struct scpi_dvfs_info *info;
@@ -683,6 +738,20 @@ static int scpi_sensor_get_capability(u16 *sensors)
 	return ret;
 }
 
+static int legacy_scpi_sensor_get_capability(u16 *sensors)
+{
+	struct sensor_capabilities cap_buf;
+	int ret;
+
+	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
+				       NULL, 0,
+				       &cap_buf, sizeof(cap_buf));
+	if (!ret)
+		*sensors = le16_to_cpu(cap_buf.sensors);
+
+	return ret;
+}
+
 static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
 {
 	__le16 id = cpu_to_le16(sensor_id);
@@ -699,6 +768,24 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
 	return ret;
 }
 
+static int legacy_scpi_sensor_get_info(u16 sensor_id,
+				       struct scpi_sensor_info *info)
+{
+	__le16 id = cpu_to_le16(sensor_id);
+	struct _scpi_sensor_info _info;
+	int ret;
+
+	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_SENSOR_INFO,
+				       &id, sizeof(id),
+				       &_info, sizeof(_info));
+	if (!ret) {
+		memcpy(info, &_info, sizeof(*info));
+		info->sensor_id = le16_to_cpu(_info.sensor_id);
+	}
+
+	return ret;
+}
+
 static int scpi_sensor_get_value(u16 sensor, u64 *val)
 {
 	__le16 id = cpu_to_le16(sensor);
@@ -714,6 +801,21 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
 	return ret;
 }
 
+static int legacy_scpi_sensor_get_value(u16 sensor, u64 *val)
+{
+	__le16 id = cpu_to_le16(sensor);
+	struct legacy_sensor_value buf;
+	int ret;
+
+	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_SENSOR_VALUE,
+				       &id, sizeof(id),
+				       &buf, sizeof(buf));
+	if (!ret)
+		*val = (u64)le32_to_cpu(buf.val);
+
+	return ret;
+}
+
 static int scpi_device_get_power_state(u16 dev_id)
 {
 	int ret;
@@ -773,6 +875,22 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
 	return ret;
 }
 
+static int legacy_scpi_init_versions(struct scpi_drvinfo *info)
+{
+	int ret;
+	struct scp_capabilities caps;
+
+	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
+				       NULL, 0,
+				       &caps, sizeof(caps));
+	if (!ret) {
+		info->protocol_version = le32_to_cpu(caps.protocol_version);
+		info->firmware_version = le32_to_cpu(caps.platform_version);
+	}
+
+	return ret;
+}
+
 static ssize_t protocol_version_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:55 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:55 +0200
Subject: [PATCH 02/13] scpi: Add alternative legacy structures and macros
In-Reply-To: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515066-3626-3-git-send-email-narmstrong@baylibre.com>

In order to support the legacy SCPI protocol variant, add back the structures
and macros that varies against the final specification.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
I checked against Amlogic implementation documentation and on-device, the channel selection
via legacy_scpi_get_chan() is needed and fails without it.
The sender_id is not needed so it was dropped.

 drivers/firmware/arm_scpi.c | 84 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 403783a..0bb6134 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -52,6 +52,8 @@
 #define CMD_TOKEN_ID_MASK	0xff
 #define CMD_DATA_SIZE_SHIFT	16
 #define CMD_DATA_SIZE_MASK	0x1ff
+#define CMD_LEGACY_DATA_SIZE_SHIFT	20
+#define CMD_LEGACY_DATA_SIZE_MASK	0x1ff
 #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
 	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
@@ -61,6 +63,9 @@
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
 #define ADD_SCPI_TOKEN(cmd, token)			\
 	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
+#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz)				\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |			       \
+	(((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
 
 #define CMD_SIZE(cmd)	(((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
 #define CMD_UNIQ_MASK	(CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
@@ -138,6 +143,42 @@ enum scpi_std_cmd {
 	SCPI_CMD_COUNT
 };
 
+enum legacy_scpi_std_cmd {
+	LEGACY_SCPI_CMD_INVALID			= 0x00,
+	LEGACY_SCPI_CMD_SCPI_READY		= 0x01,
+	LEGACY_SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
+	LEGACY_SCPI_CMD_EVENT			= 0x03,
+	LEGACY_SCPI_CMD_SET_CSS_PWR_STATE	= 0x04,
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE	= 0x05,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT	= 0x06,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT	= 0x07,
+	LEGACY_SCPI_CMD_SYS_PWR_STATE		= 0x08,
+	LEGACY_SCPI_CMD_L2_READY		= 0x09,
+	LEGACY_SCPI_CMD_SET_AP_TIMER		= 0x0a,
+	LEGACY_SCPI_CMD_CANCEL_AP_TIME		= 0x0b,
+	LEGACY_SCPI_CMD_DVFS_CAPABILITIES	= 0x0c,
+	LEGACY_SCPI_CMD_GET_DVFS_INFO		= 0x0d,
+	LEGACY_SCPI_CMD_SET_DVFS		= 0x0e,
+	LEGACY_SCPI_CMD_GET_DVFS		= 0x0f,
+	LEGACY_SCPI_CMD_GET_DVFS_STAT		= 0x10,
+	LEGACY_SCPI_CMD_SET_RTC			= 0x11,
+	LEGACY_SCPI_CMD_GET_RTC			= 0x12,
+	LEGACY_SCPI_CMD_CLOCK_CAPABILITIES	= 0x13,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX		= 0x14,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE		= 0x15,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE		= 0x16,
+	LEGACY_SCPI_CMD_PSU_CAPABILITIES	= 0x17,
+	LEGACY_SCPI_CMD_SET_PSU			= 0x18,
+	LEGACY_SCPI_CMD_GET_PSU			= 0x19,
+	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES	= 0x1a,
+	LEGACY_SCPI_CMD_SENSOR_INFO		= 0x1b,
+	LEGACY_SCPI_CMD_SENSOR_VALUE		= 0x1c,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x1d,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x1e,
+	LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1f,
+	LEGACY_SCPI_CMD_COUNT
+};
+
 struct scpi_xfer {
 	u32 slot; /* has to be first element */
 	u32 cmd;
@@ -183,6 +224,11 @@ struct scpi_shared_mem {
 	u8 payload[0];
 } __packed;
 
+struct legacy_scpi_shared_mem {
+	__le32 status;
+	u8 payload[0];
+} __packed;
+
 struct scp_capabilities {
 	__le32 protocol_version;
 	__le32 event_version;
@@ -208,6 +254,12 @@ struct clk_set_value {
 	__le32 rate;
 } __packed;
 
+struct legacy_clk_set_value {
+	__le32 rate;
+	__le16 id;
+	__le16 reserved;
+} __packed;
+
 struct dvfs_info {
 	__le32 header;
 	struct {
@@ -237,6 +289,10 @@ struct sensor_value {
 	__le32 hi_val;
 } __packed;
 
+struct legacy_sensor_value {
+	__le32 val;
+} __packed;
+
 struct dev_pstate_set {
 	u16 dev_id;
 	u8 pstate;
@@ -328,6 +384,34 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 	mem->command = cpu_to_le32(t->cmd);
 }
 
+static int legacy_high_priority_cmds[] = {
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_SET_DVFS,
+	LEGACY_SCPI_CMD_GET_DVFS,
+	LEGACY_SCPI_CMD_SET_RTC,
+	LEGACY_SCPI_CMD_GET_RTC,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_SET_PSU,
+	LEGACY_SCPI_CMD_GET_PSU,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
+};
+
+static int legacy_scpi_get_chan(u8 cmd)
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(legacy_high_priority_cmds); idx++)
+		if (cmd == legacy_high_priority_cmds[idx])
+			return 1;
+
+	return 0;
+}
+
 static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
 {
 	struct scpi_xfer *t;
-- 
1.9.1



From narmstrong at baylibre.com  Thu Aug 18 03:10:27 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 18 Aug 2016 12:10:27 +0200
Subject: [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add Meson MHU Node
In-Reply-To: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>
References: <1471515027-3543-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471515027-3543-4-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..bdbf6e7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -321,6 +321,15 @@
 				#clock-cells = <1>;
 				reg = <0x0 0x0 0x0 0x3db>;
 			};
+
+			mailbox: mailbox at 404 {
+				compatible = "amlogic,meson-gxbb-mhu";
+				reg = <0 0x404 0 0x4c>;
+				interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
+					     <0 209 IRQ_TYPE_EDGE_RISING>,
+					     <0 210 IRQ_TYPE_EDGE_RISING>;
+				#mbox-cells = <1>;
+			};
 		};
 
 		apb: apb at d0000000 {
-- 
1.9.1



From sudeep.holla at arm.com  Thu Aug 18 08:53:20 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 18 Aug 2016 16:53:20 +0100
Subject: [PATCH 01/13] scpi: Add vendor_send_message to enable access to
 vendor commands
In-Reply-To: <1471515066-3626-2-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <c5b2d698-de4c-012a-7e7b-63685b7e898c@arm.com>



On 18/08/16 11:10, Neil Armstrong wrote:
> Adds an optional vendor_send_message to the scpi to enable sending
> vendor platform specific commands to the SCP firmware.
>

I don't see any users of vendor_send_message in this series, so I prefer
it to be dropped and introduced when required.

Also I had a different view on how to introduce this[1]. I would rather
wait until the requirement comes that enables us to make use of it.
Looks like you took parts of it and introduces vendor_send_message
allowing users to send any data which I don't like especially without
knowing how will it be (ab)used.

-- 
Regards,
Sudeep

[1] http://www.spinics.net/lists/kernel/msg2263649.html


From sudeep.holla at arm.com  Thu Aug 18 10:16:34 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 18 Aug 2016 18:16:34 +0100
Subject: [PATCH 02/13] scpi: Add alternative legacy structures and macros
In-Reply-To: <1471515066-3626-3-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <2b345fec-4dbd-2144-cd34-d8451bb314c0@arm.com>



On 18/08/16 11:10, Neil Armstrong wrote:
> In order to support the legacy SCPI protocol variant, add back the structures
> and macros that varies against the final specification.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
> I checked against Amlogic implementation documentation and on-device, the channel selection
> via legacy_scpi_get_chan() is needed and fails without it.
> The sender_id is not needed so it was dropped.
>
>  drivers/firmware/arm_scpi.c | 84 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 84 insertions(+)
>
> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
> index 403783a..0bb6134 100644
> --- a/drivers/firmware/arm_scpi.c
> +++ b/drivers/firmware/arm_scpi.c

[...]

> @@ -183,6 +224,11 @@ struct scpi_shared_mem {
>  	u8 payload[0];
>  } __packed;
>
> +struct legacy_scpi_shared_mem {
> +	__le32 status;
> +	u8 payload[0];
> +} __packed;
> +
>  struct scp_capabilities {
>  	__le32 protocol_version;
>  	__le32 event_version;
> @@ -208,6 +254,12 @@ struct clk_set_value {
>  	__le32 rate;
>  } __packed;
>
> +struct legacy_clk_set_value {
> +	__le32 rate;
> +	__le16 id;
> +	__le16 reserved;
> +} __packed;
> +
>  struct dvfs_info {
>  	__le32 header;
>  	struct {
> @@ -237,6 +289,10 @@ struct sensor_value {
>  	__le32 hi_val;
>  } __packed;
>
> +struct legacy_sensor_value {
> +	__le32 val;
> +} __packed;
> +

Not required, new one is backward compatible. Otherwise this patch looks
fine.

-- 
Regards,
Sudeep


From narmstrong at baylibre.com  Fri Aug 19 01:00:44 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 19 Aug 2016 10:00:44 +0200
Subject: [PATCH 01/13] scpi: Add vendor_send_message to enable access to
 vendor commands
In-Reply-To: <c5b2d698-de4c-012a-7e7b-63685b7e898c@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-2-git-send-email-narmstrong@baylibre.com>
 <c5b2d698-de4c-012a-7e7b-63685b7e898c@arm.com>
Message-ID: <9bf4a979-5325-fd70-1887-04c605d593d8@baylibre.com>

On 08/18/2016 05:53 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:10, Neil Armstrong wrote:
>> Adds an optional vendor_send_message to the scpi to enable sending
>> vendor platform specific commands to the SCP firmware.
>>
> 
> I don't see any users of vendor_send_message in this series, so I prefer
> it to be dropped and introduced when required.
> 
> Also I had a different view on how to introduce this[1]. I would rather
> wait until the requirement comes that enables us to make use of it.
> Looks like you took parts of it and introduces vendor_send_message
> allowing users to send any data which I don't like especially without
> knowing how will it be (ab)used.
> 

Hi Sudeep,

Indeed, I won't ask you to merge patches 1, 8 and 9, they need refactoring and
a separate patchset.

Vendor commands are not necessary for Amlogic, this is a nice to have since they
have a "user" command that can be extended by a firmware loaded by u-boot.

Could you review the following patches and I'll post a reduced v2 ASAP.

Thanks,
Neil


From yamada.masahiro at socionext.com  Fri Aug 19 02:19:54 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Fri, 19 Aug 2016 18:19:54 +0900
Subject: [U-Boot] [PATCH 1/4] pinctrl: generic: scan for "pins" and
 "groups" properties in sub-nodes
In-Reply-To: <1471340990-16247-2-git-send-email-b.galvani@gmail.com>
References: <1471340990-16247-1-git-send-email-b.galvani@gmail.com>
 <1471340990-16247-2-git-send-email-b.galvani@gmail.com>
Message-ID: <CAK7LNASNDMQUzp+Mri-o4VXjYFg4DLsXFz+m+JdnVCpcsa78AQ@mail.gmail.com>

2016-08-16 18:49 GMT+09:00 Beniamino Galvani <b.galvani at gmail.com>:
> In cases where the pins and groups definitions are in a sub-node, as:
>
>         uart_a {
>                 mux {
>                         groups = "uart_tx_a", "uart_rx_a";
>                         function = "uart_a";
>                 };
>         };
>
> pinctrl_generic_set_state_subnode() returns an error for the top-level
> node and pinctrl_generic_set_state() fails. Instead, return success so
> that the child nodes are tried.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>
> ---


Looks good to me.  Thanks!

Reviewed-by: Masahiro Yamada <yamada.masahiro at socionext.com>


-- 
Best Regards
Masahiro Yamada


From sudeep.holla at arm.com  Fri Aug 19 03:39:15 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 11:39:15 +0100
Subject: [PATCH 01/13] scpi: Add vendor_send_message to enable access to
 vendor commands
In-Reply-To: <9bf4a979-5325-fd70-1887-04c605d593d8@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-2-git-send-email-narmstrong@baylibre.com>
 <c5b2d698-de4c-012a-7e7b-63685b7e898c@arm.com>
 <9bf4a979-5325-fd70-1887-04c605d593d8@baylibre.com>
Message-ID: <26c18a0c-ee62-3159-e10b-6b0e5c28fb56@arm.com>



On 19/08/16 09:00, Neil Armstrong wrote:
> On 08/18/2016 05:53 PM, Sudeep Holla wrote:
>>
>>
>> On 18/08/16 11:10, Neil Armstrong wrote:
>>> Adds an optional vendor_send_message to the scpi to enable sending
>>> vendor platform specific commands to the SCP firmware.
>>>
>>
>> I don't see any users of vendor_send_message in this series, so I prefer
>> it to be dropped and introduced when required.
>>
>> Also I had a different view on how to introduce this[1]. I would rather
>> wait until the requirement comes that enables us to make use of it.
>> Looks like you took parts of it and introduces vendor_send_message
>> allowing users to send any data which I don't like especially without
>> knowing how will it be (ab)used.
>>
>
> Hi Sudeep,
>
> Indeed, I won't ask you to merge patches 1, 8 and 9, they need refactoring and
> a separate patchset.
>

Ah OK,then better if you put then at the end. Otherwise it makes it
difficult to review.

> Vendor commands are not necessary for Amlogic, this is a nice to have
> since they have a "user" command that can be extended by a firmware
> loaded by u-boot.
>

Good :)

> Could you review the following patches and I'll post a reduced v2
> ASAP.
>

Yes I was doing that yesterday, sorry got distracted. I will continue today.

-- 
Regards,
Sudeep


From robh at kernel.org  Fri Aug 19 06:45:47 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 19 Aug 2016 08:45:47 -0500
Subject: [PATCH 11/13] dt-bindings: Add support for Amlogic GXBB SCPI
 Interface
In-Reply-To: <1471515066-3626-12-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-12-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160819134547.GA1806@rob-hp-laptop>

On Thu, Aug 18, 2016 at 12:11:04PM +0200, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)

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


From sudeep.holla at arm.com  Fri Aug 19 09:13:42 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 17:13:42 +0100
Subject: [PATCH 03/13] scpi: Add legacy send, prepare and handle remote
 functions
In-Reply-To: <1471515066-3626-4-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-4-git-send-email-narmstrong@baylibre.com>
Message-ID: <b88c0ffc-09d2-4138-3007-b1e28c955cce@arm.com>



On 18/08/16 11:10, Neil Armstrong wrote:
> In order to support the legacy SCPI procotol, add specific message_send,
> prepare_tx and handle_remote functions since the legacy procotol
> do not support message queuing and does not store the command word in the
> tx_payload data.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/firmware/arm_scpi.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
>
> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
> index 0bb6134..50b1297 100644
> --- a/drivers/firmware/arm_scpi.c
> +++ b/drivers/firmware/arm_scpi.c
> @@ -202,6 +202,7 @@ struct scpi_chan {
>  	spinlock_t rx_lock; /* locking for the rx pending list */
>  	struct mutex xfers_lock;
>  	u8 token;
> +	struct scpi_xfer *t;
>  };
>
>  struct scpi_drvinfo {
> @@ -364,6 +365,23 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
>  	scpi_process_cmd(ch, cmd);
>  }
>
> +static void legacy_scpi_handle_remote_msg(struct mbox_client *c, void *__msg)
> +{
> +	struct scpi_chan *ch =
> +		container_of(c, struct scpi_chan, cl);
> +	struct legacy_scpi_shared_mem *mem = ch->rx_payload;
> +	unsigned int len;
> +
> +	len = ch->t->rx_len;
> +
> +	ch->t->status = le32_to_cpu(mem->status);
> +
> +	if (len)
> +		memcpy_fromio(ch->t->rx_buf, mem->payload, len);
> +
> +	complete(&ch->t->done);
> +}
> +
>  static void scpi_tx_prepare(struct mbox_client *c, void *msg)
>  {
>  	unsigned long flags;
> @@ -384,6 +402,15 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
>  	mem->command = cpu_to_le32(t->cmd);
>  }
>
> +static void legacy_scpi_tx_prepare(struct mbox_client *c, void *__msg)
> +{
> +	struct scpi_chan *ch =
> +		container_of(c, struct scpi_chan, cl);
> +
> +	if (ch->t->tx_buf && ch->t->tx_len)
> +		memcpy_toio(ch->tx_payload, ch->t->tx_buf, ch->t->tx_len);


I see that you are not using the list. Any particular reason for that ?

IMO, that *might* help to reuse more code, but I may be wrong. Let's see
Some commands like DVFS take more time compared to simple query type of
commands. Queuing does help there instead of blocking the channel until
the receipt of response.

> +}
> +
>  static int legacy_high_priority_cmds[] = {
>  	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
>  	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
> @@ -434,6 +461,48 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
>  	mutex_unlock(&ch->xfers_lock);
>  }
>
> +static int legacy_scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
> +				void *rx_buf, unsigned int rx_len)
> +{
> +	int ret;
> +	u8 chan;
> +	struct scpi_xfer *msg;
> +	struct scpi_chan *scpi_chan;
> +
> +	chan = legacy_scpi_get_chan(cmd);
> +	scpi_chan = scpi_info->channels + chan;
> +
> +	msg = get_scpi_xfer(scpi_chan);
> +	if (!msg)
> +		return -ENOMEM;
> +
> +	mutex_lock(&scpi_chan->xfers_lock);
> +

May be you can copy msg->cmd to msg->slot and that may help to reuse
more code or worst-case keep them aligned.

> +	msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
> +	msg->tx_buf = tx_buf;
> +	msg->tx_len = tx_len;
> +	msg->rx_buf = rx_buf;
> +	msg->rx_len = rx_len;
> +	init_completion(&msg->done);
> +	scpi_chan->t = msg;
> +
> +	ret = mbox_send_message(scpi_chan->chan, &msg->cmd);

If slot is initialized to cmd, then you can pass msg itself above.
Then you can evaluate how much this function deviates from
scpi_send_message and try to re-use.

> +	if (ret < 0)
> +		goto out;
> +
> +	if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
> +		ret = -ETIMEDOUT;
> +	else
> +		/* first status word */
> +		ret = msg->status;
> +out:
> +	mutex_unlock(&scpi_chan->xfers_lock);
> +
> +	put_scpi_xfer(msg, scpi_chan);
> +	/* SCPI error codes > 0, translate them to Linux scale*/
> +	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
> +}
> +
>  static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
>  			       void *rx_buf, unsigned int rx_len, bool extn)
>  {
>

[Nit]: Not sure if we need this as a separate patch. It might just
generate warnings, anyways we can merge into one later.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Fri Aug 19 09:22:19 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 17:22:19 +0100
Subject: [PATCH 04/13] scpi: Add legacy SCP functions calling
 legacy_scpi_send_message
In-Reply-To: <1471515066-3626-5-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-5-git-send-email-narmstrong@baylibre.com>
Message-ID: <fe6919a2-a1dc-f056-9480-3248dc9315dc@arm.com>



On 18/08/16 11:10, Neil Armstrong wrote:
> In order to support legacy SCP functions from kernel-wide driver, add legacy
> functions using the legacy command enums and calling legacy_scpi_send_message.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/firmware/arm_scpi.c | 118 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 118 insertions(+)
>
> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
> index 50b1297..bb9965f 100644
> --- a/drivers/firmware/arm_scpi.c
> +++ b/drivers/firmware/arm_scpi.c
> @@ -578,6 +578,8 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
>  	return ret;
>  }
>
> +/* scpi_clk_get_range not available for legacy */
> +
>  static unsigned long scpi_clk_get_val(u16 clk_id)
>  {
>  	int ret;
> @@ -589,6 +591,18 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
>  	return ret ? ret : le32_to_cpu(clk.rate);
>  }
>
> +static unsigned long legacy_scpi_clk_get_val(u16 clk_id)
> +{
> +	int ret;
> +	struct clk_get_value clk;
> +	__le16 le_clk_id = cpu_to_le16(clk_id);
> +
> +	ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
> +				       &le_clk_id, sizeof(le_clk_id),
> +				       &clk, sizeof(clk));
> +	return ret ? ret : le32_to_cpu(clk.rate);
> +}
> +
>  static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>  {
>  	int stat;
> @@ -601,6 +615,19 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>  				 &stat, sizeof(stat));
>  }
>
> +static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
> +{
> +	int stat;
> +	struct legacy_clk_set_value clk = {
> +		.id = cpu_to_le16(clk_id),
> +		.rate = cpu_to_le32(rate)
> +	};
> +
> +	return legacy_scpi_send_message(LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
> +					&clk, sizeof(clk),
> +					&stat, sizeof(stat));

Except this one which has a different structure format, why do we need
to define legacy versions of other functions ? Can't we play with
function pointer or have a boolean in drvinfo structure and use then in
the existing functions as I had shown in one of the earlier emails.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Fri Aug 19 09:24:15 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 17:24:15 +0100
Subject: [PATCH 05/13] scpi: move of_match table before probe functions
In-Reply-To: <1471515066-3626-6-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-6-git-send-email-narmstrong@baylibre.com>
Message-ID: <def54975-8014-a326-6f82-8953740e520c@arm.com>



On 18/08/16 11:10, Neil Armstrong wrote:
> Move the of_match table to prapre adding new compatible strings, with
> match data in order to be used by the probe function.
>

I understand the need of this change, but can be part of the patch
introducing the need for this.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Fri Aug 19 09:39:55 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 17:39:55 +0100
Subject: [PATCH 06/13] scpi: add priv_scpi_ops and fill legacy structure
In-Reply-To: <1471515066-3626-7-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-7-git-send-email-narmstrong@baylibre.com>
Message-ID: <5c89a4e9-0100-0c67-1d6c-07651649172a@arm.com>



On 18/08/16 11:10, Neil Armstrong wrote:
> In order to use the legacy functions variants, add a new priv_scpi_ops
> structure that will contain the internal alterne functions and then use these
> alternate call in the probe function.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/firmware/arm_scpi.c | 68 ++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 64 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
> index b0d911b..3fe39fe 100644
> --- a/drivers/firmware/arm_scpi.c
> +++ b/drivers/firmware/arm_scpi.c
> @@ -213,6 +213,7 @@ struct scpi_drvinfo {
>  	struct scpi_ops *scpi_ops;
>  	struct scpi_chan *channels;
>  	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
> +	const struct priv_scpi_ops *ops;
>  };
>
>  /*
> @@ -299,6 +300,17 @@ struct dev_pstate_set {
>  	u8 pstate;
>  } __packed;
>
> +struct priv_scpi_ops {
> +	/* Internal Specific Ops */
> +	void (*handle_remote_msg)(struct mbox_client *c, void *msg);
> +	void (*tx_prepare)(struct mbox_client *c, void *msg);
> +	/* Message Specific Ops */
> +	int (*init_versions)(struct scpi_drvinfo *info);
> +	int (*dvfs_get_info)(u8 domain, struct dvfs_info *buf);
> +	/* System wide Ops */
> +	struct scpi_ops *scpi_ops;
> +};
> +


I fail to understand the need for this. Can you please explain the issue
you would face without this ?

>  static struct scpi_drvinfo *scpi_info;
>
>  static int scpi_linux_errmap[SCPI_ERR_MAX] = {
> @@ -695,9 +707,12 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
>  	if (scpi_info->dvfs[domain])	/* data already populated */
>  		return scpi_info->dvfs[domain];
>
> -	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
> +	if (scpi_info->ops && scpi_info->ops->dvfs_get_info)
> +		ret = scpi_info->ops->dvfs_get_info(domain, &buf);
> +	else
> +		ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO,
> +					&domain, sizeof(domain),
>  				&buf, sizeof(buf));
> -
>  	if (ret)
>  		return ERR_PTR(ret);
>
> @@ -855,6 +870,22 @@ static struct scpi_ops scpi_ops = {
>  	.vendor_send_message = scpi_ext_send_message,
>  };
>
> +static struct scpi_ops legacy_scpi_ops = {
> +	.get_version = scpi_get_version,
> +	.clk_get_range = NULL,
> +	.clk_get_val = legacy_scpi_clk_get_val,
> +	.clk_set_val = legacy_scpi_clk_set_val,
> +	.dvfs_get_idx = legacy_scpi_dvfs_get_idx,
> +	.dvfs_set_idx = legacy_scpi_dvfs_set_idx,
> +	.dvfs_get_info = scpi_dvfs_get_info,
> +	.sensor_get_capability = legacy_scpi_sensor_get_capability,
> +	.sensor_get_info = legacy_scpi_sensor_get_info,
> +	.sensor_get_value = legacy_scpi_sensor_get_value,
> +	.device_get_power_state = NULL,
> +	.device_set_power_state = NULL,
> +	.vendor_send_message = legacy_scpi_send_message,

I think we need not have this at all if you follow the suggestion I had
in the previous patch. Try and let's see how it would look.

> +};
> +
>  struct scpi_ops *get_scpi_ops(void)
>  {
>  	return scpi_info ? scpi_info->scpi_ops : NULL;
> @@ -972,8 +1003,17 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
>  	return 0;
>  }
>
> +static const struct priv_scpi_ops scpi_legacy_ops = {
> +	.handle_remote_msg = legacy_scpi_handle_remote_msg,
> +	.tx_prepare = legacy_scpi_tx_prepare,
> +	.init_versions = legacy_scpi_init_versions,
> +	.dvfs_get_info = legacy_scpi_dvfs_get_info,
> +	.scpi_ops = &legacy_scpi_ops,
> +};
> +

Ditto, can go away.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Fri Aug 19 09:46:11 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 17:46:11 +0100
Subject: [PATCH 07/13] scpi: ignore init_versions failure if reported not
 supported
In-Reply-To: <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>
Message-ID: <74d35f80-8499-cadf-798c-9b296218305c@arm.com>



On 18/08/16 11:11, Neil Armstrong wrote:
> In Amlogic GXBB Legacy SCPI, the LEGACY_SCPI_CMD_SCPI_CAPABILITIES report
> as SCPI_ERR_SUPPORT, so do not fail if this command is not supported.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/firmware/arm_scpi.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
> index 3fe39fe..d3be4c5 100644
> --- a/drivers/firmware/arm_scpi.c
> +++ b/drivers/firmware/arm_scpi.c
> @@ -1111,12 +1111,13 @@ err:
>  		ret = scpi_info->ops->init_versions(scpi_info);
>  	else
>  	ret = scpi_init_versions(scpi_info);
> -	if (ret) {
> +	if (ret && ret != -EOPNOTSUPP) {
>  		dev_err(dev, "incorrect or no SCP firmware found\n");
>  		scpi_remove(pdev);
>  		return ret;
>  	}
>

Why not deal it in init_versions itself.

> +	if (ret != -EOPNOTSUPP) {
>  	_dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
>  		  PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
>  		  PROTOCOL_REV_MINOR(scpi_info->protocol_version),

Why not have default value like 0.0 ? Just add a comment. Since get
version is exported out, IMO having default value makes more sense. What
do you think ?

> @@ -1124,15 +1125,16 @@ err:
>  		  FW_REV_MINOR(scpi_info->firmware_version),
>  		  FW_REV_PATCH(scpi_info->firmware_version));
>
> +		ret = sysfs_create_groups(&dev->kobj, versions_groups);
> +		if (ret)
> +			dev_err(dev, "unable to create sysfs version group\n");
> +	}
> +

Again this can stay as is if we have default.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Fri Aug 19 09:47:48 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Fri, 19 Aug 2016 17:47:48 +0100
Subject: [PATCH 08/13] scpi: add a vendor_msg mechanism in case the
 mailbox message differs
In-Reply-To: <1471515066-3626-9-git-send-email-narmstrong@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-9-git-send-email-narmstrong@baylibre.com>
Message-ID: <bd59fdb1-5f6d-ffba-0c6a-b5eb28397521@arm.com>



On 18/08/16 11:11, Neil Armstrong wrote:
> In case the mailbox message pointer must contain a specific structure.
> add a mechanism to override the pointer sent to the mailbox by a
> vendor specific data initialized by a vendor speficic function.
>

As discussed, I won't look at this and next patch. You can drop from now.

-- 
Regards,
Sudeep


From sboyd at codeaurora.org  Fri Aug 19 12:51:48 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 19 Aug 2016 12:51:48 -0700
Subject: [PATCH v2 1/3] clk: meson: Add GXBB AO Clock and Reset
 controller driver
In-Reply-To: <1471514928-3341-2-git-send-email-narmstrong@baylibre.com>
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
 <1471514928-3341-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160819195148.GF6502@codeaurora.org>

On 08/18, Neil Armstrong wrote:
> Adds a Clock and Reset controller driver for the Always-On part
> of the Amlogic Meson GXBB SoC.
> 
> It exports paired Clocks and Resets lines that will be used by
> peripherals in the Always-On subsystem.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---

Applied to clk-meson-gxbb-ao and merged into clk-next. I applied
this after the dt binding headers to keep things compiling.

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


From sboyd at codeaurora.org  Fri Aug 19 12:51:55 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 19 Aug 2016 12:51:55 -0700
Subject: [PATCH v2 2/3] dt-bindings: clock: reset: Add GXBB AO Clock and
 Reset Bindings
In-Reply-To: <1471514928-3341-3-git-send-email-narmstrong@baylibre.com>
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
 <1471514928-3341-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160819195155.GG6502@codeaurora.org>

On 08/18, Neil Armstrong wrote:
> Add documentations and dt-bindings headers for the AO clock and reset
> controller.
> 
> Acked-by: Rob Herring <robh at kernel.org>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---

Applied to clk-meson-gxbb-ao and merged into clk-next.

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


From khilman at baylibre.com  Fri Aug 19 14:40:00 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri, 19 Aug 2016 14:40:00 -0700
Subject: [PATCH 2/3] net: stmmac: add a glue driver for the Amlogic Meson
 8b / GXBB DWMAC
In-Reply-To: <20160815164100.27766-3-martin.blumenstingl@googlemail.com>
 (Martin Blumenstingl's message of "Mon, 15 Aug 2016 18:40:59 +0200")
References: <20160625165013.15917-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160815164100.27766-3-martin.blumenstingl@googlemail.com>
Message-ID: <7hshu0780f.fsf@baylibre.com>

Martin Blumenstingl <martin.blumenstingl at googlemail.com> writes:

> The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
> DesignWare MAC IP core which is already supported by the stmmac driver.
>
> In addition to the standard stmmac driver some Meson8b / GXBB specific
> registers have to be configured for the PHY clocks. These SoC specific
> registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
> datasheet.
> These registers are not backwards compatible with those on Meson 6b,
> which is why a new glue driver is introduced. This worked for many
> boards because the bootloader programs the PRG_ETHERNET registers
> correctly. Additionally the meson6-dwmac driver only sets bit 1 of
> PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
> during reset.
>
> Currently all configuration values can be determined automatically,
> based on the configured phy-mode (which is mandatory for the stmmac
> driver). If required the tx-delay and the mux clock (so it supports
> the MPLL2 clock as well) can be made configurable in the future.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

[...]

> +static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
> +{
> +	struct clk_init_data init;
> +	int i, ret;
> +	struct device *dev = &dwmac->pdev->dev;
> +	char clk_name[32];
> +	const char *clk_div_parents[1];
> +	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
> +	unsigned int mux_parent_count = 0;
> +	static struct clk_div_table clk_25m_div_table[] = {
> +		{ .val = 0, .div = 5 },
> +		{ .val = 1, .div = 10 },
> +		{ /* sentinel */ },
> +	};
> +
> +	/* get the mux parents from DT */
> +	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
> +		char name[16];
> +
> +		snprintf(name, sizeof(name), "clkin%d", i);
> +		dwmac->m250_mux_parent[i] = devm_clk_get(dev, name);
> +		if (IS_ERR(dwmac->m250_mux_parent[i])) {
> +			/* NOTE: the second clock (MP2) is unused on all known

nit: multi-line comment style  (c.f. Documentation/CodingStyle search
for "multi-line")

> +			 * boards, thus we're making it optional here.
> +			 */
> +			if (i > 0)
> +				continue;

IMO, this is a bit confusing.  I think this should either be coded to
deal with an optional "clkin1" (preferred), or it should be coded to
without a mux and clkin0 is directly the parent of the divider.  The
current way of always bailing out of this loop early is a bit confusing.

> +			ret = PTR_ERR(dwmac->m250_mux_parent[i]);
> +			if (ret != -EPROBE_DEFER)
> +				dev_err(dev, "Missing clock %s\n", name);
> +			dwmac->m250_mux_parent[i] = NULL;
> +			return ret;
> +		}
> +
> +		mux_parent_names[i] =
> +			__clk_get_name(dwmac->m250_mux_parent[i]);
> +		mux_parent_count++;
> +	}
> +
> +	/* create the m250_mux */
> +	snprintf(clk_name, sizeof(clk_name), "%s#m250_sel", dev_name(dev));
> +	init.name = clk_name;
> +	init.ops = &clk_mux_ops;
> +	init.flags = CLK_IS_BASIC;
> +	init.parent_names = mux_parent_names;
> +	init.num_parents = mux_parent_count;
> +
> +	dwmac->m250_mux.reg = dwmac->regs + PRG_ETH0;
> +	dwmac->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
> +	dwmac->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
> +	dwmac->m250_mux.flags = 0;
> +	dwmac->m250_mux.table = NULL;
> +	dwmac->m250_mux.hw.init = &init;
> +
> +	dwmac->m250_mux_clk = devm_clk_register(dev, &dwmac->m250_mux.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))
> +		return PTR_ERR(dwmac->m250_mux_clk);
> +
> +	/* create the m250_div */
> +	snprintf(clk_name, sizeof(clk_name), "%s#m250_div", dev_name(dev));
> +	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;

hmm, with CLK_SET_RATE_PARENT that implies that it might switch the mux,
but it's hard-coded above so the mux only ever has one parent, so that
can never happen.

> +	clk_div_parents[0] = __clk_get_name(dwmac->m250_mux_clk);
> +	init.parent_names = clk_div_parents;
> +	init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +	dwmac->m250_div.reg = dwmac->regs + PRG_ETH0;
> +	dwmac->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
> +	dwmac->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
> +	dwmac->m250_div.hw.init = &init;
> +	dwmac->m250_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
> +
> +	dwmac->m250_div_clk = devm_clk_register(dev, &dwmac->m250_div.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))
> +		return PTR_ERR(dwmac->m250_div_clk);
> +
> +	/* create the m25_div */
> +	snprintf(clk_name, sizeof(clk_name), "%s#m25_div", dev_name(dev));
> +	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
> +	clk_div_parents[0] = __clk_get_name(dwmac->m250_div_clk);
> +	init.parent_names = clk_div_parents;
> +	init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +	dwmac->m25_div.reg = dwmac->regs + PRG_ETH0;
> +	dwmac->m25_div.shift = PRG_ETH0_CLK_M25_DIV_SHIFT;
> +	dwmac->m25_div.width = PRG_ETH0_CLK_M25_DIV_WIDTH;
> +	dwmac->m25_div.table = clk_25m_div_table;
> +	dwmac->m25_div.hw.init = &init;
> +	dwmac->m25_div.flags = CLK_DIVIDER_ALLOW_ZERO;
> +
> +	dwmac->m25_div_clk = devm_clk_register(dev, &dwmac->m25_div.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))
> +		return PTR_ERR(dwmac->m25_div_clk);
> +
> +	return 0;
> +}
> +
> +static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
> +{
> +	int ret;
> +	unsigned long clk_rate;
> +
> +	switch (dwmac->phy_mode) {
> +	case PHY_INTERFACE_MODE_RGMII:
> +	case PHY_INTERFACE_MODE_RGMII_ID:
> +	case PHY_INTERFACE_MODE_RGMII_RXID:
> +	case PHY_INTERFACE_MODE_RGMII_TXID:
> +		/* Generate a 25MHz clock for the PHY */
> +		clk_rate = 25 * 1000 * 1000;
> +
> +		/* enable RGMII mode */
> +		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
> +					PRG_ETH0_RGMII_MODE);
> +
> +		/* only relevant for RMII mode -> disable in RGMII mode */
> +		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
> +					PRG_ETH0_INVERTED_RMII_CLK, 0);
> +
> +		/* TX clock delay - all known boards use a 1/4 cycle delay */
> +		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
> +					PRG_ETH0_TXDLY_QUARTER);
> +		break;
> +
> +	case PHY_INTERFACE_MODE_RMII:
> +		/* Use the rate of the mux clock for the internal RMII PHY */
> +		clk_rate = clk_get_rate(dwmac->m250_mux_clk);
> +
> +		/* disable RGMII mode -> enables RMII mode */
> +		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
> +					0);
> +
> +		/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
> +		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
> +					PRG_ETH0_INVERTED_RMII_CLK,
> +					PRG_ETH0_INVERTED_RMII_CLK);
> +
> +		/* TX clock delay cannot be configured in RMII mode */
> +		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
> +					0);
> +
> +		break;
> +
> +	default:
> +		dev_err(&dwmac->pdev->dev, "unsupported phy-mode %s\n",
> +			phy_modes(dwmac->phy_mode));
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_prepare_enable(dwmac->m25_div_clk);
> +	if (ret) {
> +		dev_err(&dwmac->pdev->dev, "failed to enable the PHY clock\n");
> +		return ret;
> +	}
> +
> +	ret = clk_set_rate(dwmac->m25_div_clk, clk_rate);
> +	if (ret) {
> +		clk_disable_unprepare(dwmac->m25_div_clk);
> +
> +		dev_err(&dwmac->pdev->dev, "failed to set PHY clock\n");
> +		return ret;
> +	}

In the case of success, the clock is never disabled/unprepared.   You
probably need a .remove function which disables the clock and then calls
stmmac_pltfr_remove.

> +	/* enable TX_CLK and PHY_REF_CLK generator */
> +	meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
> +				PRG_ETH0_TX_AND_PHY_REF_CLK);
> +
> +	return 0;
> +}

[...]

Otherwise, this is looking good.

Also, I tested on meson-gxbb-odroidc2 and meson-gxbb-p200 by booting a debian
root filesystem over NFS and all was well.

Tested-by: Kevin Hilman <khilman at baylibre.com>

Kevin



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:41 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:41 +0200
Subject: [PATCH v4 0/6] Add Meson 8b / GXBB support to the IR driver
In-Reply-To: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>

Newer Amlogic platforms (Meson 8b and GXBB) use a slightly different
register layout for their Infrared Remoete Controller. The decoder mode
is now configured in another register. Without the changes to the
meson-ir driver we are simply getting incorrect "durations" reported
from the hardware (because the hardware is not in time measurement aka
software decode mode).

This problem was also noticed by some people trying to use this on an
ODROID-C1 and ODROID-C2 - the workaround there (probably because the
datasheets were not publicy available yet at that time) was to switch
to ir_raw_event_store_edge (which leaves it up to the kernel to measure
the duration of a pulse). See [0] and [1] for the corresponding
patches.

Changes in v4:
- added support for pinctrl configuration which makes it possible to
  use the IR decoder when doing a cold-boot. Without these pinctrl
  changes the IR decoder was only working when booting into stock
  Android, then rebooting and booting the mainline kernel (with the
  other patches from this series). Thanks to Kevin Hilman for spotting
  this issue.
- rebased dts changes to Kevin's v4.8/integ branch

As discussed on IRC (thanks Neil):

Tested-by: Neil Armstrong <narmstrong at baylibre.com>


[0] https://github.com/erdoukki/linux-amlogic-1/commit/969b2e2242fb14a13cb651f9a1cf771b599c958b
[1] http://forum.odroid.com/viewtopic.php?f=135&t=20504


Martin Blumenstingl (3):
  pinctrl: amlogic: gxbb: add the IR remote pin
  ARM64: dts: amlogic: add the pin for the IR remote
  ARM64: dts: meson-gxbb: Enable the the IR decoder on supported boards

Neil Armstrong (3):
  dt-bindings: media: meson-ir: Add Meson8b and GXBB compatible strings
  media: rc: meson-ir: Add support for newer versions of the IR decoder
  ARM64: dts: meson-gxbb: Add Infrared Remote Controller decoder

 .../devicetree/bindings/media/meson-ir.txt         |  5 +++-
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  6 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  6 +++++
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |  6 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 14 +++++++++++
 drivers/media/rc/meson-ir.c                        | 29 ++++++++++++++++++----
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c         |  8 ++++++
 7 files changed, 68 insertions(+), 6 deletions(-)

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:44 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:44 +0200
Subject: [PATCH v4 3/6] dt-bindings: media: meson-ir: Add Meson8b and GXBB
 compatible strings
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-4-martin.blumenstingl@googlemail.com>

From: Neil Armstrong <narmstrong at baylibre.com>

New bindings are needed as the register layout on the newer platforms
is slightly different compared to Meson6b.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 Documentation/devicetree/bindings/media/meson-ir.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/media/meson-ir.txt b/Documentation/devicetree/bindings/media/meson-ir.txt
index 407848e..e7e3f3c 100644
--- a/Documentation/devicetree/bindings/media/meson-ir.txt
+++ b/Documentation/devicetree/bindings/media/meson-ir.txt
@@ -1,7 +1,10 @@
 * Amlogic Meson IR remote control receiver
 
 Required properties:
- - compatible	: should be "amlogic,meson6-ir"
+ - compatible	: depending on the platform this should be one of:
+		  - "amlogic,meson6-ir"
+		  - "amlogic,meson8b-ir"
+		  - "amlogic,meson-gxbb-ir"
  - reg		: physical base address and length of the device registers
  - interrupts	: a single specifier for the interrupt from the device
 
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:42 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:42 +0200
Subject: [PATCH v4 1/6] pinctrl: amlogic: gxbb: add the IR remote pin
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-2-martin.blumenstingl@googlemail.com>

This adds the IR remote receiver to the AO domain devices.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index cb4d6ad..8fffb31 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -225,6 +225,8 @@ static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
 static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
+static const unsigned int ir_in_ao_pins[] = {PIN(GPIOAO_7, 0) };
+
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
 	GPIO_GROUP(GPIOZ_1, EE_OFF),
@@ -432,6 +434,7 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GROUP(i2c_sda_ao,	0,	5),
 	GROUP(i2c_slave_sck_ao, 0,	2),
 	GROUP(i2c_slave_sda_ao, 0,	1),
+	GROUP(ir_in_ao,		0,	0),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -521,6 +524,10 @@ static const char * const i2c_slave_ao_groups[] = {
 	"i2c_slave_sdk_ao", "i2c_slave_sda_ao",
 };
 
+static const char * const ir_in_ao_groups[] = {
+	"ir_in_ao",
+};
+
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
@@ -537,6 +544,7 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(uart_ao_b),
 	FUNCTION(i2c_ao),
 	FUNCTION(i2c_slave_ao),
+	FUNCTION(ir_in_ao),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:43 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:43 +0200
Subject: [PATCH v4 2/6] ARM64: dts: amlogic: add the pin for the IR remote
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-3-martin.blumenstingl@googlemail.com>

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 4f42316..72df302 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -210,6 +210,13 @@
 						function = "uart_ao";
 					};
 				};
+
+				ir_in_ao_pins: ir_in_ao {
+					mux {
+						groups = "ir_in_ao";
+						function = "ir_in_ao";
+					};
+				};
 			};
 
 			uart_AO: serial at 4c0 {
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:46 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:46 +0200
Subject: [PATCH v4 5/6] ARM64: dts: meson-gxbb: Add Infrared Remote Controller
 decoder
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-6-martin.blumenstingl@googlemail.com>

From: Neil Armstrong <narmstrong at baylibre.com>

This adds the Infrared Remote Controller node so boards with an IR
remote can simply enable it.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 72df302..7070719 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -226,6 +226,13 @@
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			ir: ir at 580 {
+				compatible = "amlogic,meson-gxbb-ir";
+				reg = <0x0 0x00580 0x0 0x40>;
+				interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
 		};
 
 		periphs: periphs at c8834000 {
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:45 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:45 +0200
Subject: [PATCH v4 4/6] media: rc: meson-ir: Add support for newer versions of
 the IR decoder
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-5-martin.blumenstingl@googlemail.com>

From: Neil Armstrong <narmstrong at baylibre.com>

Newer SoCs (Meson 8b and GXBB) are using REG2 (offset 0x20) instead of
REG1 to configure the decoder mode. This makes it necessary to
introduce new bindings so the driver knows which register has to be
used.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/media/rc/meson-ir.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index fcc3b82..003fff0 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -24,6 +24,7 @@
 
 #define DRIVER_NAME		"meson-ir"
 
+/* valid on all Meson platforms */
 #define IR_DEC_LDR_ACTIVE	0x00
 #define IR_DEC_LDR_IDLE		0x04
 #define IR_DEC_LDR_REPEAT	0x08
@@ -32,12 +33,21 @@
 #define IR_DEC_FRAME		0x14
 #define IR_DEC_STATUS		0x18
 #define IR_DEC_REG1		0x1c
+/* only available on Meson 8b and newer */
+#define IR_DEC_REG2		0x20
 
 #define REG0_RATE_MASK		(BIT(11) - 1)
 
-#define REG1_MODE_MASK		(BIT(7) | BIT(8))
-#define REG1_MODE_NEC		(0 << 7)
-#define REG1_MODE_GENERAL	(2 << 7)
+#define DECODE_MODE_NEC		0x0
+#define DECODE_MODE_RAW		0x2
+
+/* Meson 6b uses REG1 to configure the mode */
+#define REG1_MODE_MASK		GENMASK(8, 7)
+#define REG1_MODE_SHIFT		7
+
+/* Meson 8b / GXBB use REG2 to configure the mode */
+#define REG2_MODE_MASK		GENMASK(3, 0)
+#define REG2_MODE_SHIFT		0
 
 #define REG1_TIME_IV_SHIFT	16
 #define REG1_TIME_IV_MASK	((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
@@ -158,8 +168,15 @@ static int meson_ir_probe(struct platform_device *pdev)
 	/* Reset the decoder */
 	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, REG1_RESET);
 	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, 0);
-	/* Set general operation mode */
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, REG1_MODE_GENERAL);
+
+	/* Set general operation mode (= raw/software decoding) */
+	if (of_device_is_compatible(node, "amlogic,meson6-ir"))
+		meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK,
+				  DECODE_MODE_RAW << REG1_MODE_SHIFT);
+	else
+		meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK,
+				  DECODE_MODE_RAW << REG2_MODE_SHIFT);
+
 	/* Set rate */
 	meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
 	/* IRQ on rising and falling edges */
@@ -197,6 +214,8 @@ static int meson_ir_remove(struct platform_device *pdev)
 
 static const struct of_device_id meson_ir_match[] = {
 	{ .compatible = "amlogic,meson6-ir" },
+	{ .compatible = "amlogic,meson8b-ir" },
+	{ .compatible = "amlogic,meson-gxbb-ir" },
 	{ },
 };
 
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Fri Aug 19 14:55:47 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 19 Aug 2016 23:55:47 +0200
Subject: [PATCH v4 6/6] ARM64: dts: meson-gxbb: Enable the the IR decoder on
 supported boards
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160819215547.20063-7-martin.blumenstingl@googlemail.com>

Enable the Infrared Remote Controller on boards which have an Infrared
receiver.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts  | 6 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi     | 6 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 6 ++++++
 3 files changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index cba3ea1..9900b87 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -161,3 +161,9 @@
 	vmmc-supply = <&vcc3v3>;
 	vmmcq-sumpply = <&vcc1v8>;
 };
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&ir_in_ao_pins>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index e118754..dc007fe 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -143,3 +143,9 @@
 	vmmc-supply = <&vcc_3v3>;
 	vmmcq-sumpply = <&vddio_boot>;
 };
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&ir_in_ao_pins>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 54bb7c7..45cd3ae 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -60,3 +60,9 @@
 	pinctrl-names = "default";
 
 };
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&ir_in_ao_pins>;
+	pinctrl-names = "default";
+};
-- 
2.9.3



From khilman at baylibre.com  Fri Aug 19 15:03:06 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri, 19 Aug 2016 15:03:06 -0700
Subject: [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add GXBB AO Clock and
 Reset node
In-Reply-To: <1471514928-3341-4-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Thu, 18 Aug 2016 12:08:48 +0200")
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
 <1471514928-3341-4-git-send-email-narmstrong@baylibre.com>
Message-ID: <7hk2fc76xx.fsf@baylibre.com>

Neil Armstrong <narmstrong at baylibre.com> writes:

> Add the AO clock controller node for the AmLogic GXBB SoC.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---

Applying this to the amlogic tree, but will need to wait a cycle due to
include dependencies on the bindings, which are going through the clock
tree.

Kevin


From khilman at baylibre.com  Fri Aug 19 15:23:19 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri, 19 Aug 2016 15:23:19 -0700
Subject: [PATCH v4 1/6] pinctrl: amlogic: gxbb: add the IR remote pin
In-Reply-To: <20160819215547.20063-2-martin.blumenstingl@googlemail.com>
 (Martin Blumenstingl's message of "Fri, 19 Aug 2016 23:55:42 +0200")
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-2-martin.blumenstingl@googlemail.com>
Message-ID: <7h4m6g7608.fsf@baylibre.com>

Martin Blumenstingl <martin.blumenstingl at googlemail.com> writes:

> This adds the IR remote receiver to the AO domain devices.

nit Re: Subject: should specify IR remote *input* pin.

> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> ---
>  drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
> index cb4d6ad..8fffb31 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
> +++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
> @@ -225,6 +225,8 @@ static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
>  static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
>  static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
>  
> +static const unsigned int ir_in_ao_pins[] = {PIN(GPIOAO_7, 0) };
> +

I'm trying to keep the names here so they match the datasheet, which
calls this remote_input_ao.  Please update throughout the patch.

Otherwise looks good to me.  Feel free to add

Reviewed-by: Kevin Hilman <khilman at baylibre.com>

and Linus W can queue it up.

Thanks,

Kevin


From khilman at baylibre.com  Fri Aug 19 15:28:22 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri, 19 Aug 2016 15:28:22 -0700
Subject: [PATCH v4 4/6] media: rc: meson-ir: Add support for newer
 versions of the IR decoder
In-Reply-To: <20160819215547.20063-5-martin.blumenstingl@googlemail.com>
 (Martin Blumenstingl's message of "Fri, 19 Aug 2016 23:55:45 +0200")
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-5-martin.blumenstingl@googlemail.com>
Message-ID: <7hy43s5r7d.fsf@baylibre.com>

Martin Blumenstingl <martin.blumenstingl at googlemail.com> writes:

> From: Neil Armstrong <narmstrong at baylibre.com>
>
> Newer SoCs (Meson 8b and GXBB) are using REG2 (offset 0x20) instead of
> REG1 to configure the decoder mode. This makes it necessary to
> introduce new bindings so the driver knows which register has to be
> used.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

Acked-by: Kevin Hilman <khilman at baylibre.com>

Mauro, are you the one to pick up new media/rc drivers?  Or if you
prefer, with your ack, I'll take this along with the DT and submit via
arm-soc.

Thanks,

Kevin


From martin.blumenstingl at googlemail.com  Sat Aug 20 02:35:34 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:35:34 +0200
Subject: [PATCH v2 0/4] meson: Meson8b and GXBB DWMAC glue driver
In-Reply-To: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>

This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.

Changes since v1:
- make clkin1 mandatory because the internal mux expects two clocks
  (in other words: this makes the driver consistent with how the
  hardware actually works)
- expose the MPLL2 clock for use by DT so we can pass it to the ethmac
- added a .remove function to the glue driver which disables and
  unprepares the clocks on driver removal


Martin Blumenstingl (4):
  net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
  clk: gxbb: expose MPLL2 clock for use by DT
  net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
  ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver

 .../devicetree/bindings/net/meson-dwmac.txt        |  45 ++-
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   8 +-
 drivers/clk/meson/gxbb.h                           |   2 +-
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 329 +++++++++++++++++++++
 include/dt-bindings/clock/gxbb-clkc.h              |   1 +
 6 files changed, 374 insertions(+), 13 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:35:35 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:35:35 +0200
Subject: [PATCH v2 1/4] net: dt-bindings: Document the new Meson8b and GXBB
 DWMAC bindings
In-Reply-To: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820093538.9707-2-martin.blumenstingl@googlemail.com>

This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/net/meson-dwmac.txt        | 45 ++++++++++++++++++----
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/meson-dwmac.txt b/Documentation/devicetree/bindings/net/meson-dwmac.txt
index ec633d7..89e62dd 100644
--- a/Documentation/devicetree/bindings/net/meson-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/meson-dwmac.txt
@@ -1,18 +1,32 @@
 * Amlogic Meson DWMAC Ethernet controller
 
 The device inherits all the properties of the dwmac/stmmac devices
-described in the file net/stmmac.txt with the following changes.
+described in the file stmmac.txt in the current directory with the
+following changes.
 
-Required properties:
+Required properties on all platforms:
 
-- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"
-	      and any applicable more detailed version number
-	      described in net/stmmac.txt
+- compatible:	Depending on the platform this should be one of:
+			- "amlogic,meson6-dwmac"
+			- "amlogic,meson8b-dwmac"
+			- "amlogic,meson-gxbb-dwmac"
+		Additionally "snps,dwmac" and any applicable more
+		detailed version number described in net/stmmac.txt
+		should be used.
 
-- reg: should contain a register range for the dwmac controller and
-       another one for the Amlogic specific configuration
+- reg:	The first register range should be the one of the DWMAC
+	controller. The second range is is for the Amlogic specific
+	configuration (for example the PRG_ETHERNET register range
+	on Meson8b and newer)
 
-Example:
+Required properties on Meson8b and newer:
+- clock-names:	Should contain the following:
+		- "stmmaceth" - see stmmac.txt
+		- "clkin0" - first parent clock of the internal mux
+		- "clkin1" - second parent clock of the internal mux
+
+
+Example for Meson6:
 
 	ethmac: ethernet at c9410000 {
 		compatible = "amlogic,meson6-dwmac", "snps,dwmac";
@@ -23,3 +37,18 @@ Example:
 		clocks = <&clk81>;
 		clock-names = "stmmaceth";
 	}
+
+Example for GXBB:
+	ethmac: ethernet at c9410000 {
+		compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+		reg = <0x0 0xc9410000 0x0 0x10000>,
+			<0x0 0xc8834540 0x0 0x8>;
+		interrupts = <0 8 1>;
+		interrupt-names = "macirq";
+		clocks = <&clkc CLKID_ETH>,
+				<&clkc CLKID_FCLK_DIV2>,
+				<&clkc CLKID_MPLL2>;
+		clock-names = "stmmaceth", "clkin0", "clkin1";
+		phy-mode = "rgmii";
+		status = "disabled";
+	};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:35:38 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:35:38 +0200
Subject: [PATCH v2 4/4] ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue
 driver
In-Reply-To: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820093538.9707-5-martin.blumenstingl@googlemail.com>

The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.

No changes are required to the board dts files because the only
required configuration option is the phy-mode, which had to be
configured correctly before as well.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 4f42316..ab817d3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -373,13 +373,15 @@
 		};
 
 		ethmac: ethernet at c9410000 {
-			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+			compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
 			reg = <0x0 0xc9410000 0x0 0x10000
 			       0x0 0xc8834540 0x0 0x4>;
 			interrupts = <0 8 1>;
 			interrupt-names = "macirq";
-			clocks = <&clkc CLKID_ETH>;
-			clock-names = "stmmaceth";
+			clocks = <&clkc CLKID_ETH>,
+				 <&clkc CLKID_FCLK_DIV2>,
+				 <&clkc CLKID_MPLL2>;
+			clock-names = "stmmaceth", "clkin0", "clkin1";
 			phy-mode = "rgmii";
 			status = "disabled";
 		};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:35:36 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:35:36 +0200
Subject: [PATCH v2 2/4] clk: gxbb: expose MPLL2 clock for use by DT
In-Reply-To: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820093538.9707-3-martin.blumenstingl@googlemail.com>

This exposes the MPLL2 clock as this is one of the input clocks of the
ethernet controller's internal mux.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/clk/meson/gxbb.h              | 2 +-
 include/dt-bindings/clock/gxbb-clkc.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 217df51..3606e875 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -183,7 +183,7 @@
 /* CLKID_CLK81 */
 #define CLKID_MPLL0		  13
 #define CLKID_MPLL1		  14
-#define CLKID_MPLL2		  15
+/* CLKID_MPLL2 */
 #define CLKID_DDR		  16
 #define CLKID_DOS		  17
 #define CLKID_ISA		  18
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index 7d41864..244ea6e 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -8,6 +8,7 @@
 #define CLKID_CPUCLK		1
 #define CLKID_FCLK_DIV2		4
 #define CLKID_CLK81		12
+#define CLKID_MPLL2		15
 #define CLKID_ETH		36
 #define CLKID_SD_EMMC_A		94
 #define CLKID_SD_EMMC_B		95
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:35:37 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:35:37 +0200
Subject: [PATCH v2 3/4] net: stmmac: add a glue driver for the Amlogic Meson
 8b / GXBB DWMAC
In-Reply-To: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820093538.9707-4-martin.blumenstingl@googlemail.com>

The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.

In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.

Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Tested-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 329 +++++++++++++++++++++
 2 files changed, 330 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 44b630c..f77edb9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -9,7 +9,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 obj-$(CONFIG_STMMAC_PLATFORM)	+= stmmac-platform.o
 obj-$(CONFIG_DWMAC_IPQ806X)	+= dwmac-ipq806x.o
 obj-$(CONFIG_DWMAC_LPC18XX)	+= dwmac-lpc18xx.o
-obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o
+obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o dwmac-meson8b.o
 obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
new file mode 100644
index 0000000..d080512
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -0,0 +1,329 @@
+/*
+ * Amlogic Meson S805/S905 DWMAC glue layer
+ *
+ * Copyright (C) 20016 Martin Blumenstingl <martin.blumenstingl at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/clk-provider.h>
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_net.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+#define PRG_ETH0			0x0
+
+#define PRG_ETH0_RGMII_MODE		BIT(0)
+
+/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
+#define PRG_ETH0_CLK_M250_SEL_SHIFT	4
+#define PRG_ETH0_CLK_M250_SEL_MASK	GENMASK(4, 4)
+
+#define PRG_ETH0_TXDLY_SHIFT		5
+#define PRG_ETH0_TXDLY_MASK		GENMASK(6, 5)
+#define PRG_ETH0_TXDLY_OFF		(0x0 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_QUARTER		(0x1 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_HALF		(0x2 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_THREE_QUARTERS	(0x3 << PRG_ETH0_TXDLY_SHIFT)
+
+/* divider for the result of m250_sel */
+#define PRG_ETH0_CLK_M250_DIV_SHIFT	7
+#define PRG_ETH0_CLK_M250_DIV_WIDTH	3
+
+/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */
+#define PRG_ETH0_CLK_M25_DIV_SHIFT	10
+#define PRG_ETH0_CLK_M25_DIV_WIDTH	1
+
+#define PRG_ETH0_INVERTED_RMII_CLK	BIT(11)
+#define PRG_ETH0_TX_AND_PHY_REF_CLK	BIT(12)
+
+#define MUX_CLK_NUM_PARENTS		2
+
+struct meson8b_dwmac {
+	struct platform_device	*pdev;
+
+	void __iomem		*regs;
+
+	phy_interface_t		phy_mode;
+
+	struct clk_mux		m250_mux;
+	struct clk		*m250_mux_clk;
+	struct clk		*m250_mux_parent[MUX_CLK_NUM_PARENTS];
+
+	struct clk_divider	m250_div;
+	struct clk		*m250_div_clk;
+
+	struct clk_divider	m25_div;
+	struct clk		*m25_div_clk;
+};
+
+static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
+				    u32 mask, u32 value)
+{
+	u32 data;
+
+	data = readl(dwmac->regs + reg);
+	data &= ~mask;
+	data |= (value & mask);
+
+	writel(data, dwmac->regs + reg);
+}
+
+static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
+{
+	struct clk_init_data init;
+	int i, ret;
+	struct device *dev = &dwmac->pdev->dev;
+	char clk_name[32];
+	const char *clk_div_parents[1];
+	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+	static struct clk_div_table clk_25m_div_table[] = {
+		{ .val = 0, .div = 5 },
+		{ .val = 1, .div = 10 },
+		{ /* sentinel */ },
+	};
+
+	/* get the mux parents from DT */
+	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+		char name[16];
+
+		snprintf(name, sizeof(name), "clkin%d", i);
+		dwmac->m250_mux_parent[i] = devm_clk_get(dev, name);
+		if (IS_ERR(dwmac->m250_mux_parent[i])) {
+			ret = PTR_ERR(dwmac->m250_mux_parent[i]);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Missing clock %s\n", name);
+			return ret;
+		}
+
+		mux_parent_names[i] =
+			__clk_get_name(dwmac->m250_mux_parent[i]);
+	}
+
+	/* create the m250_mux */
+	snprintf(clk_name, sizeof(clk_name), "%s#m250_sel", dev_name(dev));
+	init.name = clk_name;
+	init.ops = &clk_mux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = mux_parent_names;
+	init.num_parents = MUX_CLK_NUM_PARENTS;
+
+	dwmac->m250_mux.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
+	dwmac->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
+	dwmac->m250_mux.flags = 0;
+	dwmac->m250_mux.table = NULL;
+	dwmac->m250_mux.hw.init = &init;
+
+	dwmac->m250_mux_clk = devm_clk_register(dev, &dwmac->m250_mux.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))
+		return PTR_ERR(dwmac->m250_mux_clk);
+
+	/* create the m250_div */
+	snprintf(clk_name, sizeof(clk_name), "%s#m250_div", dev_name(dev));
+	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(dwmac->m250_mux_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	dwmac->m250_div.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
+	dwmac->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
+	dwmac->m250_div.hw.init = &init;
+	dwmac->m250_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+
+	dwmac->m250_div_clk = devm_clk_register(dev, &dwmac->m250_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))
+		return PTR_ERR(dwmac->m250_div_clk);
+
+	/* create the m25_div */
+	snprintf(clk_name, sizeof(clk_name), "%s#m25_div", dev_name(dev));
+	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(dwmac->m250_div_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	dwmac->m25_div.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m25_div.shift = PRG_ETH0_CLK_M25_DIV_SHIFT;
+	dwmac->m25_div.width = PRG_ETH0_CLK_M25_DIV_WIDTH;
+	dwmac->m25_div.table = clk_25m_div_table;
+	dwmac->m25_div.hw.init = &init;
+	dwmac->m25_div.flags = CLK_DIVIDER_ALLOW_ZERO;
+
+	dwmac->m25_div_clk = devm_clk_register(dev, &dwmac->m25_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))
+		return PTR_ERR(dwmac->m25_div_clk);
+
+	return 0;
+}
+
+static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
+{
+	int ret;
+	unsigned long clk_rate;
+
+	switch (dwmac->phy_mode) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		/* Generate a 25MHz clock for the PHY */
+		clk_rate = 25 * 1000 * 1000;
+
+		/* enable RGMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
+					PRG_ETH0_RGMII_MODE);
+
+		/* only relevant for RMII mode -> disable in RGMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+					PRG_ETH0_INVERTED_RMII_CLK, 0);
+
+		/* TX clock delay - all known boards use a 1/4 cycle delay */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+					PRG_ETH0_TXDLY_QUARTER);
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
+		/* Use the rate of the mux clock for the internal RMII PHY */
+		clk_rate = clk_get_rate(dwmac->m250_mux_clk);
+
+		/* disable RGMII mode -> enables RMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
+					0);
+
+		/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+					PRG_ETH0_INVERTED_RMII_CLK,
+					PRG_ETH0_INVERTED_RMII_CLK);
+
+		/* TX clock delay cannot be configured in RMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+					0);
+
+		break;
+
+	default:
+		dev_err(&dwmac->pdev->dev, "unsupported phy-mode %s\n",
+			phy_modes(dwmac->phy_mode));
+		return -EINVAL;
+	}
+
+	ret = clk_prepare_enable(dwmac->m25_div_clk);
+	if (ret) {
+		dev_err(&dwmac->pdev->dev, "failed to enable the PHY clock\n");
+		return ret;
+	}
+
+	ret = clk_set_rate(dwmac->m25_div_clk, clk_rate);
+	if (ret) {
+		clk_disable_unprepare(dwmac->m25_div_clk);
+
+		dev_err(&dwmac->pdev->dev, "failed to set PHY clock\n");
+		return ret;
+	}
+
+	/* enable TX_CLK and PHY_REF_CLK generator */
+	meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
+				PRG_ETH0_TX_AND_PHY_REF_CLK);
+
+	return 0;
+}
+
+static int meson8b_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct resource *res;
+	struct meson8b_dwmac *dwmac;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return PTR_ERR(plat_dat);
+
+	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+	if (!dwmac)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -ENODEV;
+
+	dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dwmac->regs))
+		return PTR_ERR(dwmac->regs);
+
+	dwmac->pdev = pdev;
+	dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
+	if (dwmac->phy_mode < 0) {
+		dev_err(&pdev->dev, "missing phy-mode property\n");
+		return -EINVAL;
+	}
+
+	ret = meson8b_init_clk(dwmac);
+	if (ret)
+		return ret;
+
+	ret = meson8b_init_prg_eth(dwmac);
+	if (ret)
+		return ret;
+
+	plat_dat->bsp_priv = dwmac;
+
+	platform_set_drvdata(pdev, dwmac);
+
+	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+}
+
+static int meson8b_dwmac_remove(struct platform_device *pdev)
+{
+	struct meson8b_dwmac *dwmac = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(dwmac->m25_div_clk);
+
+	return stmmac_pltfr_remove(pdev);
+}
+
+static const struct of_device_id meson8b_dwmac_match[] = {
+	{ .compatible = "amlogic,meson8b-dwmac" },
+	{ .compatible = "amlogic,meson-gxbb-dwmac" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
+
+static struct platform_driver meson8b_dwmac_driver = {
+	.probe  = meson8b_dwmac_probe,
+	.remove = meson8b_dwmac_remove,
+	.driver = {
+		.name           = "meson8b-dwmac",
+		.pm		= &stmmac_pltfr_pm_ops,
+		.of_match_table = meson8b_dwmac_match,
+	},
+};
+module_platform_driver(meson8b_dwmac_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl at googlemail.com>");
+MODULE_DESCRIPTION("Amlogic Meson S805/S905 DWMAC glue layer");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:53:23 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:53:23 +0200
Subject: [PATCH v5 0/6] Add Meson 8b / GXBB support to the IR driver
In-Reply-To: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095329.549-1-martin.blumenstingl@googlemail.com>

Newer Amlogic platforms (Meson 8b and GXBB) use a slightly different
register layout for their Infrared Remoete Controller. The decoder mode
is now configured in another register. Without the changes to the
meson-ir driver we are simply getting incorrect "durations" reported
from the hardware (because the hardware is not in time measurement aka
software decode mode).

This problem was also noticed by some people trying to use this on an
ODROID-C1 and ODROID-C2 - the workaround there (probably because the
datasheets were not publicy available yet at that time) was to switch
to ir_raw_event_store_edge (which leaves it up to the kernel to measure
the duration of a pulse). See [0] and [1] for the corresponding
patches.

Changes in v5:
- changed pin function and group names to remote_input_ao so they match
  with the datasheet


Tested-by: Neil Armstrong <narmstrong at baylibre.com>


[0] https://github.com/erdoukki/linux-amlogic-1/commit/969b2e2242fb14a13cb651f9a1cf771b599c958b
[1] http://forum.odroid.com/viewtopic.php?f=135&t=20504


Martin Blumenstingl (3):
  pinctrl: amlogic: gxbb: add the IR remote input pin
  ARM64: dts: amlogic: add the input pin for the IR remote
  ARM64: dts: meson-gxbb: Enable the the IR decoder on supported boards

Neil Armstrong (3):
  dt-bindings: media: meson-ir: Add Meson8b and GXBB compatible strings
  media: rc: meson-ir: Add support for newer versions of the IR decoder
  ARM64: dts: meson-gxbb: Add Infrared Remote Controller decoder

 .../devicetree/bindings/media/meson-ir.txt         |  5 +++-
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  6 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  6 +++++
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |  6 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 14 +++++++++++
 drivers/media/rc/meson-ir.c                        | 29 ++++++++++++++++++----
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c         |  8 ++++++
 7 files changed, 68 insertions(+), 6 deletions(-)

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:18 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:18 +0200
Subject: [PATCH v5 0/6] Add Meson 8b / GXBB support to the IR driver
In-Reply-To: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-1-martin.blumenstingl@googlemail.com>

Newer Amlogic platforms (Meson 8b and GXBB) use a slightly different
register layout for their Infrared Remoete Controller. The decoder mode
is now configured in another register. Without the changes to the
meson-ir driver we are simply getting incorrect "durations" reported
from the hardware (because the hardware is not in time measurement aka
software decode mode).

This problem was also noticed by some people trying to use this on an
ODROID-C1 and ODROID-C2 - the workaround there (probably because the
datasheets were not publicy available yet at that time) was to switch
to ir_raw_event_store_edge (which leaves it up to the kernel to measure
the duration of a pulse). See [0] and [1] for the corresponding
patches.

Changes in v5:
- changed pin function and group names to remote_input_ao so they match
  with the datasheet


Tested-by: Neil Armstrong <narmstrong at baylibre.com>


[0] https://github.com/erdoukki/linux-amlogic-1/commit/969b2e2242fb14a13cb651f9a1cf771b599c958b
[1] http://forum.odroid.com/viewtopic.php?f=135&t=20504


Martin Blumenstingl (3):
  pinctrl: amlogic: gxbb: add the IR remote input pin
  ARM64: dts: amlogic: add the input pin for the IR remote
  ARM64: dts: meson-gxbb: Enable the the IR decoder on supported boards

Neil Armstrong (3):
  dt-bindings: media: meson-ir: Add Meson8b and GXBB compatible strings
  media: rc: meson-ir: Add support for newer versions of the IR decoder
  ARM64: dts: meson-gxbb: Add Infrared Remote Controller decoder

 .../devicetree/bindings/media/meson-ir.txt         |  5 +++-
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  6 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  6 +++++
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |  6 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 14 +++++++++++
 drivers/media/rc/meson-ir.c                        | 29 ++++++++++++++++++----
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c         |  8 ++++++
 7 files changed, 68 insertions(+), 6 deletions(-)

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:21 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:21 +0200
Subject: [PATCH v5 3/6] dt-bindings: media: meson-ir: Add Meson8b and GXBB
 compatible strings
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-4-martin.blumenstingl@googlemail.com>

From: Neil Armstrong <narmstrong at baylibre.com>

New bindings are needed as the register layout on the newer platforms
is slightly different compared to Meson6b.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 Documentation/devicetree/bindings/media/meson-ir.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/media/meson-ir.txt b/Documentation/devicetree/bindings/media/meson-ir.txt
index 407848e..e7e3f3c 100644
--- a/Documentation/devicetree/bindings/media/meson-ir.txt
+++ b/Documentation/devicetree/bindings/media/meson-ir.txt
@@ -1,7 +1,10 @@
 * Amlogic Meson IR remote control receiver
 
 Required properties:
- - compatible	: should be "amlogic,meson6-ir"
+ - compatible	: depending on the platform this should be one of:
+		  - "amlogic,meson6-ir"
+		  - "amlogic,meson8b-ir"
+		  - "amlogic,meson-gxbb-ir"
  - reg		: physical base address and length of the device registers
  - interrupts	: a single specifier for the interrupt from the device
 
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:19 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:19 +0200
Subject: [PATCH v5 1/6] pinctrl: amlogic: gxbb: add the IR remote input pin
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-2-martin.blumenstingl@googlemail.com>

This adds the IR remote receiver to the AO domain devices.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Reviewed-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index cb4d6ad..ff900d1 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -225,6 +225,8 @@ static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
 static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
+static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
+
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
 	GPIO_GROUP(GPIOZ_1, EE_OFF),
@@ -432,6 +434,7 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GROUP(i2c_sda_ao,	0,	5),
 	GROUP(i2c_slave_sck_ao, 0,	2),
 	GROUP(i2c_slave_sda_ao, 0,	1),
+	GROUP(remote_input_ao,	0,	0),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -521,6 +524,10 @@ static const char * const i2c_slave_ao_groups[] = {
 	"i2c_slave_sdk_ao", "i2c_slave_sda_ao",
 };
 
+static const char * const remote_input_ao_groups[] = {
+	"remote_input_ao",
+};
+
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
@@ -537,6 +544,7 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(uart_ao_b),
 	FUNCTION(i2c_ao),
 	FUNCTION(i2c_slave_ao),
+	FUNCTION(remote_input_ao),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:20 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:20 +0200
Subject: [PATCH v5 2/6] ARM64: dts: amlogic: add the input pin for the IR
 remote
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-3-martin.blumenstingl@googlemail.com>

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 4f42316..96f4574 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -210,6 +210,13 @@
 						function = "uart_ao";
 					};
 				};
+
+				remote_input_ao_pins: remote_input_ao {
+					mux {
+						groups = "remote_input_ao";
+						function = "remote_input_ao";
+					};
+				};
 			};
 
 			uart_AO: serial at 4c0 {
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:23 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:23 +0200
Subject: [PATCH v5 5/6] ARM64: dts: meson-gxbb: Add Infrared Remote Controller
 decoder
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-6-martin.blumenstingl@googlemail.com>

From: Neil Armstrong <narmstrong at baylibre.com>

This adds the Infrared Remote Controller node so boards with an IR
remote can simply enable it.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 96f4574..1cdc059 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -226,6 +226,13 @@
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			ir: ir at 580 {
+				compatible = "amlogic,meson-gxbb-ir";
+				reg = <0x0 0x00580 0x0 0x40>;
+				interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
 		};
 
 		periphs: periphs at c8834000 {
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:22 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:22 +0200
Subject: [PATCH v5 4/6] media: rc: meson-ir: Add support for newer versions of
 the IR decoder
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-5-martin.blumenstingl@googlemail.com>

From: Neil Armstrong <narmstrong at baylibre.com>

Newer SoCs (Meson 8b and GXBB) are using REG2 (offset 0x20) instead of
REG1 to configure the decoder mode. This makes it necessary to
introduce new bindings so the driver knows which register has to be
used.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Acked-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/media/rc/meson-ir.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index fcc3b82..003fff0 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -24,6 +24,7 @@
 
 #define DRIVER_NAME		"meson-ir"
 
+/* valid on all Meson platforms */
 #define IR_DEC_LDR_ACTIVE	0x00
 #define IR_DEC_LDR_IDLE		0x04
 #define IR_DEC_LDR_REPEAT	0x08
@@ -32,12 +33,21 @@
 #define IR_DEC_FRAME		0x14
 #define IR_DEC_STATUS		0x18
 #define IR_DEC_REG1		0x1c
+/* only available on Meson 8b and newer */
+#define IR_DEC_REG2		0x20
 
 #define REG0_RATE_MASK		(BIT(11) - 1)
 
-#define REG1_MODE_MASK		(BIT(7) | BIT(8))
-#define REG1_MODE_NEC		(0 << 7)
-#define REG1_MODE_GENERAL	(2 << 7)
+#define DECODE_MODE_NEC		0x0
+#define DECODE_MODE_RAW		0x2
+
+/* Meson 6b uses REG1 to configure the mode */
+#define REG1_MODE_MASK		GENMASK(8, 7)
+#define REG1_MODE_SHIFT		7
+
+/* Meson 8b / GXBB use REG2 to configure the mode */
+#define REG2_MODE_MASK		GENMASK(3, 0)
+#define REG2_MODE_SHIFT		0
 
 #define REG1_TIME_IV_SHIFT	16
 #define REG1_TIME_IV_MASK	((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
@@ -158,8 +168,15 @@ static int meson_ir_probe(struct platform_device *pdev)
 	/* Reset the decoder */
 	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, REG1_RESET);
 	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, 0);
-	/* Set general operation mode */
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, REG1_MODE_GENERAL);
+
+	/* Set general operation mode (= raw/software decoding) */
+	if (of_device_is_compatible(node, "amlogic,meson6-ir"))
+		meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK,
+				  DECODE_MODE_RAW << REG1_MODE_SHIFT);
+	else
+		meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK,
+				  DECODE_MODE_RAW << REG2_MODE_SHIFT);
+
 	/* Set rate */
 	meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
 	/* IRQ on rising and falling edges */
@@ -197,6 +214,8 @@ static int meson_ir_remove(struct platform_device *pdev)
 
 static const struct of_device_id meson_ir_match[] = {
 	{ .compatible = "amlogic,meson6-ir" },
+	{ .compatible = "amlogic,meson8b-ir" },
+	{ .compatible = "amlogic,meson-gxbb-ir" },
 	{ },
 };
 
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sat Aug 20 02:54:24 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 20 Aug 2016 11:54:24 +0200
Subject: [PATCH v5 6/6] ARM64: dts: meson-gxbb: Enable the the IR decoder on
 supported boards
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160820095424.636-7-martin.blumenstingl@googlemail.com>

Enable the Infrared Remote Controller on boards which have an Infrared
receiver.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts  | 6 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi     | 6 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 6 ++++++
 3 files changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index cba3ea1..d4823f4 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -161,3 +161,9 @@
 	vmmc-supply = <&vcc3v3>;
 	vmmcq-sumpply = <&vcc1v8>;
 };
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index e118754..4538e5a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -143,3 +143,9 @@
 	vmmc-supply = <&vcc_3v3>;
 	vmmcq-sumpply = <&vddio_boot>;
 };
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 54bb7c7..560770e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -60,3 +60,9 @@
 	pinctrl-names = "default";
 
 };
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
-- 
2.9.3



From weiyj.lk at gmail.com  Sat Aug 20 08:30:16 2016
From: weiyj.lk at gmail.com (Wei Yongjun)
Date: Sat, 20 Aug 2016 15:30:16 +0000
Subject: [PATCH -next] MMC: meson: remove redundant return value check of
 platform_get_resource()
Message-ID: <1471707016-28957-1-git-send-email-weiyj.lk@gmail.com>

Remove unneeded error handling on the result of a call
to platform_get_resource() when the value is passed to
devm_ioremap_resource().

Signed-off-by: Wei Yongjun <weiyj.lk at gmail.com>
---
 drivers/mmc/host/meson-gxbb.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
index 10eac41..96cd883 100644
--- a/drivers/mmc/host/meson-gxbb.c
+++ b/drivers/mmc/host/meson-gxbb.c
@@ -811,10 +811,6 @@ static int meson_mmc_probe(struct platform_device *pdev)
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto free_host;
-	}
 	host->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(host->regs)) {
 		ret = PTR_ERR(host->regs);



From narmstrong at baylibre.com  Sat Aug 20 11:34:39 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Sat, 20 Aug 2016 20:34:39 +0200
Subject: [RESEND PATCH v2 0/4] pwm: Add Amlogic Meson SoC PWM Controller
Message-ID: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>

Add support for the PWM controller found in Amlogic Meson SoCs.
This controller provides a dual PWM output with 4 selectable clock source
and a two level divider to achieve a better PWM range.

Currently Meson8b and GXBB SoCs are supported.

Changes since v1 at http://lkml.kernel.org/r/1466173784-15625-1-git-send-email-narmstrong at baylibre.com :
- fix meson8b dtsi

Neil Armstrong (4):
  pwm: Add support for Meson PWM Controller
  dt-bindings: pwm: Add bindings for Meson PWM Controller
  ARM64: dts: meson-gxbb: Add Meson GXBB PWM Controller nodes
  ARM: dts: meson8b: Add Meson8b PWM Controller nodes

 .../devicetree/bindings/pwm/pwm-meson.txt          |  21 +
 arch/arm/boot/dts/meson8b.dtsi                     |  21 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  28 ++
 drivers/pwm/Kconfig                                |   9 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-meson.c                            | 491 +++++++++++++++++++++
 6 files changed, 571 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-meson.txt
 create mode 100644 drivers/pwm/pwm-meson.c

-- 
1.9.1



From narmstrong at baylibre.com  Sat Aug 20 11:34:41 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Sat, 20 Aug 2016 20:34:41 +0200
Subject: [RESEND PATCH v2 2/4] dt-bindings: pwm: Add bindings for Meson PWM
 Controller
In-Reply-To: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
References: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471718083-11516-3-git-send-email-narmstrong@baylibre.com>

Add bindings for the Amlogic PWM Controller in Meson8b and GXBB SoCs.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 Documentation/devicetree/bindings/pwm/pwm-meson.txt | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-meson.txt

diff --git a/Documentation/devicetree/bindings/pwm/pwm-meson.txt b/Documentation/devicetree/bindings/pwm/pwm-meson.txt
new file mode 100644
index 0000000..e06aed0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-meson.txt
@@ -0,0 +1,21 @@
+Amlogic Meson PWM Controller
+=================================
+
+Required properties:
+- compatible: Shall contain "amlogic,meson8b-pwm" or "amlogic,meson-gxbb-pwm".
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
+  the cells format.
+
+Optional properties:
+- clocks: Could contain one or two parents clocks phandle for each of the two pwm channels.
+- clock-names: Could contain at least the "clkin0" and/or "clkin1" names.
+
+Example:
+pwm_ab: pwm at 8550 {
+	compatible = "amlogic,meson-gxbb-pwm";
+	reg = <0x0 0x08550 0x0 0x10>;
+	#pwm-cells = <3>;
+	status = "disabled";
+	clocks = <&xtal>, <&xtal>;
+	clock-names = "clkin0", "clkin1";
+}
-- 
1.9.1



From narmstrong at baylibre.com  Sat Aug 20 11:34:40 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Sat, 20 Aug 2016 20:34:40 +0200
Subject: [RESEND PATCH v2 1/4] pwm: Add support for Meson PWM Controller
In-Reply-To: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
References: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471718083-11516-2-git-send-email-narmstrong@baylibre.com>

Add support for the PWM controller found in the Amlogic SoCs.
This driver supports the Meson8b and GXBB SoCs.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pwm/Kconfig     |   9 +
 drivers/pwm/Makefile    |   1 +
 drivers/pwm/pwm-meson.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 501 insertions(+)
 create mode 100644 drivers/pwm/pwm-meson.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 80a566a..bf01288 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -262,6 +262,15 @@ config PWM_LPSS_PLATFORM
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-lpss-platform.
 
+config PWM_MESON
+	tristate "Amlogic Meson PWM driver"
+	depends on ARCH_MESON
+	help
+	  The platform driver for Amlogic Meson PWM controller.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-meson.
+
 config PWM_MTK_DISP
 	tristate "MediaTek display PWM driver"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index feef1dd..1194c54 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_PWM_LPC32XX)	+= pwm-lpc32xx.o
 obj-$(CONFIG_PWM_LPSS)		+= pwm-lpss.o
 obj-$(CONFIG_PWM_LPSS_PCI)	+= pwm-lpss-pci.o
 obj-$(CONFIG_PWM_LPSS_PLATFORM)	+= pwm-lpss-platform.o
+obj-$(CONFIG_PWM_MESON)		+= pwm-meson.o
 obj-$(CONFIG_PWM_MTK_DISP)	+= pwm-mtk-disp.o
 obj-$(CONFIG_PWM_MXS)		+= pwm-mxs.o
 obj-$(CONFIG_PWM_OMAP_DMTIMER)	+= pwm-omap-dmtimer.o
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
new file mode 100644
index 0000000..9e7ecf5
--- /dev/null
+++ b/drivers/pwm/pwm-meson.c
@@ -0,0 +1,491 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ * Copyright (C) 2014 Amlogic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ * Copyright (C) 2014 Amlogic, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+
+#define REG_PWM_A	0x0
+#define REG_PWM_B	0x4
+#define PWM_HIGH_SHIFT	16
+
+#define REG_MISC_AB	0x8
+#define MISC_B_CLK_EN	BIT(23)
+#define MISC_A_CLK_EN	BIT(15)
+#define MISC_CLK_DIV_MASK	0x7f
+#define MISC_B_CLK_DIV_SHIFT	16
+#define MISC_A_CLK_DIV_SHIFT	8
+#define MISC_B_CLK_SEL_SHIFT	6
+#define MISC_A_CLK_SEL_SHIFT	4
+#define MISC_CLK_SEL_WIDTH	2
+#define MISC_B_EN	BIT(1)
+#define MISC_A_EN	BIT(0)
+
+#define PWM_NUM		2
+
+static const unsigned int mux_reg_shifts[PWM_NUM] = {
+	MISC_A_CLK_SEL_SHIFT, MISC_B_CLK_SEL_SHIFT
+};
+
+static const char * const pwm_parents[] = {
+	"xtal", "vid_pll", "fclk_div4", "fclk_div3", NULL
+};
+
+enum pwm_channel {
+	PWM_A = 0,
+	PWM_B,
+};
+
+struct meson_pwm_channel {
+	unsigned int pwm_hi;
+	unsigned int pwm_lo;
+	u8 pwm_pre_div;
+	int period;
+	int duty;
+};
+
+struct meson_pwm_chip {
+	struct platform_device *pdev;
+	struct pwm_chip chip;
+	void __iomem *base;
+	u8 inverter_mask;
+	spinlock_t lock;
+	struct clk *clk_parents[PWM_NUM];
+	struct clk_mux mux[PWM_NUM];
+	struct clk *clk[PWM_NUM];
+};
+
+#define to_meson_pwm_chip(chip) \
+	container_of(chip, struct meson_pwm_chip, chip)
+
+static int meson_pwm_calc(struct meson_pwm_chip *chip,
+			       struct meson_pwm_channel *pwm_chan,
+			       unsigned int id,
+			       int duty_ns, unsigned int period_ns)
+{
+	unsigned int pwm_pre_div;
+	unsigned int pwm_cnt;
+	unsigned int pwm_duty_cnt;
+	unsigned long fin_freq = -1;
+	unsigned long fin_ns;
+	unsigned int i = 0;
+
+	if (duty_ns > period_ns)
+		return -EINVAL;
+
+	switch (id) {
+	case PWM_A:
+		fin_freq = clk_get_rate(chip->clk[0]);
+		break;
+	case PWM_B:
+		fin_freq = clk_get_rate(chip->clk[1]);
+		break;
+	}
+	if (fin_freq <= 0) {
+		dev_err(chip->chip.dev, "invalid source clock frequency\n");
+		return -EINVAL;
+	}
+	dev_dbg(chip->chip.dev, "fin_freq: %luHz\n", fin_freq);
+	fin_ns = NSEC_PER_SEC / fin_freq;
+
+	/* Calc pre_div with the period */
+	for (i = 0; i < MISC_CLK_DIV_MASK; i++) {
+		pwm_pre_div = i;
+		pwm_cnt = DIV_ROUND_CLOSEST(period_ns,
+				fin_ns * (pwm_pre_div + 1));
+		dev_dbg(chip->chip.dev, "fin_ns=%lu pre_div=%d cnt=%d\n",
+				fin_ns, pwm_pre_div, pwm_cnt);
+		if (pwm_cnt <= 0xffff)
+			break;
+	}
+	if (i == MISC_CLK_DIV_MASK) {
+		dev_err(chip->chip.dev, "Unable to get period pre_div");
+		return -EINVAL;
+	}
+	dev_dbg(chip->chip.dev, "period_ns=%d pre_div=%d pwm_cnt=%d\n",
+		period_ns, pwm_pre_div, pwm_cnt);
+
+	if (duty_ns == period_ns) {
+		pwm_chan->pwm_pre_div = pwm_pre_div;
+		pwm_chan->pwm_hi = pwm_cnt;
+		pwm_chan->pwm_lo = 0;
+	} else if (duty_ns == 0) {
+		pwm_chan->pwm_pre_div = pwm_pre_div;
+		pwm_chan->pwm_hi = 0;
+		pwm_chan->pwm_lo = pwm_cnt;
+	} else {
+		/* Then check is we can have the duty with the same pre_div */
+		pwm_duty_cnt = DIV_ROUND_CLOSEST(duty_ns,
+					fin_ns * (pwm_pre_div + 1));
+		if (pwm_cnt > 0xffff) {
+			dev_err(chip->chip.dev, "Unable to get duty period, differences are too high");
+			return -EINVAL;
+		}
+		dev_dbg(chip->chip.dev, "duty_ns=%d pre_div=%d pwm_cnt=%d\n",
+			duty_ns, pwm_pre_div, pwm_duty_cnt);
+
+		pwm_chan->pwm_pre_div = pwm_pre_div;
+		pwm_chan->pwm_hi = pwm_duty_cnt;
+		pwm_chan->pwm_lo = pwm_cnt - pwm_chan->pwm_hi;
+	}
+
+	return 0;
+}
+
+static int meson_pwm_request(struct pwm_chip *chip,
+				  struct pwm_device *pwm)
+{
+	struct meson_pwm_channel *pwm_chan;
+
+	pwm_chan = devm_kzalloc(chip->dev, sizeof(*pwm_chan), GFP_KERNEL);
+	if (!pwm_chan)
+		return -ENOMEM;
+
+	pwm_set_chip_data(pwm, pwm_chan);
+
+	return 0;
+}
+
+static void meson_pwm_free(struct pwm_chip *chip,
+				struct pwm_device *pwm)
+{
+	devm_kfree(chip->dev, pwm_get_chip_data(pwm));
+	pwm_set_chip_data(pwm, NULL);
+}
+
+static int meson_pwm_enable(struct pwm_chip *chip,
+				 struct pwm_device *pwm)
+{
+	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
+	unsigned int id = pwm->hwpwm;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pwm_data->lock, flags);
+	switch (id) {
+	case PWM_A:
+		writel(readl(pwm_data->base + REG_MISC_AB) | MISC_A_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	case PWM_B:
+		writel(readl(pwm_data->base + REG_MISC_AB) | MISC_B_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&pwm_data->lock, flags);
+
+	return 0;
+}
+
+static void meson_pwm_disable(struct pwm_chip *chip,
+				   struct pwm_device *pwm)
+{
+	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
+	unsigned int id = pwm->hwpwm;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pwm_data->lock, flags);
+	switch (id) {
+	case PWM_A:
+		writel(readl(pwm_data->base + REG_MISC_AB) & ~MISC_A_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	case PWM_B:
+		writel(readl(pwm_data->base + REG_MISC_AB) & ~MISC_B_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&pwm_data->lock, flags);
+}
+
+static int meson_pwm_config(struct pwm_chip *chip,
+				 struct pwm_device *pwm,
+				 int duty_ns,
+				 int period_ns)
+{
+	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
+	struct meson_pwm_channel *pwm_chan = pwm_get_chip_data(pwm);
+	unsigned int id = pwm->hwpwm;
+	int ret;
+
+	if ((~(pwm_data->inverter_mask >> id) & 0x1))
+		duty_ns = period_ns - duty_ns;
+
+	if (period_ns == pwm_chan->period && duty_ns == pwm_chan->duty)
+		return 0;
+
+	ret = meson_pwm_calc(pwm_data, pwm_chan, id, duty_ns, period_ns);
+	if (ret) {
+		dev_err(chip->dev, "error while calculating pwm parameters\n");
+		return ret;
+	}
+
+	switch (id) {
+	case PWM_A:
+		writel((readl(pwm_data->base + REG_MISC_AB) &
+			~(MISC_CLK_DIV_MASK << MISC_A_CLK_DIV_SHIFT)) |
+			((pwm_chan->pwm_pre_div << MISC_A_CLK_DIV_SHIFT) |
+			 MISC_A_CLK_EN),
+			pwm_data->base + REG_MISC_AB);
+
+		writel((pwm_chan->pwm_hi << PWM_HIGH_SHIFT) |
+		       (pwm_chan->pwm_lo),
+		       pwm_data->base + REG_PWM_A);
+		break;
+
+	case PWM_B:
+		writel((readl(pwm_data->base + REG_MISC_AB) &
+			~(MISC_CLK_DIV_MASK << MISC_B_CLK_DIV_SHIFT)) |
+			((pwm_chan->pwm_pre_div << MISC_B_CLK_DIV_SHIFT) |
+			 MISC_B_CLK_EN),
+			pwm_data->base + REG_MISC_AB);
+
+		writel((pwm_chan->pwm_hi << PWM_HIGH_SHIFT) |
+		       (pwm_chan->pwm_lo),
+		       pwm_data->base + REG_PWM_B);
+		break;
+
+	default:
+		break;
+	}
+
+	pwm_chan->period = period_ns;
+	pwm_chan->duty = duty_ns;
+
+	return 0;
+}
+
+static int meson_pwm_set_polarity(struct pwm_chip *chip,
+				    struct pwm_device *pwm,
+				    enum pwm_polarity polarity)
+{
+	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
+	struct meson_pwm_channel *pwm_chan = pwm_get_chip_data(pwm);
+	bool invert = (polarity == PWM_POLARITY_NORMAL);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pwm_data->lock, flags);
+
+	if (invert)
+		pwm_data->inverter_mask |= BIT(pwm->hwpwm);
+	else
+		pwm_data->inverter_mask &= ~BIT(pwm->hwpwm);
+
+	meson_pwm_config(chip, pwm, pwm_chan->duty, pwm_chan->period);
+
+	spin_unlock_irqrestore(&pwm_data->lock, flags);
+
+	return 0;
+}
+
+static const struct pwm_ops meson_pwm_ops = {
+	.request	= meson_pwm_request,
+	.free		= meson_pwm_free,
+	.enable		= meson_pwm_enable,
+	.disable	= meson_pwm_disable,
+	.config		= meson_pwm_config,
+	.set_polarity	= meson_pwm_set_polarity,
+	.owner		= THIS_MODULE,
+};
+
+static const struct of_device_id meson_pwm_matches[] = {
+	{ .compatible = "amlogic,meson8b-pwm", },
+	{ .compatible = "amlogic,meson-gxbb-pwm", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, meson_pwm_matches);
+
+static int meson_pwm_mux_init(struct meson_pwm_chip *chip)
+{
+	struct device *dev = &chip->pdev->dev;
+	struct clk_init_data init;
+	char clk_name[255];
+	int ret;
+	int i;
+
+	for (i = 0 ; i < PWM_NUM ; ++i) {
+		sprintf(clk_name, "%s#mux%d",
+				of_node_full_name(dev->of_node), i);
+
+		init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+		init.ops = &clk_mux_ops;
+		init.flags = CLK_IS_BASIC;
+		init.parent_names = pwm_parents;
+		init.num_parents = 1 << MISC_CLK_SEL_WIDTH;
+
+		chip->mux[i].reg = chip->base + REG_MISC_AB;
+		chip->mux[i].shift = mux_reg_shifts[i];
+		chip->mux[i].mask = BIT(MISC_CLK_SEL_WIDTH) - 1;
+		chip->mux[i].flags = 0;
+		chip->mux[i].lock = &chip->lock;
+		chip->mux[i].table = NULL;
+		chip->mux[i].hw.init = &init;
+
+		chip->clk[i] = devm_clk_register(dev, &chip->mux[i].hw);
+		if (IS_ERR(chip->clk[i])) {
+			dev_err(dev, "Failed to register %s\n", clk_name);
+			return PTR_ERR(chip->clk[i]);
+		}
+
+		if (chip->clk_parents[i]) {
+			ret = clk_set_parent(chip->clk[i],
+					     chip->clk_parents[i]);
+			if (ret) {
+				dev_err(dev, "Failed to set %s parent\n",
+					clk_name);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int meson_pwm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct meson_pwm_chip *chip;
+	struct resource *res;
+	int ret;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	chip->pdev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	chip->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(chip->base))
+		return PTR_ERR(chip->base);
+
+	chip->clk_parents[0] = devm_clk_get(dev, "clkin0");
+	if (IS_ERR(chip->clk_parents[0])) {
+		if (PTR_ERR(chip->clk_parents[0]) == -EPROBE_DEFER)
+			return PTR_ERR(chip->clk_parents[0]);
+		chip->clk_parents[0] = NULL;
+	}
+
+	chip->clk_parents[1] = devm_clk_get(dev, "clkin1");
+	if (IS_ERR(chip->clk_parents[1])) {
+		if (PTR_ERR(chip->clk_parents[1]) == -EPROBE_DEFER)
+			return PTR_ERR(chip->clk_parents[1]);
+		chip->clk_parents[1] = NULL;
+	}
+
+	ret = meson_pwm_mux_init(chip);
+	if (ret)
+		return ret;
+
+	clk_prepare_enable(chip->clk[0]);
+	clk_prepare_enable(chip->clk[1]);
+
+	chip->chip.dev = dev;
+	chip->chip.ops = &meson_pwm_ops;
+	chip->chip.base = -1;
+	chip->chip.npwm = PWM_NUM;
+	chip->chip.of_xlate = of_pwm_xlate_with_flags;
+	chip->chip.of_pwm_n_cells = 3;
+	chip->inverter_mask = BIT(PWM_NUM) - 1;
+
+	ret = pwmchip_add(&chip->chip);
+	if (ret < 0) {
+		dev_err(dev, "failed to register PWM chip\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, chip);
+
+	return 0;
+}
+
+static int meson_pwm_remove(struct platform_device *pdev)
+{
+	struct meson_pwm_chip *chip = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&chip->chip);
+}
+
+static struct platform_driver meson_pwm_driver = {
+	.driver		= {
+		.name	= "meson-pwm",
+		.of_match_table = of_match_ptr(meson_pwm_matches),
+	},
+	.probe		= meson_pwm_probe,
+	.remove		= meson_pwm_remove,
+};
+module_platform_driver(meson_pwm_driver);
+
+MODULE_ALIAS("platform:meson-pwm");
+MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
1.9.1



From narmstrong at baylibre.com  Sat Aug 20 11:34:43 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Sat, 20 Aug 2016 20:34:43 +0200
Subject: [RESEND PATCH v2 4/4] ARM: dts: meson8b: Add Meson8b PWM Controller
 nodes
In-Reply-To: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
References: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471718083-11516-5-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm/boot/dts/meson8b.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index fc4080d..41fd536 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -162,6 +162,27 @@
 			reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
 		};
 
+		pwm_ab: pwm at 8550 {
+			compatible = "amlogic,meson8b-pwm";
+			reg = <0xc1108550 0x10>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm_cd: pwm at 8650 {
+			compatible = "amlogic,meson8b-pwm";
+			reg = <0xc1108650 0x10>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm_ef: pwm at 86c0 {
+			compatible = "amlogic,meson8b-pwm";
+			reg = <0xc11086c0 0x10>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		pinctrl_cbus: pinctrl at c1109880 {
 			compatible = "amlogic,meson8b-cbus-pinctrl";
 			reg = <0xc1109880 0x10>;
-- 
1.9.1



From narmstrong at baylibre.com  Sat Aug 20 11:34:42 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Sat, 20 Aug 2016 20:34:42 +0200
Subject: [RESEND PATCH v2 3/4] ARM64: dts: meson-gxbb: Add Meson GXBB PWM
 Controller nodes
In-Reply-To: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
References: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471718083-11516-4-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..e3f4d36 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -153,6 +153,27 @@
 				status = "disabled";
 			};
 
+			pwm_ab: pwm at 8550 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_cd: pwm at 8650 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08650 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_ef: pwm at 86c0 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x086c0 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
 			uart_C: serial at 8700 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x8700 0x0 0x14>;
@@ -212,6 +233,13 @@
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			pwm_ab_AO: pwm at 550 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x0550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
 		};
 
 		periphs: periphs at c8834000 {
-- 
1.9.1



From manabian at gmail.com  Sat Aug 20 14:29:08 2016
From: manabian at gmail.com (Joachim Eastwood)
Date: Sat, 20 Aug 2016 23:29:08 +0200
Subject: [PATCH v2 3/4] net: stmmac: add a glue driver for the Amlogic
 Meson 8b / GXBB DWMAC
In-Reply-To: <20160820093538.9707-4-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-4-martin.blumenstingl@googlemail.com>
Message-ID: <CAGhQ9VyWs=sYg7PVrt5r-fM-2t--qAnHyvNXAZXwjkYn5P196g@mail.gmail.com>

Hi Martin,

On 20 August 2016 at 11:35, Martin Blumenstingl
<martin.blumenstingl at googlemail.com> wrote:
> The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
> DesignWare MAC IP core which is already supported by the stmmac driver.
>
> In addition to the standard stmmac driver some Meson8b / GXBB specific
> registers have to be configured for the PHY clocks. These SoC specific
> registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
> datasheet.
> These registers are not backwards compatible with those on Meson 6b,
> which is why a new glue driver is introduced. This worked for many
> boards because the bootloader programs the PRG_ETHERNET registers
> correctly. Additionally the meson6-dwmac driver only sets bit 1 of
> PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
> during reset.
>
> Currently all configuration values can be determined automatically,
> based on the configured phy-mode (which is mandatory for the stmmac
> driver). If required the tx-delay and the mux clock (so it supports
> the MPLL2 clock as well) can be made configurable in the future.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> Tested-by: Kevin Hilman <khilman at baylibre.com>
> ---
>  drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
>  .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 329 +++++++++++++++++++++
>  2 files changed, 330 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

<snip>

> +static int meson8b_dwmac_probe(struct platform_device *pdev)
> +{
> +       struct plat_stmmacenet_data *plat_dat;
> +       struct stmmac_resources stmmac_res;
> +       struct resource *res;
> +       struct meson8b_dwmac *dwmac;
> +       int ret;
> +
> +       ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> +       if (ret)
> +               return ret;
> +
> +       plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
> +       if (IS_ERR(plat_dat))
> +               return PTR_ERR(plat_dat);
> +
> +       dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
> +       if (!dwmac)
> +               return -ENOMEM;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +       if (!res)
> +               return -ENODEV;
> +
> +       dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(dwmac->regs))
> +               return PTR_ERR(dwmac->regs);
> +
> +       dwmac->pdev = pdev;
> +       dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
> +       if (dwmac->phy_mode < 0) {
> +               dev_err(&pdev->dev, "missing phy-mode property\n");
> +               return -EINVAL;
> +       }
> +
> +       ret = meson8b_init_clk(dwmac);
> +       if (ret)
> +               return ret;
> +
> +       ret = meson8b_init_prg_eth(dwmac);
> +       if (ret)
> +               return ret;
> +
> +       plat_dat->bsp_priv = dwmac;
> +
> +       platform_set_drvdata(pdev, dwmac);

This will not work. The main stmmac driver already uses the driver_data field.
See: http://lxr.free-electrons.com/source/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c#L3218


> +       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);

So calling stmmac_dvr_probe here will overwrite the driver_data field.


> +}
> +
> +static int meson8b_dwmac_remove(struct platform_device *pdev)
> +{
> +       struct meson8b_dwmac *dwmac = platform_get_drvdata(pdev);
> +
> +       clk_disable_unprepare(dwmac->m25_div_clk);

Did you test this code? I am pretty sure it will blow up given that
driver_data is not set to what you expect.

To get your meson8b_dwmac struct you must retrieve it from plat_dat->bsp_priv.


I have some code for a helper to retrieve bsp_priv that I have meant
to sent to the ML for a while now.
See: https://github.com/manabian/linux-lpc/commit/c3e155a6e38b9634e4e61aa4eeb4602ede7e44a6

Feel free to add it to your patch set if you want.

Alternatively take a look at the remove function from dwmac-stm32 here:
https://patchwork.ozlabs.org/patch/619816/


> +
> +       return stmmac_pltfr_remove(pdev);
> +}


regards,
Joachim Eastwood


From martin.blumenstingl at googlemail.com  Sun Aug 21 05:00:39 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 21 Aug 2016 14:00:39 +0200
Subject: [PATCH v2 3/4] net: stmmac: add a glue driver for the Amlogic
 Meson 8b / GXBB DWMAC
In-Reply-To: <CAGhQ9VyWs=sYg7PVrt5r-fM-2t--qAnHyvNXAZXwjkYn5P196g@mail.gmail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-4-martin.blumenstingl@googlemail.com>
 <CAGhQ9VyWs=sYg7PVrt5r-fM-2t--qAnHyvNXAZXwjkYn5P196g@mail.gmail.com>
Message-ID: <CAFBinCCC4LQUkF17G-LNQWs_EuRiw44V7hep-zDsm-9MQ64VnA@mail.gmail.com>

Hi Joachim,

On Sat, Aug 20, 2016 at 11:29 PM, Joachim  Eastwood <manabian at gmail.com> wrote:
>> +       platform_set_drvdata(pdev, dwmac);
>
> This will not work. The main stmmac driver already uses the driver_data field.
> See: http://lxr.free-electrons.com/source/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c#L3218
>
>
>> +       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
>
> So calling stmmac_dvr_probe here will overwrite the driver_data field.
>
>
>> +}
>> +
>> +static int meson8b_dwmac_remove(struct platform_device *pdev)
>> +{
>> +       struct meson8b_dwmac *dwmac = platform_get_drvdata(pdev);
>> +
>> +       clk_disable_unprepare(dwmac->m25_div_clk);
>
> Did you test this code? I am pretty sure it will blow up given that
> driver_data is not set to what you expect.
I guess I should've taken a closer look at my kernel config:
CONFIG_DWMAC_MESON=y
Thanks for spotting this issue!

> To get your meson8b_dwmac struct you must retrieve it from plat_dat->bsp_priv.
>
>
> I have some code for a helper to retrieve bsp_priv that I have meant
> to sent to the ML for a while now.
> See: https://github.com/manabian/linux-lpc/commit/c3e155a6e38b9634e4e61aa4eeb4602ede7e44a6
>
> Feel free to add it to your patch set if you want.
>
> Alternatively take a look at the remove function from dwmac-stm32 here:
> https://patchwork.ozlabs.org/patch/619816/
excellent, thanks!

I will send a fixed version as soon as possible


Regards,
Martin


From linus.walleij at linaro.org  Mon Aug 22 02:23:07 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 22 Aug 2016 11:23:07 +0200
Subject: [PATCH] pinctrl: meson: get rid of unneeded domain structures
In-Reply-To: <1471110078-5946-1-git-send-email-b.galvani@gmail.com>
References: <1471110078-5946-1-git-send-email-b.galvani@gmail.com>
Message-ID: <CACRpkdbnXjOBP7KtFa+0_u9fVrqNRtBvskOwPggGbA5yW7RgDg@mail.gmail.com>

On Sat, Aug 13, 2016 at 7:41 PM, Beniamino Galvani <b.galvani at gmail.com> wrote:

> The driver originally supported more domains (register ranges) per
> pinctrl device, but since commit 9dab1868ec0d ("pinctrl: amlogic: Make
> driver independent from two-domain configuration") each device gets
> assigned a single domain and we instantiate multiple pinctrl devices
> in the DT.
>
> Therefore, now the 'meson_domain' and 'meson_domain_data' structures
> don't have any reason to exist and can be removed to make the model
> simpler to understand. This commit doesn't change behavior.
>
> Tested on a Odroid-C2.
>
> Signed-off-by: Beniamino Galvani <b.galvani at gmail.com>

Patch applied with Kevin's ACK/Test tags.

Yours,
Linus Walleij


From marc.zyngier at arm.com  Mon Aug 22 03:26:33 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 22 Aug 2016 11:26:33 +0100
Subject: [PATCH v2 2/2] arm64: dts: Fix broken architected timer interrupt
 trigger
In-Reply-To: <1470045256-9032-3-git-send-email-marc.zyngier@arm.com>
References: <1470045256-9032-1-git-send-email-marc.zyngier@arm.com>
 <1470045256-9032-3-git-send-email-marc.zyngier@arm.com>
Message-ID: <57BAD359.30707@arm.com>

Arnd, Olof,

On 01/08/16 10:54, Marc Zyngier wrote:
> The ARM architected timer specification mandates that the interrupt
> associated with each timer is level triggered (which corresponds to
> the "counter >= comparator" condition).
> 
> A number of DTs are being remarkably creative, declaring the interrupt
> to be edge triggered. A quick look at the TRM for the corresponding ARM
> CPUs clearly shows that this is wrong, and I've corrected those.
> For non-ARM designs (and in the absence of a publicly available TRM),
> I've made them active low as well, which can't be completely wrong
> as the GIC cannot disinguish between level low and level high.
> 
> The respective maintainers are of course welcome to prove me wrong.
> 
> While I was at it, I took the liberty to fix a couple of related issue,
> such as some spurious affinity bits on ThunderX, and their complete
> absence on ls1043a (both of which seem to be related to copy-pasting
> from other DTs).
> 
> Acked-by: Duc Dang <dhdang at apm.com>
> Acked-by: Carlo Caione <carlo at endlessm.com>
> Acked-by: Michal Simek <michal.simek at xilinx.com>
> Acked-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Acked-by: Dinh Nguyen <dinguyen at opensource.altera.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>

Any update on this patch? We have a workaround merged already, but it'd
be good to have the DTS fixed as well.

Thanks,

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


From arnd at arndb.de  Mon Aug 22 04:55:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 22 Aug 2016 13:55:22 +0200
Subject: [PATCH v2 1/4] net: dt-bindings: Document the new Meson8b and
 GXBB DWMAC bindings
In-Reply-To: <20160820093538.9707-2-martin.blumenstingl@googlemail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-2-martin.blumenstingl@googlemail.com>
Message-ID: <7308700.atIMKyMFZU@wuerfel>

On Saturday, August 20, 2016 11:35:35 AM CEST Martin Blumenstingl wrote:
> +- reg: The first register range should be the one of the DWMAC
> +       controller. The second range is is for the Amlogic specific
> +       configuration (for example the PRG_ETHERNET register range
> +       on Meson8b and newer)
>  
...

> +Example for GXBB:
> +       ethmac: ethernet at c9410000 {
> +               compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
> +               reg = <0x0 0xc9410000 0x0 0x10000>,
> +                       <0x0 0xc8834540 0x0 0x8>;
> 

The address "0xc8834540" suggests that this is part of a larger register
range that is used for various things, i.e. a "syscon" type of device.

How about making this a syscon reference rather than a "reg" address?

	Arnd


From martin.blumenstingl at googlemail.com  Mon Aug 22 05:04:49 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 22 Aug 2016 14:04:49 +0200
Subject: [PATCH v2 1/4] net: dt-bindings: Document the new Meson8b and
 GXBB DWMAC bindings
In-Reply-To: <7308700.atIMKyMFZU@wuerfel>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160820093538.9707-2-martin.blumenstingl@googlemail.com>
 <7308700.atIMKyMFZU@wuerfel>
Message-ID: <CAFBinCA0HWHR3UbVX-_wU14W0-KOr-BAf5Nyn1ocZdnYxojn2Q@mail.gmail.com>

On Mon, Aug 22, 2016 at 1:55 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Saturday, August 20, 2016 11:35:35 AM CEST Martin Blumenstingl wrote:
>> +- reg: The first register range should be the one of the DWMAC
>> +       controller. The second range is is for the Amlogic specific
>> +       configuration (for example the PRG_ETHERNET register range
>> +       on Meson8b and newer)
>>
> ...
>
>> +Example for GXBB:
>> +       ethmac: ethernet at c9410000 {
>> +               compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
>> +               reg = <0x0 0xc9410000 0x0 0x10000>,
>> +                       <0x0 0xc8834540 0x0 0x8>;
>>
>
> The address "0xc8834540" suggests that this is part of a larger register
> range that is used for various things, i.e. a "syscon" type of device.
You are right, these are part of the cbus range (which is already
defined in meson-gxbb.dtsi)

> How about making this a syscon reference rather than a "reg" address?
The first version of my patch ([0]) used
syscon_regmap_lookup_by_phandle. Maybe I did it wrong (and I should
have passed the cbus syscon-node instead of defining a new one just
for the 2x32bit PRG_ETHERNET registers).
I am perfectly fine with either way - however it seems that some other
dwmac glue implementations are also using a second set of resources
(that doesn't automatically make it "correct" though).


Martin


From narmstrong at baylibre.com  Mon Aug 22 05:16:52 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 14:16:52 +0200
Subject: [RESEND PATCH v2 1/4] pwm: Add support for Meson PWM Controller
In-Reply-To: <1471718083-11516-2-git-send-email-narmstrong@baylibre.com>
References: <1471718083-11516-1-git-send-email-narmstrong@baylibre.com>
 <1471718083-11516-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <ad2f719e-9236-96fd-3bea-ce20c487c67f@baylibre.com>

Hi Thierry,

On 08/20/2016 08:34 PM, Neil Armstrong wrote:
> Add support for the PWM controller found in the Amlogic SoCs.
> This driver supports the Meson8b and GXBB SoCs.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/pwm/Kconfig     |   9 +
>  drivers/pwm/Makefile    |   1 +
>  drivers/pwm/pwm-meson.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 501 insertions(+)
>  create mode 100644 drivers/pwm/pwm-meson.c
> 

[...]

> diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
> new file mode 100644
> index 0000000..9e7ecf5
> --- /dev/null
> +++ b/drivers/pwm/pwm-meson.c

[...]

> +
> +static const char * const pwm_parents[] = {
> +	"xtal", "vid_pll", "fclk_div4", "fclk_div3", NULL
> +};

Aww, crap, it's "vid_pll" on meson8b and "hdmi_pll" for gxbb.
I'll add it to DT mach data.

> +static int meson_pwm_enable(struct pwm_chip *chip,
> +				 struct pwm_device *pwm)
> +{
> +	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
> +	unsigned int id = pwm->hwpwm;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&pwm_data->lock, flags);
> +	switch (id) {
> +	case PWM_A:
> +		writel(readl(pwm_data->base + REG_MISC_AB) | MISC_A_EN,
> +			pwm_data->base + REG_MISC_AB);

Found an issue here, the HW requires to re-write the clock counts register even if the value is correct.
Let's got for a v3 !

> +		break;
> +
> +	case PWM_B:
> +		writel(readl(pwm_data->base + REG_MISC_AB) | MISC_B_EN,
> +			pwm_data->base + REG_MISC_AB);
> +		break;
> +
> +	default:
> +		break;
> +	}
> +	spin_unlock_irqrestore(&pwm_data->lock, flags);
> +
> +	return 0;
> +}

Is it worth rewriting the driver using the apply callback ?
I'll wish to have it for 4.9 if possible, do you think it's possible ?

Neil




From narmstrong at baylibre.com  Mon Aug 22 05:49:37 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 14:49:37 +0200
Subject: [PATCH] clk: meson-gxbb: Export PWM related clocks for DT
Message-ID: <1471870177-10609-1-git-send-email-narmstrong@baylibre.com>

Add the PWM related clocks in order to be referenced as PWM source
clocks.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/clk/meson/gxbb.h              | 6 +++---
 include/dt-bindings/clock/gxbb-clkc.h | 3 +++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index a2adf34..523b494 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -170,11 +170,11 @@
  */
 #define CLKID_SYS_PLL		  0
 /* CLKID_CPUCLK */
-#define CLKID_HDMI_PLL		  2
+/* CLKID_HDMI_PLL */
 #define CLKID_FIXED_PLL		  3
 #define CLKID_FCLK_DIV2		  4
-#define CLKID_FCLK_DIV3		  5
-#define CLKID_FCLK_DIV4		  6
+/* CLKID_FCLK_DIV3 */
+/* CLKID_FCLK_DIV4 */
 #define CLKID_FCLK_DIV5		  7
 #define CLKID_FCLK_DIV7		  8
 #define CLKID_GP0_PLL		  9
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index f889d80..a5897f3 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -6,6 +6,9 @@
 #define __GXBB_CLKC_H
 
 #define CLKID_CPUCLK		1
+#define CLKID_HDMI_PLL		2
+#define CLKID_FCLK_DIV3		5
+#define CLKID_FCLK_DIV4		6
 #define CLKID_CLK81		12
 #define CLKID_ETH		36
 
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 05:54:08 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 14:54:08 +0200
Subject: [PATCH 0/2] pinctrl: meson-gxbb: Export pins for PWMs
Message-ID: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>

Add PWM pins in the meson-gxbb pinctrl driver and export then in the GXBB dtsi.

Neil Armstrong (2):
  ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
  ARM64: dts: meson-gxbb: Add PWM pinctrl nodes

 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 77 ++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c  | 79 +++++++++++++++++++++++++++++
 2 files changed, 156 insertions(+)

-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 05:54:10 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 14:54:10 +0200
Subject: [PATCH 2/2] ARM64: dts: meson-gxbb: Add PWM pinctrl nodes
In-Reply-To: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471870450-11109-3-git-send-email-narmstrong@baylibre.com>

Add DT nodes for PWMs in EE and AO domains.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 77 +++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e3f4d36..0677eca 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -224,6 +224,34 @@
 						function = "uart_ao";
 					};
 				};
+
+				pwm_ao_a_3_pins: pwm_ao_a_3 {
+					mux {
+						groups = "pwm_ao_a_3";
+						function = "pwm_ao_a_3";
+					};
+				};
+
+				pwm_ao_a_6_pins: pwm_ao_a_6 {
+					mux {
+						groups = "pwm_ao_a_6";
+						function = "pwm_ao_a_6";
+					};
+				};
+
+				pwm_ao_a_12_pins: pwm_ao_a_12 {
+					mux {
+						groups = "pwm_ao_a_12";
+						function = "pwm_ao_a_12";
+					};
+				};
+
+				pwm_ao_b_pins: pwm_ao_b {
+					mux {
+						groups = "pwm_ao_b";
+						function = "pwm_ao_b";
+					};
+				};
 			};
 
 			uart_AO: serial at 4c0 {
@@ -334,6 +362,55 @@
 						function = "eth";
 					};
 				};
+
+				pwm_a_x_pins: pwm_a_x {
+					mux {
+						groups = "pwm_a_x";
+						function = "pwm_a_x";
+					};
+				};
+
+				pwm_a_y_pins: pwm_a_y {
+					mux {
+						groups = "pwm_a_y";
+						function = "pwm_a_y";
+					};
+				};
+
+				pwm_b_pins: pwm_b {
+					mux {
+						groups = "pwm_b";
+						function = "pwm_b";
+					};
+				};
+
+				pwm_d_pins: pwm_d {
+					mux {
+						groups = "pwm_d";
+						function = "pwm_d";
+					};
+				};
+
+				pwm_e_pins: pwm_e {
+					mux {
+						groups = "pwm_e";
+						function = "pwm_e";
+					};
+				};
+
+				pwm_f_x_pins: pwm_f_x {
+					mux {
+						groups = "pwm_f_x";
+						function = "pwm_f_x";
+					};
+				};
+
+				pwm_f_y_pins: pwm_f_y {
+					mux {
+						groups = "pwm_f_y";
+						function = "pwm_f_y";
+					};
+				};
 			};
 		};
 
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 05:54:09 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 14:54:09 +0200
Subject: [PATCH 1/2] ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
In-Reply-To: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>

Add support for PWM pins, for EE and AO domains.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 79 ++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index cb4d6ad..2227507 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -193,6 +193,14 @@ static const unsigned int eth_txd1_pins[]	= { PIN(GPIOZ_11, EE_OFF) };
 static const unsigned int eth_txd2_pins[]	= { PIN(GPIOZ_12, EE_OFF) };
 static const unsigned int eth_txd3_pins[]	= { PIN(GPIOZ_13, EE_OFF) };
 
+static const unsigned int pwm_a_x_pins[]	= { PIN(GPIOX_6, EE_OFF) };
+static const unsigned int pwm_a_y_pins[]	= { PIN(GPIOY_16, EE_OFF) };
+static const unsigned int pwm_b_pins[]		= { PIN(GPIODV_29, EE_OFF) };
+static const unsigned int pwm_d_pins[]		= { PIN(GPIODV_28, EE_OFF) };
+static const unsigned int pwm_e_pins[]		= { PIN(GPIOX_19, EE_OFF) };
+static const unsigned int pwm_f_x_pins[]	= { PIN(GPIOX_7, EE_OFF) };
+static const unsigned int pwm_f_y_pins[]	= { PIN(GPIOY_15, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -225,6 +233,11 @@ static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
 static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
+static const unsigned int pwm_ao_a_3_pins[]	= { PIN(GPIOAO_3, 0) };
+static const unsigned int pwm_ao_a_6_pins[]	= { PIN(GPIOAO_6, 0) };
+static const unsigned int pwm_ao_a_12_pins[]	= { PIN(GPIOAO_12, 0) };
+static const unsigned int pwm_ao_b_pins[]	= { PIN(GPIOAO_13, 0) };
+
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
 	GPIO_GROUP(GPIOZ_1, EE_OFF),
@@ -359,12 +372,17 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_rx_a,	4,	12),
 	GROUP(uart_cts_a,	4,	11),
 	GROUP(uart_rts_a,	4,	10),
+	GROUP(pwm_a_x,		3,	17),
+	GROUP(pwm_e,		2,	30),
+	GROUP(pwm_f_x,		3,	18),
 
 	/* Bank Y */
 	GROUP(uart_cts_c,	1,	19),
 	GROUP(uart_rts_c,	1,	18),
 	GROUP(uart_tx_c,	1,	17),
 	GROUP(uart_rx_c,	1,	16),
+	GROUP(pwm_a_y,		1,	20),
+	GROUP(pwm_f_y,		1,	21),
 
 	/* Bank Z */
 	GROUP(eth_mdio,		6,	1),
@@ -387,6 +405,8 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_rx_b,	2,	28),
 	GROUP(uart_cts_b,	2,	27),
 	GROUP(uart_rts_b,	2,	26),
+	GROUP(pwm_b,		3,	21),
+	GROUP(pwm_d,		3,	20),
 
 	/* Bank BOOT */
 	GROUP(emmc_nand_d07,	4,	30),
@@ -432,6 +452,10 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GROUP(i2c_sda_ao,	0,	5),
 	GROUP(i2c_slave_sck_ao, 0,	2),
 	GROUP(i2c_slave_sda_ao, 0,	1),
+	GROUP(pwm_ao_a_3,	0,	22),
+	GROUP(pwm_ao_a_6,	0,	18),
+	GROUP(pwm_ao_a_12,	0,	17),
+	GROUP(pwm_ao_b,		0,	3),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -499,6 +523,34 @@ static const char * const eth_groups[] = {
 	"eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
 };
 
+static const char * const pwm_a_x_groups[] = {
+	"pwm_a_x",
+};
+
+static const char * const pwm_a_y_groups[] = {
+	"pwm_a_y",
+};
+
+static const char * const pwm_b_groups[] = {
+	"pwm_b",
+};
+
+static const char * const pwm_d_groups[] = {
+	"pwm_d",
+};
+
+static const char * const pwm_e_groups[] = {
+	"pwm_e",
+};
+
+static const char * const pwm_f_x_groups[] = {
+	"pwm_f_x",
+};
+
+static const char * const pwm_f_y_groups[] = {
+	"pwm_f_y",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -521,6 +573,22 @@ static const char * const i2c_slave_ao_groups[] = {
 	"i2c_slave_sdk_ao", "i2c_slave_sda_ao",
 };
 
+static const char * const pwm_ao_a_3_groups[] = {
+	"pwm_ao_a_3",
+};
+
+static const char * const pwm_ao_a_6_groups[] = {
+	"pwm_ao_a_6",
+};
+
+static const char * const pwm_ao_a_12_groups[] = {
+	"pwm_ao_a_12",
+};
+
+static const char * const pwm_ao_b_groups[] = {
+	"pwm_ao_b",
+};
+
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
@@ -529,6 +597,13 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(uart_b),
 	FUNCTION(uart_c),
 	FUNCTION(eth),
+	FUNCTION(pwm_a_x),
+	FUNCTION(pwm_a_y),
+	FUNCTION(pwm_b),
+	FUNCTION(pwm_d),
+	FUNCTION(pwm_e),
+	FUNCTION(pwm_f_x),
+	FUNCTION(pwm_f_y),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
@@ -537,6 +612,10 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(uart_ao_b),
 	FUNCTION(i2c_ao),
 	FUNCTION(i2c_slave_ao),
+	FUNCTION(pwm_ao_a_3),
+	FUNCTION(pwm_ao_a_6),
+	FUNCTION(pwm_ao_a_12),
+	FUNCTION(pwm_ao_b),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
1.9.1



From linus.walleij at linaro.org  Mon Aug 22 06:51:54 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 22 Aug 2016 15:51:54 +0200
Subject: [PATCH v5 1/6] pinctrl: amlogic: gxbb: add the IR remote input pin
In-Reply-To: <20160820095424.636-2-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-2-martin.blumenstingl@googlemail.com>
Message-ID: <CACRpkda9z7gStMz6xLy2HPQo4tELq0BgZN0-ys22cgEBbRJJnw@mail.gmail.com>

On Sat, Aug 20, 2016 at 11:54 AM, Martin Blumenstingl
<martin.blumenstingl at googlemail.com> wrote:

> This adds the IR remote receiver to the AO domain devices.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> Reviewed-by: Kevin Hilman <khilman at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Mon Aug 22 06:52:33 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 22 Aug 2016 15:52:33 +0200
Subject: [PATCH v5 2/6] ARM64: dts: amlogic: add the input pin for the IR
 remote
In-Reply-To: <20160820095424.636-3-martin.blumenstingl@googlemail.com>
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-3-martin.blumenstingl@googlemail.com>
Message-ID: <CACRpkdauTrvWmv5iDa_QwkAS8M6ff_yyjBm0y_iV_sLoPPDdTg@mail.gmail.com>

On Sat, Aug 20, 2016 at 11:54 AM, Martin Blumenstingl
<martin.blumenstingl at googlemail.com> wrote:

> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

Acked-by: Linus Walleij <linus.walleij at linaro.org>

Merge this through the ARM SoC tree.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Mon Aug 22 07:02:35 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 22 Aug 2016 16:02:35 +0200
Subject: [PATCH 1/2] ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
In-Reply-To: <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
 <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdZuRwvS_p9D3Sx0avr+1mtCjfGFUX3fXjRRmYS19TYvxg@mail.gmail.com>

On Mon, Aug 22, 2016 at 2:54 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:

> Add support for PWM pins, for EE and AO domains.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

The $SUBJECT of this patch is titallyt wrong, it should be
just pinctrl: (something).

Should I fix it up or would you like to resend?

It looks nice otherwise.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Mon Aug 22 07:03:28 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 22 Aug 2016 16:03:28 +0200
Subject: [PATCH 2/2] ARM64: dts: meson-gxbb: Add PWM pinctrl nodes
In-Reply-To: <1471870450-11109-3-git-send-email-narmstrong@baylibre.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
 <1471870450-11109-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdZkttbwj7+80SQXxTMb2ETapRUH4irsCOu9P5VEkUeR6A@mail.gmail.com>

On Mon, Aug 22, 2016 at 2:54 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:

> Add DT nodes for PWMs in EE and AO domains.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Acked-by: Linus Walleij <linus.walleij at linaro.org>

Please merge this through the ARM SoC tree.

Yours,
Linus Walleij


From narmstrong at baylibre.com  Mon Aug 22 07:04:03 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 16:04:03 +0200
Subject: [PATCH 1/2] ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
In-Reply-To: <CACRpkdZuRwvS_p9D3Sx0avr+1mtCjfGFUX3fXjRRmYS19TYvxg@mail.gmail.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
 <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>
 <CACRpkdZuRwvS_p9D3Sx0avr+1mtCjfGFUX3fXjRRmYS19TYvxg@mail.gmail.com>
Message-ID: <ee4431d1-2f78-b698-76ca-8a3afff8d0ee@baylibre.com>

On 08/22/2016 04:02 PM, Linus Walleij wrote:
> On Mon, Aug 22, 2016 at 2:54 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> 
>> Add support for PWM pins, for EE and AO domains.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> 
> The $SUBJECT of this patch is titallyt wrong, it should be
> just pinctrl: (something).
> 
> Should I fix it up or would you like to resend?
> 
> It looks nice otherwise.
> 
> Yours,
> Linus Walleij
> 

Hi Linus,

Yes, sorry I missed the subject.

If you can fixup, it would be great !

Thanks,
Neil


From linus.walleij at linaro.org  Mon Aug 22 07:10:32 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 22 Aug 2016 16:10:32 +0200
Subject: [PATCH 1/2] ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
In-Reply-To: <ee4431d1-2f78-b698-76ca-8a3afff8d0ee@baylibre.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
 <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>
 <CACRpkdZuRwvS_p9D3Sx0avr+1mtCjfGFUX3fXjRRmYS19TYvxg@mail.gmail.com>
 <ee4431d1-2f78-b698-76ca-8a3afff8d0ee@baylibre.com>
Message-ID: <CACRpkdYnO-9hfDjtyLhDTQjkg1FGv+rRDVjt8GRmfs=V5V5ZdA@mail.gmail.com>

On Mon, Aug 22, 2016 at 4:04 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> On 08/22/2016 04:02 PM, Linus Walleij wrote:
>> On Mon, Aug 22, 2016 at 2:54 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>>
>>> Add support for PWM pins, for EE and AO domains.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>
>> The $SUBJECT of this patch is titallyt wrong, it should be
>> just pinctrl: (something).
>>
>> Should I fix it up or would you like to resend?
>>
>> It looks nice otherwise.
>>
>> Yours,
>> Linus Walleij
>>
>
> Hi Linus,
>
> Yes, sorry I missed the subject.
>
> If you can fixup, it would be great !

Hm I tried but the patch does not apply on my "devel" branch
in pinctrl. I chicken out and ask you to rebase it, there are a few
other patches to this driver in the devel branch.

Yours,
Linus Walleij


From narmstrong at baylibre.com  Mon Aug 22 07:11:37 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 16:11:37 +0200
Subject: [PATCH 1/2] ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
In-Reply-To: <CACRpkdYnO-9hfDjtyLhDTQjkg1FGv+rRDVjt8GRmfs=V5V5ZdA@mail.gmail.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
 <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>
 <CACRpkdZuRwvS_p9D3Sx0avr+1mtCjfGFUX3fXjRRmYS19TYvxg@mail.gmail.com>
 <ee4431d1-2f78-b698-76ca-8a3afff8d0ee@baylibre.com>
 <CACRpkdYnO-9hfDjtyLhDTQjkg1FGv+rRDVjt8GRmfs=V5V5ZdA@mail.gmail.com>
Message-ID: <585c50e0-8685-4c91-3360-990fe25cc7f0@baylibre.com>

On 08/22/2016 04:10 PM, Linus Walleij wrote:
> On Mon, Aug 22, 2016 at 4:04 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>> On 08/22/2016 04:02 PM, Linus Walleij wrote:
>>> On Mon, Aug 22, 2016 at 2:54 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>>>
>>>> Add support for PWM pins, for EE and AO domains.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>
>>> The $SUBJECT of this patch is titallyt wrong, it should be
>>> just pinctrl: (something).
>>>
>>> Should I fix it up or would you like to resend?
>>>
>>> It looks nice otherwise.
>>>
>>> Yours,
>>> Linus Walleij
>>>
>>
>> Hi Linus,
>>
>> Yes, sorry I missed the subject.
>>
>> If you can fixup, it would be great !
> 
> Hm I tried but the patch does not apply on my "devel" branch
> in pinctrl. I chicken out and ask you to rebase it, there are a few
> other patches to this driver in the devel branch.
> 
> Yours,
> Linus Walleij
> 

Ok no problem,

I'll repost.

Neil


From narmstrong at baylibre.com  Mon Aug 22 07:28:42 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 16:28:42 +0200
Subject: [PATCH 1/2] ARM64: dts: amlogic: gxbb: pinctrl: add pins for PWM
In-Reply-To: <CACRpkdYnO-9hfDjtyLhDTQjkg1FGv+rRDVjt8GRmfs=V5V5ZdA@mail.gmail.com>
References: <1471870450-11109-1-git-send-email-narmstrong@baylibre.com>
 <1471870450-11109-2-git-send-email-narmstrong@baylibre.com>
 <CACRpkdZuRwvS_p9D3Sx0avr+1mtCjfGFUX3fXjRRmYS19TYvxg@mail.gmail.com>
 <ee4431d1-2f78-b698-76ca-8a3afff8d0ee@baylibre.com>
 <CACRpkdYnO-9hfDjtyLhDTQjkg1FGv+rRDVjt8GRmfs=V5V5ZdA@mail.gmail.com>
Message-ID: <542e167e-f66e-551c-8140-bcc19a929ae8@baylibre.com>

On 08/22/2016 04:10 PM, Linus Walleij wrote:
> On Mon, Aug 22, 2016 at 4:04 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>> On 08/22/2016 04:02 PM, Linus Walleij wrote:
>>> On Mon, Aug 22, 2016 at 2:54 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>>>
>>>> Add support for PWM pins, for EE and AO domains.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>
>>> The $SUBJECT of this patch is titallyt wrong, it should be
>>> just pinctrl: (something).
>>>
>>> Should I fix it up or would you like to resend?
>>>
>>> It looks nice otherwise.
>>>
>>> Yours,
>>> Linus Walleij
>>>
>>
>> Hi Linus,
>>
>> Yes, sorry I missed the subject.
>>
>> If you can fixup, it would be great !
> 
> Hm I tried but the patch does not apply on my "devel" branch
> in pinctrl. I chicken out and ask you to rebase it, there are a few
> other patches to this driver in the devel branch.
> 
> Yours,
> Linus Walleij
> 

Hi,

This patch applies perfectly on the current kernel/git/linusw/linux-gpio.git devel branch at 7d9e59ce761f2ebe0bf57e6467cc13d932ee109b "gpio: wcove-gpio: add get_direction method".

When I rebase, the patch stays identical.

Neil


From narmstrong at baylibre.com  Mon Aug 22 07:40:58 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 16:40:58 +0200
Subject: [RESEND PATCH 0/2] pinctrl: meson-gxbb: Export pins for PWMs
Message-ID: <1471876860-5620-1-git-send-email-narmstrong@baylibre.com>

Add PWM pins in the meson-gxbb pinctrl driver and export then in the GXBB dtsi.

Resent rebased on git.linaro.org/people/linus.walleij/linux-pinctrl.git branch devel.

Neil Armstrong (2):
  pinctrl: meson-gxbb: add pins for PWM
  ARM64: dts: meson-gxbb: Add PWM pinctrl nodes

 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 77 ++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c  | 78 +++++++++++++++++++++++++++++
 2 files changed, 155 insertions(+)

-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 07:40:59 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 16:40:59 +0200
Subject: [RESEND PATCH 1/2] pinctrl: meson-gxbb: add pins for PWM
In-Reply-To: <1471876860-5620-1-git-send-email-narmstrong@baylibre.com>
References: <1471876860-5620-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471876860-5620-2-git-send-email-narmstrong@baylibre.com>

Add support for PWM pins, for EE and AO domains.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 78 ++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index 7eeb053..1c6ffb3 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -193,6 +193,14 @@ static const unsigned int eth_txd1_pins[]	= { PIN(GPIOZ_11, EE_OFF) };
 static const unsigned int eth_txd2_pins[]	= { PIN(GPIOZ_12, EE_OFF) };
 static const unsigned int eth_txd3_pins[]	= { PIN(GPIOZ_13, EE_OFF) };
 
+static const unsigned int pwm_a_x_pins[]	= { PIN(GPIOX_6, EE_OFF) };
+static const unsigned int pwm_a_y_pins[]	= { PIN(GPIOY_16, EE_OFF) };
+static const unsigned int pwm_b_pins[]		= { PIN(GPIODV_29, EE_OFF) };
+static const unsigned int pwm_d_pins[]		= { PIN(GPIODV_28, EE_OFF) };
+static const unsigned int pwm_e_pins[]		= { PIN(GPIOX_19, EE_OFF) };
+static const unsigned int pwm_f_x_pins[]	= { PIN(GPIOX_7, EE_OFF) };
+static const unsigned int pwm_f_y_pins[]	= { PIN(GPIOY_15, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -227,6 +235,11 @@ static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
 static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
 
+static const unsigned int pwm_ao_a_3_pins[]	= { PIN(GPIOAO_3, 0) };
+static const unsigned int pwm_ao_a_6_pins[]	= { PIN(GPIOAO_6, 0) };
+static const unsigned int pwm_ao_a_12_pins[]	= { PIN(GPIOAO_12, 0) };
+static const unsigned int pwm_ao_b_pins[]	= { PIN(GPIOAO_13, 0) };
+
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
 	GPIO_GROUP(GPIOZ_1, EE_OFF),
@@ -361,12 +374,17 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_rx_a,	4,	12),
 	GROUP(uart_cts_a,	4,	11),
 	GROUP(uart_rts_a,	4,	10),
+	GROUP(pwm_a_x,		3,	17),
+	GROUP(pwm_e,		2,	30),
+	GROUP(pwm_f_x,		3,	18),
 
 	/* Bank Y */
 	GROUP(uart_cts_c,	1,	19),
 	GROUP(uart_rts_c,	1,	18),
 	GROUP(uart_tx_c,	1,	17),
 	GROUP(uart_rx_c,	1,	16),
+	GROUP(pwm_a_y,		1,	21),
+	GROUP(pwm_f_y,		1,	20),
 
 	/* Bank Z */
 	GROUP(eth_mdio,		6,	1),
@@ -389,6 +407,8 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_rx_b,	2,	28),
 	GROUP(uart_cts_b,	2,	27),
 	GROUP(uart_rts_b,	2,	26),
+	GROUP(pwm_b,		3,	21),
+	GROUP(pwm_d,		3,	20),
 
 	/* Bank BOOT */
 	GROUP(emmc_nand_d07,	4,	30),
@@ -435,6 +455,10 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GROUP(i2c_slave_sck_ao, 0,	2),
 	GROUP(i2c_slave_sda_ao, 0,	1),
 	GROUP(remote_input_ao,	0,	0),
+	GROUP(pwm_ao_a_3,	0,	22),
+	GROUP(pwm_ao_a_6,	0,	18),
+	GROUP(pwm_ao_a_12,	0,	17),
+	GROUP(pwm_ao_b,		0,	3),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -502,6 +526,34 @@ static const char * const eth_groups[] = {
 	"eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
 };
 
+static const char * const pwm_a_x_groups[] = {
+	"pwm_a_x",
+};
+
+static const char * const pwm_a_y_groups[] = {
+	"pwm_a_y",
+};
+
+static const char * const pwm_b_groups[] = {
+	"pwm_b",
+};
+
+static const char * const pwm_d_groups[] = {
+	"pwm_d",
+};
+
+static const char * const pwm_e_groups[] = {
+	"pwm_e",
+};
+
+static const char * const pwm_f_x_groups[] = {
+	"pwm_f_x",
+};
+
+static const char * const pwm_f_y_groups[] = {
+	"pwm_f_y",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -526,6 +578,21 @@ static const char * const i2c_slave_ao_groups[] = {
 
 static const char * const remote_input_ao_groups[] = {
 	"remote_input_ao",
+
+static const char * const pwm_ao_a_3_groups[] = {
+	"pwm_ao_a_3",
+};
+
+static const char * const pwm_ao_a_6_groups[] = {
+	"pwm_ao_a_6",
+};
+
+static const char * const pwm_ao_a_12_groups[] = {
+	"pwm_ao_a_12",
+};
+
+static const char * const pwm_ao_b_groups[] = {
+	"pwm_ao_b",
 };
 
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
@@ -536,6 +603,13 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(uart_b),
 	FUNCTION(uart_c),
 	FUNCTION(eth),
+	FUNCTION(pwm_a_x),
+	FUNCTION(pwm_a_y),
+	FUNCTION(pwm_b),
+	FUNCTION(pwm_d),
+	FUNCTION(pwm_e),
+	FUNCTION(pwm_f_x),
+	FUNCTION(pwm_f_y),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
@@ -545,6 +619,10 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(i2c_ao),
 	FUNCTION(i2c_slave_ao),
 	FUNCTION(remote_input_ao),
+	FUNCTION(pwm_ao_a_3),
+	FUNCTION(pwm_ao_a_6),
+	FUNCTION(pwm_ao_a_12),
+	FUNCTION(pwm_ao_b),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 07:41:00 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 16:41:00 +0200
Subject: [RESEND PATCH 2/2] ARM64: dts: meson-gxbb: Add PWM pinctrl nodes
In-Reply-To: <1471876860-5620-1-git-send-email-narmstrong@baylibre.com>
References: <1471876860-5620-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471876860-5620-3-git-send-email-narmstrong@baylibre.com>

Add DT nodes for PWMs in EE and AO domains.

Acked-by: Linus Walleij <linus.walleij at linaro.org>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 77 +++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..9aeb88a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -203,6 +203,34 @@
 						function = "uart_ao";
 					};
 				};
+
+				pwm_ao_a_3_pins: pwm_ao_a_3 {
+					mux {
+						groups = "pwm_ao_a_3";
+						function = "pwm_ao_a_3";
+					};
+				};
+
+				pwm_ao_a_6_pins: pwm_ao_a_6 {
+					mux {
+						groups = "pwm_ao_a_6";
+						function = "pwm_ao_a_6";
+					};
+				};
+
+				pwm_ao_a_12_pins: pwm_ao_a_12 {
+					mux {
+						groups = "pwm_ao_a_12";
+						function = "pwm_ao_a_12";
+					};
+				};
+
+				pwm_ao_b_pins: pwm_ao_b {
+					mux {
+						groups = "pwm_ao_b";
+						function = "pwm_ao_b";
+					};
+				};
 			};
 
 			uart_AO: serial at 4c0 {
@@ -306,6 +334,55 @@
 						function = "eth";
 					};
 				};
+
+				pwm_a_x_pins: pwm_a_x {
+					mux {
+						groups = "pwm_a_x";
+						function = "pwm_a_x";
+					};
+				};
+
+				pwm_a_y_pins: pwm_a_y {
+					mux {
+						groups = "pwm_a_y";
+						function = "pwm_a_y";
+					};
+				};
+
+				pwm_b_pins: pwm_b {
+					mux {
+						groups = "pwm_b";
+						function = "pwm_b";
+					};
+				};
+
+				pwm_d_pins: pwm_d {
+					mux {
+						groups = "pwm_d";
+						function = "pwm_d";
+					};
+				};
+
+				pwm_e_pins: pwm_e {
+					mux {
+						groups = "pwm_e";
+						function = "pwm_e";
+					};
+				};
+
+				pwm_f_x_pins: pwm_f_x {
+					mux {
+						groups = "pwm_f_x";
+						function = "pwm_f_x";
+					};
+				};
+
+				pwm_f_y_pins: pwm_f_y {
+					mux {
+						groups = "pwm_f_y";
+						function = "pwm_f_y";
+					};
+				};
 			};
 		};
 
-- 
1.9.1



From arnd at arndb.de  Mon Aug 22 08:25:30 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 22 Aug 2016 17:25:30 +0200
Subject: [PATCH v2 1/4] net: dt-bindings: Document the new Meson8b and
 GXBB DWMAC bindings
In-Reply-To: <CAFBinCA0HWHR3UbVX-_wU14W0-KOr-BAf5Nyn1ocZdnYxojn2Q@mail.gmail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <7308700.atIMKyMFZU@wuerfel>
 <CAFBinCA0HWHR3UbVX-_wU14W0-KOr-BAf5Nyn1ocZdnYxojn2Q@mail.gmail.com>
Message-ID: <4041259.IszN4229Cj@wuerfel>

On Monday, August 22, 2016 2:04:49 PM CEST Martin Blumenstingl wrote:
> On Mon, Aug 22, 2016 at 1:55 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> > On Saturday, August 20, 2016 11:35:35 AM CEST Martin Blumenstingl wrote:
> >> +- reg: The first register range should be the one of the DWMAC
> >> +       controller. The second range is is for the Amlogic specific
> >> +       configuration (for example the PRG_ETHERNET register range
> >> +       on Meson8b and newer)
> >>
> > ...
> >
> >> +Example for GXBB:
> >> +       ethmac: ethernet at c9410000 {
> >> +               compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
> >> +               reg = <0x0 0xc9410000 0x0 0x10000>,
> >> +                       <0x0 0xc8834540 0x0 0x8>;
> >>
> >
> > The address "0xc8834540" suggests that this is part of a larger register
> > range that is used for various things, i.e. a "syscon" type of device.
> You are right, these are part of the cbus range (which is already
> defined in meson-gxbb.dtsi)
> 
> > How about making this a syscon reference rather than a "reg" address?
> The first version of my patch ([0]) used
> syscon_regmap_lookup_by_phandle. Maybe I did it wrong (and I should
> have passed the cbus syscon-node instead of defining a new one just
> for the 2x32bit PRG_ETHERNET registers).
> I am perfectly fine with either way - however it seems that some other
> dwmac glue implementations are also using a second set of resources
> (that doesn't automatically make it "correct" though).

It really depends on the kind of SoC. Some may have a suboptimal
binding, on some others there may be a distinct register area that
just contains a few additional registers for the dwmac.

	Arnd


From narmstrong at baylibre.com  Mon Aug 22 08:36:29 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 17:36:29 +0200
Subject: [PATCH v3 0/4] pwm: Add Amlogic Meson SoC PWM Controller
Message-ID: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>

Add support for the PWM controller found in Amlogic Meson SoCs.
This controller provides a dual PWM output with 4 selectable clock source
and a two level divider to achieve a better PWM range.

Currently Meson8b and GXBB SoCs are supported.

Changes since v2 at http://lkml.kernel.org/r/1471718083-11516-1-git-send-email-narmstrong at baylibre.com :
- Switch to apply() callback only, this fixes the setup sequence
- Implement get_state
- Make clock parent names as DT match data

Changes since v1 at http://lkml.kernel.org/r/1466173784-15625-1-git-send-email-narmstrong at baylibre.com :
- fix meson8b dtsi

Neil Armstrong (4):
  pwm: Add support for Meson PWM Controller
  dt-bindings: pwm: Add bindings for Meson PWM Controller
  ARM64: dts: meson-gxbb: Add Meson GXBB PWM Controller nodes
  ARM: dts: meson8b: Add Meson8b PWM Controller nodes

 .../devicetree/bindings/pwm/pwm-meson.txt          |  21 +
 arch/arm/boot/dts/meson8b.dtsi                     |  21 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  28 ++
 drivers/pwm/Kconfig                                |   9 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-meson.c                            | 528 +++++++++++++++++++++
 6 files changed, 608 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-meson.txt
 create mode 100644 drivers/pwm/pwm-meson.c

-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 08:36:30 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 17:36:30 +0200
Subject: [PATCH v3 1/4] pwm: Add support for Meson PWM Controller
In-Reply-To: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
References: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471880193-21879-2-git-send-email-narmstrong@baylibre.com>

Add support for the PWM controller found in the Amlogic SoCs.
This driver supports the Meson8b and GXBB SoCs.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pwm/Kconfig     |   9 +
 drivers/pwm/Makefile    |   1 +
 drivers/pwm/pwm-meson.c | 528 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 538 insertions(+)
 create mode 100644 drivers/pwm/pwm-meson.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 80a566a..bf01288 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -262,6 +262,15 @@ config PWM_LPSS_PLATFORM
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-lpss-platform.
 
+config PWM_MESON
+	tristate "Amlogic Meson PWM driver"
+	depends on ARCH_MESON
+	help
+	  The platform driver for Amlogic Meson PWM controller.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-meson.
+
 config PWM_MTK_DISP
 	tristate "MediaTek display PWM driver"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index feef1dd..1194c54 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_PWM_LPC32XX)	+= pwm-lpc32xx.o
 obj-$(CONFIG_PWM_LPSS)		+= pwm-lpss.o
 obj-$(CONFIG_PWM_LPSS_PCI)	+= pwm-lpss-pci.o
 obj-$(CONFIG_PWM_LPSS_PLATFORM)	+= pwm-lpss-platform.o
+obj-$(CONFIG_PWM_MESON)		+= pwm-meson.o
 obj-$(CONFIG_PWM_MTK_DISP)	+= pwm-mtk-disp.o
 obj-$(CONFIG_PWM_MXS)		+= pwm-mxs.o
 obj-$(CONFIG_PWM_OMAP_DMTIMER)	+= pwm-omap-dmtimer.o
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
new file mode 100644
index 0000000..56f3493
--- /dev/null
+++ b/drivers/pwm/pwm-meson.c
@@ -0,0 +1,528 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ * Copyright (C) 2014 Amlogic, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ * Copyright (C) 2014 Amlogic, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+
+#define REG_PWM_A	0x0
+#define REG_PWM_B	0x4
+#define PWM_HIGH_SHIFT	16
+
+#define REG_MISC_AB	0x8
+#define MISC_B_CLK_EN	BIT(23)
+#define MISC_A_CLK_EN	BIT(15)
+#define MISC_CLK_DIV_MASK	0x7f
+#define MISC_B_CLK_DIV_SHIFT	16
+#define MISC_A_CLK_DIV_SHIFT	8
+#define MISC_B_CLK_SEL_SHIFT	6
+#define MISC_A_CLK_SEL_SHIFT	4
+#define MISC_CLK_SEL_WIDTH	2
+#define MISC_B_EN	BIT(1)
+#define MISC_A_EN	BIT(0)
+
+#define PWM_NUM		2
+
+static const unsigned int mux_reg_shifts[PWM_NUM] = {
+	MISC_A_CLK_SEL_SHIFT, MISC_B_CLK_SEL_SHIFT
+};
+
+enum pwm_channel {
+	PWM_A = 0,
+	PWM_B,
+};
+
+struct meson_pwm_channel {
+	unsigned int pwm_hi;
+	unsigned int pwm_lo;
+	u8 pwm_pre_div;
+	int period;
+	int duty;
+	struct pwm_state state;
+};
+
+struct meson_pwm_chip {
+	struct platform_device *pdev;
+	struct pwm_chip chip;
+	void __iomem *base;
+	u8 inverter_mask;
+	spinlock_t lock;
+	struct clk *clk_parents[PWM_NUM];
+	struct clk_mux mux[PWM_NUM];
+	struct clk *clk[PWM_NUM];
+};
+
+struct meson_pwm_data {
+	const char *const *parent_names;
+};
+
+#define to_meson_pwm_chip(chip) \
+	container_of(chip, struct meson_pwm_chip, chip)
+
+static int meson_pwm_calc(struct meson_pwm_chip *pwm_data,
+			  struct meson_pwm_channel *pwm_chan,
+			  unsigned int id,
+			  unsigned int duty_ns,
+			  unsigned int period_ns)
+{
+	unsigned int pwm_pre_div;
+	unsigned int pwm_cnt;
+	unsigned int pwm_duty_cnt;
+	unsigned long fin_freq = -1;
+	unsigned long fin_ns;
+	unsigned int i = 0;
+
+	if (duty_ns > period_ns)
+		return -EINVAL;
+
+	if ((~(pwm_data->inverter_mask >> id) & 0x1))
+		duty_ns = period_ns - duty_ns;
+
+	if (period_ns == pwm_chan->period && duty_ns == pwm_chan->duty)
+		return 0;
+
+	switch (id) {
+	case PWM_A:
+		fin_freq = clk_get_rate(pwm_data->clk[0]);
+		break;
+	case PWM_B:
+		fin_freq = clk_get_rate(pwm_data->clk[1]);
+		break;
+	}
+	if (fin_freq <= 0) {
+		dev_err(pwm_data->chip.dev, "invalid source clock frequency\n");
+		return -EINVAL;
+	}
+	dev_dbg(pwm_data->chip.dev, "fin_freq: %luHz\n", fin_freq);
+	fin_ns = NSEC_PER_SEC / fin_freq;
+
+	/* Calc pre_div with the period */
+	for (i = 0; i < MISC_CLK_DIV_MASK; i++) {
+		pwm_pre_div = i;
+		pwm_cnt = DIV_ROUND_CLOSEST(period_ns,
+				fin_ns * (pwm_pre_div + 1));
+		dev_dbg(pwm_data->chip.dev, "fin_ns=%lu pre_div=%d cnt=%d\n",
+				fin_ns, pwm_pre_div, pwm_cnt);
+		if (pwm_cnt <= 0xffff)
+			break;
+	}
+	if (i == MISC_CLK_DIV_MASK) {
+		dev_err(pwm_data->chip.dev, "Unable to get period pre_div");
+		return -EINVAL;
+	}
+	dev_dbg(pwm_data->chip.dev, "period_ns=%d pre_div=%d pwm_cnt=%d\n",
+		period_ns, pwm_pre_div, pwm_cnt);
+
+	if (duty_ns == period_ns) {
+		pwm_chan->pwm_pre_div = pwm_pre_div;
+		pwm_chan->pwm_hi = pwm_cnt;
+		pwm_chan->pwm_lo = 0;
+	} else if (duty_ns == 0) {
+		pwm_chan->pwm_pre_div = pwm_pre_div;
+		pwm_chan->pwm_hi = 0;
+		pwm_chan->pwm_lo = pwm_cnt;
+	} else {
+		/* Then check is we can have the duty with the same pre_div */
+		pwm_duty_cnt = DIV_ROUND_CLOSEST(duty_ns,
+					fin_ns * (pwm_pre_div + 1));
+		if (pwm_cnt > 0xffff) {
+			dev_err(pwm_data->chip.dev, "Unable to get duty period, differences are too high");
+			return -EINVAL;
+		}
+		dev_dbg(pwm_data->chip.dev, "duty_ns=%d pre_div=%d pwm_cnt=%d\n",
+			duty_ns, pwm_pre_div, pwm_duty_cnt);
+
+		pwm_chan->pwm_pre_div = pwm_pre_div;
+		pwm_chan->pwm_hi = pwm_duty_cnt;
+		pwm_chan->pwm_lo = pwm_cnt - pwm_chan->pwm_hi;
+	}
+
+	return 0;
+}
+
+static void meson_pwm_get_state(struct pwm_chip *chip,
+				struct pwm_device *pwm,
+				struct pwm_state *state)
+{
+	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
+	unsigned int id = pwm->hwpwm;
+
+	if (!state)
+		return;
+
+	switch (id) {
+	case PWM_A:
+		if ((readl(pwm_data->base + REG_MISC_AB) & MISC_A_EN))
+			state->enabled = true;
+		break;
+	case PWM_B:
+		if ((readl(pwm_data->base + REG_MISC_AB) & MISC_B_EN))
+			state->enabled = true;
+		break;
+	}
+}
+
+static int meson_pwm_request(struct pwm_chip *chip,
+			     struct pwm_device *pwm)
+{
+	struct meson_pwm_channel *pwm_chan;
+
+	pwm_chan = devm_kzalloc(chip->dev, sizeof(*pwm_chan), GFP_KERNEL);
+	if (!pwm_chan)
+		return -ENOMEM;
+
+	meson_pwm_get_state(chip, pwm, &pwm_chan->state);
+
+	pwm_set_chip_data(pwm, pwm_chan);
+
+	return 0;
+}
+
+static void meson_pwm_free(struct pwm_chip *chip,
+			   struct pwm_device *pwm)
+{
+	devm_kfree(chip->dev, pwm_get_chip_data(pwm));
+	pwm_set_chip_data(pwm, NULL);
+}
+
+static void meson_pwm_enable(struct meson_pwm_chip *pwm_data,
+			     struct meson_pwm_channel *pwm_chan,
+			     unsigned int id)
+{
+	switch (id) {
+	case PWM_A:
+		writel((readl(pwm_data->base + REG_MISC_AB) &
+			~(MISC_CLK_DIV_MASK << MISC_A_CLK_DIV_SHIFT)) |
+			((pwm_chan->pwm_pre_div << MISC_A_CLK_DIV_SHIFT) |
+			 MISC_A_CLK_EN),
+			pwm_data->base + REG_MISC_AB);
+
+		writel((pwm_chan->pwm_hi << PWM_HIGH_SHIFT) |
+		       (pwm_chan->pwm_lo),
+		       pwm_data->base + REG_PWM_A);
+
+		writel(readl(pwm_data->base + REG_MISC_AB) | MISC_A_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	case PWM_B:
+		writel((readl(pwm_data->base + REG_MISC_AB) &
+			~(MISC_CLK_DIV_MASK << MISC_B_CLK_DIV_SHIFT)) |
+			((pwm_chan->pwm_pre_div << MISC_B_CLK_DIV_SHIFT) |
+			 MISC_B_CLK_EN),
+			pwm_data->base + REG_MISC_AB);
+
+		writel((pwm_chan->pwm_hi << PWM_HIGH_SHIFT) |
+		       (pwm_chan->pwm_lo),
+		       pwm_data->base + REG_PWM_B);
+
+		writel(readl(pwm_data->base + REG_MISC_AB) | MISC_B_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void meson_pwm_disable(struct meson_pwm_chip *pwm_data, unsigned int id)
+{
+	switch (id) {
+	case PWM_A:
+		writel(readl(pwm_data->base + REG_MISC_AB) & ~MISC_A_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	case PWM_B:
+		writel(readl(pwm_data->base + REG_MISC_AB) & ~MISC_B_EN,
+			pwm_data->base + REG_MISC_AB);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int meson_pwm_apply(struct pwm_chip *chip,
+			   struct pwm_device *pwm,
+			   struct pwm_state *state)
+{
+	struct meson_pwm_chip *pwm_data = to_meson_pwm_chip(chip);
+	struct meson_pwm_channel *pwm_chan = pwm_get_chip_data(pwm);
+	unsigned int id = pwm->hwpwm;
+	unsigned long flags;
+	int ret = 0;
+
+	if (!state)
+		return -EINVAL;
+
+	spin_lock_irqsave(&pwm_data->lock, flags);
+
+	if (!state->enabled) {
+		meson_pwm_disable(pwm_data, id);
+		pwm_chan->state.enabled = false;
+
+		goto out;
+	}
+
+	if (state->period != pwm_chan->state.period ||
+	    state->duty_cycle != pwm_chan->state.duty_cycle ||
+	    state->polarity != pwm_chan->state.polarity) {
+		if (pwm_chan->state.enabled) {
+			meson_pwm_disable(pwm_data, id);
+			pwm_chan->state.enabled = false;
+		}
+
+		if (state->polarity != pwm_chan->state.polarity) {
+			if (state->polarity == PWM_POLARITY_NORMAL)
+				pwm_data->inverter_mask |= BIT(id);
+			else
+				pwm_data->inverter_mask &= ~BIT(id);
+		}
+
+		ret = meson_pwm_calc(pwm_data, pwm_chan, id,
+				     state->duty_cycle,
+				     state->period);
+		if (ret)
+			goto out;
+
+		pwm_chan->state.polarity = state->polarity;
+		pwm_chan->state.period = state->period;
+		pwm_chan->state.duty_cycle = state->duty_cycle;
+	}
+
+	if (state->enabled && !pwm_chan->state.enabled) {
+		meson_pwm_enable(pwm_data, pwm_chan, id);
+		pwm_chan->state.enabled = true;
+	}
+
+out:
+	spin_unlock_irqrestore(&pwm_data->lock, flags);
+
+	return ret;
+}
+
+static const struct pwm_ops meson_pwm_ops = {
+	.request	= meson_pwm_request,
+	.free		= meson_pwm_free,
+	.apply		= meson_pwm_apply,
+	.get_state	= meson_pwm_get_state,
+	.owner		= THIS_MODULE,
+};
+
+static const char *const pwm_meson8b_parent_names[] = {
+	"xtal", "vid_pll", "fclk_div4", "fclk_div3", NULL
+};
+
+static const struct meson_pwm_data pwm_meson8b_data = {
+	.parent_names = pwm_meson8b_parent_names,
+};
+
+static const char *const pwm_gxbb_parent_names[] = {
+	"xtal", "hdmi_pll", "fclk_div4", "fclk_div3", NULL
+};
+
+static const struct meson_pwm_data pwm_gxbb_data = {
+	.parent_names = pwm_gxbb_parent_names,
+};
+
+static const struct of_device_id meson_pwm_matches[] = {
+	{ .compatible = "amlogic,meson8b-pwm", .data = &pwm_meson8b_data },
+	{ .compatible = "amlogic,meson-gxbb-pwm", .data = &pwm_gxbb_data },
+	{},
+};
+MODULE_DEVICE_TABLE(of, meson_pwm_matches);
+
+static int meson_pwm_mux_init(struct meson_pwm_chip *chip,
+			      const struct meson_pwm_data *data)
+{
+	struct device *dev = &chip->pdev->dev;
+	struct clk_init_data init;
+	char clk_name[255];
+	int ret;
+	int i;
+
+	for (i = 0 ; i < PWM_NUM ; ++i) {
+		sprintf(clk_name, "%s#mux%d",
+				of_node_full_name(dev->of_node), i);
+
+		init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+		init.ops = &clk_mux_ops;
+		init.flags = CLK_IS_BASIC;
+		init.parent_names = data->parent_names;
+		init.num_parents = 1 << MISC_CLK_SEL_WIDTH;
+
+		chip->mux[i].reg = chip->base + REG_MISC_AB;
+		chip->mux[i].shift = mux_reg_shifts[i];
+		chip->mux[i].mask = BIT(MISC_CLK_SEL_WIDTH) - 1;
+		chip->mux[i].flags = 0;
+		chip->mux[i].lock = &chip->lock;
+		chip->mux[i].table = NULL;
+		chip->mux[i].hw.init = &init;
+
+		chip->clk[i] = devm_clk_register(dev, &chip->mux[i].hw);
+		if (IS_ERR(chip->clk[i])) {
+			dev_err(dev, "Failed to register %s\n", clk_name);
+			return PTR_ERR(chip->clk[i]);
+		}
+
+		if (chip->clk_parents[i]) {
+			ret = clk_set_parent(chip->clk[i],
+					     chip->clk_parents[i]);
+			if (ret) {
+				dev_err(dev, "Failed to set %s parent\n",
+					clk_name);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int meson_pwm_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct device *dev = &pdev->dev;
+	struct meson_pwm_chip *chip;
+	struct resource *res;
+	int ret;
+
+	match = of_match_node(meson_pwm_matches, dev->of_node);
+	if (!match)
+		return -ENODEV;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	chip->pdev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	chip->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(chip->base))
+		return PTR_ERR(chip->base);
+
+	chip->clk_parents[0] = devm_clk_get(dev, "clkin0");
+	if (IS_ERR(chip->clk_parents[0])) {
+		if (PTR_ERR(chip->clk_parents[0]) == -EPROBE_DEFER)
+			return PTR_ERR(chip->clk_parents[0]);
+		chip->clk_parents[0] = NULL;
+	}
+
+	chip->clk_parents[1] = devm_clk_get(dev, "clkin1");
+	if (IS_ERR(chip->clk_parents[1])) {
+		if (PTR_ERR(chip->clk_parents[1]) == -EPROBE_DEFER)
+			return PTR_ERR(chip->clk_parents[1]);
+		chip->clk_parents[1] = NULL;
+	}
+
+	ret = meson_pwm_mux_init(chip, match->data);
+	if (ret)
+		return ret;
+
+	clk_prepare_enable(chip->clk[0]);
+	clk_prepare_enable(chip->clk[1]);
+
+	chip->chip.dev = dev;
+	chip->chip.ops = &meson_pwm_ops;
+	chip->chip.base = -1;
+	chip->chip.npwm = PWM_NUM;
+	chip->chip.of_xlate = of_pwm_xlate_with_flags;
+	chip->chip.of_pwm_n_cells = 3;
+	chip->inverter_mask = BIT(PWM_NUM) - 1;
+
+	ret = pwmchip_add(&chip->chip);
+	if (ret < 0) {
+		dev_err(dev, "failed to register PWM chip\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, chip);
+
+	return 0;
+}
+
+static int meson_pwm_remove(struct platform_device *pdev)
+{
+	struct meson_pwm_chip *chip = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&chip->chip);
+}
+
+static struct platform_driver meson_pwm_driver = {
+	.driver		= {
+		.name	= "meson-pwm",
+		.of_match_table = of_match_ptr(meson_pwm_matches),
+	},
+	.probe		= meson_pwm_probe,
+	.remove		= meson_pwm_remove,
+};
+module_platform_driver(meson_pwm_driver);
+
+MODULE_ALIAS("platform:meson-pwm");
+MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 08:36:31 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 17:36:31 +0200
Subject: [PATCH v3 2/4] dt-bindings: pwm: Add bindings for Meson PWM Controller
In-Reply-To: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
References: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471880193-21879-3-git-send-email-narmstrong@baylibre.com>

Add bindings for the Amlogic PWM Controller in Meson8b and GXBB SoCs.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 Documentation/devicetree/bindings/pwm/pwm-meson.txt | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-meson.txt

diff --git a/Documentation/devicetree/bindings/pwm/pwm-meson.txt b/Documentation/devicetree/bindings/pwm/pwm-meson.txt
new file mode 100644
index 0000000..e06aed0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-meson.txt
@@ -0,0 +1,21 @@
+Amlogic Meson PWM Controller
+=================================
+
+Required properties:
+- compatible: Shall contain "amlogic,meson8b-pwm" or "amlogic,meson-gxbb-pwm".
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
+  the cells format.
+
+Optional properties:
+- clocks: Could contain one or two parents clocks phandle for each of the two pwm channels.
+- clock-names: Could contain at least the "clkin0" and/or "clkin1" names.
+
+Example:
+pwm_ab: pwm at 8550 {
+	compatible = "amlogic,meson-gxbb-pwm";
+	reg = <0x0 0x08550 0x0 0x10>;
+	#pwm-cells = <3>;
+	status = "disabled";
+	clocks = <&xtal>, <&xtal>;
+	clock-names = "clkin0", "clkin1";
+}
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 08:36:32 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 17:36:32 +0200
Subject: [PATCH v3 3/4] ARM64: dts: meson-gxbb: Add Meson GXBB PWM Controller
 nodes
In-Reply-To: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
References: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471880193-21879-4-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..e3f4d36 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -153,6 +153,27 @@
 				status = "disabled";
 			};
 
+			pwm_ab: pwm at 8550 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_cd: pwm at 8650 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08650 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_ef: pwm at 86c0 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x086c0 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
 			uart_C: serial at 8700 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x8700 0x0 0x14>;
@@ -212,6 +233,13 @@
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			pwm_ab_AO: pwm at 550 {
+				compatible = "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x0550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
 		};
 
 		periphs: periphs at c8834000 {
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 22 08:36:33 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 22 Aug 2016 17:36:33 +0200
Subject: [PATCH v3 4/4] ARM: dts: meson8b: Add Meson8b PWM Controller nodes
In-Reply-To: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
References: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471880193-21879-5-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm/boot/dts/meson8b.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index fc4080d..41fd536 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -162,6 +162,27 @@
 			reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
 		};
 
+		pwm_ab: pwm at 8550 {
+			compatible = "amlogic,meson8b-pwm";
+			reg = <0xc1108550 0x10>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm_cd: pwm at 8650 {
+			compatible = "amlogic,meson8b-pwm";
+			reg = <0xc1108650 0x10>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pwm_ef: pwm at 86c0 {
+			compatible = "amlogic,meson8b-pwm";
+			reg = <0xc11086c0 0x10>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		pinctrl_cbus: pinctrl at c1109880 {
 			compatible = "amlogic,meson8b-cbus-pinctrl";
 			reg = <0xc1109880 0x10>;
-- 
1.9.1



From weiyj.lk at gmail.com  Mon Aug 22 09:08:21 2016
From: weiyj.lk at gmail.com (Wei Yongjun)
Date: Mon, 22 Aug 2016 16:08:21 +0000
Subject: [PATCH -next] clk: meson: Fix invalid use of sizeof in
 gxbb_aoclkc_probe()
Message-ID: <1471882101-22347-1-git-send-email-weiyj.lk@gmail.com>

From: Wei Yongjun <weiyongjun1 at huawei.com>

sizeof() when applied to a pointer typed expression gives the
size of the pointer, not that of the pointed data.

Signed-off-by: Wei Yongjun <weiyongjun1 at huawei.com>
---
 drivers/clk/meson/gxbb-aoclk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
index 61ef28a..b45c5fb 100644
--- a/drivers/clk/meson/gxbb-aoclk.c
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -142,7 +142,7 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct gxbb_aoclk_reset_controller *rstc;
 
-	rstc = devm_kzalloc(dev, sizeof(rstc), GFP_KERNEL);
+	rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
 	if (!rstc)
 		return -ENOMEM;
 





From martin.blumenstingl at googlemail.com  Mon Aug 22 14:39:30 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Mon, 22 Aug 2016 23:39:30 +0200
Subject: USB PHY documentation
Message-ID: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>

Hello,

last weekend I tried getting the USB PHY working on my GXBB device.
The simple part: resetting the USB part and enabling the clocks.
The tricky part: configuring the USB PHY registers

Unfortunately the public datasheet does not contain any information
about the USB PHY.
The reference driver does not contain many comments, the struct
members are using abbreviated names and it seems that a part of what
should be done by the PHY driver is part of the dwc driver
(usb_peri_reg changes were patched into it).
I am now wondering if someone can share some details from the datasheet.

I took my register #defines from the reference driver (and tried to
make them human readable): [0]
There are some USB_PHY_CLK_SEL_* definitions at the bottom which seem
interesting (at least for configuring REG_CONFIG_CLK_SEL, but
unfortunately I don't know if these are valid (for either meson8b or
gxbb)..

Symptoms are: dwc2's USB initialization is successful, but when I plug
in a device it's not being detected.
I *think* that my problem is that REG_ADP_BC_DRV_VBUS is a readonly
bit - it's set when I use the original firmware of my device, but I
cannot set it in my PHY driver.

In case anyone is interested how my changes look exactly, you can find
the code here: [1]

I also dumped the USB PHY registers from the original Android firmware
of my device in case anyone is interested:
phy0:
[0xc0000000] = 0x8000
[0xc0000004] = 0x1690500
[0xc0000008] = 0x0
[0xc000000c] = 0x8E18
[0xc0000010] = 0x0
[0xc0000014] = 0x80000
[0xc0000018] = 0x246613D
[0xc000001c] = 0x0

phy1:
[0xc0000020] = 0x8000
[0xc0000024] = 0x1690500
[0xc0000028] = 0x0
[0xc000002c] = 0x2010118
[0xc0000030] = 0x0
[0xc0000034] = 0x80000
[0xc0000038] = 0xE46613D
[0xc000003c] = 0x0

@Ben: did you get anywhere with your experiments on Meson8b (S805)?


Regards,
Martin


[0] https://github.com/150balbes/Amlogic_s905-kernel/blob/master/include/linux/amlogic/usb-meson8.h
[1] https://github.com/xdarklight/linux/commit/a1666af7fdb48734784fa368d568fd4209c5b125


From sboyd at codeaurora.org  Mon Aug 22 18:21:24 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 22 Aug 2016 18:21:24 -0700
Subject: [PATCH v2 2/2] MMC: meson: initial support for GXBB platforms
In-Reply-To: <20160803231843.23012-2-khilman@baylibre.com>
References: <20160803231843.23012-1-khilman@baylibre.com>
 <20160803231843.23012-2-khilman@baylibre.com>
Message-ID: <20160823012124.GQ6502@codeaurora.org>

On 08/03, Kevin Hilman wrote:
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7304d2e37a98..3762e46811f3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -972,6 +972,7 @@ F:	arch/arm/mach-meson/
>  F:	arch/arm/boot/dts/meson*
>  F:	arch/arm64/boot/dts/amlogic/
>  F: 	drivers/pinctrl/meson/
> +F:      drivers/mmc/host/meson*

Weird spacing here?

>  N:	meson
>  
>  ARM/Annapurna Labs ALPINE ARCHITECTURE
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 0aa484c10c0a..4c3d091f7548 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -332,6 +332,16 @@ config MMC_SDHCI_IPROC
>  
>  	  If unsure, say N.
>  
> +config MMC_MESON_GXBB
> +	tristate "Amlogic S905/GXBB SD/MMC Host Controller support"
> +	depends on ARCH_MESON && MMC
> +	help
> +	  This selects support for the Amlogic SD/MMC Host Controller
> +	  found on the S905/GXBB family of SoCs.  This controller is
> +	  MMC 5.1 compliant and support SD, eMMC and SDIO interfaces.

s/support/supports/

> +
> +	  If you have a controller with this interface, say Y here.
> +
>  config MMC_MOXART
>  	tristate "MOXART SD/MMC Host Controller support"
>  	depends on ARCH_MOXART && MMC
> diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
> new file mode 100644
> index 000000000000..10eac41cf31a
> --- /dev/null
> +++ b/drivers/mmc/host/meson-gxbb.c
> @@ -0,0 +1,918 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman at baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman at baylibre.com>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>

Unused?

> +#include <linux/init.h>
> +#include <linux/device.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/ioport.h>
> +#include <linux/regmap.h>

Unused?

> +#include <linux/spinlock.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/mmc/sdio.h>
> +#include <linux/mmc/slot-gpio.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +#define DRIVER_NAME "meson-gxbb-mmc"
> +
> +#define SD_EMMC_CLOCK 0x0
> +#define   CLK_DIV_SHIFT 0
> +#define   CLK_DIV_WIDTH 6
> +#define   CLK_DIV_MASK 0x3f
> +#define   CLK_DIV_MAX 63
> +#define   CLK_SRC_SHIFT 6
> +#define   CLK_SRC_WIDTH 2
> +#define   CLK_SRC_MASK 0x3
> +#define   CLK_SRC_XTAL 0   /* external crystal */
> +#define   CLK_SRC_XTAL_RATE 24000000
> +#define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
> +#define   CLK_SRC_PLL_RATE 1000000000
> +#define   CLK_PHASE_SHIFT 8
> +#define   CLK_PHASE_MASK 0x3
> +#define   CLK_PHASE_0 0
> +#define   CLK_PHASE_90 1
> +#define   CLK_PHASE_180 2
> +#define   CLK_PHASE_270 3
> +#define   CLK_ALWAYS_ON BIT(24)
> +
> +#define SD_EMMC_DElAY 0x4
> +#define SD_EMMC_ADJUST 0x8
> +#define SD_EMMC_CALOUT 0x10
> +#define SD_EMMC_START 0x40
> +#define   START_DESC_INIT BIT(0)
> +#define   START_DESC_BUSY BIT(1)
> +#define   START_DESC_ADDR_SHIFT 2
> +#define   START_DESC_ADDR_MASK (~0x3)
> +
> +#define SD_EMMC_CFG 0x44
> +#define   CFG_BUS_WIDTH_SHIFT 0
> +#define   CFG_BUS_WIDTH_MASK 0x3
> +#define   CFG_BUS_WIDTH_1 0x0
> +#define   CFG_BUS_WIDTH_4 0x1
> +#define   CFG_BUS_WIDTH_8 0x2
> +#define   CFG_DDR BIT(2)
> +#define   CFG_BLK_LEN_SHIFT 4
> +#define   CFG_BLK_LEN_MASK 0xf
> +#define   CFG_RESP_TIMEOUT_SHIFT 8
> +#define   CFG_RESP_TIMEOUT_MASK 0xf
> +#define   CFG_RC_CC_SHIFT 12
> +#define   CFG_RC_CC_MASK 0xf
> +#define   CFG_STOP_CLOCK BIT(22)
> +#define   CFG_CLK_ALWAYS_ON BIT(18)
> +#define   CFG_AUTO_CLK BIT(23)
> +
> +#define SD_EMMC_STATUS 0x48
> +#define   STATUS_BUSY BIT(31)
> +
> +#define SD_EMMC_IRQ_EN 0x4c
> +#define   IRQ_EN_MASK 0x3fff
> +#define   IRQ_RXD_ERR_SHIFT 0
> +#define   IRQ_RXD_ERR_MASK 0xff
> +#define   IRQ_TXD_ERR BIT(8)
> +#define   IRQ_DESC_ERR BIT(9)
> +#define   IRQ_RESP_ERR BIT(10)
> +#define   IRQ_RESP_TIMEOUT BIT(11)
> +#define   IRQ_DESC_TIMEOUT BIT(12)
> +#define   IRQ_END_OF_CHAIN BIT(13)
> +#define   IRQ_RESP_STATUS BIT(14)
> +#define   IRQ_SDIO BIT(15)
> +
> +#define SD_EMMC_CMD_CFG 0x50
> +#define SD_EMMC_CMD_ARG 0x54
> +#define SD_EMMC_CMD_DAT 0x58
> +#define SD_EMMC_CMD_RSP 0x5c
> +#define SD_EMMC_CMD_RSP1 0x60
> +#define SD_EMMC_CMD_RSP2 0x64
> +#define SD_EMMC_CMD_RSP3 0x68
> +
> +#define SD_EMMC_RXD 0x94
> +#define SD_EMMC_TXD 0x94
> +#define SD_EMMC_LAST_REG SD_EMMC_TXD
> +
> +#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
> +#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
> +#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
> +#define MUX_CLK_NUM_PARENTS 2
> +
> +struct meson_host {
> +	struct	device		*dev;
> +	struct	mmc_host	*mmc;
> +	struct	mmc_request	*mrq;
> +	struct	mmc_command	*cmd;
> +
> +	spinlock_t lock;
> +	void __iomem *regs;
> +#ifdef USE_REGMAP
> +	struct regmap *regmap;
> +#endif

Dead code?

> +	int irq;
> +	u32 ocr_mask;
> +	struct clk *core_clk;
> +	struct clk_mux mux;
> +	struct clk *mux_clk;
> +	struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
> +	unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
> +
> +	struct clk_divider cfg_div;
> +	struct clk *cfg_div_clk;
> +
> +	unsigned int bounce_buf_size;
> +	void *bounce_buf;
> +	dma_addr_t bounce_dma_addr;
> +
> +	unsigned long clk_rate;
> +	unsigned long clk_src_rate;
> +	unsigned short clk_src_div;
> +};
> +
> +#define reg_read(host, offset) readl(host->regs + offset)
> +#define reg_write(host, offset, val) writel(val, host->regs + offset)
> +
> +struct cmd_cfg {
> +	union {
> +		struct {
> +			u32 length:9;
> +			u32 block_mode:1;
> +			u32 r1b:1;
> +			u32 end_of_chain:1;
> +			u32 timeout:4; /* 2^timeout msec */
> +			u32 no_resp:1;
> +			u32 no_cmd:1;
> +			u32 data_io:1;
> +			u32 data_wr:1;
> +			u32 resp_nocrc:1;
> +			u32 resp_128:1;
> +			u32 resp_num:1;
> +			u32 data_num:1;
> +			u32 cmd_index:6;
> +			u32 error:1;
> +			u32 owner:1;

> +#define CFG_OWNER_CPU 1
> +#define CFG_OWNER_MMC 0
> +		};
> +		u32 val;

Does this need to be __le32 to handle endian swaps? I thought
bitfields weren't safe for things that are written to hardware,
but I can't seem to find any definitive email about that
anywhere.

> +	};
> +};
> +
> +struct sd_emmc_desc {
> +	struct cmd_cfg cmd_cfg;
> +	u32 cmd_arg;
> +	u32 cmd_data;
> +	u32 cmd_resp;

__le32?

> +};
> +#define CMD_DATA_MASK (~0x3)
> +#define CMD_DATA_BIG_ENDIAN BIT(1)
> +#define CMD_DATA_SRAM BIT(0)
> +#define CMD_RESP_MASK (~0x1)
> +#define CMD_RESP_SRAM BIT(0)
> +
> +static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
> +{
> +	struct mmc_host *mmc = host->mmc;
> +	int ret = 0;
> +	u32 cfg;
> +
> +	if (clk_rate) {
> +		if (WARN_ON(clk_rate > mmc->f_max))
> +			clk_rate = mmc->f_max;
> +		else if (WARN_ON(clk_rate < mmc->f_min))
> +			clk_rate = mmc->f_min;
> +	}
> +
> +	if (clk_rate == host->clk_rate)
> +		return 0;
> +
> +	/* stop clock */
> +	cfg = reg_read(host, SD_EMMC_CFG);
> +	if (!(cfg & CFG_STOP_CLOCK)) {
> +		cfg |= CFG_STOP_CLOCK;
> +		reg_write(host, SD_EMMC_CFG, cfg);
> +	}
> +
> +	dev_dbg(host->dev, "change clock rate %lu -> %lu\n",
> +		host->clk_rate, clk_rate);
> +	ret = clk_set_rate(host->cfg_div_clk, clk_rate);
> +	if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
> +		dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
> +			 clk_rate, clk_get_rate(host->cfg_div_clk), ret);
> +	else
> +		host->clk_rate = clk_rate;
> +
> +	/* (re)start clock, if non-zero */
> +	if (clk_rate) {
> +		cfg = reg_read(host, SD_EMMC_CFG);
> +		cfg &= ~CFG_STOP_CLOCK;
> +		reg_write(host, SD_EMMC_CFG, cfg);
> +	}
> +
> +	return ret;
> +}
> +
> +static int meson_mmc_clk_init(struct meson_host *host)
> +{
> +	struct clk_init_data init;
> +	char clk_name[32];
> +	int i, ret = 0;
> +	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
> +	unsigned int mux_parent_count = 0;
> +	const char *clk_div_parents[1];
> +	unsigned int f_min = UINT_MAX;
> +	u32 clk_reg, cfg;
> +
> +	/* get the mux parents from DT */

None of this looks DT specific (good).

> +	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
> +		char name[16];
> +
> +		snprintf(name, sizeof(name), "clkin%d", i);
> +		host->mux_parent[i] = devm_clk_get(host->dev, name);
> +		if (IS_ERR(host->mux_parent[i])) {
> +			ret = PTR_ERR(host->mux_parent[i]);
> +			if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
> +				dev_err(host->dev, "Missing clock %s\n", name);
> +			host->mux_parent[i] = NULL;
> +			return ret;
> +		}
> +
> +		host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
> +		mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
> +		mux_parent_count++;
> +		if (host->mux_parent_rate[i] < f_min)
> +			f_min = host->mux_parent_rate[i];
> +	}
> +
> +	/* cacluate f_min based on input clocks, and max divider value */
> +	if (f_min != UINT_MAX)
> +		f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
> +	else
> +		f_min = 4000000;  /* default min: 400 MHz */
> +	host->mmc->f_min = f_min;
> +
> +	/* create the mux */
> +	snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
> +	init.name = clk_name;
> +	init.ops = &clk_mux_ops;
> +	init.flags = CLK_IS_BASIC;

Do you need CLK_IS_BASIC? If not please drop it.

> +	init.parent_names = mux_parent_names;
> +	init.num_parents = mux_parent_count;
> +
> +	host->mux.reg = host->regs + SD_EMMC_CLOCK;
> +	host->mux.shift = CLK_SRC_SHIFT;
> +	host->mux.mask = CLK_SRC_MASK;
> +	host->mux.flags = 0;
> +	host->mux.table = NULL;
> +	host->mux.hw.init = &init;
> +
> +	host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);

Hmm I was hoping to get rid of devm_clk_register() and replace it
with devm_clk_hw_register() instead. All part of my grand plan to
split providers from consumers, but this driver is different in
the sense that it registers clks to provide to itself. Maybe we
should make __clk_create_clk() into a real clk provider API so
that we can use devm_clk_hw_register() here and then generate a
clk for this device from the hw structure.

> +	if (WARN_ON(PTR_ERR_OR_ZERO(host->mux_clk)))

NULL is a valid clk so I would expect to only see
WARN_ON(IS_ERR(host->mux_clk)) here.

> +		return PTR_ERR(host->mux_clk);
> +
> +	/* create the divider */
> +	snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
> +	init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
> +	clk_div_parents[0] = __clk_get_name(host->mux_clk);
> +	init.parent_names = clk_div_parents;
> +	init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +	host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
> +	host->cfg_div.shift = CLK_DIV_SHIFT;
> +	host->cfg_div.width = CLK_DIV_WIDTH;
> +	host->cfg_div.hw.init = &init;
> +	host->cfg_div.flags = CLK_DIVIDER_ONE_BASED |
> +		CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
> +
> +	host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
> +		return PTR_ERR(host->cfg_div_clk);
> +
> +	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> +	clk_reg = 0;
> +	clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
> +	clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
> +	clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
> +	clk_reg &= ~CLK_ALWAYS_ON;
> +	reg_write(host, SD_EMMC_CLOCK, clk_reg);
> +
> +	clk_prepare_enable(host->cfg_div_clk);

This can fail...

> +
> +	/* Ensure clock starts in "auto" mode, not "always on" */
> +	cfg = reg_read(host, SD_EMMC_CFG);
> +	cfg &= ~CFG_CLK_ALWAYS_ON;
> +	cfg |= CFG_AUTO_CLK;
> +	reg_write(host, SD_EMMC_CFG, cfg);
> +
> +	meson_mmc_clk_set(host, f_min);

This can fail too but we don't handle the error?

> +
> +	return ret;
> +}
> +
> +static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	u32 bus_width;
> +	u32 val, orig;
> +
> +	/*
> +	 * GPIO regulator, only controls switching between 1v8 and
> +	 * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON.
> +	 */
> +	switch (ios->power_mode) {
> +	case MMC_POWER_UP:
> +		if (!IS_ERR(mmc->supply.vmmc))
> +			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
> +	}
> +
> +	meson_mmc_clk_set(host, ios->clock);
> +
> +	/* Bus width */
> +	val = reg_read(host, SD_EMMC_CFG);
> +	switch (ios->bus_width) {
> +	case MMC_BUS_WIDTH_1:
> +		bus_width = CFG_BUS_WIDTH_1;
> +		break;
> +	case MMC_BUS_WIDTH_4:
> +		bus_width = CFG_BUS_WIDTH_4;
> +		break;
> +	case MMC_BUS_WIDTH_8:
> +		bus_width = CFG_BUS_WIDTH_8;
> +		break;
> +	default:
> +		dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n",
> +			ios->bus_width);
> +		bus_width = CFG_BUS_WIDTH_4;
> +		return;
> +	}
> +
> +	val = reg_read(host, SD_EMMC_CFG);
> +	orig = val;
> +
> +	val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT);
> +	val |= bus_width << CFG_BUS_WIDTH_SHIFT;
> +
> +	val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
> +	val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
> +
> +	val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT);
> +	val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
> +
> +	val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT);
> +	val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
> +
> +	reg_write(host, SD_EMMC_CFG, val);
> +
> +	if (val != orig)
> +		dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
> +			__func__, orig, val);
> +}
> +
> +static int meson_mmc_wait_busy(struct mmc_host *mmc, unsigned int timeout)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	u32 status;
> +	int i;
> +
> +	for (i = timeout; i > 0; i--) {
> +		status = reg_read(host, SD_EMMC_STATUS);
> +		if (!(status & STATUS_BUSY))
> +			break;
> +	};
> +
> +	return (timeout == 0);
> +}
> +
> +static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +	struct mmc_command *cmd = host->cmd;
> +	unsigned int loops = 0xfffff;

Perhaps this should be a value of time instead of raw loops? Who
knows how fast the CPU can run all those loops?

> +
> +	WARN_ON(host->mrq != mrq);
> +	if (cmd && !cmd->error)
> +		if (meson_mmc_wait_busy(mmc, loops))
> +			dev_warn(host->dev, "%s: timeout busy.\n", __func__);
> +
> +	host->mrq = NULL;
> +	host->cmd = NULL;
> +	mmc_request_done(host->mmc, mrq);
> +
> +	return 0;
> +}
> +
[...]
> +
> +static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +
> +	WARN_ON(host->mrq != NULL);
> +
> +	/* Stop execution */
> +	reg_write(host, SD_EMMC_START, 0);
> +
> +	/* clear, ack, enable all interrupts */
> +	reg_write(host, SD_EMMC_IRQ_EN, 0);
> +	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
> +	reg_write(host, SD_EMMC_IRQ_EN, IRQ_EN_MASK);
> +
> +	host->mrq = mrq;
> +
> +	if (meson_mmc_check_cmd(mmc, mrq->cmd))
> +		return;
> +
> +	if (mrq->sbc)
> +		meson_mmc_start_cmd(mmc, mrq->sbc);
> +	else
> +		meson_mmc_start_cmd(mmc, mrq->cmd);
> +}
> +
> +static int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +	struct meson_host *host = mmc_priv(mmc);
> +
> +	if (!cmd) {

This happens? 

> +		dev_dbg(host->dev, "%s: NULL command.\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (cmd->flags & MMC_RSP_136) {
> +		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP3);
> +		cmd->resp[1] = reg_read(host, SD_EMMC_CMD_RSP2);
> +		cmd->resp[2] = reg_read(host, SD_EMMC_CMD_RSP1);
> +		cmd->resp[3] = reg_read(host, SD_EMMC_CMD_RSP);
> +	} else if (cmd->flags & MMC_RSP_PRESENT) {
> +		cmd->resp[0] = reg_read(host, SD_EMMC_CMD_RSP);
> +	}
> +
> +	return 0;
> +}
> +
> +static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
> +{
> +	struct meson_host *host = dev_id;
> +	struct mmc_request *mrq = host->mrq;
> +	struct mmc_command *cmd = host->cmd;
> +	u32 irq_en, status, raw_status;
> +	irqreturn_t ret = IRQ_HANDLED;
> +
> +	if (WARN_ON(!host))
> +		return IRQ_NONE;
> +
> +	if (WARN_ON(!mrq))
> +		return IRQ_NONE;
> +
> +	if (WARN_ON(!cmd))
> +		return IRQ_NONE;

These can happen? Spurious interrupts abound? Ugh.

> +
> +	spin_lock(&host->lock);
> +	irq_en = reg_read(host, SD_EMMC_IRQ_EN);
> +	raw_status = reg_read(host, SD_EMMC_STATUS);
> +	status = raw_status & irq_en;
> +
> +	if (!status) {
> +		dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
> +			 raw_status, irq_en);
> +		ret = IRQ_NONE;
> +		goto out;
> +	}
> +
> +	cmd->error = 0;
> +	if (status & IRQ_RXD_ERR_MASK) {
> +		dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
> +		cmd->error = -EILSEQ;
> +	}
> +	if (status & IRQ_TXD_ERR) {
> +		dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
> +		cmd->error = -EILSEQ;
> +	}
> +	if (status & IRQ_DESC_ERR)
> +		dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
> +	if (status & IRQ_RESP_ERR) {
> +		dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
> +		cmd->error = -EILSEQ;
> +	}
> +	if (status & IRQ_RESP_TIMEOUT) {
> +		dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
> +		cmd->error = -ETIMEDOUT;
> +	}
> +	if (status & IRQ_DESC_TIMEOUT) {
> +		dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
> +		cmd->error = -ETIMEDOUT;
> +	}
> +	if (status & IRQ_SDIO)
> +		dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
> +
> +	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
> +		ret = IRQ_WAKE_THREAD;
> +	else  {
> +		dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
> +			 status, cmd->opcode, cmd->arg,
> +			 cmd->flags, mrq->stop ? 1 : 0);
> +		if (cmd->data) {
> +			struct mmc_data *data = cmd->data;
> +
> +			dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)",
> +				 data->blksz, data->blocks, data->flags,
> +				 data->flags & MMC_DATA_WRITE ? "write" : "",
> +				 data->flags & MMC_DATA_READ ? "read" : "");
> +		}
> +	}
> +
> +out:
> +	/* ack all (enabled) interrupts */
> +	reg_write(host, SD_EMMC_STATUS, status);
> +
> +	if (ret == IRQ_HANDLED) {
> +		meson_mmc_read_resp(host->mmc, cmd);
> +		meson_mmc_request_done(host->mmc, cmd->mrq);
> +	}
> +
> +	spin_unlock(&host->lock);
> +	return ret;
> +}
> +
> +static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
> +{
> +	struct meson_host *host = dev_id;
> +	struct mmc_request *mrq = host->mrq;
> +	struct mmc_command *cmd = host->cmd;
> +	struct mmc_data *data;
> +

Drop that newline?

> +	unsigned int xfer_bytes;
> +	int ret = IRQ_HANDLED;
> +
> +	if (WARN_ON(!mrq))
> +		ret = IRQ_NONE;
> +
> +	if (WARN_ON(!cmd))
> +		ret = IRQ_NONE;
> +
> +	data = cmd->data;
> +	if (data) {
> +		xfer_bytes = data->blksz * data->blocks;
> +		if (data->flags & MMC_DATA_READ) {
> +			WARN_ON(xfer_bytes > host->bounce_buf_size);
> +			sg_copy_from_buffer(data->sg, data->sg_len,
> +					    host->bounce_buf, xfer_bytes);
> +			data->bytes_xfered = xfer_bytes;
> +		}
> +	}
> +
> +	meson_mmc_read_resp(host->mmc, cmd);
> +	if (!data || !data->stop || mrq->sbc)
> +		meson_mmc_request_done(host->mmc, mrq);
> +	else
> +		meson_mmc_start_cmd(host->mmc, data->stop);
> +
> +	return ret;
> +}
> +
> +/*
> + * NOTE: we only need this until the GPIO/pinctrl driver can handle
> + * interrupts.  For now, the MMC core will use this for polling.
> + */
> +static int meson_mmc_get_cd(struct mmc_host *mmc)
> +{
> +	int status = mmc_gpio_get_cd(mmc);
> +
> +	if (status == -ENOSYS)
> +		return 1; /* assume present */
> +
> +	return status;
> +}
> +
> +static struct mmc_host_ops meson_mmc_ops = {

const?

> +	.request	= meson_mmc_request,
> +	.set_ios	= meson_mmc_set_ios,
> +	.get_cd         = meson_mmc_get_cd,
> +};
> +
> +static int meson_mmc_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct resource *res;
> +	struct meson_host *host;
> +	struct mmc_host *mmc;
> +	int ret;
> +
> +	mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
> +	if (!mmc)
> +		return -ENOMEM;
> +	host = mmc_priv(mmc);
> +	host->mmc = mmc;
> +	host->dev = &pdev->dev;
> +	dev_set_drvdata(&pdev->dev, host);
> +
> +	spin_lock_init(&host->lock);
> +
> +	host->core_clk = devm_clk_get(&pdev->dev, "core");
> +	if (IS_ERR(host->core_clk)) {
> +		ret = PTR_ERR(host->core_clk);
> +		if (ret == -EPROBE_DEFER)
> +			dev_dbg(&pdev->dev,
> +				"Missing core clock.  EPROBE_DEFER\n");
> +		else
> +			dev_err(&pdev->dev,
> +				"Unable to get core clk (ret=%d).\n", ret);
> +		goto free_host;
> +	}
> +
> +	/* Voltage supply */
> +	mmc_of_parse_voltage(np, &host->ocr_mask);
> +	ret = mmc_regulator_get_supply(mmc);
> +	if (ret == -EPROBE_DEFER) {
> +		dev_dbg(&pdev->dev, "Missing regulator: EPROBE_DEFER");
> +		goto free_host;
> +	}
> +
> +	if (!mmc->ocr_avail)
> +		mmc->ocr_avail = host->ocr_mask;
> +
> +	ret = mmc_of_parse(mmc);
> +	if (ret) {
> +		dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
> +		goto free_host;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		ret = -ENODEV;
> +		goto free_host;
> +	}

This if can be dropped and go right into devm_ioremap_resource().

> +	host->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(host->regs)) {
> +		ret = PTR_ERR(host->regs);
> +		goto free_host;
> +	}
> +
> +	host->irq = platform_get_irq(pdev, 0);
> +	if (host->irq == 0) {
> +		dev_err(&pdev->dev, "failed to get interrupt resource.\n");
> +		ret = -EINVAL;
> +		goto free_host;
> +	}
> +
> +	ret = devm_request_threaded_irq(&pdev->dev, host->irq,
> +					meson_mmc_irq, meson_mmc_irq_thread,
> +					IRQF_SHARED, DRIVER_NAME, host);
> +	if (ret)
> +		goto free_host;
> +
> +	/* data bounce buffer */
> +	host->bounce_buf_size = SZ_512K;
> +	host->bounce_buf =
> +		dma_alloc_coherent(host->dev, host->bounce_buf_size,
> +				   &host->bounce_dma_addr, GFP_KERNEL);
> +	if (host->bounce_buf == NULL) {
> +		dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
> +		ret = -ENOMEM;
> +		goto free_host;
> +	}
> +
> +	clk_prepare_enable(host->core_clk);

This can fail.

> +
> +	ret = meson_mmc_clk_init(host);
> +	if (ret)
> +		goto free_host;
> +
> +	/* Stop execution */
> +	reg_write(host, SD_EMMC_START, 0);
> +
> +	/* clear, ack, enable all interrupts */
> +	reg_write(host, SD_EMMC_IRQ_EN, 0);
> +	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);

Shouldn't we do this before requesting the interrupt?

> +
> +	mmc->ops = &meson_mmc_ops;
> +	mmc_add_host(mmc);
> +
> +	return 0;
> +
> +free_host:
> +	dev_dbg(host->dev, "Failed to probe: ret=%d\n", ret);
> +	if (host->core_clk)
> +		clk_disable_unprepare(host->core_clk);
> +	mmc_free_host(mmc);
> +	return ret;
> +}
> +

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


From narmstrong at baylibre.com  Tue Aug 23 00:58:14 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 09:58:14 +0200
Subject: [PATCH -next] clk: meson: Fix invalid use of sizeof in
 gxbb_aoclkc_probe()
In-Reply-To: <1471882101-22347-1-git-send-email-weiyj.lk@gmail.com>
References: <1471882101-22347-1-git-send-email-weiyj.lk@gmail.com>
Message-ID: <f0eeb1b0-5572-506d-0029-30b676c15a57@baylibre.com>

On 08/22/2016 06:08 PM, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1 at huawei.com>
> 
> sizeof() when applied to a pointer typed expression gives the
> size of the pointer, not that of the pointed data.
> 
> Signed-off-by: Wei Yongjun <weiyongjun1 at huawei.com>
> ---
>  drivers/clk/meson/gxbb-aoclk.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
> index 61ef28a..b45c5fb 100644
> --- a/drivers/clk/meson/gxbb-aoclk.c
> +++ b/drivers/clk/meson/gxbb-aoclk.c
> @@ -142,7 +142,7 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct gxbb_aoclk_reset_controller *rstc;
>  
> -	rstc = devm_kzalloc(dev, sizeof(rstc), GFP_KERNEL);
> +	rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
>  	if (!rstc)
>  		return -ENOMEM;
>  
> 
> 
> 

Aww, my bad.

Acked-by: Neil Armstrong <narmstrong at baylibre.com>

Also :
Fixes: f8c11f79912d ("clk: meson: Add GXBB AO Clock and Reset controller driver")


From narmstrong at baylibre.com  Tue Aug 23 01:00:57 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:00:57 +0200
Subject: [RESEND PATCH 1/2] pinctrl: meson-gxbb: add pins for PWM
In-Reply-To: <1471876860-5620-2-git-send-email-narmstrong@baylibre.com>
References: <1471876860-5620-1-git-send-email-narmstrong@baylibre.com>
 <1471876860-5620-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <45c22d0c-9cfd-b0a0-4499-6b306dfdcdd5@baylibre.com>

On 08/22/2016 04:40 PM, Neil Armstrong wrote:
> Add support for PWM pins, for EE and AO domains.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 78 ++++++++++++++++++++++++++++++
>  1 file changed, 78 insertions(+)
> 
> diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
> index 7eeb053..1c6ffb3 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
> +++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c

[...]

>  static const char * const gpio_aobus_groups[] = {
>  	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
>  	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
> @@ -526,6 +578,21 @@ static const char * const i2c_slave_ao_groups[] = {
>  
>  static const char * const remote_input_ao_groups[] = {
>  	"remote_input_ao",
> +

Linus,

Well, I missed my rebase, I'll post a v2 to fix that.

Neil

> +static const char * const pwm_ao_a_3_groups[] = {
> +	"pwm_ao_a_3",
> +};
> +
> +static const char * const pwm_ao_a_6_groups[] = {
> +	"pwm_ao_a_6",
> +};
> +
> +static const char * const pwm_ao_a_12_groups[] = {
> +	"pwm_ao_a_12",
> +};
> +
> +static const char * const pwm_ao_b_groups[] = {
> +	"pwm_ao_b",
>  };
>  
>  static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
> @@ -536,6 +603,13 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
>  	FUNCTION(uart_b),
>  	FUNCTION(uart_c),
>  	FUNCTION(eth),
> +	FUNCTION(pwm_a_x),
> +	FUNCTION(pwm_a_y),
> +	FUNCTION(pwm_b),
> +	FUNCTION(pwm_d),
> +	FUNCTION(pwm_e),
> +	FUNCTION(pwm_f_x),
> +	FUNCTION(pwm_f_y),
>  };
>  
>  static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
> @@ -545,6 +619,10 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
>  	FUNCTION(i2c_ao),
>  	FUNCTION(i2c_slave_ao),
>  	FUNCTION(remote_input_ao),
> +	FUNCTION(pwm_ao_a_3),
> +	FUNCTION(pwm_ao_a_6),
> +	FUNCTION(pwm_ao_a_12),
> +	FUNCTION(pwm_ao_b),
>  };
>  
>  static struct meson_bank meson_gxbb_periphs_banks[] = {
> 



From narmstrong at baylibre.com  Tue Aug 23 01:09:26 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:09:26 +0200
Subject: [PATCH 02/13] scpi: Add alternative legacy structures and macros
In-Reply-To: <2b345fec-4dbd-2144-cd34-d8451bb314c0@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-3-git-send-email-narmstrong@baylibre.com>
 <2b345fec-4dbd-2144-cd34-d8451bb314c0@arm.com>
Message-ID: <d6b03881-8afc-051d-6cab-01f95640526e@baylibre.com>

On 08/18/2016 07:16 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:10, Neil Armstrong wrote:
>> In order to support the legacy SCPI protocol variant, add back the structures
>> and macros that varies against the final specification.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>> I checked against Amlogic implementation documentation and on-device, the channel selection
>> via legacy_scpi_get_chan() is needed and fails without it.
>> The sender_id is not needed so it was dropped.
>>
>>  drivers/firmware/arm_scpi.c | 84 +++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 84 insertions(+)
>>
>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>> index 403783a..0bb6134 100644
>> --- a/drivers/firmware/arm_scpi.c
>> +++ b/drivers/firmware/arm_scpi.c
> 
> [...]
> 
>> @@ -183,6 +224,11 @@ struct scpi_shared_mem {
>>      u8 payload[0];
>>  } __packed;
>>
>> +struct legacy_scpi_shared_mem {
>> +    __le32 status;
>> +    u8 payload[0];
>> +} __packed;
>> +
>>  struct scp_capabilities {
>>      __le32 protocol_version;
>>      __le32 event_version;
>> @@ -208,6 +254,12 @@ struct clk_set_value {
>>      __le32 rate;
>>  } __packed;
>>
>> +struct legacy_clk_set_value {
>> +    __le32 rate;
>> +    __le16 id;
>> +    __le16 reserved;
>> +} __packed;
>> +
>>  struct dvfs_info {
>>      __le32 header;
>>      struct {
>> @@ -237,6 +289,10 @@ struct sensor_value {
>>      __le32 hi_val;
>>  } __packed;
>>
>> +struct legacy_sensor_value {
>> +    __le32 val;
>> +} __packed;
>> +
> 
> Not required, new one is backward compatible. Otherwise this patch looks
> fine.

Indeed, will use the non-legacy structure.

Thanks,
Neil



From narmstrong at baylibre.com  Tue Aug 23 01:15:04 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:15:04 +0200
Subject: [PATCH 03/13] scpi: Add legacy send, prepare and handle remote
 functions
In-Reply-To: <b88c0ffc-09d2-4138-3007-b1e28c955cce@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-4-git-send-email-narmstrong@baylibre.com>
 <b88c0ffc-09d2-4138-3007-b1e28c955cce@arm.com>
Message-ID: <3d384710-c2c1-974f-c217-a2198d98ea22@baylibre.com>

On 08/19/2016 06:13 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:10, Neil Armstrong wrote:
>> In order to support the legacy SCPI procotol, add specific message_send,
>> prepare_tx and handle_remote functions since the legacy procotol
>> do not support message queuing and does not store the command word in the
>> tx_payload data.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/firmware/arm_scpi.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 69 insertions(+)
>>
>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>> index 0bb6134..50b1297 100644
>> --- a/drivers/firmware/arm_scpi.c
>> +++ b/drivers/firmware/arm_scpi.c
>> @@ -202,6 +202,7 @@ struct scpi_chan {
>>      spinlock_t rx_lock; /* locking for the rx pending list */
>>      struct mutex xfers_lock;
>>      u8 token;
>> +    struct scpi_xfer *t;
>>  };
>>
>>  struct scpi_drvinfo {
>> @@ -364,6 +365,23 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
>>      scpi_process_cmd(ch, cmd);
>>  }
>>
>> +static void legacy_scpi_handle_remote_msg(struct mbox_client *c, void *__msg)
>> +{
>> +    struct scpi_chan *ch =
>> +        container_of(c, struct scpi_chan, cl);
>> +    struct legacy_scpi_shared_mem *mem = ch->rx_payload;
>> +    unsigned int len;
>> +
>> +    len = ch->t->rx_len;
>> +
>> +    ch->t->status = le32_to_cpu(mem->status);
>> +
>> +    if (len)
>> +        memcpy_fromio(ch->t->rx_buf, mem->payload, len);
>> +
>> +    complete(&ch->t->done);
>> +}
>> +
>>  static void scpi_tx_prepare(struct mbox_client *c, void *msg)
>>  {
>>      unsigned long flags;
>> @@ -384,6 +402,15 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
>>      mem->command = cpu_to_le32(t->cmd);
>>  }
>>
>> +static void legacy_scpi_tx_prepare(struct mbox_client *c, void *__msg)
>> +{
>> +    struct scpi_chan *ch =
>> +        container_of(c, struct scpi_chan, cl);
>> +
>> +    if (ch->t->tx_buf && ch->t->tx_len)
>> +        memcpy_toio(ch->tx_payload, ch->t->tx_buf, ch->t->tx_len);
> 
> 
> I see that you are not using the list. Any particular reason for that ?
> 
> IMO, that *might* help to reuse more code, but I may be wrong. Let's see
> Some commands like DVFS take more time compared to simple query type of
> commands. Queuing does help there instead of blocking the channel until
> the receipt of response.

I'll like to use the list, but, the "cmd" value is not stored in the shared tx
memory, so we cannot recover the original tranfer from reading the tx memory cmd.

This is why I added a "struct scpi_xfer *t;" in the scpi_chan structure to store
the current transfer.

> 
>> +}
>> +
>>  static int legacy_high_priority_cmds[] = {
>>      LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
>>      LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
>> @@ -434,6 +461,48 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
>>      mutex_unlock(&ch->xfers_lock);
>>  }
>>
>> +static int legacy_scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
>> +                void *rx_buf, unsigned int rx_len)
>> +{
>> +    int ret;
>> +    u8 chan;
>> +    struct scpi_xfer *msg;
>> +    struct scpi_chan *scpi_chan;
>> +
>> +    chan = legacy_scpi_get_chan(cmd);
>> +    scpi_chan = scpi_info->channels + chan;
>> +
>> +    msg = get_scpi_xfer(scpi_chan);
>> +    if (!msg)
>> +        return -ENOMEM;
>> +
>> +    mutex_lock(&scpi_chan->xfers_lock);
>> +
> 
> May be you can copy msg->cmd to msg->slot and that may help to reuse
> more code or worst-case keep them aligned.

Yes, it could be. But since the msg is not reused bu the tx_prepare and handle_response,
we can pass anything here.
And for the rockchip case, we must pass an xfer unrelated pointer here since they need
a specially crafted memory structure for the mailbox.

> 
>> +    msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
>> +    msg->tx_buf = tx_buf;
>> +    msg->tx_len = tx_len;
>> +    msg->rx_buf = rx_buf;
>> +    msg->rx_len = rx_len;
>> +    init_completion(&msg->done);
>> +    scpi_chan->t = msg;
>> +
>> +    ret = mbox_send_message(scpi_chan->chan, &msg->cmd);
> 
> If slot is initialized to cmd, then you can pass msg itself above.
> Then you can evaluate how much this function deviates from
> scpi_send_message and try to re-use.

The function deviates quite a lot since the queing is not used.

> 
>> +    if (ret < 0)
>> +        goto out;
>> +
>> +    if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
>> +        ret = -ETIMEDOUT;
>> +    else
>> +        /* first status word */
>> +        ret = msg->status;
>> +out:
>> +    mutex_unlock(&scpi_chan->xfers_lock);
>> +
>> +    put_scpi_xfer(msg, scpi_chan);
>> +    /* SCPI error codes > 0, translate them to Linux scale*/
>> +    return ret > 0 ? scpi_to_linux_errno(ret) : ret;
>> +}
>> +
>>  static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
>>                     void *rx_buf, unsigned int rx_len, bool extn)
>>  {
>>
> 
> [Nit]: Not sure if we need this as a separate patch. It might just
> generate warnings, anyways we can merge into one later.

I'll prefer to have functionnaly separate patches for now to clarify the changes.
I'll eventually merge them for the final apply if needed.

Thanks,
Neil



From narmstrong at baylibre.com  Tue Aug 23 01:19:43 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:19:43 +0200
Subject: [PATCH 04/13] scpi: Add legacy SCP functions calling
 legacy_scpi_send_message
In-Reply-To: <fe6919a2-a1dc-f056-9480-3248dc9315dc@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-5-git-send-email-narmstrong@baylibre.com>
 <fe6919a2-a1dc-f056-9480-3248dc9315dc@arm.com>
Message-ID: <53093fb5-22e2-3c17-3345-50c7e9df7089@baylibre.com>

On 08/19/2016 06:22 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:10, Neil Armstrong wrote:
>> In order to support legacy SCP functions from kernel-wide driver, add legacy
>> functions using the legacy command enums and calling legacy_scpi_send_message.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/firmware/arm_scpi.c | 118 ++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 118 insertions(+)
>>
>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>> index 50b1297..bb9965f 100644
>> --- a/drivers/firmware/arm_scpi.c
>> +++ b/drivers/firmware/arm_scpi.c
>> @@ -578,6 +578,8 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
>>      return ret;
>>  }
>>
>> +/* scpi_clk_get_range not available for legacy */
>> +
>>  static unsigned long scpi_clk_get_val(u16 clk_id)
>>  {
>>      int ret;
>> @@ -589,6 +591,18 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
>>      return ret ? ret : le32_to_cpu(clk.rate);
>>  }
>>
>> +static unsigned long legacy_scpi_clk_get_val(u16 clk_id)
>> +{
>> +    int ret;
>> +    struct clk_get_value clk;
>> +    __le16 le_clk_id = cpu_to_le16(clk_id);
>> +
>> +    ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
>> +                       &le_clk_id, sizeof(le_clk_id),
>> +                       &clk, sizeof(clk));
>> +    return ret ? ret : le32_to_cpu(clk.rate);
>> +}
>> +
>>  static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>>  {
>>      int stat;
>> @@ -601,6 +615,19 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>>                   &stat, sizeof(stat));
>>  }
>>
>> +static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
>> +{
>> +    int stat;
>> +    struct legacy_clk_set_value clk = {
>> +        .id = cpu_to_le16(clk_id),
>> +        .rate = cpu_to_le32(rate)
>> +    };
>> +
>> +    return legacy_scpi_send_message(LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
>> +                    &clk, sizeof(clk),
>> +                    &stat, sizeof(stat));
> 
> Except this one which has a different structure format, why do we need
> to define legacy versions of other functions ? Can't we play with
> function pointer or have a boolean in drvinfo structure and use then in
> the existing functions as I had shown in one of the earlier emails.
> 

The main problem is that the command indexes deviates starting at
SCPI_CMD_SET_CSS_PWR_STATE, I'll be pleased to know how to implement it.

Should I add a test :
if (scpi_drvinfo->is_legacy)
	legacy_scpi_send_message(...)
else
	scpi_send_message(...)

In each function ?

My strategy was to leave the "final" function untouched ans provide
alternatives to legacy.
I can add this "is_legacy" if/else instead of ops structures.

Please tell me how you'll implement this, so I'll adapt the merge.

Neil


From narmstrong at baylibre.com  Tue Aug 23 01:20:28 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:20:28 +0200
Subject: [PATCH 05/13] scpi: move of_match table before probe functions
In-Reply-To: <def54975-8014-a326-6f82-8953740e520c@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-6-git-send-email-narmstrong@baylibre.com>
 <def54975-8014-a326-6f82-8953740e520c@arm.com>
Message-ID: <833d9cf4-9eca-a8b5-96d5-5ccab159929e@baylibre.com>

On 08/19/2016 06:24 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:10, Neil Armstrong wrote:
>> Move the of_match table to prapre adding new compatible strings, with
>> match data in order to be used by the probe function.
>>
> 
> I understand the need of this change, but can be part of the patch
> introducing the need for this.
> 

Yes, but I did not want to pollute the next patch, I'll merge them for v2.

Neil


From narmstrong at baylibre.com  Tue Aug 23 01:22:25 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:22:25 +0200
Subject: [PATCH 06/13] scpi: add priv_scpi_ops and fill legacy structure
In-Reply-To: <5c89a4e9-0100-0c67-1d6c-07651649172a@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-7-git-send-email-narmstrong@baylibre.com>
 <5c89a4e9-0100-0c67-1d6c-07651649172a@arm.com>
Message-ID: <a0c9c4bc-cd83-c2e7-bfab-b8d24c886349@baylibre.com>

On 08/19/2016 06:39 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:10, Neil Armstrong wrote:
>> In order to use the legacy functions variants, add a new priv_scpi_ops
>> structure that will contain the internal alterne functions and then use these
>> alternate call in the probe function.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/firmware/arm_scpi.c | 68 ++++++++++++++++++++++++++++++++++++++++++---
>>  1 file changed, 64 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>> index b0d911b..3fe39fe 100644
>> --- a/drivers/firmware/arm_scpi.c
>> +++ b/drivers/firmware/arm_scpi.c
>> @@ -213,6 +213,7 @@ struct scpi_drvinfo {
>>      struct scpi_ops *scpi_ops;
>>      struct scpi_chan *channels;
>>      struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
>> +    const struct priv_scpi_ops *ops;
>>  };
>>
>>  /*
>> @@ -299,6 +300,17 @@ struct dev_pstate_set {
>>      u8 pstate;
>>  } __packed;
>>
>> +struct priv_scpi_ops {
>> +    /* Internal Specific Ops */
>> +    void (*handle_remote_msg)(struct mbox_client *c, void *msg);
>> +    void (*tx_prepare)(struct mbox_client *c, void *msg);
>> +    /* Message Specific Ops */
>> +    int (*init_versions)(struct scpi_drvinfo *info);
>> +    int (*dvfs_get_info)(u8 domain, struct dvfs_info *buf);
>> +    /* System wide Ops */
>> +    struct scpi_ops *scpi_ops;
>> +};
>> +
> 
> 
> I fail to understand the need for this. Can you please explain the issue
> you would face without this ?
> 
>>  static struct scpi_drvinfo *scpi_info;
>>
>>  static int scpi_linux_errmap[SCPI_ERR_MAX] = {
>> @@ -695,9 +707,12 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
>>      if (scpi_info->dvfs[domain])    /* data already populated */
>>          return scpi_info->dvfs[domain];
>>
>> -    ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
>> +    if (scpi_info->ops && scpi_info->ops->dvfs_get_info)
>> +        ret = scpi_info->ops->dvfs_get_info(domain, &buf);
>> +    else
>> +        ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO,
>> +                    &domain, sizeof(domain),
>>                  &buf, sizeof(buf));
>> -
>>      if (ret)
>>          return ERR_PTR(ret);
>>
>> @@ -855,6 +870,22 @@ static struct scpi_ops scpi_ops = {
>>      .vendor_send_message = scpi_ext_send_message,
>>  };
>>
>> +static struct scpi_ops legacy_scpi_ops = {
>> +    .get_version = scpi_get_version,
>> +    .clk_get_range = NULL,
>> +    .clk_get_val = legacy_scpi_clk_get_val,
>> +    .clk_set_val = legacy_scpi_clk_set_val,
>> +    .dvfs_get_idx = legacy_scpi_dvfs_get_idx,
>> +    .dvfs_set_idx = legacy_scpi_dvfs_set_idx,
>> +    .dvfs_get_info = scpi_dvfs_get_info,
>> +    .sensor_get_capability = legacy_scpi_sensor_get_capability,
>> +    .sensor_get_info = legacy_scpi_sensor_get_info,
>> +    .sensor_get_value = legacy_scpi_sensor_get_value,
>> +    .device_get_power_state = NULL,
>> +    .device_set_power_state = NULL,
>> +    .vendor_send_message = legacy_scpi_send_message,
> 
> I think we need not have this at all if you follow the suggestion I had
> in the previous patch. Try and let's see how it would look.

If you confirm you want the if/else as said in patch 4.

But clk_get_range, device_get/set_power_state are not available in legacy,
I think we should still have this alternate structure.

>> +};
>> +
>>  struct scpi_ops *get_scpi_ops(void)
>>  {
>>      return scpi_info ? scpi_info->scpi_ops : NULL;
>> @@ -972,8 +1003,17 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
>>      return 0;
>>  }
>>
>> +static const struct priv_scpi_ops scpi_legacy_ops = {
>> +    .handle_remote_msg = legacy_scpi_handle_remote_msg,
>> +    .tx_prepare = legacy_scpi_tx_prepare,
>> +    .init_versions = legacy_scpi_init_versions,
>> +    .dvfs_get_info = legacy_scpi_dvfs_get_info,
>> +    .scpi_ops = &legacy_scpi_ops,
>> +};
>> +
> 
> Ditto, can go away.
> 

Yes, in the if/else is_legacy variant this should go away.

Thanks,
Neil



From narmstrong at baylibre.com  Tue Aug 23 01:23:39 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 10:23:39 +0200
Subject: [PATCH 07/13] scpi: ignore init_versions failure if reported not
 supported
In-Reply-To: <74d35f80-8499-cadf-798c-9b296218305c@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>
 <74d35f80-8499-cadf-798c-9b296218305c@arm.com>
Message-ID: <86c4042a-a892-b5c4-cc75-c2139e80e226@baylibre.com>

On 08/19/2016 06:46 PM, Sudeep Holla wrote:
> 
> 
> On 18/08/16 11:11, Neil Armstrong wrote:
>> In Amlogic GXBB Legacy SCPI, the LEGACY_SCPI_CMD_SCPI_CAPABILITIES report
>> as SCPI_ERR_SUPPORT, so do not fail if this command is not supported.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/firmware/arm_scpi.c | 12 +++++++-----
>>  1 file changed, 7 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>> index 3fe39fe..d3be4c5 100644
>> --- a/drivers/firmware/arm_scpi.c
>> +++ b/drivers/firmware/arm_scpi.c
>> @@ -1111,12 +1111,13 @@ err:
>>          ret = scpi_info->ops->init_versions(scpi_info);
>>      else
>>      ret = scpi_init_versions(scpi_info);
>> -    if (ret) {
>> +    if (ret && ret != -EOPNOTSUPP) {
>>          dev_err(dev, "incorrect or no SCP firmware found\n");
>>          scpi_remove(pdev);
>>          return ret;
>>      }
>>
> 
> Why not deal it in init_versions itself.
> 
>> +    if (ret != -EOPNOTSUPP) {
>>      _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
>>            PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
>>            PROTOCOL_REV_MINOR(scpi_info->protocol_version),
> 
> Why not have default value like 0.0 ? Just add a comment. Since get
> version is exported out, IMO having default value makes more sense. What
> do you think ?
> 
>> @@ -1124,15 +1125,16 @@ err:
>>            FW_REV_MINOR(scpi_info->firmware_version),
>>            FW_REV_PATCH(scpi_info->firmware_version));
>>
>> +        ret = sysfs_create_groups(&dev->kobj, versions_groups);
>> +        if (ret)
>> +            dev_err(dev, "unable to create sysfs version group\n");
>> +    }
>> +
> 
> Again this can stay as is if we have default.
> 

Printing version 0.0 firmware 0.0.0 is a nonsense for me...

Neil


From narmstrong at baylibre.com  Tue Aug 23 04:22:50 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:22:50 +0200
Subject: [PATCH] ARM: dts: meson-gxbb: Add support for the Nexbox A95X Board
Message-ID: <1471951370-29269-1-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/Makefile               |  1 +
 .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    | 79 ++++++++++++++++++++++
 2 files changed, 80 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 47ec703..2c50439 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
new file mode 100644
index 0000000..c418bd7
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 Andreas F?rber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Neil Armstrong <narmstrong at kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library 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 library 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "meson-gxbb.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	compatible = "nexbox,a95x", "amlogic,meson-gxbb";
+	model = "NEXBOX A95X";
+	
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+};
+
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+};
+
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:25:06 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:25:06 +0200
Subject: [PATCH v2 0/2] pinctrl: meson-gxbb: Export pins for PWMs
Message-ID: <1471951508-29620-1-git-send-email-narmstrong@baylibre.com>

Add PWM pins in the meson-gxbb pinctrl driver and export then in the GXBB dtsi.

Changes since v1 at http://lkml.kernel.org/r/1471870450-11109-1-git-send-email-narmstrong at baylibre.com :
 - Rebased on git.linaro.org/people/linus.walleij/linux-pinctrl.git branch devel
 - Fixed previous rebase send on resend

Neil Armstrong (2):
  pinctrl: meson-gxbb: add pins for PWM
  ARM64: dts: meson-gxbb: Add PWM pinctrl nodes

 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 77 ++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c  | 79 +++++++++++++++++++++++++++++
 2 files changed, 156 insertions(+)

-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:25:08 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:25:08 +0200
Subject: [PATCH v2 2/2] ARM64: dts: meson-gxbb: Add PWM pinctrl nodes
In-Reply-To: <1471951508-29620-1-git-send-email-narmstrong@baylibre.com>
References: <1471951508-29620-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471951508-29620-3-git-send-email-narmstrong@baylibre.com>

Add DT nodes for PWMs in EE and AO domains.

Acked-by: Linus Walleij <linus.walleij at linaro.org>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 77 +++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..9aeb88a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -203,6 +203,34 @@
 						function = "uart_ao";
 					};
 				};
+
+				pwm_ao_a_3_pins: pwm_ao_a_3 {
+					mux {
+						groups = "pwm_ao_a_3";
+						function = "pwm_ao_a_3";
+					};
+				};
+
+				pwm_ao_a_6_pins: pwm_ao_a_6 {
+					mux {
+						groups = "pwm_ao_a_6";
+						function = "pwm_ao_a_6";
+					};
+				};
+
+				pwm_ao_a_12_pins: pwm_ao_a_12 {
+					mux {
+						groups = "pwm_ao_a_12";
+						function = "pwm_ao_a_12";
+					};
+				};
+
+				pwm_ao_b_pins: pwm_ao_b {
+					mux {
+						groups = "pwm_ao_b";
+						function = "pwm_ao_b";
+					};
+				};
 			};
 
 			uart_AO: serial at 4c0 {
@@ -306,6 +334,55 @@
 						function = "eth";
 					};
 				};
+
+				pwm_a_x_pins: pwm_a_x {
+					mux {
+						groups = "pwm_a_x";
+						function = "pwm_a_x";
+					};
+				};
+
+				pwm_a_y_pins: pwm_a_y {
+					mux {
+						groups = "pwm_a_y";
+						function = "pwm_a_y";
+					};
+				};
+
+				pwm_b_pins: pwm_b {
+					mux {
+						groups = "pwm_b";
+						function = "pwm_b";
+					};
+				};
+
+				pwm_d_pins: pwm_d {
+					mux {
+						groups = "pwm_d";
+						function = "pwm_d";
+					};
+				};
+
+				pwm_e_pins: pwm_e {
+					mux {
+						groups = "pwm_e";
+						function = "pwm_e";
+					};
+				};
+
+				pwm_f_x_pins: pwm_f_x {
+					mux {
+						groups = "pwm_f_x";
+						function = "pwm_f_x";
+					};
+				};
+
+				pwm_f_y_pins: pwm_f_y {
+					mux {
+						groups = "pwm_f_y";
+						function = "pwm_f_y";
+					};
+				};
 			};
 		};
 
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:25:07 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:25:07 +0200
Subject: [PATCH v2 1/2] pinctrl: meson-gxbb: add pins for PWM
In-Reply-To: <1471951508-29620-1-git-send-email-narmstrong@baylibre.com>
References: <1471951508-29620-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471951508-29620-2-git-send-email-narmstrong@baylibre.com>

Add support for PWM pins, for EE and AO domains.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 79 ++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index 7eeb053..9ba9172 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -193,6 +193,14 @@ static const unsigned int eth_txd1_pins[]	= { PIN(GPIOZ_11, EE_OFF) };
 static const unsigned int eth_txd2_pins[]	= { PIN(GPIOZ_12, EE_OFF) };
 static const unsigned int eth_txd3_pins[]	= { PIN(GPIOZ_13, EE_OFF) };
 
+static const unsigned int pwm_a_x_pins[]	= { PIN(GPIOX_6, EE_OFF) };
+static const unsigned int pwm_a_y_pins[]	= { PIN(GPIOY_16, EE_OFF) };
+static const unsigned int pwm_b_pins[]		= { PIN(GPIODV_29, EE_OFF) };
+static const unsigned int pwm_d_pins[]		= { PIN(GPIODV_28, EE_OFF) };
+static const unsigned int pwm_e_pins[]		= { PIN(GPIOX_19, EE_OFF) };
+static const unsigned int pwm_f_x_pins[]	= { PIN(GPIOX_7, EE_OFF) };
+static const unsigned int pwm_f_y_pins[]	= { PIN(GPIOY_15, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -227,6 +235,11 @@ static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
 static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
 
+static const unsigned int pwm_ao_a_3_pins[]	= { PIN(GPIOAO_3, 0) };
+static const unsigned int pwm_ao_a_6_pins[]	= { PIN(GPIOAO_6, 0) };
+static const unsigned int pwm_ao_a_12_pins[]	= { PIN(GPIOAO_12, 0) };
+static const unsigned int pwm_ao_b_pins[]	= { PIN(GPIOAO_13, 0) };
+
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
 	GPIO_GROUP(GPIOZ_1, EE_OFF),
@@ -361,12 +374,17 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_rx_a,	4,	12),
 	GROUP(uart_cts_a,	4,	11),
 	GROUP(uart_rts_a,	4,	10),
+	GROUP(pwm_a_x,		3,	17),
+	GROUP(pwm_e,		2,	30),
+	GROUP(pwm_f_x,		3,	18),
 
 	/* Bank Y */
 	GROUP(uart_cts_c,	1,	19),
 	GROUP(uart_rts_c,	1,	18),
 	GROUP(uart_tx_c,	1,	17),
 	GROUP(uart_rx_c,	1,	16),
+	GROUP(pwm_a_y,		1,	21),
+	GROUP(pwm_f_y,		1,	20),
 
 	/* Bank Z */
 	GROUP(eth_mdio,		6,	1),
@@ -389,6 +407,8 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_rx_b,	2,	28),
 	GROUP(uart_cts_b,	2,	27),
 	GROUP(uart_rts_b,	2,	26),
+	GROUP(pwm_b,		3,	21),
+	GROUP(pwm_d,		3,	20),
 
 	/* Bank BOOT */
 	GROUP(emmc_nand_d07,	4,	30),
@@ -435,6 +455,10 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GROUP(i2c_slave_sck_ao, 0,	2),
 	GROUP(i2c_slave_sda_ao, 0,	1),
 	GROUP(remote_input_ao,	0,	0),
+	GROUP(pwm_ao_a_3,	0,	22),
+	GROUP(pwm_ao_a_6,	0,	18),
+	GROUP(pwm_ao_a_12,	0,	17),
+	GROUP(pwm_ao_b,		0,	3),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -502,6 +526,34 @@ static const char * const eth_groups[] = {
 	"eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
 };
 
+static const char * const pwm_a_x_groups[] = {
+	"pwm_a_x",
+};
+
+static const char * const pwm_a_y_groups[] = {
+	"pwm_a_y",
+};
+
+static const char * const pwm_b_groups[] = {
+	"pwm_b",
+};
+
+static const char * const pwm_d_groups[] = {
+	"pwm_d",
+};
+
+static const char * const pwm_e_groups[] = {
+	"pwm_e",
+};
+
+static const char * const pwm_f_x_groups[] = {
+	"pwm_f_x",
+};
+
+static const char * const pwm_f_y_groups[] = {
+	"pwm_f_y",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -528,6 +580,22 @@ static const char * const remote_input_ao_groups[] = {
 	"remote_input_ao",
 };
 
+static const char * const pwm_ao_a_3_groups[] = {
+	"pwm_ao_a_3",
+};
+
+static const char * const pwm_ao_a_6_groups[] = {
+	"pwm_ao_a_6",
+};
+
+static const char * const pwm_ao_a_12_groups[] = {
+	"pwm_ao_a_12",
+};
+
+static const char * const pwm_ao_b_groups[] = {
+	"pwm_ao_b",
+};
+
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
@@ -536,6 +604,13 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(uart_b),
 	FUNCTION(uart_c),
 	FUNCTION(eth),
+	FUNCTION(pwm_a_x),
+	FUNCTION(pwm_a_y),
+	FUNCTION(pwm_b),
+	FUNCTION(pwm_d),
+	FUNCTION(pwm_e),
+	FUNCTION(pwm_f_x),
+	FUNCTION(pwm_f_y),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
@@ -545,6 +620,10 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(i2c_ao),
 	FUNCTION(i2c_slave_ao),
 	FUNCTION(remote_input_ao),
+	FUNCTION(pwm_ao_a_3),
+	FUNCTION(pwm_ao_a_6),
+	FUNCTION(pwm_ao_a_12),
+	FUNCTION(pwm_ao_b),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:49 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:49 +0200
Subject: [PATCH v2 0/7] scpi: Add support for legacy SCPI protocol
Message-ID: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>

This patchset aims to support the legacy SCPI firmware implementation that was
delivered as early technology preview for the JUNO platform.

Finally a stable, maintained and public implementation for the SCPI protocol
has been upstreamed part of the JUNO support and it is the recommended way
of implementing SCP communication on ARMv8 platforms.

The Amlogic GXBB platform is using this legacy protocol, as the RK3368 & RK3399
platforms. This patchset will only add support for Amlogic GXBB SoC.

This patchset add support for the legacy protocol in the arm_scpi.c file,
avoiding code duplication.

Last RFC discution tread can be found at : https://lkml.org/lkml/2016/8/9/210

The last patch depends on the "Platform MHU" dtsi patch.

Changes since v1 at : http://lkml.kernel.org/r/1471515066-3626-1-git-send-email-narmstrong at baylibre.com
 - Dropped vendor_send_message and rockchip vendor mechanism patches
 - Merged alternate functions into main functions using is_legacy boolean
 - Added DT match table to set is_legacy to true
 - Kept alternate scpi_ops structure for legacy

Neil Armstrong (7):
  scpi: Add alternative legacy structures, functions and macros
  scpi: Use legacy variants command index calling scpi_send_message
  scpi: Add support for Legacy match table for Amlogic GXBB SoC
  scpi: grow MAX_DVFS_OPPS to 16 entries
  dt-bindings: Add support for Amlogic GXBB SCPI Interface
  ARM64: dts: meson-gxbb: Add SRAM node
  ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes

 Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++++
 drivers/firmware/arm_scpi.c                        | 279 +++++++++++++++++++--
 3 files changed, 302 insertions(+), 30 deletions(-)

-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:52 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:52 +0200
Subject: [PATCH v2 3/7] scpi: Add support for Legacy match table for Amlogic
 GXBB SoC
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-4-git-send-email-narmstrong@baylibre.com>

Add new DT match table to setup the is_legacy boolean value across
the scpi functions.
Add the Amlogic GXBB SoC compatible for platform and as legacy match entry.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index d24d1de..badef70 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -888,6 +888,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
 	return 0;
 }
 
+static const struct of_device_id legacy_scpi_of_match[] = {
+	{.compatible = "amlogic,meson-gxbb-scpi"},
+	{},
+};
+
 static int scpi_probe(struct platform_device *pdev)
 {
 	int count, idx, ret;
@@ -900,6 +905,9 @@ static int scpi_probe(struct platform_device *pdev)
 	if (!scpi_info)
 		return -ENOMEM;
 
+	if (of_match_device(legacy_scpi_of_match, &pdev->dev))
+		scpi_info->is_legacy = true;
+
 	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
 	if (count < 0) {
 		dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -996,6 +1004,7 @@ err:
 
 static const struct of_device_id scpi_of_match[] = {
 	{.compatible = "arm,scpi"},
+	{.compatible = "amlogic,meson-gxbb-scpi"},
 	{},
 };
 
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:50 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:50 +0200
Subject: [PATCH v2 1/7] scpi: Add alternative legacy structures,
 functions and macros
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-2-git-send-email-narmstrong@baylibre.com>

In order to support the legacy SCPI protocol variant, add back the structures
and macros that varies against the final specification.
Add support for legacy in scpi_send_message.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 142 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 135 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 4388937..752e5b2 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -50,11 +50,16 @@
 #define CMD_TOKEN_ID_MASK	0xff
 #define CMD_DATA_SIZE_SHIFT	16
 #define CMD_DATA_SIZE_MASK	0x1ff
+#define CMD_LEGACY_DATA_SIZE_SHIFT	20
+#define CMD_LEGACY_DATA_SIZE_MASK	0x1ff
 #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
 	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
 #define ADD_SCPI_TOKEN(cmd, token)			\
 	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
+#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz)				\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |			       \
+	(((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
 
 #define CMD_SIZE(cmd)	(((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
 #define CMD_UNIQ_MASK	(CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
@@ -132,6 +137,42 @@ enum scpi_std_cmd {
 	SCPI_CMD_COUNT
 };
 
+enum legacy_scpi_std_cmd {
+	LEGACY_SCPI_CMD_INVALID			= 0x00,
+	LEGACY_SCPI_CMD_SCPI_READY		= 0x01,
+	LEGACY_SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
+	LEGACY_SCPI_CMD_EVENT			= 0x03,
+	LEGACY_SCPI_CMD_SET_CSS_PWR_STATE	= 0x04,
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE	= 0x05,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT	= 0x06,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT	= 0x07,
+	LEGACY_SCPI_CMD_SYS_PWR_STATE		= 0x08,
+	LEGACY_SCPI_CMD_L2_READY		= 0x09,
+	LEGACY_SCPI_CMD_SET_AP_TIMER		= 0x0a,
+	LEGACY_SCPI_CMD_CANCEL_AP_TIME		= 0x0b,
+	LEGACY_SCPI_CMD_DVFS_CAPABILITIES	= 0x0c,
+	LEGACY_SCPI_CMD_GET_DVFS_INFO		= 0x0d,
+	LEGACY_SCPI_CMD_SET_DVFS		= 0x0e,
+	LEGACY_SCPI_CMD_GET_DVFS		= 0x0f,
+	LEGACY_SCPI_CMD_GET_DVFS_STAT		= 0x10,
+	LEGACY_SCPI_CMD_SET_RTC			= 0x11,
+	LEGACY_SCPI_CMD_GET_RTC			= 0x12,
+	LEGACY_SCPI_CMD_CLOCK_CAPABILITIES	= 0x13,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX		= 0x14,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE		= 0x15,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE		= 0x16,
+	LEGACY_SCPI_CMD_PSU_CAPABILITIES	= 0x17,
+	LEGACY_SCPI_CMD_SET_PSU			= 0x18,
+	LEGACY_SCPI_CMD_GET_PSU			= 0x19,
+	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES	= 0x1a,
+	LEGACY_SCPI_CMD_SENSOR_INFO		= 0x1b,
+	LEGACY_SCPI_CMD_SENSOR_VALUE		= 0x1c,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x1d,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x1e,
+	LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1f,
+	LEGACY_SCPI_CMD_COUNT
+};
+
 struct scpi_xfer {
 	u32 slot; /* has to be first element */
 	u32 cmd;
@@ -155,11 +196,13 @@ struct scpi_chan {
 	spinlock_t rx_lock; /* locking for the rx pending list */
 	struct mutex xfers_lock;
 	u8 token;
+	struct scpi_xfer *t;
 };
 
 struct scpi_drvinfo {
 	u32 protocol_version;
 	u32 firmware_version;
+	bool is_legacy;
 	int num_chans;
 	atomic_t next_chan;
 	struct scpi_ops *scpi_ops;
@@ -177,6 +220,11 @@ struct scpi_shared_mem {
 	u8 payload[0];
 } __packed;
 
+struct legacy_scpi_shared_mem {
+	__le32 status;
+	u8 payload[0];
+} __packed;
+
 struct scp_capabilities {
 	__le32 protocol_version;
 	__le32 event_version;
@@ -202,6 +250,12 @@ struct clk_set_value {
 	__le32 rate;
 } __packed;
 
+struct legacy_clk_set_value {
+	__le32 rate;
+	__le16 id;
+	__le16 reserved;
+} __packed;
+
 struct dvfs_info {
 	__le32 header;
 	struct {
@@ -302,6 +356,23 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
 	scpi_process_cmd(ch, cmd);
 }
 
+static void legacy_scpi_handle_remote_msg(struct mbox_client *c, void *__msg)
+{
+	struct scpi_chan *ch =
+		container_of(c, struct scpi_chan, cl);
+	struct legacy_scpi_shared_mem *mem = ch->rx_payload;
+	unsigned int len;
+
+	len = ch->t->rx_len;
+
+	ch->t->status = le32_to_cpu(mem->status);
+
+	if (len)
+		memcpy_fromio(ch->t->rx_buf, mem->payload, len);
+
+	complete(&ch->t->done);
+}
+
 static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 {
 	unsigned long flags;
@@ -322,6 +393,43 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
 	mem->command = cpu_to_le32(t->cmd);
 }
 
+static void legacy_scpi_tx_prepare(struct mbox_client *c, void *__msg)
+{
+	struct scpi_chan *ch =
+		container_of(c, struct scpi_chan, cl);
+
+	if (ch->t->tx_buf && ch->t->tx_len)
+		memcpy_toio(ch->tx_payload, ch->t->tx_buf, ch->t->tx_len);
+}
+
+static int legacy_high_priority_cmds[] = {
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_SET_DVFS,
+	LEGACY_SCPI_CMD_GET_DVFS,
+	LEGACY_SCPI_CMD_SET_RTC,
+	LEGACY_SCPI_CMD_GET_RTC,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_SET_PSU,
+	LEGACY_SCPI_CMD_GET_PSU,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
+};
+
+static int legacy_scpi_get_chan(u8 cmd)
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(legacy_high_priority_cmds); idx++)
+		if (cmd == legacy_high_priority_cmds[idx])
+			return 1;
+
+	return 0;
+}
+
 static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
 {
 	struct scpi_xfer *t;
@@ -352,15 +460,27 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 	struct scpi_xfer *msg;
 	struct scpi_chan *scpi_chan;
 
-	chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
+	if (scpi_info->is_legacy)
+		chan = legacy_scpi_get_chan(cmd);
+	else
+		chan = atomic_inc_return(&scpi_info->next_chan) %
+			scpi_info->num_chans;
 	scpi_chan = scpi_info->channels + chan;
 
 	msg = get_scpi_xfer(scpi_chan);
 	if (!msg)
 		return -ENOMEM;
 
-	msg->slot = BIT(SCPI_SLOT);
-	msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	if (scpi_info->is_legacy) {
+		mutex_lock(&scpi_chan->xfers_lock);
+
+		scpi_chan->t = msg;
+		msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
+		msg->slot = msg->cmd;
+	} else {
+		msg->slot = BIT(SCPI_SLOT);
+		msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	}
 	msg->tx_buf = tx_buf;
 	msg->tx_len = tx_len;
 	msg->rx_buf = rx_buf;
@@ -368,7 +488,7 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 	init_completion(&msg->done);
 
 	ret = mbox_send_message(scpi_chan->chan, msg);
-	if (ret < 0 || !rx_buf)
+	if (ret < 0 || (!scpi_info->is_legacy && !rx_buf))
 		goto out;
 
 	if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
@@ -377,7 +497,10 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
 		/* first status word */
 		ret = msg->status;
 out:
-	if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */
+	if (scpi_info->is_legacy)
+		mutex_unlock(&scpi_chan->xfers_lock);
+	else if (ret < 0 && rx_buf)
+		/* remove entry from the list if timed-out */
 		scpi_process_cmd(scpi_chan, msg->cmd);
 
 	put_scpi_xfer(msg, scpi_chan);
@@ -725,8 +848,13 @@ static int scpi_probe(struct platform_device *pdev)
 		pchan->tx_payload = pchan->rx_payload + (size >> 1);
 
 		cl->dev = dev;
-		cl->rx_callback = scpi_handle_remote_msg;
-		cl->tx_prepare = scpi_tx_prepare;
+		if (scpi_info->is_legacy) {
+			cl->rx_callback = legacy_scpi_handle_remote_msg;
+			cl->tx_prepare = legacy_scpi_tx_prepare;
+		} else {
+			cl->rx_callback = scpi_handle_remote_msg;
+			cl->tx_prepare = scpi_tx_prepare;
+		}
 		cl->tx_block = true;
 		cl->tx_tout = 20;
 		cl->knows_txdone = false; /* controller can't ack */
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:53 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:53 +0200
Subject: [PATCH v2 4/7] scpi: grow MAX_DVFS_OPPS to 16 entries
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-5-git-send-email-narmstrong@baylibre.com>

Since Amlogic SoCs reports more than 8 OPPs per domains, grow the structure
size to 16.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index badef70..d654b62 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -68,7 +68,7 @@
 #define SCPI_SLOT		0
 
 #define MAX_DVFS_DOMAINS	8
-#define MAX_DVFS_OPPS		8
+#define MAX_DVFS_OPPS		16
 #define DVFS_LATENCY(hdr)	(le32_to_cpu(hdr) >> 16)
 #define DVFS_OPP_COUNT(hdr)	((le32_to_cpu(hdr) >> 8) & 0xff)
 
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:51 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:51 +0200
Subject: [PATCH v2 2/7] scpi: Use legacy variants command index calling
 scpi_send_message
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-3-git-send-email-narmstrong@baylibre.com>

In order to support legacy SCP functions from kernel-wide driver, use legacy
command indexes calling scpi_send_message.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/arm_scpi.c | 126 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 107 insertions(+), 19 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 752e5b2..d24d1de 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -520,6 +520,9 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
 	struct clk_get_info clk;
 	__le16 le_clk_id = cpu_to_le16(clk_id);
 
+	if (scpi_info->is_legacy)
+		return -EOPNOTSUPP;
+
 	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
 				sizeof(le_clk_id), &clk, sizeof(clk));
 	if (!ret) {
@@ -535,8 +538,14 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
 	struct clk_get_value clk;
 	__le16 le_clk_id = cpu_to_le16(clk_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
-				sizeof(le_clk_id), &clk, sizeof(clk));
+	if (scpi_info->is_legacy)
+		ret = scpi_send_message(LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+					&le_clk_id, sizeof(le_clk_id),
+					&clk, sizeof(clk));
+	else
+		ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+					sizeof(le_clk_id), &clk, sizeof(clk));
+
 	return ret ? ret : le32_to_cpu(clk.rate);
 }
 
@@ -552,13 +561,33 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
 				 &stat, sizeof(stat));
 }
 
+static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+	int stat;
+	struct legacy_clk_set_value clk = {
+		.id = cpu_to_le16(clk_id),
+		.rate = cpu_to_le32(rate)
+	};
+
+	return scpi_send_message(LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+				 &clk, sizeof(clk),
+				 &stat, sizeof(stat));
+}
+
 static int scpi_dvfs_get_idx(u8 domain)
 {
 	int ret;
 	u8 dvfs_idx;
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
-				&dvfs_idx, sizeof(dvfs_idx));
+	if (scpi_info->is_legacy)
+		ret = scpi_send_message(LEGACY_SCPI_CMD_GET_DVFS,
+					&domain, sizeof(domain),
+					&dvfs_idx, sizeof(dvfs_idx));
+	else
+		ret = scpi_send_message(SCPI_CMD_GET_DVFS,
+					&domain, sizeof(domain),
+					&dvfs_idx, sizeof(dvfs_idx));
+
 	return ret ? ret : dvfs_idx;
 }
 
@@ -567,6 +596,11 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
 	int stat;
 	struct dvfs_set dvfs = {domain, index};
 
+	if (scpi_info->is_legacy)
+		return scpi_send_message(LEGACY_SCPI_CMD_SET_DVFS,
+					 &dvfs, sizeof(dvfs),
+					 &stat, sizeof(stat));
+
 	return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
 				 &stat, sizeof(stat));
 }
@@ -591,9 +625,14 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
 	if (scpi_info->dvfs[domain])	/* data already populated */
 		return scpi_info->dvfs[domain];
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
-				&buf, sizeof(buf));
-
+	if (scpi_info->is_legacy)
+		ret = scpi_send_message(LEGACY_SCPI_CMD_GET_DVFS_INFO,
+					&domain, sizeof(domain),
+					&buf, sizeof(buf));
+	else
+		ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO,
+					&domain, sizeof(domain),
+					&buf, sizeof(buf));
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -626,8 +665,12 @@ static int scpi_sensor_get_capability(u16 *sensors)
 	struct sensor_capabilities cap_buf;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
-				sizeof(cap_buf));
+	if (scpi_info->is_legacy)
+		ret = scpi_send_message(LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
+					NULL, 0, &cap_buf, sizeof(cap_buf));
+	else
+		ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES,
+					NULL, 0, &cap_buf, sizeof(cap_buf));
 	if (!ret)
 		*sensors = le16_to_cpu(cap_buf.sensors);
 
@@ -640,8 +683,13 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
 	struct _scpi_sensor_info _info;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
-				&_info, sizeof(_info));
+	if (scpi_info->is_legacy)
+		ret = scpi_send_message(LEGACY_SCPI_CMD_SENSOR_INFO,
+					&id, sizeof(id),
+					&_info, sizeof(_info));
+	else
+		ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+					&_info, sizeof(_info));
 	if (!ret) {
 		memcpy(info, &_info, sizeof(*info));
 		info->sensor_id = le16_to_cpu(_info.sensor_id);
@@ -656,11 +704,18 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
 	struct sensor_value buf;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
-				&buf, sizeof(buf));
-	if (!ret)
-		*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
-			le32_to_cpu(buf.lo_val);
+	if (scpi_info->is_legacy) {
+		ret = scpi_send_message(LEGACY_SCPI_CMD_SENSOR_VALUE,
+					&id, sizeof(id), &buf, sizeof(buf));
+		if (!ret)
+			*val = (u64)le32_to_cpu(buf.lo_val);
+	} else {
+		ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
+					&buf, sizeof(buf));
+		if (!ret)
+			*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
+				le32_to_cpu(buf.lo_val);
+	}
 
 	return ret;
 }
@@ -671,6 +726,9 @@ static int scpi_device_get_power_state(u16 dev_id)
 	u8 pstate;
 	__le16 id = cpu_to_le16(dev_id);
 
+	if (scpi_info->is_legacy)
+		return -EOPNOTSUPP;
+
 	ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
 				sizeof(id), &pstate, sizeof(pstate));
 	return ret ? ret : pstate;
@@ -684,6 +742,9 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
 		.pstate = pstate,
 	};
 
+	if (scpi_info->is_legacy)
+		return -EOPNOTSUPP;
+
 	return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
 				 sizeof(dev_set), &stat, sizeof(stat));
 }
@@ -703,6 +764,21 @@ static struct scpi_ops scpi_ops = {
 	.device_set_power_state = scpi_device_set_power_state,
 };
 
+static struct scpi_ops legacy_scpi_ops = {
+	.get_version = scpi_get_version,
+	.clk_get_range = NULL,
+	.clk_get_val = scpi_clk_get_val,
+	.clk_set_val = legacy_scpi_clk_set_val,
+	.dvfs_get_idx = scpi_dvfs_get_idx,
+	.dvfs_set_idx = scpi_dvfs_set_idx,
+	.dvfs_get_info = scpi_dvfs_get_info,
+	.sensor_get_capability = scpi_sensor_get_capability,
+	.sensor_get_info = scpi_sensor_get_info,
+	.sensor_get_value = scpi_sensor_get_value,
+	.device_get_power_state = NULL,
+	.device_set_power_state = NULL,
+};
+
 struct scpi_ops *get_scpi_ops(void)
 {
 	return scpi_info ? scpi_info->scpi_ops : NULL;
@@ -714,12 +790,20 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
 	int ret;
 	struct scp_capabilities caps;
 
-	ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
-				&caps, sizeof(caps));
+	if (scpi_info->is_legacy)
+		ret = scpi_send_message(LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
+					NULL, 0, &caps, sizeof(caps));
+	else
+		ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+					&caps, sizeof(caps));
 	if (!ret) {
 		info->protocol_version = le32_to_cpu(caps.protocol_version);
 		info->firmware_version = le32_to_cpu(caps.platform_version);
 	}
+	/* Ignore error if not implemented */
+	if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
+		return 0;
+
 	return ret;
 }
 
@@ -897,7 +981,11 @@ err:
 		  FW_REV_MAJOR(scpi_info->firmware_version),
 		  FW_REV_MINOR(scpi_info->firmware_version),
 		  FW_REV_PATCH(scpi_info->firmware_version));
-	scpi_info->scpi_ops = &scpi_ops;
+
+	if (scpi_info->is_legacy)
+		scpi_info->scpi_ops = &legacy_scpi_ops;
+	else
+		scpi_info->scpi_ops = &scpi_ops;
 
 	ret = sysfs_create_groups(&dev->kobj, versions_groups);
 	if (ret)
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:54 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:54 +0200
Subject: [PATCH v2 5/7] dt-bindings: Add support for Amlogic GXBB SCPI
 Interface
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-6-git-send-email-narmstrong@baylibre.com>

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
index faa4b44..04bc171 100644
--- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -7,7 +7,7 @@ by Linux to initiate various system control and power operations.
 
 Required properties:
 
-- compatible : should be "arm,scpi"
+- compatible : should be "arm,scpi" or "amlogic,meson-gxbb-scpi"
 - mboxes: List of phandle and mailbox channel specifiers
 	  All the channels reserved by remote SCP firmware for use by
 	  SCPI message protocol should be specified in any order
@@ -60,7 +60,8 @@ A small area of SRAM is reserved for SCPI communication between application
 processors and SCP.
 
 Required properties:
-- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
+- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno,
+		or "amlogic,meson-gxbb-sram" for Amlogic GXBB SoC.
 
 The rest of the properties should follow the generic mmio-sram description
 found in ../../sram/sram.txt
@@ -70,7 +71,8 @@ Each sub-node represents the reserved area for SCPI.
 Required sub-node properties:
 - reg : The base offset and size of the reserved area with the SRAM
 - compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
-	       shared memory on Juno platforms
+	       shared memory on Juno platforms or
+	       "amlogic,meson-gxbb-scp-shmem" for Amlogic GXBB SoC.
 
 Sensor bindings for the sensors based on SCPI Message Protocol
 --------------------------------------------------------------
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:55 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:55 +0200
Subject: [PATCH v2 6/7] ARM64: dts: meson-gxbb: Add SRAM node
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-7-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index bdbf6e7..2748007 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -124,6 +124,15 @@
 		#size-cells = <2>;
 		ranges;
 
+		sram: sram at c8000000 {
+			compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+			reg = <0x0 0xc8000000 0x0 0x14000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x0 0xc8000000 0x14000>;
+		};
+
 		cbus: cbus at c1100000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xc1100000 0x0 0x100000>;
-- 
1.9.1



From narmstrong at baylibre.com  Tue Aug 23 04:46:56 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 13:46:56 +0200
Subject: [PATCH v2 7/7] ARM64: dts: meson-gxbb: Add SCPI with cpufreq &
 sensors Nodes
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1471952816-30877-8-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 36 +++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 2748007..257845a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -61,6 +61,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x0>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 
 		cpu1: cpu at 1 {
@@ -68,6 +69,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x1>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 
 		cpu2: cpu at 2 {
@@ -75,6 +77,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x2>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 
 		cpu3: cpu at 3 {
@@ -82,6 +85,7 @@
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0x0 0x3>;
 			enable-method = "psci";
+			clocks = <&scpi_dvfs 0>;
 		};
 	};
 
@@ -99,6 +103,28 @@
 		method = "smc";
 	};
 
+	scpi {
+		compatible = "amlogic,meson-gxbb-scpi";
+		mboxes = <&mailbox 1 &mailbox 2>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+
+		clocks {
+			compatible = "arm,scpi-clocks";
+
+			scpi_dvfs: scpi_clocks at 0 {
+				compatible = "arm,scpi-dvfs-clocks";
+				#clock-cells = <1>;
+				clock-indices = <0>;
+				clock-output-names = "vcpu";
+			};
+		};
+
+		scpi_sensors: sensors {
+			compatible = "arm,scpi-sensors";
+			#thermal-sensor-cells = <1>;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
@@ -131,6 +157,16 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x0 0xc8000000 0x14000>;
+
+			cpu_scp_lpri: scp-shmem at 0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13000 0x400>;
+			};
+
+			cpu_scp_hpri: scp-shmem at 200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13400 0x400>;
+			};
 		};
 
 		cbus: cbus at c1100000 {
-- 
1.9.1



From ben.dooks at codethink.co.uk  Tue Aug 23 06:30:21 2016
From: ben.dooks at codethink.co.uk (Ben Dooks)
Date: Tue, 23 Aug 2016 14:30:21 +0100
Subject: USB PHY documentation
In-Reply-To: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
References: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
Message-ID: <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>

On 22/08/2016 22:39, Martin Blumenstingl wrote:
> Hello,
>
> last weekend I tried getting the USB PHY working on my GXBB device.
> The simple part: resetting the USB part and enabling the clocks.
> The tricky part: configuring the USB PHY registers
>
> Unfortunately the public datasheet does not contain any information
> about the USB PHY.
> The reference driver does not contain many comments, the struct
> members are using abbreviated names and it seems that a part of what
> should be done by the PHY driver is part of the dwc driver
> (usb_peri_reg changes were patched into it).
> I am now wondering if someone can share some details from the 
> datasheet.
>
> I took my register #defines from the reference driver (and tried to
> make them human readable): [0]
> There are some USB_PHY_CLK_SEL_* definitions at the bottom which seem
> interesting (at least for configuring REG_CONFIG_CLK_SEL, but
> unfortunately I don't know if these are valid (for either meson8b or
> gxbb)..
>
> Symptoms are: dwc2's USB initialization is successful, but when I 
> plug
> in a device it's not being detected.
> I *think* that my problem is that REG_ADP_BC_DRV_VBUS is a readonly
> bit - it's set when I use the original firmware of my device, but I
> cannot set it in my PHY driver.
>
> In case anyone is interested how my changes look exactly, you can 
> find
> the code here: [1]
>
> I also dumped the USB PHY registers from the original Android 
> firmware
> of my device in case anyone is interested:
> phy0:
> [0xc0000000] = 0x8000
> [0xc0000004] = 0x1690500
> [0xc0000008] = 0x0
> [0xc000000c] = 0x8E18
> [0xc0000010] = 0x0
> [0xc0000014] = 0x80000
> [0xc0000018] = 0x246613D
> [0xc000001c] = 0x0
>
> phy1:
> [0xc0000020] = 0x8000
> [0xc0000024] = 0x1690500
> [0xc0000028] = 0x0
> [0xc000002c] = 0x2010118
> [0xc0000030] = 0x0
> [0xc0000034] = 0x80000
> [0xc0000038] = 0xE46613D
> [0xc000003c] = 0x0
>
> @Ben: did you get anywhere with your experiments on Meson8b (S805)?

I did a PHY driver and some updates to the dwc2 driver, but could
not get a reliable USB session going. I'll post my PHY driver later
as it's still in bits and needs to be made into a semi-coherent patch
set.


-- 
Ben Dooks, Senior Engineer
http://www.codethink.co.uk/


From ben-linux at fluff.org  Mon Aug 22 15:14:56 2016
From: ben-linux at fluff.org (Ben Dooks)
Date: Mon, 22 Aug 2016 23:14:56 +0100
Subject: RFC: RTC v5
Message-ID: <20160822221501.21945-1-ben-linux@fluff.org>

I've reworked the rtc patches, but have no way of testing them
until I get back from "holiday". Is anyone able to test so that
they can be submitted?

git at github.com:bendooks/amlogic-kenel.git bjdooks/v48-rc3/rtc-v5 



From ben-linux at fluff.org  Mon Aug 22 15:14:59 2016
From: ben-linux at fluff.org (Ben Dooks)
Date: Mon, 22 Aug 2016 23:14:59 +0100
Subject: [PATCH 3/5] meson-rtc: add device-tree binding
In-Reply-To: <20160822221501.21945-1-ben-linux@fluff.org>
References: <20160822221501.21945-1-ben-linux@fluff.org>
Message-ID: <20160822221501.21945-4-ben-linux@fluff.org>

From: Ben Dooks <ben.dooks at codethink.co.uk>

Add documentation for the AMLogic Meson RTC.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
Acked-by: Rob Herring <robh at kernel.org>
Acked-by: Mark Rutland <mark.rutland at arm.com>
---
 .../devicetree/bindings/rtc/rtc-amlogic.txt         | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-amlogic.txt

diff --git a/Documentation/devicetree/bindings/rtc/rtc-amlogic.txt b/Documentation/devicetree/bindings/rtc/rtc-amlogic.txt
new file mode 100644
index 0000000..efc7672
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-amlogic.txt
@@ -0,0 +1,21 @@
+* AMlogic Meson RTC
+
+Required properties:
+- compatible: should be one of the following describing the hardware:
+	* "amlogic,meson6-rtc"
+	* "amlogic,meson8-rtc"
+	* "amlogic,meson8b-rtc"
+
+- reg: physical register space for the controller's memory mapped registers.
+
+Optional properties:
+- resets: reset controller reference to allow reset of the controller
+- interrupts: single interrupt reference if interrupt support needed
+
+Example:
+
+	rtc: rtc at c8100740 {
+		compatible = "amlogic,meson6-rtc";
+		reg = <0xc8100740 0x14>;
+		status = "disabled";
+	};
-- 
2.9.3



From ben-linux at fluff.org  Mon Aug 22 15:15:00 2016
From: ben-linux at fluff.org (Ben Dooks)
Date: Mon, 22 Aug 2016 23:15:00 +0100
Subject: [PATCH 4/5] ARM: meson: enable RTC for ODRoid-C1
In-Reply-To: <20160822221501.21945-1-ben-linux@fluff.org>
References: <20160822221501.21945-1-ben-linux@fluff.org>
Message-ID: <20160822221501.21945-5-ben-linux@fluff.org>

From: Ben Dooks <ben.dooks at codethink.co.uk>

Now the RTC node has been added, enable it on the ODroid-C1
board.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
---
 arch/arm/boot/dts/meson8b-odroidc1.dts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index e50f1a1..5c7826f 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -76,3 +76,8 @@
 	pinctrl-0 = <&uart_ao_a_pins>;
 	pinctrl-names = "default";
 };
+
+&rtc {
+	status = "okay";
+};
+
-- 
2.9.3



From ben-linux at fluff.org  Mon Aug 22 15:14:57 2016
From: ben-linux at fluff.org (Ben Dooks)
Date: Mon, 22 Aug 2016 23:14:57 +0100
Subject: [PATCH 1/5] rtc: support for amlogic meson rtc
In-Reply-To: <20160822221501.21945-1-ben-linux@fluff.org>
References: <20160822221501.21945-1-ben-linux@fluff.org>
Message-ID: <20160822221501.21945-2-ben-linux@fluff.org>

From: Ben Dooks <ben.dooks at codethink.co.uk>

Add support for the AMLogic meson8b/meson6 RTC block.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
---
Changes v5:
- fixed spacing error
- fixed spelling errors
- added MESON_STATIC_DEFAULT to reduce over 80-col lines
- fixed use of unsigned by moving to unsigned int
- remove unused meson_rtc_prep_bus() function
- moved to using time64_t

Changes since V3:
  <1467748122-14833-1-git-send-email-ben.dooks at codethink.co.uk>
- Added Kevin's tested by

Changes since V1:
  <1467039135-26588-1-git-send-email-ben.dooks at codethink.co.uk>

 - Fixed checkpatch and sparse errors
 - Fixed minor locking bug when writing static-control register
 - Updated the code ordering in the rtc-meson.c driver
 - Fixed alphanumeric ordering in on-cpu rtc block
 - Added Rob Hering's ack for the DT binding documentation
 - Added better description to the RTC driver header.
---
 drivers/rtc/Kconfig     |  11 ++
 drivers/rtc/Makefile    |   1 +
 drivers/rtc/rtc-meson.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 353 insertions(+)
 create mode 100644 drivers/rtc/rtc-meson.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e215f50..40faca1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1228,6 +1228,17 @@ config RTC_DRV_IMXDI
 	   This driver can also be built as a module, if so, the module
 	   will be called "rtc-imxdi".
 
+config RTC_DRV_MESON
+	tristate "AMLogic Meson Real Time Clock"
+	depends on ARCH_MESON || COMPILE_TEST
+	help
+	   Support for AMLogic Meson RTC block in many of the Meson SoC
+	   devices. The driver supports basic read/write of the time.
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-meson".
+
+
 config RTC_DRV_OMAP
 	tristate "TI OMAP Real Time Clock"
 	depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 7cf7ad5..e1bf77c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -94,6 +94,7 @@ obj-$(CONFIG_RTC_DRV_MAX8997)	+= rtc-max8997.o
 obj-$(CONFIG_RTC_DRV_MAX8998)	+= rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MC13XXX)	+= rtc-mc13xxx.o
 obj-$(CONFIG_RTC_DRV_MCP795)	+= rtc-mcp795.o
+obj-$(CONFIG_RTC_DRV_MESON)	+= rtc-meson.o
 obj-$(CONFIG_RTC_DRV_MOXART)	+= rtc-moxart.o
 obj-$(CONFIG_RTC_DRV_MPC5121)	+= rtc-mpc5121.o
 obj-$(CONFIG_RTC_DRV_VRTC)	+= rtc-mrst.o
diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c
new file mode 100644
index 0000000..07d8b8a
--- /dev/null
+++ b/drivers/rtc/rtc-meson.c
@@ -0,0 +1,341 @@
+/* drivers/rtc/rtc-meson.c
+ *
+ * Copyright (c) 2015 Codethink Ltd
+ *	 Ben Dooks <ben.dooks at codethink.co.uk>
+ * Based on origin by Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+#include <linux/rtc.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+/* registers accessed from cpu bus */
+#define RTC_REG(x)		((x) * 4)	/* rtc registers 0-4 */
+
+#define LINE_SDI		(1 << 2)
+#define LINE_SEN		(1 << 1)
+#define LINE_SCLK		(1 << 0)
+
+#define RTCREG0_START_SER	BIT(17)
+#define RTCREG0_WAIT_SER	BIT(22)
+#define RTC_REG0_DATA(__data)	((__data) << 24)
+
+#define RTCREG1_READY		BIT(1)
+
+/* rtc registers accessed via rtc-serial interface */
+#define RTC_COUNTER		(0)
+#define RTC_SEC_ADJ		(2)
+
+#define RTC_ADDR_BITS		(3)	/* number of address bits to send */
+#define RTC_DATA_BITS		(32)	/* number of data bits to tx/rx */
+
+#define MESON_STATIC_BIAS_CUR	(0x5 << 1)
+#define MESON_STATIC_VOLTAGE	(0x3 << 11)
+#define MESON_STATIC_DEFAULT	(MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE)
+
+struct meson_rtc {
+	struct rtc_device	*rtc;	/* rtc device we created */
+	struct device		*dev;	/* device we bound from */
+	struct reset_control	*reset;	/* reset source */
+	struct mutex		lock;	/* rtc lock */
+	void __iomem		*regs;	/* rtc register access */
+};
+
+static void meson_rtc_setline(struct meson_rtc *rtc,
+			      unsigned int bit, unsigned int to)
+{
+	u32 reg0;
+
+	reg0 = readl(rtc->regs + RTC_REG(0));
+	if (to)
+		reg0 |= bit;
+	else
+		reg0 &= ~bit;
+	writel(reg0, rtc->regs + RTC_REG(0));
+}
+
+static void meson_rtc_sclk_pulse(struct meson_rtc *rtc)
+{
+	udelay(5);
+	meson_rtc_setline(rtc, LINE_SCLK, 0);
+	udelay(5);
+	meson_rtc_setline(rtc, LINE_SCLK, 1);
+}
+
+static void meson_rtc_send_bit(struct meson_rtc *rtc, unsigned int bit)
+{
+	meson_rtc_setline(rtc, LINE_SDI, bit ? 1 : 0);
+	meson_rtc_sclk_pulse(rtc);
+}
+
+static void meson_rtc_send_bits(struct meson_rtc *rtc, u32 data,
+				unsigned int nr)
+{
+	u32 bit = 1 << (nr - 1);
+
+	while (bit) {
+		meson_rtc_send_bit(rtc, data & bit);
+		bit >>= 1;
+	}
+}
+
+static void meson_rtc_set_dir(struct meson_rtc *rtc, u32 mode)
+{
+	meson_rtc_setline(rtc, LINE_SEN, 0);
+	meson_rtc_setline(rtc, LINE_SDI, 0);
+	meson_rtc_send_bit(rtc, mode);
+	meson_rtc_setline(rtc, LINE_SDI, 0);
+}
+
+static u32 meson_rtc_read_sdo(struct meson_rtc *rtc)
+{
+	return readl(rtc->regs + RTC_REG(1)) & BIT(0);
+}
+
+static u32 meson_rtc_get_data(struct meson_rtc *rtc)
+{
+	u32 val = 0;
+	int bit;
+
+	for (bit = 0; bit < RTC_DATA_BITS; bit++) {
+		meson_rtc_sclk_pulse(rtc);
+		val <<= 1;
+		val |= meson_rtc_read_sdo(rtc);
+	}
+
+	return val;
+}
+
+static int meson_rtc_wait_bus(struct meson_rtc *rtc, unsigned int timeout_ms)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	u32 val;
+
+	while (time_before(jiffies, timeout)) {
+		val = readl(rtc->regs + RTC_REG(1));
+		if (val & RTCREG1_READY)
+			return 1;
+
+		dev_dbg(rtc->dev, "%s: reg0=%08x reg1=%08x\n",
+			__func__, readl(rtc->regs + RTC_REG(0)), val);
+		msleep(10);
+	}
+
+	return 0;
+}
+
+static int meson_rtc_get_bus(struct meson_rtc *rtc)
+{
+	int ret, retries = 3;
+	u32 val;
+
+	val = readl(rtc->regs + RTC_REG(0));
+	val &= ~(LINE_SDI | LINE_SEN | LINE_SCLK);
+	writel(val, rtc->regs + RTC_REG(0));
+
+	while (retries) {
+		if (meson_rtc_wait_bus(rtc, 300))
+			return 0;
+
+		dev_warn(rtc->dev, "failed to get bus, re-setting\n");
+
+		retries--;
+		ret = reset_control_reset(rtc->reset);
+		if (ret)
+			return ret;
+	}
+
+	dev_err(rtc->dev, "%s: bus is not ready\n", __func__);
+	return -ETIMEDOUT;
+}
+
+static int meson_rtc_read(struct meson_rtc *rtc, unsigned int reg, u32 *data)
+{
+	int ret;
+
+	ret = meson_rtc_get_bus(rtc);
+	if (ret)
+		return ret;
+
+	meson_rtc_setline(rtc, LINE_SEN, 1);
+	meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS);
+	meson_rtc_set_dir(rtc, 0);
+	*data = meson_rtc_get_data(rtc);
+
+	return 0;
+}
+
+static int meson_rtc_write(struct meson_rtc *rtc, unsigned int reg, u32 data)
+{
+	int ret;
+
+	dev_dbg(rtc->dev, "%s: reg %d val %08x)\n", __func__, reg, data);
+
+	ret = meson_rtc_get_bus(rtc);
+	if (ret)
+		return ret;
+
+	meson_rtc_setline(rtc, LINE_SEN, 1);
+	meson_rtc_send_bits(rtc, data, RTC_DATA_BITS);
+	meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS);
+	meson_rtc_set_dir(rtc, 1);
+
+	return 0;
+}
+
+static int meson_rtc_gettime(struct device *dev, struct rtc_time *tm)
+{
+	struct meson_rtc *rtc = dev_get_drvdata(dev);
+	int ret;
+	u32 time;
+
+	mutex_lock(&rtc->lock);
+
+	ret = meson_rtc_read(rtc, RTC_COUNTER, &time);
+	if (!ret) {
+		rtc_time64_to_tm(time, tm);
+		dev_dbg(dev, "read time %u\n", time);
+	}
+
+	mutex_unlock(&rtc->lock);
+	return ret;
+}
+
+static int meson_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	struct meson_rtc *rtc = dev_get_drvdata(dev);
+	time64_t time;
+	int ret;
+
+	time = rtc_tm_to_time64(tm);
+	if (time >= ((time64_t)1 << 32)) {
+		dev_warn(dev, "%s: time is out of 32bit range\n", __func__);
+		return -ERANGE;
+	}
+
+	mutex_lock(&rtc->lock);
+	ret = meson_rtc_write(rtc, RTC_COUNTER, time);
+	mutex_unlock(&rtc->lock);
+	return ret;
+}
+
+static const struct rtc_class_ops meson_rtc_ops = {
+	.read_time	= meson_rtc_gettime,
+	.set_time	= meson_rtc_settime,
+};
+
+static int meson_rtc_wait_serialiser(struct meson_rtc *rtc)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+	while (time_before(jiffies, timeout)) {
+		if (!(readl(rtc->regs + RTC_REG(0)) & RTCREG0_WAIT_SER))
+			return 0;
+		msleep(10);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int meson_rtc_write_static(struct meson_rtc *rtc, u32 data)
+{
+	u32 tmp;
+
+	mutex_lock(&rtc->lock);
+
+	writel(data >> 8, rtc->regs + RTC_REG(4));
+
+	tmp = readl(rtc->regs + RTC_REG(0));
+	tmp &= ~RTC_REG0_DATA(0xff);
+	tmp |= RTC_REG0_DATA(data);
+	tmp |= RTCREG0_START_SER;
+
+	writel(tmp, rtc->regs + RTC_REG(0));
+
+	if (meson_rtc_wait_serialiser(rtc))
+		return -ETIMEDOUT;
+
+	dev_dbg(rtc->dev, "rtc_reg0 = %08x\n", readl(rtc->regs + RTC_REG(0)));
+	mutex_unlock(&rtc->lock);
+
+	return 0;
+}
+
+static int meson_rtc_probe(struct platform_device *pdev)
+{
+	struct meson_rtc *rtc;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	u32 tm;
+	int ret;
+
+	rtc = devm_kzalloc(dev, sizeof(struct meson_rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rtc->regs = devm_ioremap_resource(dev, res);
+	rtc->dev = dev;
+
+	if (IS_ERR(rtc->regs))
+		return PTR_ERR(rtc->regs);
+
+	mutex_init(&rtc->lock);
+	platform_set_drvdata(pdev, rtc);
+
+	ret = meson_rtc_write_static(rtc, MESON_STATIC_DEFAULT);
+	if (ret) {
+		dev_err(dev, "failed to set static values\n");
+		return ret;
+	}
+
+	rtc->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(rtc->reset))
+		dev_warn(dev, "no reset available, rtc may not work\n");
+
+	/* check if we can read RTC counter, if not then the RTC is probably
+	 * not functional. If it isn't probably best to not bind the device.
+	*/
+	ret = meson_rtc_read(rtc, RTC_COUNTER, &tm);
+	if (ret) {
+		dev_err(dev, "cannot read RTC counter, RTC not functional\n");
+		return ret;
+	}
+
+	rtc->rtc = devm_rtc_device_register(dev, "meson",
+					    &meson_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc))
+		return PTR_ERR(rtc->rtc);
+
+	return 0;
+}
+
+static const struct of_device_id meson_rtc_dt_match[] = {
+	{ .compatible = "amlogic,meson6-rtc", },
+	{ .compatible = "amlogic,meson8-rtc", },
+	{ .compatible = "amlogic,meson8b-rtc", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, meson_rtc_dt_match);
+
+static struct platform_driver meson_rtc_driver = {
+	.probe		= meson_rtc_probe,
+	.driver		= {
+		.name	= "meson-rtc",
+		.of_match_table	= of_match_ptr(meson_rtc_dt_match),
+	},
+};
+module_platform_driver(meson_rtc_driver);
+
+MODULE_DESCRIPTION("AMLogic MESON RTC Driver");
+MODULE_AUTHOR("Ben Dooks <ben.doosk at codethink.co.uk>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:meson-rtc");
-- 
2.9.3



From ben-linux at fluff.org  Mon Aug 22 15:15:01 2016
From: ben-linux at fluff.org (Ben Dooks)
Date: Mon, 22 Aug 2016 23:15:01 +0100
Subject: [PATCH 5/5] rtc: warn if rtc_tm_to_time64 overflows in rtc_tm_to_time
In-Reply-To: <20160822221501.21945-1-ben-linux@fluff.org>
References: <20160822221501.21945-1-ben-linux@fluff.org>
Message-ID: <20160822221501.21945-6-ben-linux@fluff.org>

The addition of the compatibility layer for rtc_tm_to_time()
to bridge the move to rtc_tm_to_time64() does not check if
the value will overflow the old call's use of unsigned long
to restore the result.

This means that if the result is bigger than the arch's
use of unsigned long then the result will be silently
truncated to whatever the maximum value of the unsigned
long. Since the call does not have an option of returning
an error, at least have an WARN_ON() to show if the value
is out of range.

Signed-off-by: Ben Dooks <ben-linux at fluff.org>
---
 include/linux/rtc.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index b693ada..ef7bb2c 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -45,7 +45,10 @@ static inline void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
  */
 static inline int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
 {
-	*time = rtc_tm_to_time64(tm);
+	time64_t tt = rtc_tm_to_time64(tm);
+
+	WARN_ON(tt > ~(0UL));
+	*time = tt;
 
 	return 0;
 }
-- 
2.9.3



From ben-linux at fluff.org  Mon Aug 22 15:14:58 2016
From: ben-linux at fluff.org (Ben Dooks)
Date: Mon, 22 Aug 2016 23:14:58 +0100
Subject: [PATCH 2/5] ARM: dts: amlogic: add rtc node for meson8b
In-Reply-To: <20160822221501.21945-1-ben-linux@fluff.org>
References: <20160822221501.21945-1-ben-linux@fluff.org>
Message-ID: <20160822221501.21945-3-ben-linux@fluff.org>

From: Ben Dooks <ben.dooks at codethink.co.uk>

Add the DT node for the RTC support.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
---
 arch/arm/boot/dts/meson8b.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index fc4080d..15a9d8d 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -156,6 +156,13 @@
 			status = "disabled";
 		};
 
+		rtc: rtc at c8100740 {
+			compatible = "amlogic,meson8b-rtc";
+			reg = <0xc8100740 0x14>;
+			resets = <&reset RESET_RTC>;
+			status = "disabled";
+		};
+
 		clkc: clock-controller at c1104000 {
 			#clock-cells = <1>;
 			compatible = "amlogic,meson8b-clkc";
-- 
2.9.3



From sudeep.holla at arm.com  Tue Aug 23 07:42:30 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 23 Aug 2016 15:42:30 +0100
Subject: [PATCH 03/13] scpi: Add legacy send, prepare and handle remote
 functions
In-Reply-To: <3d384710-c2c1-974f-c217-a2198d98ea22@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-4-git-send-email-narmstrong@baylibre.com>
 <b88c0ffc-09d2-4138-3007-b1e28c955cce@arm.com>
 <3d384710-c2c1-974f-c217-a2198d98ea22@baylibre.com>
Message-ID: <7dcd921d-e48f-ca46-2b86-4df3e332ff44@arm.com>



On 23/08/16 09:15, Neil Armstrong wrote:
> On 08/19/2016 06:13 PM, Sudeep Holla wrote:
>>
>>
>> On 18/08/16 11:10, Neil Armstrong wrote:
>>> In order to support the legacy SCPI procotol, add specific message_send,
>>> prepare_tx and handle_remote functions since the legacy procotol
>>> do not support message queuing and does not store the command word in the
>>> tx_payload data.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>> ---
>>>  drivers/firmware/arm_scpi.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 69 insertions(+)
>>>
>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>> index 0bb6134..50b1297 100644
>>> --- a/drivers/firmware/arm_scpi.c
>>> +++ b/drivers/firmware/arm_scpi.c

[..]

>>>
>>> +static void legacy_scpi_tx_prepare(struct mbox_client *c, void *__msg)
>>> +{
>>> +    struct scpi_chan *ch =
>>> +        container_of(c, struct scpi_chan, cl);
>>> +
>>> +    if (ch->t->tx_buf && ch->t->tx_len)
>>> +        memcpy_toio(ch->tx_payload, ch->t->tx_buf, ch->t->tx_len);
>>
>>
>> I see that you are not using the list. Any particular reason for that ?
>>
>> IMO, that *might* help to reuse more code, but I may be wrong. Let's see
>> Some commands like DVFS take more time compared to simple query type of
>> commands. Queuing does help there instead of blocking the channel until
>> the receipt of response.
>
> I'll like to use the list, but, the "cmd" value is not stored in the shared tx
> memory, so we cannot recover the original tranfer from reading the tx memory cmd.
>

Even in the current driver we read the mem->command and search the list
in scpi_process_cmd. Instead *(u32 *)msg gives the command value, no ?

> This is why I added a "struct scpi_xfer *t;" in the scpi_chan structure to store
> the current transfer.
>

I don't like that. I am trying to get rid of that.
1. list is not being used
2. scpi_xfer is stashed even though we have only one command in
    progress at any time in your case.

>>
>>> +}
>>> +
>>>  static int legacy_high_priority_cmds[] = {
>>>      LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
>>>      LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
>>> @@ -434,6 +461,48 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
>>>      mutex_unlock(&ch->xfers_lock);
>>>  }
>>>
>>> +static int legacy_scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
>>> +                void *rx_buf, unsigned int rx_len)
>>> +{
>>> +    int ret;
>>> +    u8 chan;
>>> +    struct scpi_xfer *msg;
>>> +    struct scpi_chan *scpi_chan;
>>> +
>>> +    chan = legacy_scpi_get_chan(cmd);
>>> +    scpi_chan = scpi_info->channels + chan;
>>> +
>>> +    msg = get_scpi_xfer(scpi_chan);
>>> +    if (!msg)
>>> +        return -ENOMEM;
>>> +
>>> +    mutex_lock(&scpi_chan->xfers_lock);
>>> +
>>
>> May be you can copy msg->cmd to msg->slot and that may help to reuse
>> more code or worst-case keep them aligned.
>
> Yes, it could be. But since the msg is not reused bu the tx_prepare and handle_response,
> we can pass anything here.

IIUC, we should be able to handle it using msg pte in handle_remote_msg

> And for the rockchip case, we must pass an xfer unrelated pointer here since they need
> a specially crafted memory structure for the mailbox.
>

We can consider that when they upstream the driver. Let's not consider
it now.

>>
>>> +    msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
>>> +    msg->tx_buf = tx_buf;
>>> +    msg->tx_len = tx_len;
>>> +    msg->rx_buf = rx_buf;
>>> +    msg->rx_len = rx_len;
>>> +    init_completion(&msg->done);
>>> +    scpi_chan->t = msg;
>>> +
>>> +    ret = mbox_send_message(scpi_chan->chan, &msg->cmd);
>>
>> If slot is initialized to cmd, then you can pass msg itself above.
>> Then you can evaluate how much this function deviates from
>> scpi_send_message and try to re-use.
>
> The function deviates quite a lot since the queing is not used.
>

You have not given me the reason for not using the list yet.
If the msg ptr is used in scpi_handle_remote_msg, you should be able to
make use of it.

>>
>>> +    if (ret < 0)
>>> +        goto out;
>>> +
>>> +    if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
>>> +        ret = -ETIMEDOUT;
>>> +    else
>>> +        /* first status word */
>>> +        ret = msg->status;
>>> +out:
>>> +    mutex_unlock(&scpi_chan->xfers_lock);
>>> +
>>> +    put_scpi_xfer(msg, scpi_chan);
>>> +    /* SCPI error codes > 0, translate them to Linux scale*/
>>> +    return ret > 0 ? scpi_to_linux_errno(ret) : ret;
>>> +}
>>> +
>>>  static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
>>>                     void *rx_buf, unsigned int rx_len, bool extn)
>>>  {
>>>
>>
>> [Nit]: Not sure if we need this as a separate patch. It might just
>> generate warnings, anyways we can merge into one later.
>
> I'll prefer to have functionnaly separate patches for now to clarify the changes.
> I'll eventually merge them for the final apply if needed.
>

Ah OK, then fine.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Aug 23 07:47:02 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 23 Aug 2016 15:47:02 +0100
Subject: [PATCH 04/13] scpi: Add legacy SCP functions calling
 legacy_scpi_send_message
In-Reply-To: <53093fb5-22e2-3c17-3345-50c7e9df7089@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-5-git-send-email-narmstrong@baylibre.com>
 <fe6919a2-a1dc-f056-9480-3248dc9315dc@arm.com>
 <53093fb5-22e2-3c17-3345-50c7e9df7089@baylibre.com>
Message-ID: <e31c0b43-a32f-bef9-c341-25783871f74f@arm.com>



On 23/08/16 09:19, Neil Armstrong wrote:
> On 08/19/2016 06:22 PM, Sudeep Holla wrote:
>>
>>
>> On 18/08/16 11:10, Neil Armstrong wrote:
>>> In order to support legacy SCP functions from kernel-wide driver, add legacy
>>> functions using the legacy command enums and calling legacy_scpi_send_message.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>> ---
>>>  drivers/firmware/arm_scpi.c | 118 ++++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 118 insertions(+)
>>>
>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>> index 50b1297..bb9965f 100644
>>> --- a/drivers/firmware/arm_scpi.c
>>> +++ b/drivers/firmware/arm_scpi.c
>>> @@ -578,6 +578,8 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
>>>      return ret;
>>>  }
>>>
>>> +/* scpi_clk_get_range not available for legacy */
>>> +
>>>  static unsigned long scpi_clk_get_val(u16 clk_id)
>>>  {
>>>      int ret;
>>> @@ -589,6 +591,18 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
>>>      return ret ? ret : le32_to_cpu(clk.rate);
>>>  }
>>>
>>> +static unsigned long legacy_scpi_clk_get_val(u16 clk_id)
>>> +{
>>> +    int ret;
>>> +    struct clk_get_value clk;
>>> +    __le16 le_clk_id = cpu_to_le16(clk_id);
>>> +
>>> +    ret = legacy_scpi_send_message(LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
>>> +                       &le_clk_id, sizeof(le_clk_id),
>>> +                       &clk, sizeof(clk));
>>> +    return ret ? ret : le32_to_cpu(clk.rate);
>>> +}
>>> +
>>>  static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>>>  {
>>>      int stat;
>>> @@ -601,6 +615,19 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
>>>                   &stat, sizeof(stat));
>>>  }
>>>
>>> +static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
>>> +{
>>> +    int stat;
>>> +    struct legacy_clk_set_value clk = {
>>> +        .id = cpu_to_le16(clk_id),
>>> +        .rate = cpu_to_le32(rate)
>>> +    };
>>> +
>>> +    return legacy_scpi_send_message(LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
>>> +                    &clk, sizeof(clk),
>>> +                    &stat, sizeof(stat));
>>
>> Except this one which has a different structure format, why do we need
>> to define legacy versions of other functions ? Can't we play with
>> function pointer or have a boolean in drvinfo structure and use then in
>> the existing functions as I had shown in one of the earlier emails.
>>
>
> The main problem is that the command indexes deviates starting at
> SCPI_CMD_SET_CSS_PWR_STATE, I'll be pleased to know how to implement it.
>

Yes, I was thinking of some kind of mapping to new index using an array.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Aug 23 07:50:01 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 23 Aug 2016 15:50:01 +0100
Subject: [PATCH 06/13] scpi: add priv_scpi_ops and fill legacy structure
In-Reply-To: <a0c9c4bc-cd83-c2e7-bfab-b8d24c886349@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-7-git-send-email-narmstrong@baylibre.com>
 <5c89a4e9-0100-0c67-1d6c-07651649172a@arm.com>
 <a0c9c4bc-cd83-c2e7-bfab-b8d24c886349@baylibre.com>
Message-ID: <cfbb96a6-4a90-01f2-591e-8f0853d7c06e@arm.com>



On 23/08/16 09:22, Neil Armstrong wrote:
> On 08/19/2016 06:39 PM, Sudeep Holla wrote:
>>
>>
>> On 18/08/16 11:10, Neil Armstrong wrote:
>>> In order to use the legacy functions variants, add a new priv_scpi_ops
>>> structure that will contain the internal alterne functions and then use these
>>> alternate call in the probe function.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>> ---
>>>  drivers/firmware/arm_scpi.c | 68 ++++++++++++++++++++++++++++++++++++++++++---
>>>  1 file changed, 64 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>> index b0d911b..3fe39fe 100644
>>> --- a/drivers/firmware/arm_scpi.c
>>> +++ b/drivers/firmware/arm_scpi.c
>>> @@ -213,6 +213,7 @@ struct scpi_drvinfo {
>>>      struct scpi_ops *scpi_ops;
>>>      struct scpi_chan *channels;
>>>      struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
>>> +    const struct priv_scpi_ops *ops;
>>>  };
>>>
>>>  /*
>>> @@ -299,6 +300,17 @@ struct dev_pstate_set {
>>>      u8 pstate;
>>>  } __packed;
>>>
>>> +struct priv_scpi_ops {
>>> +    /* Internal Specific Ops */
>>> +    void (*handle_remote_msg)(struct mbox_client *c, void *msg);
>>> +    void (*tx_prepare)(struct mbox_client *c, void *msg);
>>> +    /* Message Specific Ops */
>>> +    int (*init_versions)(struct scpi_drvinfo *info);
>>> +    int (*dvfs_get_info)(u8 domain, struct dvfs_info *buf);
>>> +    /* System wide Ops */
>>> +    struct scpi_ops *scpi_ops;
>>> +};
>>> +
>>
>>
>> I fail to understand the need for this. Can you please explain the issue
>> you would face without this ?
>>
>>>  static struct scpi_drvinfo *scpi_info;
>>>
>>>  static int scpi_linux_errmap[SCPI_ERR_MAX] = {
>>> @@ -695,9 +707,12 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
>>>      if (scpi_info->dvfs[domain])    /* data already populated */
>>>          return scpi_info->dvfs[domain];
>>>
>>> -    ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
>>> +    if (scpi_info->ops && scpi_info->ops->dvfs_get_info)
>>> +        ret = scpi_info->ops->dvfs_get_info(domain, &buf);
>>> +    else
>>> +        ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO,
>>> +                    &domain, sizeof(domain),
>>>                  &buf, sizeof(buf));
>>> -
>>>      if (ret)
>>>          return ERR_PTR(ret);
>>>
>>> @@ -855,6 +870,22 @@ static struct scpi_ops scpi_ops = {
>>>      .vendor_send_message = scpi_ext_send_message,
>>>  };
>>>
>>> +static struct scpi_ops legacy_scpi_ops = {
>>> +    .get_version = scpi_get_version,
>>> +    .clk_get_range = NULL,
>>> +    .clk_get_val = legacy_scpi_clk_get_val,
>>> +    .clk_set_val = legacy_scpi_clk_set_val,
>>> +    .dvfs_get_idx = legacy_scpi_dvfs_get_idx,
>>> +    .dvfs_set_idx = legacy_scpi_dvfs_set_idx,
>>> +    .dvfs_get_info = scpi_dvfs_get_info,
>>> +    .sensor_get_capability = legacy_scpi_sensor_get_capability,
>>> +    .sensor_get_info = legacy_scpi_sensor_get_info,
>>> +    .sensor_get_value = legacy_scpi_sensor_get_value,
>>> +    .device_get_power_state = NULL,
>>> +    .device_set_power_state = NULL,
>>> +    .vendor_send_message = legacy_scpi_send_message,
>>
>> I think we need not have this at all if you follow the suggestion I had
>> in the previous patch. Try and let's see how it would look.
>
> If you confirm you want the if/else as said in patch 4.
>
> But clk_get_range, device_get/set_power_state are not available in legacy,
> I think we should still have this alternate structure.
>

I was thinking of overriding the pointers accordingly at the probe time
as the common list is bigger than the one that differs.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Tue Aug 23 07:54:17 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 23 Aug 2016 15:54:17 +0100
Subject: [PATCH 07/13] scpi: ignore init_versions failure if reported not
 supported
In-Reply-To: <86c4042a-a892-b5c4-cc75-c2139e80e226@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>
 <74d35f80-8499-cadf-798c-9b296218305c@arm.com>
 <86c4042a-a892-b5c4-cc75-c2139e80e226@baylibre.com>
Message-ID: <5e627a97-88f6-c7cf-1d64-6439cb708aff@arm.com>



On 23/08/16 09:23, Neil Armstrong wrote:
> On 08/19/2016 06:46 PM, Sudeep Holla wrote:
>>
>>
>> On 18/08/16 11:11, Neil Armstrong wrote:
>>> In Amlogic GXBB Legacy SCPI, the LEGACY_SCPI_CMD_SCPI_CAPABILITIES report
>>> as SCPI_ERR_SUPPORT, so do not fail if this command is not supported.
>>>
>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>> ---
>>>  drivers/firmware/arm_scpi.c | 12 +++++++-----
>>>  1 file changed, 7 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>> index 3fe39fe..d3be4c5 100644
>>> --- a/drivers/firmware/arm_scpi.c
>>> +++ b/drivers/firmware/arm_scpi.c
>>> @@ -1111,12 +1111,13 @@ err:
>>>          ret = scpi_info->ops->init_versions(scpi_info);
>>>      else
>>>      ret = scpi_init_versions(scpi_info);
>>> -    if (ret) {
>>> +    if (ret && ret != -EOPNOTSUPP) {
>>>          dev_err(dev, "incorrect or no SCP firmware found\n");
>>>          scpi_remove(pdev);
>>>          return ret;
>>>      }
>>>
>>
>> Why not deal it in init_versions itself.
>>
>>> +    if (ret != -EOPNOTSUPP) {
>>>      _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
>>>            PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
>>>            PROTOCOL_REV_MINOR(scpi_info->protocol_version),
>>
>> Why not have default value like 0.0 ? Just add a comment. Since get
>> version is exported out, IMO having default value makes more sense. What
>> do you think ?
>>
>>> @@ -1124,15 +1125,16 @@ err:
>>>            FW_REV_MINOR(scpi_info->firmware_version),
>>>            FW_REV_PATCH(scpi_info->firmware_version));
>>>
>>> +        ret = sysfs_create_groups(&dev->kobj, versions_groups);
>>> +        if (ret)
>>> +            dev_err(dev, "unable to create sysfs version group\n");
>>> +    }
>>> +
>>
>> Again this can stay as is if we have default.
>>
>
> Printing version 0.0 firmware 0.0.0 is a nonsense for me...
>

OK 0.0 was a wrong example. May be 0.1 ?

Since the driver has already exposed, hypothetically user-space can use
that information, so IMO, we need to expose some static version for pre-v1.0

I am surprised that capability is not supported as this was present even
in that legacy SCPI. Do you know what happens if you send that command ?
Have you done some experiments on that ?

-- 
Regards,
Sudeep


From narmstrong at baylibre.com  Tue Aug 23 07:55:37 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 23 Aug 2016 16:55:37 +0200
Subject: [PATCH 07/13] scpi: ignore init_versions failure if reported not
 supported
In-Reply-To: <5e627a97-88f6-c7cf-1d64-6439cb708aff@arm.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>
 <74d35f80-8499-cadf-798c-9b296218305c@arm.com>
 <86c4042a-a892-b5c4-cc75-c2139e80e226@baylibre.com>
 <5e627a97-88f6-c7cf-1d64-6439cb708aff@arm.com>
Message-ID: <895da5b6-baec-daf8-814b-76bd9ebcbbbc@baylibre.com>

On 08/23/2016 04:54 PM, Sudeep Holla wrote:
> 
> 
> On 23/08/16 09:23, Neil Armstrong wrote:
>> On 08/19/2016 06:46 PM, Sudeep Holla wrote:
>>>
>>>
>>> On 18/08/16 11:11, Neil Armstrong wrote:
>>>> In Amlogic GXBB Legacy SCPI, the LEGACY_SCPI_CMD_SCPI_CAPABILITIES report
>>>> as SCPI_ERR_SUPPORT, so do not fail if this command is not supported.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>> ---
>>>>  drivers/firmware/arm_scpi.c | 12 +++++++-----
>>>>  1 file changed, 7 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>>> index 3fe39fe..d3be4c5 100644
>>>> --- a/drivers/firmware/arm_scpi.c
>>>> +++ b/drivers/firmware/arm_scpi.c
>>>> @@ -1111,12 +1111,13 @@ err:
>>>>          ret = scpi_info->ops->init_versions(scpi_info);
>>>>      else
>>>>      ret = scpi_init_versions(scpi_info);
>>>> -    if (ret) {
>>>> +    if (ret && ret != -EOPNOTSUPP) {
>>>>          dev_err(dev, "incorrect or no SCP firmware found\n");
>>>>          scpi_remove(pdev);
>>>>          return ret;
>>>>      }
>>>>
>>>
>>> Why not deal it in init_versions itself.
>>>
>>>> +    if (ret != -EOPNOTSUPP) {
>>>>      _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
>>>>            PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
>>>>            PROTOCOL_REV_MINOR(scpi_info->protocol_version),
>>>
>>> Why not have default value like 0.0 ? Just add a comment. Since get
>>> version is exported out, IMO having default value makes more sense. What
>>> do you think ?
>>>
>>>> @@ -1124,15 +1125,16 @@ err:
>>>>            FW_REV_MINOR(scpi_info->firmware_version),
>>>>            FW_REV_PATCH(scpi_info->firmware_version));
>>>>
>>>> +        ret = sysfs_create_groups(&dev->kobj, versions_groups);
>>>> +        if (ret)
>>>> +            dev_err(dev, "unable to create sysfs version group\n");
>>>> +    }
>>>> +
>>>
>>> Again this can stay as is if we have default.
>>>
>>
>> Printing version 0.0 firmware 0.0.0 is a nonsense for me...
>>
> 
> OK 0.0 was a wrong example. May be 0.1 ?
> 
> Since the driver has already exposed, hypothetically user-space can use
> that information, so IMO, we need to expose some static version for pre-v1.0
> 
> I am surprised that capability is not supported as this was present even
> in that legacy SCPI. Do you know what happens if you send that command ?
> Have you done some experiments on that ?
> 

I've experimented and returns EOPNOTSUPP, Amlogic confirmed to us the command was not implemented.

This a clearly a corner-case.

Neil


From sudeep.holla at arm.com  Tue Aug 23 08:01:24 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Tue, 23 Aug 2016 16:01:24 +0100
Subject: [PATCH 07/13] scpi: ignore init_versions failure if reported not
 supported
In-Reply-To: <895da5b6-baec-daf8-814b-76bd9ebcbbbc@baylibre.com>
References: <1471515066-3626-1-git-send-email-narmstrong@baylibre.com>
 <1471515066-3626-8-git-send-email-narmstrong@baylibre.com>
 <74d35f80-8499-cadf-798c-9b296218305c@arm.com>
 <86c4042a-a892-b5c4-cc75-c2139e80e226@baylibre.com>
 <5e627a97-88f6-c7cf-1d64-6439cb708aff@arm.com>
 <895da5b6-baec-daf8-814b-76bd9ebcbbbc@baylibre.com>
Message-ID: <584cd7fc-c6dd-d380-0842-ca663fa298ab@arm.com>



On 23/08/16 15:55, Neil Armstrong wrote:
> On 08/23/2016 04:54 PM, Sudeep Holla wrote:
>>
>>
>> On 23/08/16 09:23, Neil Armstrong wrote:
>>> On 08/19/2016 06:46 PM, Sudeep Holla wrote:
>>>>
>>>>
>>>> On 18/08/16 11:11, Neil Armstrong wrote:
>>>>> In Amlogic GXBB Legacy SCPI, the LEGACY_SCPI_CMD_SCPI_CAPABILITIES report
>>>>> as SCPI_ERR_SUPPORT, so do not fail if this command is not supported.
>>>>>
>>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>>> ---
>>>>>  drivers/firmware/arm_scpi.c | 12 +++++++-----
>>>>>  1 file changed, 7 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>>>> index 3fe39fe..d3be4c5 100644
>>>>> --- a/drivers/firmware/arm_scpi.c
>>>>> +++ b/drivers/firmware/arm_scpi.c
>>>>> @@ -1111,12 +1111,13 @@ err:
>>>>>          ret = scpi_info->ops->init_versions(scpi_info);
>>>>>      else
>>>>>      ret = scpi_init_versions(scpi_info);
>>>>> -    if (ret) {
>>>>> +    if (ret && ret != -EOPNOTSUPP) {
>>>>>          dev_err(dev, "incorrect or no SCP firmware found\n");
>>>>>          scpi_remove(pdev);
>>>>>          return ret;
>>>>>      }
>>>>>
>>>>
>>>> Why not deal it in init_versions itself.
>>>>
>>>>> +    if (ret != -EOPNOTSUPP) {
>>>>>      _dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n",
>>>>>            PROTOCOL_REV_MAJOR(scpi_info->protocol_version),
>>>>>            PROTOCOL_REV_MINOR(scpi_info->protocol_version),
>>>>
>>>> Why not have default value like 0.0 ? Just add a comment. Since get
>>>> version is exported out, IMO having default value makes more sense. What
>>>> do you think ?
>>>>
>>>>> @@ -1124,15 +1125,16 @@ err:
>>>>>            FW_REV_MINOR(scpi_info->firmware_version),
>>>>>            FW_REV_PATCH(scpi_info->firmware_version));
>>>>>
>>>>> +        ret = sysfs_create_groups(&dev->kobj, versions_groups);
>>>>> +        if (ret)
>>>>> +            dev_err(dev, "unable to create sysfs version group\n");
>>>>> +    }
>>>>> +
>>>>
>>>> Again this can stay as is if we have default.
>>>>
>>>
>>> Printing version 0.0 firmware 0.0.0 is a nonsense for me...
>>>
>>
>> OK 0.0 was a wrong example. May be 0.1 ?
>>
>> Since the driver has already exposed, hypothetically user-space can use
>> that information, so IMO, we need to expose some static version for pre-v1.0
>>
>> I am surprised that capability is not supported as this was present even
>> in that legacy SCPI. Do you know what happens if you send that command ?
>> Have you done some experiments on that ?
>>
>
> I've experimented and returns EOPNOTSUPP, Amlogic confirmed to us the command was not implemented.
>
> This a clearly a corner-case.
>

OK, thanks for the confirmation.
Not exporting anything could be kind of breaking ABI as it was not made
optional when introduced :( (you can blame me ;))

-- 
Regards,
Sudeep


From jbrunet at baylibre.com  Wed Aug 24 02:03:32 2016
From: jbrunet at baylibre.com (jbrunet)
Date: Wed, 24 Aug 2016 11:03:32 +0200
Subject: USB PHY documentation
In-Reply-To: <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>
References: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
 <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>
Message-ID: <1472029412.2322.13.camel@baylibre.com>

On Tue, 2016-08-23 at 14:30 +0100, Ben Dooks wrote:
> On 22/08/2016 22:39, Martin Blumenstingl wrote:
> > 
> > Hello,
> > 
> > last weekend I tried getting the USB PHY working on my GXBB device.
> > The simple part: resetting the USB part and enabling the clocks.
> > The tricky part: configuring the USB PHY registers
> > 
> > Unfortunately the public datasheet does not contain any information
> > about the USB PHY.
> > The reference driver does not contain many comments, the struct
> > members are using abbreviated names and it seems that a part of
> > what
> > should be done by the PHY driver is part of the dwc driver
> > (usb_peri_reg changes were patched into it).
> > I am now wondering if someone can share some details from the?
> > datasheet.
> > 
> > I took my register #defines from the reference driver (and tried to
> > make them human readable): [0]
> > There are some USB_PHY_CLK_SEL_* definitions at the bottom which
> > seem
> > interesting (at least for configuring REG_CONFIG_CLK_SEL, but
> > unfortunately I don't know if these are valid (for either meson8b
> > or
> > gxbb)..
> > 
> > Symptoms are: dwc2's USB initialization is successful, but when I?
> > plug
> > in a device it's not being detected.
> > I *think* that my problem is that REG_ADP_BC_DRV_VBUS is a readonly
> > bit - it's set when I use the original firmware of my device, but I
> > cannot set it in my PHY driver.
> > 
> > In case anyone is interested how my changes look exactly, you can?
> > find
> > the code here: [1]
> > 
> > I also dumped the USB PHY registers from the original Android?
> > firmware
> > of my device in case anyone is interested:
> > phy0:
> > [0xc0000000] = 0x8000
> > [0xc0000004] = 0x1690500
> > [0xc0000008] = 0x0
> > [0xc000000c] = 0x8E18
> > [0xc0000010] = 0x0
> > [0xc0000014] = 0x80000
> > [0xc0000018] = 0x246613D
> > [0xc000001c] = 0x0
> > 
> > phy1:
> > [0xc0000020] = 0x8000
> > [0xc0000024] = 0x1690500
> > [0xc0000028] = 0x0
> > [0xc000002c] = 0x2010118
> > [0xc0000030] = 0x0
> > [0xc0000034] = 0x80000
> > [0xc0000038] = 0xE46613D
> > [0xc000003c] = 0x0
> > 
> > @Ben: did you get anywhere with your experiments on Meson8b (S805)?
> 
> I did a PHY driver and some updates to the dwc2 driver, but could
> not get a reliable USB session going. I'll post my PHY driver later
> as it's still in bits and needs to be made into a semi-coherent patch
> set.
> 
> 
@Martin: I tried your patch and just done a few corrections, mainly
interrupt numbers in the device tree and otg_cap in amlogic_params in
dwc2 driver. the code is here [2]

The host controller seems to be working well on the p200, I'm still
checking the otg controller.

Regards
Jerome

[2]: https://github.com/jeromebrunet/linux/commits/amlogic/v4.8/usb


From martin.blumenstingl at googlemail.com  Wed Aug 24 03:19:56 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Wed, 24 Aug 2016 12:19:56 +0200
Subject: USB PHY documentation
In-Reply-To: <1472029412.2322.13.camel@baylibre.com>
References: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
 <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>
 <1472029412.2322.13.camel@baylibre.com>
Message-ID: <CAFBinCDFXZUUB2AaQU9v_DjsLN+6ciLRBv4_cBgtBu8++OT2Ww@mail.gmail.com>

Hi Jerome,

On Wed, Aug 24, 2016 at 11:03 AM, jbrunet <jbrunet at baylibre.com> wrote:
>> > In case anyone is interested how my changes look exactly, you can
>> > find
>> > the code here: [1]
> @Martin: I tried your patch and just done a few corrections, mainly
> interrupt numbers in the device tree and otg_cap in amlogic_params in
> dwc2 driver. the code is here [2]
>
> The host controller seems to be working well on the p200, I'm still
> checking the otg controller.
oh, interrupt numbering is different in the reference kernel! Many
thanks for testing and figuring this out!

I can continue working on this on Friday / Saturday.
But if you want to go ahead and finish the patches: feel free to do so.


From ulf.hansson at linaro.org  Wed Aug 24 04:53:08 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 24 Aug 2016 13:53:08 +0200
Subject: [PATCH v2 2/2] MMC: meson: initial support for GXBB platforms
In-Reply-To: <20160803231843.23012-2-khilman@baylibre.com>
References: <20160803231843.23012-1-khilman@baylibre.com>
 <20160803231843.23012-2-khilman@baylibre.com>
Message-ID: <CAPDyKFpPCkCRB436zdZ664st9xwA6wTWkFtT=U4HTwwAn-_emg@mail.gmail.com>

On 4 August 2016 at 01:18, Kevin Hilman <khilman at baylibre.com> wrote:
> Initial support for the SD/eMMC controller in the Amlogic S905/GXBB
> family of SoCs.
>
> Currently working for the SD and eMMC interfaces, but not yet tested
> for SDIO.
>
> Tested external SD card and internal eMMC on meson-gxbb-p200 and
> meson-gxbb-odroidc2.
>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>
> ---
>  MAINTAINERS                   |   1 +
>  drivers/mmc/host/Kconfig      |  10 +
>  drivers/mmc/host/Makefile     |   1 +
>  drivers/mmc/host/meson-gxbb.c | 918 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 930 insertions(+)
>  create mode 100644 drivers/mmc/host/meson-gxbb.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7304d2e37a98..3762e46811f3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -972,6 +972,7 @@ F:  arch/arm/mach-meson/
>  F:     arch/arm/boot/dts/meson*
>  F:     arch/arm64/boot/dts/amlogic/
>  F:     drivers/pinctrl/meson/
> +F:      drivers/mmc/host/meson*
>  N:     meson
>
>  ARM/Annapurna Labs ALPINE ARCHITECTURE
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 0aa484c10c0a..4c3d091f7548 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -332,6 +332,16 @@ config MMC_SDHCI_IPROC
>
>           If unsure, say N.
>
> +config MMC_MESON_GXBB
> +       tristate "Amlogic S905/GXBB SD/MMC Host Controller support"
> +       depends on ARCH_MESON && MMC
> +       help
> +         This selects support for the Amlogic SD/MMC Host Controller
> +         found on the S905/GXBB family of SoCs.  This controller is
> +         MMC 5.1 compliant and support SD, eMMC and SDIO interfaces.
> +
> +         If you have a controller with this interface, say Y here.
> +
>  config MMC_MOXART
>         tristate "MOXART SD/MMC Host Controller support"
>         depends on ARCH_MOXART && MMC
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index af918d261ff9..3e0de57f55b9 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740)      += jz4740_mmc.o
>  obj-$(CONFIG_MMC_VUB300)       += vub300.o
>  obj-$(CONFIG_MMC_USHC)         += ushc.o
>  obj-$(CONFIG_MMC_WMT)          += wmt-sdmmc.o
> +obj-$(CONFIG_MMC_MESON_GXBB)   += meson-gxbb.o
>  obj-$(CONFIG_MMC_MOXART)       += moxart-mmc.o
>  obj-$(CONFIG_MMC_SUNXI)                += sunxi-mmc.o
>  obj-$(CONFIG_MMC_USDHI6ROL0)   += usdhi6rol0.o
> diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
> new file mode 100644
> index 000000000000..10eac41cf31a
> --- /dev/null
> +++ b/drivers/mmc/host/meson-gxbb.c
> @@ -0,0 +1,918 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman at baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman at baylibre.com>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */

Lots of licence text. Isn't it enough to state dual BSD/GPLv2?

[...]

> +
> +struct meson_host {
> +       struct  device          *dev;
> +       struct  mmc_host        *mmc;
> +       struct  mmc_request     *mrq;
> +       struct  mmc_command     *cmd;
> +
> +       spinlock_t lock;
> +       void __iomem *regs;
> +#ifdef USE_REGMAP
> +       struct regmap *regmap;
> +#endif
> +       int irq;
> +       u32 ocr_mask;
> +       struct clk *core_clk;
> +       struct clk_mux mux;
> +       struct clk *mux_clk;
> +       struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
> +       unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
> +
> +       struct clk_divider cfg_div;
> +       struct clk *cfg_div_clk;
> +
> +       unsigned int bounce_buf_size;
> +       void *bounce_buf;
> +       dma_addr_t bounce_dma_addr;
> +
> +       unsigned long clk_rate;
> +       unsigned long clk_src_rate;
> +       unsigned short clk_src_div;
> +};
> +
> +#define reg_read(host, offset) readl(host->regs + offset)
> +#define reg_write(host, offset, val) writel(val, host->regs + offset)

I am not a fan of macros, especially when I don't think they improves the code.

Could we just stick to use readl/writel() directly instead!?

[...]

> +static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
> +{
> +       struct mmc_host *mmc = host->mmc;
> +       int ret = 0;
> +       u32 cfg;
> +
> +       if (clk_rate) {
> +               if (WARN_ON(clk_rate > mmc->f_max))
> +                       clk_rate = mmc->f_max;
> +               else if (WARN_ON(clk_rate < mmc->f_min))
> +                       clk_rate = mmc->f_min;
> +       }
> +
> +       if (clk_rate == host->clk_rate)
> +               return 0;
> +
> +       /* stop clock */
> +       cfg = reg_read(host, SD_EMMC_CFG);
> +       if (!(cfg & CFG_STOP_CLOCK)) {
> +               cfg |= CFG_STOP_CLOCK;
> +               reg_write(host, SD_EMMC_CFG, cfg);
> +       }
> +
> +       dev_dbg(host->dev, "change clock rate %lu -> %lu\n",
> +               host->clk_rate, clk_rate);
> +       ret = clk_set_rate(host->cfg_div_clk, clk_rate);
> +       if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
> +               dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
> +                        clk_rate, clk_get_rate(host->cfg_div_clk), ret);
> +       else
> +               host->clk_rate = clk_rate;
> +
> +       /* (re)start clock, if non-zero */
> +       if (clk_rate) {
> +               cfg = reg_read(host, SD_EMMC_CFG);
> +               cfg &= ~CFG_STOP_CLOCK;
> +               reg_write(host, SD_EMMC_CFG, cfg);
> +       }

You probably want to update mmc->actual_clock, which is useful for
debugging purpose.

> +
> +       return ret;
> +}
> +
> +static int meson_mmc_clk_init(struct meson_host *host)
> +{
> +       struct clk_init_data init;
> +       char clk_name[32];
> +       int i, ret = 0;
> +       const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
> +       unsigned int mux_parent_count = 0;
> +       const char *clk_div_parents[1];
> +       unsigned int f_min = UINT_MAX;
> +       u32 clk_reg, cfg;
> +
> +       /* get the mux parents from DT */
> +       for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
> +               char name[16];
> +
> +               snprintf(name, sizeof(name), "clkin%d", i);
> +               host->mux_parent[i] = devm_clk_get(host->dev, name);
> +               if (IS_ERR(host->mux_parent[i])) {
> +                       ret = PTR_ERR(host->mux_parent[i]);
> +                       if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
> +                               dev_err(host->dev, "Missing clock %s\n", name);
> +                       host->mux_parent[i] = NULL;
> +                       return ret;
> +               }
> +
> +               host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
> +               mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
> +               mux_parent_count++;
> +               if (host->mux_parent_rate[i] < f_min)
> +                       f_min = host->mux_parent_rate[i];
> +       }
> +
> +       /* cacluate f_min based on input clocks, and max divider value */
> +       if (f_min != UINT_MAX)
> +               f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
> +       else
> +               f_min = 4000000;  /* default min: 400 MHz */
> +       host->mmc->f_min = f_min;
> +
> +       /* create the mux */
> +       snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
> +       init.name = clk_name;
> +       init.ops = &clk_mux_ops;
> +       init.flags = CLK_IS_BASIC;
> +       init.parent_names = mux_parent_names;
> +       init.num_parents = mux_parent_count;
> +
> +       host->mux.reg = host->regs + SD_EMMC_CLOCK;
> +       host->mux.shift = CLK_SRC_SHIFT;
> +       host->mux.mask = CLK_SRC_MASK;
> +       host->mux.flags = 0;
> +       host->mux.table = NULL;
> +       host->mux.hw.init = &init;
> +
> +       host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);

I think it would make sense to add a comment here to clarify why you
register a clock like this.

I assume it's beacuse you benefit from the clock framwork about
acheiving the best/closest reqeust clockrate, as it take into account
muxes/parent clocks as well!?

> +       if (WARN_ON(PTR_ERR_OR_ZERO(host->mux_clk)))
> +               return PTR_ERR(host->mux_clk);
> +
> +       /* create the divider */
> +       snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
> +       init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
> +       init.ops = &clk_divider_ops;
> +       init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
> +       clk_div_parents[0] = __clk_get_name(host->mux_clk);
> +       init.parent_names = clk_div_parents;
> +       init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +       host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
> +       host->cfg_div.shift = CLK_DIV_SHIFT;
> +       host->cfg_div.width = CLK_DIV_WIDTH;
> +       host->cfg_div.hw.init = &init;
> +       host->cfg_div.flags = CLK_DIVIDER_ONE_BASED |
> +               CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
> +
> +       host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);

Ditto.

> +       if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
> +               return PTR_ERR(host->cfg_div_clk);
> +
> +       /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> +       clk_reg = 0;
> +       clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
> +       clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
> +       clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
> +       clk_reg &= ~CLK_ALWAYS_ON;
> +       reg_write(host, SD_EMMC_CLOCK, clk_reg);
> +
> +       clk_prepare_enable(host->cfg_div_clk);
> +
> +       /* Ensure clock starts in "auto" mode, not "always on" */
> +       cfg = reg_read(host, SD_EMMC_CFG);
> +       cfg &= ~CFG_CLK_ALWAYS_ON;
> +       cfg |= CFG_AUTO_CLK;
> +       reg_write(host, SD_EMMC_CFG, cfg);
> +
> +       meson_mmc_clk_set(host, f_min);
> +
> +       return ret;
> +}
> +
> +static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> +       struct meson_host *host = mmc_priv(mmc);
> +       u32 bus_width;
> +       u32 val, orig;
> +
> +       /*
> +        * GPIO regulator, only controls switching between 1v8 and
> +        * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON.
> +        */

I don't follow. Shouldn't you call regulator_enable|disable() for the
above regulator? Why not?

> +       switch (ios->power_mode) {
> +       case MMC_POWER_UP:
> +               if (!IS_ERR(mmc->supply.vmmc))
> +                       mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);

The above comment talks about 1v8 and 3v3, which seems to me that you
are changing the I/O voltage, but that's not what *vmmc* should be
used for.

If this is about I/O voltage, you shall instead use *vqmmc* and the
corresponding mmc_regulator_set_vqmmc() to change the voltage level.

This also leaves me to ask, then how do you control the power to the
card? This is actually what the *vmmc* should be used for.

> +       }
> +
> +       meson_mmc_clk_set(host, ios->clock);
> +
> +       /* Bus width */
> +       val = reg_read(host, SD_EMMC_CFG);
> +       switch (ios->bus_width) {
> +       case MMC_BUS_WIDTH_1:
> +               bus_width = CFG_BUS_WIDTH_1;
> +               break;
> +       case MMC_BUS_WIDTH_4:
> +               bus_width = CFG_BUS_WIDTH_4;
> +               break;
> +       case MMC_BUS_WIDTH_8:
> +               bus_width = CFG_BUS_WIDTH_8;
> +               break;
> +       default:
> +               dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n",
> +                       ios->bus_width);
> +               bus_width = CFG_BUS_WIDTH_4;
> +               return;
> +       }
> +
> +       val = reg_read(host, SD_EMMC_CFG);
> +       orig = val;
> +
> +       val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT);
> +       val |= bus_width << CFG_BUS_WIDTH_SHIFT;
> +
> +       val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
> +       val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
> +
> +       val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT);
> +       val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
> +
> +       val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT);
> +       val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
> +
> +       reg_write(host, SD_EMMC_CFG, val);
> +
> +       if (val != orig)
> +               dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
> +                       __func__, orig, val);
> +}
> +

[...]

> +
> +static int meson_mmc_probe(struct platform_device *pdev)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct resource *res;
> +       struct meson_host *host;
> +       struct mmc_host *mmc;
> +       int ret;
> +
> +       mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
> +       if (!mmc)
> +               return -ENOMEM;
> +       host = mmc_priv(mmc);
> +       host->mmc = mmc;
> +       host->dev = &pdev->dev;
> +       dev_set_drvdata(&pdev->dev, host);
> +
> +       spin_lock_init(&host->lock);
> +
> +       host->core_clk = devm_clk_get(&pdev->dev, "core");
> +       if (IS_ERR(host->core_clk)) {
> +               ret = PTR_ERR(host->core_clk);
> +               if (ret == -EPROBE_DEFER)
> +                       dev_dbg(&pdev->dev,
> +                               "Missing core clock.  EPROBE_DEFER\n");
> +               else
> +                       dev_err(&pdev->dev,
> +                               "Unable to get core clk (ret=%d).\n", ret);

I think these prints are unessarry, they should be printed by other
frameworks already, right!?

> +               goto free_host;
> +       }
> +
> +       /* Voltage supply */
> +       mmc_of_parse_voltage(np, &host->ocr_mask);

This looks odd.

Usally we get "ocr_avail" when asking the vmmc regulator about its
supported voltage range, via calling the below
mmc_regulator_get_supply() API. Can you explain why thay isn't work
for you?

> +       ret = mmc_regulator_get_supply(mmc);
> +       if (ret == -EPROBE_DEFER) {
> +               dev_dbg(&pdev->dev, "Missing regulator: EPROBE_DEFER");

The print shouldn't be needed, please remove.

> +               goto free_host;
> +       }
> +
> +       if (!mmc->ocr_avail)
> +               mmc->ocr_avail = host->ocr_mask;

mmc->ocr_avail needs to be assigned to a valid value. This fallback
doesn't cover that as host->ocr_mask may very well be zero.

> +
> +       ret = mmc_of_parse(mmc);
> +       if (ret) {
> +               dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
> +               goto free_host;
> +       }
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!res) {
> +               ret = -ENODEV;
> +               goto free_host;
> +       }
> +       host->regs = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(host->regs)) {
> +               ret = PTR_ERR(host->regs);
> +               goto free_host;
> +       }
> +
> +       host->irq = platform_get_irq(pdev, 0);
> +       if (host->irq == 0) {
> +               dev_err(&pdev->dev, "failed to get interrupt resource.\n");
> +               ret = -EINVAL;
> +               goto free_host;
> +       }
> +
> +       ret = devm_request_threaded_irq(&pdev->dev, host->irq,
> +                                       meson_mmc_irq, meson_mmc_irq_thread,
> +                                       IRQF_SHARED, DRIVER_NAME, host);
> +       if (ret)
> +               goto free_host;
> +
> +       /* data bounce buffer */
> +       host->bounce_buf_size = SZ_512K;
> +       host->bounce_buf =
> +               dma_alloc_coherent(host->dev, host->bounce_buf_size,
> +                                  &host->bounce_dma_addr, GFP_KERNEL);
> +       if (host->bounce_buf == NULL) {
> +               dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
> +               ret = -ENOMEM;
> +               goto free_host;
> +       }
> +
> +       clk_prepare_enable(host->core_clk);
> +
> +       ret = meson_mmc_clk_init(host);
> +       if (ret)
> +               goto free_host;
> +
> +       /* Stop execution */
> +       reg_write(host, SD_EMMC_START, 0);
> +
> +       /* clear, ack, enable all interrupts */
> +       reg_write(host, SD_EMMC_IRQ_EN, 0);
> +       reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
> +
> +       mmc->ops = &meson_mmc_ops;
> +       mmc_add_host(mmc);
> +
> +       return 0;
> +
> +free_host:
> +       dev_dbg(host->dev, "Failed to probe: ret=%d\n", ret);
> +       if (host->core_clk)
> +               clk_disable_unprepare(host->core_clk);
> +       mmc_free_host(mmc);
> +       return ret;
> +}
> +

[...]

> +
> +static const struct of_device_id meson_mmc_of_match[] = {
> +       {
> +               .compatible = "amlogic,meson-gxbb-mmc",

You need to fold in a DT documentation patch, in this series as to
describe all the required/optional resourses for the device. That of
course also includes the compatible string.

> +       },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, meson_mmc_of_match);

Kind regards
Uffe


From linus.walleij at linaro.org  Wed Aug 24 05:23:15 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 24 Aug 2016 14:23:15 +0200
Subject: [PATCH v2 1/2] pinctrl: meson-gxbb: add pins for PWM
In-Reply-To: <1471951508-29620-2-git-send-email-narmstrong@baylibre.com>
References: <1471951508-29620-1-git-send-email-narmstrong@baylibre.com>
 <1471951508-29620-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdaz+6=QFB-0pp-3hes=Do17eNDWxgHyFacEKsskSd+7UQ@mail.gmail.com>

On Tue, Aug 23, 2016 at 1:25 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:

> Add support for PWM pins, for EE and AO domains.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Patch applied!

Yours,
Linus Walleij


From sboyd at codeaurora.org  Wed Aug 24 10:29:44 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 24 Aug 2016 10:29:44 -0700
Subject: [PATCH -next] clk: meson: Fix invalid use of sizeof in
 gxbb_aoclkc_probe()
In-Reply-To: <1471882101-22347-1-git-send-email-weiyj.lk@gmail.com>
References: <1471882101-22347-1-git-send-email-weiyj.lk@gmail.com>
Message-ID: <20160824172944.GA19826@codeaurora.org>

On 08/22, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1 at huawei.com>
> 
> sizeof() when applied to a pointer typed expression gives the
> size of the pointer, not that of the pointed data.
> 
> Signed-off-by: Wei Yongjun <weiyongjun1 at huawei.com>
> ---

Applied to clk-next

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


From mturquette at baylibre.com  Wed Aug 24 16:09:10 2016
From: mturquette at baylibre.com (Michael Turquette)
Date: Wed, 24 Aug 2016 16:09:10 -0700
Subject: [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add GXBB AO Clock and
 Reset node
In-Reply-To: <7hk2fc76xx.fsf@baylibre.com>
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
 <1471514928-3341-4-git-send-email-narmstrong@baylibre.com>
 <7hk2fc76xx.fsf@baylibre.com>
Message-ID: <147208015014.66208.14165603610884470316@resonance>

Quoting Kevin Hilman (2016-08-19 15:03:06)
> Neil Armstrong <narmstrong at baylibre.com> writes:
> 
> > Add the AO clock controller node for the AmLogic GXBB SoC.
> >
> > Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> > ---
> 
> Applying this to the amlogic tree, but will need to wait a cycle due to
> include dependencies on the bindings, which are going through the clock
> tree.

FYI, for picked patches, Stephen and I create a stable branch for each
platform. You can pull this into your tree if you want, just let us know
so we'll be sure not to rebase:

git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-meson-gxbb-ao

Regards,
Mike

> 
> Kevin


From mturquette at baylibre.com  Wed Aug 24 17:24:39 2016
From: mturquette at baylibre.com (Michael Turquette)
Date: Wed, 24 Aug 2016 17:24:39 -0700
Subject: [PATCH v4 0/6] Add Amlogic meson8b clock gates
In-Reply-To: <1469800864-43440-1-git-send-email-serveralex@gmail.com>
References: <1469800864-43440-1-git-send-email-serveralex@gmail.com>
Message-ID: <147208467939.32728.10815386393422927131@resonance>

Quoting Alexander M?ller (2016-07-29 07:00:58)
> This patch series adds support for the Amlogic meson8b clock gates. The Amlogic
> U-Boot disables most of them at boot. In order to enable ethernet, USB and other
> components it's mandatory to enable the clock gates when loading the corresponding
> drivers.
> 
> The meson8b clock gate support is based on the previous work done for Amlogic gxbb
> currently available in clk-next.

Hi Alexander,

This series looks good to me. Can you rebase it against the
clk-meson-gxbb-ao branch?

git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-meson-gxbb-ao

I'll merge it on top of that and Kevin and Carlo can pull it into the
linux-amlogic tree if they feel like it.

Regards,
Mike

> 
> Changes since v3:
>   - Include include/dt-bindings/clock/meson8b-clkc.h to prevent code duplicates
> 
> Changes since v2:
>   - Added commit description for patch 2
>   - Changed CLK_NR_CLOCKS macro to constant int
>   - Moved back MESON_GATE macro to share it between gxbb and meson8b
> 
> Changes since v1:
>   - Fixed GXBB spelling
>   - Moved newly introduced CLKID defines to private header
>   - Moved CLK_NR_CLKS define from DT binding to private header
>   - Rebased to linux-amlogic/v4.7/integ making Kconfig select obsolete
> 
> Alexander M?ller (6):
>   clk: meson: Rename meson8b-clkc.c to reflect gxbb naming convention
>   meson: clk: Move register definitions to meson8b.h
>   meson: clk: Rename register names according to Amlogic datasheet
>   clk: meson: Copy meson8b CLKID defines to private header file
>   gxbb: clk: Adjust MESON_GATE macro to be shared with meson8b
>   meson: clk: Add support for clock gates
> 
>  drivers/clk/meson/Makefile                      |   2 +-
>  drivers/clk/meson/clkc.h                        |   2 +-
>  drivers/clk/meson/gxbb.c                        | 162 ++++++-------
>  drivers/clk/meson/{meson8b-clkc.c => meson8b.c} | 293 +++++++++++++++++++++---
>  drivers/clk/meson/meson8b.h                     | 151 ++++++++++++
>  include/dt-bindings/clock/meson8b-clkc.h        |   2 -
>  6 files changed, 497 insertions(+), 115 deletions(-)
>  rename drivers/clk/meson/{meson8b-clkc.c => meson8b.c} (52%)
>  create mode 100644 drivers/clk/meson/meson8b.h
> 
> -- 
> 2.5.0
> 


From mchehab at s-opensource.com  Thu Aug 25 05:41:14 2016
From: mchehab at s-opensource.com (Mauro Carvalho Chehab)
Date: Thu, 25 Aug 2016 09:41:14 -0300
Subject: [PATCH v4 4/6] media: rc: meson-ir: Add support for newer
 versions of the IR decoder
In-Reply-To: <7hy43s5r7d.fsf@baylibre.com>
References: <20160628191802.21227-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160819215547.20063-5-martin.blumenstingl@googlemail.com>
 <7hy43s5r7d.fsf@baylibre.com>
Message-ID: <20160825094114.2ca0a9e9@vento.lan>

Em Fri, 19 Aug 2016 15:28:22 -0700
Kevin Hilman <khilman at baylibre.com> escreveu:

> Martin Blumenstingl <martin.blumenstingl at googlemail.com> writes:
> 
> > From: Neil Armstrong <narmstrong at baylibre.com>
> >
> > Newer SoCs (Meson 8b and GXBB) are using REG2 (offset 0x20) instead of
> > REG1 to configure the decoder mode. This makes it necessary to
> > introduce new bindings so the driver knows which register has to be
> > used.
> >
> > Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> > Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>  
> 
> Acked-by: Kevin Hilman <khilman at baylibre.com>
> 
> Mauro, are you the one to pick up new media/rc drivers?  Or if you
> prefer, with your ack, I'll take this along with the DT and submit via
> arm-soc.

I generally pick new media rc drivers, but in the specific case of this
patchset, it is just adding a few extra lines to existing drivers, and
most of the work are actually at the ARM tree.

So, feel free to merge via arm-soc with my ack:

Acked-by: Mauro Carvalho Chehab <mchehab at s-opensource.com>

> 
> Thanks,
> 
> Kevin
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



Thanks,
Mauro


From narmstrong at baylibre.com  Thu Aug 25 06:18:31 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 25 Aug 2016 15:18:31 +0200
Subject: [PATCH v2 0/7] scpi: Add support for legacy SCPI protocol
In-Reply-To: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <f6c7249f-f103-fd91-2c89-a30c191427aa@baylibre.com>

On 08/23/2016 01:46 PM, Neil Armstrong wrote:
> This patchset aims to support the legacy SCPI firmware implementation that was
> delivered as early technology preview for the JUNO platform.
> 
> Finally a stable, maintained and public implementation for the SCPI protocol
> has been upstreamed part of the JUNO support and it is the recommended way
> of implementing SCP communication on ARMv8 platforms.
> 
> The Amlogic GXBB platform is using this legacy protocol, as the RK3368 & RK3399
> platforms. This patchset will only add support for Amlogic GXBB SoC.
> 
> This patchset add support for the legacy protocol in the arm_scpi.c file,
> avoiding code duplication.
> 
> Last RFC discution tread can be found at : https://lkml.org/lkml/2016/8/9/210
> 
> The last patch depends on the "Platform MHU" dtsi patch.
> 
> Changes since v1 at : http://lkml.kernel.org/r/1471515066-3626-1-git-send-email-narmstrong at baylibre.com
>  - Dropped vendor_send_message and rockchip vendor mechanism patches
>  - Merged alternate functions into main functions using is_legacy boolean
>  - Added DT match table to set is_legacy to true
>  - Kept alternate scpi_ops structure for legacy
> 
> Neil Armstrong (7):
>   scpi: Add alternative legacy structures, functions and macros
>   scpi: Use legacy variants command index calling scpi_send_message
>   scpi: Add support for Legacy match table for Amlogic GXBB SoC
>   scpi: grow MAX_DVFS_OPPS to 16 entries
>   dt-bindings: Add support for Amlogic GXBB SCPI Interface
>   ARM64: dts: meson-gxbb: Add SRAM node
>   ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes
> 
>  Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++++
>  drivers/firmware/arm_scpi.c                        | 279 +++++++++++++++++++--
>  3 files changed, 302 insertions(+), 30 deletions(-)
> 

Hi Sudeep,

Sorry but I posted this V2 before you had time to look at my previous v1 replies...

In this serie, I merged the scpi_send_message, but I must still evaluate how it's possible
to use the list to queue commands.

Here I used if(is_legacy) to stop duplicating functions, is this ok for you ?

Thanks,
Neil


From sudeep.holla at arm.com  Thu Aug 25 06:45:58 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 25 Aug 2016 14:45:58 +0100
Subject: [PATCH v2 0/7] scpi: Add support for legacy SCPI protocol
In-Reply-To: <f6c7249f-f103-fd91-2c89-a30c191427aa@baylibre.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
 <f6c7249f-f103-fd91-2c89-a30c191427aa@baylibre.com>
Message-ID: <73cce388-219d-2daa-811a-059c3d84c2e4@arm.com>



On 25/08/16 14:18, Neil Armstrong wrote:
> On 08/23/2016 01:46 PM, Neil Armstrong wrote:
>> This patchset aims to support the legacy SCPI firmware implementation that was
>> delivered as early technology preview for the JUNO platform.
>>
>> Finally a stable, maintained and public implementation for the SCPI protocol
>> has been upstreamed part of the JUNO support and it is the recommended way
>> of implementing SCP communication on ARMv8 platforms.
>>
>> The Amlogic GXBB platform is using this legacy protocol, as the RK3368 & RK3399
>> platforms. This patchset will only add support for Amlogic GXBB SoC.
>>
>> This patchset add support for the legacy protocol in the arm_scpi.c file,
>> avoiding code duplication.
>>
>> Last RFC discution tread can be found at : https://lkml.org/lkml/2016/8/9/210
>>
>> The last patch depends on the "Platform MHU" dtsi patch.
>>
>> Changes since v1 at : http://lkml.kernel.org/r/1471515066-3626-1-git-send-email-narmstrong at baylibre.com
>>  - Dropped vendor_send_message and rockchip vendor mechanism patches
>>  - Merged alternate functions into main functions using is_legacy boolean
>>  - Added DT match table to set is_legacy to true
>>  - Kept alternate scpi_ops structure for legacy
>>
>> Neil Armstrong (7):
>>   scpi: Add alternative legacy structures, functions and macros
>>   scpi: Use legacy variants command index calling scpi_send_message
>>   scpi: Add support for Legacy match table for Amlogic GXBB SoC
>>   scpi: grow MAX_DVFS_OPPS to 16 entries
>>   dt-bindings: Add support for Amlogic GXBB SCPI Interface
>>   ARM64: dts: meson-gxbb: Add SRAM node
>>   ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes
>>
>>  Documentation/devicetree/bindings/arm/arm,scpi.txt |   8 +-
>>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  45 ++++
>>  drivers/firmware/arm_scpi.c                        | 279 +++++++++++++++++++--
>>  3 files changed, 302 insertions(+), 30 deletions(-)
>>
>
> Hi Sudeep,
>
> Sorry but I posted this V2 before you had time to look at my
> previous  v1 replies...
>

That's fine.

> In this series, I merged the scpi_send_message, but I must still
> evaluate how it's possible  to use the list to queue commands.
>

Ah OK.

> Here I used if(is_legacy) to stop duplicating functions, is this ok
> for you ?
>

I am still thinking if it can be abstracted well, some kind of mapping
but haven't thought too much about that yet. Also I was thinking about
bitmap for high priority commands. I remember doing something before but
seem to have lost that copy. I will try to dig it out..

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Thu Aug 25 09:40:10 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 25 Aug 2016 17:40:10 +0100
Subject: [PATCH v2 0/7] scpi: Add support for legacy SCPI protocol
In-Reply-To: <73cce388-219d-2daa-811a-059c3d84c2e4@arm.com>
References: <1471952816-30877-1-git-send-email-narmstrong@baylibre.com>
 <f6c7249f-f103-fd91-2c89-a30c191427aa@baylibre.com>
 <73cce388-219d-2daa-811a-059c3d84c2e4@arm.com>
Message-ID: <ed4ec39d-2b3a-1223-00c3-67d0494e99e6@arm.com>



On 25/08/16 14:45, Sudeep Holla wrote:
>
>
> On 25/08/16 14:18, Neil Armstrong wrote:

[...]

>> Here I used if(is_legacy) to stop duplicating functions, is this ok
>> for you ?
>>
>
> I am still thinking if it can be abstracted well, some kind of mapping
> but haven't thought too much about that yet. Also I was thinking about
> bitmap for high priority commands. I remember doing something before but
> seem to have lost that copy. I will try to dig it out..
>

OK how about something like:

1. in struct scpi_drvinfo
	DECLARE_BITMAP(cmd_priority, SCPI_CMD_COUNT);

2. scpi_send_message
	scpi_chan = test_bit(cmd, scpi_info->cmd_priority) ?
		    scpi_info->channels + 1 : scpi_info->channels;

3. probe
	for (idx = 0; idx < ARRAY_SIZE(hpriority_cmds); idx++)
		set_bit(hpriority_cmds[idx], scpi_info->cmd_priority);

For commands, I am thinking some kind of indirection like the below
patch. See if that helps, I will add the description later, but you can
build your patches on top of it if you think that works and keeps code
simple.

Regards,
Sudeep


-->8

 From afde0d2f1d3381d443445301ab5ec111276934e5 Mon Sep 17 00:00:00 2001
From: Sudeep Holla <sudeep.holla at arm.com>
Date: Thu, 25 Aug 2016 17:21:49 +0100
Subject: [PATCH] firmware: arm_scpi: create command indirection to support
  legacy commands

Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
  drivers/firmware/arm_scpi.c | 68 
+++++++++++++++++++++++++++++++++------------
  1 file changed, 51 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 438893762076..c2063cb76b08 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -129,7 +129,39 @@ enum scpi_std_cmd {
  	SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1a,
  	SCPI_CMD_SET_DEVICE_PWR_STATE	= 0x1b,
  	SCPI_CMD_GET_DEVICE_PWR_STATE	= 0x1c,
-	SCPI_CMD_COUNT
+};
+
+enum scpi_drv_cmd {
+	SCPI_CAPABILITIES	= 0,
+	GET_DVFS_INFO		= 1,
+	SET_DVFS		= 2,
+	GET_DVFS		= 3,
+	GET_CLOCK_INFO		= 4,
+	SET_CLOCK_VALUE		= 5,
+	GET_CLOCK_VALUE		= 6,
+	PSU_CAPABILITIES	= 7,
+	SENSOR_CAPABILITIES	= 8,
+	SENSOR_INFO		= 9,
+	SENSOR_VALUE		= 10,
+	SET_DEV_PWR_STATE	= 11,
+	GET_DEV_PWR_STATE	= 12,
+	CMD_MAX_COUNT
+};
+
+static int scpi_std_commands[CMD_MAX_COUNT] = {
+	SCPI_CMD_SCPI_CAPABILITIES,
+	SCPI_CMD_GET_DVFS_INFO,
+	SCPI_CMD_SET_DVFS,
+	SCPI_CMD_GET_DVFS,
+	SCPI_CMD_GET_CLOCK_INFO,
+	SCPI_CMD_SET_CLOCK_VALUE,
+	SCPI_CMD_GET_CLOCK_VALUE,
+	SCPI_CMD_PSU_CAPABILITIES,
+	SCPI_CMD_SENSOR_CAPABILITIES,
+	SCPI_CMD_SENSOR_INFO,
+	SCPI_CMD_SENSOR_VALUE,
+	SCPI_CMD_SET_DEVICE_PWR_STATE,
+	SCPI_CMD_GET_DEVICE_PWR_STATE,
  };
   struct scpi_xfer {
@@ -161,6 +193,7 @@ struct scpi_drvinfo {
  	u32 protocol_version;
  	u32 firmware_version;
  	int num_chans;
+	int *cmds;
  	atomic_t next_chan;
  	struct scpi_ops *scpi_ops;
  	struct scpi_chan *channels;
@@ -397,7 +430,7 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, 
unsigned long *max)
  	struct clk_get_info clk;
  	__le16 le_clk_id = cpu_to_le16(clk_id);
  -	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
+	ret = scpi_send_message(scpi_info->cmds[GET_CLOCK_INFO], &le_clk_id,
  				sizeof(le_clk_id), &clk, sizeof(clk));
  	if (!ret) {
  		*min = le32_to_cpu(clk.min_rate);
@@ -412,7 +445,7 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
  	struct clk_get_value clk;
  	__le16 le_clk_id = cpu_to_le16(clk_id);
  -	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+	ret = scpi_send_message(scpi_info->cmds[GET_CLOCK_VALUE], &le_clk_id,
  				sizeof(le_clk_id), &clk, sizeof(clk));
  	return ret ? ret : le32_to_cpu(clk.rate);
  }
@@ -425,8 +458,8 @@ static int scpi_clk_set_val(u16 clk_id, unsigned 
long rate)
  		.rate = cpu_to_le32(rate)
  	};
  -	return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
-				 &stat, sizeof(stat));
+	return scpi_send_message(scpi_info->cmds[SET_CLOCK_VALUE], &clk,
+				 sizeof(clk), &stat, sizeof(stat));
  }
   static int scpi_dvfs_get_idx(u8 domain)
@@ -434,8 +467,8 @@ static int scpi_dvfs_get_idx(u8 domain)
  	int ret;
  	u8 dvfs_idx;
  -	ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
-				&dvfs_idx, sizeof(dvfs_idx));
+	ret = scpi_send_message(scpi_info->cmds[GET_DVFS], &domain,
+				sizeof(domain),	&dvfs_idx, sizeof(dvfs_idx));
  	return ret ? ret : dvfs_idx;
  }
  @@ -444,7 +477,7 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
  	int stat;
  	struct dvfs_set dvfs = {domain, index};
  -	return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
+	return scpi_send_message(scpi_info->cmds[SET_DVFS], &dvfs, sizeof(dvfs),
  				 &stat, sizeof(stat));
  }
  @@ -468,8 +501,8 @@ static struct scpi_dvfs_info 
*scpi_dvfs_get_info(u8 domain)
  	if (scpi_info->dvfs[domain])	/* data already populated */
  		return scpi_info->dvfs[domain];
  -	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
-				&buf, sizeof(buf));
+	ret = scpi_send_message(scpi_info->cmds[GET_DVFS_INFO], &domain,
+				sizeof(domain),	&buf, sizeof(buf));
   	if (ret)
  		return ERR_PTR(ret);
@@ -503,8 +536,8 @@ static int scpi_sensor_get_capability(u16 *sensors)
  	struct sensor_capabilities cap_buf;
  	int ret;
  -	ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
-				sizeof(cap_buf));
+	ret = scpi_send_message(scpi_info->cmds[SENSOR_CAPABILITIES], NULL, 0,
+				&cap_buf, sizeof(cap_buf));
  	if (!ret)
  		*sensors = le16_to_cpu(cap_buf.sensors);
  @@ -517,7 +550,7 @@ static int scpi_sensor_get_info(u16 sensor_id, 
struct scpi_sensor_info *info)
  	struct _scpi_sensor_info _info;
  	int ret;
  -	ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+	ret = scpi_send_message(scpi_info->cmds[SENSOR_INFO], &id, sizeof(id),
  				&_info, sizeof(_info));
  	if (!ret) {
  		memcpy(info, &_info, sizeof(*info));
@@ -533,7 +566,7 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
  	struct sensor_value buf;
  	int ret;
  -	ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
+	ret = scpi_send_message(scpi_info->cmds[SENSOR_VALUE], &id, sizeof(id),
  				&buf, sizeof(buf));
  	if (!ret)
  		*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
@@ -548,7 +581,7 @@ static int scpi_device_get_power_state(u16 dev_id)
  	u8 pstate;
  	__le16 id = cpu_to_le16(dev_id);
  -	ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
+	ret = scpi_send_message(scpi_info->cmds[GET_DEV_PWR_STATE], &id,
  				sizeof(id), &pstate, sizeof(pstate));
  	return ret ? ret : pstate;
  }
@@ -561,7 +594,7 @@ static int scpi_device_set_power_state(u16 dev_id, 
u8 pstate)
  		.pstate = pstate,
  	};
  -	return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
+	return scpi_send_message(scpi_info->cmds[SET_DEV_PWR_STATE], &dev_set,
  				 sizeof(dev_set), &stat, sizeof(stat));
  }
  @@ -591,7 +624,7 @@ static int scpi_init_versions(struct scpi_drvinfo 
*info)
  	int ret;
  	struct scp_capabilities caps;
  -	ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+	ret = scpi_send_message(info->cmds[SCPI_CAPABILITIES], NULL, 0,
  				&caps, sizeof(caps));
  	if (!ret) {
  		info->protocol_version = le32_to_cpu(caps.protocol_version);
@@ -754,6 +787,7 @@ static int scpi_probe(struct platform_device *pdev)
   	scpi_info->channels = scpi_chan;
  	scpi_info->num_chans = count;
+	scpi_info->cmds = scpi_std_commands;
  	platform_set_drvdata(pdev, scpi_info);
   	ret = scpi_init_versions(scpi_info);
-- 
2.7.4


From martin.blumenstingl at googlemail.com  Fri Aug 26 03:45:45 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Fri, 26 Aug 2016 12:45:45 +0200
Subject: USB PHY documentation
In-Reply-To: <1472029412.2322.13.camel@baylibre.com>
References: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
 <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>
 <1472029412.2322.13.camel@baylibre.com>
Message-ID: <CAFBinCCx4X_Lsd9NsFd-9aHL67EvCJDebdzc8zdSP9Hcw__BOA@mail.gmail.com>

On Wed, Aug 24, 2016 at 11:03 AM, jbrunet <jbrunet at baylibre.com> wrote:
> I'm still checking the otg controller.
I've seen that you made more changes in your github repo.
Maybe you could give me/us an update before your leave today so I can
continue where you left tonight/tomorrow.

How should we proceed with signed-off-by in these patches?
We have both written/changed a part of it, should we both simply add
our own SOB to the patches?


From carlo at caione.org  Sat Aug 27 06:43:42 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:42 +0200
Subject: [PATCH v3 0/6] Add Amlogic secure monitor and NVMEM drivers
Message-ID: <1472305428-16874-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

I decided to respin again the secure monitor driver this time with the NVMEM
driver in the same patchset to have a clear view on how a generic driver can
use the monitor.

The latest patchset for the secure monitor with the Changelog is here [1].

[1] http://www.spinics.net/lists/arm-kernel/msg510441.html

Changelog:
v3:
  - Add missing ACKs
  - s/0x1000/SZ_4K/
v2:
  - nvmem driver not using regmap anymore
  - headers list cleanup
  - disable sm driver for !4K kernels
  - removed meson_sm_get_fw()
  - better debug printing
  - general cleanup  

Carlo Caione (6):
  firmware: Amlogic: Add secure monitor driver
  documentation: Add secure monitor bindings documentation
  ARM64: dts: amlogic: gxbb: Enable secure monitor
  nvmem: amlogic: Add Amlogic Meson EFUSE driver
  documentation: Add nvmem bindings documentation
  ARM64: dts: amlogic: gxbb: Enable NVMEM

 .../bindings/firmware/meson/meson_sm.txt           |  15 ++
 .../devicetree/bindings/nvmem/amlogic-efuse.txt    |  39 ++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  24 ++
 drivers/firmware/Kconfig                           |   1 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/meson/Kconfig                     |   9 +
 drivers/firmware/meson/Makefile                    |   1 +
 drivers/firmware/meson/meson_sm.c                  | 248 +++++++++++++++++++++
 drivers/nvmem/Kconfig                              |  10 +
 drivers/nvmem/Makefile                             |   2 +
 drivers/nvmem/meson-efuse.c                        |  93 ++++++++
 include/linux/firmware/meson/meson_sm.h            |  31 +++
 12 files changed, 474 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 drivers/nvmem/meson-efuse.c
 create mode 100644 include/linux/firmware/meson/meson_sm.h

-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:43:43 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:43 +0200
Subject: [PATCH v3 1/6] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <1472305428-16874-2-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Introduce a driver to provide calls into secure monitor mode.

In the Amlogic SoCs these calls are used for multiple reasons: access to
NVMEM, set USB boot, enable JTAG, etc...

Acked-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/firmware/Kconfig                |   1 +
 drivers/firmware/Makefile               |   1 +
 drivers/firmware/meson/Kconfig          |   9 ++
 drivers/firmware/meson/Makefile         |   1 +
 drivers/firmware/meson/meson_sm.c       | 247 ++++++++++++++++++++++++++++++++
 include/linux/firmware/meson/meson_sm.h |  31 ++++
 6 files changed, 290 insertions(+)
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/linux/firmware/meson/meson_sm.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 0e22f24..bca172d 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -209,5 +209,6 @@ config HAVE_ARM_SMCCC
 source "drivers/firmware/broadcom/Kconfig"
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
+source "drivers/firmware/meson/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 44a59dc..898ac41 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 
 obj-y				+= broadcom/
+obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
 obj-$(CONFIG_UEFI_CPER)		+= efi/
diff --git a/drivers/firmware/meson/Kconfig b/drivers/firmware/meson/Kconfig
new file mode 100644
index 0000000..170d7e8
--- /dev/null
+++ b/drivers/firmware/meson/Kconfig
@@ -0,0 +1,9 @@
+#
+# Amlogic Secure Monitor driver
+#
+config MESON_SM
+	bool
+	default ARCH_MESON
+	depends on ARM64_4K_PAGES
+	help
+	  Say y here to enable the Amlogic secure monitor driver
diff --git a/drivers/firmware/meson/Makefile b/drivers/firmware/meson/Makefile
new file mode 100644
index 0000000..9ab3884
--- /dev/null
+++ b/drivers/firmware/meson/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MESON_SM) +=	meson_sm.o
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
new file mode 100644
index 0000000..bba594e
--- /dev/null
+++ b/drivers/firmware/meson/meson_sm.c
@@ -0,0 +1,247 @@
+/*
+ * Amlogic Secure Monitor driver
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "meson-sm: " fmt
+
+#include <linux/arm-smccc.h>
+#include <linux/bug.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/printk.h>
+#include <linux/types.h>
+
+#include <linux/firmware/meson/meson_sm.h>
+
+struct meson_sm_cmd {
+	unsigned int index;
+	u32 smc_id;
+};
+#define CMD(d, s) { .index = (d), .smc_id = (s), }
+
+struct meson_sm_chip {
+	unsigned int shmem_size;
+	u32 cmd_shmem_in_base;
+	u32 cmd_shmem_out_base;
+	struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_chip gxbb_chip = {
+	.shmem_size		= 0x1000,
+	.cmd_shmem_in_base	= 0x82000020,
+	.cmd_shmem_out_base	= 0x82000021,
+	.cmd = {
+		CMD(SM_EFUSE_READ,	0x82000030),
+		CMD(SM_EFUSE_WRITE,	0x82000031),
+		CMD(SM_EFUSE_USER_MAX,	0x82000033),
+		{ /* sentinel */ },
+	},
+};
+
+struct meson_sm_firmware {
+	const struct meson_sm_chip *chip;
+	void __iomem *sm_shmem_in_base;
+	void __iomem *sm_shmem_out_base;
+};
+
+static struct meson_sm_firmware fw;
+
+static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
+			    unsigned int cmd_index)
+{
+	const struct meson_sm_cmd *cmd = chip->cmd;
+
+	while (cmd->smc_id && cmd->index != cmd_index)
+		cmd++;
+
+	return cmd->smc_id;
+}
+
+static u32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+			   u32 arg3, u32 arg4)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(cmd, arg0, arg1, arg2, arg3, arg4, 0, 0, &res);
+	return res.a0;
+}
+
+static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
+{
+	u32 sm_phy_base;
+
+	sm_phy_base = __meson_sm_call(cmd_shmem, 0, 0, 0, 0, 0);
+	if (!sm_phy_base)
+		return 0;
+
+	return ioremap_cache(sm_phy_base, size);
+}
+
+/**
+ * meson_sm_call - generic SMC32 call to the secure-monitor
+ *
+ * @cmd_index:	Index of the SMC32 function ID
+ * @ret:	Returned value
+ * @arg0:	SMC32 Argument 0
+ * @arg1:	SMC32 Argument 1
+ * @arg2:	SMC32 Argument 2
+ * @arg3:	SMC32 Argument 3
+ * @arg4:	SMC32 Argument 4
+ *
+ * Return:	0 on success, a negative value on error
+ */
+int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0,
+		  u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 cmd, lret;
+
+	if (!fw.chip)
+		return -ENOENT;
+
+	cmd = meson_sm_get_cmd(fw.chip, cmd_index);
+	if (!cmd)
+		return -EINVAL;
+
+	lret = __meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+
+	if (ret)
+		*ret = lret;
+
+	return 0;
+}
+EXPORT_SYMBOL(meson_sm_call);
+
+/**
+ * meson_sm_call_read - retrieve data from secure-monitor
+ *
+ * @buffer:	Buffer to store the retrieved data
+ * @cmd_index:	Index of the SMC32 function ID
+ * @arg0:	SMC32 Argument 0
+ * @arg1:	SMC32 Argument 1
+ * @arg2:	SMC32 Argument 2
+ * @arg3:	SMC32 Argument 3
+ * @arg4:	SMC32 Argument 4
+ *
+ * Return:	size of read data on success, a negative value on error
+ */
+int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
+		       u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (!fw.chip)
+		return -ENOENT;
+
+	if (!fw.chip->cmd_shmem_out_base)
+		return -EINVAL;
+
+	if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
+		return -EINVAL;
+
+	if (!size || size > fw.chip->shmem_size)
+		return -EINVAL;
+
+	if (buffer)
+		memcpy(buffer, fw.sm_shmem_out_base, size);
+
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_read);
+
+/**
+ * meson_sm_call_write - send data to secure-monitor
+ *
+ * @buffer:	Buffer containing data to send
+ * @size:	Size of the data to send
+ * @cmd_index:	Index of the SMC32 function ID
+ * @arg0:	SMC32 Argument 0
+ * @arg1:	SMC32 Argument 1
+ * @arg2:	SMC32 Argument 2
+ * @arg3:	SMC32 Argument 3
+ * @arg4:	SMC32 Argument 4
+ *
+ * Return:	size of sent data on success, a negative value on error
+ */
+int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
+			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 written;
+
+	if (!fw.chip)
+		return -ENOENT;
+
+	if (size > fw.chip->shmem_size)
+		return -EINVAL;
+
+	if (!fw.chip->cmd_shmem_in_base)
+		return -EINVAL;
+
+	memcpy(fw.sm_shmem_in_base, buffer, size);
+
+	if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
+		return -EINVAL;
+
+	if (!written)
+		return -EINVAL;
+
+	return written;
+}
+EXPORT_SYMBOL(meson_sm_call_write);
+
+static const struct of_device_id meson_sm_ids[] = {
+	{ .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip },
+	{ /* sentinel */ },
+};
+
+int __init meson_sm_init(void)
+{
+	const struct meson_sm_chip *chip;
+	const struct of_device_id *matched_np;
+	struct device_node *np;
+
+	np = of_find_matching_node_and_match(NULL, meson_sm_ids, &matched_np);
+	if (!np)
+		return -ENODEV;
+
+	chip = matched_np->data;
+	if (!chip) {
+		pr_err("unable to setup secure-monitor data\n");
+		goto out;
+	}
+
+	if (chip->cmd_shmem_in_base) {
+		fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
+							 chip->shmem_size);
+		if (WARN_ON(!fw.sm_shmem_in_base))
+			goto out;
+	}
+
+	if (chip->cmd_shmem_out_base) {
+		fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
+							  chip->shmem_size);
+		if (WARN_ON(!fw.sm_shmem_out_base))
+			goto out_in_base;
+	}
+
+	fw.chip = chip;
+	pr_info("secure-monitor enabled\n");
+
+	return 0;
+
+out_in_base:
+	iounmap(fw.sm_shmem_in_base);
+out:
+	return -EINVAL;
+}
+device_initcall(meson_sm_init);
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
new file mode 100644
index 0000000..8e953c6
--- /dev/null
+++ b/include/linux/firmware/meson/meson_sm.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_FW_H_
+#define _MESON_SM_FW_H_
+
+enum {
+	SM_EFUSE_READ,
+	SM_EFUSE_WRITE,
+	SM_EFUSE_USER_MAX,
+};
+
+struct meson_sm_firmware;
+
+int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1,
+		  u32 arg2, u32 arg3, u32 arg4);
+int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index,
+			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, u32 arg1,
+		       u32 arg2, u32 arg3, u32 arg4);
+
+#endif /* _MESON_SM_FW_H_ */
-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:43:44 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:44 +0200
Subject: [PATCH v3 2/6] documentation: Add secure monitor bindings
 documentation
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <1472305428-16874-3-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the binding documentation for the Amlogic secure monitor driver.

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 .../devicetree/bindings/firmware/meson/meson_sm.txt       | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt

diff --git a/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
new file mode 100644
index 0000000..c248cd4
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
@@ -0,0 +1,15 @@
+* Amlogic Secure Monitor
+
+In the Amlogic SoCs the Secure Monitor code is used to provide access to the
+NVMEM, enable JTAG, set USB boot, etc...
+
+Required properties for the secure monitor node:
+- compatible: Should be "amlogic,meson-gxbb-sm"
+
+Example:
+
+	firmware {
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gxbb-sm";
+		};
+	};
-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:43:45 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:45 +0200
Subject: [PATCH v3 3/6] ARM64: dts: amlogic: gxbb: Enable secure monitor
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <1472305428-16874-4-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the secure monitor node in the Amlogic Meson GXBB DTSI file to
enable it.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e502c24..ca428e8 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -99,6 +99,12 @@
 		method = "smc";
 	};
 
+	firmware {
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gxbb-sm";
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:43:46 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:46 +0200
Subject: [PATCH v3 4/6] nvmem: amlogic: Add Amlogic Meson EFUSE driver
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <1472305428-16874-5-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add Amlogic EFUSE driver to access hardware data like ethernet address,
serial number or IDs.

Acked-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/nvmem/Kconfig       | 10 +++++
 drivers/nvmem/Makefile      |  2 +
 drivers/nvmem/meson-efuse.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+)
 create mode 100644 drivers/nvmem/meson-efuse.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index f550c45..ba140ea 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -101,4 +101,14 @@ config NVMEM_VF610_OCOTP
 	  This driver can also be build as a module. If so, the module will
 	  be called nvmem-vf610-ocotp.
 
+config MESON_EFUSE
+	tristate "Amlogic eFuse Support"
+	depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+	help
+	  This is a driver to retrieve specific values from the eFuse found on
+	  the Amlogic Meson SoCs.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called nvmem_meson_efuse.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 45ab1ae..8f942a0 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -22,3 +22,5 @@ obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem_sunxi_sid.o
 nvmem_sunxi_sid-y		:= sunxi_sid.o
 obj-$(CONFIG_NVMEM_VF610_OCOTP)	+= nvmem-vf610-ocotp.o
 nvmem-vf610-ocotp-y		:= vf610-ocotp.o
+obj-$(CONFIG_MESON_EFUSE)	+= nvmem_meson_efuse.o
+nvmem_meson_efuse-y		:= meson-efuse.o
diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c
new file mode 100644
index 0000000..f207c3b
--- /dev/null
+++ b/drivers/nvmem/meson-efuse.c
@@ -0,0 +1,93 @@
+/*
+ * Amlogic eFuse Driver
+ *
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <linux/firmware/meson/meson_sm.h>
+
+static int meson_efuse_read(void *context, unsigned int offset,
+			    void *val, size_t bytes)
+{
+	u8 *buf = val;
+	int ret;
+
+	ret = meson_sm_call_read(buf, SM_EFUSE_READ, offset,
+				 bytes, 0, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct nvmem_config econfig = {
+	.name = "meson-efuse",
+	.owner = THIS_MODULE,
+	.stride = 1,
+	.word_size = 1,
+	.read_only = true,
+};
+
+static const struct of_device_id meson_efuse_match[] = {
+	{ .compatible = "amlogic,meson-gxbb-efuse", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_efuse_match);
+
+static int meson_efuse_probe(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem;
+	unsigned int size;
+
+	if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0)
+		return -EINVAL;
+
+	econfig.dev = &pdev->dev;
+	econfig.reg_read = meson_efuse_read;
+	econfig.size = size;
+
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static int meson_efuse_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static struct platform_driver meson_efuse_driver = {
+	.probe = meson_efuse_probe,
+	.remove = meson_efuse_remove,
+	.driver = {
+		.name = "meson-efuse",
+		.of_match_table = meson_efuse_match,
+	},
+};
+
+module_platform_driver(meson_efuse_driver);
+
+MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
+MODULE_DESCRIPTION("Amlogic Meson NVMEM driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:43:48 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:48 +0200
Subject: [PATCH v3 6/6] ARM64: dts: amlogic: gxbb: Enable NVMEM
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <1472305428-16874-7-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the NVMEM device node in the DTSI.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 18 ++++++++++++++++++
 drivers/firmware/meson/meson_sm.c           |  3 ++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index ca428e8..aea8fd6 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -105,6 +105,24 @@
 		};
 	};
 
+	efuse: efuse {
+		compatible = "amlogic,meson-gxbb-efuse";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		sn: sn at 14 {
+			reg = <0x14 0x10>;
+		};
+
+		eth_mac: eth_mac at 34 {
+			reg = <0x34 0x10>;
+		};
+
+		bid: bid at 46 {
+			reg = <0x46 0x30>;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index bba594e..b0d2549 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -21,6 +21,7 @@
 #include <linux/of_device.h>
 #include <linux/printk.h>
 #include <linux/types.h>
+#include <linux/sizes.h>
 
 #include <linux/firmware/meson/meson_sm.h>
 
@@ -38,7 +39,7 @@ struct meson_sm_chip {
 };
 
 struct meson_sm_chip gxbb_chip = {
-	.shmem_size		= 0x1000,
+	.shmem_size		= SZ_4K,
 	.cmd_shmem_in_base	= 0x82000020,
 	.cmd_shmem_out_base	= 0x82000021,
 	.cmd = {
-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:43:47 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:43:47 +0200
Subject: [PATCH v3 5/6] documentation: Add nvmem bindings documentation
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <1472305428-16874-6-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

This patch add the bindings document of Amlogic eFuse driver.

Acked-by: Rob Herring <robh at kernel.org>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 .../devicetree/bindings/nvmem/amlogic-efuse.txt    | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt

diff --git a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
new file mode 100644
index 0000000..fafd85b
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
@@ -0,0 +1,39 @@
+= Amlogic eFuse device tree bindings =
+
+Required properties:
+- compatible: should be "amlogic,meson-gxbb-efuse"
+
+= Data cells =
+Are child nodes of eFuse, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gxbb-efuse";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		sn: sn at 14 {
+			reg = <0x14 0x10>;
+		};
+
+		eth_mac: eth_mac at 34 {
+			reg = <0x34 0x10>;
+		};
+
+		bid: bid at 46 {
+			reg = <0x46 0x30>;
+		};
+	};
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	eth_mac {
+		...
+		nvmem-cells = <&eth_mac>;
+		nvmem-cell-names = "eth_mac";
+	};
-- 
2.7.4



From carlo at caione.org  Sat Aug 27 06:47:57 2016
From: carlo at caione.org (Carlo Caione)
Date: Sat, 27 Aug 2016 15:47:57 +0200
Subject: [PATCH v3 0/6] Add Amlogic secure monitor and NVMEM drivers
In-Reply-To: <1472305428-16874-1-git-send-email-carlo@caione.org>
References: <1472305428-16874-1-git-send-email-carlo@caione.org>
Message-ID: <20160827134757.GA4957@localhost>

On 27/08/16 15:43, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> I decided to respin again the secure monitor driver this time with the NVMEM
> driver in the same patchset to have a clear view on how a generic driver can
> use the monitor.

Kevin,
finally I found the time to respin this patchset for the last time.
Since we have now all the ACKs we need, could you please take all the 6
patches in your tree?

Thanks,

-- 
Carlo Caione


From serveralex at gmail.com  Sat Aug 27 10:40:49 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:49 +0200
Subject: [PATCH v5 1/6] clk: meson: Rename meson8b-clkc.c to reflect gxbb
 naming convention
In-Reply-To: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
References: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
Message-ID: <1472319654-59048-2-git-send-email-serveralex@gmail.com>

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/Makefile                      | 2 +-
 drivers/clk/meson/{meson8b-clkc.c => meson8b.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/clk/meson/{meson8b-clkc.c => meson8b.c} (100%)

diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index d4cd4a3..3495834 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -3,5 +3,5 @@
 #
 
 obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
-obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o
+obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
 obj-$(CONFIG_COMMON_CLK_GXBB)	 += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b.c
similarity index 100%
rename from drivers/clk/meson/meson8b-clkc.c
rename to drivers/clk/meson/meson8b.c
-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:40:48 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:48 +0200
Subject: [PATCH v5 0/6] Add Amlogic meson8b clock gates
Message-ID: <1472319654-59048-1-git-send-email-serveralex@gmail.com>

This patch series adds support for the Amlogic meson8b clock gates. The Amlogic
U-Boot disables most of them at boot. In order to enable ethernet, USB and other
components it's mandatory to enable the clock gates when loading the corresponding
drivers.

The meson8b clock gate support is based on the previous work done for Amlogic gxbb
currently available in clk-next.

Changes since v4:
  - Rebased to linux-clk/clk-meson-gxbb-ao branch

Changes since v3:
  - Include include/dt-bindings/clock/meson8b-clkc.h to prevent code duplicates

Changes since v2:
  - Added commit description for patch 2
  - Changed CLK_NR_CLOCKS macro to constant int
  - Moved back MESON_GATE macro to share it between gxbb and meson8b

Changes since v1:
  - Fixed GXBB spelling
  - Moved newly introduced CLKID defines to private header
  - Moved CLK_NR_CLKS define from DT binding to private header
  - Rebased to linux-amlogic/v4.7/integ making Kconfig select obsolete

Alexander M?ller (6):
  clk: meson: Rename meson8b-clkc.c to reflect gxbb naming convention
  meson: clk: Move register definitions to meson8b.h
  meson: clk: Rename register names according to Amlogic datasheet
  clk: meson: Copy meson8b CLKID defines to private header file
  gxbb: clk: Adjust MESON_GATE macro to be shared with meson8b
  meson: clk: Add support for clock gates

 drivers/clk/meson/Makefile                      |   2 +-
 drivers/clk/meson/clkc.h                        |   2 +-
 drivers/clk/meson/gxbb.c                        | 162 ++++++-------
 drivers/clk/meson/{meson8b-clkc.c => meson8b.c} | 293 +++++++++++++++++++++---
 drivers/clk/meson/meson8b.h                     | 151 ++++++++++++
 include/dt-bindings/clock/meson8b-clkc.h        |   2 -
 6 files changed, 497 insertions(+), 115 deletions(-)
 rename drivers/clk/meson/{meson8b-clkc.c => meson8b.c} (51%)
 create mode 100644 drivers/clk/meson/meson8b.h

-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:40:50 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:50 +0200
Subject: [PATCH v5 2/6] meson: clk: Move register definitions to meson8b.h
In-Reply-To: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
References: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
Message-ID: <1472319654-59048-3-git-send-email-serveralex@gmail.com>

Move the register definitions into a separate header file
to reflect the gxbb implementation.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/meson8b.c | 17 +----------------
 drivers/clk/meson/meson8b.h | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 16 deletions(-)
 create mode 100644 drivers/clk/meson/meson8b.h

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 4c9413c..d52ae53 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -28,22 +28,7 @@
 #include <linux/init.h>
 
 #include "clkc.h"
-
-/*
- * Clock controller register offsets
- *
- * Register offsets from the HardKernel[0] data sheet are listed in comment
- * blocks below. Those offsets must be multiplied by 4 before adding them to
- * the base address to get the right value
- *
- * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
- */
-#define MESON8B_REG_SYS_CPU_CNTL1	0x015c /* 0x57 offset in data sheet */
-#define MESON8B_REG_HHI_MPEG		0x0174 /* 0x5d offset in data sheet */
-#define MESON8B_REG_MALI		0x01b0 /* 0x6c offset in data sheet */
-#define MESON8B_REG_PLL_FIXED		0x0280
-#define MESON8B_REG_PLL_SYS		0x0300
-#define MESON8B_REG_PLL_VID		0x0320
+#include "meson8b.h"
 
 static DEFINE_SPINLOCK(clk_lock);
 
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
new file mode 100644
index 0000000..5b9cb9f
--- /dev/null
+++ b/drivers/clk/meson/meson8b.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Michael Turquette <mturquette at 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/>.
+ */
+
+#ifndef __MESON8B_H
+#define __MESON8B_H
+
+/*
+ * Clock controller register offsets
+ *
+ * Register offsets from the HardKernel[0] data sheet are listed in comment
+ * blocks below. Those offsets must be multiplied by 4 before adding them to
+ * the base address to get the right value
+ *
+ * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
+ */
+#define MESON8B_REG_SYS_CPU_CNTL1	0x015c /* 0x57 offset in data sheet */
+#define MESON8B_REG_HHI_MPEG		0x0174 /* 0x5d offset in data sheet */
+#define MESON8B_REG_MALI		0x01b0 /* 0x6c offset in data sheet */
+#define MESON8B_REG_PLL_FIXED		0x0280
+#define MESON8B_REG_PLL_SYS		0x0300
+#define MESON8B_REG_PLL_VID		0x0320
+
+#endif /* __MESON8B_H */
-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:40:51 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:51 +0200
Subject: [PATCH v5 3/6] meson: clk: Rename register names according to Amlogic
 datasheet
In-Reply-To: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
References: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
Message-ID: <1472319654-59048-4-git-send-email-serveralex@gmail.com>

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/meson8b.c | 26 +++++++++++++-------------
 drivers/clk/meson/meson8b.h | 11 +++++------
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index d52ae53..24395dc 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -113,17 +113,17 @@ static struct clk_fixed_rate meson8b_xtal = {
 
 static struct meson_clk_pll meson8b_fixed_pll = {
 	.m = {
-		.reg_off = MESON8B_REG_PLL_FIXED,
+		.reg_off = HHI_MPLL_CNTL,
 		.shift   = 0,
 		.width   = 9,
 	},
 	.n = {
-		.reg_off = MESON8B_REG_PLL_FIXED,
+		.reg_off = HHI_MPLL_CNTL,
 		.shift   = 9,
 		.width   = 5,
 	},
 	.od = {
-		.reg_off = MESON8B_REG_PLL_FIXED,
+		.reg_off = HHI_MPLL_CNTL,
 		.shift   = 16,
 		.width   = 2,
 	},
@@ -139,17 +139,17 @@ static struct meson_clk_pll meson8b_fixed_pll = {
 
 static struct meson_clk_pll meson8b_vid_pll = {
 	.m = {
-		.reg_off = MESON8B_REG_PLL_VID,
+		.reg_off = HHI_VID_PLL_CNTL,
 		.shift   = 0,
 		.width   = 9,
 	},
 	.n = {
-		.reg_off = MESON8B_REG_PLL_VID,
+		.reg_off = HHI_VID_PLL_CNTL,
 		.shift   = 9,
 		.width   = 5,
 	},
 	.od = {
-		.reg_off = MESON8B_REG_PLL_VID,
+		.reg_off = HHI_VID_PLL_CNTL,
 		.shift   = 16,
 		.width   = 2,
 	},
@@ -165,17 +165,17 @@ static struct meson_clk_pll meson8b_vid_pll = {
 
 static struct meson_clk_pll meson8b_sys_pll = {
 	.m = {
-		.reg_off = MESON8B_REG_PLL_SYS,
+		.reg_off = HHI_SYS_PLL_CNTL,
 		.shift   = 0,
 		.width   = 9,
 	},
 	.n = {
-		.reg_off = MESON8B_REG_PLL_SYS,
+		.reg_off = HHI_SYS_PLL_CNTL,
 		.shift   = 9,
 		.width   = 5,
 	},
 	.od = {
-		.reg_off = MESON8B_REG_PLL_SYS,
+		.reg_off = HHI_SYS_PLL_CNTL,
 		.shift   = 16,
 		.width   = 2,
 	},
@@ -252,7 +252,7 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
  * forthcoming coordinated clock rates feature
  */
 static struct meson_clk_cpu meson8b_cpu_clk = {
-	.reg_off = MESON8B_REG_SYS_CPU_CNTL1,
+	.reg_off = HHI_SYS_CPU_CLK_CNTL1,
 	.div_table = cpu_div_table,
 	.clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
 	.hw.init = &(struct clk_init_data){
@@ -266,7 +266,7 @@ static struct meson_clk_cpu meson8b_cpu_clk = {
 static u32 mux_table_clk81[]	= { 6, 5, 7 };
 
 struct clk_mux meson8b_mpeg_clk_sel = {
-	.reg = (void *)MESON8B_REG_HHI_MPEG,
+	.reg = (void *)HHI_MPEG_CLK_CNTL,
 	.mask = 0x7,
 	.shift = 12,
 	.flags = CLK_MUX_READ_ONLY,
@@ -288,7 +288,7 @@ struct clk_mux meson8b_mpeg_clk_sel = {
 };
 
 struct clk_divider meson8b_mpeg_clk_div = {
-	.reg = (void *)MESON8B_REG_HHI_MPEG,
+	.reg = (void *)HHI_MPEG_CLK_CNTL,
 	.shift = 0,
 	.width = 7,
 	.lock = &clk_lock,
@@ -302,7 +302,7 @@ struct clk_divider meson8b_mpeg_clk_div = {
 };
 
 struct clk_gate meson8b_clk81 = {
-	.reg = (void *)MESON8B_REG_HHI_MPEG,
+	.reg = (void *)HHI_MPEG_CLK_CNTL,
 	.bit_idx = 7,
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 5b9cb9f..b2f29f7 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -30,11 +30,10 @@
  *
  * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
  */
-#define MESON8B_REG_SYS_CPU_CNTL1	0x015c /* 0x57 offset in data sheet */
-#define MESON8B_REG_HHI_MPEG		0x0174 /* 0x5d offset in data sheet */
-#define MESON8B_REG_MALI		0x01b0 /* 0x6c offset in data sheet */
-#define MESON8B_REG_PLL_FIXED		0x0280
-#define MESON8B_REG_PLL_SYS		0x0300
-#define MESON8B_REG_PLL_VID		0x0320
+#define HHI_SYS_CPU_CLK_CNTL1		0x15c /* 0x57 offset in data sheet */
+#define HHI_MPEG_CLK_CNTL		0x174 /* 0x5d offset in data sheet */
+#define HHI_MPLL_CNTL			0x280 /* 0xa0 offset in data sheet */
+#define HHI_SYS_PLL_CNTL		0x300 /* 0xc0 offset in data sheet */
+#define HHI_VID_PLL_CNTL		0x320 /* 0xc8 offset in data sheet */
 
 #endif /* __MESON8B_H */
-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:40:52 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:52 +0200
Subject: [PATCH v5 4/6] clk: meson: Copy meson8b CLKID defines to private
 header file
In-Reply-To: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
References: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
Message-ID: <1472319654-59048-5-git-send-email-serveralex@gmail.com>

Only expose future CLKID constants if necessary. This patch
removes CLK_NR_CLKS from the DT bindings but leaves all previously
defined CLKIDs there to keep backward compatibility.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/meson8b.c              |   1 -
 drivers/clk/meson/meson8b.h              | 107 +++++++++++++++++++++++++++++++
 include/dt-bindings/clock/meson8b-clkc.h |   2 -
 3 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 24395dc..f815d40 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
-#include <dt-bindings/clock/meson8b-clkc.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
 
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index b2f29f7..86efe6a 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -36,4 +36,111 @@
 #define HHI_SYS_PLL_CNTL		0x300 /* 0xc0 offset in data sheet */
 #define HHI_VID_PLL_CNTL		0x320 /* 0xc8 offset in data sheet */
 
+/*
+ * CLKID index values
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * Migrate them out of this header and into the DT header file when they need
+ * to be exposed to client nodes in DT: include/dt-bindings/clock/meson8b-clkc.h
+ */
+
+/* CLKID_UNUSED */
+/* CLKID_XTAL */
+/* CLKID_PLL_FIXED */
+/* CLKID_PLL_VID */
+/* CLKID_PLL_SYS */
+/* CLKID_FCLK_DIV2 */
+/* CLKID_FCLK_DIV3 */
+/* CLKID_FCLK_DIV4 */
+/* CLKID_FCLK_DIV5 */
+/* CLKID_FCLK_DIV7 */
+/* CLKID_CLK81 */
+/* CLKID_MALI */
+/* CLKID_CPUCLK */
+/* CLKID_ZERO */
+/* CLKID_MPEG_SEL */
+/* CLKID_MPEG_DIV */
+#define CLKID_DDR		16
+#define CLKID_DOS		17
+#define CLKID_ISA		18
+#define CLKID_PL301		19
+#define CLKID_PERIPHS		20
+#define CLKID_SPICC		21
+#define CLKID_I2C		22
+#define CLKID_SAR_ADC		23
+#define CLKID_SMART_CARD	24
+#define CLKID_RNG0		25
+#define CLKID_UART0		26
+#define CLKID_SDHC		27
+#define CLKID_STREAM		28
+#define CLKID_ASYNC_FIFO	29
+#define CLKID_SDIO		30
+#define CLKID_ABUF		31
+#define CLKID_HIU_IFACE		32
+#define CLKID_ASSIST_MISC	33
+#define CLKID_SPI		34
+#define CLKID_I2S_SPDIF		35
+#define CLKID_ETH		36
+#define CLKID_DEMUX		37
+#define CLKID_AIU_GLUE		38
+#define CLKID_IEC958		39
+#define CLKID_I2S_OUT		40
+#define CLKID_AMCLK		41
+#define CLKID_AIFIFO2		42
+#define CLKID_MIXER		43
+#define CLKID_MIXER_IFACE	44
+#define CLKID_ADC		45
+#define CLKID_BLKMV		46
+#define CLKID_AIU		47
+#define CLKID_UART1		48
+#define CLKID_G2D		49
+#define CLKID_USB0		50
+#define CLKID_USB1		51
+#define CLKID_RESET		52
+#define CLKID_NAND		53
+#define CLKID_DOS_PARSER	54
+#define CLKID_USB		55
+#define CLKID_VDIN1		56
+#define CLKID_AHB_ARB0		57
+#define CLKID_EFUSE		58
+#define CLKID_BOOT_ROM		59
+#define CLKID_AHB_DATA_BUS	60
+#define CLKID_AHB_CTRL_BUS	61
+#define CLKID_HDMI_INTR_SYNC	62
+#define CLKID_HDMI_PCLK		63
+#define CLKID_USB1_DDR_BRIDGE	64
+#define CLKID_USB0_DDR_BRIDGE	65
+#define CLKID_MMC_PCLK		66
+#define CLKID_DVIN		67
+#define CLKID_UART2		68
+#define CLKID_SANA		69
+#define CLKID_VPU_INTR		70
+#define CLKID_SEC_AHB_AHB3_BRIDGE	71
+#define CLKID_CLK81_A9		72
+#define CLKID_VCLK2_VENCI0	73
+#define CLKID_VCLK2_VENCI1	74
+#define CLKID_VCLK2_VENCP0	75
+#define CLKID_VCLK2_VENCP1	76
+#define CLKID_GCLK_VENCI_INT	77
+#define CLKID_GCLK_VENCP_INT	78
+#define CLKID_DAC_CLK		79
+#define CLKID_AOCLK_GATE	80
+#define CLKID_IEC958_GATE	81
+#define CLKID_ENC480P		82
+#define CLKID_RNG1		83
+#define CLKID_GCLK_VENCL_INT	84
+#define CLKID_VCLK2_VENCLMCC	85
+#define CLKID_VCLK2_VENCL	86
+#define CLKID_VCLK2_OTHER	87
+#define CLKID_EDP		88
+#define CLKID_AO_MEDIA_CPU	89
+#define CLKID_AO_AHB_SRAM	90
+#define CLKID_AO_AHB_BUS	91
+#define CLKID_AO_IFACE		92
+
+#define CLK_NR_CLKS		93
+
+/* include the CLKIDs that have been made part of the stable DT binding */
+#include <dt-bindings/clock/meson8b-clkc.h>
+
 #endif /* __MESON8B_H */
diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h
index 595a58d..a55ff8c 100644
--- a/include/dt-bindings/clock/meson8b-clkc.h
+++ b/include/dt-bindings/clock/meson8b-clkc.h
@@ -22,6 +22,4 @@
 #define CLKID_MPEG_SEL		14
 #define CLKID_MPEG_DIV		15
 
-#define CLK_NR_CLKS		(CLKID_MPEG_DIV + 1)
-
 #endif /* __MESON8B_CLKC_H */
-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:40:54 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:54 +0200
Subject: [PATCH v5 6/6] meson: clk: Add support for clock gates
In-Reply-To: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
References: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
Message-ID: <1472319654-59048-7-git-send-email-serveralex@gmail.com>

This patch adds support for the meson8b clock gates. Most of
them are disabled by Amlogic U-Boot, but need to be enabled
for ethernet, USB and many other components.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/meson8b.c | 249 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/meson/meson8b.h |   5 +
 2 files changed, 254 insertions(+)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index f815d40..e1d4aa1 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -313,6 +313,92 @@ struct clk_gate meson8b_clk81 = {
 	},
 };
 
+/* Everything Else (EE) domain gates */
+
+static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
+static MESON_GATE(meson8b_dos, HHI_GCLK_MPEG0, 1);
+static MESON_GATE(meson8b_isa, HHI_GCLK_MPEG0, 5);
+static MESON_GATE(meson8b_pl301, HHI_GCLK_MPEG0, 6);
+static MESON_GATE(meson8b_periphs, HHI_GCLK_MPEG0, 7);
+static MESON_GATE(meson8b_spicc, HHI_GCLK_MPEG0, 8);
+static MESON_GATE(meson8b_i2c, HHI_GCLK_MPEG0, 9);
+static MESON_GATE(meson8b_sar_adc, HHI_GCLK_MPEG0, 10);
+static MESON_GATE(meson8b_smart_card, HHI_GCLK_MPEG0, 11);
+static MESON_GATE(meson8b_rng0, HHI_GCLK_MPEG0, 12);
+static MESON_GATE(meson8b_uart0, HHI_GCLK_MPEG0, 13);
+static MESON_GATE(meson8b_sdhc, HHI_GCLK_MPEG0, 14);
+static MESON_GATE(meson8b_stream, HHI_GCLK_MPEG0, 15);
+static MESON_GATE(meson8b_async_fifo, HHI_GCLK_MPEG0, 16);
+static MESON_GATE(meson8b_sdio, HHI_GCLK_MPEG0, 17);
+static MESON_GATE(meson8b_abuf, HHI_GCLK_MPEG0, 18);
+static MESON_GATE(meson8b_hiu_iface, HHI_GCLK_MPEG0, 19);
+static MESON_GATE(meson8b_assist_misc, HHI_GCLK_MPEG0, 23);
+static MESON_GATE(meson8b_spi, HHI_GCLK_MPEG0, 30);
+
+static MESON_GATE(meson8b_i2s_spdif, HHI_GCLK_MPEG1, 2);
+static MESON_GATE(meson8b_eth, HHI_GCLK_MPEG1, 3);
+static MESON_GATE(meson8b_demux, HHI_GCLK_MPEG1, 4);
+static MESON_GATE(meson8b_aiu_glue, HHI_GCLK_MPEG1, 6);
+static MESON_GATE(meson8b_iec958, HHI_GCLK_MPEG1, 7);
+static MESON_GATE(meson8b_i2s_out, HHI_GCLK_MPEG1, 8);
+static MESON_GATE(meson8b_amclk, HHI_GCLK_MPEG1, 9);
+static MESON_GATE(meson8b_aififo2, HHI_GCLK_MPEG1, 10);
+static MESON_GATE(meson8b_mixer, HHI_GCLK_MPEG1, 11);
+static MESON_GATE(meson8b_mixer_iface, HHI_GCLK_MPEG1, 12);
+static MESON_GATE(meson8b_adc, HHI_GCLK_MPEG1, 13);
+static MESON_GATE(meson8b_blkmv, HHI_GCLK_MPEG1, 14);
+static MESON_GATE(meson8b_aiu, HHI_GCLK_MPEG1, 15);
+static MESON_GATE(meson8b_uart1, HHI_GCLK_MPEG1, 16);
+static MESON_GATE(meson8b_g2d, HHI_GCLK_MPEG1, 20);
+static MESON_GATE(meson8b_usb0, HHI_GCLK_MPEG1, 21);
+static MESON_GATE(meson8b_usb1, HHI_GCLK_MPEG1, 22);
+static MESON_GATE(meson8b_reset, HHI_GCLK_MPEG1, 23);
+static MESON_GATE(meson8b_nand, HHI_GCLK_MPEG1, 24);
+static MESON_GATE(meson8b_dos_parser, HHI_GCLK_MPEG1, 25);
+static MESON_GATE(meson8b_usb, HHI_GCLK_MPEG1, 26);
+static MESON_GATE(meson8b_vdin1, HHI_GCLK_MPEG1, 28);
+static MESON_GATE(meson8b_ahb_arb0, HHI_GCLK_MPEG1, 29);
+static MESON_GATE(meson8b_efuse, HHI_GCLK_MPEG1, 30);
+static MESON_GATE(meson8b_boot_rom, HHI_GCLK_MPEG1, 31);
+
+static MESON_GATE(meson8b_ahb_data_bus, HHI_GCLK_MPEG2, 1);
+static MESON_GATE(meson8b_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
+static MESON_GATE(meson8b_hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
+static MESON_GATE(meson8b_hdmi_pclk, HHI_GCLK_MPEG2, 4);
+static MESON_GATE(meson8b_usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
+static MESON_GATE(meson8b_usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
+static MESON_GATE(meson8b_mmc_pclk, HHI_GCLK_MPEG2, 11);
+static MESON_GATE(meson8b_dvin, HHI_GCLK_MPEG2, 12);
+static MESON_GATE(meson8b_uart2, HHI_GCLK_MPEG2, 15);
+static MESON_GATE(meson8b_sana, HHI_GCLK_MPEG2, 22);
+static MESON_GATE(meson8b_vpu_intr, HHI_GCLK_MPEG2, 25);
+static MESON_GATE(meson8b_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
+static MESON_GATE(meson8b_clk81_a9, HHI_GCLK_MPEG2, 29);
+
+static MESON_GATE(meson8b_vclk2_venci0, HHI_GCLK_OTHER, 1);
+static MESON_GATE(meson8b_vclk2_venci1, HHI_GCLK_OTHER, 2);
+static MESON_GATE(meson8b_vclk2_vencp0, HHI_GCLK_OTHER, 3);
+static MESON_GATE(meson8b_vclk2_vencp1, HHI_GCLK_OTHER, 4);
+static MESON_GATE(meson8b_gclk_venci_int, HHI_GCLK_OTHER, 8);
+static MESON_GATE(meson8b_gclk_vencp_int, HHI_GCLK_OTHER, 9);
+static MESON_GATE(meson8b_dac_clk, HHI_GCLK_OTHER, 10);
+static MESON_GATE(meson8b_aoclk_gate, HHI_GCLK_OTHER, 14);
+static MESON_GATE(meson8b_iec958_gate, HHI_GCLK_OTHER, 16);
+static MESON_GATE(meson8b_enc480p, HHI_GCLK_OTHER, 20);
+static MESON_GATE(meson8b_rng1, HHI_GCLK_OTHER, 21);
+static MESON_GATE(meson8b_gclk_vencl_int, HHI_GCLK_OTHER, 22);
+static MESON_GATE(meson8b_vclk2_venclmcc, HHI_GCLK_OTHER, 24);
+static MESON_GATE(meson8b_vclk2_vencl, HHI_GCLK_OTHER, 25);
+static MESON_GATE(meson8b_vclk2_other, HHI_GCLK_OTHER, 26);
+static MESON_GATE(meson8b_edp, HHI_GCLK_OTHER, 31);
+
+/* Always On (AO) domain gates */
+
+static MESON_GATE(meson8b_ao_media_cpu, HHI_GCLK_AO, 0);
+static MESON_GATE(meson8b_ao_ahb_sram, HHI_GCLK_AO, 1);
+static MESON_GATE(meson8b_ao_ahb_bus, HHI_GCLK_AO, 2);
+static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3);
+
 static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
 	.hws = {
 		[CLKID_XTAL] = &meson8b_xtal.hw,
@@ -328,6 +414,83 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
 		[CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw,
 		[CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw,
 		[CLKID_CLK81] = &meson8b_clk81.hw,
+		[CLKID_DDR]		    = &meson8b_ddr.hw,
+		[CLKID_DOS]		    = &meson8b_dos.hw,
+		[CLKID_ISA]		    = &meson8b_isa.hw,
+		[CLKID_PL301]		    = &meson8b_pl301.hw,
+		[CLKID_PERIPHS]		    = &meson8b_periphs.hw,
+		[CLKID_SPICC]		    = &meson8b_spicc.hw,
+		[CLKID_I2C]		    = &meson8b_i2c.hw,
+		[CLKID_SAR_ADC]		    = &meson8b_sar_adc.hw,
+		[CLKID_SMART_CARD]	    = &meson8b_smart_card.hw,
+		[CLKID_RNG0]		    = &meson8b_rng0.hw,
+		[CLKID_UART0]		    = &meson8b_uart0.hw,
+		[CLKID_SDHC]		    = &meson8b_sdhc.hw,
+		[CLKID_STREAM]		    = &meson8b_stream.hw,
+		[CLKID_ASYNC_FIFO]	    = &meson8b_async_fifo.hw,
+		[CLKID_SDIO]		    = &meson8b_sdio.hw,
+		[CLKID_ABUF]		    = &meson8b_abuf.hw,
+		[CLKID_HIU_IFACE]	    = &meson8b_hiu_iface.hw,
+		[CLKID_ASSIST_MISC]	    = &meson8b_assist_misc.hw,
+		[CLKID_SPI]		    = &meson8b_spi.hw,
+		[CLKID_I2S_SPDIF]	    = &meson8b_i2s_spdif.hw,
+		[CLKID_ETH]		    = &meson8b_eth.hw,
+		[CLKID_DEMUX]		    = &meson8b_demux.hw,
+		[CLKID_AIU_GLUE]	    = &meson8b_aiu_glue.hw,
+		[CLKID_IEC958]		    = &meson8b_iec958.hw,
+		[CLKID_I2S_OUT]		    = &meson8b_i2s_out.hw,
+		[CLKID_AMCLK]		    = &meson8b_amclk.hw,
+		[CLKID_AIFIFO2]		    = &meson8b_aififo2.hw,
+		[CLKID_MIXER]		    = &meson8b_mixer.hw,
+		[CLKID_MIXER_IFACE]	    = &meson8b_mixer_iface.hw,
+		[CLKID_ADC]		    = &meson8b_adc.hw,
+		[CLKID_BLKMV]		    = &meson8b_blkmv.hw,
+		[CLKID_AIU]		    = &meson8b_aiu.hw,
+		[CLKID_UART1]		    = &meson8b_uart1.hw,
+		[CLKID_G2D]		    = &meson8b_g2d.hw,
+		[CLKID_USB0]		    = &meson8b_usb0.hw,
+		[CLKID_USB1]		    = &meson8b_usb1.hw,
+		[CLKID_RESET]		    = &meson8b_reset.hw,
+		[CLKID_NAND]		    = &meson8b_nand.hw,
+		[CLKID_DOS_PARSER]	    = &meson8b_dos_parser.hw,
+		[CLKID_USB]		    = &meson8b_usb.hw,
+		[CLKID_VDIN1]		    = &meson8b_vdin1.hw,
+		[CLKID_AHB_ARB0]	    = &meson8b_ahb_arb0.hw,
+		[CLKID_EFUSE]		    = &meson8b_efuse.hw,
+		[CLKID_BOOT_ROM]	    = &meson8b_boot_rom.hw,
+		[CLKID_AHB_DATA_BUS]	    = &meson8b_ahb_data_bus.hw,
+		[CLKID_AHB_CTRL_BUS]	    = &meson8b_ahb_ctrl_bus.hw,
+		[CLKID_HDMI_INTR_SYNC]	    = &meson8b_hdmi_intr_sync.hw,
+		[CLKID_HDMI_PCLK]	    = &meson8b_hdmi_pclk.hw,
+		[CLKID_USB1_DDR_BRIDGE]	    = &meson8b_usb1_ddr_bridge.hw,
+		[CLKID_USB0_DDR_BRIDGE]	    = &meson8b_usb0_ddr_bridge.hw,
+		[CLKID_MMC_PCLK]	    = &meson8b_mmc_pclk.hw,
+		[CLKID_DVIN]		    = &meson8b_dvin.hw,
+		[CLKID_UART2]		    = &meson8b_uart2.hw,
+		[CLKID_SANA]		    = &meson8b_sana.hw,
+		[CLKID_VPU_INTR]	    = &meson8b_vpu_intr.hw,
+		[CLKID_SEC_AHB_AHB3_BRIDGE] = &meson8b_sec_ahb_ahb3_bridge.hw,
+		[CLKID_CLK81_A9]	    = &meson8b_clk81_a9.hw,
+		[CLKID_VCLK2_VENCI0]	    = &meson8b_vclk2_venci0.hw,
+		[CLKID_VCLK2_VENCI1]	    = &meson8b_vclk2_venci1.hw,
+		[CLKID_VCLK2_VENCP0]	    = &meson8b_vclk2_vencp0.hw,
+		[CLKID_VCLK2_VENCP1]	    = &meson8b_vclk2_vencp1.hw,
+		[CLKID_GCLK_VENCI_INT]	    = &meson8b_gclk_venci_int.hw,
+		[CLKID_GCLK_VENCI_INT]	    = &meson8b_gclk_vencp_int.hw,
+		[CLKID_DAC_CLK]		    = &meson8b_dac_clk.hw,
+		[CLKID_AOCLK_GATE]	    = &meson8b_aoclk_gate.hw,
+		[CLKID_IEC958_GATE]	    = &meson8b_iec958_gate.hw,
+		[CLKID_ENC480P]		    = &meson8b_enc480p.hw,
+		[CLKID_RNG1]		    = &meson8b_rng1.hw,
+		[CLKID_GCLK_VENCL_INT]	    = &meson8b_gclk_vencl_int.hw,
+		[CLKID_VCLK2_VENCLMCC]	    = &meson8b_vclk2_venclmcc.hw,
+		[CLKID_VCLK2_VENCL]	    = &meson8b_vclk2_vencl.hw,
+		[CLKID_VCLK2_OTHER]	    = &meson8b_vclk2_other.hw,
+		[CLKID_EDP]		    = &meson8b_edp.hw,
+		[CLKID_AO_MEDIA_CPU]	    = &meson8b_ao_media_cpu.hw,
+		[CLKID_AO_AHB_SRAM]	    = &meson8b_ao_ahb_sram.hw,
+		[CLKID_AO_AHB_BUS]	    = &meson8b_ao_ahb_bus.hw,
+		[CLKID_AO_IFACE]	    = &meson8b_ao_iface.hw,
 	},
 	.num = CLK_NR_CLKS,
 };
@@ -338,6 +501,87 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
 	&meson8b_sys_pll,
 };
 
+static struct clk_gate *meson8b_clk_gates[] = {
+	&meson8b_clk81,
+	&meson8b_ddr,
+	&meson8b_dos,
+	&meson8b_isa,
+	&meson8b_pl301,
+	&meson8b_periphs,
+	&meson8b_spicc,
+	&meson8b_i2c,
+	&meson8b_sar_adc,
+	&meson8b_smart_card,
+	&meson8b_rng0,
+	&meson8b_uart0,
+	&meson8b_sdhc,
+	&meson8b_stream,
+	&meson8b_async_fifo,
+	&meson8b_sdio,
+	&meson8b_abuf,
+	&meson8b_hiu_iface,
+	&meson8b_assist_misc,
+	&meson8b_spi,
+	&meson8b_i2s_spdif,
+	&meson8b_eth,
+	&meson8b_demux,
+	&meson8b_aiu_glue,
+	&meson8b_iec958,
+	&meson8b_i2s_out,
+	&meson8b_amclk,
+	&meson8b_aififo2,
+	&meson8b_mixer,
+	&meson8b_mixer_iface,
+	&meson8b_adc,
+	&meson8b_blkmv,
+	&meson8b_aiu,
+	&meson8b_uart1,
+	&meson8b_g2d,
+	&meson8b_usb0,
+	&meson8b_usb1,
+	&meson8b_reset,
+	&meson8b_nand,
+	&meson8b_dos_parser,
+	&meson8b_usb,
+	&meson8b_vdin1,
+	&meson8b_ahb_arb0,
+	&meson8b_efuse,
+	&meson8b_boot_rom,
+	&meson8b_ahb_data_bus,
+	&meson8b_ahb_ctrl_bus,
+	&meson8b_hdmi_intr_sync,
+	&meson8b_hdmi_pclk,
+	&meson8b_usb1_ddr_bridge,
+	&meson8b_usb0_ddr_bridge,
+	&meson8b_mmc_pclk,
+	&meson8b_dvin,
+	&meson8b_uart2,
+	&meson8b_sana,
+	&meson8b_vpu_intr,
+	&meson8b_sec_ahb_ahb3_bridge,
+	&meson8b_clk81_a9,
+	&meson8b_vclk2_venci0,
+	&meson8b_vclk2_venci1,
+	&meson8b_vclk2_vencp0,
+	&meson8b_vclk2_vencp1,
+	&meson8b_gclk_venci_int,
+	&meson8b_gclk_vencp_int,
+	&meson8b_dac_clk,
+	&meson8b_aoclk_gate,
+	&meson8b_iec958_gate,
+	&meson8b_enc480p,
+	&meson8b_rng1,
+	&meson8b_gclk_vencl_int,
+	&meson8b_vclk2_venclmcc,
+	&meson8b_vclk2_vencl,
+	&meson8b_vclk2_other,
+	&meson8b_edp,
+	&meson8b_ao_media_cpu,
+	&meson8b_ao_ahb_sram,
+	&meson8b_ao_ahb_bus,
+	&meson8b_ao_iface,
+};
+
 static int meson8b_clkc_probe(struct platform_device *pdev)
 {
 	void __iomem *clk_base;
@@ -365,6 +609,11 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
 	meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
 	meson8b_clk81.reg = clk_base + (u32)meson8b_clk81.reg;
 
+	/* Populate base address for gates */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
+		meson8b_clk_gates[i]->reg = clk_base +
+			(u32)meson8b_clk_gates[i]->reg;
+
 	/*
 	 * register all clks
 	 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 86efe6a..010e958 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -30,6 +30,11 @@
  *
  * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
  */
+#define HHI_GCLK_MPEG0			0x140 /* 0x50 offset in data sheet */
+#define HHI_GCLK_MPEG1			0x144 /* 0x51 offset in data sheet */
+#define HHI_GCLK_MPEG2			0x148 /* 0x52 offset in data sheet */
+#define HHI_GCLK_OTHER			0x150 /* 0x54 offset in data sheet */
+#define HHI_GCLK_AO			0x154 /* 0x55 offset in data sheet */
 #define HHI_SYS_CPU_CLK_CNTL1		0x15c /* 0x57 offset in data sheet */
 #define HHI_MPEG_CLK_CNTL		0x174 /* 0x5d offset in data sheet */
 #define HHI_MPLL_CNTL			0x280 /* 0xa0 offset in data sheet */
-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:40:53 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sat, 27 Aug 2016 19:40:53 +0200
Subject: [PATCH v5 5/6] gxbb: clk: Adjust MESON_GATE macro to be shared with
 meson8b
In-Reply-To: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
References: <1472319654-59048-1-git-send-email-serveralex@gmail.com>
Message-ID: <1472319654-59048-6-git-send-email-serveralex@gmail.com>

The macro used gxbb_ prefix for clock definitions. In order
to share the macro between gxbb and meson8b, the prefix must
be moved to gxbb.c.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/clkc.h |   2 +-
 drivers/clk/meson/gxbb.c | 162 +++++++++++++++++++++++------------------------
 2 files changed, 82 insertions(+), 82 deletions(-)

diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 53326c3..9bb70e7 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -98,7 +98,7 @@ struct meson_clk_mpll {
 };
 
 #define MESON_GATE(_name, _reg, _bit)					\
-struct clk_gate gxbb_##_name = { 						\
+struct clk_gate _name = { 						\
 	.reg = (void __iomem *) _reg, 					\
 	.bit_idx = (_bit), 						\
 	.lock = &clk_lock,						\
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index a4c6684b..ab7a3b5 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -565,90 +565,90 @@ static struct clk_gate gxbb_clk81 = {
 };
 
 /* Everything Else (EE) domain gates */
-static MESON_GATE(ddr, HHI_GCLK_MPEG0, 0);
-static MESON_GATE(dos, HHI_GCLK_MPEG0, 1);
-static MESON_GATE(isa, HHI_GCLK_MPEG0, 5);
-static MESON_GATE(pl301, HHI_GCLK_MPEG0, 6);
-static MESON_GATE(periphs, HHI_GCLK_MPEG0, 7);
-static MESON_GATE(spicc, HHI_GCLK_MPEG0, 8);
-static MESON_GATE(i2c, HHI_GCLK_MPEG0, 9);
-static MESON_GATE(sar_adc, HHI_GCLK_MPEG0, 10);
-static MESON_GATE(smart_card, HHI_GCLK_MPEG0, 11);
-static MESON_GATE(rng0, HHI_GCLK_MPEG0, 12);
-static MESON_GATE(uart0, HHI_GCLK_MPEG0, 13);
-static MESON_GATE(sdhc, HHI_GCLK_MPEG0, 14);
-static MESON_GATE(stream, HHI_GCLK_MPEG0, 15);
-static MESON_GATE(async_fifo, HHI_GCLK_MPEG0, 16);
-static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17);
-static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18);
-static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19);
-static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23);
-static MESON_GATE(spi, HHI_GCLK_MPEG0, 30);
-
-static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2);
-static MESON_GATE(eth, HHI_GCLK_MPEG1, 3);
-static MESON_GATE(demux, HHI_GCLK_MPEG1, 4);
-static MESON_GATE(aiu_glue, HHI_GCLK_MPEG1, 6);
-static MESON_GATE(iec958, HHI_GCLK_MPEG1, 7);
-static MESON_GATE(i2s_out, HHI_GCLK_MPEG1, 8);
-static MESON_GATE(amclk, HHI_GCLK_MPEG1, 9);
-static MESON_GATE(aififo2, HHI_GCLK_MPEG1, 10);
-static MESON_GATE(mixer, HHI_GCLK_MPEG1, 11);
-static MESON_GATE(mixer_iface, HHI_GCLK_MPEG1, 12);
-static MESON_GATE(adc, HHI_GCLK_MPEG1, 13);
-static MESON_GATE(blkmv, HHI_GCLK_MPEG1, 14);
-static MESON_GATE(aiu, HHI_GCLK_MPEG1, 15);
-static MESON_GATE(uart1, HHI_GCLK_MPEG1, 16);
-static MESON_GATE(g2d, HHI_GCLK_MPEG1, 20);
-static MESON_GATE(usb0, HHI_GCLK_MPEG1, 21);
-static MESON_GATE(usb1, HHI_GCLK_MPEG1, 22);
-static MESON_GATE(reset, HHI_GCLK_MPEG1, 23);
-static MESON_GATE(nand, HHI_GCLK_MPEG1, 24);
-static MESON_GATE(dos_parser, HHI_GCLK_MPEG1, 25);
-static MESON_GATE(usb, HHI_GCLK_MPEG1, 26);
-static MESON_GATE(vdin1, HHI_GCLK_MPEG1, 28);
-static MESON_GATE(ahb_arb0, HHI_GCLK_MPEG1, 29);
-static MESON_GATE(efuse, HHI_GCLK_MPEG1, 30);
-static MESON_GATE(boot_rom, HHI_GCLK_MPEG1, 31);
-
-static MESON_GATE(ahb_data_bus, HHI_GCLK_MPEG2, 1);
-static MESON_GATE(ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
-static MESON_GATE(hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
-static MESON_GATE(hdmi_pclk, HHI_GCLK_MPEG2, 4);
-static MESON_GATE(usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
-static MESON_GATE(usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
-static MESON_GATE(mmc_pclk, HHI_GCLK_MPEG2, 11);
-static MESON_GATE(dvin, HHI_GCLK_MPEG2, 12);
-static MESON_GATE(uart2, HHI_GCLK_MPEG2, 15);
-static MESON_GATE(sana, HHI_GCLK_MPEG2, 22);
-static MESON_GATE(vpu_intr, HHI_GCLK_MPEG2, 25);
-static MESON_GATE(sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
-static MESON_GATE(clk81_a53, HHI_GCLK_MPEG2, 29);
-
-static MESON_GATE(vclk2_venci0, HHI_GCLK_OTHER, 1);
-static MESON_GATE(vclk2_venci1, HHI_GCLK_OTHER, 2);
-static MESON_GATE(vclk2_vencp0, HHI_GCLK_OTHER, 3);
-static MESON_GATE(vclk2_vencp1, HHI_GCLK_OTHER, 4);
-static MESON_GATE(gclk_venci_int0, HHI_GCLK_OTHER, 8);
-static MESON_GATE(gclk_vencp_int, HHI_GCLK_OTHER, 9);
-static MESON_GATE(dac_clk, HHI_GCLK_OTHER, 10);
-static MESON_GATE(aoclk_gate, HHI_GCLK_OTHER, 14);
-static MESON_GATE(iec958_gate, HHI_GCLK_OTHER, 16);
-static MESON_GATE(enc480p, HHI_GCLK_OTHER, 20);
-static MESON_GATE(rng1, HHI_GCLK_OTHER, 21);
-static MESON_GATE(gclk_venci_int1, HHI_GCLK_OTHER, 22);
-static MESON_GATE(vclk2_venclmcc, HHI_GCLK_OTHER, 24);
-static MESON_GATE(vclk2_vencl, HHI_GCLK_OTHER, 25);
-static MESON_GATE(vclk_other, HHI_GCLK_OTHER, 26);
-static MESON_GATE(edp, HHI_GCLK_OTHER, 31);
+static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
+static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
+static MESON_GATE(gxbb_isa, HHI_GCLK_MPEG0, 5);
+static MESON_GATE(gxbb_pl301, HHI_GCLK_MPEG0, 6);
+static MESON_GATE(gxbb_periphs, HHI_GCLK_MPEG0, 7);
+static MESON_GATE(gxbb_spicc, HHI_GCLK_MPEG0, 8);
+static MESON_GATE(gxbb_i2c, HHI_GCLK_MPEG0, 9);
+static MESON_GATE(gxbb_sar_adc, HHI_GCLK_MPEG0, 10);
+static MESON_GATE(gxbb_smart_card, HHI_GCLK_MPEG0, 11);
+static MESON_GATE(gxbb_rng0, HHI_GCLK_MPEG0, 12);
+static MESON_GATE(gxbb_uart0, HHI_GCLK_MPEG0, 13);
+static MESON_GATE(gxbb_sdhc, HHI_GCLK_MPEG0, 14);
+static MESON_GATE(gxbb_stream, HHI_GCLK_MPEG0, 15);
+static MESON_GATE(gxbb_async_fifo, HHI_GCLK_MPEG0, 16);
+static MESON_GATE(gxbb_sdio, HHI_GCLK_MPEG0, 17);
+static MESON_GATE(gxbb_abuf, HHI_GCLK_MPEG0, 18);
+static MESON_GATE(gxbb_hiu_iface, HHI_GCLK_MPEG0, 19);
+static MESON_GATE(gxbb_assist_misc, HHI_GCLK_MPEG0, 23);
+static MESON_GATE(gxbb_spi, HHI_GCLK_MPEG0, 30);
+
+static MESON_GATE(gxbb_i2s_spdif, HHI_GCLK_MPEG1, 2);
+static MESON_GATE(gxbb_eth, HHI_GCLK_MPEG1, 3);
+static MESON_GATE(gxbb_demux, HHI_GCLK_MPEG1, 4);
+static MESON_GATE(gxbb_aiu_glue, HHI_GCLK_MPEG1, 6);
+static MESON_GATE(gxbb_iec958, HHI_GCLK_MPEG1, 7);
+static MESON_GATE(gxbb_i2s_out, HHI_GCLK_MPEG1, 8);
+static MESON_GATE(gxbb_amclk, HHI_GCLK_MPEG1, 9);
+static MESON_GATE(gxbb_aififo2, HHI_GCLK_MPEG1, 10);
+static MESON_GATE(gxbb_mixer, HHI_GCLK_MPEG1, 11);
+static MESON_GATE(gxbb_mixer_iface, HHI_GCLK_MPEG1, 12);
+static MESON_GATE(gxbb_adc, HHI_GCLK_MPEG1, 13);
+static MESON_GATE(gxbb_blkmv, HHI_GCLK_MPEG1, 14);
+static MESON_GATE(gxbb_aiu, HHI_GCLK_MPEG1, 15);
+static MESON_GATE(gxbb_uart1, HHI_GCLK_MPEG1, 16);
+static MESON_GATE(gxbb_g2d, HHI_GCLK_MPEG1, 20);
+static MESON_GATE(gxbb_usb0, HHI_GCLK_MPEG1, 21);
+static MESON_GATE(gxbb_usb1, HHI_GCLK_MPEG1, 22);
+static MESON_GATE(gxbb_reset, HHI_GCLK_MPEG1, 23);
+static MESON_GATE(gxbb_nand, HHI_GCLK_MPEG1, 24);
+static MESON_GATE(gxbb_dos_parser, HHI_GCLK_MPEG1, 25);
+static MESON_GATE(gxbb_usb, HHI_GCLK_MPEG1, 26);
+static MESON_GATE(gxbb_vdin1, HHI_GCLK_MPEG1, 28);
+static MESON_GATE(gxbb_ahb_arb0, HHI_GCLK_MPEG1, 29);
+static MESON_GATE(gxbb_efuse, HHI_GCLK_MPEG1, 30);
+static MESON_GATE(gxbb_boot_rom, HHI_GCLK_MPEG1, 31);
+
+static MESON_GATE(gxbb_ahb_data_bus, HHI_GCLK_MPEG2, 1);
+static MESON_GATE(gxbb_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
+static MESON_GATE(gxbb_hdmi_intr_sync, HHI_GCLK_MPEG2, 3);
+static MESON_GATE(gxbb_hdmi_pclk, HHI_GCLK_MPEG2, 4);
+static MESON_GATE(gxbb_usb1_ddr_bridge, HHI_GCLK_MPEG2, 8);
+static MESON_GATE(gxbb_usb0_ddr_bridge, HHI_GCLK_MPEG2, 9);
+static MESON_GATE(gxbb_mmc_pclk, HHI_GCLK_MPEG2, 11);
+static MESON_GATE(gxbb_dvin, HHI_GCLK_MPEG2, 12);
+static MESON_GATE(gxbb_uart2, HHI_GCLK_MPEG2, 15);
+static MESON_GATE(gxbb_sana, HHI_GCLK_MPEG2, 22);
+static MESON_GATE(gxbb_vpu_intr, HHI_GCLK_MPEG2, 25);
+static MESON_GATE(gxbb_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
+static MESON_GATE(gxbb_clk81_a53, HHI_GCLK_MPEG2, 29);
+
+static MESON_GATE(gxbb_vclk2_venci0, HHI_GCLK_OTHER, 1);
+static MESON_GATE(gxbb_vclk2_venci1, HHI_GCLK_OTHER, 2);
+static MESON_GATE(gxbb_vclk2_vencp0, HHI_GCLK_OTHER, 3);
+static MESON_GATE(gxbb_vclk2_vencp1, HHI_GCLK_OTHER, 4);
+static MESON_GATE(gxbb_gclk_venci_int0, HHI_GCLK_OTHER, 8);
+static MESON_GATE(gxbb_gclk_vencp_int, HHI_GCLK_OTHER, 9);
+static MESON_GATE(gxbb_dac_clk, HHI_GCLK_OTHER, 10);
+static MESON_GATE(gxbb_aoclk_gate, HHI_GCLK_OTHER, 14);
+static MESON_GATE(gxbb_iec958_gate, HHI_GCLK_OTHER, 16);
+static MESON_GATE(gxbb_enc480p, HHI_GCLK_OTHER, 20);
+static MESON_GATE(gxbb_rng1, HHI_GCLK_OTHER, 21);
+static MESON_GATE(gxbb_gclk_venci_int1, HHI_GCLK_OTHER, 22);
+static MESON_GATE(gxbb_vclk2_venclmcc, HHI_GCLK_OTHER, 24);
+static MESON_GATE(gxbb_vclk2_vencl, HHI_GCLK_OTHER, 25);
+static MESON_GATE(gxbb_vclk_other, HHI_GCLK_OTHER, 26);
+static MESON_GATE(gxbb_edp, HHI_GCLK_OTHER, 31);
 
 /* Always On (AO) domain gates */
 
-static MESON_GATE(ao_media_cpu, HHI_GCLK_AO, 0);
-static MESON_GATE(ao_ahb_sram, HHI_GCLK_AO, 1);
-static MESON_GATE(ao_ahb_bus, HHI_GCLK_AO, 2);
-static MESON_GATE(ao_iface, HHI_GCLK_AO, 3);
-static MESON_GATE(ao_i2c, HHI_GCLK_AO, 4);
+static MESON_GATE(gxbb_ao_media_cpu, HHI_GCLK_AO, 0);
+static MESON_GATE(gxbb_ao_ahb_sram, HHI_GCLK_AO, 1);
+static MESON_GATE(gxbb_ao_ahb_bus, HHI_GCLK_AO, 2);
+static MESON_GATE(gxbb_ao_iface, HHI_GCLK_AO, 3);
+static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4);
 
 /* Array of all clocks provided by this provider */
 
-- 
2.5.0



From serveralex at gmail.com  Sat Aug 27 10:42:26 2016
From: serveralex at gmail.com (=?UTF-8?Q?Alexander_M=c3=bcller?=)
Date: Sat, 27 Aug 2016 19:42:26 +0200
Subject: [PATCH v4 0/6] Add Amlogic meson8b clock gates
In-Reply-To: <147208467939.32728.10815386393422927131@resonance>
References: <1469800864-43440-1-git-send-email-serveralex@gmail.com>
 <147208467939.32728.10815386393422927131@resonance>
Message-ID: <b4db9b01-89ec-ec83-8e66-d88f03dda681@gmail.com>

Hi Mike,

The rebased patch series is on its way. Thanks!

Regards,
Alex

On 25/08/16 02:24, Michael Turquette wrote:
> Quoting Alexander M?ller (2016-07-29 07:00:58)
>> This patch series adds support for the Amlogic meson8b clock gates. The Amlogic
>> U-Boot disables most of them at boot. In order to enable ethernet, USB and other
>> components it's mandatory to enable the clock gates when loading the corresponding
>> drivers.
>>
>> The meson8b clock gate support is based on the previous work done for Amlogic gxbb
>> currently available in clk-next.
> 
> Hi Alexander,
> 
> This series looks good to me. Can you rebase it against the
> clk-meson-gxbb-ao branch?
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-meson-gxbb-ao
> 
> I'll merge it on top of that and Kevin and Carlo can pull it into the
> linux-amlogic tree if they feel like it.
> 
> Regards,
> Mike
> 
>>
>> Changes since v3:
>>   - Include include/dt-bindings/clock/meson8b-clkc.h to prevent code duplicates
>>
>> Changes since v2:
>>   - Added commit description for patch 2
>>   - Changed CLK_NR_CLOCKS macro to constant int
>>   - Moved back MESON_GATE macro to share it between gxbb and meson8b
>>
>> Changes since v1:
>>   - Fixed GXBB spelling
>>   - Moved newly introduced CLKID defines to private header
>>   - Moved CLK_NR_CLKS define from DT binding to private header
>>   - Rebased to linux-amlogic/v4.7/integ making Kconfig select obsolete
>>
>> Alexander M?ller (6):
>>   clk: meson: Rename meson8b-clkc.c to reflect gxbb naming convention
>>   meson: clk: Move register definitions to meson8b.h
>>   meson: clk: Rename register names according to Amlogic datasheet
>>   clk: meson: Copy meson8b CLKID defines to private header file
>>   gxbb: clk: Adjust MESON_GATE macro to be shared with meson8b
>>   meson: clk: Add support for clock gates
>>
>>  drivers/clk/meson/Makefile                      |   2 +-
>>  drivers/clk/meson/clkc.h                        |   2 +-
>>  drivers/clk/meson/gxbb.c                        | 162 ++++++-------
>>  drivers/clk/meson/{meson8b-clkc.c => meson8b.c} | 293 +++++++++++++++++++++---
>>  drivers/clk/meson/meson8b.h                     | 151 ++++++++++++
>>  include/dt-bindings/clock/meson8b-clkc.h        |   2 -
>>  6 files changed, 497 insertions(+), 115 deletions(-)
>>  rename drivers/clk/meson/{meson8b-clkc.c => meson8b.c} (52%)
>>  create mode 100644 drivers/clk/meson/meson8b.h
>>
>> -- 
>> 2.5.0
>>


From martin.blumenstingl at googlemail.com  Sat Aug 27 14:32:51 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 27 Aug 2016 23:32:51 +0200
Subject: USB PHY documentation
In-Reply-To: <CAO9vn2P8vPwFFpz-VN3WKV_BNhwXWW=NkjTEhoGvYShbrZMwsA@mail.gmail.com>
References: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
 <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>
 <1472029412.2322.13.camel@baylibre.com>
 <CAFBinCCx4X_Lsd9NsFd-9aHL67EvCJDebdzc8zdSP9Hcw__BOA@mail.gmail.com>
 <CAO9vn2P8vPwFFpz-VN3WKV_BNhwXWW=NkjTEhoGvYShbrZMwsA@mail.gmail.com>
Message-ID: <CAFBinCDuuw+J3BynPW+6Q3JvgvXcJi4+3ioSr6i43ONpm=DH9A@mail.gmail.com>

On Fri, Aug 26, 2016 at 12:55 PM, J?r?me Brunet <jbrunet at baylibre.com> wrote:
> I did some test on the otg controller. I had to remove the reset in the PHY
> because it was reseting both of them, so the reset intended for the 2nd PHY
> was breaking the configuration of the 1st.
I am getting the following error when 1) removing the reset and 2)
booting the mainline kernel directly (without booting the stock
Android kernel first):
[    1.297507] dwc2 c9000000.usb-controller: dwc2_core_reset() HANG!
AHB Idle GRSTCTL=0
[    1.305116] dwc2 c9000000.usb-controller: Bad value for GSNPSID: 0x00000000


From carlo at caione.org  Sun Aug 28 04:01:53 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 28 Aug 2016 13:01:53 +0200
Subject: [PATCH v2] ARM64: dts: amlogic: Add basic support for Amlogic S905X
Message-ID: <1472382113-10754-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

This patch introduces the basic support for the Amlogic S905X (Meson
GXL) and for the Amlogic evaluation board P212.
No documentation has been released yet for this SoC, so for now only the
bare minimum has been added in the DT.

Acked-by: Rob Herring <robh at kernel.org>
Reviewed-by: Andreas F?rber <afaerber at suse.de>
Signed-off-by: Carlo Caione <carlo at endlessm.com>
---

Hey Kevin,
Can you take this one?

Changelog:
v2:
  - Added acked-by and reviewed-by

---
 Documentation/devicetree/bindings/arm/amlogic.txt |   5 +
 arch/arm64/boot/dts/amlogic/Makefile              |   1 +
 arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts    |  70 +++++++++
 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi        | 179 ++++++++++++++++++++++
 4 files changed, 255 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi

diff --git a/Documentation/devicetree/bindings/arm/amlogic.txt b/Documentation/devicetree/bindings/arm/amlogic.txt
index fcc6f6c..ea75333 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.txt
+++ b/Documentation/devicetree/bindings/arm/amlogic.txt
@@ -17,6 +17,10 @@ Boards with the Amlogic Meson GXBaby SoC shall have the following properties:
   Required root node property:
     compatible: "amlogic,meson-gxbb";
 
+Boards with the Amlogic Meson GXL SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,meson-gxl";
+
 Board compatible values:
   - "geniatech,atv1200" (Meson6)
   - "minix,neo-x8" (Meson8)
@@ -28,3 +32,4 @@ Board compatible values:
   - "hardkernel,odroid-c2" (Meson gxbb)
   - "amlogic,p200" (Meson gxbb)
   - "amlogic,p201" (Meson gxbb)
+  - "amlogic,p212" (Meson gxl)
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 47ec703..46ffca7 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-p212.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts
new file mode 100644
index 0000000..046c377
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library 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 library 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "meson-gxl.dtsi"
+
+/ {
+	compatible = "amlogic,p212", "amlogic,meson-gxl";
+	model = "Amlogic Meson GXL (S905X) P212 Development Board";
+
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+/* This UART is brought out to the DB9 connector */
+&uart_AO {
+	status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
new file mode 100644
index 0000000..2aa4555
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library 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 library 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "amlogic,meson-gxl";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cbus: cbus at c1100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc1100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
+
+			uart_A: serial at 84c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x084c0 0x0 0x14>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+		};
+
+		gic: interrupt-controller at c4301000 {
+			compatible = "arm,gic-400";
+			reg = <0x0 0xc4301000 0 0x1000>,
+			      <0x0 0xc4302000 0 0x2000>,
+			      <0x0 0xc4304000 0 0x2000>,
+			      <0x0 0xc4306000 0 0x2000>;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+		};
+
+		aobus: aobus at c8100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
+
+			uart_AO: serial at 4c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004c0 0x0 0x14>;
+				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+		};
+
+		apb: apb at d0000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xd0000000 0x0 0x200000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+		};
+	};
+};
-- 
2.7.4



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:15:31 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:15:31 +0200
Subject: [PATCH v2 1/4] net: dt-bindings: Document the new Meson8b and
 GXBB DWMAC bindings
In-Reply-To: <4041259.IszN4229Cj@wuerfel>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <7308700.atIMKyMFZU@wuerfel>
 <CAFBinCA0HWHR3UbVX-_wU14W0-KOr-BAf5Nyn1ocZdnYxojn2Q@mail.gmail.com>
 <4041259.IszN4229Cj@wuerfel>
Message-ID: <CAFBinCDnHGf=wgvm9KzYQsf=kCrOUeO3bnEwdGy_OK-wgWkDug@mail.gmail.com>

On Mon, Aug 22, 2016 at 5:25 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> It really depends on the kind of SoC. Some may have a suboptimal
> binding, on some others there may be a distinct register area that
> just contains a few additional registers for the dwmac.
the dwmac PHY configuration registers (2x32bit) on the GXBB SoC are
part of the "periphs" region/module. This is already defined as
"simple-bus" in meson-gxbb.dtsi, see [0]
On Meson8b this is slightly different: there is no specific "periphs"
region - there the dwmac PHY configuration registers are directly
located in the cbus region at a slightly different offset than on the
GXBB SoCs.

In the future we might need a third memory region because the latest
reference kernel contains some more PHY configuration registers on
newer SoCs (GXL = S905X).

Please let me know if you're OK with the dts definition in it's
current state - or let me know how you would like to change it.

PS: I will re-send the patches in a v3 in a few minutes because that
fixes a bug during module unload.


Regards,
Martin


[0] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi#n217


From martin.blumenstingl at googlemail.com  Sun Aug 28 09:16:32 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:16:32 +0200
Subject: [PATCH v3 0/5] meson: Meson8b and GXBB DWMAC glue driver
In-Reply-To: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>

This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
the register layout is completely different.
Thus I introduced a separate driver.


Changes since v2:
- fixed unloading the glue driver when built as module. This pulls in a
  patch from Joachim Eastwood (thanks) to get our private data structure
  (bsp_priv).

Joachim Eastwood (1):
  stmmac: introduce get_stmmac_bsp_priv() helper

Martin Blumenstingl (4):
  net: dt-bindings: Document the new Meson8b and GXBB DWMAC bindings
  clk: gxbb: expose MPLL2 clock for use by DT
  net: stmmac: add a glue driver for the Amlogic Meson 8b / GXBB DWMAC
  ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver

 .../devicetree/bindings/net/meson-dwmac.txt        |  45 ++-
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   8 +-
 drivers/clk/meson/gxbb.h                           |   2 +-
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 327 +++++++++++++++++++++
 .../net/ethernet/stmicro/stmmac/stmmac_platform.h  |   8 +
 include/dt-bindings/clock/gxbb-clkc.h              |   1 +
 7 files changed, 380 insertions(+), 13 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:16:34 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:16:34 +0200
Subject: [PATCH v3 2/5] clk: gxbb: expose MPLL2 clock for use by DT
In-Reply-To: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828161637.9941-3-martin.blumenstingl@googlemail.com>

This exposes the MPLL2 clock as this is one of the input clocks of the
ethernet controller's internal mux.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/clk/meson/gxbb.h              | 2 +-
 include/dt-bindings/clock/gxbb-clkc.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 217df51..3606e875 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -183,7 +183,7 @@
 /* CLKID_CLK81 */
 #define CLKID_MPLL0		  13
 #define CLKID_MPLL1		  14
-#define CLKID_MPLL2		  15
+/* CLKID_MPLL2 */
 #define CLKID_DDR		  16
 #define CLKID_DOS		  17
 #define CLKID_ISA		  18
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index 7d41864..244ea6e 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -8,6 +8,7 @@
 #define CLKID_CPUCLK		1
 #define CLKID_FCLK_DIV2		4
 #define CLKID_CLK81		12
+#define CLKID_MPLL2		15
 #define CLKID_ETH		36
 #define CLKID_SD_EMMC_A		94
 #define CLKID_SD_EMMC_B		95
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:16:33 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:16:33 +0200
Subject: [PATCH v3 1/5] net: dt-bindings: Document the new Meson8b and GXBB
 DWMAC bindings
In-Reply-To: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828161637.9941-2-martin.blumenstingl@googlemail.com>

This patch adds the documentation for the DWMAC ethernet controller
found in Amlogic Meson 8b (S805) and GXBB (S905) SoCs.
The main difference between the Meson6 glue is that different registers
(with different layout) are used.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/net/meson-dwmac.txt        | 45 ++++++++++++++++++----
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/meson-dwmac.txt b/Documentation/devicetree/bindings/net/meson-dwmac.txt
index ec633d7..89e62dd 100644
--- a/Documentation/devicetree/bindings/net/meson-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/meson-dwmac.txt
@@ -1,18 +1,32 @@
 * Amlogic Meson DWMAC Ethernet controller
 
 The device inherits all the properties of the dwmac/stmmac devices
-described in the file net/stmmac.txt with the following changes.
+described in the file stmmac.txt in the current directory with the
+following changes.
 
-Required properties:
+Required properties on all platforms:
 
-- compatible: should be "amlogic,meson6-dwmac" along with "snps,dwmac"
-	      and any applicable more detailed version number
-	      described in net/stmmac.txt
+- compatible:	Depending on the platform this should be one of:
+			- "amlogic,meson6-dwmac"
+			- "amlogic,meson8b-dwmac"
+			- "amlogic,meson-gxbb-dwmac"
+		Additionally "snps,dwmac" and any applicable more
+		detailed version number described in net/stmmac.txt
+		should be used.
 
-- reg: should contain a register range for the dwmac controller and
-       another one for the Amlogic specific configuration
+- reg:	The first register range should be the one of the DWMAC
+	controller. The second range is is for the Amlogic specific
+	configuration (for example the PRG_ETHERNET register range
+	on Meson8b and newer)
 
-Example:
+Required properties on Meson8b and newer:
+- clock-names:	Should contain the following:
+		- "stmmaceth" - see stmmac.txt
+		- "clkin0" - first parent clock of the internal mux
+		- "clkin1" - second parent clock of the internal mux
+
+
+Example for Meson6:
 
 	ethmac: ethernet at c9410000 {
 		compatible = "amlogic,meson6-dwmac", "snps,dwmac";
@@ -23,3 +37,18 @@ Example:
 		clocks = <&clk81>;
 		clock-names = "stmmaceth";
 	}
+
+Example for GXBB:
+	ethmac: ethernet at c9410000 {
+		compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+		reg = <0x0 0xc9410000 0x0 0x10000>,
+			<0x0 0xc8834540 0x0 0x8>;
+		interrupts = <0 8 1>;
+		interrupt-names = "macirq";
+		clocks = <&clkc CLKID_ETH>,
+				<&clkc CLKID_FCLK_DIV2>,
+				<&clkc CLKID_MPLL2>;
+		clock-names = "stmmaceth", "clkin0", "clkin1";
+		phy-mode = "rgmii";
+		status = "disabled";
+	};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:16:35 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:16:35 +0200
Subject: [PATCH v3 3/5] stmmac: introduce get_stmmac_bsp_priv() helper
In-Reply-To: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828161637.9941-4-martin.blumenstingl@googlemail.com>

From: Joachim Eastwood <manabian at gmail.com>

Create a helper to retrive dwmac private data from a dev
pointer. This is useful in PM callbacks and driver remove.

Signed-off-by: Joachim Eastwood <manabian at gmail.com>
Tested-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
index ffeb8d9..64e147f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
@@ -30,4 +30,12 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
 int stmmac_pltfr_remove(struct platform_device *pdev);
 extern const struct dev_pm_ops stmmac_pltfr_pm_ops;
 
+static inline void *get_stmmac_bsp_priv(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+
+	return priv->plat->bsp_priv;
+}
+
 #endif /* __STMMAC_PLATFORM_H__ */
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:16:37 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:16:37 +0200
Subject: [PATCH v3 5/5] ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue
 driver
In-Reply-To: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828161637.9941-6-martin.blumenstingl@googlemail.com>

The Amlogic reference driver uses the "mc_val" devicetree property to
configure the PRG_ETHERNET_ADDR0 register. Unfortunately it uses magic
values for this configuration.
According to the datasheet the PRG_ETHERNET_ADDR0 register is at address
0xc8834108. However, the reference driver uses 0xc8834540 instead.
According to my tests, the value from the reference driver is correct.

No changes are required to the board dts files because the only
required configuration option is the phy-mode, which had to be
configured correctly before as well.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 4f42316..ab817d3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -373,13 +373,15 @@
 		};
 
 		ethmac: ethernet at c9410000 {
-			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+			compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
 			reg = <0x0 0xc9410000 0x0 0x10000
 			       0x0 0xc8834540 0x0 0x4>;
 			interrupts = <0 8 1>;
 			interrupt-names = "macirq";
-			clocks = <&clkc CLKID_ETH>;
-			clock-names = "stmmaceth";
+			clocks = <&clkc CLKID_ETH>,
+				 <&clkc CLKID_FCLK_DIV2>,
+				 <&clkc CLKID_MPLL2>;
+			clock-names = "stmmaceth", "clkin0", "clkin1";
 			phy-mode = "rgmii";
 			status = "disabled";
 		};
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:16:36 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:16:36 +0200
Subject: [PATCH v3 4/5] net: stmmac: add a glue driver for the Amlogic Meson
 8b / GXBB DWMAC
In-Reply-To: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828161637.9941-5-martin.blumenstingl@googlemail.com>

The Ethernet controller available in Meson8b and GXBB SoCs is a Synopsys
DesignWare MAC IP core which is already supported by the stmmac driver.

In addition to the standard stmmac driver some Meson8b / GXBB specific
registers have to be configured for the PHY clocks. These SoC specific
registers are called PRG_ETHERNET_ADDR0 and PRG_ETHERNET_ADDR1 in the
datasheet.
These registers are not backwards compatible with those on Meson 6b,
which is why a new glue driver is introduced. This worked for many
boards because the bootloader programs the PRG_ETHERNET registers
correctly. Additionally the meson6-dwmac driver only sets bit 1 of
PRG_ETHERNET_ADDR0 which (according to the datasheet) is only used
during reset.

Currently all configuration values can be determined automatically,
based on the configured phy-mode (which is mandatory for the stmmac
driver). If required the tx-delay and the mux clock (so it supports
the MPLL2 clock as well) can be made configurable in the future.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Tested-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c    | 327 +++++++++++++++++++++
 2 files changed, 328 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 44b630c..f77edb9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -9,7 +9,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 obj-$(CONFIG_STMMAC_PLATFORM)	+= stmmac-platform.o
 obj-$(CONFIG_DWMAC_IPQ806X)	+= dwmac-ipq806x.o
 obj-$(CONFIG_DWMAC_LPC18XX)	+= dwmac-lpc18xx.o
-obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o
+obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o dwmac-meson8b.o
 obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
new file mode 100644
index 0000000..0f185e4
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -0,0 +1,327 @@
+/*
+ * Amlogic Meson S805/S905 DWMAC glue layer
+ *
+ * Copyright (C) 20016 Martin Blumenstingl <martin.blumenstingl at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/clk-provider.h>
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_net.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+#define PRG_ETH0			0x0
+
+#define PRG_ETH0_RGMII_MODE		BIT(0)
+
+/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
+#define PRG_ETH0_CLK_M250_SEL_SHIFT	4
+#define PRG_ETH0_CLK_M250_SEL_MASK	GENMASK(4, 4)
+
+#define PRG_ETH0_TXDLY_SHIFT		5
+#define PRG_ETH0_TXDLY_MASK		GENMASK(6, 5)
+#define PRG_ETH0_TXDLY_OFF		(0x0 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_QUARTER		(0x1 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_HALF		(0x2 << PRG_ETH0_TXDLY_SHIFT)
+#define PRG_ETH0_TXDLY_THREE_QUARTERS	(0x3 << PRG_ETH0_TXDLY_SHIFT)
+
+/* divider for the result of m250_sel */
+#define PRG_ETH0_CLK_M250_DIV_SHIFT	7
+#define PRG_ETH0_CLK_M250_DIV_WIDTH	3
+
+/* divides the result of m25_sel by either 5 (bit unset) or 10 (bit set) */
+#define PRG_ETH0_CLK_M25_DIV_SHIFT	10
+#define PRG_ETH0_CLK_M25_DIV_WIDTH	1
+
+#define PRG_ETH0_INVERTED_RMII_CLK	BIT(11)
+#define PRG_ETH0_TX_AND_PHY_REF_CLK	BIT(12)
+
+#define MUX_CLK_NUM_PARENTS		2
+
+struct meson8b_dwmac {
+	struct platform_device	*pdev;
+
+	void __iomem		*regs;
+
+	phy_interface_t		phy_mode;
+
+	struct clk_mux		m250_mux;
+	struct clk		*m250_mux_clk;
+	struct clk		*m250_mux_parent[MUX_CLK_NUM_PARENTS];
+
+	struct clk_divider	m250_div;
+	struct clk		*m250_div_clk;
+
+	struct clk_divider	m25_div;
+	struct clk		*m25_div_clk;
+};
+
+static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
+				    u32 mask, u32 value)
+{
+	u32 data;
+
+	data = readl(dwmac->regs + reg);
+	data &= ~mask;
+	data |= (value & mask);
+
+	writel(data, dwmac->regs + reg);
+}
+
+static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
+{
+	struct clk_init_data init;
+	int i, ret;
+	struct device *dev = &dwmac->pdev->dev;
+	char clk_name[32];
+	const char *clk_div_parents[1];
+	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+	static struct clk_div_table clk_25m_div_table[] = {
+		{ .val = 0, .div = 5 },
+		{ .val = 1, .div = 10 },
+		{ /* sentinel */ },
+	};
+
+	/* get the mux parents from DT */
+	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+		char name[16];
+
+		snprintf(name, sizeof(name), "clkin%d", i);
+		dwmac->m250_mux_parent[i] = devm_clk_get(dev, name);
+		if (IS_ERR(dwmac->m250_mux_parent[i])) {
+			ret = PTR_ERR(dwmac->m250_mux_parent[i]);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Missing clock %s\n", name);
+			return ret;
+		}
+
+		mux_parent_names[i] =
+			__clk_get_name(dwmac->m250_mux_parent[i]);
+	}
+
+	/* create the m250_mux */
+	snprintf(clk_name, sizeof(clk_name), "%s#m250_sel", dev_name(dev));
+	init.name = clk_name;
+	init.ops = &clk_mux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = mux_parent_names;
+	init.num_parents = MUX_CLK_NUM_PARENTS;
+
+	dwmac->m250_mux.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
+	dwmac->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
+	dwmac->m250_mux.flags = 0;
+	dwmac->m250_mux.table = NULL;
+	dwmac->m250_mux.hw.init = &init;
+
+	dwmac->m250_mux_clk = devm_clk_register(dev, &dwmac->m250_mux.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))
+		return PTR_ERR(dwmac->m250_mux_clk);
+
+	/* create the m250_div */
+	snprintf(clk_name, sizeof(clk_name), "%s#m250_div", dev_name(dev));
+	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(dwmac->m250_mux_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	dwmac->m250_div.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
+	dwmac->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
+	dwmac->m250_div.hw.init = &init;
+	dwmac->m250_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+
+	dwmac->m250_div_clk = devm_clk_register(dev, &dwmac->m250_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))
+		return PTR_ERR(dwmac->m250_div_clk);
+
+	/* create the m25_div */
+	snprintf(clk_name, sizeof(clk_name), "%s#m25_div", dev_name(dev));
+	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(dwmac->m250_div_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	dwmac->m25_div.reg = dwmac->regs + PRG_ETH0;
+	dwmac->m25_div.shift = PRG_ETH0_CLK_M25_DIV_SHIFT;
+	dwmac->m25_div.width = PRG_ETH0_CLK_M25_DIV_WIDTH;
+	dwmac->m25_div.table = clk_25m_div_table;
+	dwmac->m25_div.hw.init = &init;
+	dwmac->m25_div.flags = CLK_DIVIDER_ALLOW_ZERO;
+
+	dwmac->m25_div_clk = devm_clk_register(dev, &dwmac->m25_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))
+		return PTR_ERR(dwmac->m25_div_clk);
+
+	return 0;
+}
+
+static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
+{
+	int ret;
+	unsigned long clk_rate;
+
+	switch (dwmac->phy_mode) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		/* Generate a 25MHz clock for the PHY */
+		clk_rate = 25 * 1000 * 1000;
+
+		/* enable RGMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
+					PRG_ETH0_RGMII_MODE);
+
+		/* only relevant for RMII mode -> disable in RGMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+					PRG_ETH0_INVERTED_RMII_CLK, 0);
+
+		/* TX clock delay - all known boards use a 1/4 cycle delay */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+					PRG_ETH0_TXDLY_QUARTER);
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
+		/* Use the rate of the mux clock for the internal RMII PHY */
+		clk_rate = clk_get_rate(dwmac->m250_mux_clk);
+
+		/* disable RGMII mode -> enables RMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
+					0);
+
+		/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+					PRG_ETH0_INVERTED_RMII_CLK,
+					PRG_ETH0_INVERTED_RMII_CLK);
+
+		/* TX clock delay cannot be configured in RMII mode */
+		meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+					0);
+
+		break;
+
+	default:
+		dev_err(&dwmac->pdev->dev, "unsupported phy-mode %s\n",
+			phy_modes(dwmac->phy_mode));
+		return -EINVAL;
+	}
+
+	ret = clk_prepare_enable(dwmac->m25_div_clk);
+	if (ret) {
+		dev_err(&dwmac->pdev->dev, "failed to enable the PHY clock\n");
+		return ret;
+	}
+
+	ret = clk_set_rate(dwmac->m25_div_clk, clk_rate);
+	if (ret) {
+		clk_disable_unprepare(dwmac->m25_div_clk);
+
+		dev_err(&dwmac->pdev->dev, "failed to set PHY clock\n");
+		return ret;
+	}
+
+	/* enable TX_CLK and PHY_REF_CLK generator */
+	meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
+				PRG_ETH0_TX_AND_PHY_REF_CLK);
+
+	return 0;
+}
+
+static int meson8b_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct resource *res;
+	struct meson8b_dwmac *dwmac;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return PTR_ERR(plat_dat);
+
+	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+	if (!dwmac)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -ENODEV;
+
+	dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dwmac->regs))
+		return PTR_ERR(dwmac->regs);
+
+	dwmac->pdev = pdev;
+	dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
+	if (dwmac->phy_mode < 0) {
+		dev_err(&pdev->dev, "missing phy-mode property\n");
+		return -EINVAL;
+	}
+
+	ret = meson8b_init_clk(dwmac);
+	if (ret)
+		return ret;
+
+	ret = meson8b_init_prg_eth(dwmac);
+	if (ret)
+		return ret;
+
+	plat_dat->bsp_priv = dwmac;
+
+	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+}
+
+static int meson8b_dwmac_remove(struct platform_device *pdev)
+{
+	struct meson8b_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
+
+	clk_disable_unprepare(dwmac->m25_div_clk);
+
+	return stmmac_pltfr_remove(pdev);
+}
+
+static const struct of_device_id meson8b_dwmac_match[] = {
+	{ .compatible = "amlogic,meson8b-dwmac" },
+	{ .compatible = "amlogic,meson-gxbb-dwmac" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
+
+static struct platform_driver meson8b_dwmac_driver = {
+	.probe  = meson8b_dwmac_probe,
+	.remove = meson8b_dwmac_remove,
+	.driver = {
+		.name           = "meson8b-dwmac",
+		.pm		= &stmmac_pltfr_pm_ops,
+		.of_match_table = meson8b_dwmac_match,
+	},
+};
+module_platform_driver(meson8b_dwmac_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl at googlemail.com>");
+MODULE_DESCRIPTION("Amlogic Meson S805/S905 DWMAC glue layer");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:25:32 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:25:32 +0200
Subject: USB PHY documentation
In-Reply-To: <CAFBinCDuuw+J3BynPW+6Q3JvgvXcJi4+3ioSr6i43ONpm=DH9A@mail.gmail.com>
References: <CAFBinCASOLYOfsRC7+kVA8eZ+o1OsyqKEUDOUgfRBKuhsYnuYA@mail.gmail.com>
 <4cc6ec9ce62649c283fb633b26d5cffe@codethink.co.uk>
 <1472029412.2322.13.camel@baylibre.com>
 <CAFBinCCx4X_Lsd9NsFd-9aHL67EvCJDebdzc8zdSP9Hcw__BOA@mail.gmail.com>
 <CAO9vn2P8vPwFFpz-VN3WKV_BNhwXWW=NkjTEhoGvYShbrZMwsA@mail.gmail.com>
 <CAFBinCDuuw+J3BynPW+6Q3JvgvXcJi4+3ioSr6i43ONpm=DH9A@mail.gmail.com>
Message-ID: <CAFBinCDJttiVZLtCWDPFqMJTdcHs2MS1uZQy9pvOFHdgz2ko-g@mail.gmail.com>

On Sat, Aug 27, 2016 at 11:32 PM, Martin Blumenstingl
<martin.blumenstingl at googlemail.com> wrote:
> On Fri, Aug 26, 2016 at 12:55 PM, J?r?me Brunet <jbrunet at baylibre.com> wrote:
>> I did some test on the otg controller. I had to remove the reset in the PHY
>> because it was reseting both of them, so the reset intended for the 2nd PHY
>> was breaking the configuration of the 1st.
> I am getting the following error when 1) removing the reset and 2)
> booting the mainline kernel directly (without booting the stock
> Android kernel first):
> [    1.297507] dwc2 c9000000.usb-controller: dwc2_core_reset() HANG!
> AHB Idle GRSTCTL=0
> [    1.305116] dwc2 c9000000.usb-controller: Bad value for GSNPSID: 0x00000000
I added the reset back along with some code that ensures it only calls
the reset once.
That made the error go away on my board.

Additionally I forced the first USB controller to "host" mode (which
was also not working without the reset) due to the OTG problems you
have mentioned.
I did some basic tests with both USB controllers - everything looks good!
While doing that I found out that quite a lot bits in REG_ADP_BC are
readonly - one of them is REG_ADP_BC_DRV_VBUS so I removed the code
which set that bit.

Finally I added our signed-off-by's to the patches and improved the
patch subjects and descriptions.
You can find my updated tree here: [0] (or if you only care about the
USB patches: [1])

PS: I will only have limited access to my S905 device in the next two weeks.
Feel free to submit the patches once you think they are ready - having
USB (host) support in 4.9 would be awesome!


Regards,
Martin


[0] https://github.com/xdarklight/linux/commits/meson-gxbb-integration-4.8-20160827
[1] https://github.com/torvalds/linux/compare/0ff577bf040b312301920f8589fc9fcea84a86b8...6aebadf13dcfb631399e7717c5eec0e80d72c9a7


From martin.blumenstingl at googlemail.com  Sun Aug 28 09:29:39 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:29:39 +0200
Subject: [PATCH v3 3/4] ARM64: dts: meson-gxbb: Add Meson GXBB PWM
 Controller nodes
In-Reply-To: <1471880193-21879-4-git-send-email-narmstrong@baylibre.com>
References: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
 <1471880193-21879-4-git-send-email-narmstrong@baylibre.com>
Message-ID: <CAFBinCDBPgrHsDuPLV=4MTFLZn10DmXM8FR171W9g3SoZUJ9aw@mail.gmail.com>

On Mon, Aug 22, 2016 at 5:36 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> index e502c24..e3f4d36 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> @@ -153,6 +153,27 @@
>                                 status = "disabled";
>                         };
>
> +                       pwm_ab: pwm at 8550 {
> +                               compatible = "amlogic,meson-gxbb-pwm";
> +                               reg = <0x0 0x08550 0x0 0x10>;
> +                               #pwm-cells = <3>;
> +                               status = "disabled";
> +                       };
> +
> +                       pwm_cd: pwm at 8650 {
> +                               compatible = "amlogic,meson-gxbb-pwm";
> +                               reg = <0x0 0x08650 0x0 0x10>;
> +                               #pwm-cells = <3>;
> +                               status = "disabled";
> +                       };
> +
> +                       pwm_ef: pwm at 86c0 {
> +                               compatible = "amlogic,meson-gxbb-pwm";
> +                               reg = <0x0 0x086c0 0x0 0x10>;
> +                               #pwm-cells = <3>;
> +                               status = "disabled";
> +                       };
I have successfully tested pwm_e on my meson-gxbb-vega-s95-meta clone
(see [0] for the corresponding patches), thus:
Tested-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

[0] https://github.com/xdarklight/linux/tree/meson-gxbb-integration-4.8-20160828


From martin.blumenstingl at googlemail.com  Sun Aug 28 09:33:03 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:33:03 +0200
Subject: [PATCH v3 1/4] pwm: Add support for Meson PWM Controller
In-Reply-To: <1471880193-21879-2-git-send-email-narmstrong@baylibre.com>
References: <1471880193-21879-1-git-send-email-narmstrong@baylibre.com>
 <1471880193-21879-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CAFBinCA3PoR_=+f8aU-Trg8uKWWXkkBOtrQUaXbdsb8E-fdM0g@mail.gmail.com>

On Mon, Aug 22, 2016 at 5:36 PM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> Add support for the PWM controller found in the Amlogic SoCs.
> This driver supports the Meson8b and GXBB SoCs.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
I could enable the AP6330 SDIO wifi module with this on my
meson-gxbb-vega-s95-meta clone, which uses pwm_e to generate the LPO
clock for the wifi module (see [0] for the corresponding patches).
So thank you Neil, and:
Tested-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>


[0] https://github.com/xdarklight/linux/tree/meson-gxbb-integration-4.8-20160828


From martin.blumenstingl at googlemail.com  Sun Aug 28 09:47:23 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:47:23 +0200
Subject: [PATCH 0/2] add support for the SDIO pins on GXBB
Message-ID: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>

This series adds the pins for the SDIO controller (sd_emmc_a) found on
Meson GXBB SoCs.


Martin Blumenstingl (2):
  pinctrl: meson-gxbb: add the pins for the SDIO/sd_emmc_a controller
  ARM64: dts: meson-gxbb: add the SDIO pins

 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 12 ++++++++++++
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c  | 19 +++++++++++++++++++
 2 files changed, 31 insertions(+)

-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:47:24 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:47:24 +0200
Subject: [PATCH 1/2] pinctrl: meson-gxbb: add the pins for the SDIO/sd_emmc_a
 controller
In-Reply-To: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>
References: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828164725.19429-2-martin.blumenstingl@googlemail.com>

sd_emmc_a is used a controller for the SDIO modules. This adds the pin
configuration for the SDIO controller.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index 77da6dd..fb479b8 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -163,6 +163,13 @@ static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
 static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
 static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
 
+static const unsigned int sdio_d0_pins[] = { PIN(GPIOX_0, EE_OFF) };
+static const unsigned int sdio_d1_pins[] = { PIN(GPIOX_1, EE_OFF) };
+static const unsigned int sdio_d2_pins[] = { PIN(GPIOX_2, EE_OFF) };
+static const unsigned int sdio_d3_pins[] = { PIN(GPIOX_3, EE_OFF) };
+static const unsigned int sdio_cmd_pins[] = { PIN(GPIOX_4, EE_OFF) };
+static const unsigned int sdio_clk_pins[] = { PIN(GPIOX_5, EE_OFF) };
+
 static const unsigned int uart_tx_a_pins[]	= { PIN(GPIOX_12, EE_OFF) };
 static const unsigned int uart_rx_a_pins[]	= { PIN(GPIOX_13, EE_OFF) };
 static const unsigned int uart_cts_a_pins[]	= { PIN(GPIOX_14, EE_OFF) };
@@ -370,6 +377,12 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
 
 	/* Bank X */
+	GROUP(sdio_d0,		8,	5),
+	GROUP(sdio_d1,		8,	4),
+	GROUP(sdio_d2,		8,	3),
+	GROUP(sdio_d3,		8,	2),
+	GROUP(sdio_cmd,		8,	1),
+	GROUP(sdio_clk,		8,	0),
 	GROUP(uart_tx_a,	4,	13),
 	GROUP(uart_rx_a,	4,	12),
 	GROUP(uart_cts_a,	4,	11),
@@ -507,6 +520,11 @@ static const char * const sdcard_groups[] = {
 	"sdcard_cmd", "sdcard_clk",
 };
 
+static const char * const sdio_groups[] = {
+	"sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3",
+	"sdio_cmd", "sdio_clk",
+};
+
 static const char * const uart_a_groups[] = {
 	"uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a",
 };
@@ -600,6 +618,7 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
 	FUNCTION(sdcard),
+	FUNCTION(sdio),
 	FUNCTION(uart_a),
 	FUNCTION(uart_b),
 	FUNCTION(uart_c),
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:47:25 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:47:25 +0200
Subject: [PATCH 2/2] ARM64: dts: meson-gxbb: add the SDIO pins
In-Reply-To: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>
References: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828164725.19429-3-martin.blumenstingl@googlemail.com>

This can be passed to the sd_emmc_a controller to which the SDIO module
is connected (when available).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index e2dae1a..6864523 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -355,6 +355,18 @@
 					};
 				};
 
+				sdio_pins: sdio {
+					mux {
+						groups = "sdio_d0",
+						       "sdio_d1",
+						       "sdio_d2",
+						       "sdio_d3",
+						       "sdio_cmd",
+						       "sdio_clk";
+						function = "sdio";
+					};
+				};
+
 				uart_a_pins: uart_a {
 					mux {
 						groups = "uart_tx_a",
-- 
2.9.3



From martin.blumenstingl at googlemail.com  Sun Aug 28 09:58:29 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sun, 28 Aug 2016 18:58:29 +0200
Subject: [RFC / POC] mmc: meson-gxbb: experimental SDIO support
Message-ID: <20160828165829.21882-1-martin.blumenstingl@googlemail.com>

This adds experimental SDIO support to the meson mmc controller.
The patch consists of four main changes:
- remove meson_mmc_check_cmd to allow the SDIO commands
- implement meson_mcc_enable_sdio_irq - this requires adding the
  irq_mask field to our priv struct so we always configure the
  correct IRQs.
- get rid of the magic value IRQ_EN_MASK and replace it with an OR
  of the corresponding bit/masks (when initializing host->irq_mask)
- it adds a small bugfix in meson_mmc_probe when probing failed (in
  my case: probing had to be deferred because the mmc-initseq was not
  ready yet) which disabled and unprepared a clock which was not
  enabled

I am sending this patch because I only have limited access to my board
in the next 2 weeks. Please see this as "proof of concept" and not a
finished patch. If someone wants to work in this: feel free - otherwise
I'll do it when I have full access to my board again.

An additional patch which enables wifi on the Tronsmart S95 Vega Meta
can be found here:
https://github.com/xdarklight/linux/tree/meson-gxbb-integration-4.8-20160828

Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
---
 drivers/mmc/host/meson-gxbb.c | 81 ++++++++++++++++++++++++-------------------
 1 file changed, 45 insertions(+), 36 deletions(-)

diff --git a/drivers/mmc/host/meson-gxbb.c b/drivers/mmc/host/meson-gxbb.c
index 10eac41..77a7a1f 100644
--- a/drivers/mmc/host/meson-gxbb.c
+++ b/drivers/mmc/host/meson-gxbb.c
@@ -123,7 +123,6 @@
 #define   STATUS_BUSY BIT(31)
 
 #define SD_EMMC_IRQ_EN 0x4c
-#define   IRQ_EN_MASK 0x3fff
 #define   IRQ_RXD_ERR_SHIFT 0
 #define   IRQ_RXD_ERR_MASK 0xff
 #define   IRQ_TXD_ERR BIT(8)
@@ -181,6 +180,8 @@ struct meson_host {
 	unsigned long clk_rate;
 	unsigned long clk_src_rate;
 	unsigned short clk_src_div;
+
+	u32 irq_mask;
 };
 
 #define reg_read(host, offset) readl(host->regs + offset)
@@ -457,28 +458,6 @@ static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
 	return 0;
 }
 
-static int meson_mmc_cmd_invalid(struct mmc_host *mmc, struct mmc_command *cmd)
-{
-	cmd->error = -EINVAL;
-	meson_mmc_request_done(mmc, cmd->mrq);
-
-	return -EINVAL;
-}
-
-static int meson_mmc_check_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
-{
-	int ret = 0;
-
-	/* FIXME: needs update for SDIO support */
-	if (cmd->opcode == SD_IO_SEND_OP_COND
-	    || cmd->opcode == SD_IO_RW_DIRECT
-	    || cmd->opcode == SD_IO_RW_EXTENDED) {
-		ret = meson_mmc_cmd_invalid(mmc, cmd);
-	}
-
-	return ret;
-}
-
 static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
 {
 	struct meson_host *host = mmc_priv(mmc);
@@ -588,14 +567,11 @@ static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 	/* clear, ack, enable all interrupts */
 	reg_write(host, SD_EMMC_IRQ_EN, 0);
-	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
-	reg_write(host, SD_EMMC_IRQ_EN, IRQ_EN_MASK);
+	reg_write(host, SD_EMMC_STATUS, host->irq_mask);
+	reg_write(host, SD_EMMC_IRQ_EN, host->irq_mask);
 
 	host->mrq = mrq;
 
-	if (meson_mmc_check_cmd(mmc, mrq->cmd))
-		return;
-
 	if (mrq->sbc)
 		meson_mmc_start_cmd(mmc, mrq->sbc);
 	else
@@ -629,6 +605,7 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
 	struct mmc_request *mrq = host->mrq;
 	struct mmc_command *cmd = host->cmd;
 	u32 irq_en, status, raw_status;
+	bool sdio_irq = false;
 	irqreturn_t ret = IRQ_HANDLED;
 
 	if (WARN_ON(!host))
@@ -675,8 +652,9 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
 		dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
 		cmd->error = -ETIMEDOUT;
 	}
+
 	if (status & IRQ_SDIO)
-		dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
+		sdio_irq = true;
 
 	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
 		ret = IRQ_WAKE_THREAD;
@@ -698,6 +676,9 @@ out:
 	/* ack all (enabled) interrupts */
 	reg_write(host, SD_EMMC_STATUS, status);
 
+	if (sdio_irq)
+		mmc_signal_sdio_irq(host->mmc);
+
 	if (ret == IRQ_HANDLED) {
 		meson_mmc_read_resp(host->mmc, cmd);
 		meson_mmc_request_done(host->mmc, cmd->mrq);
@@ -757,10 +738,34 @@ static int meson_mmc_get_cd(struct mmc_host *mmc)
 	return status;
 }
 
+static void meson_mcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	unsigned long flags;
+	u32 irqen;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	irqen = reg_read(host, SD_EMMC_IRQ_EN);
+
+	if (enable) {
+		irqen |= IRQ_SDIO;
+		host->irq_mask |= IRQ_SDIO;
+	} else {
+		irqen &= ~IRQ_SDIO;
+		host->irq_mask &= ~IRQ_SDIO;
+	}
+
+	reg_write(host, SD_EMMC_IRQ_EN, irqen);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
 static struct mmc_host_ops meson_mmc_ops = {
-	.request	= meson_mmc_request,
-	.set_ios	= meson_mmc_set_ios,
-	.get_cd         = meson_mmc_get_cd,
+	.request		= meson_mmc_request,
+	.set_ios		= meson_mmc_set_ios,
+	.get_cd         	= meson_mmc_get_cd,
+	.enable_sdio_irq	= meson_mcc_enable_sdio_irq,
 };
 
 static int meson_mmc_probe(struct platform_device *pdev)
@@ -847,26 +852,30 @@ static int meson_mmc_probe(struct platform_device *pdev)
 
 	clk_prepare_enable(host->core_clk);
 
+	host->irq_mask = IRQ_RXD_ERR_MASK | IRQ_TXD_ERR | IRQ_DESC_ERR |
+			 IRQ_RESP_ERR | IRQ_RESP_TIMEOUT | IRQ_DESC_TIMEOUT |
+			 IRQ_END_OF_CHAIN;
+
 	ret = meson_mmc_clk_init(host);
 	if (ret)
-		goto free_host;
+		goto free_host_clk_prepared;
 
 	/* Stop execution */
 	reg_write(host, SD_EMMC_START, 0);
 
 	/* clear, ack, enable all interrupts */
 	reg_write(host, SD_EMMC_IRQ_EN, 0);
-	reg_write(host, SD_EMMC_STATUS, IRQ_EN_MASK);
+	reg_write(host, SD_EMMC_STATUS, host->irq_mask);
 
 	mmc->ops = &meson_mmc_ops;
 	mmc_add_host(mmc);
 
 	return 0;
 
+free_host_clk_prepared:
+	clk_disable_unprepare(host->core_clk);
 free_host:
 	dev_dbg(host->dev, "Failed to probe: ret=%d\n", ret);
-	if (host->core_clk)
-		clk_disable_unprepare(host->core_clk);
 	mmc_free_host(mmc);
 	return ret;
 }
-- 
2.9.3



From ccc94453 at vip.cybercity.dk  Sun Aug 28 12:13:53 2016
From: ccc94453 at vip.cybercity.dk (Rask Ingemann Lambertsen)
Date: Sun, 28 Aug 2016 21:13:53 +0200
Subject: [PATCH 2/2] ARM64: dts: meson-gxbb: add the SDIO pins
In-Reply-To: <20160828164725.19429-3-martin.blumenstingl@googlemail.com>
References: <20160828164725.19429-1-martin.blumenstingl@googlemail.com>
 <20160828164725.19429-3-martin.blumenstingl@googlemail.com>
Message-ID: <20160828191353.wpwbqsxdg5pdmese@vip.cybercity.dk>

On Sun, Aug 28, 2016 at 06:47:25PM +0200, Martin Blumenstingl wrote:
>  				uart_a_pins: uart_a {
>  					mux {
>  						groups = "uart_tx_a",

You shouldn't use underscores in node names. Use hyphens instead, perhaps.
https://www.mail-archive.com/linux-kernel%40vger.kernel.org/msg1122967.html
https://www.mail-archive.com/linux-kernel%40vger.kernel.org/msg1145633.html

-- 
Rask Ingemann Lambertsen


From davem at davemloft.net  Sun Aug 28 20:40:08 2016
From: davem at davemloft.net (David Miller)
Date: Sun, 28 Aug 2016 23:40:08 -0400 (EDT)
Subject: [PATCH v3 0/5] meson: Meson8b and GXBB DWMAC glue driver
In-Reply-To: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
Message-ID: <20160828.234008.445367966910278179.davem@davemloft.net>

From: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Date: Sun, 28 Aug 2016 18:16:32 +0200

> This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
> Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
> the register layout is completely different.
> Thus I introduced a separate driver.
> 
> Changes since v2:
> - fixed unloading the glue driver when built as module. This pulls in a
>   patch from Joachim Eastwood (thanks) to get our private data structure
>   (bsp_priv).

This doesn't apply cleanly at all to the net-next tree, so I have
no idea where you expect these changes to be applied.


From narmstrong at baylibre.com  Mon Aug 29 00:56:08 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 29 Aug 2016 09:56:08 +0200
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
Message-ID: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>

The new Amlogic GLX SoCs (S905X and S905D) are part of the Meson GX family so
they share some basic characteritics that can be described in a common GX
dtsi file used by the Meson GXBB and Meson GXL dtsi.

This patchset introduces the common dtsi and switches the GLX and GXBB to use
the common dtsi, the GXBB dtsi is reformated to handle this situation.

This patchset depends on Carlo Caione "ARM64: dts: amlogic: Add basic support for Amlogic S905X" [1]

[1] http://lkml.kernel.org/r/1472382113-10754-1-git-send-email-carlo at caione.org

Neil Armstrong (3):
  ARM64: dts: amlogic: Add Meson GX Family common dtsi
  ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
  ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi

 arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi | 181 +++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi      | 320 +++++++----------------
 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi       | 133 +---------
 3 files changed, 281 insertions(+), 353 deletions(-)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi

-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 29 00:56:10 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 29 Aug 2016 09:56:10 +0200
Subject: [RFC PATCH 2/3] ARM64: dts: amlogic: Switch Meson GXL dtsi to use
 common GX dtsi
In-Reply-To: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1472457371-1305-3-git-send-email-narmstrong@baylibre.com>

The Amlogic Meson GXL should use the common GX dtsi as base.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 133 +----------------------------
 1 file changed, 1 insertion(+), 132 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index 2aa4555..16891e0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -41,139 +41,8 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "meson-gx-common.dtsi"
 
 / {
 	compatible = "amlogic,meson-gxl";
-	interrupt-parent = <&gic>;
-	#address-cells = <2>;
-	#size-cells = <2>;
-
-	cpus {
-		#address-cells = <0x2>;
-		#size-cells = <0x0>;
-
-		cpu0: cpu at 0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-		};
-
-		cpu1: cpu at 1 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-		};
-
-		cpu2: cpu at 2 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-		};
-
-		cpu3: cpu at 3 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-		};
-	};
-
-	arm-pmu {
-		compatible = "arm,cortex-a53-pmu";
-		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
-	};
-
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
-	timer {
-		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 14
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 11
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 10
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
-	};
-
-	xtal: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "xtal";
-		#clock-cells = <0>;
-	};
-
-	soc {
-		compatible = "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
-		cbus: cbus at c1100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc1100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
-
-			uart_A: serial at 84c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x084c0 0x0 0x14>;
-				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-		};
-
-		gic: interrupt-controller at c4301000 {
-			compatible = "arm,gic-400";
-			reg = <0x0 0xc4301000 0 0x1000>,
-			      <0x0 0xc4302000 0 0x2000>,
-			      <0x0 0xc4304000 0 0x2000>,
-			      <0x0 0xc4306000 0 0x2000>;
-			interrupt-controller;
-			interrupts = <GIC_PPI 9
-				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
-			#interrupt-cells = <3>;
-			#address-cells = <0>;
-		};
-
-		aobus: aobus at c8100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc8100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
-
-			uart_AO: serial at 4c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x004c0 0x0 0x14>;
-				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-		};
-
-		apb: apb at d0000000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xd0000000 0x0 0x200000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
-		};
-	};
 };
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 29 00:56:11 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 29 Aug 2016 09:56:11 +0200
Subject: [RFC PATCH 3/3] ARM64: dts: amlogic: Switch Meson GXBB dtsi to use
 common GX dtsi
In-Reply-To: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1472457371-1305-4-git-send-email-narmstrong@baylibre.com>

The Amlogic Meson GXBB should use the common GX dtsi as base.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 320 +++++++++-------------------
 1 file changed, 99 insertions(+), 221 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 2ea7bbd..e1e22fd 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -40,9 +40,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "meson-gx-common.dtsi"
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
 #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 #include <dt-bindings/clock/gxbb-clkc.h>
@@ -51,185 +49,8 @@
 
 / {
 	compatible = "amlogic,meson-gxbb";
-	interrupt-parent = <&gic>;
-	#address-cells = <2>;
-	#size-cells = <2>;
-
-	cpus {
-		#address-cells = <0x2>;
-		#size-cells = <0x0>;
-
-		cpu0: cpu at 0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-		};
-
-		cpu1: cpu at 1 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-		};
-
-		cpu2: cpu at 2 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-		};
-
-		cpu3: cpu at 3 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-		};
-	};
-
-	arm-pmu {
-		compatible = "arm,cortex-a53-pmu";
-		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
-	};
-
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
-	timer {
-		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 14
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 11
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 10
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
-	};
-
-	xtal: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "xtal";
-		#clock-cells = <0>;
-	};
 
 	soc {
-		compatible = "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
-		cbus: cbus at c1100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc1100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
-
-			reset: reset-controller at 4404 {
-				compatible = "amlogic,meson-gxbb-reset";
-				reg = <0x0 0x04404 0x0 0x20>;
-				#reset-cells = <1>;
-			};
-
-			uart_A: serial at 84c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x84c0 0x0 0x14>;
-				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			uart_B: serial at 84dc {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x84dc 0x0 0x14>;
-				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			uart_C: serial at 8700 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x8700 0x0 0x14>;
-				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			watchdog at 98d0 {
-				compatible = "amlogic,meson-gxbb-wdt";
-				reg = <0x0 0x098d0 0x0 0x10>;
-				clocks = <&xtal>;
-			};
-		};
-
-		gic: interrupt-controller at c4301000 {
-			compatible = "arm,gic-400";
-			reg = <0x0 0xc4301000 0 0x1000>,
-			      <0x0 0xc4302000 0 0x2000>,
-			      <0x0 0xc4304000 0 0x2000>,
-			      <0x0 0xc4306000 0 0x2000>;
-			interrupt-controller;
-			interrupts = <GIC_PPI 9
-				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
-			#interrupt-cells = <3>;
-			#address-cells = <0>;
-		};
-
-		aobus: aobus at c8100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc8100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
-
-			pinctrl_aobus: pinctrl at 14 {
-				compatible = "amlogic,meson-gxbb-aobus-pinctrl";
-				#address-cells = <2>;
-				#size-cells = <2>;
-				ranges;
-
-				gpio_ao: bank at 14 {
-					reg = <0x0 0x00014 0x0 0x8>,
-					      <0x0 0x0002c 0x0 0x4>,
-					      <0x0 0x00024 0x0 0x8>;
-					reg-names = "mux", "pull", "gpio";
-					gpio-controller;
-					#gpio-cells = <2>;
-				};
-
-				uart_ao_a_pins: uart_ao_a {
-					mux {
-						groups = "uart_tx_ao_a", "uart_rx_ao_a";
-						function = "uart_ao";
-					};
-				};
-			};
-
-			clkc_AO: clock-controller at 040 {
-				compatible = "amlogic,gxbb-aoclkc";
-				reg = <0x0 0x00040 0x0 0x4>;
-				#clock-cells = <1>;
-				#reset-cells = <1>;
-			};
-
-			uart_AO: serial at 4c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x004c0 0x0 0x14>;
-				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-		};
-
 		periphs: periphs at c8834000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xc8834000 0x0 0x2000>;
@@ -340,47 +161,6 @@
 			};
 		};
 
-		apb: apb at d0000000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xd0000000 0x0 0x200000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
-
-			sd_emmc_a: mmc at 70000 {
-				compatible = "amlogic,meson-gxbb-mmc";
-				reg = <0x0 0x70000 0x0 0x2000>;
-				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_SD_EMMC_A>,
-					 <&xtal>,
-					 <&clkc CLKID_FCLK_DIV2>;
-				clock-names = "core", "clkin0", "clkin1";
-				status = "disabled";
-			};
-
-			sd_emmc_b: mmc at 72000 {
-				compatible = "amlogic,meson-gxbb-mmc";
-				reg = <0x0 0x72000 0x0 0x2000>;
-				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_SD_EMMC_B>,
-					 <&xtal>,
-					 <&clkc CLKID_FCLK_DIV2>;
-				clock-names = "core", "clkin0", "clkin1";
-				status = "disabled";
-			};
-
-			sd_emmc_c: mmc at 74000 {
-				compatible = "amlogic,meson-gxbb-mmc";
-				reg = <0x0 0x74000 0x0 0x2000>;
-				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_SD_EMMC_C>,
-					 <&xtal>,
-					 <&clkc CLKID_FCLK_DIV2>;
-				clock-names = "core", "clkin0", "clkin1";
-				status = "disabled";
-			};
-		};
-
 		ethmac: ethernet at c9410000 {
 			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
 			reg = <0x0 0xc9410000 0x0 0x10000
@@ -394,3 +174,101 @@
 		};
 	};
 };
+
+&cbus {
+	reset: reset-controller at 4404 {
+		compatible = "amlogic,meson-gxbb-reset";
+		reg = <0x0 0x04404 0x0 0x20>;
+		#reset-cells = <1>;
+	};
+
+	uart_B: serial at 84dc {
+		compatible = "amlogic,meson-uart";
+		reg = <0x0 0x84dc 0x0 0x14>;
+		interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&xtal>;
+		status = "disabled";
+	};
+
+	uart_C: serial at 8700 {
+		compatible = "amlogic,meson-uart";
+		reg = <0x0 0x8700 0x0 0x14>;
+		interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&xtal>;
+		status = "disabled";
+	};
+
+	watchdog at 98d0 {
+		compatible = "amlogic,meson-gxbb-wdt";
+		reg = <0x0 0x098d0 0x0 0x10>;
+		clocks = <&xtal>;
+	};
+};
+
+&aobus {
+	pinctrl_aobus: pinctrl at 14 {
+		compatible = "amlogic,meson-gxbb-aobus-pinctrl";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio_ao: bank at 14 {
+			reg = <0x0 0x00014 0x0 0x8>,
+			      <0x0 0x0002c 0x0 0x4>,
+			      <0x0 0x00024 0x0 0x8>;
+			reg-names = "mux", "pull", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		uart_ao_a_pins: uart_ao_a {
+			mux {
+				groups = "uart_tx_ao_a", "uart_rx_ao_a";
+				function = "uart_ao";
+			};
+		};
+	};
+
+	clkc_AO: clock-controller at 040 {
+		compatible = "amlogic,gxbb-aoclkc";
+		reg = <0x0 0x00040 0x0 0x4>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+};
+
+&apb {
+	sd_emmc_a: mmc at 70000 {
+		compatible = "amlogic,meson-gxbb-mmc";
+		reg = <0x0 0x70000 0x0 0x2000>;
+		interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_SD_EMMC_A>,
+			 <&xtal>,
+			 <&clkc CLKID_FCLK_DIV2>;
+		clock-names = "core", "clkin0", "clkin1";
+		status = "disabled";
+	};
+
+	sd_emmc_b: mmc at 72000 {
+		compatible = "amlogic,meson-gxbb-mmc";
+		reg = <0x0 0x72000 0x0 0x2000>;
+		interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_SD_EMMC_B>,
+			 <&xtal>,
+			 <&clkc CLKID_FCLK_DIV2>;
+		clock-names = "core", "clkin0", "clkin1";
+		status = "disabled";
+	};
+
+	sd_emmc_c: mmc at 74000 {
+		compatible = "amlogic,meson-gxbb-mmc";
+		reg = <0x0 0x74000 0x0 0x2000>;
+		interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_SD_EMMC_C>,
+			 <&xtal>,
+			 <&clkc CLKID_FCLK_DIV2>;
+		clock-names = "core", "clkin0", "clkin1";
+		status = "disabled";
+	};
+};
+
-- 
1.9.1



From narmstrong at baylibre.com  Mon Aug 29 00:56:09 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 29 Aug 2016 09:56:09 +0200
Subject: [RFC PATCH 1/3] ARM64: dts: amlogic: Add Meson GX Family common dtsi
In-Reply-To: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1472457371-1305-2-git-send-email-narmstrong@baylibre.com>

Introduce a common DTSI for Amlogic Meson GX Family including the
GXBB SoC and the GLX SoCs (S905X and S905D).

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi | 181 +++++++++++++++++++++++
 1 file changed, 181 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi

diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi
new file mode 100644
index 0000000..fb393e9
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-common.dtsi
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library 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 library 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cbus: cbus at c1100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc1100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
+
+			uart_A: serial at 84c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x084c0 0x0 0x14>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+		};
+
+		gic: interrupt-controller at c4301000 {
+			compatible = "arm,gic-400";
+			reg = <0x0 0xc4301000 0 0x1000>,
+			      <0x0 0xc4302000 0 0x2000>,
+			      <0x0 0xc4304000 0 0x2000>,
+			      <0x0 0xc4306000 0 0x2000>;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+		};
+
+		aobus: aobus at c8100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
+
+			uart_AO: serial at 4c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004c0 0x0 0x14>;
+				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+		};
+
+		apb: apb at d0000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xd0000000 0x0 0x200000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+		};
+	};
+};
-- 
1.9.1



From carlo at caione.org  Mon Aug 29 01:01:46 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 29 Aug 2016 10:01:46 +0200
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
In-Reply-To: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>

On Mon, Aug 29, 2016 at 9:56 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> The new Amlogic GLX SoCs (S905X and S905D) are part of the Meson GX family so
> they share some basic characteritics that can be described in a common GX
> dtsi file used by the Meson GXBB and Meson GXL dtsi.
>
> This patchset introduces the common dtsi and switches the GLX and GXBB to use
> the common dtsi, the GXBB dtsi is reformated to handle this situation.
>
> This patchset depends on Carlo Caione "ARM64: dts: amlogic: Add basic support for Amlogic S905X" [1]
>
> [1] http://lkml.kernel.org/r/1472382113-10754-1-git-send-email-carlo at caione.org
>
> Neil Armstrong (3):
>   ARM64: dts: amlogic: Add Meson GX Family common dtsi
>   ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
>   ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi

FWIW
Acked-by: Carlo Caione <carlo at endlessm.com>

-- 
Carlo Caione


From arnd at arndb.de  Mon Aug 29 06:31:12 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 29 Aug 2016 15:31:12 +0200
Subject: [PATCH v2 1/4] net: dt-bindings: Document the new Meson8b and
 GXBB DWMAC bindings
In-Reply-To: <CAFBinCDnHGf=wgvm9KzYQsf=kCrOUeO3bnEwdGy_OK-wgWkDug@mail.gmail.com>
References: <20160815164100.27766-1-martin.blumenstingl@googlemail.com>
 <4041259.IszN4229Cj@wuerfel>
 <CAFBinCDnHGf=wgvm9KzYQsf=kCrOUeO3bnEwdGy_OK-wgWkDug@mail.gmail.com>
Message-ID: <201608291531.12188.arnd@arndb.de>

On Sunday 28 August 2016, Martin Blumenstingl wrote:
> On Mon, Aug 22, 2016 at 5:25 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> > It really depends on the kind of SoC. Some may have a suboptimal
> > binding, on some others there may be a distinct register area that
> > just contains a few additional registers for the dwmac.
> the dwmac PHY configuration registers (2x32bit) on the GXBB SoC are
> part of the "periphs" region/module. This is already defined as
> "simple-bus" in meson-gxbb.dtsi, see [0]
> On Meson8b this is slightly different: there is no specific "periphs"
> region - there the dwmac PHY configuration registers are directly
> located in the cbus region at a slightly different offset than on the
> GXBB SoCs.
> 
> In the future we might need a third memory region because the latest
> reference kernel contains some more PHY configuration registers on
> newer SoCs (GXL = S905X).
> 
> Please let me know if you're OK with the dts definition in it's
> current state - or let me know how you would like to change it.
> 
> PS: I will re-send the patches in a v3 in a few minutes because that
> fixes a bug during module unload.

I don't really see a good way to describe this hardware then. If it
was only the first case, I'd suggest marking the periphs bus node
as "compatible="simple-bus","syscon";" so you could have a
reference to it, but that doesn't seem to work well in the second
case, unless you can a separate DT node just for the PHY config
registers there.

With the third case, is there any logic at all behind the
register map?

Maybe someone else has a better idea for how to describe this.
In general, we try to avoid overlapping "reg" properties, but I
even see that the "periphs" node  on gxbb has a "reg" property
(is this intentional) that overlaps with the registers in its
ranges, so adding another one won't make this worse than it
already is.

	Arnd


From khilman at baylibre.com  Mon Aug 29 10:37:37 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 29 Aug 2016 12:37:37 -0500
Subject: [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add GXBB AO Clock and
 Reset node
In-Reply-To: <147208015014.66208.14165603610884470316@resonance> (Michael
 Turquette's message of "Wed, 24 Aug 2016 16:09:10 -0700")
References: <1471514928-3341-1-git-send-email-narmstrong@baylibre.com>
 <1471514928-3341-4-git-send-email-narmstrong@baylibre.com>
 <7hk2fc76xx.fsf@baylibre.com>
 <147208015014.66208.14165603610884470316@resonance>
Message-ID: <m260qjjx26.fsf@baylibre.com>

Michael Turquette <mturquette at baylibre.com> writes:

> Quoting Kevin Hilman (2016-08-19 15:03:06)
>> Neil Armstrong <narmstrong at baylibre.com> writes:
>> 
>> > Add the AO clock controller node for the AmLogic GXBB SoC.
>> >
>> > Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> > ---
>> 
>> Applying this to the amlogic tree, but will need to wait a cycle due to
>> include dependencies on the bindings, which are going through the clock
>> tree.
>
> FYI, for picked patches, Stephen and I create a stable branch for each
> platform. You can pull this into your tree if you want, just let us know
> so we'll be sure not to rebase:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-meson-gxbb-ao
>

OK, I'll be using clk-meson-gxb and clk-meson-gxbb-ao.

Thanks,

Kevin


From khilman at baylibre.com  Mon Aug 29 10:46:55 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 29 Aug 2016 12:46:55 -0500
Subject: [PATCH v2] ARM64: dts: amlogic: Add basic support for Amlogic
 S905X
In-Reply-To: <1472382113-10754-1-git-send-email-carlo@caione.org> (Carlo
 Caione's message of "Sun, 28 Aug 2016 13:01:53 +0200")
References: <1472382113-10754-1-git-send-email-carlo@caione.org>
Message-ID: <m2y43fii28.fsf@baylibre.com>

Carlo Caione <carlo at caione.org> writes:

> From: Carlo Caione <carlo at endlessm.com>
>
> This patch introduces the basic support for the Amlogic S905X (Meson
> GXL) and for the Amlogic evaluation board P212.
> No documentation has been released yet for this SoC, so for now only the
> bare minimum has been added in the DT.
>
> Acked-by: Rob Herring <robh at kernel.org>
> Reviewed-by: Andreas F?rber <afaerber at suse.de>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>
> Hey Kevin,
> Can you take this one?
>
> Changelog:
> v2:
>   - Added acked-by and reviewed-by
>
> ---
>  Documentation/devicetree/bindings/arm/amlogic.txt |   5 +
>  arch/arm64/boot/dts/amlogic/Makefile              |   1 +
>  arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts    |  70 +++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxl.dtsi        | 179 ++++++++++++++++++++++

It seems to me that meson-gxl.dtsi is almost identicial to
meson-gxbb.dtsi.  I think we should create another .dtsi for all the
common parts.  Something like meson-gx-common.dtsi, which is included
by meson-gxbb.dtsi and meson-gxl.dtsi

Also, the GXL family has both the S905x and S905D SoCs, so we may need
meson-gxl-s905x.dtsi and meson-gxl-s905d.dtsi but I'm not sure of the
full set of differences between those, so we can save that for later.

But, I do think the board files should probably have the SoC name.  So
they would look something like: meson-gxl-s905x-p212.dts (which you
have) and meson-gxl-s905d-p230.dts (which I have.)

Kevin


From khilman at baylibre.com  Mon Aug 29 10:50:18 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 29 Aug 2016 12:50:18 -0500
Subject: [PATCH v2] ARM64: dts: amlogic: Add basic support for Amlogic
 S905X
In-Reply-To: <m2y43fii28.fsf@baylibre.com>
References: <1472382113-10754-1-git-send-email-carlo@caione.org>
 <m2y43fii28.fsf@baylibre.com>
Message-ID: <CAOi56cW3rRVbLM9L=aCMQSsYvuXQBOKdEY4LqN0NBpbm3Lzz+g@mail.gmail.com>

On Mon, Aug 29, 2016 at 12:46 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Carlo Caione <carlo at caione.org> writes:
>
>> From: Carlo Caione <carlo at endlessm.com>
>>
>> This patch introduces the basic support for the Amlogic S905X (Meson
>> GXL) and for the Amlogic evaluation board P212.
>> No documentation has been released yet for this SoC, so for now only the
>> bare minimum has been added in the DT.
>>
>> Acked-by: Rob Herring <robh at kernel.org>
>> Reviewed-by: Andreas F?rber <afaerber at suse.de>
>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>> ---
>>
>> Hey Kevin,
>> Can you take this one?
>>
>> Changelog:
>> v2:
>>   - Added acked-by and reviewed-by
>>
>> ---
>>  Documentation/devicetree/bindings/arm/amlogic.txt |   5 +
>>  arch/arm64/boot/dts/amlogic/Makefile              |   1 +
>>  arch/arm64/boot/dts/amlogic/meson-gxl-p212.dts    |  70 +++++++++
>>  arch/arm64/boot/dts/amlogic/meson-gxl.dtsi        | 179 ++++++++++++++++++++++
>
> It seems to me that meson-gxl.dtsi is almost identicial to
> meson-gxbb.dtsi.  I think we should create another .dtsi for all the
> common parts.  Something like meson-gx-common.dtsi, which is included
> by meson-gxbb.dtsi and meson-gxl.dtsi
>
> Also, the GXL family has both the S905x and S905D SoCs, so we may need
> meson-gxl-s905x.dtsi and meson-gxl-s905d.dtsi but I'm not sure of the
> full set of differences between those, so we can save that for later.
>
> But, I do think the board files should probably have the SoC name.  So
> they would look something like: meson-gxl-s905x-p212.dts (which you
> have) and meson-gxl-s905d-p230.dts (which I have.)

Oops, I should've read a bit more of my backlog before responding
here.  I see Neil has already done this building on your patch.

Kevin (still catching up on post-holiday mails)


From afaerber at suse.de  Mon Aug 29 11:38:31 2016
From: afaerber at suse.de (=?UTF-8?Q?Andreas_F=c3=a4rber?=)
Date: Mon, 29 Aug 2016 20:38:31 +0200
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
In-Reply-To: <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
 <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>
Message-ID: <2983d731-82fd-63fc-7541-8c1d6a929416@suse.de>

Am 29.08.2016 um 10:01 schrieb Carlo Caione:
> On Mon, Aug 29, 2016 at 9:56 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>> The new Amlogic GLX SoCs (S905X and S905D) are part of the Meson GX family so
>> they share some basic characteritics that can be described in a common GX
>> dtsi file used by the Meson GXBB and Meson GXL dtsi.
>>
>> This patchset introduces the common dtsi and switches the GLX and GXBB to use
>> the common dtsi, the GXBB dtsi is reformated to handle this situation.
>>
>> This patchset depends on Carlo Caione "ARM64: dts: amlogic: Add basic support for Amlogic S905X" [1]
>>
>> [1] http://lkml.kernel.org/r/1472382113-10754-1-git-send-email-carlo at caione.org
>>
>> Neil Armstrong (3):
>>   ARM64: dts: amlogic: Add Meson GX Family common dtsi
>>   ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
>>   ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi
> 
> FWIW
> Acked-by: Carlo Caione <carlo at endlessm.com>

Adding an unused .dtsi duplicating GXBB makes me uneasy.

Any chance we can simplify this to at most two steps?
1) Move code from gxbb to gx (1/3 + 3/3)
2) Add gxl using gx ("Add basic support for Amlogic S905X" + 2/3)

Alternatively:
1) "Add basic support for Amlogic S905X"
2) Factor out common bits (1/3 + 2/3 + 3/3)

As for bike-shedding, is there a GX family as well or could we drop
-common? .dtsi is always something common - compare Exynos or i.MX.
Since there are meson8b and meson8 I was anticipating that after gxbb
would come gx, not gxl.

Do you know what the L in GXL is for? Should we consider renaming gxbb
to gxb, and then also insert -s905 as suggested by Kevin, for symmetry?
U-Boot is still in an early stage with $fdtfile issues remaining that I
need to iterate over; DT compatible strings would need to remain though.

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N?rnberg)


From khilman at baylibre.com  Mon Aug 29 12:28:10 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 29 Aug 2016 14:28:10 -0500
Subject: [PATCH v5 0/6] Add Meson 8b / GXBB support to the IR driver
In-Reply-To: <20160820095424.636-1-martin.blumenstingl@googlemail.com> (Martin
 Blumenstingl's message of "Sat, 20 Aug 2016 11:54:18 +0200")
References: <20160819215547.20063-1-martin.blumenstingl@googlemail.com>
 <20160820095424.636-1-martin.blumenstingl@googlemail.com>
Message-ID: <m2shtniddh.fsf@baylibre.com>

Martin Blumenstingl <martin.blumenstingl at googlemail.com> writes:

> Newer Amlogic platforms (Meson 8b and GXBB) use a slightly different
> register layout for their Infrared Remoete Controller. The decoder mode
> is now configured in another register. Without the changes to the
> meson-ir driver we are simply getting incorrect "durations" reported
> from the hardware (because the hardware is not in time measurement aka
> software decode mode).
>
> This problem was also noticed by some people trying to use this on an
> ODROID-C1 and ODROID-C2 - the workaround there (probably because the
> datasheets were not publicy available yet at that time) was to switch
> to ir_raw_event_store_edge (which leaves it up to the kernel to measure
> the duration of a pulse). See [0] and [1] for the corresponding
> patches.
>
> Changes in v5:
> - changed pin function and group names to remote_input_ao so they match
>   with the datasheet
>
> Tested-by: Neil Armstrong <narmstrong at baylibre.com>

Thanks for the respin.  I'll take the driver and DT/bindings through the
arm-soc tree and Linus has taken the pinctrl patch.

Kevin


From carlo at caione.org  Mon Aug 29 12:50:30 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 29 Aug 2016 21:50:30 +0200
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
In-Reply-To: <2983d731-82fd-63fc-7541-8c1d6a929416@suse.de>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
 <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>
 <2983d731-82fd-63fc-7541-8c1d6a929416@suse.de>
Message-ID: <20160829195030.GA10797@localhost>

On 29/08/16 20:38, Andreas F?rber wrote:
> Am 29.08.2016 um 10:01 schrieb Carlo Caione:
> > On Mon, Aug 29, 2016 at 9:56 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> >> The new Amlogic GLX SoCs (S905X and S905D) are part of the Meson GX family so
> >> they share some basic characteritics that can be described in a common GX
> >> dtsi file used by the Meson GXBB and Meson GXL dtsi.
> >>
> >> This patchset introduces the common dtsi and switches the GLX and GXBB to use
> >> the common dtsi, the GXBB dtsi is reformated to handle this situation.
> >>
> >> This patchset depends on Carlo Caione "ARM64: dts: amlogic: Add basic support for Amlogic S905X" [1]
> >>
> >> [1] http://lkml.kernel.org/r/1472382113-10754-1-git-send-email-carlo at caione.org
> >>
> >> Neil Armstrong (3):
> >>   ARM64: dts: amlogic: Add Meson GX Family common dtsi
> >>   ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
> >>   ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi
> > 
> > FWIW
> > Acked-by: Carlo Caione <carlo at endlessm.com>
> 
> Adding an unused .dtsi duplicating GXBB makes me uneasy.

S905x (GXL) is different from S905 (GXBB), it's unused now but in the
future we can expect something different in the two DTSI.

> Any chance we can simplify this to at most two steps?
> 1) Move code from gxbb to gx (1/3 + 3/3)
> 2) Add gxl using gx ("Add basic support for Amlogic S905X" + 2/3)

fine by me.

> Alternatively:
> 1) "Add basic support for Amlogic S905X"
> 2) Factor out common bits (1/3 + 2/3 + 3/3)

how is this different from this patchset?

> As for bike-shedding, is there a GX family as well or could we drop
> -common? .dtsi is always something common - compare Exynos or i.MX.
> Since there are meson8b and meson8 I was anticipating that after gxbb
> would come gx, not gxl.

AFAIK we have:
- GXBB
- GXL
- GXM
- GXTVBB

> Do you know what the L in GXL is for? Should we consider renaming gxbb
> to gxb, and then also insert -s905 as suggested by Kevin, for symmetry?

Yes, that make sense.

Cheers,

-- 
Carlo Caione


From afaerber at suse.de  Mon Aug 29 13:15:51 2016
From: afaerber at suse.de (=?UTF-8?Q?Andreas_F=c3=a4rber?=)
Date: Mon, 29 Aug 2016 22:15:51 +0200
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
In-Reply-To: <20160829195030.GA10797@localhost>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
 <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>
 <2983d731-82fd-63fc-7541-8c1d6a929416@suse.de>
 <20160829195030.GA10797@localhost>
Message-ID: <ca513cb4-34d4-72f9-9e32-7908329243a6@suse.de>

Am 29.08.2016 um 21:50 schrieb Carlo Caione:
> On 29/08/16 20:38, Andreas F?rber wrote:
>> Am 29.08.2016 um 10:01 schrieb Carlo Caione:
>>> On Mon, Aug 29, 2016 at 9:56 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>>>> Neil Armstrong (3):
>>>>   ARM64: dts: amlogic: Add Meson GX Family common dtsi
>>>>   ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
>>>>   ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi
>>
>> Adding an unused .dtsi duplicating GXBB makes me uneasy.
> 
> S905x (GXL) is different from S905 (GXBB), it's unused now but in the
> future we can expect something different in the two DTSI.

Guess I need to be --verbose. ;)

I meant: After patch 1/3 there is a gx-common.dtsi that duplicates
contents of gxbb.dtsi and is not yet #include'd anywhere, i.e., unused.

>> Any chance we can simplify this to at most two steps?
>> 1) Move code from gxbb to gx (1/3 + 3/3)
>> 2) Add gxl using gx ("Add basic support for Amlogic S905X" + 2/3)
> 
> fine by me.
> 
>> Alternatively:
>> 1) "Add basic support for Amlogic S905X"
>> 2) Factor out common bits (1/3 + 2/3 + 3/3)
> 
> how is this different from this patchset?

I'm suggesting we do "atomic" move operations, not copy and then remove.

The difference between my two suggestions is how many and which changes
we squash - I do appreciate that it's easy for review as is but what I
have in mind is that either we should get this refactoring applied asap
(#1 1)) and rebase all pending patches on it, or we may need to rebase
the refactoring onto any pending MMC, SDIO, etc. patches, which I feel
is safer to do in one big patch (#2 2)) than split over multiple ones.
It really depends on the merge order and roadmap you guys have in mind.

>> As for bike-shedding, is there a GX family as well or could we drop
>> -common? .dtsi is always something common - compare Exynos or i.MX.
>> Since there are meson8b and meson8 I was anticipating that after gxbb
>> would come gx, not gxl.
> 
> AFAIK we have:
> - GXBB
> - GXL
> - GXM
> - GXTVBB
> 
>> Do you know what the L in GXL is for? Should we consider renaming gxbb
>> to gxb, and then also insert -s905 as suggested by Kevin, for symmetry?
> 
> Yes, that make sense.

Hm, GXTVB would still be longer than GXL then, not much point then.
We could still do -gxbb-s905 though.

Cheers,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N?rnberg)


From narmstrong at baylibre.com  Tue Aug 30 01:33:19 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 30 Aug 2016 10:33:19 +0200
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
In-Reply-To: <ca513cb4-34d4-72f9-9e32-7908329243a6@suse.de>
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
 <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>
 <2983d731-82fd-63fc-7541-8c1d6a929416@suse.de>
 <20160829195030.GA10797@localhost>
 <ca513cb4-34d4-72f9-9e32-7908329243a6@suse.de>
Message-ID: <58294020-4c10-5e77-7d0a-b81de4497962@baylibre.com>

On 08/29/2016 10:15 PM, Andreas F?rber wrote:
> Am 29.08.2016 um 21:50 schrieb Carlo Caione:
>> On 29/08/16 20:38, Andreas F?rber wrote:
>>> Am 29.08.2016 um 10:01 schrieb Carlo Caione:
>>>> On Mon, Aug 29, 2016 at 9:56 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>>>>> Neil Armstrong (3):
>>>>>   ARM64: dts: amlogic: Add Meson GX Family common dtsi
>>>>>   ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
>>>>>   ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi
>>>
>>> Adding an unused .dtsi duplicating GXBB makes me uneasy.
>>
>> S905x (GXL) is different from S905 (GXBB), it's unused now but in the
>> future we can expect something different in the two DTSI.
> 
> Guess I need to be --verbose. ;)
> 
> I meant: After patch 1/3 there is a gx-common.dtsi that duplicates
> contents of gxbb.dtsi and is not yet #include'd anywhere, i.e., unused.
> 
>>> Any chance we can simplify this to at most two steps?
>>> 1) Move code from gxbb to gx (1/3 + 3/3)
>>> 2) Add gxl using gx ("Add basic support for Amlogic S905X" + 2/3)
>>
>> fine by me.

I can merge carlo's GXL support into this patchet.

>>
>>> Alternatively:
>>> 1) "Add basic support for Amlogic S905X"
>>> 2) Factor out common bits (1/3 + 2/3 + 3/3)
>>
>> how is this different from this patchset?
> 
> I'm suggesting we do "atomic" move operations, not copy and then remove.
> 
> The difference between my two suggestions is how many and which changes
> we squash - I do appreciate that it's easy for review as is but what I
> have in mind is that either we should get this refactoring applied asap
> (#1 1)) and rebase all pending patches on it, or we may need to rebase
> the refactoring onto any pending MMC, SDIO, etc. patches, which I feel
> is safer to do in one big patch (#2 2)) than split over multiple ones.
> It really depends on the merge order and roadmap you guys have in mind.

I'm not very convinced about the utility the reduce commits... having a dtsi alone won't arm anyone.
Nevertheless, I will squash the two commits.

> 
>>> As for bike-shedding, is there a GX family as well or could we drop
>>> -common? .dtsi is always something common - compare Exynos or i.MX.
>>> Since there are meson8b and meson8 I was anticipating that after gxbb
>>> would come gx, not gxl.
>>
>> AFAIK we have:
>> - GXBB
>> - GXL
>> - GXM
>> - GXTVBB
>>
>>> Do you know what the L in GXL is for? Should we consider renaming gxbb
>>> to gxb, and then also insert -s905 as suggested by Kevin, for symmetry?
>>
>> Yes, that make sense.

As Amlogic told us, we have at least two families :
 - GXBB with the S905
 - GXL with the S905D and S905X

The GXL and GXBB families will share a lot, except the clocks tree, pinctrl registers, USB IP versions and at least ethernet PHY handling.

But the two GXL SoCs will still share a lot, maybe everything, we are not sure for now.

In the Amlogic SDK kernel, we can see more families :
 - GXM seems to be the S912 since it has two clusters of 4xA53, but looks identical to GXL for pinctrl and clocks
 - GXTVBB looking at the Amlogic SDK it could be a GXBB variant with a different GPU (t83x instead of mali450), pinctrl and clocks

In their SDK, there is a single GXL pinctrl and clock driver for GXL and GXM.

Taking in account all the boards, families and SoCs, we should have the following:
meson-gx-common.dtsi
??? meson-gxbb-s905.dtsi
?   ??? meson-gxbb-s905-odroidc2.dts
?   ??? meson-gxbb-s905-p20x.dtsi
?       ??? meson-gxbb-s905-p200.dts
?       ??? meson-gxbb-s905-p201.dts
??? meson-gxl.dtsi
?   ??? meson-gxl-s905d.dtsi
?   ?   ??? meson-gxl-s905d-p23x.dts
?   ?       ??? meson-gxl-s905d-p230.dts
?   ?       ??? meson-gxl-s905d-p231.dts
?   ??? meson-gxl-s905x.dtsi
?       ??? meson-gxl-s905x-p212.dts
??? meson-gxm-s912.dtsi
    ??? meson-gxm-s912-q20x.dtsi
        ??? meson-gxm-s912-q200.dts
        ??? meson-gxm-s912-q201.dts

But since GXBB will only be S905, we can drop the S905 naming and keep what is already upstream,
then GXM won't happen until a certain time so I plan to push the following :

meson-gx-common.dtsi
??? meson-gxbb.dtsi
?   ??? meson-gxbb-odroidc2.dts
?   ??? meson-gxbb-p20x.dtsi
?       ??? meson-gxbb-p200.dts
?       ??? meson-gxbb-p201.dts
??? meson-gxl.dtsi
    ??? meson-gxl-s905d.dtsi
    ?   ??? meson-gxl-s905d-p23x.dts
    ?       ??? meson-gxl-s905d-p230.dts
    ?       ??? meson-gxl-s905d-p231.dts
    ??? meson-gxl-s905x.dtsi
        ??? meson-gxl-s905x-p212.dts

But the meson-gxl-s905d.dtsi, meson-gxl-s905x.dtsi and meson-gxl.dtsi will be empty until we push the pinctrl, clock, ethernet PHY and USB nodes for them.

> 
> Hm, GXTVB would still be longer than GXL then, not much point then.
> We could still do -gxbb-s905 though.
> 
> Cheers,
> Andreas
> 

Thanks,
Neil



From martin.blumenstingl at googlemail.com  Tue Aug 30 11:49:28 2016
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Tue, 30 Aug 2016 20:49:28 +0200
Subject: [PATCH v3 0/5] meson: Meson8b and GXBB DWMAC glue driver
In-Reply-To: <20160828.234008.445367966910278179.davem@davemloft.net>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
 <20160828.234008.445367966910278179.davem@davemloft.net>
Message-ID: <CAFBinCCmg-+8mjd0Xc5c7bEWL9_S_4kizs_UMiiW9ATBH_G8iw@mail.gmail.com>

On Mon, Aug 29, 2016 at 5:40 AM, David Miller <davem at davemloft.net> wrote:
> From: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> Date: Sun, 28 Aug 2016 18:16:32 +0200
>
>> This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
>> Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
>> the register layout is completely different.
>> Thus I introduced a separate driver.
>>
>> Changes since v2:
>> - fixed unloading the glue driver when built as module. This pulls in a
>>   patch from Joachim Eastwood (thanks) to get our private data structure
>>   (bsp_priv).
>
> This doesn't apply cleanly at all to the net-next tree, so I have
> no idea where you expect these changes to be applied.
OK, maybe Kevin can me help out here as I think the patches should go
to various trees.

I think patches 1, 3 and 4 should go through the net-next tree (as
these touch drivers/net/ethernet/stmicro/stmmac/ and the corresponding
documentation).
Patch 2 should probably go through clk-meson-gxbb / clk-next (just
like the other clk changes we had).
The last patch (patch 5) should probably go through the ARM SoC tree
(just like the other dts changes we had).

@David, Kevin: would this be fine for you?


From sboyd at codeaurora.org  Tue Aug 30 12:19:06 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Tue, 30 Aug 2016 12:19:06 -0700
Subject: [PATCH v3 4/5] net: stmmac: add a glue driver for the Amlogic
 Meson 8b / GXBB DWMAC
In-Reply-To: <20160828161637.9941-5-martin.blumenstingl@googlemail.com>
References: <20160820093538.9707-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
 <20160828161637.9941-5-martin.blumenstingl@googlemail.com>
Message-ID: <20160830191906.GD12510@codeaurora.org>

On 08/28, Martin Blumenstingl wrote:
> +static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
> +{
> +	struct clk_init_data init;
> +	int i, ret;
> +	struct device *dev = &dwmac->pdev->dev;
> +	char clk_name[32];
> +	const char *clk_div_parents[1];
> +	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
> +	static struct clk_div_table clk_25m_div_table[] = {
> +		{ .val = 0, .div = 5 },
> +		{ .val = 1, .div = 10 },
> +		{ /* sentinel */ },
> +	};
> +
> +	/* get the mux parents from DT */
> +	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
> +		char name[16];
> +
> +		snprintf(name, sizeof(name), "clkin%d", i);
> +		dwmac->m250_mux_parent[i] = devm_clk_get(dev, name);
> +		if (IS_ERR(dwmac->m250_mux_parent[i])) {
> +			ret = PTR_ERR(dwmac->m250_mux_parent[i]);
> +			if (ret != -EPROBE_DEFER)
> +				dev_err(dev, "Missing clock %s\n", name);
> +			return ret;
> +		}
> +
> +		mux_parent_names[i] =
> +			__clk_get_name(dwmac->m250_mux_parent[i]);
> +	}
> +
> +	/* create the m250_mux */
> +	snprintf(clk_name, sizeof(clk_name), "%s#m250_sel", dev_name(dev));
> +	init.name = clk_name;
> +	init.ops = &clk_mux_ops;
> +	init.flags = CLK_IS_BASIC;

Please don't use this flag unless you need it.

> +	init.parent_names = mux_parent_names;
> +	init.num_parents = MUX_CLK_NUM_PARENTS;
> +
> +	dwmac->m250_mux.reg = dwmac->regs + PRG_ETH0;
> +	dwmac->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
> +	dwmac->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
> +	dwmac->m250_mux.flags = 0;
> +	dwmac->m250_mux.table = NULL;
> +	dwmac->m250_mux.hw.init = &init;
> +
> +	dwmac->m250_mux_clk = devm_clk_register(dev, &dwmac->m250_mux.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_mux_clk)))

Why not if(WARN_ON(IS_ERR())? The OR_ZERO part seems confusing.

> +		return PTR_ERR(dwmac->m250_mux_clk);
> +
> +	/* create the m250_div */
> +	snprintf(clk_name, sizeof(clk_name), "%s#m250_div", dev_name(dev));
> +	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
> +	clk_div_parents[0] = __clk_get_name(dwmac->m250_mux_clk);
> +	init.parent_names = clk_div_parents;
> +	init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +	dwmac->m250_div.reg = dwmac->regs + PRG_ETH0;
> +	dwmac->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
> +	dwmac->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
> +	dwmac->m250_div.hw.init = &init;
> +	dwmac->m250_div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
> +
> +	dwmac->m250_div_clk = devm_clk_register(dev, &dwmac->m250_div.hw);

We've been trying to move away from devm_clk_register() to
devm_clk_hw_register() so that clk providers aren't also clk
consumers. Obviously in this case this driver is a provider and a
consumer, so this isn't as important. Kevin did something similar
in the mmc driver, so I'll reiterate what I said on that patch.
Perhaps we should make __clk_create_clk() into a real clk
provider API so that we can use devm_clk_hw_register() here and
then generate a clk for this device. That would allow us to have
proper consumer tracking without relying on the clk that is
returned from clk_register() (the intent is to make that clk
instance internal to the framework).

> +	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m250_div_clk)))
> +		return PTR_ERR(dwmac->m250_div_clk);
> +
> +	/* create the m25_div */
> +	snprintf(clk_name, sizeof(clk_name), "%s#m25_div", dev_name(dev));
> +	init.name = devm_kstrdup(dev, clk_name, GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
> +	clk_div_parents[0] = __clk_get_name(dwmac->m250_div_clk);
> +	init.parent_names = clk_div_parents;
> +	init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +	dwmac->m25_div.reg = dwmac->regs + PRG_ETH0;
> +	dwmac->m25_div.shift = PRG_ETH0_CLK_M25_DIV_SHIFT;
> +	dwmac->m25_div.width = PRG_ETH0_CLK_M25_DIV_WIDTH;
> +	dwmac->m25_div.table = clk_25m_div_table;
> +	dwmac->m25_div.hw.init = &init;
> +	dwmac->m25_div.flags = CLK_DIVIDER_ALLOW_ZERO;
> +
> +	dwmac->m25_div_clk = devm_clk_register(dev, &dwmac->m25_div.hw);
> +	if (WARN_ON(PTR_ERR_OR_ZERO(dwmac->m25_div_clk)))
> +		return PTR_ERR(dwmac->m25_div_clk);
> +
> +	return 0;

This could be return WARN_ON(PTR_ERR_OR_ZERO(...))

> +
> +static int meson8b_dwmac_probe(struct platform_device *pdev)
> +{
> +	struct plat_stmmacenet_data *plat_dat;
> +	struct stmmac_resources stmmac_res;
> +	struct resource *res;
> +	struct meson8b_dwmac *dwmac;
> +	int ret;
> +
> +	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> +	if (ret)
> +		return ret;
> +
> +	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
> +	if (IS_ERR(plat_dat))
> +		return PTR_ERR(plat_dat);
> +
> +	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
> +	if (!dwmac)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!res)
> +		return -ENODEV;
> +

You can drop the above two lines and just call
devm_ioremap_resource().

> +	dwmac->regs = devm_ioremap_resource(&pdev->dev, res);

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


From davem at davemloft.net  Tue Aug 30 21:57:32 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 30 Aug 2016 21:57:32 -0700 (PDT)
Subject: [PATCH v3 0/5] meson: Meson8b and GXBB DWMAC glue driver
In-Reply-To: <CAFBinCCmg-+8mjd0Xc5c7bEWL9_S_4kizs_UMiiW9ATBH_G8iw@mail.gmail.com>
References: <20160828161637.9941-1-martin.blumenstingl@googlemail.com>
 <20160828.234008.445367966910278179.davem@davemloft.net>
 <CAFBinCCmg-+8mjd0Xc5c7bEWL9_S_4kizs_UMiiW9ATBH_G8iw@mail.gmail.com>
Message-ID: <20160830.215732.429612225008644820.davem@davemloft.net>

From: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
Date: Tue, 30 Aug 2016 20:49:28 +0200

> On Mon, Aug 29, 2016 at 5:40 AM, David Miller <davem at davemloft.net> wrote:
>> From: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
>> Date: Sun, 28 Aug 2016 18:16:32 +0200
>>
>>> This adds a DWMAC glue driver for the PRG_ETHERNET registers found in
>>> Meson8b and GXBB SoCs. Based on the "old" meson6b-dwmac glue driver
>>> the register layout is completely different.
>>> Thus I introduced a separate driver.
>>>
>>> Changes since v2:
>>> - fixed unloading the glue driver when built as module. This pulls in a
>>>   patch from Joachim Eastwood (thanks) to get our private data structure
>>>   (bsp_priv).
>>
>> This doesn't apply cleanly at all to the net-next tree, so I have
>> no idea where you expect these changes to be applied.
> OK, maybe Kevin can me help out here as I think the patches should go
> to various trees.
> 
> I think patches 1, 3 and 4 should go through the net-next tree (as
> these touch drivers/net/ethernet/stmicro/stmmac/ and the corresponding
> documentation).
> Patch 2 should probably go through clk-meson-gxbb / clk-next (just
> like the other clk changes we had).
> The last patch (patch 5) should probably go through the ARM SoC tree
> (just like the other dts changes we had).
> 
> @David, Kevin: would this be fine for you?

I would prefer if all of the patches went through one tree, that way
all the dependencies are satisfied in one place.


From khilman at baylibre.com  Wed Aug 31 12:32:42 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 31 Aug 2016 12:32:42 -0700
Subject: [RFC PATCH 0/3] ARm64: amlogic: Introduce common GX family dtsi
In-Reply-To: <58294020-4c10-5e77-7d0a-b81de4497962@baylibre.com> (Neil
 Armstrong's message of "Tue, 30 Aug 2016 10:33:19 +0200")
References: <1472457371-1305-1-git-send-email-narmstrong@baylibre.com>
 <CAOQ7t2YGbASh7v25wgDspKNWgFOcRsikJs_WZptn+LkVXmaHig@mail.gmail.com>
 <2983d731-82fd-63fc-7541-8c1d6a929416@suse.de>
 <20160829195030.GA10797@localhost>
 <ca513cb4-34d4-72f9-9e32-7908329243a6@suse.de>
 <58294020-4c10-5e77-7d0a-b81de4497962@baylibre.com>
Message-ID: <7hh9a068f9.fsf@baylibre.com>

Neil Armstrong <narmstrong at baylibre.com> writes:

> On 08/29/2016 10:15 PM, Andreas F?rber wrote:
>> Am 29.08.2016 um 21:50 schrieb Carlo Caione:
>>> On 29/08/16 20:38, Andreas F?rber wrote:
>>>> Am 29.08.2016 um 10:01 schrieb Carlo Caione:
>>>>> On Mon, Aug 29, 2016 at 9:56 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
>>>>>> Neil Armstrong (3):
>>>>>>   ARM64: dts: amlogic: Add Meson GX Family common dtsi
>>>>>>   ARM64: dts: amlogic: Switch Meson GXL dtsi to use common GX dtsi
>>>>>>   ARM64: dts: amlogic: Switch Meson GXBB dtsi to use common GX dtsi
>>>>
>>>> Adding an unused .dtsi duplicating GXBB makes me uneasy.
>>>
>>> S905x (GXL) is different from S905 (GXBB), it's unused now but in the
>>> future we can expect something different in the two DTSI.
>> 
>> Guess I need to be --verbose. ;)
>> 
>> I meant: After patch 1/3 there is a gx-common.dtsi that duplicates
>> contents of gxbb.dtsi and is not yet #include'd anywhere, i.e., unused.
>> 
>>>> Any chance we can simplify this to at most two steps?
>>>> 1) Move code from gxbb to gx (1/3 + 3/3)
>>>> 2) Add gxl using gx ("Add basic support for Amlogic S905X" + 2/3)
>>>
>>> fine by me.
>
> I can merge carlo's GXL support into this patchet.
>
>>>
>>>> Alternatively:
>>>> 1) "Add basic support for Amlogic S905X"
>>>> 2) Factor out common bits (1/3 + 2/3 + 3/3)
>>>
>>> how is this different from this patchset?
>> 
>> I'm suggesting we do "atomic" move operations, not copy and then remove.
>> 
>> The difference between my two suggestions is how many and which changes
>> we squash - I do appreciate that it's easy for review as is but what I
>> have in mind is that either we should get this refactoring applied asap
>> (#1 1)) and rebase all pending patches on it, or we may need to rebase
>> the refactoring onto any pending MMC, SDIO, etc. patches, which I feel
>> is safer to do in one big patch (#2 2)) than split over multiple ones.
>> It really depends on the merge order and roadmap you guys have in mind.
>
> I'm not very convinced about the utility the reduce commits... having a dtsi alone won't arm anyone.
> Nevertheless, I will squash the two commits.
>
>> 
>>>> As for bike-shedding, is there a GX family as well or could we drop
>>>> -common? .dtsi is always something common - compare Exynos or i.MX.
>>>> Since there are meson8b and meson8 I was anticipating that after gxbb
>>>> would come gx, not gxl.
>>>
>>> AFAIK we have:
>>> - GXBB
>>> - GXL
>>> - GXM
>>> - GXTVBB
>>>
>>>> Do you know what the L in GXL is for? Should we consider renaming gxbb
>>>> to gxb, and then also insert -s905 as suggested by Kevin, for symmetry?
>>>
>>> Yes, that make sense.
>
> As Amlogic told us, we have at least two families :
>  - GXBB with the S905
>  - GXL with the S905D and S905X
>
> The GXL and GXBB families will share a lot, except the clocks tree, pinctrl registers, USB IP versions and at least ethernet PHY handling.
>
> But the two GXL SoCs will still share a lot, maybe everything, we are not sure for now.
>
> In the Amlogic SDK kernel, we can see more families :
>  - GXM seems to be the S912 since it has two clusters of 4xA53, but looks identical to GXL for pinctrl and clocks
>  - GXTVBB looking at the Amlogic SDK it could be a GXBB variant with a different GPU (t83x instead of mali450), pinctrl and clocks
>
> In their SDK, there is a single GXL pinctrl and clock driver for GXL and GXM.
>
> Taking in account all the boards, families and SoCs, we should have the following:
> meson-gx-common.dtsi
> ??? meson-gxbb-s905.dtsi
> ?   ??? meson-gxbb-s905-odroidc2.dts
> ?   ??? meson-gxbb-s905-p20x.dtsi
> ?       ??? meson-gxbb-s905-p200.dts
> ?       ??? meson-gxbb-s905-p201.dts
> ??? meson-gxl.dtsi
> ?   ??? meson-gxl-s905d.dtsi
> ?   ?   ??? meson-gxl-s905d-p23x.dts
> ?   ?       ??? meson-gxl-s905d-p230.dts
> ?   ?       ??? meson-gxl-s905d-p231.dts
> ?   ??? meson-gxl-s905x.dtsi
> ?       ??? meson-gxl-s905x-p212.dts
> ??? meson-gxm-s912.dtsi
>     ??? meson-gxm-s912-q20x.dtsi
>         ??? meson-gxm-s912-q200.dts
>         ??? meson-gxm-s912-q201.dts
>
> But since GXBB will only be S905, we can drop the S905 naming and keep what is already upstream,
> then GXM won't happen until a certain time so I plan to push the following :
>
> meson-gx-common.dtsi

nit: drop the -common, as suggested by Andreas since it's kidna
redundant since it's a .dtsi.

> ??? meson-gxbb.dtsi
> ?   ??? meson-gxbb-odroidc2.dts
> ?   ??? meson-gxbb-p20x.dtsi
> ?       ??? meson-gxbb-p200.dts
> ?       ??? meson-gxbb-p201.dts
> ??? meson-gxl.dtsi
>     ??? meson-gxl-s905d.dtsi
>     ?   ??? meson-gxl-s905d-p23x.dts
>     ?       ??? meson-gxl-s905d-p230.dts
>     ?       ??? meson-gxl-s905d-p231.dts
>     ??? meson-gxl-s905x.dtsi
>         ??? meson-gxl-s905x-p212.dts
>
> But the meson-gxl-s905d.dtsi, meson-gxl-s905x.dtsi and meson-gxl.dtsi will be empty until we push the pinctrl, clock, ethernet PHY and USB nodes for them.

Looks good to me.

Kevin


