Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH net-next] dt-bindings: mdio: Clarify binding document
From: David Miller @ 2017-04-26 18:46 UTC (permalink / raw)
  To: f.fainelli-Re5JQEeQqe8AvxtiuMwx3w
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, rogerq-l0cyMroinI0,
	andrew-g2DYL2Zd6BY, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	nsekhar-l0cyMroinI0, jsarha-l0cyMroinI0,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, lars-Qo5EllUWu/uELgA04lAiVw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170425183308.26107-1-f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

From: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Tue, 25 Apr 2017 11:33:03 -0700

> The described GPIO reset property is applicable to *all* child PHYs. If
> we have one reset line per PHY present on the MDIO bus, these
> automatically become properties of the child PHY nodes.
> 
> Finally, indicate how the RESET pulse width must be defined, which is
> the maximum value of all individual PHYs RESET pulse widths determined
> by reading their datasheets.
> 
> Fixes: 69226896ad63 ("mdio_bus: Issue GPIO RESET to PHYs.")
> Signed-off-by: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

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

^ permalink raw reply

* Re: [PATCH v2 2/4] gpio - Add EXAR XRA1403 SPI GPIO expander driver
From: Andy Shevchenko @ 2017-04-26 17:50 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: zoobab-Re5JQEeQqe8AvxtiuMwx3w, Linus Walleij, Nandor Han, Greg KH,
	David S. Miller, Mauro Carvalho Chehab, Daniel Vetter,
	Alexandre Courbot, Rob Herring, Mark Rutland,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Semi Malinen
In-Reply-To: <CAMuHMdUvQwqhuoWnS3h1S7p0q1K9m5BBFue54pkOykMgi+xmWw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Tue, Apr 25, 2017 at 10:15 AM, Geert Uytterhoeven
<geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org> wrote:

>> Is there some good cli tools to access the new char device? If they
>> are shipped with most distros, that would reduce the pain.
>
> https://github.com/brgl/libgpiod
>
> A bit early to expect it to be shipped with all distros, though.

Buildroot has it.
For kernel development it is quite enough.

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

^ permalink raw reply

* Re: [PATCH v2 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Eric Anholt @ 2017-04-26 17:26 UTC (permalink / raw)
  To: Florian Fainelli, Vivien Didelot, Andrew Lunn,
	netdev-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Ray Jui,
	Scott Branden, Jon Mason
In-Reply-To: <0cb00eb7-41d0-0390-4687-d966499ed9f4-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

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

Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:

> On 04/25/2017 04:53 PM, Eric Anholt wrote:
>> Cygnus has a single AMAC controller connected to the B53 switch with 2
>> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
>> the external ethernet jacks.
>> 
>> Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> Reviewed-by: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>> 
>> v2: Call the node "switch", just call the ports "port" (suggestions by
>>     Florian), drop max-speed on the phys (suggestion by Andrew Lunn),
>>     call the other nodes "ethernet" and "ethernet-phy" (suggestions by
>>     Sergei Shtylyov)
>> 
>>  arch/arm/boot/dts/bcm-cygnus.dtsi      | 58 ++++++++++++++++++++++++++++++++++
>>  arch/arm/boot/dts/bcm911360_entphn.dts |  8 +++++
>>  2 files changed, 66 insertions(+)
>> 
>> diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi
>> index 009f1346b817..9fd89be0f5e0 100644
>> --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
>> +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
>> @@ -142,6 +142,54 @@
>>  			interrupts = <0>;
>>  		};
>>  
>> +		mdio: mdio@18002000 {
>> +			compatible = "brcm,iproc-mdio";
>> +			reg = <0x18002000 0x8>;
>> +			#size-cells = <1>;
>> +			#address-cells = <0>;
>
> Sorry for not noticing earlier, since you override this correctly in the
> board-level DTS file can you put a:
>
> 			status = "disabled"
>
> property in there by default?

Done.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Eric Anholt @ 2017-04-26 17:26 UTC (permalink / raw)
  To: Florian Fainelli, Vivien Didelot, Andrew Lunn,
	netdev-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Ray Jui,
	Scott Branden, Jon Mason
In-Reply-To: <0cb00eb7-41d0-0390-4687-d966499ed9f4-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

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

Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:

> On 04/25/2017 04:53 PM, Eric Anholt wrote:
>> Cygnus has a single AMAC controller connected to the B53 switch with 2
>> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
>> the external ethernet jacks.
>> 
>> Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> Reviewed-by: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>> 
>> v2: Call the node "switch", just call the ports "port" (suggestions by
>>     Florian), drop max-speed on the phys (suggestion by Andrew Lunn),
>>     call the other nodes "ethernet" and "ethernet-phy" (suggestions by
>>     Sergei Shtylyov)
>> 
>>  arch/arm/boot/dts/bcm-cygnus.dtsi      | 58 ++++++++++++++++++++++++++++++++++
>>  arch/arm/boot/dts/bcm911360_entphn.dts |  8 +++++
>>  2 files changed, 66 insertions(+)
>> 
>> diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi
>> index 009f1346b817..9fd89be0f5e0 100644
>> --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
>> +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
>> @@ -142,6 +142,54 @@
>>  			interrupts = <0>;
>>  		};
>>  
>> +		mdio: mdio@18002000 {
>> +			compatible = "brcm,iproc-mdio";
>> +			reg = <0x18002000 0x8>;
>> +			#size-cells = <1>;
>> +			#address-cells = <0>;
>
> Sorry for not noticing earlier, since you override this correctly in the
> board-level DTS file can you put a:
>
> 			status = "disabled"
>
> property in there by default?

I didn't have the override in the board file either, just switch and
ethernet.  Fixed.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Eric Anholt @ 2017-04-26 17:25 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Florian Fainelli, Vivien Didelot, netdev, Rob Herring,
	Mark Rutland, devicetree, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, Ray Jui, Scott Branden, Jon Mason
In-Reply-To: <20170426004907.GA9453@lunn.ch>

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

Andrew Lunn <andrew@lunn.ch> writes:

>> +		eth0: ethernet@18042000 {
>> +			compatible = "brcm,amac";
>> +			reg = <0x18042000 0x1000>,
>> +			      <0x18110000 0x1000>;
>> +			reg-names = "amac_base", "idm_base";
>> +			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
>> +			max-speed = <1000>;
>
> Hi Eric
>
> Sorry i missed this the first time. Does this Ethernet controller do >
> 1Gbps? Does this max-speed do anything useful?

It doesn't look like it.  Dropped.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply

* Re: [PATCH] NFC: trf7970a: Correct register settings for 27MHz clock
From: Mark Greer @ 2017-04-26 17:04 UTC (permalink / raw)
  To: Geoff Lansberry, g
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	sameo-VuQAYsv1563Yd54FQh9/CA,
	kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	devicetree-u79uwXL29TY76Z2rM5mHXA, mgreer-luAo+O/VEmrlveNOaEYElw,
	justin-R+k406RtEhcAvxtiuMwx3w, colin.king-Z7WLFzj8eWMS+FvcfC7Uqw
In-Reply-To: <1493214513-12245-1-git-send-email-geoff-R+k406RtEhcAvxtiuMwx3w@public.gmane.org>

On Wed, Apr 26, 2017 at 09:48:33AM -0400, Geoff Lansberry wrote:
> In prior commits the selected clock frequency does not propagate
> correctly to what is written the the TRF7970A_MODULATOR_SYS_CLK_CTRL
> register.
> Also fixes a bug that causes the device tree property check to always
> pass.
> 
> Signed-off-by: Geoff Lansberry <geoff-R+k406RtEhcAvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/nfc/trf7970a.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
> index 2d1c8ca..c278b0e 100644
> --- a/drivers/nfc/trf7970a.c
> +++ b/drivers/nfc/trf7970a.c
> @@ -2071,7 +2071,7 @@ static int trf7970a_probe(struct spi_device *spi)
>  	}
>  
>  	of_property_read_u32(np, "clock-frequency", &clk_freq);
> -	if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) ||
> +	if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) &&

There is already a patch submitted to fix this issue so no need to fix
it again.  For the record, it should have been in a separate patch
since it fixes a different issue than what is fixed below.

>  		(clk_freq != TRF7970A_13MHZ_CLOCK_FREQUENCY)) {
>  		dev_err(trf->dev,
>  			"clock-frequency (%u Hz) unsupported\n",
> @@ -2079,6 +2079,13 @@ static int trf7970a_probe(struct spi_device *spi)
>  		return -EINVAL;
>  	}
>  
> +	if (clk_freq == TRF7970A_27MHZ_CLOCK_FREQUENCY) {
> +		trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_27MHZ;
> +		dev_dbg(trf->dev, "trf7970a configured for 27MHz crystal\n");
> +	} else {
> +		trf->modulator_sys_clk_ctrl = 0;
> +	}
> +
>  	if (of_property_read_bool(np, "en2-rf-quirk"))
>  		trf->quirks |= TRF7970A_QUIRK_EN2_MUST_STAY_LOW;

This part looks okay to me but I like Walter's suggestion too.

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

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: Document STM32 I2S bindings
From: Mark Brown @ 2017-04-26 16:15 UTC (permalink / raw)
  To: Olivier MOYSAN
  Cc: mark.rutland@arm.com, Rob Herring, alsa-devel@alsa-project.org,
	Alexandre TORGUE, devicetree@vger.kernel.org, Arnaud POULIQUEN,
	tiwai@suse.com, lgirdwood@gmail.com, mcoquelin.stm32@gmail.com,
	linux-arm-kernel@lists.infradead.org, Benjamin GAIGNARD
In-Reply-To: <a87748e4-21e7-f65a-5be1-fe4f60bdfbef@st.com>


[-- Attachment #1.1: Type: text/plain, Size: 2168 bytes --]

On Thu, Apr 13, 2017 at 08:01:34AM +0000, Olivier MOYSAN wrote:

> 1) 2 static dais NOT exclusive
> 	- dai tx
> 	- dai rx
> The IP exhibits a mode register, where you select mode TX, RX or FD.
> There are 2 two options to manage this register.
> option 1:
> 	start first channel with mode RX or TX
> 	when second channel is started, mode has to be changed to FD.
> 	Transfers have to be stopped before changing configuration
> 	registers, so this leads to cuts in audio stream.
> option 2:
> 	start a first channel with mode FD.
> 	In this case, we may have unpredictable behavior for the stream
> 	which is not already started. probably underrun/overrun.
> So, this solution rises problem for full-duplex management.

> 2) 3 static dais exclusive
> 	- dai tx
> 	- dai rx
> 	- dai rx-tx (fd)
> This is the current implementation.
> The choice of the dai is done at probe time. It is provided by DT 
> through sound-dai parameter.
> When dai fd is selected, after starting first stream, we assume that
> second stream will be started. In this case we wait for second stream
> to be available before enabling IP and starting transfers.

> 3) 1 dynamic dai
> 	- dai rx or tx or fd (according to dma conf in IP node)
> Here the driver exposes only a single dai constructed from dma 
> configuration provided by IP DT node.
> This allows to get ride of sound-dai parameter.

None of these options reflect how normal I2S controllers present
themselves in DT.  To repeat, you should present a single bidirectional
DAI for the single physical bidirectional I2S controller that your
hardware has.

