Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 3/5] arm64: dts: actions: Add gpio line names to Bubblegum-96 board
From: Linus Walleij @ 2018-05-23  8:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180520051736.4842-4-manivannan.sadhasivam@linaro.org>

On Sun, May 20, 2018 at 7:17 AM, Manivannan Sadhasivam
<manivannan.sadhasivam@linaro.org> wrote:

> Add gpio line names to Actions Semi S900 based Bubblegum-96 board.
>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v2 2/5] arm64: dts: actions: Add gpio properties to pinctrl node for S900
From: Linus Walleij @ 2018-05-23  8:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180520051736.4842-3-manivannan.sadhasivam@linaro.org>

On Sun, May 20, 2018 at 7:17 AM, Manivannan Sadhasivam
<manivannan.sadhasivam@linaro.org> wrote:

> Add gpio properties to pinctrl node for Actions Semi S900 SoC.
>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v2 1/5] dt-bindings: pinctrl: Add gpio bindings for Actions S900 SoC
From: Linus Walleij @ 2018-05-23  8:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180520051736.4842-2-manivannan.sadhasivam@linaro.org>

On Sun, May 20, 2018 at 7:17 AM, Manivannan Sadhasivam
<manivannan.sadhasivam@linaro.org> wrote:

> Add gpio bindings for Actions Semi S900 SoC.
>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Patch applied with Rob's review tag.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v2] pinctrl: pinctrl-single: Add functions to save and restore pinctrl context
From: Linus Walleij @ 2018-05-23  8:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526532021-16387-1-git-send-email-j-keerthy@ti.com>

On Thu, May 17, 2018 at 6:40 AM, Keerthy <j-keerthy@ti.com> wrote:

> This adds a pair of context save/restore functions to save/restore the
> state of a set of pinctrl registers. The context is lost during rtc only
> suspend with ddr in self-refresh on am43xx. Currently the save/restore
> is being done unconditionally. This will be optimized later with a
> pdata-quirk function which will allow is to save/restore only when doing
> the rtc only mode with ddr in self refresh.
>
> Signed-off-by: Keerthy <j-keerthy@ti.com>
> ---
>
> Changes in v2:

Patch applied with Tony's ACK.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] arm64: dts: renesas: r8a77980: add SMP support
From: Simon Horman @ 2018-05-23  8:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdWepA=YbjtVN2iw7uXrWu62LRx1ymix_AUgp6NrOTUgpw@mail.gmail.com>

On Tue, May 22, 2018 at 11:49:36AM +0200, Geert Uytterhoeven wrote:
> On Tue, May 22, 2018 at 10:54 AM, Simon Horman <horms@verge.net.au> wrote:
> > On Sat, May 19, 2018 at 08:38:13PM +0300, Sergei Shtylyov wrote:
> >> On 05/17/2018 11:23 PM, Geert Uytterhoeven wrote:
> >>
> >> >> Add the device nodes for 3 more Cortex-A53 CPU cores; adjust the interrupt
> >> >> delivery masks for the ARM GIC and Architectured Timer.
> >> >>
> >> >> Based on the original (and large) patch by Vladimir Barinov.
> >> >>
> >> >> Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
> >> >> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> >> >
> >> > Thanks for your patch!
> >> >
> >> >> --- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980.dtsi
> >> >> +++ renesas/arch/arm64/boot/dts/renesas/r8a77980.dtsi
> >> >> @@ -30,6 +30,36 @@
> >> >>                         enable-method = "psci";
> >> >>                 };
> >> >>
> >> >> +               a53_1: cpu at 1 {
> >> >> +                       device_type = "cpu";
> >> >> +                       compatible = "arm,cortex-a53","arm,armv8";
> >> >
> >> > Please stop copying spaceless lists ;-)
> >>
> >>    Oops! Simon, do I need to re-post?
> >
> > No, but Geert, are you otherwise ok with this patch?
> 
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Thanks, I have applied the following:

From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Subject: [PATCH] arm64: dts: renesas: r8a77980: add SMP support

Add the device nodes for 3 more Cortex-A53 CPU cores; adjust the interrupt
delivery masks for the ARM GIC and Architectured Timer.

Based on the original (and large) patch by Vladimir Barinov.

Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
[simon: corrected whitespace]
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm64/boot/dts/renesas/r8a77980.dtsi | 40 +++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
index 4c40f9f0ebc9..6d2b61d83caf 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
@@ -30,6 +30,36 @@
 			enable-method = "psci";
 		};
 
+		a53_1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <1>;
+			clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+			power-domains = <&sysc R8A77980_PD_CA53_CPU1>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+		};
+
+		a53_2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <2>;
+			clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+			power-domains = <&sysc R8A77980_PD_CA53_CPU2>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+		};
+
+		a53_3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <3>;
+			clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+			power-domains = <&sysc R8A77980_PD_CA53_CPU3>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+		};
+
 		L2_CA53: cache-controller {
 			compatible = "cache";
 			power-domains = <&sysc R8A77980_PD_CA53_SCU>;
@@ -408,7 +438,7 @@
 			      <0x0 0xf1020000 0 0x20000>,
 			      <0x0 0xf1040000 0 0x20000>,
 			      <0x0 0xf1060000 0 0x20000>;
-			interrupts = <GIC_PPI 9	(GIC_CPU_MASK_SIMPLE(1) |
+			interrupts = <GIC_PPI 9	(GIC_CPU_MASK_SIMPLE(4) |
 				      IRQ_TYPE_LEVEL_HIGH)>;
 			clocks = <&cpg CPG_MOD 408>;
 			clock-names = "clk";
@@ -424,13 +454,13 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) |
+		interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
 				       IRQ_TYPE_LEVEL_LOW)>,
-				      <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) |
+				      <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
 				       IRQ_TYPE_LEVEL_LOW)>,
-				      <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) |
+				      <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
 				       IRQ_TYPE_LEVEL_LOW)>,
-				      <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) |
+				      <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
 				       IRQ_TYPE_LEVEL_LOW)>;
 	};
 };
-- 
2.11.0

^ permalink raw reply related

* [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
From: Mark Brown @ 2018-05-23  8:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6a59e071-3159-4939-8535-6c7a9d491379@microchip.com>

On Wed, May 23, 2018 at 11:10:28AM +0300, Radu Pirea wrote:
> On 05/17/2018 08:04 AM, Mark Brown wrote:

> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Driver for AT91 USART Controllers as SPI
> > > + *
> > > + * Copyright (C) 2018 Microchip Technology Inc.

> > Make the entire block a C++ comment so it looks more intentional rather
> > tha mixing C and C++.

> I know it's ugly, but SPDX license identifier must be in a separate comment
> block.

No, it doesn't - it just needs to be the first line of the file.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180523/77fafae7/attachment.sig>

^ permalink raw reply

* [PATCH 2/2] ARM: dts: am437x: make edt-ft5x06 a wakeup source for imx6 boards
From: Daniel Mack @ 2018-05-23  8:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180523083013.7570-1-daniel@zonque.org>

The touchscreen driver no longer configures the device as wakeup source by
default. A "wakeup-source" property is needed.

Signed-off-by: Daniel Mack <daniel@zonque.org>
---
 arch/arm/boot/dts/am437x-sk-evm.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index 4118802b7fea..f17ed89da06b 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -537,6 +537,8 @@
 
 		touchscreen-size-x = <480>;
 		touchscreen-size-y = <272>;
+
+		wakeup-source;
 	};
 
 	tlv320aic3106: tlv320aic3106 at 1b {
-- 
2.14.3

^ permalink raw reply related

* [PATCH 1/2] ARM: dts: imx6: make edt-ft5x06 a wakeup source for imx6 boards
From: Daniel Mack @ 2018-05-23  8:30 UTC (permalink / raw)
  To: linux-arm-kernel

The touchscreen driver no longer configures the device as wakeup source by
default. A "wakeup-source" property is needed.

Signed-off-by: Daniel Mack <daniel@zonque.org>
---
 arch/arm/boot/dts/imx6q-var-dt6customboard.dts | 1 +
 arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi       | 1 +
 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi   | 1 +
 arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi  | 1 +
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi      | 1 +
 5 files changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q-var-dt6customboard.dts b/arch/arm/boot/dts/imx6q-var-dt6customboard.dts
index e0728d475f6f..7537d77b3415 100644
--- a/arch/arm/boot/dts/imx6q-var-dt6customboard.dts
+++ b/arch/arm/boot/dts/imx6q-var-dt6customboard.dts
@@ -179,6 +179,7 @@
 		touchscreen-size-y = <480>;
 		touchscreen-inverted-x;
 		touchscreen-inverted-y;
+		wakeup-source;
 	};
 
 	rtc at 68 {
diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
index aab088f318e8..aef4a756ca81 100644
--- a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
@@ -292,6 +292,7 @@
 		reg = <0x38>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-source;
 	};
 
 	rtc at 6f {
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
index 87ca6ead4098..9cb464b65be1 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
@@ -442,6 +442,7 @@
 		reg = <0x38>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-source;
 	};
 };
 
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
index f5b763d39285..5e4da6d6fcff 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
@@ -360,6 +360,7 @@
 		reg = <0x38>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-source;
 	};
 };
 
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index 596866b0a0d2..a14872436c5e 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -370,6 +370,7 @@
 		reg = <0x38>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-source;
 	};
 };
 
-- 
2.14.3

^ permalink raw reply related

* [PATCH v3 1/2] regulator: dt-bindings: add QCOM RPMh regulator bindings
From: Mark Brown @ 2018-05-23  8:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD=FV=W=BquL5ojORz4HNP889s=-uNJ-QEzUfAxwXj2Oa3cGew@mail.gmail.com>

On Tue, May 22, 2018 at 05:08:45PM -0700, Doug Anderson wrote:

> So one client's vote for a voltage continues to be in effect even if
> that client votes to have the regulator disabled?  That seems
> fundamentally broken in RPMh.  I guess my take would be to work around

It's arguable either way - you could say that the client gets to specify
a safe range at all times or you could say that the machine constraints
should cover all cases where the hardware is idling.  Of course RPMh
is missing anything like the machine constraints (as we can see from all
the fixing up of undesirable hard coding we have to do) so it's kind of
pushed towards the first case.

> >> A) Turn off VMMC and VQMMC
> >> B) Program VMMC and VQMMC to defaults
> >> C) Turn on VMMC and VQMMC

