Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 14/14] ARM: sun7i: dts: Add ahci / sata support
From: Maxime Ripard @ 2014-01-31 13:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390417489-5354-15-git-send-email-hdegoede@redhat.com>

On Wed, Jan 22, 2014 at 08:04:49PM +0100, Hans de Goede wrote:
> This patch adds sunxi sata support to A20 boards that have such a connector.
> Some boards also feature a regulator via a GPIO and support for this is also
> added.
> 
> Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/boot/dts/sun7i-a20-cubieboard2.dts     |  6 ++++++
>  arch/arm/boot/dts/sun7i-a20-cubietruck.dts      | 20 ++++++++++++++++++++
>  arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts |  6 ++++++
>  arch/arm/boot/dts/sun7i-a20.dtsi                |  8 ++++++++
>  4 files changed, 40 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
> index 48777cd..1cab521 100644
> --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
> +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
> @@ -13,6 +13,7 @@
>  
>  /dts-v1/;
>  /include/ "sun7i-a20.dtsi"
> +/include/ "sunxi-ahci-reg.dtsi"
>  
>  / {
>  	model = "Cubietech Cubieboard2";
> @@ -28,6 +29,11 @@
>  			status = "okay";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			target-supply = <&reg_ahci_5v>;
> +			status = "okay";
> +		};
> +
>  		pinctrl at 01c20800 {
>  			mmc0_cd_pin_cubieboard2: mmc0_cd_pin at 0 {
>  				allwinner,pins = "PH1";
> diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
> index 2684f27..1247ea1 100644
> --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
> +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
> @@ -13,6 +13,7 @@
>  
>  /dts-v1/;
>  /include/ "sun7i-a20.dtsi"
> +/include/ "sunxi-ahci-reg.dtsi"
>  
>  / {
>  	model = "Cubietech Cubietruck";
> @@ -28,6 +29,11 @@
>  			status = "okay";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			target-supply = <&reg_ahci_5v>;
> +			status = "okay";
> +		};
> +
>  		pinctrl at 01c20800 {
>  			mmc0_cd_pin_cubietruck: mmc0_cd_pin at 0 {
>  				allwinner,pins = "PH1";
> @@ -36,6 +42,13 @@
>  				allwinner,pull = <0>;
>  			};
>  
> +			ahci_pwr_pin_cubietruck: ahci_pwr_pin at 1 {
> +				allwinner,pins = "PH12";
> +				allwinner,function = "gpio_out";
> +				allwinner,drive = <0>;
> +				allwinner,pull = <0>;
> +			};
> +
>  			led_pins_cubietruck: led_pins at 0 {
>  				allwinner,pins = "PH7", "PH11", "PH20", "PH21";
>  				allwinner,function = "gpio_out";
> @@ -84,4 +97,11 @@
>  			gpios = <&pio 7 7 0>;
>  		};
>  	};
> +
> +	regulators {
> +		reg_ahci_5v: ahci-5v {
> +			pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
> +			gpio = <&pio 7 12 0>;
> +		};
> +	};
>  };
> diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
> index bf6f6c8..f135886 100644
> --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
> +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
> @@ -13,6 +13,7 @@
>  
>  /dts-v1/;
>  /include/ "sun7i-a20.dtsi"
> +/include/ "sunxi-ahci-reg.dtsi"
>  
>  / {
>  	model = "Olimex A20-Olinuxino Micro";
> @@ -37,6 +38,11 @@
>  			status = "okay";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			target-supply = <&reg_ahci_5v>;
> +			status = "okay";
> +		};
> +
>  		pinctrl at 01c20800 {
>  			mmc0_cd_pin_olinuxinom: mmc0_cd_pin at 0 {
>  				allwinner,pins = "PH1";
> diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
> index c9c123a..0657bad 100644
> --- a/arch/arm/boot/dts/sun7i-a20.dtsi
> +++ b/arch/arm/boot/dts/sun7i-a20.dtsi
> @@ -347,6 +347,14 @@
>  			status = "disabled";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			compatible = "allwinner,sun4i-a10-ahci";
> +			reg = <0x01c18000 0x1000>;
> +			interrupts = <0 56 1>;

This is supposed to be a level triggered interrupt, not an edge
triggered one.

Thanks for your work!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/d3dbd525/attachment-0001.sig>

^ permalink raw reply

* [PATCH v5 13/14] ARM: sun4i: dts: Add ahci / sata support
From: Maxime Ripard @ 2014-01-31 13:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390417489-5354-14-git-send-email-hdegoede@redhat.com>

Hi Hans,

On Wed, Jan 22, 2014 at 08:04:48PM +0100, Hans de Goede wrote:
> From: Oliver Schinagl <oliver@schinagl.nl>
> 
> This patch adds sunxi sata support to A10 boards that have such a connector.
> Some boards also feature a regulator via a GPIO and support for this is also
> added.
> 
> Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/boot/dts/sun4i-a10-a1000.dts      |  4 ++++
>  arch/arm/boot/dts/sun4i-a10-cubieboard.dts |  6 +++++
>  arch/arm/boot/dts/sun4i-a10.dtsi           |  8 +++++++
>  arch/arm/boot/dts/sunxi-ahci-reg.dtsi      | 38 ++++++++++++++++++++++++++++++

I'm still half convinced about this at the moment, given the number of
platforms we support, we can always change it back if things become too messy.

>  4 files changed, 56 insertions(+)
>  create mode 100644 arch/arm/boot/dts/sunxi-ahci-reg.dtsi
> 
> diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
> index aef8207..3fb7305 100644
> --- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
> +++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
> @@ -48,6 +48,10 @@
>  			status = "okay";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			status = "okay";
> +		};
> +
>  		pinctrl at 01c20800 {
>  			mmc0_cd_pin_a1000: mmc0_cd_pin at 0 {
>  				allwinner,pins = "PH1";
> diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
> index f50fb2b..6ae1110 100644
> --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
> +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
> @@ -12,6 +12,7 @@
>  
>  /dts-v1/;
>  /include/ "sun4i-a10.dtsi"
> +/include/ "sunxi-ahci-reg.dtsi"
>  
>  / {
>  	model = "Cubietech Cubieboard";
> @@ -51,6 +52,11 @@
>  			status = "okay";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			target-supply = <&reg_ahci_5v>;
> +			status = "okay";
> +		};
> +
>  		pinctrl at 01c20800 {
>  			mmc0_cd_pin_cubieboard: mmc0_cd_pin at 0 {
>  				allwinner,pins = "PH1";
> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> index 4736dd2..198dcda 100644
> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> @@ -331,6 +331,14 @@
>  			status = "disabled";
>  		};
>  
> +		ahci: sata at 01c18000 {
> +			compatible = "allwinner,sun4i-a10-ahci";

To be consistent with the rest of the sun4i devices compatible, It
should be sun4i-ahci.

However, since these devices don't use the same compatible pattern as
their own machine compatible, and are consisent with the rest of the
compatibles for the other SoCs, we can probably make this a go to
transition progressively to this pattern.

I'll cook up some patches for the other devices.

> +			reg = <0x01c18000 0x1000>;
> +			interrupts = <56>;
> +			clocks = <&pll6 0>, <&ahb_gates 25>;
> +			status = "disabled";
> +		};
> +
>  		intc: interrupt-controller at 01c20400 {
>  			compatible = "allwinner,sun4i-ic";
>  			reg = <0x01c20400 0x400>;
> diff --git a/arch/arm/boot/dts/sunxi-ahci-reg.dtsi b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
> new file mode 100644
> index 0000000..955b197
> --- /dev/null
> +++ b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
> @@ -0,0 +1,38 @@
> +/*
> + * sunxi boards sata target power supply common code
> + *
> + * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
> + *
> + * 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
> + */
> +
> +/ {
> +	soc at 01c00000 {
> +		ahci_pwr_pin_a: ahci_pwr_pin at 0 {
> +			allwinner,pins = "PB8";
> +			allwinner,function = "gpio_out";
> +			allwinner,drive = <0>;
> +			allwinner,pull = <0>;
> +		};

This should be under the pinctrl node.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/4caca1fa/attachment.sig>

^ permalink raw reply

* [PATCH 0/3] spi: core: Introduce devm_spi_alloc_master
From: Maxime Ripard @ 2014-01-31 13:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140131121215.GB22609@sirena.org.uk>

On Fri, Jan 31, 2014 at 12:12:15PM +0000, Mark Brown wrote:
> On Fri, Jan 31, 2014 at 11:23:09AM +0100, Maxime Ripard wrote:
> 
> > This patchset introduces a devm_spi_alloc_master to the spi core. While most of
> > the drivers have a spi_master_put call in the probe, a lot of them using the
> > devm_spi_register_master function are missing it in the remove function,
> > leading to leaked resources.
> 
> This seems confusing - the idea here is that if we've handed the device
> off to the managed function then the managed function deals with
> destroying it.  Note that spi_alloc_master() says that the put is only
> required after errors adding the device (which would be the expected
> behaviour if you look at other APIs).  Looking at the code I think there
> is an issue here but I'm not at all clear that this is the best fix.

Ah, right, spi_master_put doesn't free the memory either...

I guess we have a few choices here, either:
  - Add a devm_kzalloc to spi_alloc_master, since most of the drivers
    I've been looking at fail to free the memory, this would be the
    least intrusive solution. We'd still have to remove all the kfree
    calls in the driver that rightfully free the memory.
  - Make devm_unregister_master also call kfree on the master
  - Add a kfree to my devm_put_master so that the memory is reclaimed,
    which isn't the case for now.

I don't have a strong preference here, maybe for the third one, since
it makes obvious that it's managed and you don't have to do anything
about it, while the other do not.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/a8aa0f8d/attachment.sig>

^ permalink raw reply

* [PATCH] ARM: dts: k2hk-evm: rename clock node to clocks
From: Grygorii Strashko @ 2014-01-31 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

Fix type in clock(s) node name: "clock"-->"clocks".

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 arch/arm/boot/dts/k2hk-evm.dts |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/k2hk-evm.dts b/arch/arm/boot/dts/k2hk-evm.dts
index eaefdfe..c02c3a8 100644
--- a/arch/arm/boot/dts/k2hk-evm.dts
+++ b/arch/arm/boot/dts/k2hk-evm.dts
@@ -15,7 +15,7 @@
 	compatible =  "ti,keystone-evm";
 
 	soc {
-		clock {
+		clocks {
 			refclksys: refclksys {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] usb: dwc3: keystone: switch to use runtime pm
From: Grygorii Strashko @ 2014-01-31 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

The Keystone PM management layer has been implemented using PM bus for
power management clocks. As result, most of Keystone drivers don't need
to manage clocks directly. They just need to enable runtime PM and use it
to handle their PM state and clocks.

Hence, remove clock management code and switch to use runtime PM.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 drivers/usb/dwc3/dwc3-keystone.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index 1fad161..a810b41 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -23,6 +23,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
 
 /* USBSS register offsets */
 #define USBSS_REVISION		0x0000
@@ -116,12 +117,10 @@ static int kdwc3_probe(struct platform_device *pdev)
 	kdwc3_dma_mask = dma_get_mask(dev);
 	dev->dma_mask = &kdwc3_dma_mask;
 
-	kdwc->clk = devm_clk_get(kdwc->dev, "usb");
-
-	error = clk_prepare_enable(kdwc->clk);
+	pm_runtime_enable(dev);
+	error = pm_runtime_get_sync(dev);
 	if (error < 0) {
-		dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
-			error);
+		dev_dbg(dev, "unable to enable usb dev, err %d\n", error);
 		return error;
 	}
 
@@ -152,7 +151,8 @@ static int kdwc3_probe(struct platform_device *pdev)
 err_core:
 	kdwc3_disable_irqs(kdwc);
 err_irq:
-	clk_disable_unprepare(kdwc->clk);
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
 
 	return error;
 }
@@ -172,7 +172,8 @@ static int kdwc3_remove(struct platform_device *pdev)
 
 	kdwc3_disable_irqs(kdwc);
 	device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
-	clk_disable_unprepare(kdwc->clk);
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 4/4] ARM: dts: add B2112 board support
From: srinivas kandagatla @ 2014-01-31 12:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391093744-19905-5-git-send-email-patrice.chotard@st.com>

On 30/01/14 14:55, Patrice CHOTARD wrote:
> From: Alexandre TORGUE <alexandre.torgue@st.com>
> 
> Add support for B2112  board based on STiD127 SoC.
> 
> Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com>
> Signed-off-by: Maxime Coquelin <maxime.coquelin@st.com>
> ---
>  arch/arm/boot/dts/Makefile          |    3 ++-
>  arch/arm/boot/dts/stid127-b2112.dts |   35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 37 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/boot/dts/stid127-b2112.dts
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index d57c1a6..7173dca 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -247,7 +247,8 @@ dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
>  dtb-$(CONFIG_ARCH_STI)+= stih415-b2000.dtb \
>  	stih416-b2000.dtb \
>  	stih415-b2020.dtb \
> -	stih416-b2020.dtb
> +	stih416-b2020.dtb \
> +	stid127-b2112.dtb
>  dtb-$(CONFIG_ARCH_SUNXI) += \
>  	sun4i-a10-a1000.dtb \
>  	sun4i-a10-cubieboard.dtb \
> diff --git a/arch/arm/boot/dts/stid127-b2112.dts b/arch/arm/boot/dts/stid127-b2112.dts
> new file mode 100644
> index 0000000..b4507e3
> --- /dev/null
> +++ b/arch/arm/boot/dts/stid127-b2112.dts
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) 2013 STMicroelectronics Limited.

2014

> + * Author: Alexandre Torgue <alexandre.torgue@st.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * publishhed by the Free Software Foundation.

s/publishhed/published/

> + */
> +/dts-v1/;
> +#include "stid127.dtsi"
> +
> +/ {
> +	model = "STiD127 B2112 Board";
> +	compatible = "st,stid127", "st,stid127-b2112";
> +
> +	memory{
> +		device_type = "memory";
> +		reg = <0x40000000 0x10000000>;
> +	};
> +
> +	chosen {
> +		bootargs = "console=ttyAS0,115200";
> +		linux,stdout-path = &uart2;
> +	};
> +
> +	aliases {
> +		ttyAS0 = &uart2;
> +	};
> +
> +	soc {
> +		uart2: serial at fe532000{
> +			status = "okay";
> +		};
> +	};
> +};
> 

^ permalink raw reply

* [PATCH 3/4] ARM: dts: Add support of STid127 Soc.
From: srinivas kandagatla @ 2014-01-31 12:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391093744-19905-4-git-send-email-patrice.chotard@st.com>

Hi Patrice,

On 30/01/14 14:55, Patrice CHOTARD wrote:
> From: Alexandre TORGUE <alexandre.torgue@st.com>
> 
> The STid127 integrates all harware components to function as a cable modem
s/harware/hardware/

s/STid127/STiD127

Please fix other instances too.

> or, in combination with a back end device, as a Gateway set top boxe.
s/boxe/box/
> 
> Supported devices:
> 	-UART0
> 	-UART2
> 
> Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
> ---
>  arch/arm/boot/dts/stid127-clock.dtsi   |   31 ++++
>  arch/arm/boot/dts/stid127-pinctrl.dtsi |  245 ++++++++++++++++++++++++++++++++
>  arch/arm/boot/dts/stid127.dtsi         |  130 +++++++++++++++++
>  3 files changed, 406 insertions(+)
>  create mode 100644 arch/arm/boot/dts/stid127-clock.dtsi
>  create mode 100644 arch/arm/boot/dts/stid127-pinctrl.dtsi
>  create mode 100644 arch/arm/boot/dts/stid127.dtsi
> 
> diff --git a/arch/arm/boot/dts/stid127-clock.dtsi b/arch/arm/boot/dts/stid127-clock.dtsi
> new file mode 100644
> index 0000000..c6cafa9
> --- /dev/null
> +++ b/arch/arm/boot/dts/stid127-clock.dtsi
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (C) 2013 STMicroelectronics (R&D) Limited

2014

> + * Author(s): Giuseppe Cavallaro <peppe.cavallaro@st.com>
> + *	      Alexandre Torgue <alexandre.torgue@st.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +/ {Acked-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> +	clocks {
> +		/*
> +		 * ARM Peripheral clock for timers
> +		 */
> +		arm_periph_clk: arm_periph_clk {
> +			#clock-cells = <0>;
> +			compatible = "fixed-clock";
> +			clock-frequency = <100000000>;
> +		};
> +		/*
> +		 * Bootloader initialized system infrastructure clock for
> +		 * serial devices.
> +		 */
> +		CLK_IC_LP_HD: clockgenA0 at 29 {
> +			#clock-cells = <0>;
> +			compatible = "fixed-clock";
> +			clock-frequency = <100000000>;
> +			clock-output-names = "CLK_IC_LP_HD";
> +		};
> +	};
> +};
> diff --git a/arch/arm/boot/dts/stid127-pinctrl.dtsi b/arch/arm/boot/dts/stid127-pinctrl.dtsi
> new file mode 100644
> index 0000000..3fa66f3
> --- /dev/null
> +++ b/arch/arm/boot/dts/stid127-pinctrl.dtsi
> @@ -0,0 +1,245 @@
> +/*
> + * Copyright (C) 2012 STMicroelectronics Limited.

2014

> + * Author(s): Giuseppe Cavallaro <peppe.cavallaro@st.com>
> + *	      Alexandre Torgue <alexandre.torgue@st.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * publishhed by the Free Software Foundation.

s/publishhed/published/

> + */
> +#include "st-pincfg.h"
> +/ {
> +	aliases {
> +		gpio0	= &PIO0;
> +		gpio1	= &PIO1;
> +		gpio2	= &PIO2;
> +		gpio3	= &PIO3;
> +		gpio4	= &PIO4;
> +		gpio5	= &PIO5;
> +		gpio6	= &PIO6;
> +		gpio7	= &PIO7;
> +		gpio8	= &PIO8;
> +		gpio9	= &PIO9;
> +		gpio10	= &PIO10;
> +		gpio11	= &PIO11;
> +		gpio12	= &PIO12;
> +		gpio13	= &PIO13;
> +		gpio14	= &PIO14;
> +		gpio15	= &PIO15;
> +		gpio16	= &PIO16;
> +		gpio17	= &PIO17;
> +		gpio18	= &PIO18;
> +		gpio19	= &PIO19;
> +		gpio20	= &PIO20;
> +		gpio21	= &PIO21;
> +		gpio22	= &PIO22;
> +
> +	};
> +
> +	soc {
> +		pin-controller-pwest {
> +			#address-cells	= <1>;
> +			#size-cells	= <1>;
> +			compatible	= "st,stid127-pwest-pinctrl";
> +			st,syscfg	= <&syscfg_pwest>;
> +			ranges		= <0 0xfebe0000 0x8000>;

Can you add interrupt controller support to the pin controller.

Patches are in : https://lkml.org/lkml/2014/1/16/342
All these patches are due to be in v3.15.

> +
> +			PIO0: gpio at febe0000 {
> +				gpio-controller;
> +				#gpio-cells = <1>;
> +				reg = <0 0x100>;
> +				interrupts =  <0 149 0>;
> +				st,bank-name  = "PIO0";
> +			};
> +						rx	= <&PIO3 0 ALT2	IN>;
> +					};
> +				};
> +			};
> +
> +		};
unnecessary empty line  here.

> diff --git a/arch/arm/boot/dts/stid127.dtsi b/arch/arm/boot/dts/stid127.dtsi
> new file mode 100644
> index 0000000..a6f0b8fe
> --- /dev/null
> +++ b/arch/arm/boot/dts/stid127.dtsi
> @@ -0,0 +1,130 @@
> +/*
> + * Copyright (C) 2013 STMicroelectronics Limited.
2014
> + * Author(s): Giuseppe Cavallaro <peppe.cavallaro@st.com>
> + *	      Alexandre Torgue <alexandre.torgue@st.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * publishhed by the Free Software Foundation.

s/publishhed/published/

> + */
> +#include "stid127-pinctrl.dtsi"
> +#include "stid127-clock.dtsi"
> +/ {
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu at 0 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a9";
> +			reg = <0>;
> +		};
> +		cpu at 1 {
> +			device_type = "cpu";
> +			compatible = "arm,cortex-a9";
> +			reg = <1>;
> +		};
> +	};
> +
> +	intc: interrupt-controller at fffe1000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells = <3>;
> +		interrupt-controller;
> +		reg = <0xfffe1000 0x1000>,
> +		      <0xfffe0100 0x100>;
> +	};
> +
> +	scu at fffe0000 {
> +		compatible = "arm,cortex-a9-scu";
> +		reg = <0xfffe0000 0x1000>;
> +	};
> +
> +	timer at fffe0200 {
> +			interrupt-parent = <&intc>;
> +			compatible = "arm,cortex-a9-global-timer";
> +			reg = <0xfffe0200 0x100>;
> +			interrupts = <1 11 0x04>;
> +			clocks = <&arm_periph_clk>;

Fix the tab spacing here.

Thanks,
srini
> 

^ permalink raw reply

* [PATCH v3 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Mark Brown @ 2014-01-31 12:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391165752-1819-4-git-send-email-maxime.ripard@free-electrons.com>

On Fri, Jan 31, 2014 at 11:55:50AM +0100, Maxime Ripard wrote:

> +	master = devm_spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
> +	if (!master) {
> +		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
> +		return -ENOMEM;
> +	}

This now depends on your other series which as I said doesn't look like
the best approach.

> +	pm_runtime_enable(&pdev->dev);
> +	if (!pm_runtime_enabled(&pdev->dev)) {
> +		ret = sun6i_spi_runtime_resume(&pdev->dev);
> +		if (ret) {
> +			dev_err(&pdev->dev, "Couldn't resume the device\n");
> +			return ret;
> +		}
> +	}

No, as discussed don't do this - notice how other drivers aren't written
this way either.  Like I said leave the device powered on startup and
then let it be idled by runtime PM.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/768cbcd7/attachment.sig>

^ permalink raw reply

* Extending OPP bindings
From: Lorenzo Pieralisi @ 2014-01-31 12:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52EAF1CA.3040702@ti.com>

Hi Nishanth,

On Fri, Jan 31, 2014 at 12:43:54AM +0000, Nishanth Menon wrote:
> Hi Sudeep,
> 
> On 01/30/2014 07:43 AM, Sudeep Holla wrote:
> 
> > 
> > I am looking into a couple shortcomings in the current OPP bindings and
> > how to address them. Feel free to add to the list if you think of any more
> > issues that needs to be addressed or if and how any problem mentioned below
> > can be handled with the existing bindings.
> > 
> > 1. indexing: currently there are no indices in the operating-points.
> indexing is based on frequency which is why the accessors use
> frequency to pull out the OPP data.
> 
> indexing is a horrible idea - on platforms where OPP may be disabled
> or enabled for various reasons(see arch/arm/mach-imx/mach-imx6q.c,
> arch/arm/mach-omap2/board-omap3beagle.c etc) - the indexing you see in
> dts is just a myth that may not exist once the nodes are loaded and
> operated upon depending on SoC variations (example efuse describing
> which OPPs can be used and which not).

I do not understand why. As long as a mapping from DT to data structures
in the kernel is done at boot, I can see how by indexing device nodes
can refer to specific OPPs. If they are disabled, amen, as long as we
can point at specific operating points that should be ok.

Indexing does not mean that the index in the DT is the same as the one
allocated by the OS. Indexing is there to point at specific OPPs from
different DT nodes, a good example are clock bindings and that's exactly
how they work.

Can you provide me with an example where the indexing would go wrong
please ?

Certainly relying on implicit ordering is not great either, actually I
would say that it is broken.

> That said, the original OPP[1][2] series discussion started by trying
> to kill indexing precisely for the same reason.. once you have it - it
> becomes just crazy to deal with.

I could not find any "index killing" :) discussion in there, but I will
keep reading.

> > 	It's assumed that the list is either in ascending or descending
> > 	order of frequency but not explicit in the binding document.
> > 	There are arch/arm/boot/dts/* files with opps in both styles.
> it should not matter -> opp library should do an insertion sort and
> organize it in ascending order once all the data is inserted. (line
> 449ish in opp.c)

That's OS details and they must not be mandated by the bindings.
We cannot rely on word of mouth for things to work, I do not like
implicit rules, so the bindings should speficy the ordering or better
a way to reference OPPs.

> if you see issues with the insertion sort not functioning, it is a bug
> and should be easy to track down and fix.

Problem is not the insertion sort, problem is that DT bindings do not
define a way to refer to a specific OPP, unless we do that implicitly
and again, I rest my case, that is broken.

> > 	Few other bindings like thermal defines bindings like
> > 	cooling-{min,max}-state assuming some order which is broken IMO.
> Now that you bring it up, I missed it :(.. yeah, I might have
> preferred it to be min frequency and max_frequency - I agree it is
> probably broken. I'd let Eduardo comment more about it.
> 
> > 
> > 	One such use-case that came up recently[0] is the c-state latencies
> > 	which could be different for each OPP. It would be good if the
> > 	latencies are specified with the indices to OPP table to avoid
> > 	inconsistency between the bindings.
> 
> You can define C states based on frequencies as well - which really
> makes sense - since that sounds really like our constraint (say
> valid-at-frequency "xyz"

I do not think that's generic enough, I do not like the idea of looking
up frequencies (eg a C-state target_residency does not depend on the
frequency only - ie voltage and other factors play a role, it really
depends on an operating point- looking it up by frequency is misleading IMO).

> > 	It's mainly to avoid issues due to inconsistency and duplication
> > 	on data(frequency) in multiple bindings requiring it.
> > 
> > 	Once we have indices to each on the OPP entries, then other binding
> > 	using it can refer to OPP with phandle and OPP index/specifier pairs
> > 	very similar to clock provider and consumer.
> 
> Having used indexing in OMAP platforms, indexing is a problem waiting
> to happen unfortunately :(

Please be specific, I do not see why it is a problem.

[...]

> > 3. latencies(*): currently the latency that the CPU/memory access is unavailable
> > 	during an OPP transition is generic i.e. same from any OPP to any
> > 	other OPP. Does it make sense to have this per-OPP entry ?
> 
> Why modify OPP when you are describing something else? you are
> describing "latency at a frequency" - just because an OPP definition
> as it stands right now is {frequency, voltage} tuple, makes it a very
> attractive target to keep extending it -> believe me, we have done
> that in the past ->arch/arm/mach-omap2/opp4xxx_data.c efuse register
> describing AVS per frequency is tempting..
> 
> why not have memory-latency-per-opp = <frequency latency>?
> 
> that allows OPP definitions to change in the future, but the
> definition remain constant.
> 
> That said -> consider the following usecase: AM335x, OMAP3,4... (i
> will use omap4 as an example)
> MPU at 300MHz and bus (on which LPDDR2 memory is) at 100MHz
> AND
> MPU at 300MHz and bus (on which LPDDR2 memory is) at 200MHz
> 
> are both valid with different memory access latencies. tying it down
> to OPP for MPU is just plain wrong - as it ignores other factors.

I think it is time we were defining OPPs for the system as a whole, the
issue has been brought up for C-state dependencies as well.

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-January/228042.html

We can easily define a global node that encompasses OPPs for various
devices, and then map the OPPs for devices to a global OPP table.

(totally made-up DT bindings, just to get the message across)

opps {
	operating-points = <......>;
	operating-point-cells = <2>;

	cpu-opps {
	/* where index maps to a global OPP above where the CPU OPP is valid */
		operating-points = <...... index>;
	
	};
	memory-opp {
	/*
	   where index maps to a global OPP above where the memory OPP is
	   valid
	*/
		operating-points = <...... index>;
	};
};

> > 4. power(*): A measure of maximum power dissipation in an OPP state.
> > 	This might be useful measure for power aware scheduling ?
> Umm.. this is a hard nut to crack -> I had considered that previously
> as well -> In reality the leakage characteristics of the SoC
> distribution varies dramatically depending on which end of the
> distribution you look for a specific process node. in my company, we
> typically use cold, hot,nominal devices, this is some form or other
> (example - Samsung calls it "SoC's ASV group" [4]) - and every SoC
> company comes up with some strategy or other to control it optimally
> -> TI uses ABB[5], AVS[6] - etc... - not an unique problem -> so what
> will "power" mean? we cannot create dts per SoC part.

Yes, that's a hard nut to crack. Probably we can define a reference value,
to be debated.

> > (*) these are already part of P-state in ACPI(refer struct acpi_processor_px
> > in include/acpi/processor.h)
> 
> Hmm.. what do we do with legacy processors that dont support ACPI or
> what ever our latest ARM term is for the equivalent?
> 
> > 
> > Apart from these I have seen on-going discussion for Samsung Exynos CPUFreq[2]
> > which might have some feedback for OPP bindings.
> > 
> > It would be good to consolidate the shortcomings found so far, that could
> > help in extending the current OPP bindings.
> 
> I hope this discussion helps. open to more views as well.

It helps a lot, thank you, please keep it going.

Thanks,
Lorenzo

^ permalink raw reply

* [PATCH 2/4] pinctrl: st: add stid127 support
From: srinivas kandagatla @ 2014-01-31 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391093744-19905-3-git-send-email-patrice.chotard@st.com>

Looks good for me.

Acked-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>

On 30/01/14 14:55, Patrice CHOTARD wrote:
> From: Alexandre TORGUE <alexandre.torgue@st.com>
> 
> Add STid127 PIOs (psouth, pwest, peast) in pinctrl.
> 
> Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
> ---
>  drivers/pinctrl/pinctrl-st.c |   25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
> index 9cadc68..01227de 100644
> --- a/drivers/pinctrl/pinctrl-st.c
> +++ b/drivers/pinctrl/pinctrl-st.c
> @@ -336,6 +336,27 @@ static const struct st_pctl_data  stih416_data = {
>  	.alt = 0, .oe = 40, .pu = 50, .od = 60, .rt = 100,
>  };
>  
> +/* STid127 data */
> +static const struct st_pctl_data  stid127_data = {
> +	.rt_style	= st_retime_style_dedicated,
> +	/* reuse stih416 delays as they are identical */
> +	.input_delays	= stih416_delays,
> +	.ninput_delays	= 14,
> +	/* reuse stih416 delays as they are identical */
> +	.output_delays	= stih416_delays,
> +	.noutput_delays = 14,
> +	.alt = 0, .oe = 8, .pu = 10, .od = 12, .rt = 14,
> +};
> +
> +static const struct st_pctl_data  stid127_psouth_data = {
> +	.rt_style	= st_retime_style_dedicated,
> +	.input_delays	= stid127_delays,
> +	.ninput_delays	= 14,
> +	.output_delays	= stid127_delays,
> +	.noutput_delays = 14,
> +	.alt = 0, .oe = 7, .pu = 9, .od = 11, .rt = 13,
> +};
> +
>  /* Low level functions.. */
>  static inline int st_gpio_bank(int gpio)
>  {
> @@ -1264,6 +1285,10 @@ static struct of_device_id st_pctl_of_match[] = {
>  	{ .compatible = "st,stih416-rear-pinctrl", .data = &stih416_data},
>  	{ .compatible = "st,stih416-fvdp-fe-pinctrl", .data = &stih416_data},
>  	{ .compatible = "st,stih416-fvdp-lite-pinctrl", .data = &stih416_data},
> +	{ .compatible = "st,stid127-pwest-pinctrl", .data = &stid127_data },
> +	{ .compatible = "st,stid127-psouth-pinctrl",
> +		.data = &stid127_psouth_data },
> +	{ .compatible = "st,stid127-peast-pinctrl", .data = &stid127_data },
>  	{ /* sentinel */ }
>  };
>  
> 

^ permalink raw reply

* [PATCH 1/4] ARM: STi: add stid127 soc support
From: srinivas kandagatla @ 2014-01-31 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401301939.08302.arnd@arndb.de>

Hi Arnd,
On 30/01/14 18:39, Arnd Bergmann wrote:
> Actually reading the code in this file shows that the L2 cache
> initialization is the only nonstandard thing in there. We should
> really find a way to get rid of the entire function.
I think this will get rid of lot of code left in board-dt.

> 
> Sorry if I missed the initial review, but can you explain
> why this is needed to start with?
On ST SoCs the default value for L2 AUX_CTRL register is 0x0, so we  set
the way-size explicit here.

Thanks,
srini

^ permalink raw reply

* [PATCH 0/3] spi: core: Introduce devm_spi_alloc_master
From: Mark Brown @ 2014-01-31 12:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391163792-21819-1-git-send-email-maxime.ripard@free-electrons.com>

On Fri, Jan 31, 2014 at 11:23:09AM +0100, Maxime Ripard wrote:

> This patchset introduces a devm_spi_alloc_master to the spi core. While most of
> the drivers have a spi_master_put call in the probe, a lot of them using the
> devm_spi_register_master function are missing it in the remove function,
> leading to leaked resources.

This seems confusing - the idea here is that if we've handed the device
off to the managed function then the managed function deals with
destroying it.  Note that spi_alloc_master() says that the put is only
required after errors adding the device (which would be the expected
behaviour if you look at other APIs).  Looking at the code I think there
is an issue here but I'm not at all clear that this is the best fix.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/b7e655ca/attachment.sig>

^ permalink raw reply

* [PATCH] ARM: zynq: Reserve not DMAable space in front of the kernel
From: Michal Simek @ 2014-01-31 12:08 UTC (permalink / raw)
  To: linux-arm-kernel

Reserve space from 0x0 - __pa(swapper_pg_dir),
if kernel is loaded from 0, which is not DMAable.
It is causing problem with MMC driver and others
which want to add dma buffers to this space.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

Jason: I don't think it is worth to bring 0x8000 magic
value and count minimum from it and phys_addr of swapper_pg_dir.
Full 512k of memory shouldn't be used by DMA.

---
 arch/arm/mach-zynq/common.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 1db2a5ca..8c09a83 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -25,6 +25,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of.h>
+#include <linux/memblock.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>

@@ -41,6 +42,18 @@

 void __iomem *zynq_scu_base;

+/**
+ * zynq_memory_init - Initialize special memory
+ *
+ * We need to stop things allocating the low memory as DMA can't work in
+ * the 1st 512K of memory.
+ */
+static void __init zynq_memory_init(void)
+{
+	if (!__pa(PAGE_OFFSET))
+		memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
+}
+
 static struct platform_device zynq_cpuidle_device = {
 	.name = "cpuidle-zynq",
 };
@@ -117,5 +130,6 @@ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
 	.init_machine	= zynq_init_machine,
 	.init_time	= zynq_timer_init,
 	.dt_compat	= zynq_dt_match,
+	.reserve	= zynq_memory_init,
 	.restart	= zynq_system_reset,
 MACHINE_END
--
1.8.2.3

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/7214a18f/attachment.sig>

^ permalink raw reply related

* [PATCH v2] pwm: add CSR SiRFSoC PWM driver
From: Barry Song @ 2014-01-31 12:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401302049.27521.arnd@arndb.de>

2014-01-31 Arnd Bergmann <arnd@arndb.de>:
> On Thursday 30 January 2014, Barry Song wrote:
>> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
>> index 7acab93..0a252f8 100644
>> --- a/drivers/pwm/Kconfig
>> +++ b/drivers/pwm/Kconfig
>> @@ -166,6 +166,15 @@ config PWM_SAMSUNG
>>         To compile this driver as a module, choose M here: the module
>>         will be called pwm-samsung.
>>
>> +config PWM_SIRF
>> +     tristate "SiRF PWM support"
>> +     depends on ARCH_SIRF
>> +     help
>
> please make this "depends on ARCH_SIRF || COMPILE_TEST" if you can, so we
> can build it on other platforms for test purposes. If you do this, you
> have to list the full set of dependencies, so probably another
> "depends on HAVE_CLK".

sounds good. it seems we can have this for other PWM drivers as well?

>
>> +
>> +#define to_sirf_chip(chip)   container_of(chip, struct sirf_pwm, chip)
>> +
>> +static unsigned int sirf_pwm_ns_to_cycles(struct pwm_chip *chip, unsigned int time_ns)
>> +{
>> +     u64 dividend;
>> +     unsigned int cycle;
>> +     /*
>> +      * on SiRFSoC, OSC input is const, we use it as the source to generate
>> +      * PWM wave
>> +      */
>> +#define SRC_OSC_RATE 26000000ULL
>> +     dividend = SRC_OSC_RATE * time_ns + NSEC_PER_SEC / 2;
>> +     do_div(dividend, NSEC_PER_SEC);
>> +
>> +     cycle = dividend & 0xFFFFFFFFUL;
>> +
>> +     return cycle > 1 ? cycle : 1;
>> +}
>> +
>
> Is SRC_OSC_RATE the rate of spwm->clk? If so, it would be nice to just call
> clk_get_rate() here, in case you ever have a chip with a different rate.
>

SRC_OSC_RATE is the fixed frequency of crystal oscillator, but
spwm->clk comes from the IO bus. the design is a little strange, pwm
channels don't use the clock of PWM controller to generate
period/duty, but use other sources.

> This is a very nice driver otherwise!
>
>         Arnd

-barry

^ permalink raw reply

* [PATCH] pinctrl: sirf: correct the pin index of ac97_pins group
From: Linus Walleij @ 2014-01-31 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390802489-2535-1-git-send-email-21cnbao@gmail.com>

On Mon, Jan 27, 2014 at 7:01 AM, Barry Song <21cnbao@gmail.com> wrote:

> From: Qipan Li <Qipan.Li@csr.com>
>
> according to datasheet and ac97_muxmask assignment, ac97_pins should be
> corrected.
>
> Signed-off-by: Qipan Li <Qipan.Li@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>

Patch applied for fixes.

Yours,
Linus Walleij

^ permalink raw reply

* [RFC PATCH 0/2] dmaengine: at_hdmac: fix locking according to slave DMA requirements
From: Jouko Haapaluoma @ 2014-01-31 10:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1390832343.git.nicolas.ferre@atmel.com>

Hi

Thanks for the patches. We got the DMA working for now but the tasklet_disable() and tasklet_enable() had to be removed from atc_control().

If the device driver calls dmaengine_terminate_all() from the callback (like in our previous deadlock example), the tasklet_disable() will cause
another deadlock because the tasklet will then wait for itself to close.

The tasklet_disable() seems to be used to ensure that no tasklet is running when terminating the DMA transfers. This prevents the terminate_all from
happening in between the critical sections in the tasklet which are locked with atchan->lock. Maybe the tasklet needs to be implemented so that it can
detect and recover if the terminate_all was called in between the critical sections in the tasklet?

BR,
Jouko Haapaluoma

^ permalink raw reply

* [PATCH v3 5/5] ARM: sunxi: Enable A31 SPI and SID in the defconfig
From: Maxime Ripard @ 2014-01-31 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391165752-1819-1-git-send-email-maxime.ripard@free-electrons.com>

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/configs/sunxi_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index 3e2259b..b5df4a5 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -24,6 +24,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EEPROM_SUNXI_SID=y
 CONFIG_NETDEVICES=y
 CONFIG_SUN4I_EMAC=y
 # CONFIG_NET_CADENCE is not set
@@ -48,6 +49,8 @@ CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MV64XXX=y
+CONFIG_SPI=y
+CONFIG_SPI_SUN6I=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v3 4/5] ARM: sun6i: dt: Add SPI controllers to the A31 DTSI
From: Maxime Ripard @ 2014-01-31 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391165752-1819-1-git-send-email-maxime.ripard@free-electrons.com>

The A31 has 4 SPI controllers. Add them in the DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun6i-a31.dtsi | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 0eea325..57af66f 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -340,6 +340,46 @@
 			status = "disabled";
 		};
 
+		spi0: spi at 01c68000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c68000 0x1000>;
+			interrupts = <0 65 4>;
+			clocks = <&ahb1_gates 20>, <&spi0_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 20>;
+			status = "disabled";
+		};
+
+		spi1: spi at 01c69000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c69000 0x1000>;
+			interrupts = <0 66 4>;
+			clocks = <&ahb1_gates 21>, <&spi1_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 21>;
+			status = "disabled";
+		};
+
+		spi2: spi at 01c6a000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c6a000 0x1000>;
+			interrupts = <0 67 4>;
+			clocks = <&ahb1_gates 22>, <&spi2_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 22>;
+			status = "disabled";
+		};
+
+		spi3: spi at 01c6b000 {
+			compatible = "allwinner,sun6i-a31-spi";
+			reg = <0x01c6b000 0x1000>;
+			interrupts = <0 68 4>;
+			clocks = <&ahb1_gates 23>, <&spi3_clk>;
+			clock-names = "ahb", "mod";
+			resets = <&ahb1_rst 23>;
+			status = "disabled";
+		};
+
 		gic: interrupt-controller at 01c81000 {
 			compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
 			reg = <0x01c81000 0x1000>,
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v3 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Maxime Ripard @ 2014-01-31 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391165752-1819-1-git-send-email-maxime.ripard@free-electrons.com>

The Allwinner A31 has a new SPI controller IP compared to the older Allwinner
SoCs.

It supports DMA, but the driver only does PIO for now, and DMA will be
supported eventually.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 .../devicetree/bindings/spi/spi-sun6i.txt          |  24 ++
 drivers/spi/Kconfig                                |   6 +
 drivers/spi/Makefile                               |   1 +
 drivers/spi/spi-sun6i.c                            | 473 +++++++++++++++++++++
 4 files changed, 504 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
 create mode 100644 drivers/spi/spi-sun6i.c

diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
new file mode 100644
index 0000000..21de73d
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
@@ -0,0 +1,24 @@
+Allwinner A31 SPI controller
+
+Required properties:
+- compatible: Should be "allwinner,sun6i-a31-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: phandle to the clocks feeding the SPI controller. Two are
+          needed:
+  - "ahb": the gated AHB parent clock
+  - "mod": the parent module clock
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset controller asserting this device in
+          reset
+
+Example:
+
+spi1: spi at 01c69000 {
+	compatible = "allwinner,sun6i-a31-spi";
+	reg = <0x01c69000 0x1000>;
+	interrupts = <0 66 4>;
+	clocks = <&ahb1_gates 21>, <&spi1_clk>;
+	clock-names = "ahb", "mod";
+	resets = <&ahb1_rst 21>;
+};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5072b71..24f3b85 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -446,6 +446,12 @@ config SPI_SIRF
 	help
 	  SPI driver for CSR SiRFprimaII SoCs
 
+config SPI_SUN6I
+	tristate "Allwinner A31 SPI controller"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	help
+	  This enables using the SPI controller on the Allwinner A31 SoCs.
+
 config SPI_MXS
 	tristate "Freescale MXS SPI controller"
 	depends on ARCH_MXS
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 95af48d..13b6ccf 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_SPI_SH_HSPI)		+= spi-sh-hspi.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.o
 obj-$(CONFIG_SPI_SIRF)		+= spi-sirf.o