If it's not possible to figure out a way to make the controller support
simultaneous playback and record with the two started independently then
the driver should just return an error if userspace tries to start the
second direction up.  This will severely limit the utility of the driver
as Linux generally treats playback and record independently but that's
going to apply just as much with any of the options involving multiple
DAIs or configuration in DT.  You might be able to do something with
feeding it dummy data I guess?

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Applied "ASoC: stm32: add bindings for SAI" to the asoc tree
From: Mark Brown @ 2017-04-26 15:50 UTC (permalink / raw)
  Cc: Mark Brown, lgirdwood-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1491837596-2924-2-git-send-email-olivier.moysan-qxv4g6HH51o@public.gmane.org>

The patch

   ASoC: stm32: add bindings for SAI

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From b45c4f117b002a902e8b9f52eaf542e3e82c36a8 Mon Sep 17 00:00:00 2001
From: olivier moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org>
Date: Mon, 10 Apr 2017 17:19:55 +0200
Subject: [PATCH] ASoC: stm32: add bindings for SAI

This patch adds documentation of device tree bindings for the
STM32 SAI ASoC driver.

Signed-off-by: olivier moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/sound/st,stm32-sai.txt     | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-sai.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
new file mode 100644
index 000000000000..c59a3d779e06
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -0,0 +1,89 @@
+STMicroelectronics STM32 Serial Audio Interface (SAI).
+
+The SAI interface (Serial Audio Interface) offers a wide set of audio protocols
+as I2S standards, LSB or MSB-justified, PCM/DSP, TDM, and AC'97.
+The SAI contains two independent audio sub-blocks. Each sub-block has
+its own clock generator and I/O lines controller.
+
+Required properties:
+  - compatible: Should be "st,stm32f4-sai"
+  - reg: Base address and size of SAI common register set.
+  - clocks: Must contain phandle and clock specifier pairs for each entry
+	in clock-names.
+  - clock-names: Must contain "x8k" and "x11k"
+	"x8k": SAI parent clock for sampling rates multiple of 8kHz.
+	"x11k": SAI parent clock for sampling rates multiple of 11.025kHz.
+  - interrupts: cpu DAI interrupt line shared by SAI sub-blocks
+
+Optional properties:
+  - resets: Reference to a reset controller asserting the SAI
+
+SAI subnodes:
+Two subnodes corresponding to SAI sub-block instances A et B can be defined.
+Subnode can be omitted for unsused sub-block.
+
+SAI subnodes required properties:
+  - compatible: Should be "st,stm32-sai-sub-a" or "st,stm32-sai-sub-b"
+	for SAI sub-block A or B respectively.
+  - reg: Base address and size of SAI sub-block register set.
+  - clocks: Must contain one phandle and clock specifier pair
+	for sai_ck which feeds the internal clock generator.
+  - clock-names: Must contain "sai_ck".
+  - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt
+  - dma-names: identifier string for each DMA request line
+	"tx": if sai sub-block is configured as playback DAI
+	"rx": if sai sub-block is configured as capture DAI
+  - pinctrl-names: should contain only value "default"
+  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+
+Example:
+sound_card {
+	compatible = "audio-graph-card";
+	dais = <&sai1b_port>;
+};
+
+sai1: sai1@40015800 {
+	compatible = "st,stm32f4-sai";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	reg = <0x40015800 0x4>;
+	clocks = <&rcc 1 CLK_SAIQ_PDIV>, <&rcc 1 CLK_I2SQ_PDIV>;
+	clock-names = "x8k", "x11k";
+	interrupts = <87>;
+
+	sai1b: audio-controller@40015824 {
+		#sound-dai-cells = <0>;
+		compatible = "st,stm32-sai-sub-b";
+		reg = <0x40015824 0x1C>;
+		clocks = <&rcc 1 CLK_SAI2>;
+		clock-names = "sai_ck";
+		dmas = <&dma2 5 0 0x400 0x0>;
+		dma-names = "tx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sai1b>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			sai1b_port: port@0 {
+				reg = <0>;
+				cpu_endpoint: endpoint {
+					remote-endpoint = <&codec_endpoint>;
+					audio-graph-card,format = "i2s";
+					audio-graph-card,bitclock-master = <&codec_endpoint>;
+					audio-graph-card,frame-master = <&codec_endpoint>;
+				};
+			};
+		};
+	};
+};
+
+audio-codec {
+	codec_port: port {
+		codec_endpoint: endpoint {
+			remote-endpoint = <&cpu_endpoint>;
+		};
+	};
+};
-- 
2.11.0

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

^ permalink raw reply related

* Applied "ASoC: stm32: add SAI driver" to the asoc tree
From: Mark Brown @ 2017-04-26 15:50 UTC (permalink / raw)
  Cc: Mark Brown, lgirdwood-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1491837596-2924-3-git-send-email-olivier.moysan-qxv4g6HH51o@public.gmane.org>

The patch

   ASoC: stm32: add SAI driver

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 3e086edfe0c73daaabd929b926bbe26536272d9a Mon Sep 17 00:00:00 2001
From: olivier moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org>
Date: Mon, 10 Apr 2017 17:19:56 +0200
Subject: [PATCH] ASoC: stm32: add SAI driver

This patch implements SAI ASoC driver for STM32.

Signed-off-by: olivier moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 sound/soc/Kconfig             |   1 +
 sound/soc/Makefile            |   1 +
 sound/soc/stm/Kconfig         |   8 +
 sound/soc/stm/Makefile        |   6 +
 sound/soc/stm/stm32_sai.c     | 115 ++++++
 sound/soc/stm/stm32_sai.h     | 200 ++++++++++
 sound/soc/stm/stm32_sai_sub.c | 884 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 1215 insertions(+)
 create mode 100644 sound/soc/stm/Kconfig
 create mode 100644 sound/soc/stm/Makefile
 create mode 100644 sound/soc/stm/stm32_sai.c
 create mode 100644 sound/soc/stm/stm32_sai.h
 create mode 100644 sound/soc/stm/stm32_sai_sub.c

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 182d92efc7c8..3836ebe8938f 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -63,6 +63,7 @@ source "sound/soc/sh/Kconfig"
 source "sound/soc/sirf/Kconfig"
 source "sound/soc/spear/Kconfig"
 source "sound/soc/sti/Kconfig"
+source "sound/soc/stm/Kconfig"
 source "sound/soc/sunxi/Kconfig"
 source "sound/soc/tegra/Kconfig"
 source "sound/soc/txx9/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9a30f21d16ee..5440cf77c39a 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_SND_SOC)	+= sh/
 obj-$(CONFIG_SND_SOC)	+= sirf/
 obj-$(CONFIG_SND_SOC)	+= spear/
 obj-$(CONFIG_SND_SOC)	+= sti/