> >> ...right now we bootup and pretend to Linux that VMMC and VQMMC start
> >> off, so step A) will be no-op.  Sigh.

> > Step A) would not work because the regulator's use_count would be 0 and
> > regulator_disable() can only be called successfully if use_count > 0.  The
> > call would have no impact and it would return an error.

> Are you sure regulator_force_disable() won't do the trick on most
> boards (which will report the regulator being enabled at bootup)?  I
> haven't tried it, but it seems like it might.

It does mean that things will go wrong if the regulator is shared.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180523/95a4e8ad/attachment-0001.sig>

^ permalink raw reply

* [PATCH v2 1/3] input: touchscreen: edt-ft5x06: don't make device a wakeup source by default
From: Daniel Mack @ 2018-05-23  8:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522175413.GA24850@rob-hp-laptop>

On Tuesday, May 22, 2018 07:54 PM, Rob Herring wrote:
> On Thu, May 17, 2018 at 11:05:50AM +0200, Daniel Mack wrote:
>> Allow configuring the device as wakeup source through device properties, as
>> not all platforms want to wake up on touch screen activity.
>>
>> The I2C core automatically reads the "wakeup-source" DT property to
>> configure a device's wakeup capability, and board supports files can set
>> I2C_CLIENT_WAKE in the flags.
> 
> This will break wake-up on working systems. Looks like mostly i.MX, but
> there's one AM437x board. If that board doesn't care, then it is up to
> Shawn.

I added the property to the dts files, but as Dmitry pointed out, I 
missed some. Sorry for that.


Thanks,
Daniel

^ permalink raw reply

* [PATCH v2 3/3] ARM: dts: imx28/imx53: enable edt-ft5x06 wakeup source
From: Daniel Mack @ 2018-05-23  8:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522182043.GA123708@dtor-ws>

On Tuesday, May 22, 2018 08:20 PM, Dmitry Torokhov wrote:
> On Sun, May 20, 2018 at 09:05:30PM +0800, Shawn Guo wrote:
>> On Thu, May 17, 2018 at 11:05:52AM +0200, Daniel Mack wrote:
>>> The touchscreen driver no longer configures the device as wakeup source by
>>> default. A "wakeup-source" property is needed.
>>>
>>> To avoid regressions, this patch changes the DTS files for the only two
>>> users of this driver that didn't have this property yet.
>>>
>>> Signed-off-by: Daniel Mack <daniel@zonque.org>
>>> Cc: Shawn Guo <shawnguo@kernel.org>
>>> Cc: Sascha Hauer <kernel@pengutronix.de>
>>> Cc: Fabio Estevam <fabio.estevam@nxp.com>
>>> Cc: Rob Herring <robh+dt@kernel.org>
>>
>> Applied this one, thanks.
> 
> I think there are few more that need "wakeup-source" added:
> 
> arch/arm/boot/dts/am437x-sk-evm.dts
> arch/arm/boot/dts/imx6q-var-dt6customboard.dts
> arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
> arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
> arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi

Oh, sorry for having missed them. Will send patches.


Thanks,
Daniel

^ permalink raw reply

* [PATCH v3] arm64: allwinner: a64: Add Amarula A64-Relic initial support
From: Maxime Ripard @ 2018-05-23  8:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMty3ZD3JT-ToGAUHN_uj7uVK-jkyAwfEdTBCmJSj34bACFpYQ@mail.gmail.com>

On Wed, May 23, 2018 at 11:44:56AM +0530, Jagan Teki wrote:
> On Tue, May 22, 2018 at 8:00 PM, Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> > On Tue, May 22, 2018 at 06:52:28PM +0530, Jagan Teki wrote:
> >> Amarula A64-Relic is Allwinner A64 based IoT device, which support
> >> - Allwinner A64 Cortex-A53
> >> - Mali-400MP2 GPU
> >> - AXP803 PMIC
> >> - 1GB DDR3 RAM
> >> - 8GB eMMC
> >> - AP6330 Wifi/BLE
> >> - MIPI-DSI
> >> - CSI: OV5640 sensor
> >> - USB OTG
> >
> > You claim that this is doing OTG...
> >
> > [..]
> >
> >> +&usb_otg {
> >> +     dr_mode = "peripheral";
> >> +     status = "okay";
> >> +};
> >
> > ... and yet you're setting it as peripheral...
> 
> Though it claims OTG, board doesn't have any USB ports to operate(not
> even Mini-AB) the only way to use the board as peripheral to transfer
> images from host.

I'm not sure what you mean here. If there's no USB connector, why do
you even enable it?

maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180523/aa60090a/attachment.sig>

^ permalink raw reply

* [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
From: Radu Pirea @ 2018-05-23  8:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180517050406.GF20254@sirena.org.uk>



On 05/17/2018 08:04 AM, Mark Brown wrote:
> On Fri, May 11, 2018 at 01:38:21PM +0300, Radu Pirea wrote:
> 
>> +config SPI_AT91_USART
>> +        tristate "Atmel USART Controller as SPI"
>> +	depends on HAS_DMA
>> +	depends on (ARCH_AT91 || COMPILE_TEST)
>> +        select MFD_AT91_USART
>> +	help
>> +	  This selects a driver for the AT91 USART Controller as SPI Master,
>> +	  present on AT91 and SAMA5 SoC series.
>> +
> 
> This looks like there's some tab/space mixing going on here.
> 
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Driver for AT91 USART Controllers as SPI
>> + *
>> + * Copyright (C) 2018 Microchip Technology Inc.
> 
> Make the entire block a C++ comment so it looks more intentional rather
> tha mixing C and C++.

Hi Mark,

I know it's ugly, but SPDX license identifier must be in a separate 
comment block.

> 
>> +static inline void at91_usart_spi_tx(struct at91_usart_spi *aus)
>> +{
>> +	unsigned int len = aus->current_transfer->len;
>> +	unsigned int remaining = aus->current_tx_remaining_bytes;
>> +	const u8  *tx_buf = aus->current_transfer->tx_buf;
>> +
>> +	if (tx_buf && remaining) {
>> +		if (at91_usart_spi_tx_ready(aus))
>> +			spi_writel(aus, THR, tx_buf[len - remaining]);
>> +			aus->current_tx_remaining_bytes--;
> 
> Missing braces here - we only write to the FIFO if there's space but we
> unconditionally decrement the counter.
> 

Thanks. I will fix it.

>> +	} else {
>> +		if (at91_usart_spi_tx_ready(aus))
>> +			spi_writel(aus, THR, US_DUMMY_TX);
>> +	}
>> +}
> 
> This looks like you're open coding SPI_CONTROLLER_MUST_TX
> 
>> +	int len = aus->current_transfer->len;
>> +	int remaining = aus->current_rx_remaining_bytes;
>> +	u8  *rx_buf = aus->current_transfer->rx_buf;
>> +
>> +	if (aus->current_rx_remaining_bytes) {
>> +		rx_buf[len - remaining] = spi_readb(aus, RHR);
>> +		aus->current_rx_remaining_bytes--;
>> +	} else {
>> +		spi_readb(aus, RHR);
>> +	}
> 
> Similarly for _MUST_RX.
> 
>> +	controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
> 
> You're actually setting both flags...  this means that the handling for
> cases with missing TX or RX buffers can't happen.

Sorry. My mistake. I will remove unnecessary code.

^ permalink raw reply

* [PATCH] ARM: dts: vexpress: Replace '_' with '-' in node names
From: Linus Walleij @ 2018-05-23  8:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_Jsq+VNuvbxgFTFVouJF-_yMS90u0fd8jaXnYtKwogOP5rww@mail.gmail.com>

On Wed, May 9, 2018 at 11:14 PM, Rob Herring <robh+dt@kernel.org> wrote:
> On Wed, May 9, 2018 at 11:48 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> The latest DTC throws warnings for character '_' in the node names.
>>
>> Warning (node_name_chars_strict): /sysreg at 10000/sys_led: Character '_' not recommended in node name
>> Warning (node_name_chars_strict): /sysreg at 10000/sys_mci: Character '_' not recommended in node name
>> Warning (node_name_chars_strict): /sysreg at 10000/sys_flash: Character '_' not recommended in node name
>>
>> The general recommendation is to use character '-' for all the node names.
>> This patch fixes the warnings following the recommendation.
>>
>> Cc: Liviu Dudau <liviu.dudau@arm.com>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 6 +++---
>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
>> index 7b8ff5b3b912..58e73131ecef 100644
>> --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
>> +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
>> @@ -77,19 +77,19 @@
>>                                         compatible = "arm,vexpress-sysreg";
>>                                         reg = <0x010000 0x1000>;
>>
>> -                                       v2m_led_gpios: sys_led {
>> +                                       v2m_led_gpios: sys-led {
>
> Except this is a gpio-controller so it should have 'gpio' for its node
> name. (I have a dtc check written for that, but there are too many
> false positives.)
>
> But then you have 3 of them and no addressing, so you need to add reg
> property (with the register's offset and size) and unit-address.
>
> I'm surprised Linus W accepted these a GPIO when they are not really
> general purpose, but then lots of things slip in.

I guess is was back in this day when we had a finger constantly
on the fastforward button for DT conversion, and a few not so
elegant things slipped in.

I was annoyed by this thing later, especially since others started
to use it as a consistency argument "well you allowed this so
now allow this other crazy thing that looks the same" :D

I suspect I either was not CC:ed or I just sucked at shepherding
this, I try to do better these days.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH 3/3] arm64: dts: juno/rtsm: re-structure motherboard includes
From: Linus Walleij @ 2018-05-23  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525884291-18851-3-git-send-email-sudeep.holla@arm.com>

On Wed, May 9, 2018 at 6:44 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> It is a bit unorthodox to just include a file in the middle of a another
> DTS file, it breaks the pattern from other device trees and also makes
> it really hard to reference things across the files with phandles.
>
> Restructure the include for the Juno/RTSM motherboards to happen at the
> top of the file, reference the target nodes directly, and indent the
> motherboard .dtsi files to reflect their actual depth in the hierarchy.
>
> This is a purely syntactic change that result in the same DTB files from
> the DTS/DTSI files. This is based on similar patch from Linus Walleij
> for ARM Vexpress platforms.
>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Thanks for doing this, it is much more readable for me now.

Sorry for slow review :/

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH V2 3/3] ARM: dts: imx7: correct enet ipg clock
From: Stefan Agner @ 2018-05-23  7:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1526605266-18464-3-git-send-email-Anson.Huang@nxp.com>

On 18.05.2018 03:01, Anson Huang wrote:
> ENET "ipg" clock should be IMX7D_ENETx_IPG_ROOT_CLK
> rather than IMX7D_ENET_AXI_ROOT_CLK which is for ENET bus
> clock.
> 
> Based on Andy Duan's patch from the NXP kernel tree.
> 
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>

Reviewed-by: Stefan Agner <stefan@agner.ch>

--
Stefan

> ---
>  arch/arm/boot/dts/imx7d.dtsi | 2 +-
>  arch/arm/boot/dts/imx7s.dtsi | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
> index 200714e..d74dd7f 100644
> --- a/arch/arm/boot/dts/imx7d.dtsi
> +++ b/arch/arm/boot/dts/imx7d.dtsi
> @@ -120,7 +120,7 @@
>  			<GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
>  			<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
>  			<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
> +		clocks = <&clks IMX7D_ENET2_IPG_ROOT_CLK>,
>  			<&clks IMX7D_ENET_AXI_ROOT_CLK>,
>  			<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
>  			<&clks IMX7D_PLL_ENET_MAIN_125M_CLK>,
> diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
> index 4d42335..b90769d 100644
> --- a/arch/arm/boot/dts/imx7s.dtsi
> +++ b/arch/arm/boot/dts/imx7s.dtsi
> @@ -1091,7 +1091,7 @@
>  					<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
>  					<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
>  					<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
> -				clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
> +				clocks = <&clks IMX7D_ENET1_IPG_ROOT_CLK>,
>  					<&clks IMX7D_ENET_AXI_ROOT_CLK>,
>  					<&clks IMX7D_ENET1_TIME_ROOT_CLK>,
>  					<&clks IMX7D_PLL_ENET_MAIN_125M_CLK>,

^ permalink raw reply

* [PATCH 3/5] watchdog: sp805: set WDOG_HW_RUNNING when appropriate
From: Scott Branden @ 2018-05-23  7:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0d92b9e9-a3d1-6e91-8371-b5ed3a83e399@broadcom.com>



On 18-05-22 04:24 PM, Ray Jui wrote:
> Hi Guenter,
>
> On 5/22/2018 1:54 PM, Guenter Roeck wrote:
>> On Tue, May 22, 2018 at 11:47:18AM -0700, Ray Jui wrote:
>>> If the watchdog hardware is already enabled during the boot process,
>>> when the Linux watchdog driver loads, it should reset the watchdog and
>>> tell the watchdog framework. As a result, ping can be generated from
>>> the watchdog framework, until the userspace watchdog daemon takes over
>>> control
>>>
>>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>>> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
>>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
>>> ---
>>> ? drivers/watchdog/sp805_wdt.c | 22 ++++++++++++++++++++++
>>> ? 1 file changed, 22 insertions(+)
>>>
>>> diff --git a/drivers/watchdog/sp805_wdt.c 
>>> b/drivers/watchdog/sp805_wdt.c
>>> index 1484609..408ffbe 100644
>>> --- a/drivers/watchdog/sp805_wdt.c
>>> +++ b/drivers/watchdog/sp805_wdt.c
>>> @@ -42,6 +42,7 @@
>>> ????? /* control register masks */
>>> ????? #define??? INT_ENABLE??? (1 << 0)
>>> ????? #define??? RESET_ENABLE??? (1 << 1)
>>> +??? #define??? ENABLE_MASK??? (INT_ENABLE | RESET_ENABLE)
>>> ? #define WDTINTCLR??????? 0x00C
>>> ? #define WDTRIS??????????? 0x010
>>> ? #define WDTMIS??????????? 0x014
>>> @@ -74,6 +75,18 @@ module_param(nowayout, bool, 0);
>>> ? MODULE_PARM_DESC(nowayout,
>>> ????????? "Set to 1 to keep watchdog running after device release");
>>> ? +/* returns true if wdt is running; otherwise returns false */
>>> +static bool wdt_is_running(struct watchdog_device *wdd)
>>> +{
>>> +??? struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>>> +
>>> +??? if ((readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK) ==
>>> +??????? ENABLE_MASK)
>>> +??????? return true;
>>> +??? else
>>> +??????? return false;
>>
>> ????return !!(readl_relaxed(wdt->base + WDTCONTROL) & ENABLE_MASK));
>>
>
> Note ENABLE_MASK contains two bits (INT_ENABLE and RESET_ENABLE); 
> therefore, a simple !!(expression) would not work? That is, the masked 
> result needs to be compared against the mask again to ensure both bits 
> are set, right?
Ray - your original code looks correct to me.? Easier to read and less 
prone to errors as shown in the attempted translation to a single statement.
>
> Thanks,
>
> Ray

^ permalink raw reply

* [PATCH v7 5/5] drm/rockchip: support dp training outside dp firmware
From: Lin Huang @ 2018-05-23  7:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527061353-16902-1-git-send-email-hl@rock-chips.com>

DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So get phy config values from dts and use software link training
instead of relying on firmware, if software training fail, keep firmware
training as a fallback if sw training fails.

Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training
Changes in v4:
- improve cdn_dp_get_lower_link_rate() and cdn_dp_software_train_link() follow Sean suggest
Changes in v5:
- fix some whitespcae issue
Changes in v6:
- None
Changes in v7:
- None

 drivers/gpu/drm/rockchip/Makefile               |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c          |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h          |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 420 ++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.c           |  31 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h           |  38 ++-
 6 files changed, 505 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+					cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..783d57a 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
 			goto out;
 		}
 	}
