Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 06/11] ARM: shmobile: r8a7791/koelsch dts: Rename label spi to qspi, add spi0 alias
From: Geert Uytterhoeven @ 2014-02-25 10:30 UTC (permalink / raw)
  To: Simon Horman, Magnus Damm
  Cc: linux-sh-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393324219-3317-1-git-send-email-geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>

From: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>

Prepare for the advent of MSIOF SPI, which will be spi1 to spi3.

Signed-off-by: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
v2:
  - No changes

 arch/arm/boot/dts/r8a7791-koelsch.dts |    4 ++--
 arch/arm/boot/dts/r8a7791.dtsi        |    3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 603af8caae5b..03508cc73e8b 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -157,7 +157,7 @@
 		renesas,function = "intc";
 	};
 
-	qspi_pins: spi {
+	qspi_pins: spi0 {
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
 	};
@@ -182,7 +182,7 @@
 	status = "okay";
 };
 
-&spi {
+&qspi {
 	pinctrl-0 = <&qspi_pins>;
 	pinctrl-names = "default";
 
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index cde7bc486f22..3bc4546fa9c5 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -27,6 +27,7 @@
 		i2c3 = &i2c3;
 		i2c4 = &i2c4;
 		i2c5 = &i2c5;
+		spi0 = &qspi;
 	};
 
 	cpus {
@@ -762,7 +763,7 @@
 		};
 	};
 
-	spi: spi@e6b10000 {
+	qspi: spi@e6b10000 {
 		compatible = "renesas,qspi-r8a7791", "renesas,qspi";
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
-- 
1.7.9.5

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

^ permalink raw reply related

* [PATCH v2 07/11] ARM: shmobile: r8a7790 dtsi: Add MSIOF nodes and aliases
From: Geert Uytterhoeven @ 2014-02-25 10:30 UTC (permalink / raw)
  To: Simon Horman, Magnus Damm
  Cc: linux-sh, linux-arm-kernel, linux-kernel, Geert Uytterhoeven,
	devicetree
In-Reply-To: <1393324219-3317-1-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Cc: devicetree@vger.kernel.org
---
v2:
  - Drop "num-cs" and "renesas,rx-fifo-size", as they match the defaults.

 arch/arm/boot/dts/r8a7790.dtsi |   44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 9383b8436111..da69afc9e5cb 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -25,6 +25,10 @@
 		i2c2 = &i2c2;
 		i2c3 = &i2c3;
 		spi0 = &qspi;
+		spi1 = &msiof0;
+		spi2 = &msiof1;
+		spi3 = &msiof2;
+		spi4 = &msiof3;
 	};
 
 	cpus {
@@ -776,4 +780,44 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	msiof0: spi@e6e20000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6e20000 0 0x0064>;
+		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof1: spi@e6e10000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6e10000 0 0x0064>;
+		interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof2: spi@e6e00000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6e00000 0 0x0064>;
+		interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof3: spi@e6c90000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6c90000 0 0x0064>;
+		interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 08/11] ARM: shmobile: r8a7791 dtsi: Add MSIOF nodes and aliases
From: Geert Uytterhoeven @ 2014-02-25 10:30 UTC (permalink / raw)
  To: Simon Horman, Magnus Damm
  Cc: linux-sh, linux-arm-kernel, linux-kernel, Geert Uytterhoeven,
	devicetree
In-Reply-To: <1393324219-3317-1-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Cc: devicetree@vger.kernel.org
---
v2:
  - Drop "num-cs" and "renesas,rx-fifo-size", as they match the defaults.

 arch/arm/boot/dts/r8a7791.dtsi |   33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 3bc4546fa9c5..f7eec9335858 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -28,6 +28,9 @@
 		i2c4 = &i2c4;
 		i2c5 = &i2c5;
 		spi0 = &qspi;
+		spi1 = &msiof0;
+		spi2 = &msiof1;
+		spi3 = &msiof2;
 	};
 
 	cpus {
@@ -773,4 +776,34 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	msiof0: spi@e6e20000 {
+		compatible = "renesas,msiof-r8a7791";
+		reg = <0 0xe6e20000 0 0x0064>;
+		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof1: spi@e6e10000 {
+		compatible = "renesas,msiof-r8a7791";
+		reg = <0 0xe6e10000 0 0x0064>;
+		interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof2: spi@e6e00000 {
+		compatible = "renesas,msiof-r8a7791";
+		reg = <0 0xe6e00000 0 0x0064>;
+		interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 09/11] ARM: shmobile: lager dts: Add MSIOF nodes
From: Geert Uytterhoeven @ 2014-02-25 10:30 UTC (permalink / raw)
  To: Simon Horman, Magnus Damm
  Cc: linux-sh, linux-arm-kernel, linux-kernel, Geert Uytterhoeven,
	devicetree
In-Reply-To: <1393324219-3317-1-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Add pinctrl and SPI device for MSIOF on Lager.
On this board, only MSIOF1 is in use. Its bus contains a single device
(a Renesas R2A11302FT PMIC), for which no bindings are defined yet.

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Cc: devicetree@vger.kernel.org
---
v2:
  - No changes

 arch/arm/boot/dts/r8a7790-lager.dts |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 86dbdc10fe9c..cdec1af99be1 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -159,6 +159,12 @@
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
 	};
+
+	msiof1_pins: spi2 {
+		renesas,groups = "msiof1_clk", "msiof1_sync", "msiof1_rx",
+				 "msiof1_tx";
+		renesas,function = "msiof1";
+	};
 };
 
 &ether {
@@ -221,6 +227,22 @@
 	};
 };
 
+&msiof1 {
+	pinctrl-0 = <&msiof1_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	pmic: pmic@0 {
+		compatible = "renesas,r2a11302ft";
+		reg = <0>;
+		spi-max-frequency = <6000000>;
+		spi-cpol;
+		spi-cpha;
+	};
+
+};
+
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
 	pinctrl-names = "default";
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 10/11] ARM: shmobile: koelsch dts: Add MSIOF nodes
From: Geert Uytterhoeven @ 2014-02-25 10:30 UTC (permalink / raw)
  To: Simon Horman, Magnus Damm
  Cc: linux-sh, linux-arm-kernel, linux-kernel, Geert Uytterhoeven,
	devicetree
In-Reply-To: <1393324219-3317-1-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Add pinctrl and SPI device for MSIOF on Koelsch.
On this board, only MSIOF0 is in use. Its bus contains a single device
(a Renesas R2A11302FT PMIC), for which no bindings are defined yet.

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Cc: devicetree@vger.kernel.org
---
v2:
  - No changes

 arch/arm/boot/dts/r8a7791-koelsch.dts |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 03508cc73e8b..f3eb83c4265d 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -161,6 +161,12 @@
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
 	};
+
+	msiof0_pins: spi1 {
+		renesas,groups = "msiof0_clk", "msiof0_sync", "msiof0_rx",
+				 "msiof0_tx";
+		renesas,function = "msiof0";
+	};
 };
 
 &ether {
@@ -212,3 +218,18 @@
 		};
 	};
 };
+
+&msiof0 {
+	pinctrl-0 = <&msiof0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	pmic: pmic@0 {
+		compatible = "renesas,r2a11302ft";
+		reg = <0>;
+		spi-max-frequency = <6000000>;
+		spi-cpol;
+		spi-cpha;
+	};
+};
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 2/3] ARM: shmobile: r8a7778/r8a7779 dtsi: Improve and correct HSPI nodes
From: Geert Uytterhoeven @ 2014-02-25 10:37 UTC (permalink / raw)
  To: Simon Horman
  Cc: devicetree, linux-sh, linux-arm-kernel, linux-kernel,
	Geert Uytterhoeven

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

  - Add "renesas,hspi-r8a7778" resp. "renesas,hspi-r8a7779" compatible
    values,
  - Correct reference to parent interrupt controller
    (use "interrupt-parent" instead of "interrupt-controller"),
  - Add missing "#address-cells" and "#size-cells" properties, which are
    needed when populating the SPI buses.

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> [HSPI/BockW]
---
v3:
  - Split in two patches: bindings and dtsi updates
v2:
  - Add Tested-by
  - List full example compatible properties with soctypes instead of just
    the soctypes, so checkpatch can validate DTSes.

 arch/arm/boot/dts/r8a7778.dtsi |   18 ++++++++++++------
 arch/arm/boot/dts/r8a7779.dtsi |   18 ++++++++++++------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index 85c5b3b99f5e..3c6fab5c9702 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -204,26 +204,32 @@
 	};
 
 	hspi0: spi@fffc7000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
 		reg = <0xfffc7000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi1: spi@fffc8000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
 		reg = <0xfffc8000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi2: spi@fffc6000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
 		reg = <0xfffc6000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 };
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index d0561d4c7c46..8b1a336ee401 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -256,26 +256,32 @@
 	};
 
 	hspi0: spi@fffc7000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
 		reg = <0xfffc7000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi1: spi@fffc8000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
 		reg = <0xfffc8000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi2: spi@fffc6000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
 		reg = <0xfffc6000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 };
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 3/3] ARM: shmobile: bockw reference dts: Add SPI FLASH
From: Geert Uytterhoeven @ 2014-02-25 10:37 UTC (permalink / raw)
  To: Simon Horman
  Cc: devicetree, linux-sh, linux-arm-kernel, linux-kernel,
	Geert Uytterhoeven
In-Reply-To: <1393324641-3690-1-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Add Spansion s25fl008k SPI FLASH and MTD partition, based on bockw legacy
board code.

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
v3:
  - No changes

 arch/arm/boot/dts/r8a7778-bockw-reference.dts |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
index 06cda19dac6a..f76f6ec01e19 100644
--- a/arch/arm/boot/dts/r8a7778-bockw-reference.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
@@ -109,4 +109,18 @@
 	pinctrl-0 = <&hspi0_pins>;
 	pinctrl-names = "default";
 	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,s25fl008k";
+		reg = <0>;
+		spi-max-frequency = <104000000>;
+		m25p,fast-read;
+
+		partition@0 {
+			label = "data(spi)";
+			reg = <0x00000000 0x00100000>;
+		};
+	};
 };
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH v2 0/6] ARM: STi reset controller support
From: srinivas kandagatla @ 2014-02-25 10:56 UTC (permalink / raw)
  To: Philipp Zabel, Olof Johansson, Arnd Bergmann
  Cc: Maxime Coquelin, Mark Rutland, devicetree, Russell King, kernel,
	Pawel Moll, Ian Campbell, linux-doc, linux-kernel,
	stephen.gallimore, Rob Herring, Rob Landley, Kumar Gala,
	Grant Likely, linux-arm-kernel
In-Reply-To: <1393321661.4156.2.camel@pizza.hi.pengutronix.de>

Thankyou Philipp,
On 25/02/14 09:47, Philipp Zabel wrote:
>> No, the context is lost, the IP needs re-initialization.
> alright then, I'll add them to the queue.
Thats Great..
Can I ask your Ack on these patches so that I can request Arnd/Olof to
take these patches via arm-soc tree.

Hi Arnd/Olof,

I have few more DT patches which depend on the reset controller header
file. Is is possible to take the reset controller patches with Philipp's
Acks via arm-soc tree?

Thanks,
srini

> 
> thanks
> Philipp
> 
> 
> 


^ permalink raw reply

* Re: [PATCH 2/3] input: touchscreen: imx25 tcq driver
From: Markus Pargmann @ 2014-02-25 11:05 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: devicetree, linux-input, linux-iio, Samuel Ortiz, Lee Jones,
	Jonathan Cameron, linux-arm-kernel, kernel
In-Reply-To: <20140223064406.GC10151@core.coreip.homeip.net>

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

Hi,

