Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] ARM: move flexcan1 configuration to hummingboard
From: Shawn Guo @ 2014-01-19  3:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <E1W3rab-00009u-5I@rmk-PC.arm.linux.org.uk>

On Thu, Jan 16, 2014 at 06:22:49PM +0000, Russell King wrote:
> Flexcan1 is not used on the cubox-i, so move it out of the microsom.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

The patch will not apply against the branch/tag - imx-dt-3.14 I'm
sending to arm-soc.  Please re-generate it against the tag.

Acked-by: Shawn Guo <shawn.guo@linaro.org>

> ---
>  arch/arm/boot/dts/imx6dl-hummingboard.dts | 13 +++++++++++++
>  arch/arm/boot/dts/imx6qdl-microsom.dtsi   | 13 -------------
>  2 files changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts
> index 6184b0366926..e22f3d855c02 100644
> --- a/arch/arm/boot/dts/imx6dl-hummingboard.dts
> +++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts
> @@ -36,6 +36,12 @@
>  	};
>  };
>  
> +&can1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_hummingboard_flexcan1>;
> +	status = "okay";
> +};
> +
>  &i2c1 {
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&pinctrl_i2c1_1>;
> @@ -53,6 +59,13 @@
>  
>  &iomuxc {
>  	hummingboard {
> +		pinctrl_hummingboard_flexcan1: hummingboard-flexcan1 {
> +			fsl,pins = <
> +				MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX 0x80000000
> +				MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX 0x80000000
> +			>;
> +		};
> +
>  		pinctrl_hummingboard_gpio1_2: hummingboard-gpio1_2 {
>  			fsl,pins = <
>  				MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
> diff --git a/arch/arm/boot/dts/imx6qdl-microsom.dtsi b/arch/arm/boot/dts/imx6qdl-microsom.dtsi
> index 8aa31a842236..965ac4c1f509 100644
> --- a/arch/arm/boot/dts/imx6qdl-microsom.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-microsom.dtsi
> @@ -36,21 +36,8 @@
>  	};
>  };
>  
> -&can1 {
> -	pinctrl-names = "default";
> -	pinctrl-0 = <&pinctrl_microsom_flexcan1>;
> -	status = "okay";
> -};
> -
>  &iomuxc {
>  	microsom {
> -		pinctrl_microsom_flexcan1: microsom-flexcan1 {
> -			fsl,pins = <
> -				MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX 0x80000000
> -				MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX 0x80000000
> -			>;
> -		};
> -
>  		pinctrl_microsom_usbotg: microsom-usbotg {
>  			/*
>  			 * Similar to pinctrl_usbotg_2, but we want it
> -- 
> 1.8.3.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 0/2] DT updates for Hummingboard and new Cubox-i
From: Shawn Guo @ 2014-01-19  3:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140116182211.GX15937@n2100.arm.linux.org.uk>

On Thu, Jan 16, 2014 at 06:22:12PM +0000, Russell King - ARM Linux wrote:
> Now that the Cubox-i has been released, and I have one, I've been able to
> update things a little.  Out of the following two patches, the first one
> I think is critical to be merged before the microsom support hits
> mainline, since it drops the flexcan support from the microsom level,
> moving it to the Hummingboard level.

I will be out of town for a few days, and won't be online until next
weekend.  So please send the patch directly to arm-soc folks, so that
they can send it together with imx-dt-3.14 stuff.

arm-soc folks, please take this as another ping for my imx-dt-3.14 pull
request :)

Shawn

> 
> That doesn't have _too_ much visible effect, but it's something which
> should not be there (since as far as the microsom is concerned, there's
> nothing special about these pads.)

^ permalink raw reply

* [PATCH V8 1/3] ARM: imx: add suspend in ocram support for i.mx6q
From: Shawn Guo @ 2014-01-19  2:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389929947-25707-1-git-send-email-b20788@freescale.com>

On Fri, Jan 17, 2014 at 11:39:05AM +0800, Anson Huang wrote:
> When system enter suspend, we can set the DDR IO to
> high-Z state to save DDR IOs' power consumption, this
> operation can save many power(from ~26mA at 1.5V to ~15mA at 1.5V,
> measured on i.MX6Q SabreSD board, R25) of DDR IOs. To
> achieve that, we need to copy the suspend code to ocram
> and run the low level hardware related code(set DDR IOs
> to high-Z state) in ocram.
> 
> If there is no ocram space available, then system will
> still do suspend in external DDR, hence no DDR IOs will
> be set to high-Z.
> 
> The OCRAM usage layout is as below,
> 
> ocram suspend region(4K currently):
> ======================== high address ======================
>                               .
>                               .
>                               .
>                               ^
>                               ^
>                               ^
>                       imx6_suspend code
>              PM_INFO structure(imx6_cpu_pm_info)
> ======================== low address =======================
> 
> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Anson Huang <b20788@freescale.com>

Thanks for the work.  Applied all 3, thanks.

^ permalink raw reply

* [PATCH v7 0/2] ohci and ehci-platform clks, phy and dt support
From: Alan Stern @ 2014-01-19  2:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52DAA9F4.2090601@redhat.com>

On Sat, 18 Jan 2014, Hans de Goede wrote:

> > A simple copy from the PPC driver isn't quite enough, because the
> > platform data settings would override the DT values.
> > ehci_platform_reset has to be changed so that it sets
> > ehci->big_endian_desc and _mmio if the pdata flags are set, but
> > otherwise leaves them alone.
> >
> > Hans, would you like to write another patch to take care of this?
> 
> I already took a quick look at this, setting the ehci->big_endian* flags is easy,
> the problem is that they won't work unless we also define
> CONFIG_USB_EHCI_BIG_ENDIAN_DESC and CONFIG_USB_EHCI_BIG_ENDIAN_MMIO

That's right.  The platforms have to define those symbols if they use 
big-endian values (or even worse, mixed endian).

> I would like to avoid doing something like the ugliness we've with
> USB_OHCI_HCD_PPC_OF_BE and USB_OHCI_HCD_PPC_OF_LE, which means just selecting these
> 2 config options whenever USB_EHCI_HCD_PLATFORM is enabled, but I'm not sure if that
> is acceptable.

At the moment, I don't think it's so terrible.  That ohci_ppc ugliness
probably could have been avoided originally.  It looks like an attempt
to make sure you don't end up matching the hardware to a driver built
with the wrong endianness.  I imagine it would be less messy to detect 
that sort of problem at runtime.

> The same goes for the ohci code btw.

Certainly.

Alan Stern

^ permalink raw reply

* [PATCH] ARM i.MX: remove PWM platform support
From: Shawn Guo @ 2014-01-19  2:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389886782-11140-1-git-send-email-s.hauer@pengutronix.de>

On Thu, Jan 16, 2014 at 04:39:42PM +0100, Sascha Hauer wrote:
> As the i.MX pwm driver is devicetree only, remove the platform
> support for this device.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

Applied, thanks.

^ permalink raw reply

* [PATCH v4 0/7] mtd: spi-nor: add a new framework for SPI NOR
From: Huang Shijie @ 2014-01-19  2:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20980858CB6D3A4BAE95CA194937D5E73EA664C6@DBDE04.ent.ti.com>

On Fri, Jan 17, 2014 at 05:40:09PM +0000, Gupta, Pekon wrote:
> Hi Shijie,
> 
> >From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
> [...]
> >
> >I feel these are good points to discuss all.
> >1. With new framework seems like we need two separate controller drivers
> >    one for non spi-nor and one for spi-nor with single controller hw
> >2. With spi-nor implementation though the hw is spi complaint but the sw is
> >   completely ignoring the Linux SPI core interaction.
> >
> >I feel above two points are technically wrong - Please correct me if am wrong
> >but need all developers will join..thanks!
> >
> I have been following this patch-set from sometime, And I think point (2)
> has been discussed back and forth in multiple times in earlier discussions.
> So, Is it possible for you to summarize point (2) with all pros-n-cons ?
> 
> - A README will helpful to clear all doubts and will ease your implementation
>   as well.
> - It will also help in reducing turn-around time to get this framework in
>    acceptable state and still keep it generic enough.
> 
> You can submit the README as Documentation/mtd/spi-nor.txt
okay.

thanks
Huang Shijie

^ permalink raw reply

* [PATCH] ARM: dts: imx6q: Add support for Zealz GK802
From: Shawn Guo @ 2014-01-19  2:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876499-24247-1-git-send-email-s.hauer@pengutronix.de>

On Thu, Jan 16, 2014 at 01:48:19PM +0100, Sascha Hauer wrote:
> Add support for the GK802 'QUAD CORE Mini PC', which seems to be loosely
> based on the Freescale i.MX6Q HDMI dongle reference design.
> It is supposedly identical to the Hiapad Hi802.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>

The patch has a couple of minor things like we did for patch 'ARM: dts:
imx6: Add DFI FS700-M60 board support' to fix up.  I fixed them up and
apply the patch.

Shawn

> ---
>  arch/arm/boot/dts/Makefile        |   1 +
>  arch/arm/boot/dts/imx6q-gk802.dts | 151 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 152 insertions(+)
>  create mode 100644 arch/arm/boot/dts/imx6q-gk802.dts
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index aeb8053..9ed00a0 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -171,6 +171,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
>  	imx6q-arm2.dtb \
>  	imx6q-cm-fx6.dtb \
>  	imx6q-dmo-edmqmx6.dtb \
> +	imx6q-gk802.dtb \
>  	imx6q-gw51xx.dtb \
>  	imx6q-gw52xx.dtb \
>  	imx6q-gw53xx.dtb \
> diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/imx6q-gk802.dts
> new file mode 100644
> index 0000000..0d010df
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx6q-gk802.dts
> @@ -0,0 +1,151 @@
> +/*
> + * Copyright (C) 2013 Philipp Zabel
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2.  This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +/dts-v1/;
> +#include "imx6q.dtsi"
> +
> +/ {
> +	model = "Zealz GK802";
> +	compatible = "zealz,imx6q-gk802", "fsl,imx6q";
> +
> +	chosen {
> +		linux,stdout-path = &uart4;
> +	};
> +
> +	memory {
> +		reg = <0x10000000 0x40000000>;
> +	};
> +
> +	regulators {
> +		compatible = "simple-bus";
> +
> +		reg_3p3v: 3p3v {
> +			compatible = "regulator-fixed";
> +			regulator-name = "3P3V";
> +			regulator-min-microvolt = <3300000>;
> +			regulator-max-microvolt = <3300000>;
> +			regulator-always-on;
> +		};
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +
> +		recovery-button {
> +			label = "recovery";
> +			gpios = <&gpio3 16 1>;
> +			linux,code = <0x198>; /* KEY_RESTART */
> +			gpio-key,wakeup;
> +		};
> +	};
> +};
> +
> +/* Internal I2C */
> +&i2c2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_i2c2_gk802>;
> +	clock-frequency = <100000>;
> +	status = "okay";
> +
> +	/* SDMC DM2016 1024 bit EEPROM + 128 bit OTP */
> +	eeprom: dm2016 at 51 {
> +		compatible = "sdmc,dm2016";
> +		reg = <0x51>;
> +	};
> +};
> +
> +/* External I2C via HDMI */
> +&i2c3 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_i2c3_gk802>;
> +	clock-frequency = <100000>;
> +	status = "okay";
> +};
> +
> +&iomuxc {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_hog>;
> +
> +	hog {
> +		pinctrl_hog: hoggrp {
> +			fsl,pins = <
> +				/* Recovery button, active-low */
> +				MX6QDL_PAD_EIM_D16__GPIO3_IO16  0x100b1
> +				/* RTL8192CU enable GPIO, active-low */
> +				MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
> +			>;
> +		};
> +	};
> +
> +	i2c {
> +		pinctrl_i2c2_gk802: i2c2grp-1 {
> +			fsl,pins = <MX6QDL_I2C2_PINGRP2>;
> +		};
> +
> +		pinctrl_i2c3_gk802: i2c3grp-1 {
> +			fsl,pins = <MX6QDL_I2C3_PINGRP3>;
> +		};
> +	};
> +
> +	uart {
> +		pinctrl_uart4: uart4grp {
> +			fsl,pins = <MX6QDL_UART4_PINGRP1>;
> +		};
> +	};
> +
> +	usdhc {
> +		pinctrl_usdhc3: usdhc3grp {
> +			fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
> +		};
> +
> +		pinctrl_usdhc4: usdhc4grp {
> +			fsl,pins = <MX6QDL_USDHC4_PINGRP_D4>;
> +		};
> +	};
> +};
> +
> +&uart2 {
> +	status = "okay";
> +};
> +
> +&uart4 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_uart4>;
> +	status = "okay";
> +};
> +
> +/* External USB-A port (USBOTG) */
> +&usbotg {
> +	disable-over-current;
> +	status = "okay";
> +};
> +
> +/* Internal USB port (USBH1), connected to RTL8192CU */
> +&usbh1 {
> +	disable-over-current;
> +	status = "okay";
> +};
> +
> +/* External microSD */
> +&usdhc3 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usdhc3>;
> +	bus-width = <4>;
> +	cd-gpios = <&gpio6 11 0>;
> +	vmmc-supply = <&reg_3p3v>;
> +	status = "okay";
> +};
> +
> +/* Internal microSD */
> +&usdhc4 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usdhc4>;
> +	bus-width = <4>;
> +	vmmc-supply = <&reg_3p3v>;
> +	status = "okay";
> +};
> -- 
> 1.8.5.2
> 

^ permalink raw reply

* [PATCH v4 0/7] mtd: spi-nor: add a new framework for SPI NOR
From: Huang Shijie @ 2014-01-19  2:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD6G_RSF_TPk8g9CNmSc+xs+9psLmJoakZw3Eqf-a8KD5P4AVg@mail.gmail.com>


? 2014?01?17? 16:39, Jagan Teki ??:
> On Fri, Jan 17, 2014 at 12:24 PM, Huang Shijie <b32955@freescale.com> wrote:
>> On Fri, Jan 17, 2014 at 12:36:08PM +0530, Jagan Teki wrote:
>>>>> My basic question is like I have a qspi spi controller in my SOC and I
>>>>> designed two boards B1 and B2
>>>> okay.
>>>>
>>>>> B1 with quad spi controller connected with non-flash as a slave and B2
>>>>> with quad spi controller connected
>>>>> with quad flash as a slave.
>>>> You can use the framework for B2. But for B1, you should not use the framework,
>>>> since this framework is just for the SPI-NOR. If you do not connected with
>>>> a NOR, i think it's better to code another driver for your controller.
>>> Means we have two separate controller drivers for same controller one
>>> with spi-nor and
>>> another with spi is it?
>> Take drivers/spi/spi-imx.c for example, if you connect a NOR to it, you only
>> need to add a NOR device node in the device tree. In the probe, it will call
>> the m25p80.c to probe the NOR device.
>>
>> But if we connect other device to it. you should set another device node for it.
>>
>> I am not sure if your controller driver can works as the spi-imx.c
> My question here was - this new framework suggest to write a two
> different controller
> drivers one is for non spi-nor and spi-nor models? do you agree that?


If your controller can either connects to a NOR, or can connects to 
other devices, it means your controller is a _BUS_.
You just need to write the bus driver for your controller, such as the 
spi-imx.c and drivers/bus/imx-weim.c do.

Since you have connect a device to your controller. you also need to 
write a driver for your device, such as the m25p80.c is
for your spi nor device.

Just think about that how do you code your driver for SPI NOR _without_ 
this framework:
do your driver need to call the m25p80.c? if you do call the m25p80.c, 
you actually write your so-called "two drivers" :)


This framework does not change any logic for the current kernel, except 
adding a layer. With the new layer, we can code the
driver for the controllers which is a SPI-NOR controller, not a SPI bus 
controller.


>
> And also one important note from your design was spi-nor mode is
> completely bypassing
> Linux spi core is that the good idea?
>
yes. I think it's a good idea.

As Mark even pointed, the freescale's Quadspi controller is not a SPI 
controller, it is a SPI-NOR controller, it does _not_ need the
LINUX SPI core.


thanks
Huang Shijie

^ permalink raw reply

* [PATCH] ARM: kirkwood: kirkwood_pm_init() should return void
From: Ezequiel Garcia @ 2014-01-19  0:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140118235411.GN29184@titan.lakedaemon.net>

On Sat, Jan 18, 2014 at 06:54:11PM -0500, Jason Cooper wrote:
> On Fri, Jan 17, 2014 at 03:52:11PM -0300, Ezequiel Garcia wrote:
> > This function was originally meant to return void as declared in the
> > common.h header. Fix it and include the header to catch these errors
> > in the future.
> > 
> > Reported-by: Andrew Lunn <andrew@lunn.ch>
> > Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> > ---
> >  arch/arm/mach-kirkwood/pm.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> merf.  I get the following warning when building kirkwood_defconfig:
> 
> arch/arm/mach-kirkwood/pm.c: In function 'kirkwood_pm_init':
> arch/arm/mach-kirkwood/pm.c:73:2: warning: 'return' with a value, in function returning void [enabled by default]
> 

Doh...

> I've amended the patch as below and pushed it to mvebu/fixes
> 

Thanks!
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH] ARM: kirkwood: kirkwood_pm_init() should return void
From: Jason Cooper @ 2014-01-18 23:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389984731-20220-1-git-send-email-ezequiel.garcia@free-electrons.com>

On Fri, Jan 17, 2014 at 03:52:11PM -0300, Ezequiel Garcia wrote:
> This function was originally meant to return void as declared in the
> common.h header. Fix it and include the header to catch these errors
> in the future.
> 
> Reported-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---
>  arch/arm/mach-kirkwood/pm.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

merf.  I get the following warning when building kirkwood_defconfig:

arch/arm/mach-kirkwood/pm.c: In function 'kirkwood_pm_init':
arch/arm/mach-kirkwood/pm.c:73:2: warning: 'return' with a value, in function returning void [enabled by default]

I've amended the patch as below and pushed it to mvebu/fixes

thx,

Jason.

--------->8--------------------
commit 77dfdeb41125b6468790fa4c620da262c910cbc9
Author: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Date:   Fri Jan 17 15:52:11 2014 -0300

    ARM: kirkwood: kirkwood_pm_init() should return void
    
    This function was originally meant to return void as declared in the
    common.h header. Fix it and include the header to catch these errors
    in the future.
    
    [jac] removed 'return 0;' to clear this warning:
    
      arch/arm/mach-kirkwood/pm.c: In function 'kirkwood_pm_init':
      arch/arm/mach-kirkwood/pm.c:73:2: warning: 'return' with a value, in function returning void [enabled by default]
    
    Reported-by: Andrew Lunn <andrew@lunn.ch>
    Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
    Acked-by: Andrew Lunn <andrew@lunn.ch>
    Signed-off-by: Jason Cooper <jason@lakedaemon.net>

diff --git a/arch/arm/mach-kirkwood/pm.c b/arch/arm/mach-kirkwood/pm.c
index 8783a7184e73..c6ab8d9303a5 100644
--- a/arch/arm/mach-kirkwood/pm.c
+++ b/arch/arm/mach-kirkwood/pm.c
@@ -18,6 +18,7 @@
 #include <linux/suspend.h>
 #include <linux/io.h>
 #include <mach/bridge-regs.h>
+#include "common.h"
 
 static void __iomem *ddr_operation_base;
 
@@ -65,9 +66,8 @@ static const struct platform_suspend_ops kirkwood_suspend_ops = {
 	.valid = kirkwood_pm_valid_standby,
 };
 
-int __init kirkwood_pm_init(void)
+void __init kirkwood_pm_init(void)
 {
 	ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
 	suspend_set_ops(&kirkwood_suspend_ops);
-	return 0;
 }

^ permalink raw reply related

* [RFC v3 13/13] ARM: sun7i: dts: Add ahci / sata support
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

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..785fac0 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";
 		};
 
+		sata: ahci 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..68e0809 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";
 		};
 
+		sata: ahci 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..8a289c4 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";
 		};
 
+		sata: ahci 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..fc1be33 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -347,6 +347,14 @@
 			status = "disabled";
 		};
 
+		sata: ahci at 01c18000 {
+			compatible = "allwinner,sun4i-a10-ahci";
+			reg = <0x01c18000 0x1000>;
+			interrupts = <0 56 1>;
+			clocks = <&pll6 0>, <&ahb_gates 25>;
+			status = "disabled";
+		};
+
 		pio: pinctrl at 01c20800 {
 			compatible = "allwinner,sun7i-a20-pinctrl";
 			reg = <0x01c20800 0x400>;
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 12/13] ARM: sun4i: dts: Add ahci / sata support
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

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 ++++++++++++++++++++++++++++++
 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..fd6d512 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";
 		};
 
+		sata: ahci 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..d23aaa8 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";
 		};
 
+		sata: ahci 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..09517c3 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -331,6 +331,14 @@
 			status = "disabled";
 		};
 
+		sata: ahci at 01c18000 {
+			compatible = "allwinner,sun4i-a10-ahci";
+			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>;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		pinctrl-names = "default";
+
+		reg_ahci_5v: ahci-5v {
+			compatible = "regulator-fixed";
+			regulator-name = "ahci-5v";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			pinctrl-0 = <&ahci_pwr_pin_a>;
+			gpio = <&pio 1 8 0>;
+			enable-active-high;
+		};
+	};
+};
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 11/13] ahci-imx: Don't create a nested platform device from probe
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

Instead only provide platform_data through of_device_id, like the ahci-sunxi
driver does.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/ata/Kconfig           |   4 +-
 drivers/ata/Makefile          |   3 +-
 drivers/ata/ahci_imx.c        | 118 ++++++------------------------------------
 drivers/ata/ahci_platform.c   |   3 ++
 include/linux/ahci_platform.h |   1 +
 5 files changed, 22 insertions(+), 107 deletions(-)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 5f6c11a..05523ad 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -98,11 +98,11 @@ config SATA_AHCI_PLATFORM
 	  If unsure, say N.
 
 config AHCI_IMX
-	tristate "Freescale i.MX AHCI SATA support"
+	bool "Freescale i.MX AHCI SATA support"
 	depends on SATA_AHCI_PLATFORM && MFD_SYSCON
 	help
 	  This option enables support for the Freescale i.MX SoC's
-	  onboard AHCI SATA.
+	  onboard AHCI SATA in the ahci_platform driver.
 
 	  If unsure, say N.
 
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 4d8778c..99f4715 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -10,9 +10,8 @@ obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o
 obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o libahci.o
-obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o
 
-ahci_plat-objs := ahci_platform.o ahci_sunxi.o
+ahci_plat-objs := ahci_platform.o ahci_imx.o ahci_sunxi.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 8eb24a3..6e0178f 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -28,6 +28,8 @@
 #include <linux/libata.h>
 #include "ahci.h"
 
+#ifdef CONFIG_AHCI_IMX
+
 enum {
 	PORT_PHY_CTL = 0x178,			/* Port0 PHY Control */
 	PORT_PHY_CTL_PDDQ_LOC = 0x100000,	/* PORT_PHY_CTL bits */
@@ -57,7 +59,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
 	struct ata_host *host = dev_get_drvdata(ap->dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	void __iomem *mmio = hpriv->mmio;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 	int i;
 
 	ahci_error_handler(ap);
@@ -104,8 +106,13 @@ static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
 			   void __iomem *mmio)
 {
 	unsigned int reg_val;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+	struct imx_ahci_priv *imxpriv;
+
+	imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
+	if (!imxpriv)
+		return -ENOMEM;
 
+	hpriv->plat_data = imxpriv;
 	imxpriv->gpr =
 		syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (IS_ERR(imxpriv->gpr)) {
@@ -173,7 +180,7 @@ static void imx6q_sata_exit(struct device *dev)
 {
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 
 	if (hpriv->clks[CLK_SATA])
 		regmap_update_bits(imxpriv->gpr, 0x34,
@@ -185,7 +192,7 @@ static void imx_ahci_suspend(struct device *dev)
 {
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 
 	/* Check the CLKs have not been gated off in the initialization. */
 	if (hpriv->clks[CLK_SATA])
@@ -198,7 +205,7 @@ static int imx_ahci_resume(struct device *dev)
 {
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
-	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+	struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 
 	if (hpriv->clks[CLK_SATA]) {
 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
@@ -210,7 +217,7 @@ static int imx_ahci_resume(struct device *dev)
 	return 0;
 }
 
-static struct ahci_platform_data imx6q_sata_pdata = {
+struct ahci_platform_data imx6q_sata_pdata = {
 	.init = imx6q_sata_init,
 	.exit = imx6q_sata_exit,
 	.ata_port_info = &ahci_imx_port_info,
@@ -218,102 +225,7 @@ static struct ahci_platform_data imx6q_sata_pdata = {
 	.resume = imx_ahci_resume,
 };
 
-static const struct of_device_id imx_ahci_of_match[] = {
-	{ .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata},
-	{},
-};
-MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
-
-static int imx_ahci_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *mem, *irq, res[2];
-	const struct of_device_id *of_id;
-	const struct ahci_platform_data *pdata = NULL;
-	struct imx_ahci_priv *imxpriv;
-	struct device *ahci_dev;
-	struct platform_device *ahci_pdev;
-	int ret;
-
-	imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
-	if (!imxpriv) {
-		dev_err(dev, "can't alloc ahci_host_priv\n");
-		return -ENOMEM;
-	}
-
-	ahci_pdev = platform_device_alloc("ahci", -1);
-	if (!ahci_pdev)
-		return -ENODEV;
-
-	ahci_dev = &ahci_pdev->dev;
-	ahci_dev->parent = dev;
-
-	imxpriv->first_time = true;
-	imxpriv->ahci_pdev = ahci_pdev;
-	platform_set_drvdata(pdev, imxpriv);
-
-	of_id = of_match_device(imx_ahci_of_match, dev);
-	if (of_id) {
-		pdata = of_id->data;
-	} else {
-		ret = -EINVAL;
-		goto err_out;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!mem || !irq) {
-		dev_err(dev, "no mmio/irq resource\n");
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	res[0] = *mem;
-	res[1] = *irq;
-
-	ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
-	ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
-	ahci_dev->of_node = dev->of_node;
-
-	ret = platform_device_add_resources(ahci_pdev, res, 2);
-	if (ret)
-		goto err_out;
-
-	ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
-	if (ret)
-		goto err_out;
-
-	ret = platform_device_add(ahci_pdev);
-	if (ret) {
-err_out:
-		platform_device_put(ahci_pdev);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int imx_ahci_remove(struct platform_device *pdev)
-{
-	struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
-	struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
-
-	platform_device_unregister(ahci_pdev);
-	return 0;
-}
-
-static struct platform_driver imx_ahci_driver = {
-	.probe = imx_ahci_probe,
-	.remove = imx_ahci_remove,
-	.driver = {
-		.name = "ahci-imx",
-		.owner = THIS_MODULE,
-		.of_match_table = imx_ahci_of_match,
-	},
-};
-module_platform_driver(imx_ahci_driver);
-
-MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
 MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
-MODULE_LICENSE("GPL");
 MODULE_ALIAS("ahci:imx");
+
+#endif
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 324d066..9022922 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -96,6 +96,9 @@ static const struct of_device_id ahci_of_match[] = {
 	{ .compatible = "allwinner,sun4i-a10-ahci",
 	  .data = &ahci_sunxi_pdata, },
 #endif
+#ifdef CONFIG_AHCI_IMX
+	{ .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata, },
+#endif
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 4e6cbe0..19623ad 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -33,5 +33,6 @@ struct ahci_platform_data {
 };
 
 extern struct ahci_platform_data ahci_sunxi_pdata;
+extern struct ahci_platform_data imx6q_sata_pdata;
 
 #endif /* _AHCI_PLATFORM_H */
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 10/13] ahci_imx: Adjust for ahci_platform managing the clocks
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

ahci_platform manages all 3 clocks now, so enabling / disabling them from
ahci_imx just results in the sata_ref clock getting enabled / disabled twice.

Note untested, I've ordered a wandboard to be able to test these changes.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../devicetree/bindings/ata/ahci-platform.txt      |  8 ++-
 drivers/ata/ahci_imx.c                             | 82 +++++++++-------------
 2 files changed, 40 insertions(+), 50 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index f036e786..ee3a127 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -5,8 +5,8 @@ Each SATA controller should have its own node.
 
 Required properties:
 - compatible        : compatible list, one of "snps,spear-ahci",
-                      "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
-                      "allwinner,sun4i-a10-ahci"
+                      "snps,exynos5440-ahci", "ibm,476gtr-ahci",
+                      "allwinner,sun4i-a10-ahci" or "fsl,imx6q-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
@@ -18,6 +18,10 @@ Optional properties:
 allwinner,sun4i-a10-ahci required properties:
 - clocks            : index 0 must point to the sata_ref clk, 1 to the ahb clk
 
+fsl,imx6q-ahci required properties:
+- clocks            : index 0 must point to the sataf clk, 1 to the sata_ref
+		      clk and 2 to the ahb clk
+
 Examples:
         sata at ffe08000 {
 		compatible = "snps,spear-ahci";
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 0051f29..8eb24a3 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -34,12 +34,15 @@ enum {
 	HOST_TIMER1MS = 0xe0,			/* Timer 1-ms */
 };
 
+enum {
+	CLK_SATA,
+	CLK_SATA_REF,
+	CLK_AHB
+};
+
 struct imx_ahci_priv {
 	struct platform_device *ahci_pdev;
-	struct clk *sata_ref_clk;
-	struct clk *ahb_clk;
 	struct regmap *gpr;
-	bool no_device;
 	bool first_time;
 };
 
@@ -55,6 +58,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
 	struct ahci_host_priv *hpriv = host->private_data;
 	void __iomem *mmio = hpriv->mmio;
 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+	int i;
 
 	ahci_error_handler(ap);
 
@@ -75,8 +79,13 @@ static void ahci_imx_error_handler(struct ata_port *ap)
 	regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 			IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 			!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-	clk_disable_unprepare(imxpriv->sata_ref_clk);
-	imxpriv->no_device = true;
+
+	for (i = CLK_AHB; i >= 0; i--) {
+		clk_disable_unprepare(hpriv->clks[i]);
+		/* Stop ahci_platform.c from trying to use the clks */
+		clk_put(hpriv->clks[i]);
+		hpriv->clks[i] = NULL;
+	}
 }
 
 static struct ata_port_operations ahci_imx_ops = {
@@ -94,7 +103,6 @@ static const struct ata_port_info ahci_imx_port_info = {
 static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
 			   void __iomem *mmio)
 {
-	int ret = 0;
 	unsigned int reg_val;
 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
@@ -105,12 +113,6 @@ static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
 		return PTR_ERR(imxpriv->gpr);
 	}
 
-	ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-	if (ret < 0) {
-		dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret);
-		return ret;
-	}
-
 	/*
 	 * set PHY Paremeters, two steps to configure the GPR13,
 	 * one write for rest of parameters, mask of first write
@@ -157,7 +159,11 @@ static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
 		writel(reg_val, mmio + HOST_PORTS_IMPL);
 	}
 
-	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
+	if (!hpriv->clks[CLK_AHB]) {
+		dev_err(dev, "no ahb clk, need sata, sata_ref and ahb clks\n");
+		return -ENOENT;
+	}
+	reg_val = clk_get_rate(hpriv->clks[CLK_AHB]) / 1000;
 	writel(reg_val, mmio + HOST_TIMER1MS);
 
 	return 0;
@@ -165,41 +171,36 @@ static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
 
 static void imx6q_sata_exit(struct device *dev)
 {
-	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
-	regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+	if (hpriv->clks[CLK_SATA])
+		regmap_update_bits(imxpriv->gpr, 0x34,
+			IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 			!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-	clk_disable_unprepare(imxpriv->sata_ref_clk);
 }
 
 static void imx_ahci_suspend(struct device *dev)
 {
-	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
-	/*
-	 * If no_device is set, The CLKs had been gated off in the
-	 * initialization so don't do it again here.
-	 */
-	if (!imxpriv->no_device) {
+	/* Check the CLKs have not been gated off in the initialization. */
+	if (hpriv->clks[CLK_SATA])
 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 				IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 				!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-		clk_disable_unprepare(imxpriv->sata_ref_clk);
-	}
 }
 
 static int imx_ahci_resume(struct device *dev)
 {
-	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-	int ret;
-
-	if (!imxpriv->no_device) {
-		ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-		if (ret < 0) {
-			dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret);
-			return ret;
-		}
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
+	if (hpriv->clks[CLK_SATA]) {
 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 				IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 				IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -247,22 +248,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
 	ahci_dev = &ahci_pdev->dev;
 	ahci_dev->parent = dev;
 
-	imxpriv->no_device = false;
 	imxpriv->first_time = true;
-	imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
-	if (IS_ERR(imxpriv->ahb_clk)) {
-		dev_err(dev, "can't get ahb clock.\n");
-		ret = PTR_ERR(imxpriv->ahb_clk);
-		goto err_out;
-	}
-
-	imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
-	if (IS_ERR(imxpriv->sata_ref_clk)) {
-		dev_err(dev, "can't get sata_ref clock.\n");
-		ret = PTR_ERR(imxpriv->sata_ref_clk);
-		goto err_out;
-	}
-
 	imxpriv->ahci_pdev = ahci_pdev;
 	platform_set_drvdata(pdev, imxpriv);
 
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 09/13] ARM: sunxi: Add support for Allwinner SUNXi SoCs sata to ahci_platform
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

From: Olliver Schinagl <oliver@schinagl.nl>

This patch adds support for the ahci sata controler found on Allwinner A10
and A20 SoCs to the ahci_platform driver.

Orignally written by Olliver Schinagl using the approach of having a platform
device which probe method creates a new child platform device which gets
driven by ahci_platform.c, as done by ahci_imx.c .

Refactored by Hans de Goede to add most of the non sunxi specific functionality
to ahci_platform.c and use a platform_data pointer from of_device_id for the
sunxi specific bits.

Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../devicetree/bindings/ata/ahci-platform.txt      |  18 +-
 drivers/ata/Kconfig                                |   9 +
 drivers/ata/Makefile                               |   4 +-
 drivers/ata/ahci_platform.c                        |   4 +
 drivers/ata/ahci_sunxi.c                           | 182 +++++++++++++++++++++
 include/linux/ahci_platform.h                      |   2 +
 6 files changed, 215 insertions(+), 4 deletions(-)
 create mode 100644 drivers/ata/ahci_sunxi.c

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 1ac807f..f036e786 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -4,7 +4,9 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
 Each SATA controller should have its own node.
 
 Required properties:
-- compatible        : compatible list, contains "snps,spear-ahci"
+- compatible        : compatible list, one of "snps,spear-ahci",
+                      "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
+                      "allwinner,sun4i-a10-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
@@ -13,10 +15,20 @@ Optional properties:
 - clocks            : a list of phandle + clock specifier pairs
 - target-supply     : regulator for SATA target power
 
-Example:
+allwinner,sun4i-a10-ahci required properties:
+- clocks            : index 0 must point to the sata_ref clk, 1 to the ahb clk
+
+Examples:
         sata at ffe08000 {
 		compatible = "snps,spear-ahci";
 		reg = <0xffe08000 0x1000>;
 		interrupts = <115>;
-
         };
+
+	sata: ahci at 01c18000 {
+		compatible = "allwinner,sun4i-a10-ahci";
+		reg = <0x01c18000 0x1000>;
+		interrupts = <56>;
+		clocks = <&pll6 0>, <&ahb_gates 25>;
+		target-supply = <&reg_ahci_5v>;
+	};
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4e73772..5f6c11a 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -106,6 +106,15 @@ config AHCI_IMX
 
 	  If unsure, say N.
 
+config AHCI_SUNXI
+	bool "Allwinner sunxi AHCI SATA support"
+	depends on ARCH_SUNXI && SATA_AHCI_PLATFORM
+	help
+	  This option enables support for the Allwinner sunxi SoC's
+	  onboard AHCI SATA in the ahci_platform driver.
+
+	  If unsure, say N.
+
 config SATA_FSL
 	tristate "Freescale 3.0Gbps SATA support"
 	depends on FSL_SOC
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 46518c6..4d8778c 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_ATA)		+= libata.o
 # non-SFF interface
 obj-$(CONFIG_SATA_AHCI)		+= ahci.o libahci.o
 obj-$(CONFIG_SATA_ACARD_AHCI)	+= acard-ahci.o libahci.o
-obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
+obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_plat.o libahci.o
 obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o
 obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o
@@ -12,6 +12,8 @@ obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o libahci.o
 obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o
 
+ahci_plat-objs := ahci_platform.o ahci_sunxi.o
+
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
 obj-$(CONFIG_PATA_ARASAN_CF)	+= pata_arasan_cf.o
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 0676d72..324d066 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -92,6 +92,10 @@ static const struct of_device_id ahci_of_match[] = {
 	{ .compatible = "snps,spear-ahci", },
 	{ .compatible = "snps,exynos5440-ahci", },
 	{ .compatible = "ibm,476gtr-ahci", },
+#ifdef CONFIG_AHCI_SUNXI
+	{ .compatible = "allwinner,sun4i-a10-ahci",
+	  .data = &ahci_sunxi_pdata, },
+#endif
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
new file mode 100644
index 0000000..cf357bf
--- /dev/null
+++ b/drivers/ata/ahci_sunxi.c
@@ -0,0 +1,182 @@
+/*
+ * Allwinner sunxi AHCI SATA platform driver
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
+ * Daniel Wang <danielwang@allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include "ahci.h"
+
+#define AHCI_BISTAFR 0x00a0
+#define AHCI_BISTCR 0x00a4
+#define AHCI_BISTFCTR 0x00a8
+#define AHCI_BISTSR 0x00ac
+#define AHCI_BISTDECR 0x00b0
+#define AHCI_DIAGNR0 0x00b4
+#define AHCI_DIAGNR1 0x00b8
+#define AHCI_OOBR 0x00bc
+#define AHCI_PHYCS0R 0x00c0
+#define AHCI_PHYCS1R 0x00c4
+#define AHCI_PHYCS2R 0x00c8
+#define AHCI_TIMER1MS 0x00e0
+#define AHCI_GPARAM1R 0x00e8
+#define AHCI_GPARAM2R 0x00ec
+#define AHCI_PPARAMR 0x00f0
+#define AHCI_TESTR 0x00f4
+#define AHCI_VERSIONR 0x00f8
+#define AHCI_IDR 0x00fc
+#define AHCI_RWCR 0x00fc
+#define AHCI_P0DMACR 0x0170
+#define AHCI_P0PHYCR 0x0178
+#define AHCI_P0PHYSR 0x017c
+
+#ifdef CONFIG_AHCI_SUNXI
+
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
+{
+	u32 reg_val;
+
+	reg_val = readl(reg);
+	reg_val &= ~(clr_val);
+	writel(reg_val, reg);
+}
+
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
+{
+	u32 reg_val;
+
+	reg_val = readl(reg);
+	reg_val |= set_val;
+	writel(reg_val, reg);
+}
+
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
+{
+	u32 reg_val;
+
+	reg_val = readl(reg);
+	reg_val &= ~(clr_val);
+	reg_val |= set_val;
+	writel(reg_val, reg);
+}
+
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
+{
+	return (readl(reg) >> shift) & mask;
+}
+
+static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+{
+	u32 reg_val;
+	int timeout;
+
+	/* This magic is from the original code */
+	writel(0, reg_base + AHCI_RWCR);
+	mdelay(5);
+
+	sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+			 (0x7 << 24),
+			 (0x5 << 24) | BIT(23) | BIT(18));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
+			 (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
+			 (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
+	sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
+	sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+			 (0x7 << 20), (0x3 << 20));
+	sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
+			 (0x1f << 5), (0x19 << 5));
+	mdelay(5);
+
+	sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+	timeout = 0x100000;
+	do {
+		reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
+	} while (--timeout && (reg_val != 0x2));
+	if (!timeout) {
+		dev_err(dev, "PHY power up failed.\n");
+		return -EIO;
+	}
+
+	sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
+
+	timeout = 0x100000;
+	do {
+		reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
+	} while (--timeout && reg_val);
+	if (!timeout) {
+		dev_err(dev, "PHY calibration failed.\n");
+		return -EIO;
+	}
+	mdelay(15);
+
+	writel(0x7, reg_base + AHCI_RWCR);
+
+	return 0;
+}
+
+static void ahci_sunxi_start_engine(struct ata_port *ap)
+{
+	void __iomem *port_mmio = ahci_port_base(ap);
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+
+	/* Setup DMA before DMA start */
+	sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
+
+	/* Start DMA */
+	sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
+}
+
+static int ahci_sunxi_init(struct device *dev, struct ahci_host_priv *hpriv,
+			   void __iomem *reg_base)
+{
+	hpriv->start_engine = ahci_sunxi_start_engine;
+	return ahci_sunxi_phy_init(dev, reg_base);
+}
+
+int ahci_sunxi_resume(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+
+	return ahci_sunxi_phy_init(dev, hpriv->mmio);
+}
+
+static const struct ata_port_info ahci_sunxi_port_info = {
+	AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+			  AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
+	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+	.pio_mask	= ATA_PIO4,
+	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &ahci_platform_ops,
+};
+
+struct ahci_platform_data ahci_sunxi_pdata = {
+	.init = ahci_sunxi_init,
+	.resume = ahci_sunxi_resume,
+	.ata_port_info = &ahci_sunxi_port_info,
+};
+
+#endif
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 796dfb4..4e6cbe0 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -32,4 +32,6 @@ struct ahci_platform_data {
 	unsigned int mask_port_map;
 };
 
+extern struct ahci_platform_data ahci_sunxi_pdata;
+
 #endif /* _AHCI_PLATFORM_H */
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 08/13] ahci-platform: Allow specifying platform_data through of_device_id
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/ata/ahci_platform.c | 41 +++++++++++++++++++++++++++++------------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 3bc2dab..0676d72 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/libata.h>
 #include <linux/ahci_platform.h>
@@ -87,6 +88,30 @@ static struct scsi_host_template ahci_platform_sht = {
 	AHCI_SHT("ahci_platform"),
 };
 
+static const struct of_device_id ahci_of_match[] = {
+	{ .compatible = "snps,spear-ahci", },
+	{ .compatible = "snps,exynos5440-ahci", },
+	{ .compatible = "ibm,476gtr-ahci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
+static const struct ahci_platform_data *ahci_get_pdata(struct device *dev)
+{
+	struct ahci_platform_data *pdata;
+	const struct of_device_id *of_id;
+
+	pdata = dev_get_platdata(dev);
+	if (pdata)
+		return pdata;
+
+	of_id = of_match_device(ahci_of_match, dev);
+	if (of_id)
+		return of_id->data;
+
+	return NULL;
+}
+
 static int ahci_enable_clks(struct device *dev, struct ahci_host_priv *hpriv)
 {
 	int c, rc;
@@ -126,7 +151,7 @@ static void ahci_put_clks(struct ahci_host_priv *hpriv)
 static int ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	const struct ahci_platform_data *pdata = ahci_get_pdata(dev);
 	const struct platform_device_id *id = platform_get_device_id(pdev);
 	struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -290,7 +315,7 @@ free_clk:
 static void ahci_host_stop(struct ata_host *host)
 {
 	struct device *dev = host->dev;
-	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	const struct ahci_platform_data *pdata = ahci_get_pdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 
 	if (hpriv->target_pwr)
@@ -306,7 +331,7 @@ static void ahci_host_stop(struct ata_host *host)
 #ifdef CONFIG_PM_SLEEP
 static int ahci_suspend(struct device *dev)
 {
-	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	const struct ahci_platform_data *pdata = ahci_get_pdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	void __iomem *mmio = hpriv->mmio;
@@ -345,7 +370,7 @@ static int ahci_suspend(struct device *dev)
 
 static int ahci_resume(struct device *dev)
 {
-	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	const struct ahci_platform_data *pdata = ahci_get_pdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	int rc;
@@ -393,14 +418,6 @@ disable_unprepare_clk:
 
 static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
 
-static const struct of_device_id ahci_of_match[] = {
-	{ .compatible = "snps,spear-ahci", },
-	{ .compatible = "snps,exynos5440-ahci", },
-	{ .compatible = "ibm,476gtr-ahci", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ahci_of_match);
-
 static struct platform_driver ahci_driver = {
 	.probe = ahci_probe,
 	.remove = ata_platform_remove_one,
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 07/13] ahci-platform: Add support for an optional regulator for sata-target power
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../devicetree/bindings/ata/ahci-platform.txt      |  1 +
 drivers/ata/ahci.h                                 |  2 ++
 drivers/ata/ahci_platform.c                        | 39 +++++++++++++++++++---
 3 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 3ced07d..1ac807f 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -11,6 +11,7 @@ Required properties:
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
 - clocks            : a list of phandle + clock specifier pairs
+- target-supply     : regulator for SATA target power
 
 Example:
         sata at ffe08000 {
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 7950b3a..c3e0c49 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -36,6 +36,7 @@
 #define _AHCI_H
 
 #include <linux/clk.h>
+#include <linux/regulator/consumer.h>
 #include <linux/libata.h>
 
 /* Enclosure Management Control */
@@ -323,6 +324,7 @@ struct ahci_host_priv {
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
 	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
+	struct regulator	*target_pwr;	/* Optional */
 	void			*plat_data;	/* Other platform data */
 	/* Optional ahci_start_engine override */
 	void			(*start_engine)(struct ata_port *ap);
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 75a3d47..3bc2dab 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -181,6 +181,13 @@ static int ahci_probe(struct platform_device *pdev)
 		hpriv->clks[i] = clk;
 	}
 
+	hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
+	if (IS_ERR(hpriv->target_pwr)) {
+		if (PTR_ERR(hpriv->target_pwr) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		hpriv->target_pwr = NULL;
+	}
+
 	rc = ahci_enable_clks(dev, hpriv);
 	if (rc)
 		goto free_clk;
@@ -197,6 +204,12 @@ static int ahci_probe(struct platform_device *pdev)
 			goto disable_unprepare_clk;
 	}
 
+	if (hpriv->target_pwr) {
+		rc = regulator_enable(hpriv->target_pwr);
+		if (rc)
+			goto pdata_exit;
+	}
+
 	ahci_save_initial_config(dev, hpriv,
 		pdata ? pdata->force_port_map : 0,
 		pdata ? pdata->mask_port_map  : 0);
@@ -220,7 +233,7 @@ static int ahci_probe(struct platform_device *pdev)
 	host = ata_host_alloc_pinfo(dev, ppi, n_ports);
 	if (!host) {
 		rc = -ENOMEM;
-		goto pdata_exit;
+		goto disable_regulator;
 	}
 
 	host->private_data = hpriv;
@@ -250,7 +263,7 @@ static int ahci_probe(struct platform_device *pdev)
 
 	rc = ahci_reset_controller(host);
 	if (rc)
-		goto pdata_exit;
+		goto disable_regulator;
 
 	ahci_init_controller(host);
 	ahci_print_info(host, "platform");
@@ -258,9 +271,12 @@ static int ahci_probe(struct platform_device *pdev)
 	rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
 			       &ahci_platform_sht);
 	if (rc)
-		goto pdata_exit;
+		goto disable_regulator;
 
 	return 0;
+disable_regulator:
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
 pdata_exit:
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
@@ -277,6 +293,9 @@ static void ahci_host_stop(struct ata_host *host)
 	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
+
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
 
@@ -313,6 +332,9 @@ static int ahci_suspend(struct device *dev)
 	if (rc)
 		return rc;
 
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
+
 	if (pdata && pdata->suspend)
 		pdata->suspend(dev);
 
@@ -338,10 +360,16 @@ static int ahci_resume(struct device *dev)
 			goto disable_unprepare_clk;
 	}
 
+	if (hpriv->target_pwr) {
+		rc = regulator_enable(hpriv->target_pwr);
+		if (rc)
+			goto pdata_suspend;
+	}
+
 	if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
 		rc = ahci_reset_controller(host);
 		if (rc)
-			goto pdata_suspend;
+			goto disable_regulator;
 
 		ahci_init_controller(host);
 	}
@@ -350,6 +378,9 @@ static int ahci_resume(struct device *dev)
 
 	return 0;
 
+disable_regulator:
+	if (hpriv->target_pwr)
+		regulator_disable(hpriv->target_pwr);
 pdata_suspend:
 	if (pdata && pdata->suspend)
 		pdata->suspend(dev);
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 06/13] ahci-platform: Add support for devices with more then 1 clock
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

The allwinner-sun4i AHCI controller needs 2 clocks to be enabled and the
imx AHCI controller needs 3 clocks to be enabled.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../devicetree/bindings/ata/ahci-platform.txt      |  1 +
 drivers/ata/ahci.h                                 |  3 +-
 drivers/ata/ahci_platform.c                        | 95 +++++++++++++++-------
 3 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 89de156..3ced07d 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -10,6 +10,7 @@ Required properties:
 
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
+- clocks            : a list of phandle + clock specifier pairs
 
 Example:
         sata at ffe08000 {
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 8f60f33..7950b3a 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -52,6 +52,7 @@
 enum {
 	AHCI_MAX_PORTS		= 32,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
+	AHCI_MAX_CLKS		= 3,
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_MAX_CMDS		= 32,
 	AHCI_CMD_SZ		= 32,
@@ -321,7 +322,7 @@ struct ahci_host_priv {
 	u32 			em_loc; /* enclosure management location */
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
-	struct clk		*clk;		/* Only for platforms supporting clk */
+	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
 	void			*plat_data;	/* Other platform data */
 	/* Optional ahci_start_engine override */
 	void			(*start_engine)(struct ata_port *ap);
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 33ac7a4..75a3d47 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -87,6 +87,42 @@ static struct scsi_host_template ahci_platform_sht = {
 	AHCI_SHT("ahci_platform"),
 };
 
+static int ahci_enable_clks(struct device *dev, struct ahci_host_priv *hpriv)
+{
+	int c, rc;
+
+	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
+		rc = clk_prepare_enable(hpriv->clks[c]);
+		if (rc) {
+			dev_err(dev, "clock prepare enable failed");
+			goto disable_unprepare_clk;
+		}
+	}
+	return 0;
+
+disable_unprepare_clk:
+	while (--c >= 0)
+		clk_disable_unprepare(hpriv->clks[c]);
+	return rc;
+}
+
+static void ahci_disable_clks(struct ahci_host_priv *hpriv)
+{
+	int c;
+
+	for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
+		if (hpriv->clks[c])
+			clk_disable_unprepare(hpriv->clks[c]);
+}
+
+static void ahci_put_clks(struct ahci_host_priv *hpriv)
+{
+	int c;
+
+	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
+		clk_put(hpriv->clks[c]);
+}
+
 static int ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -97,10 +133,8 @@ static int ahci_probe(struct platform_device *pdev)
 	struct ahci_host_priv *hpriv;
 	struct ata_host *host;
 	struct resource *mem;
-	int irq;
-	int n_ports;
-	int i;
-	int rc;
+	struct clk *clk;
+	int i, irq, max_clk, n_ports, rc;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -131,17 +165,26 @@ static int ahci_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	hpriv->clk = clk_get(dev, NULL);
-	if (IS_ERR(hpriv->clk)) {
-		dev_err(dev, "can't get clock\n");
-	} else {
-		rc = clk_prepare_enable(hpriv->clk);
-		if (rc) {
-			dev_err(dev, "clock prepare enable failed");
-			goto free_clk;
+	max_clk = dev->of_node ? AHCI_MAX_CLKS : 1;
+	for (i = 0; i < max_clk; i++) {
+		if (i == 0)
+			clk = clk_get(dev, NULL); /* For old platform init */
+		else
+			clk = of_clk_get(dev->of_node, i);
+
+		if (IS_ERR(clk)) {
+			rc = PTR_ERR(clk);
+			if (rc == -EPROBE_DEFER)
+				goto free_clk;
+			break;
 		}
+		hpriv->clks[i] = clk;
 	}
 
+	rc = ahci_enable_clks(dev, hpriv);
+	if (rc)
+		goto free_clk;
+
 	/*
 	 * Some platforms might need to prepare for mmio region access,
 	 * which could be done in the following init call. So, the mmio
@@ -222,11 +265,9 @@ pdata_exit:
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
 disable_unprepare_clk:
-	if (!IS_ERR(hpriv->clk))
-		clk_disable_unprepare(hpriv->clk);
+	ahci_disable_clks(hpriv);
 free_clk:
-	if (!IS_ERR(hpriv->clk))
-		clk_put(hpriv->clk);
+	ahci_put_clks(hpriv);
 	return rc;
 }
 
@@ -239,10 +280,8 @@ static void ahci_host_stop(struct ata_host *host)
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
 
-	if (!IS_ERR(hpriv->clk)) {
-		clk_disable_unprepare(hpriv->clk);
-		clk_put(hpriv->clk);
-	}
+	ahci_disable_clks(hpriv);
+	ahci_put_clks(hpriv);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -277,8 +316,7 @@ static int ahci_suspend(struct device *dev)
 	if (pdata && pdata->suspend)
 		pdata->suspend(dev);
 
-	if (!IS_ERR(hpriv->clk))
-		clk_disable_unprepare(hpriv->clk);
+	ahci_disable_clks(hpriv);
 
 	return 0;
 }
@@ -290,13 +328,9 @@ static int ahci_resume(struct device *dev)
 	struct ahci_host_priv *hpriv = host->private_data;
 	int rc;
 
-	if (!IS_ERR(hpriv->clk)) {
-		rc = clk_prepare_enable(hpriv->clk);
-		if (rc) {
-			dev_err(dev, "clock prepare enable failed");
-			return rc;
-		}
-	}
+	rc = ahci_enable_clks(dev, hpriv);
+	if (rc)
+		return rc;
 
 	if (pdata && pdata->resume) {
 		rc = pdata->resume(dev);
@@ -320,8 +354,7 @@ pdata_suspend:
 	if (pdata && pdata->suspend)
 		pdata->suspend(dev);
 disable_unprepare_clk:
-	if (!IS_ERR(hpriv->clk))
-		clk_disable_unprepare(hpriv->clk);
+	ahci_disable_clks(hpriv);
 
 	return rc;
 }
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 05/13] ahci-platform: Pass ahci_host_priv ptr to ahci_platform_data init method
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

Some ahci_platform_data->init methods need access to the ahci_host_priv data.

Note:

When calling ahci_platform_data->init the ata_host has not been allocated yet,
so access to ahci_host_priv through the dev argument is not possible.

The hpriv->mmio argument may seem redundant, but it is useful for drivers
which live outside of drivers/ata and thus don't know the contents of the
ahci_platform_data data type.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/mach-davinci/devices-da8xx.c | 3 ++-
 arch/arm/mach-spear/spear1340.c       | 3 ++-
 drivers/ata/ahci_imx.c                | 3 ++-
 drivers/ata/ahci_platform.c           | 2 +-
 include/linux/ahci_platform.h         | 4 +++-
 5 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 78829c5..81d0110 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -1061,7 +1061,8 @@ static unsigned long da850_sata_xtal[] = {
 	KHZ_TO_HZ(60000),
 };
 
-static int da850_sata_init(struct device *dev, void __iomem *addr)
+static int da850_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
+			   void __iomem *addr)
 {
 	int i, ret;
 	unsigned int val;
diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
index c4cbbd2..9e4f70b 100644
--- a/arch/arm/mach-spear/spear1340.c
+++ b/arch/arm/mach-spear/spear1340.c
@@ -77,7 +77,8 @@
 			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
 
 /* SATA device registration */
-static int sata_miphy_init(struct device *dev, void __iomem *addr)
+static int sata_miphy_init(struct device *dev, struct ahci_host_priv *hpriv,
+			   void __iomem *addr)
 {
 	writel(SPEAR1340_SATA_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
 	writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK,
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 30568d3..0051f29 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -91,7 +91,8 @@ static const struct ata_port_info ahci_imx_port_info = {
 	.port_ops	= &ahci_imx_ops,
 };
 
-static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
+static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
+			   void __iomem *mmio)
 {
 	int ret = 0;
 	unsigned int reg_val;
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 41720cb..33ac7a4 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -149,7 +149,7 @@ static int ahci_probe(struct platform_device *pdev)
 	 * returned successfully.
 	 */
 	if (pdata && pdata->init) {
-		rc = pdata->init(dev, hpriv->mmio);
+		rc = pdata->init(dev, hpriv, hpriv->mmio);
 		if (rc)
 			goto disable_unprepare_clk;
 	}
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index a641cb6..796dfb4 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -19,9 +19,11 @@
 
 struct device;
 struct ata_port_info;
+struct ahci_host_priv;
 
 struct ahci_platform_data {
-	int (*init)(struct device *dev, void __iomem *addr);
+	int (*init)(struct device *dev, struct ahci_host_priv *hpriv,
+		    void __iomem *addr);
 	void (*exit)(struct device *dev);
 	void (*suspend)(struct device *dev);
 	int (*resume)(struct device *dev);
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 04/13] ahci-platform: Undo pdata->resume on resume failure
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

When the ahci_resume fails the error handling code tries to undo all changes
made, but it was not undoing the results of pdata->resume.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/ata/ahci_platform.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index dc1ef73..41720cb 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -307,7 +307,7 @@ static int ahci_resume(struct device *dev)
 	if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
 		rc = ahci_reset_controller(host);
 		if (rc)
-			goto disable_unprepare_clk;
+			goto pdata_suspend;
 
 		ahci_init_controller(host);
 	}
@@ -316,6 +316,9 @@ static int ahci_resume(struct device *dev)
 
 	return 0;
 
+pdata_suspend:
+	if (pdata && pdata->suspend)
+		pdata->suspend(dev);
 disable_unprepare_clk:
 	if (!IS_ERR(hpriv->clk))
 		clk_disable_unprepare(hpriv->clk);
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 03/13] ahci-platform: Fix clk enable/disable unbalance on suspend/resume
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

For devices where ahci_platform_data provides suspend() there is an unbalance
in clk enable/disable calls. The suspend path does not disable the clk, but
the resume path enables it. This commit fixes it by always disabling the clk
in the suspend path independent of there being an ahci_platform_data suspend
method.

On all drivers currently using a suspend method, the suspend method always
succeeds, so change its return type to void, to avoid having the introduce
somewhat complex error handling paths.

The disabling of the clock on suspend is a functional change, to ensure this
is ok I've audited all drivers using ahci_platform_data:

arch/arm/mach-davinci/devices-da8xx.c: Does not use a suspend method
arch/arm/mach-spear/spear1340.c: Does not use the clock framework
drivers/ata/ahci_imx.c: Does have suspend and resume pdata methods, these
disable / enable another clock, so likely it is ok to disable / enable the
clock at of-node index 0 as well, I've ordered a wandboard to be able to
test these changes.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/mach-spear/spear1340.c | 6 ++----
 drivers/ata/ahci_imx.c          | 4 +---
 drivers/ata/ahci_platform.c     | 2 +-
 include/linux/ahci_platform.h   | 2 +-
 4 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
index 3fb6834..c4cbbd2 100644
--- a/arch/arm/mach-spear/spear1340.c
+++ b/arch/arm/mach-spear/spear1340.c
@@ -107,14 +107,12 @@ void sata_miphy_exit(struct device *dev)
 	msleep(20);
 }
 
-int sata_suspend(struct device *dev)
+void sata_suspend(struct device *dev)
 {
 	if (dev->power.power_state.event == PM_EVENT_FREEZE)
-		return 0;
+		return;
 
 	sata_miphy_exit(dev);
-
-	return 0;
 }
 
 int sata_resume(struct device *dev)
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3e23e99..30568d3 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -171,7 +171,7 @@ static void imx6q_sata_exit(struct device *dev)
 	clk_disable_unprepare(imxpriv->sata_ref_clk);
 }
 
-static int imx_ahci_suspend(struct device *dev)
+static void imx_ahci_suspend(struct device *dev)
 {
 	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
 
@@ -185,8 +185,6 @@ static int imx_ahci_suspend(struct device *dev)
 				!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
 		clk_disable_unprepare(imxpriv->sata_ref_clk);
 	}
-
-	return 0;
 }
 
 static int imx_ahci_resume(struct device *dev)
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 4b231ba..dc1ef73 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -275,7 +275,7 @@ static int ahci_suspend(struct device *dev)
 		return rc;
 
 	if (pdata && pdata->suspend)
-		return pdata->suspend(dev);
+		pdata->suspend(dev);
 
 	if (!IS_ERR(hpriv->clk))
 		clk_disable_unprepare(hpriv->clk);
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 73a2500..a641cb6 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -23,7 +23,7 @@ struct ata_port_info;
 struct ahci_platform_data {
 	int (*init)(struct device *dev, void __iomem *addr);
 	void (*exit)(struct device *dev);
-	int (*suspend)(struct device *dev);
+	void (*suspend)(struct device *dev);
 	int (*resume)(struct device *dev);
 	const struct ata_port_info *ata_port_info;
 	unsigned int force_port_map;
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 02/13] sata-highbank: Remove unnecessary ahci_platform.h include
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

The sata-highbank driver is a complete standalone sata driver, which does
not use ahci_platform.c / ahci_platform_data in any way.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/ata/sata_highbank.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index ea3b3dc..870b11e 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -29,7 +29,6 @@
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/libata.h>
-#include <linux/ahci_platform.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/export.h>
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 01/13] libahci: Allow drivers to override start_engine
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390088935-7193-1-git-send-email-hdegoede@redhat.com>

From: Oliver Schinagl <oliver@schinagl.nl>

Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which needs a
special register to be poked before starting the DMA engine.

This register gets reset on an ahci_stop_engine call, so there is no other
place then ahci_start_engine where this poking can be done.

This commit allows drivers to override ahci_start_engine behavior for use by
the Allwinner AHCI driver (and potentially other drivers in the future).

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/ata/ahci.h    | 2 ++
 drivers/ata/libahci.c | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 2289efd..8f60f33 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -323,6 +323,8 @@ struct ahci_host_priv {
 	u32			em_msg_type;	/* EM message type */
 	struct clk		*clk;		/* Only for platforms supporting clk */
 	void			*plat_data;	/* Other platform data */
+	/* Optional ahci_start_engine override */
+	void			(*start_engine)(struct ata_port *ap);
 };
 
 extern int ahci_ignore_sss;
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index c482f8c..f6eabbc 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -568,8 +568,14 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
 void ahci_start_engine(struct ata_port *ap)
 {
 	void __iomem *port_mmio = ahci_port_base(ap);
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	u32 tmp;
 
+	if (hpriv->start_engine) {
+		hpriv->start_engine(ap);
+		return;
+	}
+
 	/* start DMA */
 	tmp = readl(port_mmio + PORT_CMD);
 	tmp |= PORT_CMD_START;
-- 
1.8.4.2

^ permalink raw reply related

* [RFC v3 00/13] ahci: add sunxi driver and cleanup imx driver
From: Hans de Goede @ 2014-01-18 23:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi All,

Here is v3 of my patchset for adding ahci-sunxi support. It has grown quite
a bit since I've been going for a more generic approach this time and I've
also cleaned up the ahci-imx driver to use the same generic approach.

History:

v1, by Olliver Schinagl:
This was using the approach of having a platform device which probe method
creates a new child platform device which gets driven by ahci_platform.c,
as done by ahci_imx.c .

v2, by Hans de Goede:
Stand-alone platform driver based on Olliver's work

v3, by Hans de Goede:
patch-series, with 4 different parts
a) Make ahci_platform.c more generic, handle more then 1 clk, target pwr
   regulator
b) New ahci-sunxi code only populating ahci_platform_data, passed to
   ahci_platform.c to of_device_id matching.
c) Refactor ahci-imx code to work the same as the new ahci-sunxi code, this
   is the reason why v3 is an RFC, I'm waiting for the wandboard I ordered to
   arrive so that I can actually test this.
d) dts bindings for the sunxi ahci parts

Parts a-c are intended for merging through the ata tree, the dts bindings
will be merged to Maxime Ripard's sunxi-dts tree.

I hope people like the new approach for dealing with of drivers which need
to provide ahci_platform_data. An alternate approach would be to export
ahci_probe (renamed to ahci_platform_probe) from ahci_platform.c, then
ahci_sunxi.c could have a probe function like this:

int ahci_sunxi_probe(struct platform_device *pdev) {
    pdev->dev.platform_data = &ahci_sunxi_pdata;
    return ahci_platform_probe(pdev);
}

And then each of ahci_platform, ahci_sunxi and ahci_imx could be its own
module (if build as module) rather then all of them being build into one
module.

Regards,

Hans

^ permalink raw reply

* [BUG] FL1009: xHCI host not responding to stop endpoint command.
From: Arnaud Ebalard @ 2014-01-18 21:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140117205432.GB5618@xanatos>

Hi,

I have added Thomas in the recipients, because I guess he may be of some
help debugging the issue further. Thomas, the beginning of the thread is
here: http://thread.gmane.org/gmane.linux.usb.general/101531

Sarah Sharp <sarah.a.sharp@linux.intel.com> writes:

>> >>> I am slowly starting to see a bisect session coming ;-)
>> >>
>> >> Try reverting commit 60e102ac73cd40069d077014c93c86dc7205cb68.
>> >
>> > AFAICT, this commit does not exist in master (Linus tree), i.e. it is
>> > not in 3.13.0-rc8.
>> 
>> That commit is a stable backport of 9df89d85b407690afa46ddfbccc80bec6869971d 
>> which is in v3.13-rc8:
>> 
>> bjorn at nemi:/usr/local/src/git/linux$ git tag --contains 9df89d85b407690afa46ddfbccc80bec6869971d
>> usb-3.13-rc1
>> usb-3.13-rc3
>> usb-3.13-rc5
>> v3.13-rc1
>> v3.13-rc2
>> v3.13-rc3
>> v3.13-rc4
>> v3.13-rc5
>> v3.13-rc6
>> v3.13-rc7
>> v3.13-rc8
>
> Sorry for using the stable commit ID.  Arnaud, please try reverting
> commit 9df89d85b407690afa46ddfbccc80bec6869971d "usbcore: set
> lpm_capable field for LPM capable root hubs" and see if it fixes your
> issues.

Nope, 9df89d85b407690 does not fix the issue but I guess I found the
reason: I think the regression is not directly due to some usb/XHCI
related change. More below.

I started a git bisect session but I had to stop between the two
following commits, because the last ones I tested after those were just
not bootable.

 bad : f9efbce6334844c7f8b9b9459f6d7a6fbc2928e0 (merge commit)
 good: aac59e3efce3dca787b11e34726001603ce3d161 (merge commit)

At that point, I decided to switch to a manual review of the changes
introduced *between* those commits:

$ git log -p aac59e3efce3..f9efbce63348 | grep -c ^commit
524

I looked at which files where touched (387 in total) and dropped those
that are not use on my platform or cannot be suspected fo the bug. I
ended up w/:

  drivers/irqchip/irq-armada-370-xp.c
  drivers/pci/host/pci-mvebu.c

Which are modified by those commits:

  commit f5072dfbac05: PCI: mvebu: make local functions static
  commit 032b4c0cc321: PCI: mvebu: add I/O access wrappers
  commit 9f352f0e6c0f: PCI: mvebu: Dynamically detect if the PEX link is up to enable hot plug
  commit cc54ccd9a696: PCI: mvebu: add support for Marvell Dove SoCs
  commit 52ba992e201f: PCI: mvebu: add support for reset on GPIO
  commit e5615c30c1c9: PCI: mvebu: remove subsys_initcall
  commit bf09b6ae588f: PCI: mvebu: increment nports only for registered ports
  commit b42285f66f87: PCI: mvebu: move clock enable before register access
  commit 5b4deb6526bd: PCI: mvebu: add support for MSI
  commit 31f614edb726: irqchip: armada-370-xp: implement MSI support
  commit 627dfcc249e2: irqchip: armada-370-xp: properly request resources
  
I started suspecting the introduction of MSI support in Marvell PCIe
host controller driver (FL1009 is on the PCIe bus) and compiled a
a 3.13.0-rc8 w/ CONFIG_PCI_MSI disabled (it was enabled in all my
previous tests): I did not manage to reproduce the issue with this
kernel. As a side note, commits 5b4deb6526bd, 31f614edb726 and
627dfcc249e2 are

ATM, I do not know if the problem is related to a bug in introduced MSI
support or some weird incompatibility of that functionality with the
FL1009 which would require some quirk in XHCI stack.

Thomas, I took a look at the changes but I am not familiar w/ how MSI
work. You may have an idea on what is going on here.

Cheers,

a+

ps: Thomas, this is completely unrelated but the code below caught my
eye at the beginning of a hunk in 31f614edb726. When CONFIG_PCI_MSI is
disabled, why is irqnr now compared to 1 instead of 0?

@@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
                if (irqnr > 1022)
                        break;
 
-               if (irqnr > 0) {
+               if (irqnr > 1) {
                        irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
                                        irqnr);
                        handle_IRQ(irqnr, regs);
                        continue;
                }
+
+#ifdef CONFIG_PCI_MSI
+               /* MSI handling */
+               if (irqnr == 1) {

The comparisonWhen CONFIG_PCI_MSI

^ 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