-
-	ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-	if (ret) {
-		DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-		goto out;
+	if (dp->use_fw_training) {
+		ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+		if (ret) {
+			DRM_DEV_ERROR(dp->dev,
+				      "Failed to idle video %d\n", ret);
+			goto out;
+		}
 	}
 
 	ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
 		goto out;
 	}
 
-	ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-	if (ret) {
-		DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-		goto out;
+	if (dp->use_fw_training) {
+		ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+		if (ret) {
+			DRM_DEV_ERROR(dp->dev,
+				"Failed to valid video %d\n", ret);
+			goto out;
+		}
 	}
+
 out:
 	mutex_unlock(&dp->lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
 	bool connected;
 	bool active;
 	bool suspended;
+	bool use_fw_training;
 
 	const struct firmware *fw;	/* cdn dp firmware */
 	unsigned int fw_version;	/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
 	u8 ports;
 	u8 lanes;
 	int active_port;
+	u8 train_set[4];
 
 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
 	bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 0000000..73c3290
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/phy/phy.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+	struct cdn_dp_port *port = dp->port[dp->active_port];
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy);
+
+	int rate = drm_dp_bw_code_to_link_rate(dp->link.rate);
+	u8 swing = (dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) >>
+		   DP_TRAIN_VOLTAGE_SWING_SHIFT;
+	u8 pre_emphasis = (dp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
+			  >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
+
+	tcphy->typec_phy_config(port->phy, rate, dp->link.num_lanes,
+				swing, pre_emphasis);
+}
+
+static int cdn_dp_set_pattern(struct cdn_dp_device *dp, uint8_t dp_train_pat)
+{
+	u32 phy_config, global_config;
+	int ret;
+	uint8_t pattern = dp_train_pat & DP_TRAINING_PATTERN_MASK;
+
+	global_config = NUM_LANES(dp->link.num_lanes - 1) | SST_MODE |
+			GLOBAL_EN | RG_EN | ENC_RST_DIS | WR_VHSYNC_FALL;
+
+	phy_config = DP_TX_PHY_ENCODER_BYPASS(0) |
+		     DP_TX_PHY_SKEW_BYPASS(0) |
+		     DP_TX_PHY_DISPARITY_RST(0) |
+		     DP_TX_PHY_LANE0_SKEW(0) |
+		     DP_TX_PHY_LANE1_SKEW(1) |
+		     DP_TX_PHY_LANE2_SKEW(2) |
+		     DP_TX_PHY_LANE3_SKEW(3) |
+		     DP_TX_PHY_10BIT_ENABLE(0);
+
+	if (pattern != DP_TRAINING_PATTERN_DISABLE) {
+		global_config |= NO_VIDEO;
+		phy_config |= DP_TX_PHY_TRAINING_ENABLE(1) |
+			      DP_TX_PHY_SCRAMBLER_BYPASS(1) |
+			      DP_TX_PHY_TRAINING_PATTERN(pattern);
+	}
+
+	ret = cdn_dp_reg_write(dp, DP_FRAMER_GLOBAL_CONFIG, global_config);
+	if (ret) {
+		DRM_ERROR("fail to set DP_FRAMER_GLOBAL_CONFIG, error: %d\n",
+			  ret);
+		return ret;
+	}
+
+	ret = cdn_dp_reg_write(dp, DP_TX_PHY_CONFIG_REG, phy_config);
+	if (ret) {
+		DRM_ERROR("fail to set DP_TX_PHY_CONFIG_REG, error: %d\n",
+			  ret);
+		return ret;
+	}
+
+	ret = cdn_dp_reg_write(dp, DPTX_LANE_EN, BIT(dp->link.num_lanes) - 1);
+	if (ret) {
+		DRM_ERROR("fail to set DPTX_LANE_EN, error: %d\n", ret);
+		return ret;
+	}
+
+	if (drm_dp_enhanced_frame_cap(dp->dpcd))
+		ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 1);
+	else
+		ret = cdn_dp_reg_write(dp, DPTX_ENHNCD, 0);
+	if (ret)
+		DRM_ERROR("failed to set DPTX_ENHNCD, error: %x\n", ret);
+
+	return ret;
+}
+
+static u8 cdn_dp_pre_emphasis_max(u8 voltage_swing)
+{
+	switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
+		return DP_TRAIN_PRE_EMPH_LEVEL_3;
+	case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
+		return DP_TRAIN_PRE_EMPH_LEVEL_2;
+	case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
+		return DP_TRAIN_PRE_EMPH_LEVEL_1;
+	default:
+		return DP_TRAIN_PRE_EMPH_LEVEL_0;
+	}
+}
+
+static void cdn_dp_get_adjust_train(struct cdn_dp_device *dp,
+				    uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+	int i;
+	uint8_t v = 0, p = 0;
+	uint8_t preemph_max;
+
+	for (i = 0; i < dp->link.num_lanes; i++) {
+		v = max(v, drm_dp_get_adjust_request_voltage(link_status, i));
+		p = max(p, drm_dp_get_adjust_request_pre_emphasis(link_status,
+								  i));
+	}
+
+	if (v >= VOLTAGE_LEVEL_2)
+		v = VOLTAGE_LEVEL_2 | DP_TRAIN_MAX_SWING_REACHED;
+
+	preemph_max = cdn_dp_pre_emphasis_max(v);
+	if (p >= preemph_max)
+		p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+	for (i = 0; i < dp->link.num_lanes; i++)
+		dp->train_set[i] = v | p;
+}
+
+/*
+ * Pick training pattern for channel equalization. Training Pattern 3 for HBR2
+ * or 1.2 devices that support it, Training Pattern 2 otherwise.
+ */
+static u32 cdn_dp_select_chaneq_pattern(struct cdn_dp_device *dp)
+{
+	u32 training_pattern = DP_TRAINING_PATTERN_2;
+
+	/*
+	 * cdn dp support HBR2 also support TPS3. TPS3 support is also mandatory
+	 * for downstream devices that support HBR2. However, not all sinks
+	 * follow the spec.
+	 */
+	if (drm_dp_tps3_supported(dp->dpcd))
+		training_pattern = DP_TRAINING_PATTERN_3;
+	else
+		DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n");
+
+	return training_pattern;
+}
+
+
+static bool cdn_dp_link_max_vswing_reached(struct cdn_dp_device *dp)
+{
+	int lane;
+
+	for (lane = 0; lane < dp->link.num_lanes; lane++)
+		if ((dp->train_set[lane] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+			return false;
+
+	return true;
+}
+
+static int cdn_dp_update_link_train(struct cdn_dp_device *dp)
+{
+	int ret;
+
+	cdn_dp_set_signal_levels(dp);
+
+	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
+				dp->train_set, dp->link.num_lanes);
+	if (ret != dp->link.num_lanes)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int cdn_dp_set_link_train(struct cdn_dp_device *dp,
+				  uint8_t dp_train_pat)
+{
+	uint8_t buf[sizeof(dp->train_set) + 1];
+	int ret, len;
+
+	buf[0] = dp_train_pat;
+	if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) ==
+	    DP_TRAINING_PATTERN_DISABLE) {
+		/* don't write DP_TRAINING_LANEx_SET on disable */
+		len = 1;
+	} else {
+		/* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
+		memcpy(buf + 1, dp->train_set, dp->link.num_lanes);
+		len = dp->link.num_lanes + 1;
+	}
+
+	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_PATTERN_SET,
+				buf, len);
+	if (ret != len)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int cdn_dp_reset_link_train(struct cdn_dp_device *dp,
+				    uint8_t dp_train_pat)
+{
+	int ret;
+
+	memset(dp->train_set, 0, sizeof(dp->train_set));
+
+	cdn_dp_set_signal_levels(dp);
+
+	ret = cdn_dp_set_pattern(dp, dp_train_pat);
+	if (ret)
+		return ret;
+
+	return cdn_dp_set_link_train(dp, dp_train_pat);
+}
+
+/* Enable corresponding port and start training pattern 1 */
+static int cdn_dp_link_training_clock_recovery(struct cdn_dp_device *dp)
+{
+	u8 voltage;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+	u32 voltage_tries, max_vswing_tries;
+	int ret;
+
+	/* clock recovery */
+	ret = cdn_dp_reset_link_train(dp, DP_TRAINING_PATTERN_1 |
+					  DP_LINK_SCRAMBLING_DISABLE);
+	if (ret) {
+		DRM_ERROR("failed to start link train\n");
+		return ret;
+	}
+
+	voltage_tries = 1;
+	max_vswing_tries = 0;
+	for (;;) {
+		drm_dp_link_train_clock_recovery_delay(dp->dpcd);
+		if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
+		    DP_LINK_STATUS_SIZE) {
+			DRM_ERROR("failed to get link status\n");
+			return -EINVAL;
+		}
+
+		if (drm_dp_clock_recovery_ok(link_status, dp->link.num_lanes)) {
+			DRM_DEBUG_KMS("clock recovery OK\n");
+			return 0;
+		}
+
+		if (voltage_tries >= 5) {
+			DRM_DEBUG_KMS("Same voltage tried 5 times\n");
+			return -EINVAL;
+		}
+
+		if (max_vswing_tries >= 1) {
+			DRM_DEBUG_KMS("Max Voltage Swing reached\n");
+			return -EINVAL;
+		}
+
+		voltage = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+		/* Update training set as requested by target */
+		cdn_dp_get_adjust_train(dp, link_status);
+		if (cdn_dp_update_link_train(dp)) {
+			DRM_ERROR("failed to update link training\n");
+			return -EINVAL;
+		}
+
+		if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) ==
+		    voltage)
+			++voltage_tries;
+		else
+			voltage_tries = 1;
+
+		if (cdn_dp_link_max_vswing_reached(dp))
+			++max_vswing_tries;
+	}
+}
+
+static int cdn_dp_link_training_channel_equalization(struct cdn_dp_device *dp)
+{
+	int tries, ret;
+	u32 training_pattern;
+	uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+	training_pattern = cdn_dp_select_chaneq_pattern(dp);
+	training_pattern |= DP_LINK_SCRAMBLING_DISABLE;
+
+	ret = cdn_dp_set_pattern(dp, training_pattern);
+	if (ret)
+		return ret;
+
+	ret = cdn_dp_set_link_train(dp, training_pattern);
+	if (ret) {
+		DRM_ERROR("failed to start channel equalization\n");
+		return ret;
+	}
+
+	for (tries = 0; tries < 5; tries++) {
+		drm_dp_link_train_channel_eq_delay(dp->dpcd);
+		if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
+		    DP_LINK_STATUS_SIZE) {
+			DRM_ERROR("failed to get link status\n");
+			break;
+		}
+
+		/* Make sure clock is still ok */
+		if (!drm_dp_clock_recovery_ok(link_status,
+					      dp->link.num_lanes)) {
+			DRM_DEBUG_KMS("Clock recovery check failed\n");
+			break;
+		}
+
+		if (drm_dp_channel_eq_ok(link_status,  dp->link.num_lanes)) {
+			DRM_DEBUG_KMS("Channel EQ done\n");
+			return 0;
+		}
+
+		/* Update training set as requested by target */
+		cdn_dp_get_adjust_train(dp, link_status);
+		if (cdn_dp_update_link_train(dp)) {
+			DRM_ERROR("failed to update link training\n");
+			break;
+		}
+	}
+
+	/* Try 5 times, else fail and try at lower BW */
+	if (tries == 5)
+		DRM_DEBUG_KMS("Channel equalization failed 5 times\n");
+
+	return -EINVAL;
+}
+
+static int cdn_dp_stop_link_train(struct cdn_dp_device *dp)
+{
+	int ret = cdn_dp_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
+
+	if (ret)
+		return ret;
+
+	return cdn_dp_set_link_train(dp, DP_TRAINING_PATTERN_DISABLE);
+}
+
+static int cdn_dp_get_lower_link_rate(struct cdn_dp_device *dp)
+{
+	switch (dp->link.rate) {
+	case DP_LINK_BW_1_62:
+		return -EINVAL;
+	case DP_LINK_BW_2_7:
+		dp->link.rate = DP_LINK_BW_1_62;
+		break;
+	case DP_LINK_BW_5_4:
+		dp->link.rate = DP_LINK_BW_2_7;
+		break;
+	default:
+		dp->link.rate = DP_LINK_BW_5_4;
+		break;
+	}
+
+	return 0;
+}
+
+int cdn_dp_software_train_link(struct cdn_dp_device *dp)
+{
+	int ret, stop_err;
+	u8 link_config[2];
+	u32 rate, sink_max, source_max;
+
+	ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd,
+			       sizeof(dp->dpcd));
+	if (ret < 0) {
+		DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
+		return ret;
+	}
+
+	source_max = dp->lanes;
+	sink_max = drm_dp_max_lane_count(dp->dpcd);
+	dp->link.num_lanes = min(source_max, sink_max);
+
+	source_max = drm_dp_bw_code_to_link_rate(CDN_DP_MAX_LINK_RATE);
+	sink_max = drm_dp_max_link_rate(dp->dpcd);
+	rate = min(source_max, sink_max);
+	dp->link.rate = drm_dp_link_rate_to_bw_code(rate);
+
+	link_config[0] = 0;
+	link_config[1] = 0;
+	if (dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & 0x01)
+		link_config[1] = DP_SET_ANSI_8B10B;
+	drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
+
+	while (true) {
+
+		/* Write the link configuration data */
+		link_config[0] = dp->link.rate;
+		link_config[1] = dp->link.num_lanes;
+		if (drm_dp_enhanced_frame_cap(dp->dpcd))
+			link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+		drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, link_config, 2);
+
+		ret = cdn_dp_link_training_clock_recovery(dp);
+		if (ret) {
+			if (!cdn_dp_get_lower_link_rate(dp))
+				continue;
+
+			DRM_ERROR("training clock recovery failed: %d\n", ret);
+			break;
+		}
+
+		ret = cdn_dp_link_training_channel_equalization(dp);
+		if (ret) {
+			if (!cdn_dp_get_lower_link_rate(dp))
+				continue;
+
+			DRM_ERROR("training channel eq failed: %d\n", ret);
+			break;
+		}
+
+		break;
+	}
+
+	stop_err = cdn_dp_stop_link_train(dp);
+	if (stop_err) {
+		DRM_ERROR("stop training fail, error: %d\n", stop_err);
+		return stop_err;
+	}
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 979355d..e1273e6 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -17,7 +17,9 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/phy/phy.h>
 #include <linux/reset.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
 
 #include "cdn-dp-core.h"
 #include "cdn-dp-reg.h"