On Sat, Feb 22, 2014 at 10:44:06PM -0800, Dmitry Torokhov wrote:
> Hi Marjus,
> 
> On Thu, Feb 20, 2014 at 05:21:51PM +0100, Markus Pargmann wrote:
> > This is a driver for the imx25 ADC/TSC module. It controls the
> > touchscreen conversion queue and creates a touchscreen input device.
> > The driver currently only supports 4 wire touchscreens. The driver uses
> > a simple conversion queue of precharge, touch detection, X measurement,
> > Y measurement, precharge and another touch detection.
> > 
> > This driver uses the regmap from the parent to setup some touch specific
> > settings in the core driver and setup a idle configuration with touch
> > detection.
> > 
> > Signed-off-by: Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > ---
> >  .../bindings/input/touchscreen/fsl-mx25-tcq.txt    |  29 +
> >  drivers/input/touchscreen/Kconfig                  |   6 +
> >  drivers/input/touchscreen/Makefile                 |   1 +
> >  drivers/input/touchscreen/fsl-imx25-tcq.c          | 589 +++++++++++++++++++++
> >  4 files changed, 625 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
> >  create mode 100644 drivers/input/touchscreen/fsl-imx25-tcq.c
> > 
> > diff --git a/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
> > new file mode 100644
> > index 0000000..4214a99
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
> > @@ -0,0 +1,29 @@
> > +Freescale mx25 TS conversion queue module
> > +
> > +mx25 touchscreen conversion queue module which controls the ADC unit of the
> > +mx25 for attached touchscreens.
> > +
> > +Required properties:
> > + - compatible: Should be "fsl,imx25-tcq".
> > + - reg: Memory range of the device.
> > + - interrupts: Should be the interrupt number associated with this module within
> > +   the tscadc unit (<0>).
> > + - interrupt-parent: Should be a phandle to the tscadc unit.
> > + - fsl,wires: Should be '<4>' or '<5>'
> > +
> > +Optional properties:
> > + - fsl,pen-debounce: Pen debounce time.
> > + - fsl,pen-threshold: Pen-down threshold for the touchscreen.
> > + - fsl,settling-time: Settling time in nanoseconds.
> > +
> > +This device includes two conversion queues which can be added as subnodes.
> > +The first queue is for the touchscreen, the second for general purpose ADC.
> > +
> > +Example:
> > +	tsc: tcq@50030400 {
> > +		compatible = "fsl,imx25-tcq";
> > +		reg = <0x50030400 0x60>;
> > +		interrupt-parent = <&tscadc>;
> > +		interrupts = <0>;
> > +		fsl,wires = <4>;
> > +	};
> > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> > index 07e9e82..d52c055 100644
> > --- a/drivers/input/touchscreen/Kconfig
> > +++ b/drivers/input/touchscreen/Kconfig
> > @@ -715,6 +715,12 @@ config TOUCHSCREEN_USB_COMPOSITE
> >  	  To compile this driver as a module, choose M here: the
> >  	  module will be called usbtouchscreen.
> >  
> > +config TOUCHSCREEN_MX25
> > +	tristate "Freescale i.MX25 touchscreen input driver"
> > +	depends on MFD_MX25_TSADC
> > +	help
> > +	  Enable support for touchscreen connected to your i.MX25.
> > +
> >  config TOUCHSCREEN_MC13783
> >  	tristate "Freescale MC13783 touchscreen input driver"
> >  	depends on MFD_MC13XXX
> > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> > index 62801f2..c891f30 100644
> > --- a/drivers/input/touchscreen/Makefile
> > +++ b/drivers/input/touchscreen/Makefile
> > @@ -38,6 +38,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
> >  obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
> >  obj-$(CONFIG_TOUCHSCREEN_LPC32XX)	+= lpc32xx_ts.o
> >  obj-$(CONFIG_TOUCHSCREEN_MAX11801)	+= max11801_ts.o
> > +obj-$(CONFIG_TOUCHSCREEN_MX25)		+= fsl-imx25-tcq.o
> >  obj-$(CONFIG_TOUCHSCREEN_MC13783)	+= mc13783_ts.o
> >  obj-$(CONFIG_TOUCHSCREEN_MCS5000)	+= mcs5000_ts.o
> >  obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
> > diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c
> > new file mode 100644
> > index 0000000..436cc8b
> > --- /dev/null
> > +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c
> > @@ -0,0 +1,589 @@
> > +/*
> > + * Copyright 2014 Markus Pargmann, Pengutronix <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + * Based on driver from 2011 Juergen Beisert, Pengutronix <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > + *
> > + * The code contained herein is licensed under the GNU General Public
> > + * License. You may obtain a copy of the GNU General Public License
> > + * Version 2 or later at the following locations:
> > + *
> > + * http://www.opensource.org/licenses/gpl-license.html
> > + * http://www.gnu.org/copyleft/gpl.html
> > + *
> > + * This is the driver for the imx25 TCQ (Touchscreen Conversion Queue)
> > + * connected to the imx25 ADC.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/input.h>
> > +#include <linux/mfd/imx25-tsadc.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +static const char mx25_tcq_name[] = "mx25-tcq";
> > +
> > +enum mx25_tcq_mode {
> > +	MX25_TS_4WIRE,
> > +};
> > +
> > +struct mx25_tcq_priv {
> > +	struct regmap *regs;
> > +	struct regmap *core_regs;
> > +	struct input_dev *idev;
> > +	enum mx25_tcq_mode mode;
> > +	unsigned int pen_threshold;
> > +	unsigned int sample_count;
> > +	unsigned int expected_samples;
> > +	unsigned int repeat_wait;
> > +	unsigned int pen_debounce;
> > +	unsigned int settling_time;
> > +	struct clk *clk;
> > +};
> > +
> > +static struct regmap_config mx25_tcq_regconfig = {
> > +	.fast_io = true,
> > +	.max_register = 0x5c,
> > +	.reg_bits = 32,
> > +	.val_bits = 32,
> > +	.reg_stride = 4,
> > +};
> > +
> > +static struct of_device_id mx25_tcq_ids[] = {
> > +	{ .compatible = "fsl,imx25-tcq", },
> > +	{ /* Senitel */ }
> > +};
> > +
> > +#define TSC_4WIRE_PRE_INDEX 0
> > +#define TSC_4WIRE_X_INDEX 1
> > +#define TSC_4WIRE_Y_INDEX 2
> > +#define TSC_4WIRE_POST_INDEX 3
> > +#define TSC_4WIRE_LEAVE 4
> > +
> > +#define MX25_TSC_DEF_THRESHOLD 80
> > +#define TSC_MAX_SAMPLES 16
> > +
> > +
> > +enum mx25_adc_configurations {
> > +	MX25_CFG_PRECHARGE = 0,
> > +	MX25_CFG_TOUCH_DETECT,
> > +	MX25_CFG_X_MEASUREMENT,
> > +	MX25_CFG_Y_MEASUREMENT,
> > +};
> > +
> > +#define MX25_PRECHARGE_VALUE (\
> > +			MX25_ADCQ_CFG_YPLL_OFF | \
> > +			MX25_ADCQ_CFG_XNUR_OFF | \
> > +			MX25_ADCQ_CFG_XPUL_HIGH | \
> > +			MX25_ADCQ_CFG_REFP_INT | \
> > +			MX25_ADCQ_CFG_IN_XP | \
> > +			MX25_ADCQ_CFG_REFN_NGND2 | \
> > +			MX25_ADCQ_CFG_IGS)
> > +
> > +#define MX25_TOUCH_DETECT_VALUE (\
> > +			MX25_ADCQ_CFG_YNLR | \
> > +			MX25_ADCQ_CFG_YPLL_OFF | \
> > +			MX25_ADCQ_CFG_XNUR_OFF | \
> > +			MX25_ADCQ_CFG_XPUL_OFF | \
> > +			MX25_ADCQ_CFG_REFP_INT | \
> > +			MX25_ADCQ_CFG_IN_XP | \
> > +			MX25_ADCQ_CFG_REFN_NGND2 | \
> > +			MX25_ADCQ_CFG_PENIACK)
> > +
> > +static void imx25_setup_queue_cfgs(struct mx25_tcq_priv *priv,
> > +		unsigned int settling_time)
> > +{
> > +	u32 precharge_cfg =
> > +			MX25_PRECHARGE_VALUE |
> > +			MX25_ADCQ_CFG_SETTLING_TIME(settling_time);
> > +	u32 touch_detect_cfg =
> > +			MX25_TOUCH_DETECT_VALUE |
> > +			MX25_ADCQ_CFG_NOS(1) |
> > +			MX25_ADCQ_CFG_SETTLING_TIME(settling_time);
> > +
> > +	regmap_write(priv->core_regs, MX25_TSC_TICR, precharge_cfg);
> > +
> > +	/* PRECHARGE */
> > +	regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_PRECHARGE),
> > +			precharge_cfg);
> > +
> > +	/* TOUCH_DETECT */
> > +	regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_TOUCH_DETECT),
> > +			touch_detect_cfg);
> > +
> > +	/* X Measurement */
> > +	regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_X_MEASUREMENT),
> > +			MX25_ADCQ_CFG_YPLL_OFF |
> > +			MX25_ADCQ_CFG_XNUR_LOW |
> > +			MX25_ADCQ_CFG_XPUL_HIGH |
> > +			MX25_ADCQ_CFG_REFP_XP |
> > +			MX25_ADCQ_CFG_IN_YP |
> > +			MX25_ADCQ_CFG_REFN_XN |
> > +			MX25_ADCQ_CFG_NOS(priv->sample_count) |
> > +			MX25_ADCQ_CFG_SETTLING_TIME(settling_time));
> > +
> > +	/* Y Measurement */
> > +	regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_Y_MEASUREMENT),
> > +			MX25_ADCQ_CFG_YNLR |
> > +			MX25_ADCQ_CFG_YPLL_HIGH |
> > +			MX25_ADCQ_CFG_XNUR_OFF |
> > +			MX25_ADCQ_CFG_XPUL_OFF |
> > +			MX25_ADCQ_CFG_REFP_YP |
> > +			MX25_ADCQ_CFG_IN_XP |
> > +			MX25_ADCQ_CFG_REFN_YN |
> > +			MX25_ADCQ_CFG_NOS(priv->sample_count) |
> > +			MX25_ADCQ_CFG_SETTLING_TIME(settling_time));
> > +
> > +	/* Enable the touch detection right now */
> > +	regmap_write(priv->core_regs, MX25_TSC_TICR, touch_detect_cfg |
> > +			MX25_ADCQ_CFG_IGS);
> > +}
> > +
> > +static int imx25_setup_queue_4wire(struct mx25_tcq_priv *priv,
> > +		unsigned settling_time, int *items)
> > +{
> > +	imx25_setup_queue_cfgs(priv, settling_time);
> > +
> > +	/* Setup the conversion queue */
> > +	regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0,
> > +			MX25_ADCQ_ITEM(0, MX25_CFG_PRECHARGE) |
> > +			MX25_ADCQ_ITEM(1, MX25_CFG_TOUCH_DETECT) |
> > +			MX25_ADCQ_ITEM(2, MX25_CFG_X_MEASUREMENT) |
> > +			MX25_ADCQ_ITEM(3, MX25_CFG_Y_MEASUREMENT) |
> > +			MX25_ADCQ_ITEM(4, MX25_CFG_PRECHARGE) |
> > +			MX25_ADCQ_ITEM(5, MX25_CFG_TOUCH_DETECT));
> > +
> > +	/* We measure X/Y with 'sample_count' number of samples and execute a
> > +	 * touch detection twice, with 1 sample each */
> > +	priv->expected_samples = priv->sample_count * 2 + 2;
> > +	*items = 6;
> > +
> > +	return 0;
> > +}
> > +
> > +static void mx25_tcq_disable_touch_irq(struct mx25_tcq_priv *priv)
> > +{
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK,
> > +			MX25_ADCQ_CR_PDMSK);
> > +}
> > +
> > +static void mx25_tcq_enable_touch_irq(struct mx25_tcq_priv *priv)
> > +{
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK, 0);
> > +}
> > +
> > +static void mx25_tcq_disable_fifo_irq(struct mx25_tcq_priv *priv)
> > +{
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ,
> > +			MX25_ADCQ_MR_FDRY_IRQ);
> > +}
> > +
> > +static void mx25_tcq_enable_fifo_irq(struct mx25_tcq_priv *priv)
> > +{
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ, 0);
> > +}
> > +
> > +static void mx25_tcq_force_queue_start(struct mx25_tcq_priv *priv)
> > +{
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS,
> > +			MX25_ADCQ_CR_FQS);
> > +
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
> > +}
> > +
> > +static void mx25_tcq_force_queue_stop(struct mx25_tcq_priv *priv)
> > +{
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
> > +}
> > +
> > +static void mx25_tcq_fifo_reset(struct mx25_tcq_priv *priv)
> > +{
> > +	u32 tcqcr;
> > +
> > +	regmap_read(priv->regs, MX25_ADCQ_CR, &tcqcr);
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST,
> > +			MX25_ADCQ_CR_FRST);
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST,
> > +			0);
> > +	regmap_write(priv->regs, MX25_ADCQ_CR, tcqcr);
> > +}
> > +
> > +static void mx25_tcq_re_enable_touch_detection(struct mx25_tcq_priv *priv)
> > +{
> > +	/* stop the queue from looping */
> > +	mx25_tcq_force_queue_stop(priv);
> > +
> > +	/* for a clean touch detection, preload the X plane */
> > +	regmap_write(priv->core_regs, MX25_TSC_TICR, MX25_PRECHARGE_VALUE);
> > +
> > +	/* waste some time now to pre-load the X plate to high voltage */
> > +	mx25_tcq_fifo_reset(priv);
> > +
> > +	/* re-enable the detection right now */
> > +	regmap_write(priv->core_regs, MX25_TSC_TICR, MX25_TOUCH_DETECT_VALUE |
> > +			MX25_ADCQ_CFG_IGS);
> > +
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_PD,
> > +			MX25_ADCQ_SR_PD);
> > +
> > +	/* enable the pen down event to be a source for the interrupt */
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_PD_IRQ, 0);
> > +
> > +	/* lets fire the next IRQ if someone touches the touchscreen */
> > +	mx25_tcq_enable_touch_irq(priv);
> > +}
> > +
> > +static int mx25_tcq_create_event_for_4wire(struct mx25_tcq_priv *priv,
> > +		u32 *sample_buf, int samples)
> > +{
> > +	unsigned int x_pos = 0;
> > +	unsigned int y_pos = 0;
> > +	unsigned int touch_pre = 0;
> > +	unsigned int touch_post = 0;
> > +	unsigned i;
> > +	int ret = 0;
> > +
> > +	for (i = 0; i < samples; i++) {
> > +		unsigned int index = MX25_ADCQ_FIFO_ID(sample_buf[i]);
> > +		unsigned int val = MX25_ADCQ_FIFO_DATA(sample_buf[i]);
> > +
> > +		switch (index) {
> > +		case 1:
> > +			touch_pre = val;
> > +			break;
> > +		case 2:
> > +			x_pos = val;
> > +			break;
> > +		case 3:
> > +			y_pos = val;
> > +			break;
> > +		case 5:
> > +			touch_post = val;
> > +			break;
> > +		default:
> > +			ret = -EINVAL;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (ret == 0 && samples != 0) {
> > +		/*
> > +		 * only if both touch measures are below a treshold,
> > +		 * the position is valid
> > +		 */
> > +		if (touch_pre < priv->pen_threshold &&
> > +					touch_post < priv->pen_threshold) {
> > +			/* valid samples, generate a report */
> > +			x_pos /= priv->sample_count;
> > +			y_pos /= priv->sample_count;
> > +			input_report_abs(priv->idev, ABS_X, x_pos);
> > +			input_report_abs(priv->idev, ABS_Y, y_pos);
> > +			input_report_key(priv->idev, BTN_TOUCH,
> > +					0xfff - ((touch_pre + touch_post) / 2));
> 
> Hmm, are you trying to report pressure here?

No this is only to detect touches, not pressure. Reporting pressure
would require a different, more complex conversion queue.

> 
> > +			input_sync(priv->idev);
> > +
> > +			/* get next sample */
> > +			mx25_tcq_force_queue_start(priv);
> > +			mx25_tcq_enable_fifo_irq(priv);
> > +		} else {
> > +			if (touch_pre >= priv->pen_threshold &&
> 
> You can convert this to "else if" and save indentation level here.

Fixed.

> 
> > +					touch_post >= priv->pen_threshold) {
> > +				/*
> > +				 * if both samples are invalid,
> > +				 * generate a release report
> > +				 */
> > +				input_report_key(priv->idev, BTN_TOUCH, 0);
> > +				input_sync(priv->idev);
> > +				mx25_tcq_re_enable_touch_detection(priv);
> > +			} else {
> > +				/*
> > +				 * if only one of both touch measurements are
> > +				 * below the threshold, still some bouncing
> > +				 * happens. Take additional samples in this
> > +				 * case to be sure
> > +				 */
> > +				mx25_tcq_force_queue_start(priv);
> > +				mx25_tcq_enable_fifo_irq(priv);
> > +			}
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static irqreturn_t mx25_tcq_irq_thread(int irq, void *dev_id)
> > +{
> > +	struct mx25_tcq_priv *priv = (struct mx25_tcq_priv *) dev_id;
> > +	u32 sample_buf[TSC_MAX_SAMPLES];
> > +	int samples = 0;
> > +
> > +	/* read all samples */
> > +	while (1) {
> > +		u32 stats;
> > +
> > +		regmap_read(priv->regs, MX25_ADCQ_SR, &stats);
> 
> Error handling for I/O operations?

This is memory mapped io. It only returns an error when the clock enable
operation fails. As regmap is not configured to use a clock for this
driver, I would prefer to not use error handling for regmap_read/write.

> 
> > +		if (stats & MX25_ADCQ_SR_EMPT)
> > +			break;
> > +
> > +		if (samples < TSC_MAX_SAMPLES) {
> > +			regmap_read(priv->regs, MX25_ADCQ_FIFO,
> > +					&sample_buf[samples]);
> > +			++samples;
> > +		} else {
> > +			u32 discarded;
> > +			/* discard samples */
> > +			regmap_read(priv->regs, MX25_ADCQ_FIFO, &discarded);
> 
> Should there be some upper bound for number of discarded samples?

I just noticed that we do not repeat the conversion queue. The bit is
not set, so all the repeat code can be removed. This also means that the
conversion is stopped when we reach the end of the conversion queue and
this should not need an additional upper bound for discarded samples.

> 
> > +		}
> > +	}
> > +
> > +	mx25_tcq_create_event_for_4wire(priv, sample_buf, samples);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static irqreturn_t mx25_tcq_irq(int irq, void *dev_id)
> > +{
> > +	struct mx25_tcq_priv *priv = (struct mx25_tcq_priv *)dev_id;
> > +	u32 stat;
> > +	int ret = IRQ_HANDLED;
> > +
> > +	regmap_read(priv->regs, MX25_ADCQ_SR, &stat);
> > +
> > +	if (stat & (MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR))
> > +		mx25_tcq_fifo_reset(priv);
> > +
> > +	if (stat & MX25_ADCQ_SR_PD) {
> > +		mx25_tcq_disable_touch_irq(priv);
> > +		mx25_tcq_force_queue_start(priv);
> > +		mx25_tcq_enable_fifo_irq(priv);
> > +	}
> > +
> > +	if (stat & MX25_ADCQ_SR_FDRY) {
> > +		mx25_tcq_disable_fifo_irq(priv);
> > +		ret = IRQ_WAKE_THREAD;
> > +	}
> > +
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR |
> > +			MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD |
> > +			MX25_ADCQ_SR_EOQ,
> > +			MX25_ADCQ_SR_FRR |
> > +			MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD |
> > +			MX25_ADCQ_SR_EOQ);
> > +
> > +	return ret;
> > +}
> > +
> > +/* configure the statemachine for a 4-wire touchscreen */
> > +static int mx25_tcq_init(struct mx25_tcq_priv *priv)
> > +{
> > +	u32 tgcr;
> > +	unsigned int ipg_div;
> > +	unsigned int adc_period;
> > +	unsigned int repeat_wait;
> > +	unsigned int debounce_cnt;
> > +	unsigned int settling_time;
> > +	int itemct;
> > +	int ret;
> > +
> > +	regmap_read(priv->core_regs, MX25_TSC_TGCR, &tgcr);
> > +	ipg_div = max_t(unsigned int, 4, MX25_TGCR_GET_ADCCLK(tgcr));
> > +	adc_period = clk_get_rate(priv->clk) / (ipg_div * 2 + 2);
> > +	repeat_wait = fls(DIV_ROUND_UP(priv->repeat_wait, adc_period));
> > +	debounce_cnt = DIV_ROUND_UP(priv->pen_debounce, adc_period * 8) - 1;
> > +	settling_time = DIV_ROUND_UP(priv->settling_time, adc_period);
> > +
> > +
> > +	/* Reset */
> > +	regmap_write(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QRST |
> > +			MX25_ADCQ_CR_FRST);
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QRST |
> > +			MX25_ADCQ_CR_FRST, 0);
> > +
> > +	/* up to 128 * 8 ADC clocks are possible */
> > +	if (debounce_cnt > 127)
> > +		debounce_cnt = 127;
> > +
> > +	if (repeat_wait > 15)
> > +		repeat_wait = 15;
> > +
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_RWAIT_MASK,
> > +			MX25_ADCQ_CR_RWAIT(repeat_wait));
> > +
> > +	ret = imx25_setup_queue_4wire(priv, 0x0, &itemct);
> > +	if (ret)
> > +		return ret;
> > +
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_LITEMID_MASK |
> > +			MX25_ADCQ_CR_WMRK_MASK,
> > +			MX25_ADCQ_CR_LITEMID(itemct - 1) |
> > +			MX25_ADCQ_CR_WMRK(priv->expected_samples - 1));
> > +
> > +	/* setup debounce count */
> > +	regmap_update_bits(priv->core_regs, MX25_TSC_TGCR,
> > +			MX25_TGCR_PDBTIME_MASK,
> > +			MX25_TGCR_PDBTIME(debounce_cnt));
> > +
> > +	/* enable debounce */
> > +	regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDBEN,
> > +			MX25_TGCR_PDBEN);
> > +	regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDEN,
> > +			MX25_TGCR_PDEN);
> > +
> > +	/* enable the engine on demand */
> > +	regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QSM_FQS,
> > +			MX25_ADCQ_CR_QSM_FQS);
> > +
> > +	mx25_tcq_re_enable_touch_detection(priv);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mx25_tcq_parse_dt(struct platform_device *pdev,
> > +		struct mx25_tcq_priv *priv)
> > +{
> > +	struct device_node *np = pdev->dev.of_node;
> > +	u32 wires;
> > +	int ret;
> > +
> > +	/* Setup defaults */
> > +	priv->pen_threshold = 500;
> > +	priv->sample_count = 3;
> > +	priv->repeat_wait = 15000000;
> > +	priv->pen_debounce = 1000000;
> > +	priv->settling_time = 250000;
> > +
> > +	ret = of_property_read_u32(np, "fsl,wires", &wires);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "Failed to find fsl,wires properties\n");
> > +		return ret;
> > +	}
> > +
> > +	if (wires == 4) {
> > +		priv->mode = MX25_TS_4WIRE;
> > +	} else {
> > +		dev_err(&pdev->dev, "%u-wire mode not supported\n", wires);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* These are optional, we don't care about the return values */
> > +	of_property_read_u32(np, "fsl,pen-threshold", &priv->pen_threshold);
> > +	of_property_read_u32(np, "fsl,settling-time", &priv->settling_time);
> > +	of_property_read_u32(np, "fsl,pen-debounce", &priv->pen_debounce);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mx25_tcq_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct input_dev *idev;
> > +	struct mx25_tcq_priv *priv;
> > +	struct resource *res;
> > +	void __iomem *mem;
> > +	int ret;
> > +	int irq;
> > +
> > +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	mem = devm_ioremap_resource(dev, res);
> > +	if (!mem) {
> > +		dev_err(dev, "Failed to get iomem");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ret = mx25_tcq_parse_dt(pdev, priv);
> > +	if (ret)
> > +		return ret;
> > +
> > +	priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_tcq_regconfig);
> > +	if (IS_ERR(priv->regs)) {
> > +		dev_err(dev, "Failed to initialize regmap\n");
> > +		return PTR_ERR(priv->regs);
> > +	}
> > +
> > +	irq = platform_get_irq(pdev, 0);
> > +	if (irq < 0) {
> > +		dev_err(dev, "Failed to get IRQ\n");
> > +		return irq;
> > +	}
> > +
> > +	ret = devm_request_threaded_irq(dev, irq, mx25_tcq_irq,
> > +			mx25_tcq_irq_thread, IRQF_ONESHOT, pdev->name, priv);
> > +	if (ret) {
> > +		dev_err(dev, "Failed requesting IRQ\n");
> > +		return ret;
> > +	}
> 
> Are we sure the device is quiesce here? Otherwise interrupts will start
> coming but input device is not there yet.

I moved it to the end of the probe function just before tcq_init where
the interrupts are enabled.

> 
> > +
> > +	idev = devm_input_allocate_device(dev);
> > +	if (!idev) {
> > +		dev_err(dev, "Failed to allocate input device\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	idev->name = mx25_tcq_name;
> > +	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> > +	idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> > +	input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
> > +	input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
> > +
> > +	idev->id.bustype = BUS_HOST;
> > +
> > +	ret = input_register_device(idev);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to register input device\n");
> > +		return ret;
> > +	}
> > +
> > +	priv->idev = idev;
> > +
> > +	priv->core_regs = mx25_tsadc_get_regmap(pdev->dev.parent);
> > +	priv->clk = mx25_tsadc_get_ipg(pdev->dev.parent);
> > +
> > +	ret = clk_prepare_enable(priv->clk);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to enable ipg clock\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = mx25_tcq_init(priv);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to init tcq\n");
> > +		goto error_tcq_init;
> > +	}
> > +
> > +	platform_set_drvdata(pdev, priv);
> > +
> > +	return 0;
> > +
> > +error_tcq_init:
> > +	clk_disable_unprepare(priv->clk);
> > +	return ret;
> > +}
> > +
> > +static int mx25_tcq_remove(struct platform_device *pdev)
> > +{
> > +	struct mx25_tcq_priv *priv = platform_get_drvdata(pdev);
> > +
> > +	clk_disable_unprepare(priv->clk);
> 
> Hmm, if you disable clk all other operations will likely to fail. We
> really need devm clk interface, I guess I need to dust off my old
> patch...
> 
> > +
> > +	return 0;
> > +}
> > +
> > +static struct platform_driver mx25_tcq_driver = {
> > +	.driver		= {
> > +		.name	= "mx25-tcq",
> > +		.owner	= THIS_MODULE,
> > +		.of_match_table = mx25_tcq_ids,
> > +	},
> > +	.probe		= mx25_tcq_probe,
> > +	.remove		= mx25_tcq_remove,
> > +};
> > +module_platform_driver(mx25_tcq_driver);
> > +
> > +MODULE_DESCRIPTION("TS input driver for Freescale mx25");
> > +MODULE_AUTHOR("Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>");
> > +MODULE_LICENSE("GPL v2");
> > -- 
> > 1.8.5.3
> > 