+obj-$(CONFIG_SND_SOC)	+= stm/
 obj-$(CONFIG_SND_SOC)	+= sunxi/
 obj-$(CONFIG_SND_SOC)	+= tegra/
 obj-$(CONFIG_SND_SOC)	+= txx9/
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
new file mode 100644
index 000000000000..972970f0890a
--- /dev/null
+++ b/sound/soc/stm/Kconfig
@@ -0,0 +1,8 @@
+menuconfig SND_SOC_STM32
+	tristate "STMicroelectronics STM32 SOC audio support"
+	depends on ARCH_STM32 || COMPILE_TEST
+	depends on SND_SOC
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	select REGMAP_MMIO
+	help
+	  Say Y if you want to enable ASoC-support for STM32
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
new file mode 100644
index 000000000000..e466a4759698
--- /dev/null
+++ b/sound/soc/stm/Makefile
@@ -0,0 +1,6 @@
+# SAI
+snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o
+
+snd-soc-stm32-sai-objs := stm32_sai.o
+obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
new file mode 100644
index 000000000000..2a27a26bf7a1
--- /dev/null
+++ b/sound/soc/stm/stm32_sai.c
@@ -0,0 +1,115 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+
+#include <sound/dmaengine_pcm.h>
+#include <sound/core.h>
+
+#include "stm32_sai.h"
+
+static const struct of_device_id stm32_sai_ids[] = {
+	{ .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 },
+	{}
+};
+
+static int stm32_sai_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct stm32_sai_data *sai;
+	struct reset_control *rst;
+	struct resource *res;
+	void __iomem *base;
+	const struct of_device_id *of_id;
+
+	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
+	if (!sai)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	of_id = of_match_device(stm32_sai_ids, &pdev->dev);
+	if (of_id)
+		sai->version = (enum stm32_sai_version)of_id->data;
+	else
+		return -EINVAL;
+
+	sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k");
+	if (IS_ERR(sai->clk_x8k)) {
+		dev_err(&pdev->dev, "missing x8k parent clock\n");
+		return PTR_ERR(sai->clk_x8k);
+	}
+
+	sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k");
+	if (IS_ERR(sai->clk_x11k)) {
+		dev_err(&pdev->dev, "missing x11k parent clock\n");
+		return PTR_ERR(sai->clk_x11k);
+	}
+
+	/* init irqs */
+	sai->irq = platform_get_irq(pdev, 0);
+	if (sai->irq < 0) {
+		dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
+		return sai->irq;
+	}
+
+	/* reset */
+	rst = reset_control_get(&pdev->dev, NULL);
+	if (!IS_ERR(rst)) {
+		reset_control_assert(rst);
+		udelay(2);
+		reset_control_deassert(rst);
+	}
+
+	sai->pdev = pdev;
+	platform_set_drvdata(pdev, sai);
+
+	return of_platform_populate(np, NULL, NULL, &pdev->dev);
+}
+
+static int stm32_sai_remove(struct platform_device *pdev)
+{
+	of_platform_depopulate(&pdev->dev);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(of, stm32_sai_ids);
+
+static struct platform_driver stm32_sai_driver = {
+	.driver = {
+		.name = "st,stm32-sai",
+		.of_match_table = stm32_sai_ids,
+	},
+	.probe = stm32_sai_probe,
+	.remove = stm32_sai_remove,
+};
+
+module_platform_driver(stm32_sai_driver);
+
+MODULE_DESCRIPTION("STM32 Soc SAI Interface");
+MODULE_AUTHOR("Olivier Moysan, <olivier.moysan-qxv4g6HH51o@public.gmane.org>");
+MODULE_ALIAS("platform:st,stm32-sai");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h
new file mode 100644
index 000000000000..a801fda5066f
--- /dev/null
+++ b/sound/soc/stm/stm32_sai.h
@@ -0,0 +1,200 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ */
+
+/******************** SAI Register Map **************************************/
+
+/* common register */
+#define STM_SAI_GCR		0x00
+
+/* Sub-block A&B registers offsets, relative to A&B sub-block addresses */
+#define STM_SAI_CR1_REGX	0x00	/* A offset: 0x04. B offset: 0x24 */
+#define STM_SAI_CR2_REGX	0x04
+#define STM_SAI_FRCR_REGX	0x08
+#define STM_SAI_SLOTR_REGX	0x0C
+#define STM_SAI_IMR_REGX	0x10
+#define STM_SAI_SR_REGX		0x14
+#define STM_SAI_CLRFR_REGX	0x18
+#define STM_SAI_DR_REGX		0x1C
+
+/******************** Bit definition for SAI_GCR register *******************/
+#define SAI_GCR_SYNCIN_SHIFT	0
+#define SAI_GCR_SYNCIN_MASK	GENMASK(1, SAI_GCR_SYNCIN_SHIFT)
+#define SAI_GCR_SYNCIN_SET(x)	((x) << SAI_GCR_SYNCIN_SHIFT)
+
+#define SAI_GCR_SYNCOUT_SHIFT	4
+#define SAI_GCR_SYNCOUT_MASK	GENMASK(5, SAI_GCR_SYNCOUT_SHIFT)
+#define SAI_GCR_SYNCOUT_SET(x)	((x) << SAI_GCR_SYNCOUT_SHIFT)
+
+/******************* Bit definition for SAI_XCR1 register *******************/
+#define SAI_XCR1_RX_TX_SHIFT	0
+#define SAI_XCR1_RX_TX		BIT(SAI_XCR1_RX_TX_SHIFT)
+#define SAI_XCR1_SLAVE_SHIFT	1
+#define SAI_XCR1_SLAVE		BIT(SAI_XCR1_SLAVE_SHIFT)
+
+#define SAI_XCR1_PRTCFG_SHIFT	2
+#define SAI_XCR1_PRTCFG_MASK	GENMASK(3, SAI_XCR1_PRTCFG_SHIFT)
+#define SAI_XCR1_PRTCFG_SET(x)	((x) << SAI_XCR1_PRTCFG_SHIFT)
+
+#define SAI_XCR1_DS_SHIFT	5
+#define SAI_XCR1_DS_MASK	GENMASK(7, SAI_XCR1_DS_SHIFT)
+#define SAI_XCR1_DS_SET(x)	((x) << SAI_XCR1_DS_SHIFT)
+
+#define SAI_XCR1_LSBFIRST_SHIFT	8
+#define SAI_XCR1_LSBFIRST	BIT(SAI_XCR1_LSBFIRST_SHIFT)
+#define SAI_XCR1_CKSTR_SHIFT	9
+#define SAI_XCR1_CKSTR		BIT(SAI_XCR1_CKSTR_SHIFT)
+
+#define SAI_XCR1_SYNCEN_SHIFT	10
+#define SAI_XCR1_SYNCEN_MASK	GENMASK(11, SAI_XCR1_SYNCEN_SHIFT)
+#define SAI_XCR1_SYNCEN_SET(x)	((x) << SAI_XCR1_SYNCEN_SHIFT)
+
+#define SAI_XCR1_MONO_SHIFT	12
+#define SAI_XCR1_MONO		BIT(SAI_XCR1_MONO_SHIFT)
+#define SAI_XCR1_OUTDRIV_SHIFT	13
+#define SAI_XCR1_OUTDRIV	BIT(SAI_XCR1_OUTDRIV_SHIFT)
+#define SAI_XCR1_SAIEN_SHIFT	16
+#define SAI_XCR1_SAIEN		BIT(SAI_XCR1_SAIEN_SHIFT)
+#define SAI_XCR1_DMAEN_SHIFT	17
+#define SAI_XCR1_DMAEN		BIT(SAI_XCR1_DMAEN_SHIFT)
+#define SAI_XCR1_NODIV_SHIFT	19
+#define SAI_XCR1_NODIV		BIT(SAI_XCR1_NODIV_SHIFT)
+
+#define SAI_XCR1_MCKDIV_SHIFT	20
+#define SAI_XCR1_MCKDIV_WIDTH	4
+#define SAI_XCR1_MCKDIV_MASK	GENMASK(24, SAI_XCR1_MCKDIV_SHIFT)
+#define SAI_XCR1_MCKDIV_SET(x)	((x) << SAI_XCR1_MCKDIV_SHIFT)
+#define SAI_XCR1_MCKDIV_MAX	((1 << SAI_XCR1_MCKDIV_WIDTH) - 1)
+
+#define SAI_XCR1_OSR_SHIFT	26
+#define SAI_XCR1_OSR		BIT(SAI_XCR1_OSR_SHIFT)
+
+/******************* Bit definition for SAI_XCR2 register *******************/
+#define SAI_XCR2_FTH_SHIFT	0
+#define SAI_XCR2_FTH_MASK	GENMASK(2, SAI_XCR2_FTH_SHIFT)
+#define SAI_XCR2_FTH_SET(x)	((x) << SAI_XCR2_FTH_SHIFT)
+
+#define SAI_XCR2_FFLUSH_SHIFT	3
+#define SAI_XCR2_FFLUSH		BIT(SAI_XCR2_FFLUSH_SHIFT)
+#define SAI_XCR2_TRIS_SHIFT	4
+#define SAI_XCR2_TRIS		BIT(SAI_XCR2_TRIS_SHIFT)
+#define SAI_XCR2_MUTE_SHIFT	5
+#define SAI_XCR2_MUTE		BIT(SAI_XCR2_MUTE_SHIFT)
+#define SAI_XCR2_MUTEVAL_SHIFT	6
+#define SAI_XCR2_MUTEVAL	BIT(SAI_XCR2_MUTEVAL_SHIFT)
+
+#define SAI_XCR2_MUTECNT_SHIFT	7
+#define SAI_XCR2_MUTECNT_MASK	GENMASK(12, SAI_XCR2_MUTECNT_SHIFT)
+#define SAI_XCR2_MUTECNT_SET(x)	((x) << SAI_XCR2_MUTECNT_SHIFT)
+
+#define SAI_XCR2_CPL_SHIFT	13
+#define SAI_XCR2_CPL		BIT(SAI_XCR2_CPL_SHIFT)
+
+#define SAI_XCR2_COMP_SHIFT	14
+#define SAI_XCR2_COMP_MASK	GENMASK(15, SAI_XCR2_COMP_SHIFT)
+#define SAI_XCR2_COMP_SET(x)	((x) << SAI_XCR2_COMP_SHIFT)
+
+/****************** Bit definition for SAI_XFRCR register *******************/
+#define SAI_XFRCR_FRL_SHIFT	0
+#define SAI_XFRCR_FRL_MASK	GENMASK(7, SAI_XFRCR_FRL_SHIFT)
+#define SAI_XFRCR_FRL_SET(x)	((x) << SAI_XFRCR_FRL_SHIFT)
+
+#define SAI_XFRCR_FSALL_SHIFT	8
+#define SAI_XFRCR_FSALL_MASK	GENMASK(14, SAI_XFRCR_FSALL_SHIFT)
+#define SAI_XFRCR_FSALL_SET(x)	((x) << SAI_XFRCR_FSALL_SHIFT)
+
+#define SAI_XFRCR_FSDEF_SHIFT	16
+#define SAI_XFRCR_FSDEF		BIT(SAI_XFRCR_FSDEF_SHIFT)
+#define SAI_XFRCR_FSPOL_SHIFT	17
+#define SAI_XFRCR_FSPOL		BIT(SAI_XFRCR_FSPOL_SHIFT)
+#define SAI_XFRCR_FSOFF_SHIFT	18
+#define SAI_XFRCR_FSOFF		BIT(SAI_XFRCR_FSOFF_SHIFT)
+
+/****************** Bit definition for SAI_XSLOTR register ******************/
+
+#define SAI_XSLOTR_FBOFF_SHIFT	0
+#define SAI_XSLOTR_FBOFF_MASK	GENMASK(4, SAI_XSLOTR_FBOFF_SHIFT)
+#define SAI_XSLOTR_FBOFF_SET(x)	((x) << SAI_XSLOTR_FBOFF_SHIFT)
+
+#define SAI_XSLOTR_SLOTSZ_SHIFT	6
+#define SAI_XSLOTR_SLOTSZ_MASK	GENMASK(7, SAI_XSLOTR_SLOTSZ_SHIFT)
+#define SAI_XSLOTR_SLOTSZ_SET(x)	((x) << SAI_XSLOTR_SLOTSZ_SHIFT)
+
+#define SAI_XSLOTR_NBSLOT_SHIFT 8
+#define SAI_XSLOTR_NBSLOT_MASK	GENMASK(11, SAI_XSLOTR_NBSLOT_SHIFT)
+#define SAI_XSLOTR_NBSLOT_SET(x) ((x) << SAI_XSLOTR_NBSLOT_SHIFT)
+
+#define SAI_XSLOTR_SLOTEN_SHIFT	16
+#define SAI_XSLOTR_SLOTEN_WIDTH	16
+#define SAI_XSLOTR_SLOTEN_MASK	GENMASK(31, SAI_XSLOTR_SLOTEN_SHIFT)
+#define SAI_XSLOTR_SLOTEN_SET(x) ((x) << SAI_XSLOTR_SLOTEN_SHIFT)
+
+/******************* Bit definition for SAI_XIMR register *******************/
+#define SAI_XIMR_OVRUDRIE	BIT(0)
+#define SAI_XIMR_MUTEDETIE	BIT(1)
+#define SAI_XIMR_WCKCFGIE	BIT(2)
+#define SAI_XIMR_FREQIE		BIT(3)
+#define SAI_XIMR_CNRDYIE	BIT(4)
+#define SAI_XIMR_AFSDETIE	BIT(5)
+#define SAI_XIMR_LFSDETIE	BIT(6)
+
+#define SAI_XIMR_SHIFT	0
+#define SAI_XIMR_MASK		GENMASK(6, SAI_XIMR_SHIFT)
+
+/******************** Bit definition for SAI_XSR register *******************/
+#define SAI_XSR_OVRUDR		BIT(0)
+#define SAI_XSR_MUTEDET		BIT(1)
+#define SAI_XSR_WCKCFG		BIT(2)
+#define SAI_XSR_FREQ		BIT(3)
+#define SAI_XSR_CNRDY		BIT(4)
+#define SAI_XSR_AFSDET		BIT(5)
+#define SAI_XSR_LFSDET		BIT(6)
+
+#define SAI_XSR_SHIFT	0
+#define SAI_XSR_MASK		GENMASK(6, SAI_XSR_SHIFT)
+
+/****************** Bit definition for SAI_XCLRFR register ******************/
+#define SAI_XCLRFR_COVRUDR	BIT(0)
+#define SAI_XCLRFR_CMUTEDET	BIT(1)
+#define SAI_XCLRFR_CWCKCFG	BIT(2)
+#define SAI_XCLRFR_CFREQ	BIT(3)
+#define SAI_XCLRFR_CCNRDY	BIT(4)
+#define SAI_XCLRFR_CAFSDET	BIT(5)
+#define SAI_XCLRFR_CLFSDET	BIT(6)
+
+#define SAI_XCLRFR_SHIFT	0
+#define SAI_XCLRFR_MASK		GENMASK(6, SAI_XCLRFR_SHIFT)
+
+enum stm32_sai_version {
+	SAI_STM32F4
+};
+
+/**
+ * struct stm32_sai_data - private data of SAI instance driver
+ * @pdev: device data pointer
+ * @clk_x8k: SAI parent clock for sampling frequencies multiple of 8kHz
+ * @clk_x11k: SAI parent clock for sampling frequencies multiple of 11kHz
+ * @version: SOC version
+ * @irq: SAI interrupt line
+ */
+struct stm32_sai_data {
+	struct platform_device *pdev;
+	struct clk *clk_x8k;
+	struct clk *clk_x11k;
+	int version;
+	int irq;
+};
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
new file mode 100644
index 000000000000..ae4706ca265b
--- /dev/null
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -0,0 +1,884 @@
+/*
+ * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Olivier Moysan <olivier.moysan-qxv4g6HH51o@public.gmane.org> for STMicroelectronics.
+ *
+ * License terms: GPL V2.0.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "stm32_sai.h"
+
+#define SAI_FREE_PROTOCOL	0x0
+
+#define SAI_SLOT_SIZE_AUTO	0x0
+#define SAI_SLOT_SIZE_16	0x1
+#define SAI_SLOT_SIZE_32	0x2
+
+#define SAI_DATASIZE_8		0x2
+#define SAI_DATASIZE_10		0x3
+#define SAI_DATASIZE_16		0x4
+#define SAI_DATASIZE_20		0x5
+#define SAI_DATASIZE_24		0x6
+#define SAI_DATASIZE_32		0x7
+
+#define STM_SAI_FIFO_SIZE	8
+#define STM_SAI_DAI_NAME_SIZE	15
+
+#define STM_SAI_IS_PLAYBACK(ip)	((ip)->dir == SNDRV_PCM_STREAM_PLAYBACK)
+#define STM_SAI_IS_CAPTURE(ip)	((ip)->dir == SNDRV_PCM_STREAM_CAPTURE)
+
+#define STM_SAI_A_ID		0x0
+#define STM_SAI_B_ID		0x1
+
+#define STM_SAI_BLOCK_NAME(x)	(((x)->id == STM_SAI_A_ID) ? "A" : "B")
+
+/**
+ * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
+ * @pdev: device data pointer
+ * @regmap: SAI register map pointer
+ * @dma_params: dma configuration data for rx or tx channel
+ * @cpu_dai_drv: DAI driver data pointer
+ * @cpu_dai: DAI runtime data pointer
+ * @substream: PCM substream data pointer
+ * @pdata: SAI block parent data pointer
+ * @sai_ck: kernel clock feeding the SAI clock generator
+ * @phys_addr: SAI registers physical base address
+ * @mclk_rate: SAI block master clock frequency (Hz). set at init
+ * @id: SAI sub block id corresponding to sub-block A or B
+ * @dir: SAI block direction (playback or capture). set at init
+ * @master: SAI block mode flag. (true=master, false=slave) set at init
+ * @fmt: SAI block format. relevant only for custom protocols. set at init
+ * @sync: SAI block synchronization mode. (none, internal or external)
+ * @fs_length: frame synchronization length. depends on protocol settings
+ * @slots: rx or tx slot number
+ * @slot_width: rx or tx slot width in bits
+ * @slot_mask: rx or tx active slots mask. set at init or at runtime
+ * @data_size: PCM data width. corresponds to PCM substream width.
+ */
+struct stm32_sai_sub_data {
+	struct platform_device *pdev;
+	struct regmap *regmap;
+	struct snd_dmaengine_dai_dma_data dma_params;
+	struct snd_soc_dai_driver *cpu_dai_drv;
+	struct snd_soc_dai *cpu_dai;
+	struct snd_pcm_substream *substream;
+	struct stm32_sai_data *pdata;
+	struct clk *sai_ck;
+	dma_addr_t phys_addr;
+	unsigned int mclk_rate;
+	unsigned int id;
+	int dir;
+	bool master;
+	int fmt;
+	int sync;
+	int fs_length;
+	int slots;
+	int slot_width;
+	int slot_mask;
+	int data_size;
+};
+
+enum stm32_sai_fifo_th {
+	STM_SAI_FIFO_TH_EMPTY,
+	STM_SAI_FIFO_TH_QUARTER,
+	STM_SAI_FIFO_TH_HALF,
+	STM_SAI_FIFO_TH_3_QUARTER,
+	STM_SAI_FIFO_TH_FULL,
+};
+
+static bool stm32_sai_sub_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case STM_SAI_CR1_REGX:
+	case STM_SAI_CR2_REGX:
+	case STM_SAI_FRCR_REGX:
+	case STM_SAI_SLOTR_REGX:
+	case STM_SAI_IMR_REGX:
+	case STM_SAI_SR_REGX:
+	case STM_SAI_CLRFR_REGX:
+	case STM_SAI_DR_REGX:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool stm32_sai_sub_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case STM_SAI_DR_REGX:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool stm32_sai_sub_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case STM_SAI_CR1_REGX:
+	case STM_SAI_CR2_REGX:
+	case STM_SAI_FRCR_REGX:
+	case STM_SAI_SLOTR_REGX:
+	case STM_SAI_IMR_REGX:
+	case STM_SAI_SR_REGX:
+	case STM_SAI_CLRFR_REGX:
+	case STM_SAI_DR_REGX:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config stm32_sai_sub_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = STM_SAI_DR_REGX,
+	.readable_reg = stm32_sai_sub_readable_reg,
+	.volatile_reg = stm32_sai_sub_volatile_reg,
+	.writeable_reg = stm32_sai_sub_writeable_reg,
+	.fast_io = true,
+};
+
+static irqreturn_t stm32_sai_isr(int irq, void *devid)
+{
+	struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid;
+	struct snd_pcm_substream *substream = sai->substream;
+	struct platform_device *pdev = sai->pdev;
+	unsigned int sr, imr, flags;
+	snd_pcm_state_t status = SNDRV_PCM_STATE_RUNNING;
+
+	regmap_read(sai->regmap, STM_SAI_IMR_REGX, &imr);
+	regmap_read(sai->regmap, STM_SAI_SR_REGX, &sr);
+
+	flags = sr & imr;
+	if (!flags)
+		return IRQ_NONE;
+
+	regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK,
+			   SAI_XCLRFR_MASK);
+
+	if (flags & SAI_XIMR_OVRUDRIE) {
+		dev_err(&pdev->dev, "IT %s\n",
+			STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun");
+		status = SNDRV_PCM_STATE_XRUN;
+	}
+
+	if (flags & SAI_XIMR_MUTEDETIE)
+		dev_dbg(&pdev->dev, "IT mute detected\n");
+
+	if (flags & SAI_XIMR_WCKCFGIE) {
+		dev_err(&pdev->dev, "IT wrong clock configuration\n");
+		status = SNDRV_PCM_STATE_DISCONNECTED;
+	}
+
+	if (flags & SAI_XIMR_CNRDYIE)
+		dev_warn(&pdev->dev, "IT Codec not ready\n");
+
+	if (flags & SAI_XIMR_AFSDETIE) {
+		dev_warn(&pdev->dev, "IT Anticipated frame synchro\n");
+		status = SNDRV_PCM_STATE_XRUN;
+	}
+
+	if (flags & SAI_XIMR_LFSDETIE) {
+		dev_warn(&pdev->dev, "IT Late frame synchro\n");
+		status = SNDRV_PCM_STATE_XRUN;
+	}
+
+	if (status != SNDRV_PCM_STATE_RUNNING) {
+		snd_pcm_stream_lock(substream);
+		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		snd_pcm_stream_unlock(substream);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
+				int clk_id, unsigned int freq, int dir)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if ((dir == SND_SOC_CLOCK_OUT) && sai->master) {
+		sai->mclk_rate = freq;
+		dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
+	}
+
+	return 0;
+}
+
+static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
+				      u32 rx_mask, int slots, int slot_width)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int slotr, slotr_mask, slot_size;
+
+	dev_dbg(cpu_dai->dev, "masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
+		tx_mask, rx_mask, slots, slot_width);
+
+	switch (slot_width) {
+	case 16:
+		slot_size = SAI_SLOT_SIZE_16;
+		break;
+	case 32:
+		slot_size = SAI_SLOT_SIZE_32;
+		break;
+	default:
+		slot_size = SAI_SLOT_SIZE_AUTO;
+		break;
+	}
+
+	slotr = SAI_XSLOTR_SLOTSZ_SET(slot_size) |
+		SAI_XSLOTR_NBSLOT_SET(slots - 1);
+	slotr_mask = SAI_XSLOTR_SLOTSZ_MASK | SAI_XSLOTR_NBSLOT_MASK;
+
+	/* tx/rx mask set in machine init, if slot number defined in DT */
+	if (STM_SAI_IS_PLAYBACK(sai)) {
+		sai->slot_mask = tx_mask;
+		slotr |= SAI_XSLOTR_SLOTEN_SET(tx_mask);
+	}
+
+	if (STM_SAI_IS_CAPTURE(sai)) {
+		sai->slot_mask = rx_mask;
+		slotr |= SAI_XSLOTR_SLOTEN_SET(rx_mask);
+	}
+
+	slotr_mask |= SAI_XSLOTR_SLOTEN_MASK;
+
+	regmap_update_bits(sai->regmap, STM_SAI_SLOTR_REGX, slotr_mask, slotr);
+
+	sai->slot_width = slot_width;
+	sai->slots = slots;
+
+	return 0;
+}
+
+static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int cr1 = 0, frcr = 0;
+	int cr1_mask = 0, frcr_mask = 0;
+	int ret;
+
+	dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	/* SCK active high for all protocols */
+	case SND_SOC_DAIFMT_I2S:
+		cr1 |= SAI_XCR1_CKSTR;
+		frcr |= SAI_XFRCR_FSOFF | SAI_XFRCR_FSDEF;
+		break;
+	/* Left justified */
+	case SND_SOC_DAIFMT_MSB:
+		frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF;
+		break;
+	/* Right justified */
+	case SND_SOC_DAIFMT_LSB:
+		frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		frcr |= SAI_XFRCR_FSPOL;
+		break;
+	default:
+		dev_err(cpu_dai->dev, "Unsupported protocol %#x\n",
+			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		return -EINVAL;
+	}
+
+	cr1_mask |= SAI_XCR1_PRTCFG_MASK | SAI_XCR1_CKSTR;
+	frcr_mask |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF |
+		     SAI_XFRCR_FSDEF;
+
+	/* DAI clock strobing. Invert setting previously set */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		cr1 ^= SAI_XCR1_CKSTR;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		frcr ^= SAI_XFRCR_FSPOL;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		/* Invert fs & sck */
+		cr1 ^= SAI_XCR1_CKSTR;
+		frcr ^= SAI_XFRCR_FSPOL;
+		break;
+	default:
+		dev_err(cpu_dai->dev, "Unsupported strobing %#x\n",
+			fmt & SND_SOC_DAIFMT_INV_MASK);
+		return -EINVAL;
+	}
+	cr1_mask |= SAI_XCR1_CKSTR;
+	frcr_mask |= SAI_XFRCR_FSPOL;
+
+	regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr);
+
+	/* DAI clock master masks */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		/* codec is master */
+		cr1 |= SAI_XCR1_SLAVE;
+		sai->master = false;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		sai->master = true;
+		break;
+	default:
+		dev_err(cpu_dai->dev, "Unsupported mode %#x\n",
+			fmt & SND_SOC_DAIFMT_MASTER_MASK);
+		return -EINVAL;
+	}
+	cr1_mask |= SAI_XCR1_SLAVE;
+
+	ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+		return ret;
+	}
+
+	sai->fmt = fmt;
+
+	return 0;
+}
+
+static int stm32_sai_startup(struct snd_pcm_substream *substream,
+			     struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int imr, cr2, ret;
+
+	sai->substream = substream;
+
+	ret = clk_prepare_enable(sai->sai_ck);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	/* Enable ITs */
+	regmap_update_bits(sai->regmap, STM_SAI_SR_REGX,
+			   SAI_XSR_MASK, (unsigned int)~SAI_XSR_MASK);
+
+	regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX,
+			   SAI_XCLRFR_MASK, SAI_XCLRFR_MASK);
+
+	imr = SAI_XIMR_OVRUDRIE;
+	if (STM_SAI_IS_CAPTURE(sai)) {
+		regmap_read(sai->regmap, STM_SAI_CR2_REGX, &cr2);
+		if (cr2 & SAI_XCR2_MUTECNT_MASK)
+			imr |= SAI_XIMR_MUTEDETIE;
+	}
+
+	if (sai->master)
+		imr |= SAI_XIMR_WCKCFGIE;
+	else
+		imr |= SAI_XIMR_AFSDETIE | SAI_XIMR_LFSDETIE;
+
+	regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX,
+			   SAI_XIMR_MASK, imr);
+
+	return 0;
+}
+
+static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
+				struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int cr1, cr1_mask, ret;
+	int fth = STM_SAI_FIFO_TH_HALF;
+
+	/* FIFO config */
+	regmap_update_bits(sai->regmap, STM_SAI_CR2_REGX,
+			   SAI_XCR2_FFLUSH | SAI_XCR2_FTH_MASK,
+			   SAI_XCR2_FFLUSH | SAI_XCR2_FTH_SET(fth));
+
+	/* Mode, data format and channel config */
+	cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_8);
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_16);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		cr1 |= SAI_XCR1_DS_SET(SAI_DATASIZE_32);
+		break;
+	default:
+		dev_err(cpu_dai->dev, "Data format not supported");
+		return -EINVAL;
+	}
+	cr1_mask = SAI_XCR1_DS_MASK | SAI_XCR1_PRTCFG_MASK;
+
+	cr1_mask |= SAI_XCR1_RX_TX;
+	if (STM_SAI_IS_CAPTURE(sai))
+		cr1 |= SAI_XCR1_RX_TX;
+
+	cr1_mask |= SAI_XCR1_MONO;
+	if ((sai->slots == 2) && (params_channels(params) == 1))
+		cr1 |= SAI_XCR1_MONO;
+
+	ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+		return ret;
+	}
+
+	/* DMA config */
+	sai->dma_params.maxburst = STM_SAI_FIFO_SIZE * fth / sizeof(u32);
+	snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&sai->dma_params);
+
+	return 0;
+}
+
+static int stm32_sai_set_slots(struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int slotr, slot_sz;
+
+	regmap_read(sai->regmap, STM_SAI_SLOTR_REGX, &slotr);
+
+	/*
+	 * If SLOTSZ is set to auto in SLOTR, align slot width on data size
+	 * By default slot width = data size, if not forced from DT
+	 */
+	slot_sz = slotr & SAI_XSLOTR_SLOTSZ_MASK;
+	if (slot_sz == SAI_XSLOTR_SLOTSZ_SET(SAI_SLOT_SIZE_AUTO))
+		sai->slot_width = sai->data_size;
+
+	if (sai->slot_width < sai->data_size) {
+		dev_err(cpu_dai->dev,
+			"Data size %d larger than slot width\n",
+			sai->data_size);
+		return -EINVAL;
+	}
+
+	/* Slot number is set to 2, if not specified in DT */
+	if (!sai->slots)
+		sai->slots = 2;
+
+	/* The number of slots in the audio frame is equal to NBSLOT[3:0] + 1*/
+	regmap_update_bits(sai->regmap, STM_SAI_SLOTR_REGX,
+			   SAI_XSLOTR_NBSLOT_MASK,
+			   SAI_XSLOTR_NBSLOT_SET((sai->slots - 1)));
+
+	/* Set default slots mask if not already set from DT */
+	if (!(slotr & SAI_XSLOTR_SLOTEN_MASK)) {
+		sai->slot_mask = (1 << sai->slots) - 1;
+		regmap_update_bits(sai->regmap,
+				   STM_SAI_SLOTR_REGX, SAI_XSLOTR_SLOTEN_MASK,
+				   SAI_XSLOTR_SLOTEN_SET(sai->slot_mask));
+	}
+
+	dev_dbg(cpu_dai->dev, "slots %d, slot width %d\n",
+		sai->slots, sai->slot_width);
+
+	return 0;
+}
+
+static void stm32_sai_set_frame(struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int fs_active, offset, format;
+	int frcr, frcr_mask;
+
+	format = sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+	sai->fs_length = sai->slot_width * sai->slots;
+
+	fs_active = sai->fs_length / 2;
+	if ((format == SND_SOC_DAIFMT_DSP_A) ||
+	    (format == SND_SOC_DAIFMT_DSP_B))
+		fs_active = 1;
+
+	frcr = SAI_XFRCR_FRL_SET((sai->fs_length - 1));
+	frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1));
+	frcr_mask = SAI_XFRCR_FRL_MASK | SAI_XFRCR_FSALL_MASK;
+
+	dev_dbg(cpu_dai->dev, "frame length %d, frame active %d\n",
+		sai->fs_length, fs_active);
+
+	regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr);
+
+	if ((sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_LSB) {
+		offset = sai->slot_width - sai->data_size;
+
+		regmap_update_bits(sai->regmap, STM_SAI_SLOTR_REGX,
+				   SAI_XSLOTR_FBOFF_MASK,
+				   SAI_XSLOTR_FBOFF_SET(offset));
+	}
+}
+
+static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
+				     struct snd_pcm_hw_params *params)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int cr1, mask, div = 0;
+	int sai_clk_rate, ret;
+
+	if (!sai->mclk_rate) {
+		dev_err(cpu_dai->dev, "Mclk rate is null\n");
+		return -EINVAL;
+	}
+
+	if (!(params_rate(params) % 11025))
+		clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
+	else
+		clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
+	sai_clk_rate = clk_get_rate(sai->sai_ck);
+
+	/*
+	 * mclk_rate = 256 * fs
+	 * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate
+	 * MCKDIV = sai_ck / (2 * mclk_rate) otherwise
+	 */
+	if (2 * sai_clk_rate >= 3 * sai->mclk_rate)
+		div = DIV_ROUND_CLOSEST(sai_clk_rate, 2 * sai->mclk_rate);
+
+	if (div > SAI_XCR1_MCKDIV_MAX) {
+		dev_err(cpu_dai->dev, "Divider %d out of range\n", div);
+		return -EINVAL;
+	}
+	dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div);
+
+	mask = SAI_XCR1_MCKDIV_MASK;
+	cr1 = SAI_XCR1_MCKDIV_SET(div);
+	ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int stm32_sai_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *params,
+			       struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int ret;
+
+	sai->data_size = params_width(params);
+
+	ret = stm32_sai_set_slots(cpu_dai);
+	if (ret < 0)
+		return ret;
+	stm32_sai_set_frame(cpu_dai);
+
+	ret = stm32_sai_set_config(cpu_dai, substream, params);
+	if (ret)
+		return ret;
+
+	if (sai->master)
+		ret = stm32_sai_configure_clock(cpu_dai, params);
+
+	return ret;
+}
+
+static int stm32_sai_trigger(struct snd_pcm_substream *substream, int cmd,
+			     struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		dev_dbg(cpu_dai->dev, "Enable DMA and SAI\n");
+
+		regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
+				   SAI_XCR1_DMAEN, SAI_XCR1_DMAEN);
+
+		/* Enable SAI */
+		ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
+					 SAI_XCR1_SAIEN, SAI_XCR1_SAIEN);
+		if (ret < 0)
+			dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_STOP:
+		dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n");
+
+		regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
+				   SAI_XCR1_DMAEN,
+				   (unsigned int)~SAI_XCR1_DMAEN);
+
+		ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
+					 SAI_XCR1_SAIEN,
+					 (unsigned int)~SAI_XCR1_SAIEN);
+		if (ret < 0)
+			dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+	regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
+
+	clk_disable_unprepare(sai->sai_ck);
+	sai->substream = NULL;
+}
+
+static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
+{
+	struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
+
+	sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX);
+	sai->dma_params.maxburst = 1;
+	/* Buswidth will be set by framework at runtime */
+	sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+
+	if (STM_SAI_IS_PLAYBACK(sai))
+		snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params, NULL);
+	else
+		snd_soc_dai_init_dma_data(cpu_dai, NULL, &sai->dma_params);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops stm32_sai_pcm_dai_ops = {
+	.set_sysclk	= stm32_sai_set_sysclk,
+	.set_fmt	= stm32_sai_set_dai_fmt,
+	.set_tdm_slot	= stm32_sai_set_dai_tdm_slot,
+	.startup	= stm32_sai_startup,
+	.hw_params	= stm32_sai_hw_params,
+	.trigger	= stm32_sai_trigger,
+	.shutdown	= stm32_sai_shutdown,
+};
+
+static const struct snd_pcm_hardware stm32_sai_pcm_hw = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
+	.buffer_bytes_max = 8 * PAGE_SIZE,
+	.period_bytes_min = 1024, /* 5ms at 48kHz */
+	.period_bytes_max = PAGE_SIZE,
+	.periods_min = 2,
+	.periods_max = 8,
+};
+
+static struct snd_soc_dai_driver stm32_sai_playback_dai[] = {
+{
+		.probe = stm32_sai_dai_probe,
+		.id = 1, /* avoid call to fmt_single_name() */
+		.playback = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.rates = SNDRV_PCM_RATE_CONTINUOUS,
+			/* DMA does not support 24 bits transfers */
+			.formats =
+				SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &stm32_sai_pcm_dai_ops,
+	}
+};
+
+static struct snd_soc_dai_driver stm32_sai_capture_dai[] = {
+{
+		.probe = stm32_sai_dai_probe,
+		.id = 1, /* avoid call to fmt_single_name() */
+		.capture = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.rates = SNDRV_PCM_RATE_CONTINUOUS,
+			/* DMA does not support 24 bits transfers */
+			.formats =
+				SNDRV_PCM_FMTBIT_S8 |
+				SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &stm32_sai_pcm_dai_ops,
+	}
+};
+
+static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config = {
+	.pcm_hardware	= &stm32_sai_pcm_hw,
+	.prepare_slave_config	= snd_dmaengine_pcm_prepare_slave_config,
+};
+
+static const struct snd_soc_component_driver stm32_component = {
+	.name = "stm32-sai",
+};
+
+static const struct of_device_id stm32_sai_sub_ids[] = {
+	{ .compatible = "st,stm32-sai-sub-a",
+	  .data = (void *)STM_SAI_A_ID},
+	{ .compatible = "st,stm32-sai-sub-b",
+	  .data = (void *)STM_SAI_B_ID},
+	{}
+};
+MODULE_DEVICE_TABLE(of, stm32_sai_sub_ids);
+
+static int stm32_sai_sub_parse_of(struct platform_device *pdev,
+				  struct stm32_sai_sub_data *sai)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	void __iomem *base;
+
+	if (!np)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	dev_err(&pdev->dev, "res %pr\n", res);
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	sai->phys_addr = res->start;
+	sai->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+					    &stm32_sai_sub_regmap_config);
+
+	/* Get direction property */
+	if (of_property_match_string(np, "dma-names", "tx") >= 0) {
+		sai->dir = SNDRV_PCM_STREAM_PLAYBACK;
+	} else if (of_property_match_string(np, "dma-names", "rx") >= 0) {
+		sai->dir = SNDRV_PCM_STREAM_CAPTURE;
+	} else {
+		dev_err(&pdev->dev, "Unsupported direction\n");
+		return -EINVAL;
+	}
+
+	sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
+	if (IS_ERR(sai->sai_ck)) {
+		dev_err(&pdev->dev, "missing kernel clock sai_ck\n");
+		return PTR_ERR(sai->sai_ck);
+	}
+
+	return 0;
+}
+
+static int stm32_sai_sub_dais_init(struct platform_device *pdev,
+				   struct stm32_sai_sub_data *sai)
+{
+	sai->cpu_dai_drv = devm_kzalloc(&pdev->dev,
+					sizeof(struct snd_soc_dai_driver),
+					GFP_KERNEL);
+	if (!sai->cpu_dai_drv)
+		return -ENOMEM;
+
+	sai->cpu_dai_drv->name = dev_name(&pdev->dev);
+	if (STM_SAI_IS_PLAYBACK(sai)) {
+		memcpy(sai->cpu_dai_drv, &stm32_sai_playback_dai,
+		       sizeof(stm32_sai_playback_dai));
+		sai->cpu_dai_drv->playback.stream_name = sai->cpu_dai_drv->name;
+	} else {
+		memcpy(sai->cpu_dai_drv, &stm32_sai_capture_dai,
+		       sizeof(stm32_sai_capture_dai));
+		sai->cpu_dai_drv->capture.stream_name = sai->cpu_dai_drv->name;
+	}
+
+	return 0;
+}
+
+static int stm32_sai_sub_probe(struct platform_device *pdev)
+{
+	struct stm32_sai_sub_data *sai;
+	const struct of_device_id *of_id;
+	int ret;
+
+	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
+	if (!sai)
+		return -ENOMEM;
+
+	of_id = of_match_device(stm32_sai_sub_ids, &pdev->dev);
+	if (!of_id)
+		return -EINVAL;
+	sai->id = (uintptr_t)of_id->data;
+
+	sai->pdev = pdev;
+	platform_set_drvdata(pdev, sai);
+
+	sai->pdata = dev_get_drvdata(pdev->dev.parent);
+	if (!sai->pdata) {
+		dev_err(&pdev->dev, "Parent device data not available\n");
+		return -EINVAL;
+	}
+
+	ret = stm32_sai_sub_parse_of(pdev, sai);
+	if (ret)
+		return ret;
+
+	ret = stm32_sai_sub_dais_init(pdev, sai);
+	if (ret)
+		return ret;
+
+	ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr,
+			       IRQF_SHARED, dev_name(&pdev->dev), sai);
+	if (ret) {
+		dev_err(&pdev->dev, "irq request returned %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_snd_soc_register_component(&pdev->dev, &stm32_component,
+					      sai->cpu_dai_drv, 1);
+	if (ret)
+		return ret;
+
+	ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
+					      &stm32_sai_pcm_config, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "could not register pcm dma\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver stm32_sai_sub_driver = {
+	.driver = {
+		.name = "st,stm32-sai-sub",
+		.of_match_table = stm32_sai_sub_ids,
+	},
+	.probe = stm32_sai_sub_probe,
+};
+
+module_platform_driver(stm32_sai_sub_driver);
+
+MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface");
+MODULE_AUTHOR("Olivier Moysan, <olivier.moysan-qxv4g6HH51o@public.gmane.org>");
+MODULE_ALIAS("platform:st,stm32-sai-sub");
+MODULE_LICENSE("GPL v2");
-- 
2.11.0

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