@@ -189,7 +191,7 @@ static int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id,
 	return 0;
 }
 
-static int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
 {
 	u8 msg[6];
 
@@ -609,6 +611,31 @@ int cdn_dp_train_link(struct cdn_dp_device *dp)
 {
 	int ret;
 
+	/*
+	 * DP firmware uses fixed phy config values to do training, but some
+	 * boards need to adjust these values to fit for their unique hardware
+	 * design. So if the phy is using custom config values, do software
+	 * link training instead of relying on firmware, if software training
+	 * fail, keep firmware training as a fallback if sw training fails.
+	 */
+	ret = cdn_dp_software_train_link(dp);
+	if (ret) {
+		DRM_DEV_ERROR(dp->dev,
+			"Failed to do software training %d\n", ret);
+		goto do_fw_training;
+	}
+	ret = cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf);
+	if (ret) {
+		DRM_DEV_ERROR(dp->dev,
+		"Failed to write SOURCE_HDTX_CAR register %d\n", ret);
+		goto do_fw_training;
+	}
+	dp->use_fw_training = false;
+	return 0;
+
+do_fw_training:
+	dp->use_fw_training = true;
+	DRM_DEV_DEBUG_KMS(dp->dev, "use fw training\n");
 	ret = cdn_dp_training_start(dp);
 	if (ret) {
 		DRM_DEV_ERROR(dp->dev, "Failed to start training %d\n", ret);
@@ -623,7 +650,7 @@ int cdn_dp_train_link(struct cdn_dp_device *dp)
 
 	DRM_DEV_DEBUG_KMS(dp->dev, "rate:0x%x, lanes:%d\n", dp->link.rate,
 			  dp->link.num_lanes);
-	return ret;
+	return 0;
 }
 
 int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active)
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index 6580b11..3420771 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -137,7 +137,7 @@
 #define HPD_EVENT_MASK			0x211c
 #define HPD_EVENT_DET			0x2120
 