Thanks,

Markus

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v2 0/6] ARM: STi reset controller support
From: Philipp Zabel @ 2014-02-25 11:15 UTC (permalink / raw)
  To: srinivas kandagatla
  Cc: Olof Johansson, Arnd Bergmann, Maxime Coquelin, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Russell King,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, Pawel Moll, Ian Campbell,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	stephen.gallimore-qxv4g6HH51o, Rob Herring, Rob Landley,
	Kumar Gala, Grant Likely,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <530C76F0.8000909-qxv4g6HH51o@public.gmane.org>

Hi Srinivas,

Am Dienstag, den 25.02.2014, 10:56 +0000 schrieb srinivas kandagatla:
> Thankyou Philipp,
> On 25/02/14 09:47, Philipp Zabel wrote:
> >> No, the context is lost, the IP needs re-initialization.
> > alright then, I'll add them to the queue.
> Thats Great..
> Can I ask your Ack on these patches so that I can request Arnd/Olof to
> take these patches via arm-soc tree.
> 
> Hi Arnd/Olof,
> 
> I have few more DT patches which depend on the reset controller header
> file. Is is possible to take the reset controller patches with Philipp's
> Acks via arm-soc tree?

That's fine with me, too. Shall I back the patches out of the reset
queue, then?

Acked-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

regards
Philipp

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

^ permalink raw reply

* Re: [PATCH v5 2/4] devicetree: bindings: Document Krait CPU/L1 EDAC
From: Lorenzo Pieralisi @ 2014-02-25 11:16 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Borislav Petkov, linux-kernel@vger.kernel.org,
	linux-arm-msm@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-edac@vger.kernel.org,
	Mark Rutland, Kumar Gala, devicetree@vger.kernel.org
In-Reply-To: <20140219002043.GE14769@codeaurora.org>

Hi Stephen,

On Wed, Feb 19, 2014 at 12:20:43AM +0000, Stephen Boyd wrote:
> (Sorry, this discussion stalled due to merge window + life events)

Sorry for the delay in replying on my side too.

> On 01/17, Lorenzo Pieralisi wrote:
> > On Thu, Jan 16, 2014 at 07:26:17PM +0000, Stephen Boyd wrote:
> > > On 01/16, Lorenzo Pieralisi wrote:
> > > > On Thu, Jan 16, 2014 at 06:05:05PM +0000, Stephen Boyd wrote:
> > > > > On 01/16, Lorenzo Pieralisi wrote:
> > > > > > Do we really want to do that ? I am not sure. A cpus node is supposed to
> > > > > > be a container node, we should not define this binding just because we
> > > > > > know the kernel creates a platform device for it then.
> > > > > 
> > > > > This is just copying more of the ePAPR spec into this document.
> > > > > It just so happens that having a compatible field here allows a
> > > > > platform device to be created. I don't see why that's a problem.
> > > > 
> > > > I do not see why you cannot define a node like pmu or arch-timer and stick
> > > > a compatible property in there. cpus node does not represent a device, and
> > > > must not be created as a platform device, that's my opinion.
> > > > 
> > > 
> > > I had what you're suggesting before in the original revision of
> > > this patch. Please take a look at the original patch series[1]. I
> > > suppose it could be tweaked slightly to still have a cache node
> > > for the L2 interrupt and the next-level-cache pointer from the
> > > CPUs.
> > 
> > Ok, sorry, we are running around in circles here, basically you moved
> > the node to cpus according to reviews. I still think that treating cpus
> > as a device is not a great idea, even though I am in the same
> > position with C-states and probably will add C-state tables in the cpus
> > node.
> > 
> > http://comments.gmane.org/gmane.linux.power-management.general/41012
> > 
> > I just would like to see under cpus nodes and properties that apply to
> > all ARM systems, and avoid defining properties (eg interrupts) that
> > have different meanings for different ARM cores.
> > 
> > The question related to why the kernel should create a platform device
> > out of cpus is still open. I really do not want to block your series
> > for these simple issues but we have to make a decision and stick to that,
> > I am fine either way if we have a plan.
> > 
> 
> Do you just want a backup plan in case we don't make a platform
> device out of the cpus node? I believe we can always add code
> somewhere to create a platform device at runtime if we detect the
> cpus node has a compatible string equal to "qcom,krait". We could
> probably change this driver's module_init() to scan the DT for
> such a compatible string and create the platform device right
> there. If we get more than one interrupt in the cpus node we can
> add interrupt-names and then have software look for interrupts by
> name instead of number.

As I mentioned, I do not like the idea of adding compatible properties
just to force the kernel to create platform devices out of device tree
nodes. On top of that I would avoid adding a compatible property
to the cpus node (after all properties like enable-method are common for all
cpus but still duplicated), my only concern being backward compatibility
here (ie if we do that for interrupts, we should do that also for other
common cpu nodes properties, otherwise we have different rules for
different properties).

I think you can then add interrupts to cpu nodes ("qcom,krait" specific),
and as you mentioned create a platform device for that.

Thanks,
Lorenzo

^ permalink raw reply

* Re: [PATCH 4/5] DMA: sun6i: Add driver for the Allwinner A31 DMA controller
From: Andy Shevchenko @ 2014-02-25 11:28 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Emilio Lopez, Dan Williams, Vinod Koul, Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <1393258967-4843-5-git-send-email-maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