+obj-$(CONFIG_SPI_SUN6I)			+= spi-sun6i.o
 obj-$(CONFIG_SPI_TEGRA114)		+= spi-tegra114.o
 obj-$(CONFIG_SPI_TEGRA20_SFLASH)	+= spi-tegra20-sflash.o
 obj-$(CONFIG_SPI_TEGRA20_SLINK)		+= spi-tegra20-slink.o
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
new file mode 100644
index 0000000..1747892
--- /dev/null
+++ b/drivers/spi/spi-sun6i.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+
+#define SUN6I_FIFO_DEPTH		128
+
+#define SUN6I_GBL_CTL_REG		0x04
+#define SUN6I_GBL_CTL_BUS_ENABLE		BIT(0)
+#define SUN6I_GBL_CTL_MASTER			BIT(1)
+#define SUN6I_GBL_CTL_TP			BIT(7)
+#define SUN6I_GBL_CTL_RST			BIT(31)
+
+#define SUN6I_TFR_CTL_REG		0x08
+#define SUN6I_TFR_CTL_CPHA			BIT(0)
+#define SUN6I_TFR_CTL_CPOL			BIT(1)
+#define SUN6I_TFR_CTL_SPOL			BIT(2)
+#define SUN6I_TFR_CTL_CS_MASK			0x3
+#define SUN6I_TFR_CTL_CS(cs)			(((cs) & SUN6I_TFR_CTL_CS_MASK) << 4)
+#define SUN6I_TFR_CTL_CS_MANUAL			BIT(6)
+#define SUN6I_TFR_CTL_CS_LEVEL			BIT(7)
+#define SUN6I_TFR_CTL_DHB			BIT(8)
+#define SUN6I_TFR_CTL_FBS			BIT(12)
+#define SUN6I_TFR_CTL_XCH			BIT(31)
+
+#define SUN6I_INT_CTL_REG		0x10
+#define SUN6I_INT_CTL_RF_OVF			BIT(8)
+#define SUN6I_INT_CTL_TC			BIT(12)
+
+#define SUN6I_INT_STA_REG		0x14
+
+#define SUN6I_FIFO_CTL_REG		0x18
+#define SUN6I_FIFO_CTL_RF_RST			BIT(15)
+#define SUN6I_FIFO_CTL_TF_RST			BIT(31)
+
+#define SUN6I_FIFO_STA_REG		0x1c
+#define SUN6I_FIFO_STA_RF_CNT_MASK		0x7f
+#define SUN6I_FIFO_STA_RF_CNT_BITS		0
+#define SUN6I_FIFO_STA_TF_CNT_MASK		0x7f
+#define SUN6I_FIFO_STA_TF_CNT_BITS		16
+
+#define SUN6I_CLK_CTL_REG		0x24
+#define SUN6I_CLK_CTL_CDR2_MASK			0xff
+#define SUN6I_CLK_CTL_CDR2(div)			(((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
+#define SUN6I_CLK_CTL_CDR1_MASK			0xf
+#define SUN6I_CLK_CTL_CDR1(div)			(((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN6I_CLK_CTL_DRS			BIT(12)
+
+#define SUN6I_BURST_CNT_REG		0x30
+#define SUN6I_BURST_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN6I_XMIT_CNT_REG		0x34
+#define SUN6I_XMIT_CNT(cnt)			((cnt) & 0xffffff)
+
+#define SUN6I_BURST_CTL_CNT_REG		0x38
+#define SUN6I_BURST_CTL_CNT_STC(cnt)		((cnt) & 0xffffff)
+
+#define SUN6I_TXDATA_REG		0x200
+#define SUN6I_RXDATA_REG		0x300
+
+struct sun6i_spi {
+	struct spi_master	*master;
+	void __iomem		*base_addr;
+	struct clk		*hclk;
+	struct clk		*mclk;
+	struct reset_control	*rstc;
+
+	struct completion	done;
+
+	const u8		*tx_buf;
+	u8			*rx_buf;
+	int			len;
+};
+
+static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
+{
+	return readl(sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
+{
+	writel(value, sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
+{
+	u32 reg, cnt;
+	u8 byte;
+
+	/* See how much data is available */
+	reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
+	reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
+	cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
+
+	if (len > cnt)
+		len = cnt;
+
+	while (len--) {
+		byte = readb(sspi->base_addr + SUN6I_RXDATA_REG);
+		if (sspi->rx_buf)
+			*sspi->rx_buf++ = byte;
+	}
+}
+
+static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len)
+{
+	u8 byte;
+
+	if (len > sspi->len)
+		len = sspi->len;
+
+	while (len--) {
+		byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
+		writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG);
+		sspi->len--;
+	}
+}
+
+static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
+{
+	struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
+	u32 reg;
+
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+	reg &= ~SUN6I_TFR_CTL_CS_MASK;
+	reg |= SUN6I_TFR_CTL_CS(spi->chip_select);
+
+	if (enable)
+		reg |= SUN6I_TFR_CTL_CS_LEVEL;
+	else
+		reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
+
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+}
+
+
+static int sun6i_spi_transfer_one(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *tfr)
+{
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+	unsigned int mclk_rate, div, timeout;
+	unsigned int tx_len = 0;
+	int ret = 0;
+	u32 reg;
+
+	/* We don't support transfer larger than the FIFO */
+	if (tfr->len > SUN6I_FIFO_DEPTH)
+		return -EINVAL;
+
+	reinit_completion(&sspi->done);
+	sspi->tx_buf = tfr->tx_buf;
+	sspi->rx_buf = tfr->rx_buf;
+	sspi->len = tfr->len;
+
+	/* Clear pending interrupts */
+	sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
+
+	/* Reset FIFO */
+	sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
+			SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
+
+	/*
+	 * Setup the transfer control register: Chip Select,
+	 * polarities, etc.
+	 */
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+
+	if (spi->mode & SPI_CPOL)
+		reg |= SUN6I_TFR_CTL_CPOL;
+	else
+		reg &= ~SUN6I_TFR_CTL_CPOL;
+
+	if (spi->mode & SPI_CPHA)
+		reg |= SUN6I_TFR_CTL_CPHA;
+	else
+		reg &= ~SUN6I_TFR_CTL_CPHA;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		reg |= SUN6I_TFR_CTL_FBS;
+	else
+		reg &= ~SUN6I_TFR_CTL_FBS;
+
+	/*
+	 * If it's a TX only transfer, we don't want to fill the RX
+	 * FIFO with bogus data
+	 */
+	if (sspi->rx_buf)
+		reg &= ~SUN6I_TFR_CTL_DHB;
+	else
+		reg |= SUN6I_TFR_CTL_DHB;
+
+	/* We want to control the chip select manually */
+	reg |= SUN6I_TFR_CTL_CS_MANUAL;
+
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+
+	/* Ensure that we have a parent clock fast enough */
+	mclk_rate = clk_get_rate(sspi->mclk);
+	if (mclk_rate < (2 * spi->max_speed_hz)) {
+		clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
+		mclk_rate = clk_get_rate(sspi->mclk);
+	}
+
+	/*
+	 * Setup clock divider.
+	 *
+	 * We have two choices there. Either we can use the clock
+	 * divide rate 1, which is calculated thanks to this formula:
+	 * SPI_CLK = MOD_CLK / (2 ^ cdr)
+	 * Or we can use CDR2, which is calculated with the formula:
+	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+	 * Wether we use the former or the latter is set through the
+	 * DRS bit.
+	 *
+	 * First try CDR2, and if we can't reach the expected
+	 * frequency, fall back to CDR1.
+	 */
+	div = mclk_rate / (2 * spi->max_speed_hz);
+	if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+		if (div > 0)
+			div--;
+
+		reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
+	} else {
+		div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
+		reg = SUN6I_CLK_CTL_CDR1(div);
+	}
+
+	sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
+
+	/* Setup the transfer now... */
+	if (sspi->tx_buf)
+		tx_len = tfr->len;
+
+	/* Setup the counters */
+	sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, SUN6I_BURST_CNT(tfr->len));
+	sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, SUN6I_XMIT_CNT(tx_len));
+	sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG,
+			SUN6I_BURST_CTL_CNT_STC(tx_len));
+
+	/* Fill the TX FIFO */
+	sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+	/* Enable the interrupts */
+	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
+
+	/* Start the transfer */
+	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+
+	timeout = wait_for_completion_timeout(&sspi->done,
+					      msecs_to_jiffies(1000));
+	if (!timeout) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+out:
+	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
+
+	return ret;
+}
+
+static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
+{
+	struct sun6i_spi *sspi = dev_id;
+	u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
+
+	/* Transfer complete */
+	if (status & SUN6I_INT_CTL_TC) {
+		sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
+		complete(&sspi->done);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int sun6i_spi_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(sspi->hclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable AHB clock\n");
+		goto out;
+	}
+
+	ret = clk_prepare_enable(sspi->mclk);
+	if (ret) {
+		dev_err(dev, "Couldn't enable module clock\n");
+		goto err;
+	}
+
+	ret = reset_control_deassert(sspi->rstc);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert the device from reset\n");
+		goto err2;
+	}
+
+	sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
+			SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
+
+	return 0;
+
+err2:
+	clk_disable_unprepare(sspi->mclk);
+err:
+	clk_disable_unprepare(sspi->hclk);
+out:
+	return ret;
+}
+
+static int sun6i_spi_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+	reset_control_assert(sspi->rstc);
+	clk_disable_unprepare(sspi->mclk);
+	clk_disable_unprepare(sspi->hclk);
+
+	return 0;
+}
+
+static int sun6i_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct sun6i_spi *sspi;
+	struct resource	*res;
+	int ret = 0, irq;
+
+	master = devm_spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
+	if (!master) {
+		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, master);
+	sspi = spi_master_get_devdata(master);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sspi->base_addr))
+		return PTR_ERR(sspi->base_addr);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No spi IRQ specified\n");
+		return -ENXIO;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
+			       0, "sun6i-spi", sspi);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot request IRQ\n");
+		return ret;
+	}
+
+	sspi->master = master;
+	master->bus_num	= -1;
+	master->set_cs = sun6i_spi_set_cs;
+	master->transfer_one = sun6i_spi_transfer_one;
+	master->num_chipselect = 4;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+	master->dev.of_node = pdev->dev.of_node;
+	master->auto_runtime_pm = true;
+
+	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(sspi->hclk)) {
+		dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+		return PTR_ERR(sspi->hclk);
+	}
+
+	sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+	if (IS_ERR(sspi->mclk)) {
+		dev_err(&pdev->dev, "Unable to acquire module clock\n");
+		return PTR_ERR(sspi->mclk);
+	}
+
+	init_completion(&sspi->done);
+
+	sspi->rstc = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(sspi->rstc)) {
+		dev_err(&pdev->dev, "Couldn't get reset controller\n");
+		return PTR_ERR(sspi->rstc);
+	}
+
+	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		ret = sun6i_spi_runtime_resume(&pdev->dev);
+		if (ret) {
+			dev_err(&pdev->dev, "Couldn't resume the device\n");
+			return ret;
+		}
+	}
+
+	ret = devm_spi_register_master(&pdev->dev, master);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot register SPI master\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	if (!pm_runtime_enabled(&pdev->dev))
+		sun6i_spi_runtime_suspend(&pdev->dev);
+
+	pm_runtime_disable(&pdev->dev);
+	return ret;
+}
+
+static int sun6i_spi_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id sun6i_spi_match[] = {
+	{ .compatible = "allwinner,sun6i-a31-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun6i_spi_match);
+
+static const struct dev_pm_ops sun6i_spi_pm_ops = {
+	.runtime_resume		= sun6i_spi_runtime_resume,
+	.runtime_suspend	= sun6i_spi_runtime_suspend,
+};
+
+static struct platform_driver sun6i_spi_driver = {
+	.probe	= sun6i_spi_probe,
+	.remove	= sun6i_spi_remove,
+	.driver	= {
+		.name		= "sun6i-spi",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sun6i_spi_match,
+		.pm		= &sun6i_spi_pm_ops,
+	},
+};
+module_platform_driver(sun6i_spi_driver);
+
+MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
+MODULE_LICENSE("GPL");
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v3 2/5] ARM: sun6i: dt: Add PLL6 and SPI module clocks
From: Maxime Ripard @ 2014-01-31 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391165752-1819-1-git-send-email-maxime.ripard@free-electrons.com>

The module clocks in the A31 are still compatible with the A10 one. Add the SPI
module clocks and the PLL6 in the device tree to allow their use by the SPI
controllers.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun6i-a31.dtsi | 46 ++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 5256ad9..0eea325 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -73,16 +73,12 @@
 			clocks = <&osc24M>;
 		};
 