^ permalink raw reply related

* ''''Order Inquiry''''
From: Utilities Packages USA @ 2017-04-26 15:40 UTC (permalink / raw)
  To: Recipients

Hello,

We would like to make a purchase on your product.

Urgently send samples of your product to the below Email Address now:
kennethturner4440-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

We're ready to make orders now.

Kindly get back to us ASAP.

Sincerely Yours,

--
Utilities Packages USA
Kenneth Turner  President and CEO
Office 407-348-8848
Cell....407-301-7789
3728 Grissom Lane
Kissimmee Fl 34744
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v5 10/10] arm64: allwinner: a64: enable Wi-Fi for Pine64
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

The Wi-Fi module of Pine64 is powered via DLDO4 and ELDO1 (the latter
one provides I/O voltage).

Add device node for it.

Although the Wi-Fi module is an external module which should be inserted
to a header, according to my personal talk with TL Lim, he does not want
this header to be used as GPIO (so it's with 2.0mm pitch, not 2.54mm as
other GPIO headers).

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
 arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index abc1879e91f2..2e4f44800162 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -64,6 +64,11 @@
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+	};
 };
 
 &ehci1 {
@@ -91,6 +96,17 @@
 	status = "okay";
 };
 
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&reg_dldo4>;
+	vqmmc-supply = <&reg_eldo1>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	non-removable;
+	bus-width = <4>;
+	status = "okay";
+};
+
 &ohci1 {
 	status = "okay";
 };
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 09/10] arm64: allwinner: a64: enable AXP803 regulators for Pine64
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