On Mon, 2014-02-24 at 17:22 +0100, Maxime Ripard wrote:
> The Allwinner A31 has a 16 channels DMA controller that it shares with the
> newer A23. Although sharing some similarities with the DMA controller of the
> older Allwinner SoCs, it's significantly different, I don't expect it to be
> possible to share the driver for these two.
> 
> The A31 Controller is able to memory-to-memory or memory-to-device transfers on
> the 16 channels in parallel.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  .../devicetree/bindings/dma/sun6i-dma.txt          |  45 +
>  drivers/dma/Kconfig                                |   8 +
>  drivers/dma/Makefile                               |   1 +
>  drivers/dma/sun6i-dma.c                            | 960 +++++++++++++++++++++
>  4 files changed, 1014 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/sun6i-dma.txt
>  create mode 100644 drivers/dma/sun6i-dma.c
> 
> diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> new file mode 100644
> index 0000000..5d7c86d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> @@ -0,0 +1,45 @@
> +Allwinner A31 DMA Controller
> +
> +This driver follows the generic DMA bindings defined in dma.txt.
> +
> +Required properties:
> +
> +- compatible:	Must be "allwinner,sun6i-a31-dma"
> +- reg:		Should contain the registers base address and length
> +- interrupts:	Should contain a reference to the interrupt used by this device
> +- clocks:	Should contain a reference to the parent AHB clock
> +- resets:	Should contain a reference to the reset controller asserting
> +	  	this device in reset
> +- #dma-cells :	Should be 1, a single cell holding a line request number
> +
> +Example:
> +	dma: dma-controller@01c02000 {
> +		compatible = "allwinner,sun6i-a31-dma";
> +		reg = <0x01c02000 0x1000>;
> +		interrupts = <0 50 4>;
> +		clocks = <&ahb1_gates 6>;
> +		resets = <&ahb1_rst 6>;
> +		#dma-cells = <1>;
> +	};
> +
> +Clients:
> +
> +DMA clients connected to the A31 DMA controller must use the format
> +described in the dma.txt file, using a two-cell specifier for each
> +channel: a phandle plus one integer cells.
> +The two cells in order are:
> +
> +1. A phandle pointing to the DMA controller.
> +2. The port ID as specified in the datasheet
> +
> +Example:
> +spi2: spi@01c6a000 {
> +	compatible = "allwinner,sun6i-a31-spi";
> +	reg = <0x01c6a000 0x1000>;
> +	interrupts = <0 67 4>;
> +	clocks = <&ahb1_gates 22>, <&spi2_clk>;
> +	clock-names = "ahb", "mod";
> +	dmas = <&dma 25>, <&dma 25>;
> +	dma-names = "rx", "tx";
> +	resets = <&ahb1_rst 22>;
> +};
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 605b016..7923697 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -351,6 +351,14 @@ config MOXART_DMA
>  	help
>  	  Enable support for the MOXA ART SoC DMA controller.
>  
> +config DMA_SUN6I
> +	tristate "Allwinner A31 SoCs DMA support"
> +	depends on ARCH_SUNXI
> +	select DMA_ENGINE
> +	select DMA_VIRTUAL_CHANNELS
> +	help
> +	  Support for the DMA engine for Allwinner A31 SoCs.
> +
>  config DMA_ENGINE
>  	bool
>  
> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> index a029d0f4..18cdbad 100644
> --- a/drivers/dma/Makefile
> +++ b/drivers/dma/Makefile
> @@ -44,3 +44,4 @@ obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
>  obj-$(CONFIG_TI_CPPI41) += cppi41.o
>  obj-$(CONFIG_K3_DMA) += k3dma.o
>  obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
> +obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> new file mode 100644
> index 0000000..2649fde
> --- /dev/null
> +++ b/drivers/dma/sun6i-dma.c
> @@ -0,0 +1,960 @@
> +/*
> + * Copyright (C) 2013-2014 Allwinner Tech Co., Ltd
> + * Author: Sugar <shuge-0TFLnhJekD6UEPyfVivIlAC/G2K4zDHf@public.gmane.org>
> + *
> + * Copyright (C) 2014 Maxime Ripard
> + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/dmaengine.h>
> +#include <linux/dmapool.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_dma.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +
> +#include "virt-dma.h"
> +
> +/*
> + * There's 16 physical channels that can work in parallel.
> + *
> + * However we have 30 different endpoints for our requests.
> + *
> + * Since the channels are able to handle only an unidirectional
> + * transfer, we need to allocate more virtual channels so that
> + * everyone can grab one channel.
> + *
> + * Some devices can't work in both direction (mostly because it
> + * wouldn't make sense), so we have a bit fewer virtual channels than
> + * 2 channels per endpoints.
> + */
> +
> +#define NR_MAX_CHANNELS		16
> +#define NR_MAX_REQUESTS		30
> +#define NR_MAX_VCHANS		53
> +
> +/*
> + * Common registers
> + */
> +#define DMA_IRQ_EN(x)		((x) * 0x04)
> +#define DMA_IRQ_HALF			BIT(0)
> +#define DMA_IRQ_PKG			BIT(1)
> +#define DMA_IRQ_QUEUE			BIT(2)
> +
> +#define DMA_IRQ_CHAN_NR			8
> +#define DMA_IRQ_CHAN_WIDTH		4
> +
> +
> +#define DMA_IRQ_STAT(x)		((x) * 0x04 + 0x10)
> +
> +#define DMA_STAT		0x30
> +
> +/*
> + * Channels specific registers
> + */
> +#define DMA_CHAN_ENABLE		0x00
> +#define DMA_CHAN_ENABLE_START		BIT(0)
> +#define DMA_CHAN_ENABLE_STOP		0
> +
> +#define DMA_CHAN_PAUSE		0x04
> +#define DMA_CHAN_PAUSE_PAUSE		BIT(1)
> +#define DMA_CHAN_PAUSE_RESUME		0
> +
> +#define DMA_CHAN_LLI_ADDR	0x08
> +
> +#define DMA_CHAN_CUR_CFG	0x0c
> +#define DMA_CHAN_CFG_SRC_DRQ(x)		((x) & 0x1f)
> +#define DMA_CHAN_CFG_SRC_IO_MODE	BIT(5)
> +#define DMA_CHAN_CFG_SRC_LINEAR_MODE	(0 << 5)
> +#define DMA_CHAN_CFG_SRC_BURST(x)	(((x) & 0x3) << 7)
> +#define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
> +
> +#define DMA_CHAN_CFG_DST_DRQ(x)		(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
> +#define DMA_CHAN_CFG_DST_IO_MODE	(DMA_CHAN_CFG_SRC_IO_MODE << 16)
> +#define DMA_CHAN_CFG_DST_LINEAR_MODE	(DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
> +#define DMA_CHAN_CFG_DST_BURST(x)	(DMA_CHAN_CFG_SRC_BURST(x) << 16)
> +#define DMA_CHAN_CFG_DST_WIDTH(x)	(DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
> +
> +#define DMA_CHAN_CUR_SRC	0x10
> +
> +#define DMA_CHAN_CUR_DST	0x14
> +
> +#define DMA_CHAN_CUR_CNT	0x18
> +
> +#define DMA_CHAN_CUR_PARA	0x1c
> +
> +
> +/*
> + * Various hardware related defines
> + */
> +#define LLI_LAST_ITEM	0xfffff800
> +#define NORMAL_WAIT	8
> +#define DRQ_SDRAM	1
> +
> +/*
> + * Hardware representation of the LLI
> + *
> + * The hardware will be fed the physical address of this structure,
> + * and read its content in order to start the transfer.
> + */
> +struct sun6i_dma_lli {
> +	u32			cfg;
> +	dma_addr_t		src;
> +	dma_addr_t		dst;
> +	u32			len;
> +	u32			para;
> +	dma_addr_t		p_lli_next;
> +	struct sun6i_dma_lli	*v_lli_next;
> +} __packed;

dma_addr_t could be different depending on platform configuration. If
your hardware is using constant length of those field I think would be
better to use something reliable in that case.