-		/*
-		 * This is a dummy clock, to be used as placeholder on
-		 * other mux clocks when a specific parent clock is not
-		 * yet implemented. It should be dropped when the driver
-		 * is complete.
-		 */
-		pll6: pll6 {
+		pll6: clk at 01c20028 {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
+			compatible = "allwinner,sun6i-a31-pll6-clk";
+			reg = <0x01c20028 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll6";
 		};
 
 		cpu: cpu at 01c20050 {
@@ -182,6 +178,38 @@
 					"apb2_uart1", "apb2_uart2", "apb2_uart3",
 					"apb2_uart4", "apb2_uart5";
 		};
+
+		spi0_clk: clk at 01c200a0 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200a0 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi0";
+		};
+
+		spi1_clk: clk at 01c200a4 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200a4 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi1";
+		};
+
+		spi2_clk: clk at 01c200a8 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200a8 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi2";
+		};
+
+		spi3_clk: clk at 01c200ac {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-mod0-clk";
+			reg = <0x01c200ac 0x4>;
+			clocks = <&osc24M>, <&pll6>;
+			clock-output-names = "spi3";
+		};
 	};
 
 	soc at 01c00000 {
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v3 1/5] clk: sunxi: Add support for PLL6 on the A31
From: Maxime Ripard @ 2014-01-31 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391165752-1819-1-git-send-email-maxime.ripard@free-electrons.com>