-/* dpyx framer addr */
+/* dptx framer addr */
 #define DP_FRAMER_GLOBAL_CONFIG		0x2200
 #define DP_SW_RESET			0x2204
 #define DP_FRAMER_TU			0x2208
@@ -431,6 +431,40 @@
 /* Reference cycles when using lane clock as reference */
 #define LANE_REF_CYC				0x8000
 
+/* register CM_VID_CTRL */
+#define LANE_VID_REF_CYC(x)                    (((x) & (BIT(24) - 1)) << 0)
+#define NMVID_MEAS_TOLERANCE(x)                        (((x) & 0xf) << 24)
+
+/* register DP_TX_PHY_CONFIG_REG */
+#define DP_TX_PHY_TRAINING_ENABLE(x)           ((x) & 1)
+#define DP_TX_PHY_TRAINING_TYPE_PRBS7          (0 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS1           (1 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS2           (2 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS3           (3 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_TPS4           (4 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_PLTPAT         (5 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_D10_2          (6 << 1)
+#define DP_TX_PHY_TRAINING_TYPE_HBR2CPAT       (8 << 1)
+#define DP_TX_PHY_TRAINING_PATTERN(x)          ((x) << 1)
+#define DP_TX_PHY_SCRAMBLER_BYPASS(x)          (((x) & 1) << 5)
+#define DP_TX_PHY_ENCODER_BYPASS(x)            (((x) & 1) << 6)
+#define DP_TX_PHY_SKEW_BYPASS(x)               (((x) & 1) << 7)
+#define DP_TX_PHY_DISPARITY_RST(x)             (((x) & 1) << 8)
+#define DP_TX_PHY_LANE0_SKEW(x)                (((x) & 7) << 9)
+#define DP_TX_PHY_LANE1_SKEW(x)                (((x) & 7) << 12)
+#define DP_TX_PHY_LANE2_SKEW(x)                (((x) & 7) << 15)
+#define DP_TX_PHY_LANE3_SKEW(x)                (((x) & 7) << 18)
+#define DP_TX_PHY_10BIT_ENABLE(x)              (((x) & 1) << 21)
+
+/* register DP_FRAMER_GLOBAL_CONFIG */
+#define NUM_LANES(x)           ((x) & 3)
+#define SST_MODE               (0 << 2)
+#define RG_EN                  (0 << 4)
+#define GLOBAL_EN              BIT(3)
+#define NO_VIDEO               BIT(5)
+#define ENC_RST_DIS            BIT(6)
+#define WR_VHSYNC_FALL         BIT(7)
+
 enum voltage_swing_level {
 	VOLTAGE_LEVEL_0,
 	VOLTAGE_LEVEL_1,
@@ -476,6 +510,7 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip);
 int cdn_dp_event_config(struct cdn_dp_device *dp);
 u32 cdn_dp_get_event(struct cdn_dp_device *dp);
 int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val);
 ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr,
 			  u8 *data, u16 len);
 ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr,
@@ -489,4 +524,5 @@ int cdn_dp_config_video(struct cdn_dp_device *dp);
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio);
 int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable);
 int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio);
+int cdn_dp_software_train_link(struct cdn_dp_device *dp);
 #endif /* _CDN_DP_REG_H */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 4/5] phy: rockchip-typec: support variable phy config value
From: Lin Huang @ 2018-05-23  7:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527061353-16902-1-git-send-email-hl@rock-chips.com>

the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use these value
Changes in v4:
- rename variable config to tcphy_default_config
Changes in v5:
- None
Changes in v6:
- split the header file to new patch
Changes in v7:
- add default case when check link rate
- move struct rockchip_typec_phy new element to this patch

 drivers/phy/rockchip/phy-rockchip-typec.c | 263 ++++++++++++++++++++++++------
 include/soc/rockchip/rockchip_phy_typec.h |   8 +
 2 files changed, 218 insertions(+), 53 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 795055f..69af90e 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -324,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG			0X30
+#define CLK_PLL1_DIV1			0x20
+#define CLK_PLL1_DIV2			0x30
 #define CLK_PLL_MASK			0x33
 
 #define CMN_READY			BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACK		BIT(3)
 #define DP_PLL_CLOCK_ENABLE		BIT(2)
+#define DP_PLL_ENABLE_ACK		BIT(1)
 #define DP_PLL_ENABLE			BIT(0)
 #define DP_PLL_DATA_RATE_RBR		((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR		((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2		((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK		0xff00
 
-#define DP_MODE_A0			BIT(4)
-#define DP_MODE_A2			BIT(6)
-#define DP_MODE_ENTER_A0		0xc101
-#define DP_MODE_ENTER_A2		0xc104
+#define DP_MODE_MASK			0xf
+#define DP_MODE_ENTER_A0		BIT(0)
+#define DP_MODE_ENTER_A2		BIT(2)
+#define DP_MODE_ENTER_A3		BIT(3)
+#define DP_MODE_A0_ACK			BIT(4)
+#define DP_MODE_A2_ACK			BIT(6)
+#define DP_MODE_A3_ACK			BIT(7)
+#define DP_LINK_RESET_DEASSERTED	BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT		100000
 
@@ -350,6 +358,8 @@
 #define MODE_DFP_USB			BIT(1)
 #define MODE_DFP_DP			BIT(2)
 
+#define DP_DEFAULT_RATE		162000
+
 struct phy_reg {
 	u16 value;
 	u32 addr;
@@ -372,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
 	{ 0x8,		CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
 	{ 0xf0,		CMN_PLL1_VCOCAL_INIT },
 	{ 0x18,		CMN_PLL1_VCOCAL_ITER },
 	{ 0x30b9,	CMN_PLL1_VCOCAL_START },
-	{ 0x21c,	CMN_PLL1_INTDIV },
+	{ 0x87,		CMN_PLL1_INTDIV },
 	{ 0,		CMN_PLL1_FRACDIV },
-	{ 0x5,		CMN_PLL1_HIGH_THR },
-	{ 0x35,		CMN_PLL1_SS_CTRL1 },
-	{ 0x7f1e,	CMN_PLL1_SS_CTRL2 },
+	{ 0x22,		CMN_PLL1_HIGH_THR },
+	{ 0x8000,	CMN_PLL1_SS_CTRL1 },
+	{ 0,		CMN_PLL1_SS_CTRL2 },
 	{ 0x20,		CMN_PLL1_DSM_DIAG },
 	{ 0,		CMN_PLLSM1_USER_DEF_CTRL },
 	{ 0,		CMN_DIAG_PLL1_OVRD },
@@ -391,9 +401,52 @@ struct phy_reg dp_pll_cfg[] = {
 	{ 0x8,		CMN_DIAG_PLL1_LF_PROG },
 	{ 0x100,	CMN_DIAG_PLL1_PTATIS_TUNE1 },
 	{ 0x7,		CMN_DIAG_PLL1_PTATIS_TUNE2 },
-	{ 0x4,		CMN_DIAG_PLL1_INCLK_CTRL },
+	{ 0x1,		CMN_DIAG_PLL1_INCLK_CTRL },
 };
 
+struct phy_reg dp_pll_hbr_cfg[] = {
+	{ 0xf0,		CMN_PLL1_VCOCAL_INIT },
+	{ 0x18,		CMN_PLL1_VCOCAL_ITER },
+	{ 0x30b4,	CMN_PLL1_VCOCAL_START },
+	{ 0xe1,		CMN_PLL1_INTDIV },
+	{ 0,		CMN_PLL1_FRACDIV },
+	{ 0x5,		CMN_PLL1_HIGH_THR },
+	{ 0x8000,	CMN_PLL1_SS_CTRL1 },
+	{ 0,		CMN_PLL1_SS_CTRL2 },
+	{ 0x20,		CMN_PLL1_DSM_DIAG },
+	{ 0x1000,	CMN_PLLSM1_USER_DEF_CTRL },
+	{ 0,		CMN_DIAG_PLL1_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBH_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBL_OVRD },
+	{ 0x7,		CMN_DIAG_PLL1_V2I_TUNE },
+	{ 0x45,		CMN_DIAG_PLL1_CP_TUNE },
+	{ 0x8,		CMN_DIAG_PLL1_LF_PROG },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE1 },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE2 },
+	{ 0x1,		CMN_DIAG_PLL1_INCLK_CTRL },
+};
+
+struct phy_reg dp_pll_hbr2_cfg[] = {
+	{ 0xf0,		CMN_PLL1_VCOCAL_INIT },
+	{ 0x18,		CMN_PLL1_VCOCAL_ITER },
+	{ 0x30b4,	CMN_PLL1_VCOCAL_START },
+	{ 0xe1,		CMN_PLL1_INTDIV },
+	{ 0,		CMN_PLL1_FRACDIV },
+	{ 0x5,		CMN_PLL1_HIGH_THR },
+	{ 0x8000,	CMN_PLL1_SS_CTRL1 },
+	{ 0,		CMN_PLL1_SS_CTRL2 },
+	{ 0x20,		CMN_PLL1_DSM_DIAG },
+	{ 0x1000,	CMN_PLLSM1_USER_DEF_CTRL },
+	{ 0,		CMN_DIAG_PLL1_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBH_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBL_OVRD },
+	{ 0x7,		CMN_DIAG_PLL1_V2I_TUNE },
+	{ 0x45,		CMN_DIAG_PLL1_CP_TUNE },
+	{ 0x8,		CMN_DIAG_PLL1_LF_PROG },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE1 },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE2 },
+	{ 0x1,		CMN_DIAG_PLL1_INCLK_CTRL },
+};
 static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
 	{
 		.reg = 0xff7c0000,
@@ -418,6 +471,24 @@ static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
 	{ /* sentinel */ }
 };
 