> +
> +
> +struct sun6i_desc {
> +	struct virt_dma_desc	vd;
> +	dma_addr_t		p_lli;
> +	struct sun6i_dma_lli	*v_lli;
> +};
> +
> +struct sun6i_pchan {
> +	u32			idx;
> +	void __iomem		*base;
> +	struct sun6i_vchan	*vchan;
> +	struct sun6i_desc	*desc;
> +	struct sun6i_desc	*done;
> +};
> +
> +struct sun6i_vchan {
> +	struct virt_dma_chan	vc;
> +	struct list_head	node;
> +	struct dma_slave_config	cfg;
> +	struct sun6i_pchan	*phy;
> +	u8			port;
> +};
> +
> +struct sun6i_dma_dev {
> +	struct dma_device	slave;
> +	void __iomem		*base;
> +	struct clk		*clk;
> +	struct reset_control	*rstc;
> +	spinlock_t		lock;
> +	struct tasklet_struct	task;
> +	struct list_head	pending;
> +	struct dma_pool		*pool;
> +	struct sun6i_pchan	*pchans;
> +	struct sun6i_vchan	*vchans;
> +};
> +
> +static struct device *chan2dev(struct dma_chan *chan)
> +{
> +	return &chan->dev->device;
> +}
> +
> +static inline struct sun6i_dma_dev *to_sun6i_dma_dev(struct dma_device *d)
> +{
> +	return container_of(d, struct sun6i_dma_dev, slave);
> +}
> +
> +static inline struct sun6i_vchan *to_sun6i_vchan(struct dma_chan *chan)
> +{
> +	return container_of(chan, struct sun6i_vchan, vc.chan);
> +}
> +
> +static inline struct sun6i_desc *
> +to_sun6i_desc(struct dma_async_tx_descriptor *tx)
> +{
> +	return container_of(tx, struct sun6i_desc, vd.tx);
> +}
> +
> +static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev)
> +{
> +	pr_debug("Common register:\n"
> +		 "\tmask0(%04x): 0x%08x\n"
> +		 "\tmask1(%04x): 0x%08x\n"
> +		 "\tpend0(%04x): 0x%08x\n"
> +		 "\tpend1(%04x): 0x%08x\n"
> +		 "\tstats(%04x): 0x%08x\n",
> +		 DMA_IRQ_EN(0), readl(sdev->base + DMA_IRQ_EN(0)),
> +		 DMA_IRQ_EN(1), readl(sdev->base + DMA_IRQ_EN(1)),
> +		 DMA_IRQ_STAT(0), readl(sdev->base + DMA_IRQ_STAT(0)),
> +		 DMA_IRQ_STAT(1), readl(sdev->base + DMA_IRQ_STAT(1)),
> +		 DMA_STAT, readl(sdev->base + DMA_STAT));

dev_dbg() ?

> +}
> +
> +static inline void sun6i_dma_dump_chan_regs(struct sun6i_pchan *pchan)
> +{
> +	pr_debug("Chan %d reg: 0x%x\n"
> +		 "\t___en(%04x): \t0x%08x\n"
> +		 "\tpause(%04x): \t0x%08x\n"
> +		 "\tstart(%04x): \t0x%08x\n"
> +		 "\t__cfg(%04x): \t0x%08x\n"
> +		 "\t__src(%04x): \t0x%08x\n"
> +		 "\t__dst(%04x): \t0x%08x\n"
> +		 "\tcount(%04x): \t0x%08x\n"
> +		 "\t_para(%04x): \t0x%08x\n\n",
> +		 pchan->idx, __virt_to_phys((unsigned long)pchan->base),
> +		 DMA_CHAN_ENABLE,
> +		 readl(pchan->base + DMA_CHAN_ENABLE),
> +		 DMA_CHAN_PAUSE,
> +		 readl(pchan->base + DMA_CHAN_PAUSE),
> +		 DMA_CHAN_LLI_ADDR,
> +		 readl(pchan->base + DMA_CHAN_LLI_ADDR),
> +		 DMA_CHAN_CUR_CFG,
> +		 readl(pchan->base + DMA_CHAN_CUR_CFG),
> +		 DMA_CHAN_CUR_SRC,
> +		 readl(pchan->base + DMA_CHAN_CUR_SRC),
> +		 DMA_CHAN_CUR_DST,
> +		 readl(pchan->base + DMA_CHAN_CUR_DST),
> +		 DMA_CHAN_CUR_CNT,
> +		 readl(pchan->base + DMA_CHAN_CUR_CNT),
> +		 DMA_CHAN_CUR_PARA,
> +		 readl(pchan->base + DMA_CHAN_CUR_PARA));

Ditto.

> +}
> +
> +static inline u8 convert_burst(u8 maxburst)
> +{
> +	if (maxburst == 1 || maxburst > 16)
> +		return 0;
> +
> +	return ilog2(maxburst) - 1;

fls() - 1 ?

> +}
> +
> +static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width)
> +{
> +	switch (addr_width) {
> +	case DMA_SLAVE_BUSWIDTH_2_BYTES:
> +		return 1;
> +	case DMA_SLAVE_BUSWIDTH_4_BYTES:
> +		return 2;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev,
> +			       struct sun6i_dma_lli *next,
> +			       dma_addr_t next_phy,
> +			       struct sun6i_desc *txd)
> +{
> +	if ((!prev && !txd) || !next)
> +		return NULL;
> +
> +	if (!prev) {
> +		txd->p_lli = next_phy;
> +		txd->v_lli = next;
> +	} else {
> +		prev->p_lli_next = next_phy;
> +		prev->v_lli_next = next;
> +	}
> +
> +	next->p_lli_next = LLI_LAST_ITEM;
> +	next->v_lli_next = NULL;
> +
> +	return next;
> +}
> +
> +static inline void sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli,
> +				     dma_addr_t src,
> +				     dma_addr_t dst, u32 len,
> +				     struct dma_slave_config *config)
> +{
> +	u32 src_width, dst_width, src_burst, dst_burst;
> +
> +	if (!config)
> +		return;
> +
> +	src_burst = convert_burst(config->src_maxburst);
> +	dst_burst = convert_burst(config->dst_maxburst);
> +
> +	src_width = convert_buswidth(config->src_addr_width);
> +	dst_width = convert_buswidth(config->dst_addr_width);
> +
> +	lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
> +		DMA_CHAN_CFG_SRC_WIDTH(src_width) |
> +		DMA_CHAN_CFG_DST_BURST(dst_burst) |
> +		DMA_CHAN_CFG_DST_WIDTH(dst_width);
> +
> +	lli->src = src;
> +	lli->dst = dst;
> +	lli->len = len;
> +	lli->para = NORMAL_WAIT;
> +
> +}
> +
> +static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan,
> +				      struct sun6i_dma_lli *lli)
> +{
> +	dev_dbg(chan2dev(&vchan->vc.chan),
> +		"\n\tdesc:   p - 0x%08x v - 0x%08x\n"
> +		"\t\tc - 0x%08x s - 0x%08x d - 0x%08x\n"
> +		"\t\tl - 0x%08x p - 0x%08x n - 0x%08x\n",
> +		__virt_to_phys((unsigned long)lli), (u32)lli,
> +		lli->cfg, lli->src, lli->dst,
> +		lli->len, lli->para, lli->p_lli_next);
> +}
> +
> +static void sun6i_dma_free_desc(struct virt_dma_desc *vd)
> +{
> +	struct sun6i_desc *txd = to_sun6i_desc(&vd->tx);
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vd->tx.chan->device);
> +	struct sun6i_dma_lli *v_lli, *v_next;
> +	dma_addr_t p_lli, p_next;
> +
> +	if (unlikely(!txd))
> +		return;
> +
> +	p_lli = txd->p_lli;
> +	v_lli = txd->v_lli;
> +
> +	while (v_lli) {
> +		v_next = v_lli->v_lli_next;
> +		p_next = v_lli->p_lli_next;
> +
> +		dma_pool_free(sdev->pool, v_lli, p_lli);
> +
> +		v_lli = v_next;
> +		p_lli = p_next;
> +	}
> +
> +	kfree(txd);
> +}
> +
> +static int sun6i_dma_terminate_all(struct sun6i_vchan *vchan)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
> +	struct sun6i_pchan *pchan = vchan->phy;
> +	unsigned long flags;
> +	LIST_HEAD(head);
> +
> +	spin_lock(&sdev->lock);
> +	list_del_init(&vchan->node);
> +	spin_unlock(&sdev->lock);
> +
> +	spin_lock_irqsave(&vchan->vc.lock, flags);
> +
> +	vchan_get_all_descriptors(&vchan->vc, &head);
> +
> +	if (pchan) {
> +		writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE);
> +		writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE);
> +
> +		vchan->phy = NULL;
> +		pchan->vchan = NULL;
> +		pchan->desc = NULL;
> +		pchan->done = NULL;
> +	}
> +
> +	spin_unlock_irqrestore(&vchan->vc.lock, flags);
> +
> +	vchan_dma_desc_free_list(&vchan->vc, &head);
> +
> +	return 0;
> +}
> +
> +static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
> +	struct virt_dma_desc *desc = vchan_next_desc(&vchan->vc);
> +	struct sun6i_pchan *pchan = vchan->phy;
> +	u32 irq_val, irq_reg, irq_offset;
> +
> +	if (!pchan)
> +		return -EAGAIN;
> +
> +	if (!desc) {
> +		pchan->desc = NULL;
> +		pchan->done = NULL;
> +		return -EAGAIN;
> +	}
> +
> +	list_del(&desc->node);
> +
> +	pchan->desc = to_sun6i_desc(&desc->tx);
> +	pchan->done = NULL;
> +
> +	sun6i_dma_dump_lli(vchan, pchan->desc->v_lli);
> +
> +	irq_reg = pchan->idx / DMA_IRQ_CHAN_NR;
> +	irq_offset = pchan->idx % DMA_IRQ_CHAN_NR;
> +
> +	irq_val = readl(sdev->base + DMA_IRQ_EN(irq_offset));
> +	irq_val |= DMA_IRQ_QUEUE << (irq_offset * DMA_IRQ_CHAN_WIDTH);
> +	writel(irq_val, sdev->base + DMA_IRQ_EN(irq_offset));
> +
> +	writel(pchan->desc->p_lli, pchan->base + DMA_CHAN_LLI_ADDR);
> +	writel(DMA_CHAN_ENABLE_START, pchan->base + DMA_CHAN_ENABLE);
> +
> +	sun6i_dma_dump_com_regs(sdev);
> +	sun6i_dma_dump_chan_regs(pchan);
> +
> +	return 0;
> +}
> +
> +static void sun6i_dma_tasklet(unsigned long data)
> +{
> +	struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
> +	struct sun6i_vchan *vchan;
> +	struct sun6i_pchan *pchan;
> +	unsigned int pchan_alloc = 0;
> +	unsigned int pchan_idx;
> +
> +	list_for_each_entry(vchan, &sdev->slave.channels, vc.chan.device_node) {
> +		spin_lock_irq(&vchan->vc.lock);
> +
> +		pchan = vchan->phy;
> +
> +		if (pchan && pchan->done) {
> +			if (sun6i_dma_start_desc(vchan)) {
> +				/*
> +				 * No current txd associated with this channel
> +				 */
> +				dev_dbg(sdev->slave.dev, "pchan %u: free\n",
> +					pchan->idx);
> +
> +				/* Mark this channel free */
> +				vchan->phy = NULL;
> +				pchan->vchan = NULL;
> +			}
> +		}
> +		spin_unlock_irq(&vchan->vc.lock);
> +	}
> +
> +	spin_lock_irq(&sdev->lock);
> +	for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
> +		pchan = &sdev->pchans[pchan_idx];
> +
> +		if (pchan->vchan == NULL && !list_empty(&sdev->pending)) {
> +			vchan = list_first_entry(&sdev->pending,
> +						 struct sun6i_vchan, node);
> +
> +			/* remove from pending channels */

Keep style in the comments. Like capital letter to start sentence with.

> +			list_del_init(&vchan->node);
> +			pchan_alloc |= BIT(pchan_idx);
> +
> +			/* Mark this channel allocated */
> +			pchan->vchan = vchan;
> +			vchan->phy = pchan;
> +			dev_dbg(sdev->slave.dev, "pchan %u: alloc vchan %p\n",
> +				pchan->idx, &vchan->vc);
> +		}
> +	}
> +	spin_unlock_irq(&sdev->lock);
> +
> +	for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
> +		if (pchan_alloc & BIT(pchan_idx)) {
> +			pchan = sdev->pchans + pchan_idx;
> +			vchan = pchan->vchan;
> +			if (vchan) {
> +				spin_lock_irq(&vchan->vc.lock);
> +				sun6i_dma_start_desc(vchan);
> +				spin_unlock_irq(&vchan->vc.lock);
> +			}
> +		}
> +	}
> +}
> +
> +static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
> +{
> +	struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)dev_id;
> +	struct sun6i_vchan *vchan;
> +	struct sun6i_pchan *pchan;
> +	int i, j, ret = 0;
> +	u32 status;
> +
> +	for (i = 0; i < 2; i++) {
> +		status = readl(sdev->base + DMA_IRQ_STAT(i));
> +		if (!status) {
> +			ret |= IRQ_NONE;

Maybe move this to definition block.

> +			continue;
> +		}
> +
> +		dev_dbg(sdev->slave.dev, "DMA irq status %s: 0x%x\n",
> +			i ? "high" : "low", status);
> +
> +		writel(status, sdev->base + DMA_IRQ_STAT(i));
> +
> +		for (j = 0; (j < 8) && status; j++) {
> +			if (status & DMA_IRQ_QUEUE) {
> +				pchan = sdev->pchans + j;
> +				vchan = pchan->vchan;
> +
> +				if (vchan) {
> +					unsigned long flags;
> +
> +					spin_lock_irqsave(&vchan->vc.lock,
> +							  flags);
> +					vchan_cookie_complete(&pchan->desc->vd);
> +					pchan->done = pchan->desc;
> +					spin_unlock_irqrestore(&vchan->vc.lock,
> +							       flags);
> +				}
> +			}
> +
> +			status = status >> 4;
> +		}
> +
> +		ret |= IRQ_HANDLED;

In case one is handled, another is not, what you have to do?

> +	}
> +
> +	if (ret == IRQ_HANDLED)
> +		tasklet_schedule(&sdev->task);
> +
> +	return ret;
> +}
> +
> +static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
> +		struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
> +		size_t len, unsigned long flags)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
> +	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
> +	struct dma_slave_config *sconfig = &vchan->cfg;
> +	struct sun6i_dma_lli *v_lli;
> +	struct sun6i_desc *txd;
> +	dma_addr_t p_lli;
> +
> +	dev_dbg(chan2dev(chan),
> +		"%s; chan: %d, dest: 0x%08x, src: 0x%08x, len: 0x%08x. flags: 0x%08lx\n",
> +		__func__, vchan->vc.chan.chan_id, dest, src, len, flags);
> +
> +	if (!len)
> +		return NULL;
> +
> +	txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
> +	if (!txd)
> +		return NULL;
> +
> +	v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
> +	if (!v_lli) {
> +		dev_err(sdev->slave.dev, "Failed to alloc lli memory\n");
> +		kfree(txd);
> +		return NULL;
> +	}
> +
> +	sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig);
> +	v_lli->cfg |= DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
> +		DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
> +		DMA_CHAN_CFG_DST_LINEAR_MODE |
> +		DMA_CHAN_CFG_SRC_LINEAR_MODE;
> +
> +	sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
> +
> +	sun6i_dma_dump_lli(vchan, v_lli);
> +
> +	return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
> +}
> +
> +static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
> +		struct dma_chan *chan, struct scatterlist *sgl,
> +		unsigned int sg_len, enum dma_transfer_direction dir,
> +		unsigned long flags, void *context)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
> +	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
> +	struct dma_slave_config *sconfig = &vchan->cfg;
> +	struct sun6i_dma_lli *v_lli, *prev = NULL;
> +	struct sun6i_desc *txd;
> +	struct scatterlist *sg;
> +	dma_addr_t p_lli;
> +	int i;
> +
> +	if (!sgl)
> +		return NULL;
> +
> +	txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
> +	if (!txd)
> +		return NULL;
> +
> +	for_each_sg(sgl, sg, sg_len, i) {
> +		v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
> +		if (!v_lli) {
> +			kfree(txd);
> +			return NULL;
> +		}
> +
> +		if (dir == DMA_MEM_TO_DEV) {
> +			sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg),
> +					  sconfig->dst_addr, sg_dma_len(sg),
> +					  sconfig);
> +			v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE |
> +				DMA_CHAN_CFG_SRC_LINEAR_MODE |
> +				DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
> +				DMA_CHAN_CFG_DST_DRQ(vchan->port);
> +
> +			dev_dbg(chan2dev(chan), "%s; chan: %d, dest: 0x%08x, "
> +				"src: 0x%08x, len: 0x%08x. flags: 0x%08lx\n",
> +				__func__, vchan->vc.chan.chan_id,
> +				sconfig->dst_addr, sg_dma_address(sg),
> +				sg_dma_len(sg), flags);
> +
> +		} else if (dir == DMA_DEV_TO_MEM) {
> +			sun6i_dma_cfg_lli(v_lli, sconfig->src_addr,
> +					  sg_dma_address(sg), sg_dma_len(sg),
> +					  sconfig);
> +			v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE |
> +				DMA_CHAN_CFG_SRC_IO_MODE |
> +				DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
> +				DMA_CHAN_CFG_SRC_DRQ(vchan->port);
> +
> +			dev_dbg(chan2dev(chan), "%s; chan: %d, dest: 0x%08x, "
> +				"src: 0x%08x, len: 0x%08x. flags: 0x%08lx\n",
> +				__func__, vchan->vc.chan.chan_id,
> +				sg_dma_address(sg), sconfig->src_addr,
> +				sg_dma_len(sg), flags);
> +		}
> +
> +		prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
> +	}
> +
> +#ifdef DEBUG
> +	dev_dbg(chan2dev(chan), "First: 0x%08x\n", txd->p_lli);
> +	for (prev = txd->v_lli; prev != NULL; prev = prev->v_lli_next)
> +		sun6i_dma_dump_lli(vchan, prev);
> +#endif
> +
> +	return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
> +}
> +
> +static int sun6i_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
> +		       unsigned long arg)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
> +	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
> +	struct sun6i_pchan *pchan = vchan->phy;
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	switch (cmd) {
> +	case DMA_RESUME:
> +		dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc);
> +
> +		spin_lock_irqsave(&vchan->vc.lock, flags);
> +
> +		if (pchan) {
> +			writel(DMA_CHAN_PAUSE_RESUME,
> +			       pchan->base + DMA_CHAN_PAUSE);
> +		} else if (!list_empty(&vchan->vc.desc_issued)) {
> +			spin_lock(&sdev->lock);
> +			list_add_tail(&vchan->node, &sdev->pending);
> +			spin_unlock(&sdev->lock);
> +		}
> +
> +		spin_unlock_irqrestore(&vchan->vc.lock, flags);
> +		break;
> +
> +	case DMA_PAUSE:
> +		dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc);
> +
> +		if (pchan) {
> +			writel(DMA_CHAN_PAUSE_PAUSE,
> +			       pchan->base + DMA_CHAN_PAUSE);
> +		} else {
> +			spin_lock(&sdev->lock);
> +			list_del_init(&vchan->node);
> +			spin_unlock(&sdev->lock);
> +		}
> +		break;
> +
> +	case DMA_TERMINATE_ALL:
> +		ret = sun6i_dma_terminate_all(vchan);
> +		break;
> +	case DMA_SLAVE_CONFIG:
> +		memcpy(&vchan->cfg, (struct dma_slave_config *)arg,
> +		       sizeof(struct dma_slave_config));
> +		break;
> +	default:
> +		ret = -ENXIO;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan,
> +					   dma_cookie_t cookie,
> +					   struct dma_tx_state *state)
> +{
> +	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
> +	struct sun6i_pchan *pchan = vchan->phy;
> +	struct sun6i_dma_lli *lli;
> +	struct virt_dma_desc *vd;
> +	struct sun6i_desc *txd;
> +	enum dma_status ret;
> +	unsigned long flags;
> +	size_t bytes = 0;
> +
> +	ret = dma_cookie_status(chan, cookie, state);
> +	if (ret == DMA_COMPLETE)
> +		return ret;
> +
> +	spin_lock_irqsave(&vchan->vc.lock, flags);
> +
> +	vd = vchan_find_desc(&vchan->vc, cookie);
> +	txd = to_sun6i_desc(&vd->tx);
> +
> +	if (vd) {
> +		for (lli = txd->v_lli; lli != NULL; lli = lli->v_lli_next)
> +			bytes += lli->len;
> +	} else if (!pchan || !pchan->desc) {
> +		bytes = 0;
> +	} else {
> +		bytes = readl(pchan->base + DMA_CHAN_CUR_CNT);
> +	}
> +
> +	spin_unlock_irqrestore(&vchan->vc.lock, flags);
> +
> +	dma_set_residue(state, bytes);
> +
> +	return ret;
> +}
> +
> +static void sun6i_dma_issue_pending(struct dma_chan *chan)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
> +	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&vchan->vc.lock, flags);
> +
> +	if (vchan_issue_pending(&vchan->vc)) {
> +		spin_lock(&sdev->lock);
> +
> +		if (!vchan->phy) {
> +			if (list_empty(&vchan->node)) {
> +				list_add_tail(&vchan->node, &sdev->pending);
> +				tasklet_schedule(&sdev->task);
> +				dev_dbg(chan2dev(chan), "vchan %p: issued\n",
> +					&vchan->vc);
> +			}
> +		}
> +
> +		spin_unlock(&sdev->lock);
> +	} else {
> +		dev_dbg(chan2dev(chan), "vchan %p: nothing to issue\n",
> +			&vchan->vc);
> +	}
> +
> +	spin_unlock_irqrestore(&vchan->vc.lock, flags);
> +}
> +
> +static int sun6i_dma_alloc_chan_resources(struct dma_chan *chan)
> +{
> +	return 0;
> +}
> +
> +static void sun6i_dma_free_chan_resources(struct dma_chan *chan)
> +{
> +	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
> +	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&sdev->lock, flags);
> +	list_del_init(&vchan->node);
> +	spin_unlock_irqrestore(&sdev->lock, flags);
> +
> +	vchan_free_chan_resources(&vchan->vc);
> +}
> +
> +static inline void sun6i_dma_free(struct sun6i_dma_dev *sdc)
> +{
> +	int i;
> +
> +	for (i = 0; i < NR_MAX_VCHANS; i++) {
> +		struct sun6i_vchan *vchan = &sdc->vchans[i];
> +
> +		list_del(&vchan->vc.chan.device_node);
> +		tasklet_kill(&vchan->vc.task);
> +	}
> +
> +	tasklet_kill(&sdc->task);
> +}
> +
> +static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec,
> +					   struct of_dma *ofdma)
> +{
> +	struct sun6i_dma_dev *sdev = ofdma->of_dma_data;
> +	struct sun6i_vchan *vchan;
> +	struct dma_chan *chan;
> +	u8 port = dma_spec->args[0];
> +
> +	if (port > NR_MAX_REQUESTS)
> +		return NULL;
> +
> +	chan = dma_get_any_slave_channel(&sdev->slave);
> +	if (!chan)
> +		return NULL;
> +
> +	vchan = to_sun6i_vchan(chan);
> +	vchan->port = port;
> +
> +	return chan;
> +}
> +
> +static int sun6i_dma_probe(struct platform_device *pdev)
> +{
> +	struct sun6i_dma_dev *sdc;
> +	struct resource *res;
> +	int irq;
> +	int ret, i;
> +
> +	sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL);
> +	if (!sdc)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	sdc->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(sdc->base))
> +		return PTR_ERR(sdc->base);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	ret = devm_request_irq(&pdev->dev, irq, sun6i_dma_interrupt, 0,
> +			       dev_name(&pdev->dev), sdc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot request IRQ\n");
> +		return ret;
> +	}
> +
> +	sdc->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(sdc->clk)) {
> +		dev_err(&pdev->dev, "No clock specified\n");
> +		return PTR_ERR(sdc->clk);
> +	}
> +
> +	sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
> +	if (IS_ERR(sdc->rstc)) {
> +		dev_err(&pdev->dev, "No reset controller specified\n");
> +		return PTR_ERR(sdc->rstc);
> +	}
> +
> +	sdc->pool = dma_pool_create(dev_name(&pdev->dev), &pdev->dev,
> +					sizeof(struct sun6i_dma_lli), 4, 0);