Add support of AXP803 regulators in the Pine64 device tree, in order to
enable many future functionalities, e.g. Wi-Fi.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
 .../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 109 +++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index 3e1b44292534..abc1879e91f2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -106,6 +106,115 @@
 	};
 };
 
+#include "axp803.dtsi"
+
+&reg_aldo1 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "vcc-csi";
+};
+
+&reg_aldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-pl";
+};
+
+&reg_aldo3 {
+	regulator-always-on;
+	regulator-min-microvolt = <2700000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dc1sw {
+	regulator-name = "vcc-phy";
+};
+
+&reg_dcdc1 {
+	regulator-always-on;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1300000>;
+	regulator-name = "vdd-cpux";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc5 {
+	regulator-always-on;
+	regulator-min-microvolt = <1500000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+	regulator-always-on;
+	regulator-min-microvolt = <1100000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-hdmi";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-mipi";
+};
+
+&reg_dldo3 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "avdd-csi";
+};
+
+&reg_dldo4 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi";
+};
+
+&reg_eldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "cpvdd";
+};
+
+&reg_eldo3 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vdd-1v8-csi";
+};
+
+&reg_fldo1 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "vcc-1v2-hsic";
+};
+
+&reg_fldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1100000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vdd-cpus";
+};
+
+&reg_rtc_ldo {
+	regulator-name = "vcc-rtc";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 08/10] arm64: allwinner: a64: add DTSI file for AXP803 PMIC
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