+/* default phy config */
+static const struct phy_config tcphy_default_config[3][4] = {
+	{{ .swing = 0x2a, .pe = 0x00 },
+	 { .swing = 0x1f, .pe = 0x15 },
+	 { .swing = 0x14, .pe = 0x22 },
+	 { .swing = 0x02, .pe = 0x2b } },
+
+	{{ .swing = 0x21, .pe = 0x00 },
+	 { .swing = 0x12, .pe = 0x15 },
+	 { .swing = 0x02, .pe = 0x22 },
+	 { .swing = 0,    .pe = 0 } },
+
+	{{ .swing = 0x15, .pe = 0x00 },
+	 { .swing = 0x00, .pe = 0x15 },
+	 { .swing = 0,    .pe = 0 },
+	 { .swing = 0,    .pe = 0 } },
+};
+
 static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
 {
 	u32 i, rdata;
@@ -439,7 +510,7 @@ static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
 
 	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
 	rdata &= ~CLK_PLL_MASK;
-	rdata |= CLK_PLL_CONFIG;
+	rdata |= CLK_PLL1_DIV2;
 	writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
 }
 
@@ -453,17 +524,45 @@ static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
 		       tcphy->base + usb3_pll_cfg[i].addr);
 }
 
-static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
+static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy, int link_rate)
 {
-	u32 i;
+	struct phy_reg *phy_cfg;
+	u32 clk_ctrl;
+	u32 i, cfg_size, hsclk_sel;
+
+	hsclk_sel = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+	hsclk_sel &= ~CLK_PLL_MASK;
+
+	switch (link_rate) {
+	case 540000:
+		clk_ctrl = DP_PLL_DATA_RATE_HBR2;
+		hsclk_sel |= CLK_PLL1_DIV1;
+		phy_cfg = dp_pll_hbr2_cfg;
+		cfg_size = ARRAY_SIZE(dp_pll_hbr2_cfg);
+		break;
+	case 270000:
+		clk_ctrl = DP_PLL_DATA_RATE_HBR;
+		hsclk_sel |= CLK_PLL1_DIV2;
+		phy_cfg = dp_pll_hbr_cfg;
+		cfg_size = ARRAY_SIZE(dp_pll_hbr_cfg);
+		break;
+	case 162000:
+	default:
+		clk_ctrl = DP_PLL_DATA_RATE_RBR;
+		hsclk_sel |= CLK_PLL1_DIV2;
+		phy_cfg = dp_pll_rbr_cfg;
+		cfg_size = ARRAY_SIZE(dp_pll_rbr_cfg);
+		break;
+	}
 
-	/* set the default mode to RBR */
-	writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
-	       tcphy->base + DP_CLK_CTL);
+	clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
+	writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
+
+	writel(hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
 
 	/* load the configuration of PLL1 */
-	for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
-		writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
+	for (i = 0; i < cfg_size; i++)
+		writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
 }
 
 static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
@@ -490,9 +589,10 @@ static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
 	writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
 }
 
-static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
+			      u8 swing, u8 pre_emp, u32 lane)
 {
-	u16 rdata;
+	u16 val;
 
 	writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
 	writel(0x6799, tcphy->base + TX_PSC_A0(lane));
@@ -500,25 +600,32 @@ static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
 	writel(0x98, tcphy->base + TX_PSC_A2(lane));
 	writel(0x98, tcphy->base + TX_PSC_A3(lane));
 
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
-
-	writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
-	writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
-
-	rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
-	rdata = (rdata & 0x8fff) | 0x6000;
-	writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+	writel(tcphy->config[swing][pre_emp].swing,
+	       tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+	writel(tcphy->config[swing][pre_emp].pe,
+	       tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+
+	if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
+		writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
+		writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+	} else {
+		writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+		writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
+	}
+
+	val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+	val = val & 0x8fff;
+	switch (link_rate) {
+	case 540000:
+		val |= (4 << 12);
+		break;
+	case 162000:
+	case 270000:
+	default:
+		val |= (6 << 12);
+		break;
+	}
+	writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
 }
 
 static inline int property_enable(struct rockchip_typec_phy *tcphy,
@@ -709,30 +816,33 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
 	tcphy_cfg_24m(tcphy);
 
 	if (mode == MODE_DFP_DP) {
-		tcphy_cfg_dp_pll(tcphy);
+		tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
 		for (i = 0; i < 4; i++)
-			tcphy_dp_cfg_lane(tcphy, i);
+			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, i);
 
 		writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
 	} else {
 		tcphy_cfg_usb3_pll(tcphy);
-		tcphy_cfg_dp_pll(tcphy);
+		tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
 		if (tcphy->flip) {
 			tcphy_tx_usb3_cfg_lane(tcphy, 3);
 			tcphy_rx_usb3_cfg_lane(tcphy, 2);
-			tcphy_dp_cfg_lane(tcphy, 0);
-			tcphy_dp_cfg_lane(tcphy, 1);
+			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 0);
+			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 1);
 		} else {
 			tcphy_tx_usb3_cfg_lane(tcphy, 0);
 			tcphy_rx_usb3_cfg_lane(tcphy, 1);
-			tcphy_dp_cfg_lane(tcphy, 2);
-			tcphy_dp_cfg_lane(tcphy, 3);
+			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 2);
+			tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 3);
 		}
 
 		writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
 	}
 
-	writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+	val = readl(tcphy->base + DP_MODE_CTL);
+	val &= ~DP_MODE_MASK;
+	val |= DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED;
+	writel(val, tcphy->base + DP_MODE_CTL);
 
 	reset_control_deassert(tcphy->uphy_rst);
 
@@ -945,7 +1055,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
 	property_enable(tcphy, &cfg->uphy_dp_sel, 1);
 
 	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
-				 val, val & DP_MODE_A2, 1000,
+				 val, val & DP_MODE_A2_ACK, 1000,
 				 PHY_MODE_SET_TIMEOUT);
 	if (ret < 0) {
 		dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
@@ -954,13 +1064,19 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
 
 	tcphy_dp_aux_calibration(tcphy);
 
-	writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
+	/* enter A0 mode */
+	val = readl(tcphy->base + DP_MODE_CTL);
+	val &= ~DP_MODE_MASK;
+	val |= DP_MODE_ENTER_A0;
+	writel(val, tcphy->base + DP_MODE_CTL);
 
 	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
-				 val, val & DP_MODE_A0, 1000,
+				 val, val & DP_MODE_A0_ACK, 1000,
 				 PHY_MODE_SET_TIMEOUT);
 	if (ret < 0) {
-		writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+		val &= ~DP_MODE_MASK;
+		val |= DP_MODE_ENTER_A2;
+		writel(val, tcphy->base + DP_MODE_CTL);
 		dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
 		goto power_on_finish;
 	}
@@ -978,6 +1094,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
 static int rockchip_dp_phy_power_off(struct phy *phy)
 {
 	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+	u32 val;
 
 	mutex_lock(&tcphy->lock);
 
@@ -986,7 +1103,10 @@ static int rockchip_dp_phy_power_off(struct phy *phy)
 
 	tcphy->mode &= ~MODE_DFP_DP;
 
-	writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+	val = readl(tcphy->base + DP_MODE_CTL);
+	val &= ~DP_MODE_MASK;
+	val |= DP_MODE_ENTER_A2;
+	writel(val, tcphy->base + DP_MODE_CTL);
 
 	if (tcphy->mode == MODE_DISCONNECT)
 		tcphy_phy_deinit(tcphy);
@@ -1002,9 +1122,35 @@ static const struct phy_ops rockchip_dp_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+static int typec_dp_phy_config(struct phy *phy, int link_rate,
+			 int lanes, u8 swing, u8 pre_emp)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+	u8 i;
+
+	tcphy_cfg_dp_pll(tcphy, link_rate);
+
+	if (tcphy->mode == MODE_DFP_DP) {
+		for (i = 0; i < 4; i++)
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
+	} else {
+		if (tcphy->flip) {
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
+		} else {
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
+		}
+	}
+
+	return 0;
+}
+
 static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
 			  struct device *dev)
 {
+	int ret;
+
 	tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
 							  "rockchip,grf");
 	if (IS_ERR(tcphy->grf_regs)) {
@@ -1042,6 +1188,16 @@ static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
 		return PTR_ERR(tcphy->tcphy_rst);
 	}
 
+	/*
+	 * check if phy_config pass from dts, if no,
+	 * use default phy config value.
+	 */
+	ret = of_property_read_u32_array(dev->of_node, "rockchip,phy-config",
+		(u32 *)tcphy->config, sizeof(tcphy->config) / sizeof(u32));
+	if (ret)
+		memcpy(tcphy->config, tcphy_default_config,
+		       sizeof(tcphy->config));
+
 	return 0;
 }
 