dmam_pool_create()

> +	if (!sdc->pool) {
> +		dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
> +		return -ENOMEM;
> +	}
> +
> +	platform_set_drvdata(pdev, sdc);
> +	INIT_LIST_HEAD(&sdc->pending);
> +	spin_lock_init(&sdc->lock);
> +
> +	dma_cap_set(DMA_PRIVATE, sdc->slave.cap_mask);
> +	dma_cap_set(DMA_MEMCPY, sdc->slave.cap_mask);
> +	dma_cap_set(DMA_SLAVE, sdc->slave.cap_mask);
> +
> +	INIT_LIST_HEAD(&sdc->slave.channels);
> +	sdc->slave.device_alloc_chan_resources	= sun6i_dma_alloc_chan_resources;
> +	sdc->slave.device_free_chan_resources	= sun6i_dma_free_chan_resources;
> +	sdc->slave.device_tx_status		= sun6i_dma_tx_status;
> +	sdc->slave.device_issue_pending		= sun6i_dma_issue_pending;
> +	sdc->slave.device_prep_slave_sg		= sun6i_dma_prep_slave_sg;
> +	sdc->slave.device_prep_dma_memcpy	= sun6i_dma_prep_dma_memcpy;
> +	sdc->slave.device_control		= sun6i_dma_control;
> +	sdc->slave.chancnt			= NR_MAX_VCHANS;
> +
> +	sdc->slave.dev = &pdev->dev;
> +
> +	sdc->pchans = devm_kzalloc(&pdev->dev,
> +				   NR_MAX_CHANNELS * sizeof(struct sun6i_pchan),
> +				   GFP_KERNEL);
> +	if (!sdc->pchans) {
> +		ret = -ENOMEM;
> +		goto err_dma_pool_destroy;
> +	}
> +
> +	sdc->vchans = devm_kzalloc(&pdev->dev,
> +				   NR_MAX_VCHANS * sizeof(struct sun6i_vchan),
> +				   GFP_KERNEL);
> +	if (!sdc->vchans) {
> +		ret = -ENOMEM;
> +		goto err_dma_pool_destroy;
> +	}
> +
> +	tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
> +
> +	for (i = 0; i < NR_MAX_CHANNELS; i++) {
> +		struct sun6i_pchan *pchan = &sdc->pchans[i];
> +
> +		pchan->idx = i;
> +		pchan->base = sdc->base + 0x100 + i * 0x40;
> +	}
> +
> +	for (i = 0; i < NR_MAX_VCHANS; i++) {
> +		struct sun6i_vchan *vchan = &sdc->vchans[i];
> +
> +		INIT_LIST_HEAD(&vchan->node);
> +		vchan->vc.desc_free = sun6i_dma_free_desc;
> +		vchan_init(&vchan->vc, &sdc->slave);
> +	}
> +
> +	reset_control_deassert(sdc->rstc);
> +
> +	clk_prepare_enable(sdc->clk);

Would you like to check an return code here?

> +
> +	ret = dma_async_device_register(&sdc->slave);
> +	if (ret) {
> +		dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
> +		goto err_clk_disable;
> +	}
> +
> +	ret = of_dma_controller_register(pdev->dev.of_node, sun6i_dma_of_xlate,
> +					 sdc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "of_dma_controller_register failed\n");
> +		goto err_dma_unregister;
> +	}
> +
> +	return 0;
> +
> +err_dma_unregister:
> +	dma_async_device_unregister(&sdc->slave);
> +err_clk_disable:
> +	clk_disable_unprepare(sdc->clk);
> +	reset_control_assert(sdc->rstc);
> +	sun6i_dma_free(sdc);
> +err_dma_pool_destroy:
> +	dma_pool_destroy(sdc->pool);
> +	return ret;
> +}
> +
> +static int sun6i_dma_remove(struct platform_device *pdev)
> +{
> +	struct sun6i_dma_dev *sdc = platform_get_drvdata(pdev);
> +
> +	of_dma_controller_free(pdev->dev.of_node);
> +	dma_async_device_unregister(&sdc->slave);
> +
> +	clk_disable_unprepare(sdc->clk);
> +	reset_control_assert(sdc->rstc);
> +
> +	sun6i_dma_free(sdc);
> +
> +	dma_pool_destroy(sdc->pool);
> +
> +	return 0;
> +}
> +
> +static struct of_device_id sun6i_dma_match[] = {
> +	{ .compatible = "allwinner,sun6i-a31-dma" }
> +};
> +
> +static struct platform_driver sun6i_dma_driver = {
> +	.probe		= sun6i_dma_probe,
> +	.remove		= sun6i_dma_remove,
> +	.driver = {
> +		.name		= "sun6i-dma",
> +		.of_match_table	= sun6i_dma_match,
> +	},
> +};
> +module_platform_driver(sun6i_dma_driver);
> +
> +MODULE_DESCRIPTION("Allwinner A31 DMA Controller Driver");
> +MODULE_AUTHOR("Sugar <shuge-0TFLnhJekD6UEPyfVivIlAC/G2K4zDHf@public.gmane.org>");
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>");
> +MODULE_LICENSE("GPL");


-- 
Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Intel Finland Oy

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

^ permalink raw reply

* [PATCH v2 1/3] ata: ahci_st: Provide DT bindings for ST's SATA implementation
From: Lee Jones @ 2014-02-25 11:41 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	DCG_UPD_stlinux_kernel-nkJGhpqTU55BDgjK7y7TUQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Srinivas Kandagatla

Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
Acked-by: Alexandre Torgue <alexandre.torgue-qxv4g6HH51o@public.gmane.org>
Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/devicetree/bindings/ata/ahci-st.txt | 31 +++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/ata/ahci-st.txt

diff --git a/Documentation/devicetree/bindings/ata/ahci-st.txt b/Documentation/devicetree/bindings/ata/ahci-st.txt
new file mode 100644
index 0000000..1b69fa9
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/ahci-st.txt
@@ -0,0 +1,31 @@
+STMicroelectronics STi SATA controller
+
+This binding describes a SATA device.
+
+Required properties:
+ - compatible	   : Must be "st,ahci"
+ - reg		   : Physical base addresses and length of register sets
+ - interrupts	   : Interrupt associated with the SATA device
+ - interrupt-names :   Associated name must be; "hostc"
+ - resets	   : The power-down and soft-reset lines of SATA IP
+ - reset-names	   :   Associated names must be; "pwr-dwn" and "sw-rst"
+ - clocks	   : The phandle for the clock
+ - clock-names	   :   Associated name must be; "ahci_clk"
+ - phys		   : The phandle for the PHY device
+ - phy-names	   :   Associated name must be; "ahci_phy"
+
+Example:
+
+	sata0: sata@fe380000 {
+		compatible      = "st,ahci";
+		reg             = <0xfe380000 0x1000>;
+		interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
+		interrupt-names = "hostc";
+		phys	        = <&miphy365x_phy MIPHY_PORT_0 MIPHY_TYPE_SATA>;
+		phy-names       = "ahci_phy";
+		resets	        = <&powerdown STIH416_SATA0_POWERDOWN>,
+				  <&softreset STIH416_SATA0_SOFTRESET>;
+		reset-names     = "pwr-dwn", "sw-rst";
+		clocks	        = <&CLK_S_ICN_REG_0>;
+		clock-names     = "ahci_clk";
+	};
-- 
1.8.3.2

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

^ permalink raw reply related

* [PATCH v2 2/3] ARM: DT: STi: Add DT node for ST's SATA device
From: Lee Jones @ 2014-02-25 11:41 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: lee.jones, DCG_UPD_stlinux_kernel, devicetree,
	Srinivas Kandagatla
In-Reply-To: <1393328481-7251-1-git-send-email-lee.jones@linaro.org>

Cc: devicetree@vger.kernel.org
Cc: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Alexandre Torgue <alexandre.torgue@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/boot/dts/stih416-b2020-revE.dts |  4 ++++
 arch/arm/boot/dts/stih416-b2020.dts      |  4 ++++
 arch/arm/boot/dts/stih416.dtsi           | 16 ++++++++++++++++
 3 files changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/stih416-b2020-revE.dts b/arch/arm/boot/dts/stih416-b2020-revE.dts
index 693d0ec..7350a86 100644
--- a/arch/arm/boot/dts/stih416-b2020-revE.dts
+++ b/arch/arm/boot/dts/stih416-b2020-revE.dts
@@ -37,5 +37,9 @@
 			st,pcie-tx-pol-inv;
 			st,sata-gen = <3>;
 		};
+
+		sata0: sata@fe380000{
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih416-b2020.dts b/arch/arm/boot/dts/stih416-b2020.dts
index fd9cbad..ebd784b 100644
--- a/arch/arm/boot/dts/stih416-b2020.dts
+++ b/arch/arm/boot/dts/stih416-b2020.dts
@@ -18,5 +18,9 @@
 			st,pcie_tx_pol_inv = <1>;
 			st,sata_gen = "gen3";
 		};
+
+		sata0: sata@fe380000{
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
index 0d3f59c..313d4fd 100644
--- a/arch/arm/boot/dts/stih416.dtsi
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -205,5 +205,21 @@
 			#phy-cells 	= <2>;
 			st,syscfg  	= <&syscfg_rear>;
 		};
+
+		sata0: sata@fe380000 {
+			compatible      = "st,ahci";
+			reg             = <0xfe380000 0x1000>;
+			interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
+			interrupt-names = "hostc";
+			phys	        = <&miphy365x_phy MIPHY_PORT_0 MIPHY_TYPE_SATA>;
+			phy-names       = "sata-phy";
+			resets	        = <&powerdown STIH416_SATA0_POWERDOWN>,
+					  <&softreset STIH416_SATA0_SOFTRESET>;
+			reset-names     = "pwr-dwn", "sw-rst";
+			clock-names     = "ahci_clk";
+			clocks	        = <&CLK_S_ICN_REG_0>;
+
+			status	        = "disabled";
+		};
 	};
 };
-- 
1.8.3.2

^ permalink raw reply related

* Re: [PATCH 1/1] ARM: Exynos: Add generic compatible string
From: Arnd Bergmann @ 2014-02-25 11:42 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Sachin Kamat, Tomasz Figa, Kukjin Kim, Tomasz Figa,
	linux-arm-kernel, Mark Rutland, devicetree@vger.kernel.org,
	Ian Campbell, Rob Herring, Grant Likely, linux-samsung-soc
In-Reply-To: <CAOesGMiZXKRbrbmvKs4pF7HiXM1hsGjzbFUQmJ-n5-nar5uMBw@mail.gmail.com>

On Tuesday 25 February 2014, Olof Johansson wrote:
> I disagree. I don't know what Samsung has in mind, but the revision of
> the CPU doesn't have all that much to do with the rest of the SoC.
> It's quite likely that some vendors (maybe not Samsung, but the same
> concept applies) will ship 64-bit SoCs that are very similar to their
> preceding 32-bit ones, same IP, similar busses, etc. I'm pretty sure
> at least some vendors will do very close to that.

Right.

> So, if EXYNOS4 and EXYNOS5 can share a compatible value when they use
> different CPUs, then there's no reason that whatever future 64-bit
> ones can also share it.

How about putting both 'samsung,exynos' and 'samsung,exynos4' in DT then
and having the platform code match exynos4 and exynos5 but not exynos?

That way, I think we are consistent and future-proof. Any code that needs
to know if it's running on some exynos version can just check for the
'samsung,exynos' compatible value and that will work on both arm32 and
arm64. Also, if we ever decide we want to run a 32-bit kernel on a 64-bit
exynos, we can just add 'samsung,exynos6' (or whatever number that will
be) to the list.

My usual disclaimer for this: You should never ever consider actually
running a 32-bit kernel on a 64-bit CPU, but at the same time there
shouldn't be any reason why it won't work either, given that we require
arm64 based systems to have all SoC specific code in drivers and we
can use the same drivers on arm32.

	Arnd