As nearly all A64 boards are using AXP803 PMIC, add a DTSI file for it,
like the old DTSI files for AXP20x/22x, for the common parts of the
PMIC.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
Acked-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes in v5:
- Added Mark Brown's ACK.
Changes in v4:
- Re-sorted the nodes.

 arch/arm64/boot/dts/allwinner/axp803.dtsi | 150 ++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/axp803.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/axp803.dtsi b/arch/arm64/boot/dts/allwinner/axp803.dtsi
new file mode 100644
index 000000000000..ff8af52743ff
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/axp803.dtsi
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * AXP803 Integrated Power Management Chip
+ * http://files.pine64.org/doc/datasheet/pine64/AXP803_Datasheet_V1.0.pdf
+ */
+
+&axp803 {
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+	regulators {
+		/* Default work frequency for buck regulators */
+		x-powers,dcdc-freq = <3000>;
+
+		reg_aldo1: aldo1 {
+			regulator-name = "aldo1";
+		};
+
+		reg_aldo2: aldo2 {
+			regulator-name = "aldo2";
+		};
+
+		reg_aldo3: aldo3 {
+			regulator-name = "aldo3";
+		};
+
+		reg_dc1sw: dc1sw {
+			regulator-name = "dc1sw";
+		};
+
+		reg_dcdc1: dcdc1 {
+			regulator-name = "dcdc1";
+		};
+
+		reg_dcdc2: dcdc2 {
+			regulator-name = "dcdc2";
+		};
+
+		reg_dcdc3: dcdc3 {
+			regulator-name = "dcdc3";
+		};
+
+		reg_dcdc4: dcdc4 {
+			regulator-name = "dcdc4";
+		};
+
+		reg_dcdc5: dcdc5 {
+			regulator-name = "dcdc5";
+		};
+
+		reg_dcdc6: dcdc6 {
+			regulator-name = "dcdc6";
+		};
+
+		reg_dldo1: dldo1 {
+			regulator-name = "dldo1";
+		};
+
+		reg_dldo2: dldo2 {
+			regulator-name = "dldo2";
+		};
+
+		reg_dldo3: dldo3 {
+			regulator-name = "dldo3";
+		};
+
+		reg_dldo4: dldo4 {
+			regulator-name = "dldo4";
+		};
+
+		reg_eldo1: eldo1 {
+			regulator-name = "eldo1";
+		};
+
+		reg_eldo2: eldo2 {
+			regulator-name = "eldo2";
+		};
+
+		reg_eldo3: eldo3 {
+			regulator-name = "eldo3";
+		};
+
+		reg_fldo1: fldo1 {
+			regulator-name = "fldo1";
+		};
+
+		reg_fldo2: fldo2 {
+			regulator-name = "fldo2";
+		};
+
+		reg_ldo_io0: ldo-io0 {
+			regulator-name = "ldo-io0";
+			status = "disabled";
+		};
+
+		reg_ldo_io1: ldo-io1 {
+			regulator-name = "ldo-io1";
+			status = "disabled";
+		};
+
+		reg_rtc_ldo: rtc-ldo {
+			/* RTC_LDO is a fixed, always-on regulator */
+			regulator-always-on;
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			regulator-name = "rtc-ldo";
+		};
+	};
+};
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 07/10] mfd: axp20x: add axp20x-regulator cell for AXP803
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

As axp20x-regulator now supports AXP803, add a cell for it.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
Acked-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Changes in v5:
- Removed wrong snippet.
Changes in v4:
- Added a trailing comma for new cell, for easier further cell addition.
Changes in v3:
- Make the new cell one-liner.

 drivers/mfd/axp20x.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 1dc6235778eb..917b6ddc4f15 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -848,7 +848,8 @@ static struct mfd_cell axp803_cells[] = {
 		.name			= "axp20x-pek",
 		.num_resources		= ARRAY_SIZE(axp803_pek_resources),
 		.resources		= axp803_pek_resources,
-	}
+	},
+	{	.name			= "axp20x-regulator" },
 };
 
 static struct mfd_cell axp806_cells[] = {
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 06/10] regulator: axp20x-regulator: add support for AXP803
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

AXP803 PMIC also have a series of regulators (DCDCs and LDOs)
controllable via I2C/RSB bus.

Add support for them.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
Acked-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Changes in v4:
- Fixed somewhere which mention AXP806 before 803.
Changes in v2:
- Place AXP803 codes before AXP806/809 ones.
- Fixed some errors in regulator description.
- Reuse AXP803 DLDO2 range for AXP806 CLDO2 & AXP809 DLDO1.

 drivers/regulator/axp20x-regulator.c | 153 ++++++++++++++++++++++++++++++-----
 include/linux/mfd/axp20x.h           |  37 +++++++++
 2 files changed, 168 insertions(+), 22 deletions(-)

diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 0b9d4e3e52c7..e2608fe770b9 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -244,6 +244,82 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
 	.ops		= &axp20x_ops_sw,
 };
 
+static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0x0, 0x46, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 0x47, 0x4b, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 0x21, 0x44, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
+};
+
+/* AXP806's CLDO2 and AXP809's DLDO1 shares the same range */
+static const struct regulator_linear_range axp803_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
+};
+
+static const struct regulator_desc axp803_regulators[] = {
+	AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc234_ranges,
+			76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc234_ranges,
+			76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc234_ranges,
+			76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
+			68, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
+			72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	/* secondary switchable output of DCDC1 */
+	AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+		    BIT(7)),
+	AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
+			32, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+	AXP_DESC_IO(AXP803, LDO_IO0, "ldo-io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP803, LDO_IO1, "ldo-io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc-ldo", "ips", 3000),
+};
+
 static const struct regulator_linear_range axp806_dcdca_ranges[] = {
 	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
 	REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
@@ -254,11 +330,6 @@ static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
 	REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
 };
 
-static const struct regulator_linear_range axp806_cldo2_ranges[] = {
-	REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
-	REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
-};
-
 static const struct regulator_desc axp806_regulators[] = {
 	AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
 			72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
@@ -289,7 +360,7 @@ static const struct regulator_desc axp806_regulators[] = {
 		 AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
 	AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
 		 AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
-	AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges,
+	AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp803_dldo2_ranges,
 			32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
 			BIT(5)),
 	AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
@@ -326,7 +397,7 @@ static const struct regulator_desc axp809_regulators[] = {
 		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
 	AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
 		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
-	AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges,
+	AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp803_dldo2_ranges,
 			32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
 			BIT(3)),
 	AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
@@ -369,14 +440,21 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 		def = 1500;
 		step = 75;
 		break;
-	case AXP806_ID:
+	case AXP803_ID:
 		/*
-		 * AXP806 DCDC work frequency setting has the same range and
+		 * AXP803 DCDC work frequency setting has the same range and
 		 * step as AXP22X, but at a different register.
 		 * Fall through to the check below.
 		 * (See include/linux/mfd/axp20x.h)
 		 */
-		reg = AXP806_DCDC_FREQ_CTRL;
+		reg = AXP803_DCDC_FREQ_CTRL;
+	case AXP806_ID:
+		/*
+		 * AXP806 also have DCDC work frequency setting register at a
+		 * different position.
+		 */
+		if (axp20x->variant == AXP806_ID)
+			reg = AXP806_DCDC_FREQ_CTRL;
 	case AXP221_ID:
 	case AXP223_ID:
 	case AXP809_ID:
@@ -475,6 +553,14 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
 		workmode <<= id - AXP22X_DCDC1;
 		break;
 
+	case AXP803_ID:
+		if (id < AXP803_DCDC1 || id > AXP803_DCDC6)
+			return -EINVAL;
+
+		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP803_DCDC1);
+		workmode <<= id - AXP803_DCDC1;
+		break;
+
 	default:
 		/* should not happen */
 		WARN_ON(1);
@@ -492,20 +578,38 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
 {
 	u32 reg = 0;
 
-	/* Only AXP806 has poly-phase outputs */
-	if (axp20x->variant != AXP806_ID)
-		return false;
+	/*
+	 * Currently in our supported AXP variants, only AXP803 and AXP806
+	 * have polyphase regulators.
+	 */
+	switch (axp20x->variant) {
+	case AXP803_ID:
+		regmap_read(axp20x->regmap, AXP803_POLYPHASE_CTRL, &reg);
+
+		switch (id) {
+		case AXP803_DCDC3:
+			return !!(reg & BIT(6));
+		case AXP803_DCDC6:
+			return !!(reg & BIT(7));
+		}
+		break;
 
-	regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
+	case AXP806_ID:
+		regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
+
+		switch (id) {
+		case AXP806_DCDCB:
+			return (((reg & GENMASK(7, 6)) == BIT(6)) ||
+				((reg & GENMASK(7, 6)) == BIT(7)));
+		case AXP806_DCDCC:
+			return ((reg & GENMASK(7, 6)) == BIT(7));
+		case AXP806_DCDCE:
+			return !!(reg & BIT(5));
+		}
+		break;
 
-	switch (id) {
-	case AXP806_DCDCB:
-		return (((reg & GENMASK(7, 6)) == BIT(6)) ||
-			((reg & GENMASK(7, 6)) == BIT(7)));
-	case AXP806_DCDCC:
-		return ((reg & GENMASK(7, 6)) == BIT(7));
-	case AXP806_DCDCE:
-		return !!(reg & BIT(5));
+	default:
+		return false;
 	}
 
 	return false;
@@ -540,6 +644,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
 						  "x-powers,drive-vbus-en");
 		break;
+	case AXP803_ID:
+		regulators = axp803_regulators;
+		nregulators = AXP803_REG_ID_MAX;
+		break;
 	case AXP806_ID:
 		regulators = axp806_regulators;
 		nregulators = AXP806_REG_ID_MAX;
@@ -579,6 +687,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		 * name.
 		 */
 		if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
+		    (regulators == axp803_regulators && i == AXP803_DC1SW) ||
 		    (regulators == axp809_regulators && i == AXP809_DC1SW)) {
 			new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
 						GFP_KERNEL);
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index cde56cfe8446..965b027e31b3 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -119,6 +119,17 @@ enum axp20x_variants {
 #define AXP806_BUS_ADDR_EXT		0xfe
 #define AXP806_REG_ADDR_EXT		0xff
 
+#define AXP803_POLYPHASE_CTRL		0x14
+#define AXP803_FLDO1_V_OUT		0x1c
+#define AXP803_FLDO2_V_OUT		0x1d
+#define AXP803_DCDC1_V_OUT		0x20
+#define AXP803_DCDC2_V_OUT		0x21
+#define AXP803_DCDC3_V_OUT		0x22
+#define AXP803_DCDC4_V_OUT		0x23
+#define AXP803_DCDC5_V_OUT		0x24
+#define AXP803_DCDC6_V_OUT		0x25
+#define AXP803_DCDC_FREQ_CTRL		0x3b
+
 /* Interrupt */
 #define AXP152_IRQ1_EN			0x40
 #define AXP152_IRQ2_EN			0x41
@@ -350,6 +361,32 @@ enum {
 	AXP809_REG_ID_MAX,
 };
 
+enum {
+	AXP803_DCDC1 = 0,
+	AXP803_DCDC2,
+	AXP803_DCDC3,
+	AXP803_DCDC4,
+	AXP803_DCDC5,
+	AXP803_DCDC6,
+	AXP803_DC1SW,
+	AXP803_ALDO1,
+	AXP803_ALDO2,
+	AXP803_ALDO3,
+	AXP803_DLDO1,
+	AXP803_DLDO2,
+	AXP803_DLDO3,
+	AXP803_DLDO4,
+	AXP803_ELDO1,
+	AXP803_ELDO2,
+	AXP803_ELDO3,
+	AXP803_FLDO1,
+	AXP803_FLDO2,
+	AXP803_RTC_LDO,
+	AXP803_LDO_IO0,
+	AXP803_LDO_IO1,
+	AXP803_REG_ID_MAX,
+};
+
 /* IRQs */
 enum {
 	AXP152_IRQ_LDO0IN_CONNECT = 1,
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 05/10] arm64: allwinner: a64: add AXP803 node to Pine64 device tree
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

The Pine64 (including Pine64+) boards have an AXP803 as its main PMIC.

Add its device node.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
 arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index c680ed385da3..3e1b44292534 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -95,6 +95,17 @@
 	status = "okay";
 };
 
+&r_rsb {
+	status = "okay";
+
+	axp803: pmic@3a3 {
+		compatible = "x-powers,axp803";
+		reg = <0x3a3>;
+		interrupt-parent = <&r_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 04/10] arm64: allwinner: a64: add NMI (R_INTC) controller on A64
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

Allwinner A64 SoC features a R_INTC controller, which controls the NMI
line, and this interrupt line is usually connected to the AXP PMIC.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Changes in v4:
- Changes it to use R_INTC binding and change node label to r_intc.
- Fixed MMIO region.
- Dropped Chen-Yu's ACK due to big change.
Changes in v2:
- Added Chen-Yu's ACK.

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 05ec9fc5e81f..a6566d292934 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -403,6 +403,14 @@
 				     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		r_intc: interrupt-controller@1f00c00 {
+			compatible = "allwinner,sun50i-a64-r-intc";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x01f00c00 0x400>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
 		r_ccu: clock@1f01400 {
 			compatible = "allwinner,sun50i-a64-r-ccu";
 			reg = <0x01f01400 0x100>;
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 03/10] irqchip/sunxi-nmi: add support for the NMI in A64 R_INTC
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

Add support for the newly imported compatible for the A64 R_INTC in
irq-sunxi-nmi driver.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Changes in v5:
- Fix A64 R_INTC compatible.

 drivers/irqchip/irq-sunxi-nmi.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index 668730c5cb66..5559c1d593bf 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -56,6 +56,12 @@ static struct sunxi_sc_nmi_reg_offs sun9i_reg_offs = {
 	.enable	= 0x04,
 };
 
+static struct sunxi_sc_nmi_reg_offs sun50i_reg_offs = {
+	.ctrl	= 0x0c,
+	.pend	= 0x10,
+	.enable	= 0x40,
+};
+
 static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
 				      u32 val)
 {
@@ -220,3 +226,10 @@ static int __init sun9i_nmi_irq_init(struct device_node *node,
 	return sunxi_sc_nmi_irq_init(node, &sun9i_reg_offs);
 }
 IRQCHIP_DECLARE(sun9i_nmi, "allwinner,sun9i-a80-nmi", sun9i_nmi_irq_init);
+
+static int __init sun50i_nmi_irq_init(struct device_node *node,
+				     struct device_node *parent)
+{
+	return sunxi_sc_nmi_irq_init(node, &sun50i_reg_offs);
+}
+IRQCHIP_DECLARE(sun50i_nmi, "allwinner,sun50i-a64-r-intc", sun50i_nmi_irq_init);
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 02/10] irqchip/sunxi-nmi: add A64 R_INTC to the binding doc
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

The A31 NMI driver seems to be using wrong base address.

As we're going to convert to use a correct NMI base address (and
correctly name it to R_INTC as the datasheet suggests), add a new
compatible string for the "correct" R_INTC, which we will use for A64
SoC.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
 .../bindings/interrupt-controller/allwinner,sunxi-nmi.txt          | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt
index 81cd3692405e..fea0c6a6211f 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-nmi.txt
@@ -3,8 +3,11 @@ Allwinner Sunxi NMI Controller
 
 Required properties:
 
-- compatible : should be "allwinner,sun7i-a20-sc-nmi" or
-  "allwinner,sun6i-a31-sc-nmi" or "allwinner,sun9i-a80-nmi"
+- compatible : should be one of:
+	"allwinner,sun6i-a31-sc-nmi"
+	"allwinner,sun7i-a20-sc-nmi"
+	"allwinner,sun9i-a80-nmi"
+	"allwinner,sun50i-a64-r-intc"
 - reg : Specifies base physical address and size of the registers.
 - interrupt-controller : Identifies the node as an interrupt controller
 - #interrupt-cells : Specifies the number of cells needed to encode an
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 01/10] arm64: allwinner: a64: enable RSB on A64
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170426152023.41567-1-icenowy-h8G6r0blFSE@public.gmane.org>