@@ -1126,6 +1282,7 @@ static int rockchip_typec_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	tcphy->typec_phy_config = typec_dp_phy_config;
 	pm_runtime_enable(dev);
 
 	for_each_available_child_of_node(np, child_np) {
diff --git a/include/soc/rockchip/rockchip_phy_typec.h b/include/soc/rockchip/rockchip_phy_typec.h
index 4afe039..8e45c4d 100644
--- a/include/soc/rockchip/rockchip_phy_typec.h
+++ b/include/soc/rockchip/rockchip_phy_typec.h
@@ -35,6 +35,11 @@ struct rockchip_usb3phy_port_cfg {
 	struct usb3phy_reg uphy_dp_sel;
 };
 
+struct phy_config {
+	int swing;
+	int pe;
+};
+
 struct rockchip_typec_phy {
 	struct device *dev;
 	void __iomem *base;
@@ -50,6 +55,9 @@ struct rockchip_typec_phy {
 	struct mutex lock;
 	bool flip;
 	u8 mode;
+	struct phy_config config[3][4];
+	int (*typec_phy_config)(struct phy *phy, int link_rate,
+				int lanes, u8 swing, u8 pre_emp);
 };
 
 #endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 3/5] soc: rockchip: split rockchip_typec_phy struct to separate header
From: Lin Huang @ 2018-05-23  7:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527061353-16902-1-git-send-email-hl@rock-chips.com>

we may use rockchip_phy_typec struct in other driver, so split
it to separate header.

Signed-off-by: Lin Huang <hl@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- new patch here
Changes in v7:
- move new element to next patch

 drivers/phy/rockchip/phy-rockchip-typec.c | 47 +-------------------------
 include/soc/rockchip/rockchip_phy_typec.h | 55 +++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 46 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..795055f 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include <linux/mfd/syscon.h>
 #include <linux/phy/phy.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
 
 #define CMN_SSM_BANDGAP			(0x21 << 2)
 #define CMN_SSM_BIAS			(0x22 << 2)
@@ -349,52 +350,6 @@
 #define MODE_DFP_USB			BIT(1)
 #define MODE_DFP_DP			BIT(2)
 
-struct usb3phy_reg {
-	u32 offset;
-	u32 enable_bit;
-	u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-	unsigned int reg;
-	struct usb3phy_reg typec_conn_dir;
-	struct usb3phy_reg usb3tousb2_en;
-	struct usb3phy_reg external_psm;
-	struct usb3phy_reg pipe_status;
-	struct usb3phy_reg usb3_host_disable;
-	struct usb3phy_reg usb3_host_port;
-	struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-	struct device *dev;
-	void __iomem *base;
-	struct extcon_dev *extcon;
-	struct regmap *grf_regs;
-	struct clk *clk_core;
-	struct clk *clk_ref;
-	struct reset_control *uphy_rst;
-	struct reset_control *pipe_rst;
-	struct reset_control *tcphy_rst;
-	const struct rockchip_usb3phy_port_cfg *port_cfgs;
-	/* mutex to protect access to individual PHYs */
-	struct mutex lock;
-
-	bool flip;
-	u8 mode;
-};
-
 struct phy_reg {
 	u16 value;
 	u32 addr;
diff --git a/include/soc/rockchip/rockchip_phy_typec.h b/include/soc/rockchip/rockchip_phy_typec.h
new file mode 100644
index 0000000..4afe039
--- /dev/null
+++ b/include/soc/rockchip/rockchip_phy_typec.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Lin Huang <hl@rock-chips.com>
+ */
+
+#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
+#define __SOC_ROCKCHIP_PHY_TYPEC_H
+
+struct usb3phy_reg {
+	u32 offset;
+	u32 enable_bit;
+	u32 write_enable;
+};
+
+/**
+ * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
+ * @reg: the base address for usb3-phy config.
+ * @typec_conn_dir: the register of type-c connector direction.
+ * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
+ * @external_psm: the register of type-c phy external psm clock.
+ * @pipe_status: the register of type-c phy pipe status.
+ * @usb3_host_disable: the register of type-c usb3 host disable.
+ * @usb3_host_port: the register of type-c usb3 host port.
+ * @uphy_dp_sel: the register of type-c phy DP select control.
+ */
+struct rockchip_usb3phy_port_cfg {
+	unsigned int reg;
+	struct usb3phy_reg typec_conn_dir;
+	struct usb3phy_reg usb3tousb2_en;
+	struct usb3phy_reg external_psm;
+	struct usb3phy_reg pipe_status;
+	struct usb3phy_reg usb3_host_disable;
+	struct usb3phy_reg usb3_host_port;
+	struct usb3phy_reg uphy_dp_sel;
+};
+
+struct rockchip_typec_phy {
+	struct device *dev;
+	void __iomem *base;
+	struct extcon_dev *extcon;
+	struct regmap *grf_regs;
+	struct clk *clk_core;
+	struct clk *clk_ref;
+	struct reset_control *uphy_rst;
+	struct reset_control *pipe_rst;
+	struct reset_control *tcphy_rst;
+	const struct rockchip_usb3phy_port_cfg *port_cfgs;
+	/* mutex to protect access to individual PHYs */
+	struct mutex lock;
+	bool flip;
+	u8 mode;
+};
+
+#endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 2/5] Documentation: dt-bindings: phy: add phy_config for Rockchip USB Type-C PHY
From: Lin Huang @ 2018-05-23  7:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527061353-16902-1-git-send-email-hl@rock-chips.com>

If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <hl@rock-chips.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v2:
- None 
Changes in v3:
- modify property description and add this property to Example
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- change rockchip,phy_config to rockchip,phy-config and descript it in detail.
Changes in v7:
- None

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 36 +++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..40d5e7a 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,11 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy-config : A list of voltage swing(mV) and pre-emphasis
+			(dB) pairs. They are 3 blocks of 4 entries and
+			correspond to s0p0 ~ s0p3, s1p0 ~ s1p3,
+			s2p0 ~ s2p3, s3p0 ~ s2p3 swing and pre-emphasis
+			values.
 Required nodes : a sub-node is required for each port the phy provides.
 		 The sub-node name is used to identify dp or usb3 port,
 		 and shall be the following entries:
@@ -50,6 +54,21 @@ Example:
 			 <&cru SRST_P_UPHY0_TCPHY>;
 		reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+		rockchip,phy-config = <0x2a 0x00>,
+			<0x1f 0x15>,
+			<0x14 0x22>,
+			<0x02 0x2b>,
+
+			<0x21 0x00>,
+			<0x12 0x15>,
+			<0x02 0x22>,
+			<0 0>,
+
+			<0x15 0x00>,
+			<0x00 0x15>,
+			<0 0>,
+			<0 0>;
+
 		tcphy0_dp: dp-port {
 			#phy-cells = <0>;
 		};
@@ -74,6 +93,21 @@ Example:
 			 <&cru SRST_P_UPHY1_TCPHY>;
 		reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+		rockchip,phy-config = <0x2a 0x00>,
+			<0x1f 0x15>,
+			<0x14 0x22>,
+			<0x02 0x2b>,
+
+			<0x21 0x00>,
+			<0x12 0x15>,
+			<0x02 0x22>,
+			<0 0>,
+
+			<0x15 0x00>,
+			<0x00 0x15>,
+			<0 0>,
+			<0 0>;
+
 		tcphy1_dp: dp-port {
 			#phy-cells = <0>;
 		};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 1/5] drm/rockchip: add transfer function for cdn-dp
From: Lin Huang @ 2018-05-23  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

From: Chris Zhong <zyw@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Enric Balletbo <enric.balletbo@collabora.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- None
Changes in v7:
- None

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++++++++++++++++++++++----
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 69 ++++++++++++++++++++++++++++++----
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++++++-
 4 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, u8 *sink_count)
 	u8 value;
 
 	*sink_count = 0;
-	ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, &value, 1);
-	if (ret)
+	ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, &value, 1);
+	if (ret < 0)
 		return ret;
 
 	*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp)
 	if (!cdn_dp_check_sink_connection(dp))
 		return -ENODEV;
 
-	ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-			       DP_RECEIVER_CAP_SIZE);
-	if (ret) {
+	ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd,
+			       sizeof(dp->dpcd));
+	if (ret < 0) {
 		DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
 		return ret;
 	}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device *dp)
 	if (!port || !dp->link.rate || !dp->link.num_lanes)
 		return false;
 
-	if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-			     DP_LINK_STATUS_SIZE)) {
+	if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
+	    DP_LINK_STATUS_SIZE) {
 		DRM_ERROR("Failed to get link status\n");
 		return false;
 	}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+				   struct drm_dp_aux_msg *msg)
+{
+	struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+	int ret;
+	u8 status;
+
+	switch (msg->request & ~DP_AUX_I2C_MOT) {
+	case DP_AUX_NATIVE_WRITE:
+	case DP_AUX_I2C_WRITE:
+	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+		ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+					msg->size);
+		break;
+	case DP_AUX_NATIVE_READ:
+	case DP_AUX_I2C_READ:
+		ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+				       msg->size);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	status = cdn_dp_get_aux_status(dp);
+	if (status == AUX_STATUS_ACK)
+		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+	else if (status == AUX_STATUS_NACK)
+		msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+	else if (status == AUX_STATUS_DEFER)
+		msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+	return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
 	struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 	dp->active = false;
 	dp->active_port = -1;
 	dp->fw_loaded = false;
+	dp->aux.name = "DP-AUX";
+	dp->aux.transfer = cdn_dp_aux_transfer;
+	dp->aux.dev = dev;
+
+	ret = drm_dp_aux_register(&dp->aux);
+	if (ret)
+		return ret;
 
 	INIT_WORK(&dp->event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
 	struct platform_device *audio_pdev;
 	struct work_struct event_work;
 	struct edid *edid;
+	struct drm_dp_aux aux;
 
 	struct mutex lock;
 	bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..979355d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -221,7 +221,12 @@ static int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, u16 addr,
 				   sizeof(field), field);
 }
 
-int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
+/*
+ * Returns the number of bytes transferred on success, or a negative
+ * error code on failure. -ETIMEDOUT is returned if mailbox message was
+ * not send successfully;
+ */
+ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
 {
 	u8 msg[5], reg[5];
 	int ret;
@@ -247,24 +252,41 @@ int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
 		goto err_dpcd_read;
 
 	ret = cdn_dp_mailbox_read_receive(dp, data, len);
+	if (!ret)
+		return len;
 
 err_dpcd_read:
+	DRM_DEV_ERROR(dp->dev, "dpcd read failed: %d\n", ret);
 	return ret;
 }
 
-int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
+#define CDN_AUX_HEADER_SIZE	5
+#define CDN_AUX_MSG_SIZE	20
+/*
+ * Returns the number of bytes transferred on success, or a negative error
+ * code on failure. -ETIMEDOUT is returned if mailbox message was not send
+ * success; -EINVAL is returned if get the wrong data size after message
+ * is sent
+ */
+ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
 {
-	u8 msg[6], reg[5];
+	u8 msg[CDN_AUX_MSG_SIZE + CDN_AUX_HEADER_SIZE];
+	u8 reg[CDN_AUX_HEADER_SIZE];
 	int ret;
 
-	msg[0] = 0;
-	msg[1] = 1;
+	if (WARN_ON(len > CDN_AUX_MSG_SIZE) || WARN_ON(len <= 0))
+		return -EINVAL;
+
+	msg[0] = (len >> 8) & 0xff;
+	msg[1] = len & 0xff;
 	msg[2] = (addr >> 16) & 0xff;
 	msg[3] = (addr >> 8) & 0xff;
 	msg[4] = addr & 0xff;
-	msg[5] = value;
+
+	memcpy(msg + CDN_AUX_HEADER_SIZE, data, len);
+
 	ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD,
-				  sizeof(msg), msg);
+				  CDN_AUX_HEADER_SIZE + len, msg);
 	if (ret)
 		goto err_dpcd_write;
 
@@ -277,8 +299,12 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
 	if (ret)
 		goto err_dpcd_write;
 
-	if (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))
+	if ((len != (reg[0] << 8 | reg[1])) ||
+	    (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))) {
 		ret = -EINVAL;
+	} else {
+		return len;
+	}
 
 err_dpcd_write:
 	if (ret)
@@ -286,6 +312,33 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
 	return ret;
 }
 
+int cdn_dp_get_aux_status(struct cdn_dp_device *dp)
+{
+	u8 status;
+	int ret;
+
+	ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX,
+				  DPTX_GET_LAST_AUX_STAUS, 0, NULL);
+	if (ret)
+		goto err_get_hpd;
+
+	ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX,
+					      DPTX_GET_LAST_AUX_STAUS,
+					      sizeof(status));
+	if (ret)
+		goto err_get_hpd;
+
+	ret = cdn_dp_mailbox_read_receive(dp, &status, sizeof(status));
+	if (ret)
+		goto err_get_hpd;
+
+	return status;
+
+err_get_hpd:
+	DRM_DEV_ERROR(dp->dev, "get aux status failed: %d\n", ret);
+	return ret;
+}
+
 int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
 			 u32 i_size, const u32 *d_mem, u32 d_size)
 {
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
index c4bbb4a83..6580b11 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -328,6 +328,13 @@
 #define GENERAL_BUS_SETTINGS            0x03
 #define GENERAL_TEST_ACCESS             0x04
 
+/* AUX status*/
+#define AUX_STATUS_ACK			0
+#define AUX_STATUS_NACK			1
+#define AUX_STATUS_DEFER			2
+#define AUX_STATUS_SINK_ERROR		3
+#define AUX_STATUS_BUS_ERROR		4
+
 #define DPTX_SET_POWER_MNG			0x00
 #define DPTX_SET_HOST_CAPABILITIES		0x01
 #define DPTX_GET_EDID				0x02
@@ -469,8 +476,11 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip);
 int cdn_dp_event_config(struct cdn_dp_device *dp);
 u32 cdn_dp_get_event(struct cdn_dp_device *dp);
 int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
-int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value);
-int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len);
+ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr,
+			  u8 *data, u16 len);
+ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr,
+			 u8 *data, u16 len);
+int cdn_dp_get_aux_status(struct cdn_dp_device *dp);
 int cdn_dp_get_edid_block(void *dp, u8 *edid,
 			  unsigned int block, size_t length);
 int cdn_dp_train_link(struct cdn_dp_device *dp);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 02/16] arm64: dts: marvell: fix CP110 ICU node size
From: Gregory CLEMENT @ 2018-05-23  7:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522094042.24770-3-miquel.raynal@bootlin.com>

Hi Miquel,
 
 On mar., mai 22 2018, Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> ICU size in CP110 is not 0x10 but at least 0x440 bytes long (from the
> specification).
>
> Fixes: 6ef84a827c37 ("arm64: dts: marvell: enable GICP and ICU on Armada 7K/8K")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> Reviewed-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>

Applied on mvebu/fixes

Thanks,

Gregory

> ---
>  arch/arm64/boot/dts/marvell/armada-cp110.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
> index 48cad7919efa..9fa41c54f69c 100644
> --- a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
> +++ b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
> @@ -146,7 +146,7 @@
>  
>  		CP110_LABEL(icu): interrupt-controller at 1e0000 {
>  			compatible = "marvell,cp110-icu";
> -			reg = <0x1e0000 0x10>;
> +			reg = <0x1e0000 0x440>;
>  			#interrupt-cells = <3>;
>  			interrupt-controller;
>  			msi-parent = <&gicp>;
> -- 
> 2.14.1
>

-- 
Gregory Clement, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
http://bootlin.com

^ permalink raw reply

* [PATCH 09/14] ARM: spectre-v2: add PSCI based hardening
From: Marc Zyngier @ 2018-05-23  7:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522175717.GT17671@n2100.armlinux.org.uk>

On Tue, 22 May 2018 18:57:18 +0100,
Russell King wrote:
> 
> On Tue, May 22, 2018 at 06:24:13PM +0100, Marc Zyngier wrote:
> > On 21/05/18 12:45, Russell King wrote:
> > > Add PSCI based hardening for cores that require more complex handling in
> > > firmware.
> > > 
> > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> > > Acked-by: Marc Zyngier <marc.zyngier@arm.com>
> > > ---
> > >  arch/arm/mm/proc-v7-bugs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
> > >  arch/arm/mm/proc-v7.S      | 21 +++++++++++++++++++
> > >  2 files changed, 71 insertions(+)
> > > 
> > > diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
> > > index 65a9b8141f86..0c37e6a2830d 100644
> > > --- a/arch/arm/mm/proc-v7-bugs.c
> > > +++ b/arch/arm/mm/proc-v7-bugs.c
> > > @@ -1,9 +1,12 @@
> > >  // SPDX-License-Identifier: GPL-2.0
> > > +#include <linux/arm-smccc.h>
> > >  #include <linux/kernel.h>
> > > +#include <linux/psci.h>
> > >  #include <linux/smp.h>
> > >  
> > >  #include <asm/cp15.h>
> > >  #include <asm/cputype.h>
> > > +#include <asm/proc-fns.h>
> > >  #include <asm/system_misc.h>
> > >  
> > >  void cpu_v7_bugs_init(void);
> > > @@ -39,6 +42,9 @@ void cpu_v7_ca15_ibe(void)
> > >  #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> > >  void (*harden_branch_predictor)(void);
> > >  
> > > +extern void cpu_v7_smc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
> > > +extern void cpu_v7_hvc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
> > > +
> > >  static void harden_branch_predictor_bpiall(void)
> > >  {
> > >  	write_sysreg(0, BPIALL);
> > > @@ -49,6 +55,18 @@ static void harden_branch_predictor_iciallu(void)
> > >  	write_sysreg(0, ICIALLU);
> > >  }
> > >  
> > > +#ifdef CONFIG_ARM_PSCI
> > > +static void call_smc_arch_workaround_1(void)
> > > +{
> > > +	arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
> > > +}
> > > +
> > > +static void call_hvc_arch_workaround_1(void)
> > > +{
> > > +	arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
> > > +}
> > > +#endif
> > > +
> > >  void cpu_v7_bugs_init(void)
> > >  {
> > >  	const char *spectre_v2_method = NULL;
> > > @@ -73,6 +91,38 @@ void cpu_v7_bugs_init(void)
> > >  		spectre_v2_method = "ICIALLU";
> > >  		break;
> > >  	}
> > > +
> > > +#ifdef CONFIG_ARM_PSCI
> > > +	if (psci_ops.smccc_version != SMCCC_VERSION_1_0) {
> > > +		struct arm_smccc_res res;
> > > +
> > > +		switch (psci_ops.conduit) {
> > > +		case PSCI_CONDUIT_HVC:
> > > +			arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> > > +					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
> > > +			if ((int)res.a0 < 0)
> > > +				break;
> > 
> > I just realised that there is a small, but significant difference
> > between this and the arm64 version: On arm64, we have a table of
> > vulnerable implementations, and we try the mitigation on a per-cpu
> > basis. Here, you entirely rely on the firmware to discover whether the
> > CPU needs mitigation or not. You then need to check for a return value
> > of 1, which indicates that although the mitigation is implemented, it is
> > not required on this particular CPU.
> > 
> > But that's probably moot if you don't support BL systems.
> > 
> > > +			harden_branch_predictor = call_hvc_arch_workaround_1;
> > > +			processor.switch_mm = cpu_v7_hvc_switch_mm;
> > > +			spectre_v2_method = "hypervisor";
> > > +			break;
> > > +
> > > +		case PSCI_CONDUIT_SMC:
> > > +			arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> > > +					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
> > > +			if ((int)res.a0 < 0)
> > > +				break;
> > > +			harden_branch_predictor = call_smc_arch_workaround_1;
> > > +			processor.switch_mm = cpu_v7_smc_switch_mm;
> > > +			spectre_v2_method = "firmware PSCI";
> > 
> > My previous remark still stands: this is not really PSCI.
> 
> Sorry, no.  Your comment was for the HVC call, not the SMC.  You said
> nothing about this one.

My bad then. For all intents and purposes, they are the same thing,
just serviced by a different exception level.

	M.

-- 
Jazz is not dead, it just smell funny.

^ permalink raw reply

* [PATCH v2] rtc: st-lpc: add range
From: Patrice CHOTARD @ 2018-05-23  7:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180521204905.7113-1-alexandre.belloni@bootlin.com>

Hi Alexandre

On 05/21/2018 10:49 PM, Alexandre Belloni wrote:
> The RTC has a 64 bit counter.
> 
> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
> ---
>   drivers/rtc/rtc-st-lpc.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
> index 2f1ef2c28740..bee75ca7ff79 100644
> --- a/drivers/rtc/rtc-st-lpc.c
> +++ b/drivers/rtc/rtc-st-lpc.c
> @@ -258,6 +258,8 @@ static int st_rtc_probe(struct platform_device *pdev)
>   	platform_set_drvdata(pdev, rtc);
>   
>   	rtc->rtc_dev->ops = &st_rtc_ops;
> +	rtc->rtc_dev->range_max = U64_MAX;
> +	do_div(rtc->rtc_dev->range_max, rtc->clkrate);
>   
>   	ret = rtc_register_device(rtc->rtc_dev);
>   	if (ret) {
> 

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

Patrice

^ 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