^ permalink raw reply

* [PATCH v8 0/6] ARM: rockchip: add smp functionality
From: Heiko Stübner @ 2014-02-25 11:44 UTC (permalink / raw)
  To: linux-arm-kernel@lists.infradead.org
  Cc: Mark Rutland, devicetree, Pawel Moll, Stephen Warren,
	Greg Kroah-Hartman, Ian Campbell, linux-kernel, arm,
	Philipp Zabel, Grant Likely

This series enables the use of the additional cores on Rockchip
Cortex-A9 SoCs.

To achieve this, add the scu, the needed sram and power-management-unit.

Tested on both a BQ Curie2 (rk3066a / dual core) and
on a Radxa Rock (rk3188 / quad core).

As this version again involves bigger changes to the way reserved sram-
regions are handled, I've dropped the ACKs I had for binding and driver
changes again and therefore would be very happy if I could get new ones
if applicable (dt-maintainers and Philipp Zabel for sram.c).


changes since v7:
- move reserved sram regions to be described through subnodes, similar
  to the general memory-reserve bindings, as suggested by Grant Likely.

changes since v6:
- address comments from Mark Rutland
  - using of_property_read_u32_index instead of parsing the list manually
  - include v4 of "of: add functions to count number of elements in a property"
    to not have to count property-elements manually anymore

changes since v5:
- Grant Likely liked it better to "specify reserved regions of the
  memory instead of the valid ranges", so go back to the mmio-sram-reserved
  property originally suggested by Rob Herring

changes since v4:
- rebase on top of the recent rk3188 board support
- implement suggestion from Matt Sealey in moving the sram-limit from
  marking reserved regions to marking available regions - hopefully
  I got the usage right 
- remove __CPUINIT as suggested by Fabio Estevam

changes since v3:
- address comments from Rob Herring:
  - split the gathering of the reserve-data into a separate loop
  - spelling and style fixes
- first patch only included for reference, already part of the
  char-misc git tree

changes since v2:
- rework the sram allocation following the suggestion from Philipp Zabel

changes since v1:
- add reserved block feature for mmio-sram, to not use two logical
  sram nodes
- the sram content is kept intact while the device is running, so
  copying the trampoline is only needed once

Heiko Stuebner (6):
  dt-bindings: sram: describe option to reserve parts of the memory
  misc: sram: implement reserved sram areas
  ARM: rockchip: add snoop-control-unit
  ARM: rockchip: add sram dt nodes and documentation
  ARM: rockchip: add power-management-unit
  ARM: rockchip: add smp bringup code

 .../devicetree/bindings/arm/rockchip/pmu.txt       |  16 ++
 .../devicetree/bindings/arm/rockchip/smp-sram.txt  |  30 ++++
 Documentation/devicetree/bindings/misc/sram.txt    |  33 ++++
 arch/arm/boot/dts/rk3066a.dtsi                     |  13 ++
 arch/arm/boot/dts/rk3188.dtsi                      |  13 ++
 arch/arm/boot/dts/rk3xxx.dtsi                      |  10 ++
 arch/arm/mach-rockchip/Kconfig                     |   1 +
 arch/arm/mach-rockchip/Makefile                    |   1 +
 arch/arm/mach-rockchip/core.h                      |  22 +++
 arch/arm/mach-rockchip/headsmp.S                   |  30 ++++
 arch/arm/mach-rockchip/platsmp.c                   | 184 +++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c                  |   2 +
 drivers/misc/sram.c                                | 125 +++++++++++++-
 13 files changed, 473 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu.txt
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt
 create mode 100644 arch/arm/mach-rockchip/core.h
 create mode 100644 arch/arm/mach-rockchip/headsmp.S
 create mode 100644 arch/arm/mach-rockchip/platsmp.c

-- 
1.8.5.3

^ permalink raw reply

* [PATCH v8 1/6] dt-bindings: sram: describe option to reserve parts of the memory
From: Heiko Stübner @ 2014-02-25 11:45 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
  Cc: arm-DgEjT+Ai2ygdnm+yROfE0A, Grant Likely, Rob Herring,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Philipp Zabel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Greg Kroah-Hartman,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell
In-Reply-To: <21117503.1c6iOkvYSr@phil>

Some SoCs need parts of their sram for special purposes. So while being part
of the peripheral, it should not be part of the genpool controlling the sram.

Therefore add the option to define reserved regions as subnodes of the
sram-node similar to defining reserved global memory regions.

Originally
Suggested-by: Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Using subnodes for reserved regions
Suggested-by: Grant Likely <grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
Tested-by: Ulrich Prinz <ulrich.prinz-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 Documentation/devicetree/bindings/misc/sram.txt | 33 +++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/Documentation/devicetree/bindings/misc/sram.txt b/Documentation/devicetree/bindings/misc/sram.txt
index 4d0a00e..2d83758 100644
--- a/Documentation/devicetree/bindings/misc/sram.txt
+++ b/Documentation/devicetree/bindings/misc/sram.txt
@@ -8,9 +8,42 @@ Required properties:
 
 - reg : SRAM iomem address range
 
+Reserving sram areas:
+---------------------
+
+Each child of the sram node specifies a region of reserved memory. Each
+child node should use a 'reg' property to specify a specific range of
+reserved memory.
+
+Following the generic-names recommended practice, node names should
+reflect the purpose of the node. Unit address (@<address>) should be
+appended to the name.
+
+Required properties in the sram node:
+
+- #address-cells, #size-cells : should use the same values as the root node
+- ranges : standard definition, should be empty
+
+Required properties in the area nodes:
+
+- reg : iomem address range
+
+Optional properties in the area nodes:
+
+- compatible : standard definition
+
 Example:
 
 sram: sram@5c000000 {
 	compatible = "mmio-sram";
 	reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
+
+	#adress-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	smp-sram@5c000100 {
+		compatible = "socvendor,smp-sram";
+		reg = <0x5c000100 0x50>;
+	};
 };
-- 
1.8.5.3


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

^ permalink raw reply related

* [PATCH v8 2/6] misc: sram: implement reserved sram areas
From: Heiko Stübner @ 2014-02-25 11:46 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
  Cc: arm-DgEjT+Ai2ygdnm+yROfE0A, Grant Likely, Rob Herring,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Philipp Zabel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Greg Kroah-Hartman,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell
In-Reply-To: <21117503.1c6iOkvYSr@phil>

This implements support for defining reserved areas as subnodes,
to keep the genpool from using these.

Suggested-by: Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
Tested-by: Ulrich Prinz <ulrich.prinz-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 drivers/misc/sram.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 118 insertions(+), 7 deletions(-)

diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index afe66571..674b0cd 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -24,6 +24,9 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -36,14 +39,35 @@ struct sram_dev {
 	struct clk *clk;
 };
 
+struct sram_reserve {
+	struct list_head list;
+	u32 start;
+	u32 size;
+};
+
+static int sram_reserve_cmp(void *priv, struct list_head *a,
+					struct list_head *b)
+{
+	struct sram_reserve *ra = list_entry(a, struct sram_reserve, list);
+	struct sram_reserve *rb = list_entry(b, struct sram_reserve, list);
+
+	return ra->start - rb->start;
+}
+
 static int sram_probe(struct platform_device *pdev)
 {
 	void __iomem *virt_base;
 	struct sram_dev *sram;
 	struct resource *res;
-	unsigned long size;
+	struct device_node *np = pdev->dev.of_node, *child;
+	unsigned long size, cur_start, cur_size;
+	struct sram_reserve *rblocks, *block;
+	struct list_head reserve_list;
+	unsigned int nblocks;
 	int ret;
 
+	INIT_LIST_HEAD(&reserve_list);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	virt_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(virt_base))
@@ -65,19 +89,106 @@ static int sram_probe(struct platform_device *pdev)
 	if (!sram->pool)
 		return -ENOMEM;
 
-	ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base,
-				res->start, size, -1);
-	if (ret < 0) {
-		if (sram->clk)
-			clk_disable_unprepare(sram->clk);
-		return ret;
+	/*
+	 * We need an additional block to mark the end of the memory region
+	 * after the reserved blocks from the dt are processed.
+	 */
+	nblocks = (np) ? of_get_available_child_count(np) + 1 : 1;
+	rblocks = kmalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL);
+	if (!rblocks) {
+		ret = -ENOMEM;
+		goto err_alloc;
 	}
 
+	block = &rblocks[0];
+	for_each_available_child_of_node(np, child) {
+		struct resource child_res;
+
+		ret = of_address_to_resource(child, 0, &child_res);
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"could not get address for node %s\n",
+				child->full_name);
+			goto err_chunks;
+		}
+
+		if (child_res.start < res->start || child_res.end > res->end) {
+			dev_err(&pdev->dev,
+				"reserved block %s outside the sram area\n",
+				child->full_name);
+			ret = -EINVAL;
+			goto err_chunks;
+		}
+
+		block->start = child_res.start - res->start;
+		block->size = resource_size(&child_res);
+		list_add_tail(&block->list, &reserve_list);
+
+		dev_dbg(&pdev->dev, "found reserved block 0x%x-0x%x\n",
+			block->start,
+			block->start + block->size);
+
+		block++;
+	}
+
+	/* the last chunk marks the end of the region */
+	rblocks[nblocks - 1].start = size;
+	rblocks[nblocks - 1].size = 0;
+	list_add_tail(&rblocks[nblocks - 1].list, &reserve_list);
+
+	list_sort(NULL, &reserve_list, sram_reserve_cmp);
+
+	cur_start = 0;
+
+	list_for_each_entry(block, &reserve_list, list) {
+		/* can only happen if sections overlap */
+		if (block->start < cur_start) {
+			dev_err(&pdev->dev,
+				"block at 0x%x starts after current offset 0x%lx\n",
+				block->start, cur_start);
+			ret = -EINVAL;
+			goto err_chunks;
+		}
+
+		/* current start is in a reserved block, so continue after it */
+		if (block->start == cur_start) {
+			cur_start = block->start + block->size;
+			continue;
+		}
+
+		/*
+		 * allocate the space between the current starting
+		 * address and the following reserved block, or the
+		 * end of the region.
+		 */
+		cur_size = block->start - cur_start;
+
+		dev_dbg(&pdev->dev, "adding chunk 0x%lx-0x%lx\n",
+			cur_start, cur_start + cur_size);
+		ret = gen_pool_add_virt(sram->pool,
+				(unsigned long)virt_base + cur_start,
+				res->start + cur_start, cur_size, -1);
+		if (ret < 0)
+			goto err_chunks;
+
+		/* next allocation after this reserved block */
+		cur_start = block->start + block->size;
+	}
+
+	kfree(rblocks);
+
 	platform_set_drvdata(pdev, sram);
 
 	dev_dbg(&pdev->dev, "SRAM pool: %ld KiB @ 0x%p\n", size / 1024, virt_base);
 
 	return 0;
+
+err_chunks:
+	kfree(rblocks);
+err_alloc:
+	if (sram->clk)
+		clk_disable_unprepare(sram->clk);
+	return ret;
 }
 
 static int sram_remove(struct platform_device *pdev)
-- 
1.8.5.3


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

^ permalink raw reply related

* [PATCH v8 3/6] ARM: rockchip: add snoop-control-unit
From: Heiko Stübner @ 2014-02-25 11:47 UTC (permalink / raw)
  To: linux-arm-kernel@lists.infradead.org
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell
In-Reply-To: <21117503.1c6iOkvYSr@phil>

This adds the device-node and config select to enable the
scu in all Rockchip Cortex-A9 SoCs.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 arch/arm/boot/dts/rk3xxx.dtsi  | 5 +++++
 arch/arm/mach-rockchip/Kconfig | 1 +
 2 files changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
index 0fcbcfd..0a3d5b1 100644
--- a/arch/arm/boot/dts/rk3xxx.dtsi
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -26,6 +26,11 @@
 		compatible = "simple-bus";
 		ranges;
 
+		scu@1013c000 {
+			compatible = "arm,cortex-a9-scu";
+			reg = <0x1013c000 0x100>;
+		};
+
 		gic: interrupt-controller@1013d000 {
 			compatible = "arm,cortex-a9-gic";
 			interrupt-controller;
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index cf073de..133410e 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -5,6 +5,7 @@ config ARCH_ROCKCHIP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select CACHE_L2X0
+	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
 	select COMMON_CLK
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v8 4/6] ARM: rockchip: add sram dt nodes and documentation
From: Heiko Stübner @ 2014-02-25 11:47 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
  Cc: arm-DgEjT+Ai2ygdnm+yROfE0A, Grant Likely, Rob Herring,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Philipp Zabel,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Greg Kroah-Hartman,
	Pawel Moll, Mark Rutland, Stephen Warren, Ian Campbell
In-Reply-To: <21117503.1c6iOkvYSr@phil>

Add dt-nodes for the sram on rk3066 and rk3188 including the reserved section
needed for smp bringup.

Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
Tested-by: Ulrich Prinz <ulrich.prinz-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 .../devicetree/bindings/arm/rockchip/smp-sram.txt  | 30 ++++++++++++++++++++++
 arch/arm/boot/dts/rk3066a.dtsi                     | 13 ++++++++++
 arch/arm/boot/dts/rk3188.dtsi                      | 13 ++++++++++
 3 files changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt

diff --git a/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt b/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt
new file mode 100644
index 0000000..d9416fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt
@@ -0,0 +1,30 @@
+Rockchip SRAM for smp bringup:
+------------------------------
+
+Rockchip's smp-capable SoCs use the first part of the sram for the bringup
+of the cores. Once the core gets powered up it executes the code that is
+residing at the very beginning of the sram.
+
+Therefore a reserved section sub-node has to be added to the mmio-sram
+declaration.
+
+Required sub-node properties:
+- compatible : should be "rockchip,rk3066-smp-sram"
+
+The rest of the properties should follow the generic mmio-sram discription
+found in ../../misc/sram.txt
+
+Example:
+
+	sram: sram@10080000 {
+		compatible = "mmio-sram";
+		reg = <0x10080000 0x10000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		smp-sram@10080000 {
+			compatible = "rockchip,rk3066-smp-sram";
+			reg = <0x10080000 0x50>;
+		};
+	};
diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index be5d2b0..37d0768 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -64,6 +64,19 @@
 			clock-names = "timer", "pclk";
 		};
 
+		sram: sram@10080000 {
+			compatible = "mmio-sram";
+			reg = <0x10080000 0x10000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			smp-sram@10080000 {
+				compatible = "rockchip,rk3066-smp-sram";
+				reg = <0x10080000 0x50>;
+			};
+		};
+
 		pinctrl@20008000 {
 			compatible = "rockchip,rk3066a-pinctrl";
 			reg = <0x20008000 0x150>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 1a26b03..412f4d0 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -60,6 +60,19 @@
 			interrupts = <GIC_PPI 13 0xf04>;
 		};
 