Allwinner A64 have a RSB controller like the one on A23/A33 SoCs.

Add it and its pinmux.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
Acked-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Changes in v2:
- Removed bonus properties in pio node.
- Added Chen-Yu's ACK.

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index c7f669f5884f..05ec9fc5e81f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -422,6 +422,25 @@
 			#gpio-cells = <3>;
 			interrupt-controller;
 			#interrupt-cells = <3>;
+
+			r_rsb_pins: rsb@0 {
+				pins = "PL0", "PL1";
+				function = "s_rsb";
+			};
+		};
+
+		r_rsb: rsb@1f03400 {
+			compatible = "allwinner,sun8i-a23-rsb";
+			reg = <0x01f03400 0x400>;
+			interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu 6>;
+			clock-frequency = <3000000>;
+			resets = <&r_ccu 2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&r_rsb_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 	};
 };
-- 
2.12.2

^ permalink raw reply related

* [PATCH v5 00/10] AXP803 PMIC support for Pine64
From: Icenowy Zheng @ 2017-04-26 15:20 UTC (permalink / raw)
  To: Thomas Gleixner, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Lee Jones, Liam Girdwood
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

The Pine64 (including Pine64+) boards have an AXP803 PMIC, which is a PMIC
similar to AXP288, but tweaked to use with Allwinner SoCs rather than Intel
tablets (with DCIN and Vbus re-splitted like other AXP PMICs, and RSB bus
support added).

This patchset adds support for it and enabled it in Pine64 device tree.

The basical part of AXP803 MFD driver is already applied, according to Lee.

Thus this patchset is now still two parts, but a bit different to older
revisions:

- Part1: from PATCH 1/10 to PATCH 5/10, which focus on enabling AXP803 in
  the device tree: the RSB bus, the R_INTC interrupt controller (for the
  NMI line, which is connected to AXP803 on Pine64), and finally the basical
  AXP803 node.
- Part2: from PATCH 5/10 to PATCH 10/10, which are enabling the regulator
  function of the AXP803 PMIC. Finally Wi-Fi function is added
  as a usage of regulators function.

PATCH 1 adds RSB device nodes, which is used for the communication between
A64 and AXP803.

PATCH 2 adds device tree binding of A64 R_INTC.

PATCH 3 really adds support for A64 R_INTC in NMI driver.

PATCH 4 adds R_INTC node in A64 device tree.

PATCH 5 adds AXP803 node to the Pine64 device tree by using already
applied drivers/bindings.

PATCH 6 adds support for AXP803 regulators in AXP20x regulatoe driver.
(The binding is already applied)

PATCH 7 enables the AXP803 regulator cell in MFD driver.

PATCH 8 adds a DTSI file for AXP803, like other older AXP PMICs.

PATCH 9 enables AXP803 regulators in Pine64 device tree.

PATCH 10 enables Wi-Fi for Pine64.

Icenowy Zheng (10):
  arm64: allwinner: a64: enable RSB on A64
  irqchip/sunxi-nmi: add A64 R_INTC to the binding doc
  irqchip/sunxi-nmi: add support for the NMI in A64 R_INTC
  arm64: allwinner: a64: add NMI (R_INTC) controller on A64
  arm64: allwinner: a64: add AXP803 node to Pine64 device tree
  regulator: axp20x-regulator: add support for AXP803
  mfd: axp20x: add axp20x-regulator cell for AXP803
  arm64: allwinner: a64: add DTSI file for AXP803 PMIC
  arm64: allwinner: a64: enable AXP803 regulators for Pine64
  arm64: allwinner: a64: enable Wi-Fi for Pine64

 .../interrupt-controller/allwinner,sunxi-nmi.txt   |   7 +-
 arch/arm64/boot/dts/allwinner/axp803.dtsi          | 150 ++++++++++++++++++++
 .../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 136 ++++++++++++++++++
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi      |  27 ++++
 drivers/irqchip/irq-sunxi-nmi.c                    |  13 ++
 drivers/mfd/axp20x.c                               |   3 +-
 drivers/regulator/axp20x-regulator.c               | 153 ++++++++++++++++++---
 include/linux/mfd/axp20x.h                         |  37 +++++
 8 files changed, 501 insertions(+), 25 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/axp803.dtsi

-- 
2.12.2

^ permalink raw reply

* Re: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver
From: Andy Shevchenko @ 2017-04-26 15:04 UTC (permalink / raw)
  To: Eugeniy Paltsev
  Cc: devicetree@vger.kernel.org, vinod.koul@intel.com,
	Alexey.Brodkin@synopsys.com, linux-kernel@vger.kernel.org,
	robh+dt@kernel.org, dmaengine@vger.kernel.org,
	dan.j.williams@intel.com, linux-snps-arc@lists.infradead.org
In-Reply-To: <1493143941.24567.196.camel@linux.intel.com>

On Tue, 2017-04-25 at 21:12 +0300, Andy Shevchenko wrote:
> On Tue, 2017-04-25 at 15:16 +0000, Eugeniy Paltsev wrote:
> > On Mon, 2017-04-24 at 19:56 +0300, Andy Shevchenko wrote:
> > > On Mon, 2017-04-24 at 15:55 +0000, Eugeniy Paltsev wrote:

> > > Descriptor is active until terminate_all() is called or new
> > > descriptor
> > > is supplied. So, the caller has a quite time to check on it.
> > > 
> > > So, what's wrong on it by your opinion?
> > 
> > Hmm, this looks OK. (In my example (hsu/hsu.c driver) error
> > descriptors
> > are not freed even after terminate_all is called)
> 
> If it's active it will be freed.
> Otherwise caller should check somewhere that descriptor fails.
> 
> But actually this is fragile and we need to monitor failed
> descriptors.
> Thanks for reporting.
> 
> > 
> > > Of course, if you want to keep by some reason (should be stated
> > > what
> > > the reason in comment) erred descriptors, you can do that.
> > 
> > So, I'll create desc_error list and store failed descriptors in this
> > list until terminate_all() is called.
> > Is it OK implementation?
> 
> Nope, we need to amend virt-chan API for that. I'm on it. Will send a
> series soon.

I have to correct what I wrote before.

We have two options:
a) one I proposed above;
b) move descriptor to complete list and call complete callback with
result.

So, it looks like the b) variant is what is done already in 4 (did I
calculate correctly?) drivers and respective users.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply

* Re: [PATCH v3 08/12] regulator: axp20x-regulator: add support for AXP803
From: Mark Brown @ 2017-04-26 14:45 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Lee Jones, Rob Herring, Chen-Yu Tsai, Maxime Ripard,
	Liam Girdwood, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170417115747.7300-9-icenowy-h8G6r0blFSE@public.gmane.org>

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

On Mon, Apr 17, 2017 at 07:57:43PM +0800, Icenowy Zheng wrote:
> AXP803 PMIC also have a series of regulators (DCDCs and LDOs)
> controllable via I2C/RSB bus.
> 
> Add support for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>

Acked-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/4] gpio - Add EXAR XRA1403 SPI GPIO expander driver
From: Linus Walleij @ 2017-04-26 14:42 UTC (permalink / raw)
  To: Benjamin Henrion
  Cc: Nandor Han, Greg KH, David S. Miller, Geert Uytterhoeven,
	Mauro Carvalho Chehab, Daniel Vetter, Alexandre Courbot,
	Rob Herring, Mark Rutland, linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Semi Malinen
In-Reply-To: <CANjd3ndZkVi5OA0eqDewrpqVLQpT11QbVOA98F=ghMhcwPu2hQ@mail.gmail.com>

On Tue, Apr 25, 2017 at 9:07 AM, Benjamin Henrion <zoobab@gmail.com> wrote:

> I doubt you will be able to convince the majority of people toggling
> GPIOs via a simple shell script to switch to write a complex C
> program. Not to mention cross compilation and the libraries
> dependencies here.

I do not need to convince anyone, I'm not into politics.

The way to attract users to the character device is by offering better
features... so we smack in the following goodies:

- Need a userspace ABI? No more need to select CONFIG_GPIO_SYSFS!
  The chardev is always there for any gpio chip in newer kernels!
  Board vendors would have to actively delete core code to disable it!

- Need open drain? The chardev will support that, the sysfs will never.

- Need to set/get multiple lines with a single context switch? Chardev
  does this. Also the set operation will turn into a single register write
  if your driver implements .set_multiple()

- All future needs: line biasing? Schmitt triggers? Drive strengths?
  All that will use the character device, and the sysfs ABI will never
  support any of it.

> Is there some good cli tools to access the new char device? If they
> are shipped with most distros, that would reduce the pain.

I have those that come with the kernel:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/gpio

Then libgpiod as mentioned:
https://github.com/brgl/libgpiod/tree/master/src/tools

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH] NFC: trf7970a: Correct register settings for 27MHz clock
From: walter harms @ 2017-04-26 14:34 UTC (permalink / raw)
  To: Geoff Lansberry
  Cc: linux-wireless, sameo, kernel-janitors, linux-kernel, linux-nfc,
	devicetree, mgreer, justin, colin.king
In-Reply-To: <1493214513-12245-1-git-send-email-geoff@kuvee.com>



Am 26.04.2017 15:48, schrieb Geoff Lansberry:
> In prior commits the selected clock frequency does not propagate
> correctly to what is written the the TRF7970A_MODULATOR_SYS_CLK_CTRL
> register.
> Also fixes a bug that causes the device tree property check to always
> pass.
> 
> Signed-off-by: Geoff Lansberry <geoff@kuvee.com>
> ---
>  drivers/nfc/trf7970a.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
> index 2d1c8ca..c278b0e 100644
> --- a/drivers/nfc/trf7970a.c
> +++ b/drivers/nfc/trf7970a.c
> @@ -2071,7 +2071,7 @@ static int trf7970a_probe(struct spi_device *spi)
>  	}
>  
>  	of_property_read_u32(np, "clock-frequency", &clk_freq);
> -	if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) ||
> +	if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) &&
>  		(clk_freq != TRF7970A_13MHZ_CLOCK_FREQUENCY)) {
>  		dev_err(trf->dev,
>  			"clock-frequency (%u Hz) unsupported\n",
> @@ -2079,6 +2079,13 @@ static int trf7970a_probe(struct spi_device *spi)
>  		return -EINVAL;
>  	}
>  
> +	if (clk_freq == TRF7970A_27MHZ_CLOCK_FREQUENCY) {
> +		trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_27MHZ;
> +		dev_dbg(trf->dev, "trf7970a configured for 27MHz crystal\n");
> +	} else {
> +		trf->modulator_sys_clk_ctrl = 0;
> +	}
> +


I am a fan of defensive programming and would move do:
trf->modulator_sys_clk_ctrl = 0;
if (clk_freq == TRF7970A_27MHZ_CLOCK_FREQUENCY) {
		trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_27MHZ;
		dev_dbg(trf->dev, "trf7970a configured for 27MHz crystal\n");
	}

perhaps using a switch/case here is appropriate IMHO a border case for 2 case
but would make the init code more clear.

just my 2 cents,

re,
 wh

>  	if (of_property_read_bool(np, "en2-rf-quirk"))
>  		trf->quirks |= TRF7970A_QUIRK_EN2_MUST_STAY_LOW;
>  

^ 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