The A31 has a slightly different PLL6 clock. Add support for this new clock in
our driver.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |  1 +
 drivers/clk/sunxi/clk-sunxi.c                     | 45 +++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index c2cb762..954845c 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -11,6 +11,7 @@ Required properties:
 	"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
 	"allwinner,sun4i-pll5-clk" - for the PLL5 clock
 	"allwinner,sun4i-pll6-clk" - for the PLL6 clock
+	"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
 	"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
 	"allwinner,sun4i-axi-clk" - for the AXI clock
 	"allwinner,sun4i-axi-gates-clk" - for the AXI gates
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 659e4ea..990ad5d 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -249,7 +249,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
 	*n = DIV_ROUND_UP(div, (*k+1));
 }
 
+/**
+ * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6
+ * PLL6 rate is calculated as follows
+ * rate = parent_rate * n * (k + 1) / 2
+ * parent_rate is always 24Mhz
+ */
+
+static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
+				       u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 div;
+
+	/*
+	 * We always have 24MHz / 2, so we can just say that our
+	 * parent clock is 12MHz.
+	 */
+	parent_rate = parent_rate / 2;
+
+	/* Normalize value to a parent_rate multiple (24M / 2) */
+	div = *freq / parent_rate;
+	*freq = parent_rate * div;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	*k = div / 32;
+	if (*k > 3)
+		*k = 3;
 
+	*n = DIV_ROUND_UP(div, (*k+1));
+}
 
 /**
  * sun4i_get_apb1_factors() - calculates m, p factors for APB1
@@ -416,6 +447,13 @@ static struct clk_factors_config sun4i_pll5_config = {
 	.kwidth = 2,
 };
 
+static struct clk_factors_config sun6i_a31_pll6_config = {
+	.nshift	= 8,
+	.nwidth = 5,
+	.kshift = 4,
+	.kwidth = 2,
+};
+
 static struct clk_factors_config sun4i_apb1_config = {
 	.mshift = 0,
 	.mwidth = 5,
@@ -457,6 +495,12 @@ static const struct factors_data sun4i_pll5_data __initconst = {
 	.getter = sun4i_get_pll5_factors,
 };
 
+static const struct factors_data sun6i_a31_pll6_data __initconst = {
+	.enable = 31,
+	.table = &sun6i_a31_pll6_config,
+	.getter = sun6i_a31_get_pll6_factors,
+};
+
 static const struct factors_data sun4i_apb1_data __initconst = {
 	.table = &sun4i_apb1_config,
 	.getter = sun4i_get_apb1_factors,
@@ -972,6 +1016,7 @@ free_clkdata:
 static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
 	{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
+	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
 	{.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
-- 
1.8.4.2

^ permalink raw reply related

* [PATCH v3 0/5] Add Allwinner A31 SPI controller support
From: Maxime Ripard @ 2014-01-31 10:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi everyone,

This patchset brings support for the SPI controller found in the
Allwinner A31 SoC.

Even though the controller supports DMA, the driver only supports PIO
mode for now. This driver will be used to bring up and test DMA on the
SoC, so support for the DMA will come eventually.

It doesn't support transfer larger than the FIFO size (128 bytes) for
now, I expect it to be fixed in the future.

Thanks!
Maxime

Changes from v2:
  - Removed the select on runtime_pm
  - Fixed the clock error messages
  - Trigger the CS manually, and honour the enable bit in set_cs
  - Convert to devm_* functions
  - Remove useless clk_disable_unprepare in probe

Changes from v1:
  - Switched to using the transfer_one and set_cs callbacks
  - Switched to using runtime_pm
  - Report an error when we try to do a transfer larger than the FIFO
    size, instead of silently timeouting.
  - Added a Kconfig symbol
  - Move the clock ratio change at transfer time
  - Fixed the PLL6 cell size in the DTSI
  - A few fixes here and there: typos, etc.

Maxime Ripard (5):
  clk: sunxi: Add support for PLL6 on the A31
  ARM: sun6i: dt: Add PLL6 and SPI module clocks
  spi: sunxi: Add Allwinner A31 SPI controller driver
  ARM: sun6i: dt: Add SPI controllers to the A31 DTSI
  ARM: sunxi: Enable A31 SPI and SID in the defconfig

 Documentation/devicetree/bindings/clock/sunxi.txt  |   1 +
 .../devicetree/bindings/spi/spi-sun6i.txt          |  24 ++
 arch/arm/boot/dts/sun6i-a31.dtsi                   |  86 +++-
 arch/arm/configs/sunxi_defconfig                   |   3 +
 drivers/clk/sunxi/clk-sunxi.c                      |  45 ++
 drivers/spi/Kconfig                                |   6 +
 drivers/spi/Makefile                               |   1 +
 drivers/spi/spi-sun6i.c                            | 473 +++++++++++++++++++++
 8 files changed, 630 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
 create mode 100644 drivers/spi/spi-sun6i.c

-- 
1.8.4.2

^ permalink raw reply

* [PATCH v2 2/3] ata: sata_mv: fix disk hotplug for Armada 370/XP SoCs
From: Thomas Petazzoni @ 2014-01-31 10:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140131104643.GC10250@kw.sim.vm.gnt>

Dear Simon Guinot,

On Fri, 31 Jan 2014 11:46:44 +0100, Simon Guinot wrote:

> > > +	/*
> > > +	 * To allow disk hotplug on Armada 370/XP SoCs, the PHY speed must be
> > > +	 * updated in the LP_PHY_CTL register.
> > > +	 */
> > > +	if (pdev->dev.of_node &&
> > > +		of_device_is_compatible(pdev->dev.of_node,
> > > +					"marvell,armada-370-xp-sata"))
> > 
> > Testing whether pdev->dev.of_node is not NULL does not seems to be
> > useful. A quick read of of_device_is_compatible() and the function it's
> > calling seem to indicate that of_device_is_compatible will return false
> > if the passed struct device_node * is NULL.
> 
> I see.
> 
> It seems to me, you already have a patch ready to send. Isn't it ?
> Or do you want me to do the update ?

I see that your patches have been merged, so I will send followup fixes.

Thanks!

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH V2] arm64: add DSB after icache flush in __flush_icache_all()
From: Russell King - ARM Linux @ 2014-01-31 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140131001647.GA5525@mudshark.cambridge.arm.com>

On Fri, Jan 31, 2014 at 12:16:48AM +0000, Will Deacon wrote:
> Hi Nico,
> 
> On Thu, Jan 30, 2014 at 09:42:29PM +0000, Nicolas Pitre wrote:
> > On Thu, 30 Jan 2014, Will Deacon wrote:
> > > On Thu, Jan 30, 2014 at 06:04:43AM +0000, Vinayak Kale wrote:
> > > > Can you please elaborate whether you are referring to lack of memory
> > > > clobber or missing barriers?
> > > 
> > > The clobbers. For example:
> > > 
> > > arch/arm64/kvm/sys_regs.c:
> > > 
> > >         /* Make sure noone else changes CSSELR during this! */
> > >         local_irq_disable();
> > >         /* Put value into CSSELR */
> > >         asm volatile("msr csselr_el1, %x0" : : "r" (csselr));
> > >         isb();
> > >         /* Read result out of CCSIDR */
> > >         asm volatile("mrs %0, ccsidr_el1" : "=r" (ccsidr));
> > >         local_irq_enable();
> > > 
> > > Just about everything can be re-ordered in that block, because the asm
> > > volatile statements don't have "memory" clobbers.
> > 
> > I don't think they would be reordered at all with the 
> > volatile qualifiers.
> 
> Whilst that may be the case in current compilers (i.e. I've not actually
> seen the above sequence get re-ordered), the GCC documentation states that:
> 
>   Similarly, you can't expect a sequence of volatile asm instructions to remain
>   perfectly consecutive. If you want consecutive output, use a single asm. Also,
>   GCC performs some optimizations across a volatile asm instruction; GCC does not
>   `forget everything' when it encounters a volatile asm instruction the way some
>   other compilers do.
> 
> so I really think that the "memory" clobbers are needed to ensure strict
> ordering. This matches my understanding from discussions with the compiler
> engineers at ARM.

What it means is that the compiler may introduce additional instructions
between your consecutive asm() statements.  So there's no guarantee that
the ISB will immediately follow the MSR instruction - there may be other
instructions which the compiler may decide to schedule between the two.

For example, instructions to load the address of the variable(s) may be
inserted between the assembly specified in the asm() statements which
may involve loading from a literal pool.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* [PATCH v2 2/3] ata: sata_mv: fix disk hotplug for Armada 370/XP SoCs
From: Simon Guinot @ 2014-01-31 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140126083210.2998ef12@skate>

On Sun, Jan 26, 2014 at 08:32:10AM +0100, Thomas Petazzoni wrote:
> Dear Simon Guinot,

Hi Thomas,

> 
> On Tue, 14 Jan 2014 15:50:06 +0100, Simon Guinot wrote:
> 
> > +			if (hpriv->hp_flags & MV_HP_FIX_LP_PHY_CTL) {
> > +				void __iomem *lp_phy_addr =
> > +					mv_ap_base(link->ap) + LP_PHY_CTL;
> > +				/*
> > +				 * Set PHY speed according to SControl speed.
> > +				 */
> > +				if ((val & 0xf0) == 0x10)
> > +					writelfl(0x7, lp_phy_addr);
> > +				else
> > +					writelfl(0x227, lp_phy_addr);
> > +			}
> 
> I think we could do a little bit better than these magical values.
> 
> The datasheet says:
> 
>  * bits 12:9, PIN_PHY_GEN_RX. Value 0x0 => 1.5 Gbps, value 0x1 => 3 Gbps
>  * bits 8:5, PIN_PHY_GEN_TX. Value 0x0 => 1.5 Gbps, value 0x1 => 3 Gbps
>  * bit 2, PIN_PU_TX. Value 0x0 => Power down, value 0x1 => Power up.
>  * bit 1, PIN_PU_RX. Value 0x0 => Power down, value 0x1 => Power up.
>  * bit 0, PIN_PU_PLL. Value 0x0 => Power down, value 0x1 => Power up.

I missed this section in the datasheet...

> 
> So maybe something like:
> 
> #define PIN_PHY_GEN_1_5		0
> #define PIN_PHY_GEN_3		1
> 
> #define PIN_PHY_GEN_RX(gen)	((gen) << 9)
> #define PIN_PHY_GEN_TX(gen)	((gen) << 5)
> #define PIN_PU_TX		BIT(2)
> #define PIN_PU_RX		BIT(1)
> #define PIN_PU_PLL		BIT(0)
> 
> 
> 		u32 sata_gen;
> 
> 		if ((val & 0xf0) == 0x10)
> 			sata_gen = PIN_PHY_GEN_1_5;
> 		else
> 			sata_gen = PIN_PHY_GEN_3;
> 
> 		writelfl(PIN_PHY_GEN_RX(sata_gen) |
> 			 PIN_PHY_GEN_TX(sata_gen) |
> 			 PIN_PU_TX | PIN_PU_RX | PIN_PU_PLL,
> 			 lp_phy_addr);

Yes, it is much more understandable.

> 
> 
> > +	/*
> > +	 * To allow disk hotplug on Armada 370/XP SoCs, the PHY speed must be
> > +	 * updated in the LP_PHY_CTL register.
> > +	 */
> > +	if (pdev->dev.of_node &&
> > +		of_device_is_compatible(pdev->dev.of_node,
> > +					"marvell,armada-370-xp-sata"))
> 
> Testing whether pdev->dev.of_node is not NULL does not seems to be
> useful. A quick read of of_device_is_compatible() and the function it's
> calling seem to indicate that of_device_is_compatible will return false
> if the passed struct device_node * is NULL.

I see.

It seems to me, you already have a patch ready to send. Isn't it ?
Or do you want me to do the update ?

Simon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140131/1e4dc2f0/attachment.sig>

^ 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