+		sram: sram@10080000 {
+			compatible = "mmio-sram";
+			reg = <0x10080000 0x8000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			smp-sram@10080000 {
+				compatible = "rockchip,rk3066-smp-sram";
+				reg = <0x10080000 0x50>;
+			};
+		};
+
 		pinctrl@20008000 {
 			compatible = "rockchip,rk3188-pinctrl";
 			reg = <0x20008000 0xa0>,
-- 
1.8.5.3


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

^ permalink raw reply related

* [PATCH v8 5/6] ARM: rockchip: add power-management-unit
From: Heiko Stübner @ 2014-02-25 11:48 UTC (permalink / raw)
  To: linux-arm-kernel@lists.infradead.org
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell
In-Reply-To: <21117503.1c6iOkvYSr@phil>

The pmu is needed to bring up the cores during smp operations and later
also other system parts. Therefore add a node and documentation for it.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 Documentation/devicetree/bindings/arm/rockchip/pmu.txt | 16 ++++++++++++++++
 arch/arm/boot/dts/rk3xxx.dtsi                          |  5 +++++
 2 files changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu.txt

diff --git a/Documentation/devicetree/bindings/arm/rockchip/pmu.txt b/Documentation/devicetree/bindings/arm/rockchip/pmu.txt
new file mode 100644
index 0000000..3ee9b42
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/rockchip/pmu.txt
@@ -0,0 +1,16 @@
+Rockchip power-management-unit:
+-------------------------------
+
+The pmu is used to turn off and on different power domains of the SoCs
+This includes the power to the CPU cores.
+
+Required node properties:
+- compatible value : = "rockchip,rk3066-pmu";
+- reg : physical base address and the size of the registers window
+
+Example:
+
+	pmu@20004000 {
+		compatible = "rockchip,rk3066-pmu";
+		reg = <0x20004000 0x100>;
+	};
diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
index 0a3d5b1..26e5a96 100644
--- a/arch/arm/boot/dts/rk3xxx.dtsi
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -31,6 +31,11 @@
 			reg = <0x1013c000 0x100>;
 		};
 
+		pmu@20004000 {
+			compatible = "rockchip,rk3066-pmu";
+			reg = <0x20004000 0x100>;
+		};
+
 		gic: interrupt-controller@1013d000 {
 			compatible = "arm,cortex-a9-gic";
 			interrupt-controller;
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v8 6/6] ARM: rockchip: add smp bringup code
From: Heiko Stübner @ 2014-02-25 11:48 UTC (permalink / raw)
  To: linux-arm-kernel@lists.infradead.org
  Cc: arm, Grant Likely, Rob Herring, devicetree, Philipp Zabel,
	linux-kernel, Greg Kroah-Hartman, Pawel Moll, Mark Rutland,
	Stephen Warren, Ian Campbell
In-Reply-To: <21117503.1c6iOkvYSr@phil>

This adds the necessary smp-operations and startup code to use
additional cores on Rockchip SoCs.

We currently hog the power management unit in the smp code, as it is
necessary to control the power to the cpu core and nothing else is
currently using it, so a generic implementation can be done later.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Ulrich Prinz <ulrich.prinz@googlemail.com>
---
 arch/arm/mach-rockchip/Makefile   |   1 +
 arch/arm/mach-rockchip/core.h     |  22 +++++
 arch/arm/mach-rockchip/headsmp.S  |  30 +++++++
 arch/arm/mach-rockchip/platsmp.c  | 184 ++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c |   2 +
 5 files changed, 239 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/core.h
 create mode 100644 arch/arm/mach-rockchip/headsmp.S
 create mode 100644 arch/arm/mach-rockchip/platsmp.c

diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 1547d4f..4377a14 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-rockchip/core.h b/arch/arm/mach-rockchip/core.h
new file mode 100644
index 0000000..e2e7c9d
--- /dev/null
+++ b/arch/arm/mach-rockchip/core.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+extern char rockchip_secondary_trampoline;
+extern char rockchip_secondary_trampoline_end;
+
+extern unsigned long rockchip_boot_fn;
+extern void rockchip_secondary_startup(void);
+
+extern struct smp_operations rockchip_smp_ops;
diff --git a/arch/arm/mach-rockchip/headsmp.S b/arch/arm/mach-rockchip/headsmp.S
new file mode 100644
index 0000000..73206e3
--- /dev/null
+++ b/arch/arm/mach-rockchip/headsmp.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ENTRY(rockchip_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
+ENDPROC(rockchip_secondary_startup)
+
+ENTRY(rockchip_secondary_trampoline)
+	ldr	pc, 1f
+ENDPROC(rockchip_secondary_trampoline)
+	.globl	rockchip_boot_fn
+rockchip_boot_fn:
+1:	.space	4
+
+ENTRY(rockchip_secondary_trampoline_end)
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
new file mode 100644
index 0000000..dbfa5a2
--- /dev/null
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+#include <asm/mach/map.h>
+
+#include "core.h"
+
+static void __iomem *scu_base_addr;
+static void __iomem *sram_base_addr;
+static int ncores;
+
+#define PMU_PWRDN_CON		0x08
+#define PMU_PWRDN_ST		0x0c
+
+#define PMU_PWRDN_SCU		4
+
+static void __iomem *pmu_base_addr;
+
+static inline bool pmu_power_domain_is_on(int pd)
+{
+	return !(readl_relaxed(pmu_base_addr + PMU_PWRDN_ST) & BIT(pd));
+}
+
+static void pmu_set_power_domain(int pd, bool on)
+{
+	u32 val = readl_relaxed(pmu_base_addr + PMU_PWRDN_CON);
+	if (on)
+		val &= ~BIT(pd);
+	else
+		val |=  BIT(pd);
+	writel(val, pmu_base_addr + PMU_PWRDN_CON);
+
+	while (pmu_power_domain_is_on(pd) != on) { }
+}
+
+/*
+ * Handling of CPU cores
+ */
+
+static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
+					     struct task_struct *idle)
+{
+	if (!sram_base_addr || !pmu_base_addr) {
+		pr_err("%s: sram or pmu missing for cpu boot\n", __func__);
+		return -ENXIO;
+	}
+
+	if (cpu >= ncores) {
+		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
+							__func__, cpu, ncores);
+		return -ENXIO;
+	}
+
+	/* start the core */
+	pmu_set_power_domain(0 + cpu, true);
+
+	return 0;
+}
+
+/**
+ * rockchip_smp_prepare_sram - populate necessary sram block
+ * Starting cores execute the code residing at the start of the on-chip sram
+ * after power-on. Therefore make sure, this sram region is reserved and
+ * big enough. After this check, copy the trampoline code that directs the
+ * core to the real startup code in ram into the sram-region.
+ * @node: mmio-sram device node
+ */
+static int __init rockchip_smp_prepare_sram(struct device_node *node)
+{
+	unsigned int trampoline_sz = &rockchip_secondary_trampoline_end -
+					    &rockchip_secondary_trampoline;
+	struct resource res;
+	unsigned int rsize;
+	int ret;
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret < 0) {
+		pr_err("%s: could not get address for node %s\n",
+		       __func__, node->full_name);
+		return ret;
+	}
+
+	rsize = resource_size(&res);
+	if (rsize < trampoline_sz) {
+		pr_err("%s: reserved block with size 0x%x is to small for trampoline size 0x%x\n",
+		       __func__, rsize, trampoline_sz);
+		return -EINVAL;
+	}
+
+	sram_base_addr = of_iomap(node, 0);
+
+	/* set the boot function for the sram code */
+	rockchip_boot_fn = virt_to_phys(rockchip_secondary_startup);
+
+	/* copy the trampoline to sram, that runs during startup of the core */
+	memcpy(sram_base_addr, &rockchip_secondary_trampoline, trampoline_sz);
+	flush_cache_all();
+	outer_clean_range(0, trampoline_sz);
+
+	dsb_sev();
+
+	return 0;
+}
+
+static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *node;
+	unsigned int i;
+
+	node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+	if (!node) {
+		pr_err("%s: missing scu\n", __func__);
+		return;
+	}
+
+	scu_base_addr = of_iomap(node, 0);
+	if (!scu_base_addr) {
+		pr_err("%s: could not map scu registers\n", __func__);
+		return;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-smp-sram");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	if (rockchip_smp_prepare_sram(node))
+		return;
+
+	node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu");
+	if (!node) {
+		pr_err("%s: could not find sram dt node\n", __func__);
+		return;
+	}
+
+	pmu_base_addr = of_iomap(node, 0);
+	if (!pmu_base_addr) {
+		pr_err("%s: could not map pmu registers\n", __func__);
+		return;
+	}
+
+	/* enable the SCU power domain */
+	pmu_set_power_domain(PMU_PWRDN_SCU, true);
+
+	/*
+	 * While the number of cpus is gathered from dt, also get the number
+	 * of cores from the scu to verify this value when booting the cores.
+	 */
+	ncores = scu_get_core_count(scu_base_addr);
+
+	scu_enable(scu_base_addr);
+
+	/* Make sure that all cores except the first are really off */
+	for (i = 1; i < ncores; i++)
+		pmu_set_power_domain(0 + i, false);
+}
+
+struct smp_operations rockchip_smp_ops __initdata = {
+	.smp_prepare_cpus	= rockchip_smp_prepare_cpus,
+	.smp_boot_secondary	= rockchip_boot_secondary,
+};
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 82c0b07..d211d6f 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -22,6 +22,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/cache-l2x0.h>
+#include "core.h"
 
 static void __init rockchip_dt_init(void)
 {
@@ -38,6 +39,7 @@ static const char * const rockchip_board_dt_compat[] = {
 };
 
 DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+	.smp		= smp_ops(rockchip_smp_ops),
 	.init_machine	= rockchip_dt_init,
 	.dt_compat	= rockchip_board_dt_compat,
 MACHINE_END
-- 
1.8.5.3

^ permalink raw reply related

* Re: [RESEND][PATCH v4] gpio: davinci: reuse for keystone soc
From: Grygorii Strashko @ 2014-02-25 11:52 UTC (permalink / raw)
  To: Santosh Shilimkar, Linus Walleij
  Cc: Alexandre Courbot,
	davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <53076032.5080202-l0cyMroinI0@public.gmane.org>

Hi Linus,

On 02/21/2014 04:18 PM, Santosh Shilimkar wrote:
> On Thursday 13 February 2014 10:58 AM, Grygorii Strashko wrote:
>> The similar GPIO HW block is used by keystone SoCs as
>> in Davinci SoCs.
>> Hence, reuse Davinci GPIO driver for Keystone taking into
>> account that Keystone contains ARM GIC IRQ controller which
>> is implemented using IRQ Chip.
>>
>> Documentation:
>> 	http://www.ti.com/lit/ug/sprugv1/sprugv1.pdf
>>
>> Acked-by: Santosh Shilimkar <santosh.shilimkar-l0cyMroinI0@public.gmane.org>
>> Acked-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Signed-off-by: Grygorii Strashko <grygorii.strashko-l0cyMroinI0@public.gmane.org>
>> ---
>> - rebased on top of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
>>    branch: devel
>>    top commit: ef70bbe gpio: make gpiod_direction_output take a logical value
>>
> Can you please pick this one ? Its rebased as per your suggestion.

I've just rechecked this patch and it's applied without conflicts
on top of your "devel" branch.

Pls, inform me if I need to do anything else for you
in order to have this patch applied.

[...]

>> @@ -554,7 +585,8 @@ done:
>>   
>>   #if IS_ENABLED(CONFIG_OF)
>>   static const struct of_device_id davinci_gpio_ids[] = {
>> -	{ .compatible = "ti,dm6441-gpio", },
>> +	{ .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip},
>> +	{ .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip},
>>   	{ /* sentinel */ },
>>   };
>>   MODULE_DEVICE_TABLE(of, davinci_gpio_ids);
>>
> 
Regards,
-grygorii

^ permalink raw reply

* Re: [PATCH RESEND v10 1/4] PHY: Add function set_speed to generic PHY framework
From: Kishon Vijay Abraham I @ 2014-02-25 12:05 UTC (permalink / raw)
  To: Loc Ho, tj
  Cc: devicetree, arnd, jcm, patches, linux-kernel, ddutile, olof,
	linux-arm-kernel
In-Reply-To: <1393308882-3964-2-git-send-email-lho@apm.com>

Hi,

On Tuesday 25 February 2014 11:44 AM, Loc Ho wrote:
> This patch adds function set_speed to the generic PHY framework operation
> structure. This function can be called to instruct the PHY underlying layer
> at specified lane to configure for specified speed in hertz.
> 
> Signed-off-by: Loc Ho <lho@apm.com>
> ---
>  drivers/phy/phy-core.c  |   21 +++++++++++++++++++++
>  include/linux/phy/phy.h |    8 ++++++++
>  2 files changed, 29 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index 645c867..44f2f63 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -257,6 +257,27 @@ int phy_power_off(struct phy *phy)
>  }
>  EXPORT_SYMBOL_GPL(phy_power_off);
>  

missing function comment :-s

> +int phy_set_speed(struct phy *phy, int lane, u64 speed)
> +{

Thanks
Kishon

^ permalink raw reply

* Re: Movement of testcases.dtsi
From: Grant Likely @ 2014-02-25 12:09 UTC (permalink / raw)
  To: Ian Campbell; +Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1393272348.9640.4.camel-ztPmHsLffjjnO4AKDKe2m+kiAK3p4hvP@public.gmane.org>

On Mon, 24 Feb 2014 20:05:48 +0000, Ian Campbell <ijc-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org> wrote:
> On Mon, 2014-02-24 at 19:48 +0000, Grant Likely wrote:
> > On Mon, 24 Feb 2014 10:25:42 +0000, Ian Campbell <ijc-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org> wrote:
> > > My device-tree-rebasing.git repo no longer builds, it fails with:
> > > src/arm/versatile-pb.dts:50:26: fatal error: testcases.dtsi: No such file or directory
> > > 
> > > I suspect this is due to b5190516b282 "of: Move testcase FDT data into
> > > drivers/of". I think I need to add drivers/of/testcase-data to the list
> > > of paths to convert, probably extracting it to /testcase-data in the dt
> > > repo and teach the build system about the new path in the obvious way.
> > > 
> > > Does that make sense?
> > 
> > Yup, that's the right thing to do... 
> 
> Thanks, I'll look into it.
> 
> > although I would like it to be a
> > short term solution. Ultimately I want the testcase data to be loaded at
> > runtime by the selftest module.
> 
> I suppose at this point linux.git will have a git rm done and my
> conversion script will just import that as expected?

Yes. When versatile-pb.dts stops including the testcases it will become
a non-issue.

g.

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

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox