* [PATCH 0/2] Fix msm8974 apcs syscon compatible
From: Luca Weiss @ 2024-04-08 19:32 UTC (permalink / raw)
To: ~postmarketos/upstreaming, phone-devel, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Matthias Brugger, AngeloGioacchino Del Regno, Jacky Huang,
Shan-Chun Hung
Cc: linux-arm-msm, linux-kernel, devicetree, linux-arm-kernel,
linux-mediatek, Luca Weiss
Finally fix a warning about the apcs-global syscon used on msm8974 that
has been around forever.
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
---
Luca Weiss (2):
dt-bindings: mailbox: qcom: Add MSM8974 APCS compatible
ARM: dts: qcom: msm8974: Use proper compatible for APCS syscon
.../devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml | 1 +
arch/arm/boot/dts/qcom/qcom-msm8974.dtsi | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
---
base-commit: 8568bb2ccc278f344e6ac44af6ed010a90aa88dc
change-id: 20240408-msm8974-apcs-b7765f6bab99
Best regards,
--
Luca Weiss <luca@z3ntu.xyz>
^ permalink raw reply
* [PATCH 1/2] dt-bindings: mailbox: qcom: Add MSM8974 APCS compatible
From: Luca Weiss @ 2024-04-08 19:32 UTC (permalink / raw)
To: ~postmarketos/upstreaming, phone-devel, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Matthias Brugger, AngeloGioacchino Del Regno, Jacky Huang,
Shan-Chun Hung
Cc: linux-arm-msm, linux-kernel, devicetree, linux-arm-kernel,
linux-mediatek, Luca Weiss
In-Reply-To: <20240408-msm8974-apcs-v1-0-90cb7368836e@z3ntu.xyz>
Add compatible for the Qualcomm MSM8974 APCS block.
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
---
Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
index 79eb523b8436..982c741e6225 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
@@ -30,6 +30,7 @@ properties:
- const: syscon
- items:
- enum:
+ - qcom,msm8974-apcs-kpss-global
- qcom,msm8976-apcs-kpss-global
- const: qcom,msm8994-apcs-kpss-global
- const: syscon
--
2.44.0
^ permalink raw reply related
* [PATCH 2/2] ARM: dts: qcom: msm8974: Use proper compatible for APCS syscon
From: Luca Weiss @ 2024-04-08 19:32 UTC (permalink / raw)
To: ~postmarketos/upstreaming, phone-devel, Jassi Brar, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Matthias Brugger, AngeloGioacchino Del Regno, Jacky Huang,
Shan-Chun Hung
Cc: linux-arm-msm, linux-kernel, devicetree, linux-arm-kernel,
linux-mediatek, Luca Weiss
In-Reply-To: <20240408-msm8974-apcs-v1-0-90cb7368836e@z3ntu.xyz>
Use the apcs-kpss-global compatible for the APCS global mailbox block
found on this SoC.
This also resolves a dt-binding checker warning:
arch/arm/boot/dts/qcom/qcom-msm8974pro-fairphone-fp2.dtb: syscon@f9011000: compatible: 'anyOf' conditional failed, one must be fixed:
['syscon'] is too short
'syscon' is not one of ['allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'amd,pensando-elba-syscon', 'brcm,cru-clkset', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-syscfg', 'fsl,imx93-wakeupmix-syscfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'intel,lgm-syscon', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'marvell,armada-3700-usb2-host-misc', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,sparx5-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk356
8-qos', 'rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'starfive,jh7100-sysmain', 'ti,am62-usb-phy-ctrl', 'ti,am654-dss-oldi-io-ctrl', 'ti,am654-serdes-ctrl', 'ti,j784s4-pcie-ctrl']
from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
---
arch/arm/boot/dts/qcom/qcom-msm8974.dtsi | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
index 233d9bf42298..7e0224006b1f 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
@@ -341,9 +341,11 @@ intc: interrupt-controller@f9000000 {
<0xf9002000 0x1000>;
};
- apcs: syscon@f9011000 {
- compatible = "syscon";
+ apcs: mailbox@f9011000 {
+ compatible = "qcom,msm8974-apcs-kpss-global",
+ "qcom,msm8994-apcs-kpss-global", "syscon";
reg = <0xf9011000 0x1000>;
+ #mbox-cells = <1>;
};
saw_l2: power-manager@f9012000 {
--
2.44.0
^ permalink raw reply related
* Re: [PATCH] dt-bindings: iio: imu: mpu6050: Improve i2c-gate disallow list
From: Jean-Baptiste Maneyrol @ 2024-04-08 19:49 UTC (permalink / raw)
To: Luca Weiss, ~postmarketos/upstreaming@lists.sr.ht,
phone-devel@vger.kernel.org, Jonathan Cameron, Lars-Peter Clausen,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20240408-mpu6050-i2c-gate-v1-1-621f051ce7de@z3ntu.xyz>
Hello Luca,
good catch, thanks for the patch!
Acked-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
From: Luca Weiss <luca@z3ntu.xyz>
Sent: Monday, April 8, 2024 18:34
To: ~postmarketos/upstreaming@lists.sr.ht <~postmarketos/upstreaming@lists.sr.ht>; phone-devel@vger.kernel.org <phone-devel@vger.kernel.org>; Jonathan Cameron <jic23@kernel.org>; Lars-Peter Clausen <lars@metafoo.de>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Jean-Baptiste Maneyrol <Jean-Baptiste.Maneyrol@tdk.com>
Cc: linux-iio@vger.kernel.org <linux-iio@vger.kernel.org>; devicetree@vger.kernel.org <devicetree@vger.kernel.org>; linux-kernel@vger.kernel.org <linux-kernel@vger.kernel.org>; Luca Weiss <luca@z3ntu.xyz>
Subject: [PATCH] dt-bindings: iio: imu: mpu6050: Improve i2c-gate disallow list
This Message Is From an Untrusted Sender
You have not previously corresponded with this sender.
Before all supported sensors except for MPU{9150,9250,9255} were not
allowed to use i2c-gate in the bindings which excluded quite a few
supported sensors where this functionality is supported.
Switch the list of sensors to ones where the Linux driver explicitly
disallows support for the auxiliary bus ("inv_mpu_i2c_aux_bus"). Since
the driver is also based on "default: return true" this should scale
better into the future.
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
---
This fixes dt validation error on qcom-msm8974-lge-nexus5-hammerhead
which uses mpu6515
arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dtb: mpu6515@68: i2c-gate: False schema does not allow {'#address-cells': [[1]], '#size-cells': [[0]], 'ak8963@f': {'compatible': ['asahi-kasei,ak8963'], 'reg': [[15]], 'gpios': [[40, 67, 0]], 'vid-supply': [[50]], 'vdd-supply': [[49]]}, 'bmp280@76': {'compatible': ['bosch,bmp280'], 'reg': [[118]], 'vdda-supply': [[50]], 'vddd-supply': [[49]]}}
from schema $id: https://urldefense.com/v3/__http://devicetree.org/schemas/iio/imu/invensense,mpu6050.yaml*__;Iw!!FtrhtPsWDhZ6tw!Athn1pwCL_LPpZ97exHEFSkirApIqFF2ISY01IuyHtFBxpbPkcPWh_FmzB_TiCzb8uv1HO0AHY4IeIlv1-o$[devicetree[.]org]
---
.../devicetree/bindings/iio/imu/invensense,mpu6050.yaml | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
index 297b8a1a7ffb..587ff2bced2d 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
@@ -62,14 +62,15 @@ properties:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
- if:
- not:
- properties:
- compatible:
- contains:
- enum:
- - invensense,mpu9150
- - invensense,mpu9250
- - invensense,mpu9255
+ properties:
+ compatible:
+ contains:
+ enum:
+ - invensense,iam20680
+ - invensense,icm20602
+ - invensense,icm20608
+ - invensense,icm20609
+ - invensense,icm20689
then:
properties:
i2c-gate: false
---
base-commit: 8568bb2ccc278f344e6ac44af6ed010a90aa88dc
change-id: 20240408-mpu6050-i2c-gate-4ea473e492f4
Best regards,
--
Luca Weiss <luca@z3ntu.xyz>
^ permalink raw reply related
* Re: [PATCHv3 1/2] dt-bindings: usb: typec: anx7688: start a binding document
From: Krzysztof Kozlowski @ 2024-04-08 20:12 UTC (permalink / raw)
To: Ondřej Jirman, Pavel Machek, phone-devel, kernel list,
fiona.klute, martijn, samuel, heikki.krogerus, gregkh, linux-usb,
robh+dt, krzysztof.kozlowski+dt, devicetree
In-Reply-To: <vbo7bacecuagu4qzrr6tsdh4qlejrv7ia67yylf6ay4u7qnwge@kqj27bun2m7d>
On 08/04/2024 17:17, Ondřej Jirman wrote:
> On Mon, Apr 08, 2024 at 03:27:00PM GMT, Krzysztof Kozlowski wrote:
>> On 08/04/2024 14:48, Ondřej Jirman wrote:
>>> Yeah, I understand where the confusion is. The driver is not for anx7688 chip
>>> really. The driver is named anx7688, but that's mostly a historical accident at
>>> this point.
>>>
>>> I guess there can be a driver for anx7688 chip that can directly use the chip's
>>> resources from the host by directly manipulating its registers and implementing
>>> type-c functionality via eg. Linux's TCPM or TCPCI stack, etc. (eg. like
>>> fusb302 driver, or various tcpci subdrivers).
>>>
>>> But in this case the chip is driven by an optional on-chip microcontroller's
>>> firmware and *this driver* is specifically for *the Type-C port on Pinephone*
>>
>> We do not talk here about the driver, but bindings, so hardware.
>
> Got it. Bindings should be the same regardless of what driver would be used,
> whether this OCM based one, or some future one based on the above mentioned
> TCPCI in-kernel implementation. Hardware is the same in both cases.
>
> Just trying to imagine how to actually solve the issues...
>
> Basic thing with the I2C regulator thing is that needs to be enabled as long
> as anx7688 needs to communicate over I2C. Other user of this power rail is
> touchscreen controller for its normal power supply, and it needs to be able
> to disable it during system suspend.
This does not look like anything specific to this particular device...
but even without this, please think how you want it to be solved. Same
supply which has to be on always, because your anx7688 can talk over
I2C, and in the same time sometimes off, so touchscreen can be shutdown.
If this is regulator for the I2C bus, then I think we already had this
discussion some time ago. I think it is not a property of the I2C
device, but the controller.
>
> Now for things to not fail during suspend/resume based on PM callbacks
> invocation order, anx7688 driver needs to enable this regulator too, as long
> as it needs it.
No, the I2C bus driver needs to manage it. Not one individual I2C
device. Again, why anx7688 is specific? If you next phone has anx8867,
using different driver, you also add there i2c-supply? And if it is
nxp,ptn5100 as well?
>
> I can put bus-supply to I2C controller node, and read it from the ANX7688 driver
> I guess, by going up a DT node. Whether that's going to be acceptable, I don't
> know.
>
>
> VCONN regulator I don't know where else to put either. It doesn't seem to belong
> anywhere. It's not something directly connected to Type-C connector, so
> not part of connector bindings, and there's nothing else I can see, other
> than anx7688 device which needs it for core functionality.
That sounds like a GPIO, not regulator. anx7688 has GPIOs, right? On
Pinephone they go to regulator, but on FooPhone also using anx7688 they
go somewhere else, so why this anx7688 assumes this is a regulator?
You need to properly represent the hardware, not bend it to your one
use-case for one hardware.
>
> ANX7688 chip desing doesn't have integrated VCONN mosfet switches so it always
> needs external supply + switches that are controlled by the chip itself. There's
> no sensible design where someone would not want this and the driver needs
> to get this regulator reference from somewhere. The switches are sort of an
> extension of the chip.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2] dt-bindings: PCI: altera: Convert to YAML
From: matthew.gerlach @ 2024-04-08 20:34 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: bhelgaas, lpieralisi, kw, robh, krzysztof.kozlowski+dt, conor+dt,
linux-pci, devicetree, linux-kernel
In-Reply-To: <2ece9ac2-899c-4185-b0f3-8ab939afc1e5@linaro.org>
On Sun, 7 Apr 2024, Krzysztof Kozlowski wrote:
> On 05/04/2024 16:53, matthew.gerlach@linux.intel.com wrote:
>> From: Matthew Gerlach <matthew.gerlach@linux.intel.com>
>>
>> Convert the device tree bindings for the Altera Root Port PCIe controller
>> from text to YAML.
>>
>> Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
>> ---
>> v2:
>> - Move allOf: to bottom of file, just like example-schema is showing
>
> No, just open it and you will see it is placed differently...
I see what you mean. I will match the ordering of example-schema.
>
>> - add constraint for reg and reg-names
>
> Not complete...
I will complete.
>
>> - remove unneeded device_type
>> - drop #address-cells and #size-cells
>> - change minItems to maxItems for interrupts:
>> - change msi-parent to just "msi-parent: true"
>> - cleaned up required:
>> - make subject consistent with other commits coverting to YAML
>> - s/overt/onvert/g
>> ---
>> .../devicetree/bindings/pci/altera-pcie.txt | 50 ---------
>> .../bindings/pci/altr,pcie-root-port.yaml | 106 ++++++++++++++++++
>> 2 files changed, 106 insertions(+), 50 deletions(-)
>> delete mode 100644 Documentation/devicetree/bindings/pci/altera-pcie.txt
>> create mode 100644 Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/pci/altera-pcie.txt b/Documentation/devicetree/bindings/pci/altera-pcie.txt
>> deleted file mode 100644
>> index 816b244a221e..000000000000
>> --- a/Documentation/devicetree/bindings/pci/altera-pcie.txt
>> +++ /dev/null
>> @@ -1,50 +0,0 @@
>> -* Altera PCIe controller
>> -
>> -Required properties:
>> -- compatible : should contain "altr,pcie-root-port-1.0" or "altr,pcie-root-port-2.0"
>> -- reg: a list of physical base address and length for TXS and CRA.
>> - For "altr,pcie-root-port-2.0", additional HIP base address and length.
>> -- reg-names: must include the following entries:
>> - "Txs": TX slave port region
>> - "Cra": Control register access region
>> - "Hip": Hard IP region (if "altr,pcie-root-port-2.0")
>> -- interrupts: specifies the interrupt source of the parent interrupt
>> - controller. The format of the interrupt specifier depends
>> - on the parent interrupt controller.
>> -- device_type: must be "pci"
>> -- #address-cells: set to <3>
>> -- #size-cells: set to <2>
>> -- #interrupt-cells: set to <1>
>> -- ranges: describes the translation of addresses for root ports and
>> - standard PCI regions.
>> -- interrupt-map-mask and interrupt-map: standard PCI properties to define the
>> - mapping of the PCIe interface to interrupt numbers.
>> -
>> -Optional properties:
>> -- msi-parent: Link to the hardware entity that serves as the MSI controller
>> - for this PCIe controller.
>> -- bus-range: PCI bus numbers covered
>> -
>> -Example
>> - pcie_0: pcie@c00000000 {
>> - compatible = "altr,pcie-root-port-1.0";
>> - reg = <0xc0000000 0x20000000>,
>> - <0xff220000 0x00004000>;
>> - reg-names = "Txs", "Cra";
>> - interrupt-parent = <&hps_0_arm_gic_0>;
>> - interrupts = <0 40 4>;
>> - interrupt-controller;
>> - #interrupt-cells = <1>;
>> - bus-range = <0x0 0xFF>;
>> - device_type = "pci";
>> - msi-parent = <&msi_to_gic_gen_0>;
>> - #address-cells = <3>;
>> - #size-cells = <2>;
>> - interrupt-map-mask = <0 0 0 7>;
>> - interrupt-map = <0 0 0 1 &pcie_0 1>,
>> - <0 0 0 2 &pcie_0 2>,
>> - <0 0 0 3 &pcie_0 3>,
>> - <0 0 0 4 &pcie_0 4>;
>> - ranges = <0x82000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x10000000
>> - 0x82000000 0x00000000 0x10000000 0xd0000000 0x00000000 0x10000000>;
>> - };
>> diff --git a/Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml b/Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml
>> new file mode 100644
>> index 000000000000..999dcda05f55
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml
>> @@ -0,0 +1,106 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +# Copyright (C) 2024, Intel Corporation
>
> This is derivative of previous work, which is easily visible by doing
> the same mistakes in DTS as they were before.
This is definitely derivative of previous work, and I want to fix the
DTS mistakes too.
>
> You now added fresh copyrights ignoring all previous work, even though
> you copied it. I don't agree.
>
> If you want to ignore previous copyrights, then at least don't copy
> existing code... although even that would not be sufficient.
Ignoring previous copyrights was not my intent. There is no copyright
statement in the original text version of the device tree bindings. Should
that lack of copyright statement carry forward?
>
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/altr,pcie-root-port.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Altera PCIe Root Port
>> +
>> +maintainers:
>> + - Matthew Gerlach <matthew.gerlach@linux.intel.com>
>> +
>> +properties:
>> + compatible:
>> + items:
>
> Drop items.
I will drop the items.
>
>> + - enum:
>> + - altr,pcie-root-port-1.0
>> + - altr,pcie-root-port-2.0
>> +
>
> Missing reg with constraints.
I will add the following here:
reg:
minItems: 2
maxItems: 3
reg-names:
minItems: 2
maxItems: 3
>
>> + interrupts:
>> + maxItems: 1
>> +
>> + interrupt-map-mask:
>> + items:
>> + - const: 0
>> + - const: 0
>> + - const: 0
>> + - const: 7
>> +
>> + interrupt-map:
>> + maxItems: 4
>> +
>> + "#interrupt-cells":
>> + const: 1
>> +
>> + msi-parent: true
>> +
>> +required:
>> + - compatible
>> + - reg
>> + - reg-names
>> + - device_type
>> + - interrupts
>> + - interrupt-map
>> + - interrupt-map-mask
>> +
>> +unevaluatedProperties: false
>> +
>> +allOf:
>> + - $ref: /schemas/pci/pci-bus.yaml#
>
> That's deprecated, as explained in its description. You should use
> pci-host-bridge.yaml.
I will switch to pci-host-bridge.yaml.
>
>
>
>> + - if:
>> + properties:
>> + compatible:
>> + enum:
>> + - altr,pcie-root-port-1.0
>> + then:
>> + properties:
>> + reg:
>> + items:
>> + - description: TX slave port region
>> + - description: Control register access region
>> +
>> + reg-names:
>> + items:
>> + - const: Txs
>> + - const: Cra
>> +
>> + else:
>> + properties:
>> + reg:
>> + items:
>> + - description: Hard IP region
>> + - description: TX slave port region
>> + - description: Control register access region
>> +
>> + reg-names:
>> + items:
>> + - const: Hip
>> + - const: Txs
>> + - const: Cra
>> +
>
> unevaluated goes here, just like example-schema.
Yes, just like the example-schema
>
>> +examples:
>> + - |
>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> + #include <dt-bindings/interrupt-controller/irq.h>
>> + pcie_0: pcie@c00000000 {
>> + compatible = "altr,pcie-root-port-1.0";
>> + reg = <0xc0000000 0x20000000>,
>> + <0xff220000 0x00004000>;
>> + reg-names = "Txs", "Cra";
>> + interrupt-parent = <&hps_0_arm_gic_0>;
>> + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
>> + #interrupt-cells = <1>;
>> + bus-range = <0x0 0xff>;
>> + device_type = "pci";
>> + msi-parent = <&msi_to_gic_gen_0>;
>> + #address-cells = <3>;
>> + #size-cells = <2>;
>> + interrupt-map-mask = <0 0 0 7>;
>> + interrupt-map = <0 0 0 1 &pcie_intc 1>,
>> + <0 0 0 2 &pcie_intc 2>,
>> + <0 0 0 3 &pcie_intc 3>,
>> + <0 0 0 4 &pcie_intc 4>;
>> + ranges = <0x82000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x10000000
>> + 0x82000000 0x00000000 0x10000000 0xd0000000 0x00000000 0x10000000>;
>
> That's two entries.
I will fix the broken DTS as follows:
ranges = <0x82000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x10000000>,
<0x82000000 0x00000000 0x10000000 0xd0000000 0x00000000 0x10000000>;
>
> Best regards,
> Krzysztof
>
>
Thank you for the review,
Matthew Gerlach
^ permalink raw reply
* [PATCH v14 1/4] remoteproc: zynqmp: fix lockstep mode memory region
From: Tanmay Shah @ 2024-04-08 20:53 UTC (permalink / raw)
To: andersson, mathieu.poirier, robh, krzysztof.kozlowski+dt,
conor+dt, michal.simek, ben.levinsky, tanmay.shah
Cc: linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20240408205313.3552165-1-tanmay.shah@amd.com>
In lockstep mode, r5 core0 uses TCM of R5 core1. Following is lockstep
mode memory region as per hardware reference manual.
| *TCM* | *R5 View* | *Linux view* |
| R5_0 ATCM (128 KB) | 0x0000_0000 | 0xFFE0_0000 |
| R5_0 BTCM (128 KB) | 0x0002_0000 | 0xFFE2_0000 |
However, driver shouldn't model it as above because R5 core0 TCM and core1
TCM has different power-domains mapped to it.
Hence, TCM address space in lockstep mode should be modeled as 64KB
regions only where each region has its own power-domain as following:
| *TCM* | *R5 View* | *Linux view* |
| R5_0 ATCM0 (64 KB) | 0x0000_0000 | 0xFFE0_0000 |
| R5_0 BTCM0 (64 KB) | 0x0002_0000 | 0xFFE2_0000 |
| R5_0 ATCM1 (64 KB) | 0x0001_0000 | 0xFFE1_0000 |
| R5_0 BTCM1 (64 KB) | 0x0003_0000 | 0xFFE3_0000 |
This makes driver maintanance easy and makes design robust for future
platorms as well.
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
---
drivers/remoteproc/xlnx_r5_remoteproc.c | 146 ++----------------------
1 file changed, 12 insertions(+), 134 deletions(-)
diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index cfbd97b89c26..0f942440b4e2 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -84,12 +84,12 @@ static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
{0xffeb0000UL, 0x20000, 0x10000UL, PD_R5_1_BTCM, "btcm1"},
};
-/* In lockstep mode cluster combines each 64KB TCM and makes 128KB TCM */
+/* In lockstep mode cluster uses each 64KB TCM from second core as well */
static const struct mem_bank_data zynqmp_tcm_banks_lockstep[] = {
- {0xffe00000UL, 0x0, 0x20000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 128KB each */
- {0xffe20000UL, 0x20000, 0x20000UL, PD_R5_0_BTCM, "btcm0"},
- {0, 0, 0, PD_R5_1_ATCM, ""},
- {0, 0, 0, PD_R5_1_BTCM, ""},
+ {0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
+ {0xffe20000UL, 0x20000, 0x10000UL, PD_R5_0_BTCM, "btcm0"},
+ {0xffe10000UL, 0x10000, 0x10000UL, PD_R5_1_ATCM, "atcm1"},
+ {0xffe30000UL, 0x30000, 0x10000UL, PD_R5_1_BTCM, "btcm1"},
};
/**
@@ -541,14 +541,14 @@ static int tcm_mem_map(struct rproc *rproc,
}
/*
- * add_tcm_carveout_split_mode()
+ * add_tcm_banks()
* @rproc: single R5 core's corresponding rproc instance
*
- * allocate and add remoteproc carveout for TCM memory in split mode
+ * allocate and add remoteproc carveout for TCM memory
*
* return 0 on success, otherwise non-zero value on failure
*/
-static int add_tcm_carveout_split_mode(struct rproc *rproc)
+static int add_tcm_banks(struct rproc *rproc)
{
struct rproc_mem_entry *rproc_mem;
struct zynqmp_r5_core *r5_core;
@@ -581,10 +581,10 @@ static int add_tcm_carveout_split_mode(struct rproc *rproc)
ZYNQMP_PM_REQUEST_ACK_BLOCKING);
if (ret < 0) {
dev_err(dev, "failed to turn on TCM 0x%x", pm_domain_id);
- goto release_tcm_split;
+ goto release_tcm;
}
- dev_dbg(dev, "TCM carveout split mode %s addr=%llx, da=0x%x, size=0x%lx",
+ dev_dbg(dev, "TCM carveout %s addr=%llx, da=0x%x, size=0x%lx",
bank_name, bank_addr, da, bank_size);
rproc_mem = rproc_mem_entry_init(dev, NULL, bank_addr,
@@ -594,99 +594,16 @@ static int add_tcm_carveout_split_mode(struct rproc *rproc)
if (!rproc_mem) {
ret = -ENOMEM;
zynqmp_pm_release_node(pm_domain_id);
- goto release_tcm_split;
- }
-
- rproc_add_carveout(rproc, rproc_mem);
- rproc_coredump_add_segment(rproc, da, bank_size);
- }
-
- return 0;
-
-release_tcm_split:
- /* If failed, Turn off all TCM banks turned on before */
- for (i--; i >= 0; i--) {
- pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
- zynqmp_pm_release_node(pm_domain_id);
- }
- return ret;
-}
-
-/*
- * add_tcm_carveout_lockstep_mode()
- * @rproc: single R5 core's corresponding rproc instance
- *
- * allocate and add remoteproc carveout for TCM memory in lockstep mode
- *
- * return 0 on success, otherwise non-zero value on failure
- */
-static int add_tcm_carveout_lockstep_mode(struct rproc *rproc)
-{
- struct rproc_mem_entry *rproc_mem;
- struct zynqmp_r5_core *r5_core;
- int i, num_banks, ret;
- phys_addr_t bank_addr;
- size_t bank_size = 0;
- struct device *dev;
- u32 pm_domain_id;
- char *bank_name;
- u32 da;
-
- r5_core = rproc->priv;
- dev = r5_core->dev;
-
- /* Go through zynqmp banks for r5 node */
- num_banks = r5_core->tcm_bank_count;
-
- /*
- * In lockstep mode, TCM is contiguous memory block
- * However, each TCM block still needs to be enabled individually.
- * So, Enable each TCM block individually.
- * Although ATCM and BTCM is contiguous memory block, add two separate
- * carveouts for both.
- */
- for (i = 0; i < num_banks; i++) {
- pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
-
- /* Turn on each TCM bank individually */
- ret = zynqmp_pm_request_node(pm_domain_id,
- ZYNQMP_PM_CAPABILITY_ACCESS, 0,
- ZYNQMP_PM_REQUEST_ACK_BLOCKING);
- if (ret < 0) {
- dev_err(dev, "failed to turn on TCM 0x%x", pm_domain_id);
- goto release_tcm_lockstep;
- }
-
- bank_size = r5_core->tcm_banks[i]->size;
- if (bank_size == 0)
- continue;
-
- bank_addr = r5_core->tcm_banks[i]->addr;
- da = r5_core->tcm_banks[i]->da;
- bank_name = r5_core->tcm_banks[i]->bank_name;
-
- /* Register TCM address range, TCM map and unmap functions */
- rproc_mem = rproc_mem_entry_init(dev, NULL, bank_addr,
- bank_size, da,
- tcm_mem_map, tcm_mem_unmap,
- bank_name);
- if (!rproc_mem) {
- ret = -ENOMEM;
- zynqmp_pm_release_node(pm_domain_id);
- goto release_tcm_lockstep;
+ goto release_tcm;
}
- /* If registration is success, add carveouts */
rproc_add_carveout(rproc, rproc_mem);
rproc_coredump_add_segment(rproc, da, bank_size);
-
- dev_dbg(dev, "TCM carveout lockstep mode %s addr=0x%llx, da=0x%x, size=0x%lx",
- bank_name, bank_addr, da, bank_size);
}
return 0;
-release_tcm_lockstep:
+release_tcm:
/* If failed, Turn off all TCM banks turned on before */
for (i--; i >= 0; i--) {
pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
@@ -695,45 +612,6 @@ static int add_tcm_carveout_lockstep_mode(struct rproc *rproc)
return ret;
}
-/*
- * add_tcm_banks()
- * @rproc: single R5 core's corresponding rproc instance
- *
- * allocate and add remoteproc carveouts for TCM memory based on cluster mode
- *
- * return 0 on success, otherwise non-zero value on failure
- */
-static int add_tcm_banks(struct rproc *rproc)
-{
- struct zynqmp_r5_cluster *cluster;
- struct zynqmp_r5_core *r5_core;
- struct device *dev;
-
- r5_core = rproc->priv;
- if (!r5_core)
- return -EINVAL;
-
- dev = r5_core->dev;
-
- cluster = dev_get_drvdata(dev->parent);
- if (!cluster) {
- dev_err(dev->parent, "Invalid driver data\n");
- return -EINVAL;
- }
-
- /*
- * In lockstep mode TCM banks are one contiguous memory region of 256Kb
- * In split mode, each TCM bank is 64Kb and not contiguous.
- * We add memory carveouts accordingly.
- */
- if (cluster->mode == SPLIT_MODE)
- return add_tcm_carveout_split_mode(rproc);
- else if (cluster->mode == LOCKSTEP_MODE)
- return add_tcm_carveout_lockstep_mode(rproc);
-
- return -EINVAL;
-}
-
/*
* zynqmp_r5_parse_fw()
* @rproc: single R5 core's corresponding rproc instance
--
2.25.1
^ permalink raw reply related
* [PATCH v14 0/4] add zynqmp TCM bindings
From: Tanmay Shah @ 2024-04-08 20:53 UTC (permalink / raw)
To: andersson, mathieu.poirier, robh, krzysztof.kozlowski+dt,
conor+dt, michal.simek, ben.levinsky, tanmay.shah
Cc: linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
Tightly-Coupled Memories(TCMs) are low-latency memory that provides
predictable instruction execution and predictable data load/store
timing. Each Cortex-R5F processor contains exclusive two 64 KB memory
banks on the ATCM and BTCM ports, for a total of 128 KB of memory.
In lockstep mode, both 128KB memory is accessible to the cluster.
As per ZynqMP Ultrascale+ Technical Reference Manual UG1085, following
is address space of TCM memory. The bindings in this patch series
introduces properties to accommodate following address space with
address translation between Linux and Cortex-R5 views.
| | | |
| --- | --- | --- |
| *Mode* | *R5 View* | *Linux view* | Notes |
| *Split Mode* | *start addr*| *start addr* | |
| R5_0 ATCM (64 KB) | 0x0000_0000 | 0xFFE0_0000 | |
| R5_0 BTCM (64 KB) | 0x0002_0000 | 0xFFE2_0000 | |
| R5_1 ATCM (64 KB) | 0x0000_0000 | 0xFFE9_0000 | alias of 0xFFE1_0000 |
| R5_1 BTCM (64 KB) | 0x0002_0000 | 0xFFEB_0000 | alias of 0xFFE3_0000 |
| ___ | ___ | ___ | |
| *Lockstep Mode* | | | |
| R5_0 ATCM (128 KB) | 0x0000_0000 | 0xFFE0_0000 | |
| R5_0 BTCM (128 KB) | 0x0002_0000 | 0xFFE2_0000 | |
References:
UG1085 TCM address space:
https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Tightly-Coupled-Memory-Address-Map
---
prerequisite-patch-link: https://lore.kernel.org/all/d4556268-8274-4089-949f-3b97d67793c7@gmail.com/
Base Branch: 6.9.rc2
Changes in v14:
- Add xlnx,tcm-mode property and use it for TCM configuration
- Add Versal and Versal-NET platform support
- Maintain backward compatibility for ZynqMP platform and use hardcode
TCM addresses
Changes in v13:
- Have power-domains property for lockstep case instead of
keeping it flexible.
- Add "items:" list in power-domains property
Changes in v12:
- add "reg", "reg-names" and "power-domains" in pattern properties
- add "reg" and "reg-names" in required list
- keep "power-domains" in required list as it was before the change
Changes in v11:
- Fix yamllint warning and reduce indentation as needed
- Remove redundant initialization of the variable
- Return correct error code if memory allocation failed
Changs in v10:
- Add new patch (1/4) to series that changes hardcode TCM addresses in
lockstep mode and removes separate handling of TCM in lockstep and
split mode
- modify number of "reg", "reg-names" and "power-domains" entries
based on cluster mode
- Add extra optional atcm and btcm in "reg" property for lockstep mode
- Add "reg-names" for extra optional atcm and btcm for lockstep mode
- Drop previous Ack as bindings has new change
- Add individual tcm regions via "reg" and "reg-names" for lockstep mode
- Add each tcm's power-domains in lockstep mode
- Drop previous Ack as new change in dts patchset
- Remove redundant changes in driver to handle TCM in lockstep mode
Changes in v9:
- Fix rproc lockstep dts
- Introduce new API to request and release core1 TCM power-domains in
lockstep mode. This will be used during prepare -> add_tcm_banks
callback to enable TCM in lockstep mode.
- Parse TCM from device-tree in lockstep mode and split mode in
uniform way.
- Fix TCM representation in device-tree in lockstep mode.
- Fix comments as suggested
Changes in v8:
- Remove use of pm_domains framework
- Remove checking of pm_domain_id validation to power on/off tcm
- Remove spurious change
- parse power-domains property from device-tree and use EEMI calls
to power on/off TCM instead of using pm domains framework
Changes in v7:
- %s/pm_dev1/pm_dev_core0/r
- %s/pm_dev_link1/pm_dev_core0_link/r
- %s/pm_dev2/pm_dev_core1/r
- %s/pm_dev_link2/pm_dev_core1_link/r
- remove pm_domain_id check to move next patch
- add comment about how 1st entry in pm domain list is used
- fix loop when jump to fail_add_pm_domains loop
- move checking of pm_domain_id from previous patch
- fix mem_bank_data memory allocation
Changes in v6:
- Introduce new node entry for r5f cluster split mode dts and
keep it disabled by default.
- Keep remoteproc lockstep mode enabled by default to maintian
back compatibility.
- Enable split mode only for zcu102 board to demo split mode use
- Remove spurious change
- Handle errors in add_pm_domains function
- Remove redundant code to handle errors from remove_pm_domains
- Missing . at the end of the commit message
- remove redundant initialization of variables
- remove fail_tcm label and relevant code to free memory
acquired using devm_* API. As this will be freed when device free it
- add extra check to see if "reg" property is supported or not
Changes in v5:
- maintain Rob's Ack on bindings patch as no changes in bindings
- split previous patch into multiple patches
- Use pm domain framework to turn on/off TCM
- Add support of parsing TCM information from device-tree
- maintain backward compatibility with previous bindings without
TCM information available in device-tree
This patch series continues previous effort to upstream ZynqMP
TCM bindings:
Previous v4 version link:
https://lore.kernel.org/all/20230829181900.2561194-1-tanmay.shah@amd.com/
Previous v3 version link:
https://lore.kernel.org/all/1689964908-22371-1-git-send-email-radhey.shyam.pandey@amd.com/
Radhey Shyam Pandey (1):
dt-bindings: remoteproc: add Tightly Coupled Memory (TCM) bindings
Tanmay Shah (3):
remoteproc: zynqmp: fix lockstep mode memory region
dts: zynqmp: add properties for TCM in remoteproc
remoteproc: zynqmp: parse TCM from device tree
.../remoteproc/xlnx,zynqmp-r5fss.yaml | 279 +++++++++++++--
.../boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts | 8 +
arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 67 +++-
drivers/remoteproc/xlnx_r5_remoteproc.c | 319 ++++++++----------
4 files changed, 471 insertions(+), 202 deletions(-)
base-commit: 39cd87c4eb2b893354f3b850f916353f2658ae6f
prerequisite-patch-id: f6c4bf78d30a332948d38e5c937f031496cd3b5a
--
2.25.1
^ permalink raw reply
* [PATCH v14 2/4] dt-bindings: remoteproc: add Tightly Coupled Memory (TCM) bindings
From: Tanmay Shah @ 2024-04-08 20:53 UTC (permalink / raw)
To: andersson, mathieu.poirier, robh, krzysztof.kozlowski+dt,
conor+dt, michal.simek, ben.levinsky, tanmay.shah
Cc: linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel,
Radhey Shyam Pandey
In-Reply-To: <20240408205313.3552165-1-tanmay.shah@amd.com>
From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Introduce bindings for TCM memory address space on AMD-xilinx Zynq
UltraScale+ platform. It will help in defining TCM in device-tree
and make it's access platform agnostic and data-driven.
Tightly-coupled memories(TCMs) are low-latency memory that provides
predictable instruction execution and predictable data load/store
timing. Each Cortex-R5F processor contains two 64-bit wide 64 KB memory
banks on the ATCM and BTCM ports, for a total of 128 KB of memory.
The TCM resources(reg, reg-names and power-domain) are documented for
each TCM in the R5 node. The reg and reg-names are made as required
properties as we don't want to hardcode TCM addresses for future
platforms and for zu+ legacy implementation will ensure that the
old dts w/o reg/reg-names works and stable ABI is maintained.
It also extends the examples for TCM split and lockstep modes.
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
---
Changes in v14:
- Remove previous RB tag
- Add xlnx,tcm-mode property
- Add Versal platform support
- Add Versal-NET platform support
.../remoteproc/xlnx,zynqmp-r5fss.yaml | 279 ++++++++++++++++--
1 file changed, 257 insertions(+), 22 deletions(-)
diff --git a/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml b/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
index 78aac69f1060..6f13da11f593 100644
--- a/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
@@ -18,11 +18,26 @@ description: |
properties:
compatible:
- const: xlnx,zynqmp-r5fss
+ enum:
+ - xlnx,zynqmp-r5fss
+ - xlnx,versal-r5fss
+ - xlnx,versal-net-r52fss
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges:
+ description: |
+ Standard ranges definition providing address translations for
+ local R5F TCM address spaces to bus addresses.
xlnx,cluster-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2]
+ default: 1
description: |
The RPU MPCore can operate in split mode (Dual-processor performance), Safety
lock-step mode(Both RPU cores execute the same code in lock-step,
@@ -36,8 +51,16 @@ properties:
1: lockstep mode (default)
2: single cpu mode
+ xlnx,tcm-mode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ description: |
+ Configure RPU TCM
+ 0: split mode
+ 1: lockstep mode
+
patternProperties:
- "^r5f-[a-f0-9]+$":
+ "^r(.*)@[0-9a-f]+$":
type: object
description: |
The RPU is located in the Low Power Domain of the Processor Subsystem.
@@ -52,10 +75,22 @@ patternProperties:
properties:
compatible:
- const: xlnx,zynqmp-r5f
+ enum:
+ - xlnx,zynqmp-r5f
+ - xlnx,versal-r5f
+ - xlnx,versal-net-r52f
+
+ reg:
+ minItems: 1
+ maxItems: 4
+
+ reg-names:
+ minItems: 1
+ maxItems: 4
power-domains:
- maxItems: 1
+ minItems: 2
+ maxItems: 5
mboxes:
minItems: 1
@@ -101,35 +136,235 @@ patternProperties:
required:
- compatible
+ - reg
+ - reg-names
- power-domains
- unevaluatedProperties: false
-
required:
- compatible
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - xlnx,versal-net-r52fss
+ then:
+ properties:
+ xlnx,tcm-mode: false
+
+ patternProperties:
+ "^r52f@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ minItems: 1
+ items:
+ - description: ATCM internal memory
+ - description: BTCM internal memory
+ - description: CTCM internal memory
+
+ reg-names:
+ minItems: 1
+ items:
+ - const: atcm0
+ - const: btcm0
+ - const: ctcm0
+
+ power-domains:
+ minItems: 2
+ items:
+ - description: RPU core power domain
+ - description: ATCM power domain
+ - description: BTCM power domain
+ - description: CTCM power domain
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - xlnx,zynqmp-r5fss
+ - xlnx,versal-r5fss
+ then:
+ if:
+ properties:
+ xlnx,cluster-mode:
+ enum: [1, 2]
+ then:
+ properties:
+ xlnx,tcm-mode:
+ enum: [1]
+
+ patternProperties:
+ "^r5f@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ minItems: 1
+ items:
+ - description: ATCM internal memory
+ - description: BTCM internal memory
+ - description: extra ATCM memory in lockstep mode
+ - description: extra BTCM memory in lockstep mode
+
+ reg-names:
+ minItems: 1
+ items:
+ - const: atcm0
+ - const: btcm0
+ - const: atcm1
+ - const: btcm1
+
+ power-domains:
+ minItems: 2
+ items:
+ - description: RPU core power domain
+ - description: ATCM power domain
+ - description: BTCM power domain
+ - description: second ATCM power domain
+ - description: second BTCM power domain
+
+ required:
+ - xlnx,tcm-mode
+
+ else:
+ properties:
+ xlnx,tcm-mode:
+ enum: [0]
+
+ patternProperties:
+ "^r5f@[0-9a-f]+$":
+ type: object
+
+ properties:
+ reg:
+ minItems: 1
+ items:
+ - description: ATCM internal memory
+ - description: BTCM internal memory
+
+ reg-names:
+ minItems: 1
+ items:
+ - const: atcm0
+ - const: btcm0
+
+ power-domains:
+ minItems: 2
+ items:
+ - description: RPU core power domain
+ - description: ATCM power domain
+ - description: BTCM power domain
+
+ required:
+ - xlnx,tcm-mode
additionalProperties: false
examples:
- |
- remoteproc {
- compatible = "xlnx,zynqmp-r5fss";
- xlnx,cluster-mode = <1>;
-
- r5f-0 {
- compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware 0x7>;
- memory-region = <&rproc_0_fw_image>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
- mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
- mbox-names = "tx", "rx";
+ #include <dt-bindings/power/xlnx-zynqmp-power.h>
+
+ // Split mode configuration
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ remoteproc@ffe00000 {
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <0>;
+ xlnx,tcm-mode = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x1 0x0 0x0 0xffe90000 0x0 0x10000>,
+ <0x1 0x20000 0x0 0xffeb0000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>, <0x0 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>;
+ memory-region = <&rproc_0_fw_image>, <&rpu0vdev0buffer>,
+ <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
+ mbox-names = "tx", "rx";
+ };
+
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>, <&rpu1vdev0buffer>,
+ <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
+ mbox-names = "tx", "rx";
+ };
};
+ };
+
+ - |
+ //Lockstep configuration
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ remoteproc@ffe00000 {
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <1>;
+ xlnx,tcm-mode = <1>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0xffe10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0xffe30000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>,
+ <0x0 0x20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0", "atcm1", "btcm1";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_0_fw_image>, <&rpu0vdev0buffer>,
+ <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
+ mbox-names = "tx", "rx";
+ };
- r5f-1 {
- compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware 0x8>;
- memory-region = <&rproc_1_fw_image>, <&rpu1vdev0buffer>, <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
- mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
- mbox-names = "tx", "rx";
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>, <&rpu1vdev0buffer>,
+ <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
+ mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
+ mbox-names = "tx", "rx";
+ };
};
};
...
--
2.25.1
^ permalink raw reply related
* [PATCH v14 3/4] dts: zynqmp: add properties for TCM in remoteproc
From: Tanmay Shah @ 2024-04-08 20:53 UTC (permalink / raw)
To: andersson, mathieu.poirier, robh, krzysztof.kozlowski+dt,
conor+dt, michal.simek, ben.levinsky, tanmay.shah
Cc: linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20240408205313.3552165-1-tanmay.shah@amd.com>
Add properties as per new bindings in zynqmp remoteproc node
to represent TCM address and size.
This patch also adds alternative remoteproc node to represent
remoteproc cluster in split mode. By default lockstep mode is
enabled and users should disable it before using split mode
dts. Both device-tree nodes can't be used simultaneously one
of them must be disabled. For zcu102-1.0 and zcu102-1.1 board
remoteproc split mode dts node is enabled and lockstep mode
dts is disabled.
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
---
Changes in v14:
- Add xlnx,tcm-mode property in remoteproc node
.../boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts | 8 +++
arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 67 +++++++++++++++++--
2 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
index c8f71a1aec89..495ca94b45db 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
@@ -14,6 +14,14 @@ / {
compatible = "xlnx,zynqmp-zcu102-rev1.0", "xlnx,zynqmp-zcu102", "xlnx,zynqmp";
};
+&rproc_split {
+ status = "okay";
+};
+
+&rproc_lockstep {
+ status = "disabled";
+};
+
&eeprom {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 25d20d803230..ef31b0fc73d1 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -260,19 +260,76 @@ fpga_full: fpga-full {
ranges;
};
- remoteproc {
+ rproc_lockstep: remoteproc@ffe00000 {
compatible = "xlnx,zynqmp-r5fss";
xlnx,cluster-mode = <1>;
+ xlnx,tcm-mode = <1>;
- r5f-0 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0xffe10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0xffe30000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>,
+ <0x0 0x20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0", "atcm1", "btcm1";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_0_fw_image>;
+ };
+
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>;
+ };
+ };
+
+ rproc_split: remoteproc-split@ffe00000 {
+ status = "disabled";
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <0>;
+ xlnx,tcm-mode = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x1 0x0 0x0 0xffe90000 0x0 0x10000>,
+ <0x1 0x20000 0x0 0xffeb0000 0x0 0x10000>;
+
+ r5f@0 {
compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware PD_RPU_0>;
+ reg = <0x0 0x0 0x0 0x10000>, <0x0 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>;
memory-region = <&rproc_0_fw_image>;
};
- r5f-1 {
+ r5f@1 {
compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware PD_RPU_1>;
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
memory-region = <&rproc_1_fw_image>;
};
};
--
2.25.1
^ permalink raw reply related
* [PATCH v14 4/4] remoteproc: zynqmp: parse TCM from device tree
From: Tanmay Shah @ 2024-04-08 20:53 UTC (permalink / raw)
To: andersson, mathieu.poirier, robh, krzysztof.kozlowski+dt,
conor+dt, michal.simek, ben.levinsky, tanmay.shah
Cc: linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20240408205313.3552165-1-tanmay.shah@amd.com>
ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
is available in device-tree. Parse TCM information in driver
as per new bindings.
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
---
Changes in v14:
- Add Versal platform support
- Add Versal-NET platform support
- Maintain backward compatibility for ZynqMP platform and use hardcode
TCM addresses
- Configure TCM based on xlnx,tcm-mode property for Versal
- Avoid TCM configuration if that property isn't available in DT
drivers/remoteproc/xlnx_r5_remoteproc.c | 173 ++++++++++++++++++------
1 file changed, 132 insertions(+), 41 deletions(-)
diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index 0f942440b4e2..504492f930ac 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -74,8 +74,8 @@ struct mbox_info {
};
/*
- * Hardcoded TCM bank values. This will be removed once TCM bindings are
- * accepted for system-dt specifications and upstreamed in linux kernel
+ * Hardcoded TCM bank values. This will stay in driver to maintain backward
+ * compatibility with device-tree that does not have TCM information.
*/
static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
{0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
@@ -300,36 +300,6 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
dev_warn(dev, "failed to send message\n");
}
-/*
- * zynqmp_r5_set_mode()
- *
- * set RPU cluster and TCM operation mode
- *
- * @r5_core: pointer to zynqmp_r5_core type object
- * @fw_reg_val: value expected by firmware to configure RPU cluster mode
- * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
- *
- * Return: 0 for success and < 0 for failure
- */
-static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
- enum rpu_oper_mode fw_reg_val,
- enum rpu_tcm_comb tcm_mode)
-{
- int ret;
-
- ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
- if (ret < 0) {
- dev_err(r5_core->dev, "failed to set RPU mode\n");
- return ret;
- }
-
- ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
- if (ret < 0)
- dev_err(r5_core->dev, "failed to configure TCM\n");
-
- return ret;
-}
-
/*
* zynqmp_r5_rproc_start()
* @rproc: single R5 core's corresponding rproc instance
@@ -761,6 +731,103 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
return ERR_PTR(ret);
}
+static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster)
+{
+ int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count;
+ struct of_phandle_args out_args;
+ struct zynqmp_r5_core *r5_core;
+ struct platform_device *cpdev;
+ struct mem_bank_data *tcm;
+ struct device_node *np;
+ struct resource *res;
+ u64 abs_addr, size;
+ struct device *dev;
+
+ for (i = 0; i < cluster->core_count; i++) {
+ r5_core = cluster->r5_cores[i];
+ dev = r5_core->dev;
+ np = r5_core->np;
+
+ pd_count = of_count_phandle_with_args(np, "power-domains",
+ "#power-domain-cells");
+
+ if (pd_count <= 0) {
+ dev_err(dev, "invalid power-domains property, %d\n", pd_count);
+ return -EINVAL;
+ }
+
+ /* First entry in power-domains list is for r5 core, rest for TCM. */
+ tcm_bank_count = pd_count - 1;
+
+ if (tcm_bank_count <= 0) {
+ dev_err(dev, "invalid TCM count %d\n", tcm_bank_count);
+ return -EINVAL;
+ }
+
+ r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
+ sizeof(struct mem_bank_data *),
+ GFP_KERNEL);
+ if (!r5_core->tcm_banks)
+ return -ENOMEM;
+
+ r5_core->tcm_bank_count = tcm_bank_count;
+ for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) {
+ tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data),
+ GFP_KERNEL);
+ if (!tcm)
+ return -ENOMEM;
+
+ r5_core->tcm_banks[j] = tcm;
+
+ /* Get power-domains id of TCM. */
+ ret = of_parse_phandle_with_args(np, "power-domains",
+ "#power-domain-cells",
+ tcm_pd_idx, &out_args);
+ if (ret) {
+ dev_err(r5_core->dev,
+ "failed to get tcm %d pm domain, ret %d\n",
+ tcm_pd_idx, ret);
+ return ret;
+ }
+ tcm->pm_domain_id = out_args.args[0];
+ of_node_put(out_args.np);
+
+ /* Get TCM address without translation. */
+ ret = of_property_read_reg(np, j, &abs_addr, &size);
+ if (ret) {
+ dev_err(dev, "failed to get reg property\n");
+ return ret;
+ }
+
+ /*
+ * Remote processor can address only 32 bits
+ * so convert 64-bits into 32-bits. This will discard
+ * any unwanted upper 32-bits.
+ */
+ tcm->da = (u32)abs_addr;
+ tcm->size = (u32)size;
+
+ cpdev = to_platform_device(dev);
+ res = platform_get_resource(cpdev, IORESOURCE_MEM, j);
+ if (!res) {
+ dev_err(dev, "failed to get tcm resource\n");
+ return -EINVAL;
+ }
+
+ tcm->addr = (u32)res->start;
+ tcm->bank_name = (char *)res->name;
+ res = devm_request_mem_region(dev, tcm->addr, tcm->size,
+ tcm->bank_name);
+ if (!res) {
+ dev_err(dev, "failed to request tcm resource\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
/**
* zynqmp_r5_get_tcm_node()
* Ideally this function should parse tcm node and store information
@@ -839,9 +906,16 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
struct zynqmp_r5_core *r5_core;
int ret, i;
- ret = zynqmp_r5_get_tcm_node(cluster);
- if (ret < 0) {
- dev_err(dev, "can't get tcm node, err %d\n", ret);
+ r5_core = cluster->r5_cores[0];
+
+ /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */
+ if (device_is_compatible(dev, "xlnx,zynqmp-r5fss"))
+ ret = zynqmp_r5_get_tcm_node(cluster);
+ else
+ ret = zynqmp_r5_get_tcm_node_from_dt(cluster);
+
+ if (ret) {
+ dev_err(dev, "can't get tcm, err %d\n", ret);
return ret;
}
@@ -856,12 +930,18 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
return ret;
}
- ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
- if (ret) {
- dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
- cluster->mode, ret);
+ ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
+ if (ret < 0) {
+ dev_err(r5_core->dev, "failed to set RPU mode\n");
return ret;
}
+
+ if (device_is_compatible(dev, "xlnx,zynqmp-r5fss") ||
+ of_find_property(dev_of_node(dev), "xlnx,tcm-mode", NULL)) {
+ ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
+ if (ret < 0)
+ dev_err(r5_core->dev, "failed to configure TCM\n");
+ }
}
return 0;
@@ -906,16 +986,25 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
* fail driver probe if either of that is not set in dts.
*/
if (cluster_mode == LOCKSTEP_MODE) {
- tcm_mode = PM_RPU_TCM_COMB;
fw_reg_val = PM_RPU_MODE_LOCKSTEP;
} else if (cluster_mode == SPLIT_MODE) {
- tcm_mode = PM_RPU_TCM_SPLIT;
fw_reg_val = PM_RPU_MODE_SPLIT;
} else {
dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
return -EINVAL;
}
+ if (device_is_compatible(dev, "xlnx,zynqmp-r5fss")) {
+ if (cluster_mode == LOCKSTEP_MODE)
+ tcm_mode = PM_RPU_TCM_COMB;
+ else
+ tcm_mode = PM_RPU_TCM_SPLIT;
+ } else if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) {
+ ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode);
+ if (ret)
+ return ret;
+ }
+
/*
* Number of cores is decided by number of child nodes of
* r5f subsystem node in dts. If Split mode is used in dts
@@ -1100,6 +1189,8 @@ static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
/* Match table for OF platform binding */
static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
{ .compatible = "xlnx,zynqmp-r5fss", },
+ { .compatible = "xlnx,versal-r5fss", },
+ { .compatible = "xlnx,versal-net-r52fss", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v2 1/2] dt-bindings: mtd: amlogic,meson-nand: support fields for boot ROM code
From: kernel test robot @ 2024-04-08 21:24 UTC (permalink / raw)
To: Arseniy Krasnov, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl
Cc: oe-kbuild-all, linux-mtd, devicetree, linux-arm-kernel,
linux-amlogic, linux-kernel, oxffffaa, kernel, Arseniy Krasnov
In-Reply-To: <20240408085931.456337-2-avkrasnov@salutedevices.com>
Hi Arseniy,
kernel test robot noticed the following build warnings:
[auto build test WARNING on mtd/mtd/next]
[also build test WARNING on mtd/mtd/fixes mtd/nand/next robh/for-next linus/master v6.9-rc3 next-20240408]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Arseniy-Krasnov/dt-bindings-mtd-amlogic-meson-nand-support-fields-for-boot-ROM-code/20240408-171119
base: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
patch link: https://lore.kernel.org/r/20240408085931.456337-2-avkrasnov%40salutedevices.com
patch subject: [PATCH v2 1/2] dt-bindings: mtd: amlogic,meson-nand: support fields for boot ROM code
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20240409/202404090420.FyEkmAU9-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202404090420.FyEkmAU9-lkp@intel.com/
dtcheck warnings: (new ones prefixed by >>)
>> Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml:84:61: [warning] too few spaces after comma (commas)
Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml:85:61: [warning] too few spaces after comma (commas)
vim +84 Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml
8
9 allOf:
10 - $ref: nand-controller.yaml
11
12 maintainers:
13 - liang.yang@amlogic.com
14
15 properties:
16 compatible:
17 enum:
18 - amlogic,meson-gxl-nfc
19 - amlogic,meson-axg-nfc
20
21 reg:
22 maxItems: 2
23
24 reg-names:
25 items:
26 - const: nfc
27 - const: emmc
28
29 interrupts:
30 maxItems: 1
31
32 clocks:
33 minItems: 2
34
35 clock-names:
36 items:
37 - const: core
38 - const: device
39
40 patternProperties:
41 "^nand@[0-7]$":
42 type: object
43 $ref: raw-nand-chip.yaml
44 properties:
45 reg:
46 minimum: 0
47 maximum: 1
48
49 nand-ecc-mode:
50 const: hw
51
52 nand-ecc-step-size:
53 enum: [512, 1024]
54
55 nand-ecc-strength:
56 enum: [8, 16, 24, 30, 40, 50, 60]
57 description: |
58 The ECC configurations that can be supported are as follows.
59 meson-gxl-nfc 8, 16, 24, 30, 40, 50, 60
60 meson-axg-nfc 8
61
62 nand-rb:
63 maxItems: 1
64 items:
65 maximum: 0
66
67 amlogic,boot-page-last:
68 $ref: /schemas/types.yaml#/definitions/uint32
69 description:
70 The NFC driver needs this information to select ECC
71 algorithms supported by the boot ROM.
72
73 amlogic,boot-page-step:
74 $ref: /schemas/types.yaml#/definitions/uint32
75 description:
76 The NFC driver needs this information to select ECC
77 algorithms supported by the boot ROM (in pages).
78
79 unevaluatedProperties: false
80
81 dependencies:
82 nand-ecc-strength: [nand-ecc-step-size]
83 nand-ecc-step-size: [nand-ecc-strength]
> 84 amlogic,boot-page-last: [nand-is-boot-medium, amlogic,boot-page-step]
85 amlogic,boot-page-step: [nand-is-boot-medium, amlogic,boot-page-last]
86
87
88 required:
89 - compatible
90 - reg
91 - interrupts
92 - clocks
93 - clock-names
94
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v7 11/37] pci: pci-sh7751: Add SH7751 PCI driver
From: Mayank Rana @ 2024-04-08 21:32 UTC (permalink / raw)
To: Yoshinori Sato, linux-sh
Cc: Damien Le Moal, Niklas Cassel, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Geert Uytterhoeven, Michael Turquette, Stephen Boyd,
David Airlie, Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Thomas Gleixner, Bjorn Helgaas,
Lorenzo Pieralisi, Krzysztof Wilczyński, Greg Kroah-Hartman,
Jiri Slaby, Magnus Damm, Daniel Lezcano, Rich Felker,
John Paul Adrian Glaubitz, Lee Jones, Helge Deller,
Heiko Stuebner, Shawn Guo, Sebastian Reichel, Chris Morgan,
Linus Walleij, Arnd Bergmann, David Rientjes, Hyeonggon Yoo,
Vlastimil Babka, Baoquan He, Andrew Morton, Guenter Roeck,
Kefeng Wang, Stephen Rothwell, Javier Martinez Canillas, Guo Ren,
Azeem Shaikh, Max Filippov, Jonathan Corbet, Jacky Huang,
Herve Codina, Manikanta Guntupalli, Anup Patel, Biju Das,
Uwe Kleine-König, Sam Ravnborg, Sergey Shtylyov,
Laurent Pinchart, linux-ide, devicetree, linux-kernel,
linux-renesas-soc, linux-clk, dri-devel, linux-pci, linux-serial,
linux-fbdev
In-Reply-To: <8c44b3e28da65cf47ff6bd53cf8e9cf30f2b4cb0.1712205900.git.ysato@users.sourceforge.jp>
Hi,
On 4/3/2024 9:59 PM, Yoshinori Sato wrote:
> Renesas SH7751 CPU Internal PCI Controller driver.
>
> Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
> ---
> drivers/pci/controller/Kconfig | 9 +
> drivers/pci/controller/Makefile | 1 +
> drivers/pci/controller/pci-sh7751.c | 342 ++++++++++++++++++++++++++++
> 3 files changed, 352 insertions(+)
> create mode 100644 drivers/pci/controller/pci-sh7751.c
>
> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index e534c02ee34f..a2fd917a2e03 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -353,6 +353,15 @@ config PCIE_XILINX_CPM
> Say 'Y' here if you want kernel support for the
> Xilinx Versal CPM host bridge.
>
> +config PCI_SH7751
> + bool "Renesas SH7751 PCI controller"
> + depends on OF
> + depends on CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R || COMPILE_TEST
> + select PCI_HOST_COMMON
> + help
> + Say 'Y' here if you want kernel to support the Renesas SH7751 PCI
> + Host Bridge driver.
> +
> source "drivers/pci/controller/cadence/Kconfig"
> source "drivers/pci/controller/dwc/Kconfig"
> source "drivers/pci/controller/mobiveil/Kconfig"
> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
> index f2b19e6174af..aa97e5d74e58 100644
> --- a/drivers/pci/controller/Makefile
> +++ b/drivers/pci/controller/Makefile
> @@ -40,6 +40,7 @@ obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
> obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o
> obj-$(CONFIG_PCIE_APPLE) += pcie-apple.o
> obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621.o
> +obj-$(CONFIG_PCI_SH7751) += pci-sh7751.o
>
> # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
> obj-y += dwc/
> diff --git a/drivers/pci/controller/pci-sh7751.c b/drivers/pci/controller/pci-sh7751.c
> new file mode 100644
> index 000000000000..a5340689f737
> --- /dev/null
> +++ b/drivers/pci/controller/pci-sh7751.c
> @@ -0,0 +1,342 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SH7751 PCI driver
> + * Copyright (C) 2023 Yoshinori Sato
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci-ecam.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/pci.h>
> +#include <linux/dma-direct.h>
> +#include <asm/addrspace.h>
can you consider to rearranging headers into alphabetically sorted order ?
> +
> +/* PCICR and PCICLKCR write enable magic key */
> +#define PCIC_WE_KEY (0xa5 << 24)
> +
> +/* PCIC registers */
> +/* 0x0000 - 0x00ff mapped to PCI device configuration space */
> +#define PCIC_PCICR 0x100 /* PCI Control Register */
> +#define PCIC_PCICR_TRSB BIT(9) /* Target Read Single */
> +#define PCIC_PCICR_BSWP BIT(8) /* Target Byte Swap */
> +#define PCIC_PCICR_PLUP BIT(7) /* Enable PCI Pullup */
> +#define PCIC_PCICR_ARBM BIT(6) /* PCI Arbitration Mode */
> +#define PCIC_PCICR_MD10 BIT(5) /* MD10 status */
> +#define PCIC_PCICR_MD9 BIT(4) /* MD9 status */
> +#define PCIC_PCICR_SERR BIT(3) /* SERR output assert */
> +#define PCIC_PCICR_INTA BIT(2) /* INTA output assert */
> +#define PCIC_PCICR_PRST BIT(1) /* PCI Reset Assert */
> +#define PCIC_PCICR_CFIN BIT(0) /* Central Fun. Init Done */
> +
> +#define PCIC_PCILSR0 0x104 /* PCI Local Space Register0 */
> +#define PCIC_PCILSR1 0x108 /* PCI Local Space Register1 */
> +#define PCIC_PCILAR0 0x10c /* PCI Local Addr Register1 */
> +#define PCIC_PCILAR1 0x110 /* PCI Local Addr Register1 */
> +#define PCIC_PCIINT 0x114 /* PCI Interrupt Register */
> +#define PCIC_PCIINTM 0x118 /* PCI Interrupt Mask */
> +#define PCIC_PCIALR 0x11c /* Error Address Register */
> +#define PCIC_PCICLR 0x120 /* Error Command/Data */
> +#define PCIC_PCIAINT 0x130 /* Arbiter Interrupt Register */
> +#define PCIC_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
> +#define PCIC_PCIBMLR 0x138 /* Error Bus Master Register */
> +#define PCIC_PCIDMABT 0x140 /* DMA Transfer Arb. Register */
> +#define PCIC_PCIPAR 0x1c0 /* PIO Address Register */
> +#define PCIC_PCIMBR 0x1c4 /* Memory Base Address */
> +#define PCIC_PCIIOBR 0x1c8 /* I/O Base Address Register */
> +
> +#define PCIC_PCIPINT 0x1cc /* Power Mgmnt Int. Register */
> +#define PCIC_PCIPINT_D3 BIT(1) /* D3 Pwr Mgmt. Interrupt */
> +#define PCIC_PCIPINT_D0 BIT(0) /* D0 Pwr Mgmt. Interrupt */
> +
> +#define PCIC_PCIPINTM 0x1d0 /* Power Mgmnt Mask Register */
> +#define PCIC_PCICLKR 0x1d4 /* Clock Ctrl. Register */
> +#define PCIC_PCIBCR1 0x1e0 /* Memory BCR1 Register */
> +#define PCIC_PCIBCR2 0x1e4 /* Memory BCR2 Register */
> +#define PCIC_PCIWCR1 0x1e8 /* Wait Control 1 Register */
> +#define PCIC_PCIWCR2 0x1ec /* Wait Control 2 Register */
> +#define PCIC_PCIWCR3 0x1f0 /* Wait Control 3 Register */
> +#define PCIC_PCIMCR 0x1f4 /* Memory Control Register */
> +#define PCIC_PCIBCR3 0x1f8 /* Memory BCR3 Register */
> +#define PCIC_PCIPDR 0x220 /* Port IO Data Register */
> +
> +/* PCI IDs */
> +/* Hitachi is the company that led to Renesas. */
> +/* The SH7751 was designed by Hitachi, so it has a Hitachi ID. */
multi-line comments way ?
> +#define PCI_VENDOR_ID_HITACHI 0x1054
> +#define PCI_DEVICE_ID_SH7751 0x3505
> +#define PCI_DEVICE_ID_SH7751R 0x350e
> +
> +/* BSC registers */
> +/* Copy BSC setting to PCI BSC */
> +#define BSC_BCR1 0x0000
> +#define BSC_BCR1_SLAVE BIT(30)
> +#define BSC_BCR1_BRQEN BIT(19)
> +#define BSC_BCR2 0x0004
> +#define BSC_BCR3 0x0050
> +#define BSC_WCR1 0x0008
> +#define BSC_WCR2 0x000c
> +#define BSC_WCR3 0x0010
> +#define BSC_MCR 0x0014
> +#define BSC_MCR_MRSET BIT(30)
> +#define BSC_MCR_RFSH BIT(2)
> +
> +/* PCIC access wrapper */
> +#define pcic_writel(val, base, reg) writel(val, base + (reg))
> +#define pcic_readl(base, reg) readl(base + (reg))
Do you really needed these new macros ? Is it for better readability ?
> +/*
> + * We need to avoid collisions with `mirrored' VGA ports
> + * and other strange ISA hardware, so we always want the
> + * addresses to be allocated in the 0x000-0x0ff region
> + * modulo 0x400.
> + */
> +#define IO_REGION_BASE 0x1000
> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
> + resource_size_t size, resource_size_t align)
> +{
> + resource_size_t start = res->start;
> +
> + if (res->flags & IORESOURCE_IO) {
> + if (start < PCIBIOS_MIN_IO + IO_REGION_BASE)
> + start = PCIBIOS_MIN_IO + IO_REGION_BASE;
> +
> + /*
> + * Put everything into 0x00-0xff region modulo 0x400.
> + */
single line comment would work. no ?
> + if (start & 0x300)
> + start = (start + 0x3ff) & ~0x3ff;
> + }
> +
> + return start;
> +}
> +
> +static int setup_pci_bsc(struct device *dev, void __iomem *pcic,
> + void __iomem *bsc, unsigned int area, bool bcr3)
> +{
> + u32 word;
> +
> + word = __raw_readl(bsc + BSC_BCR1);
> + /* check BCR for SDRAM in area */
> + if (((word >> area) & 1) == 0) {
> + dev_err(dev, "Area %u is not configured for SDRAM. BCR1=0x%x\n",
> + area, word);
> + return -EINVAL;
> + }
> + word |= BSC_BCR1_SLAVE; /* PCIC BSC is slave only */
> + pcic_writel(word, pcic, PCIC_PCIBCR1);
> +
> + word = __raw_readw(bsc + BSC_BCR2);
> + /* check BCR2 for 32bit SDRAM interface*/
> + if (((word >> (area << 1)) & 0x3) != 0x3) {
> + dev_err(dev, "Area %u is not 32 bit SDRAM. BCR2=0x%x\n",
> + area, word);
> + return -EINVAL;
> + }
> + pcic_writel(word, pcic, PCIC_PCIBCR2);
> +
> + if (bcr3) {
> + /* BCR3 have only SH7751R */
> + word = __raw_readw(bsc + BSC_BCR3);
> + pcic_writel(word, pcic, PCIC_PCIBCR3);
> + }
> +
> + /* configure the wait control registers */
> + word = __raw_readl(bsc + BSC_WCR1);
> + pcic_writel(word, pcic, PCIC_PCIWCR1);
> + word = __raw_readl(bsc + BSC_WCR2);
> + pcic_writel(word, pcic, PCIC_PCIWCR2);
> + word = __raw_readl(bsc + BSC_WCR3);
> + pcic_writel(word, pcic, PCIC_PCIWCR3);
> + word = __raw_readl(bsc + BSC_MCR);
> + /* Clear MRSET and RFSH bit */
> + word &= ~(BSC_MCR_MRSET | BSC_MCR_RFSH);
> + pcic_writel(word, pcic, PCIC_PCIMCR);
> +
> + return 0;
> +}
> +
> +#define NUM_AREA 7
> +static int set_pci_ranges(struct device *dev,
> + void __iomem *pcic, void __iomem *bsc, bool bcr3)
> +{
> + struct resource_entry *dma, *tmp;
> + struct pci_host_bridge *bridge;
> + u32 bsc_done[NUM_AREA];
> + unsigned int la;
> +
> + bridge = dev_get_drvdata(dev);
> + pcic_writel(0, pcic, PCIC_PCILAR0);
> + pcic_writel(0, pcic, PCIC_PCILAR1);
> + la = 0;
> + memset(&bsc_done, 0, sizeof(bsc_done));
> + resource_list_for_each_entry_safe(dma, tmp, &bridge->dma_ranges) {
> + struct resource *res = dma->res;
> + unsigned int area;
> + u32 word;
> +
> + switch (resource_type(res)) {
> + case IORESOURCE_IO:
> + /* BAR0 is I/O space */
> + word = res->start | 1;
> + pcic_writel(word, pcic, PCI_BASE_ADDRESS_0);
> + word = pcic_readl(pcic, PCI_COMMAND);
> + word |= PCI_COMMAND_IO;
> + pcic_writel(word, pcic, PCI_COMMAND);
> + break;
> + case IORESOURCE_MEM:
> + if (la > 4) {
> + dev_err(dev, "Invalid range definition.\n");
> + return -EINVAL;
> + }
> + area = (res->start >> 26) & 0x07;
> + word = res->end - res->start;
> + if (area >= NUM_AREA) {
> + /* Area 7 is reserved. */
> + dev_info(dev, "Invalid local address 0x%08x. Ignore it.\n",
> + res->start);
> + break;
> + }
> + pcic_writel(res->start, pcic, PCI_BASE_ADDRESS_1 + la);
> + /* if dummy entry, skip BSC setup */
> + if (word < 4)
> + break;
> + /* BAR1 is local area 0, BAR2 is local area 1 */
> + pcic_writel(word, pcic, PCIC_PCILSR0 + la);
> + word = P2SEGADDR(res->start);
> + pcic_writel(word, pcic, PCIC_PCILAR0 + la);
> + la += 4;
> + if (!bsc_done[area]) {
> + /* check BCR for SDRAM in specified area. And setup PCI BSC. */
> + if (setup_pci_bsc(dev, pcic, bsc, area, bcr3))
> + return -EINVAL;
> + bsc_done[area] = 1;
> + }
> + break;
> + }
> + }
> + return 0;
> +}
> +
> +static int sh7751_pci_probe(struct platform_device *pdev)
> +{
> + struct resource *res, *bscres;
> + void __iomem *pcic;
> + void __iomem *bsc;
> + u16 vid, did;
> + u32 word;
> + int ret;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (IS_ERR(res))
> + return PTR_ERR(res);
> + pcic = ioremap(res->start, res->end - res->start + 1);
Can you consider using devm_platform_ioremap_resource() API ?
> + bscres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + bsc = devm_ioremap_resource(&pdev->dev, bscres);
> + if (IS_ERR(bsc))
> + return PTR_ERR(bsc);
Same as above.
> + /* check for SH7751/SH7751R hardware */
> + word = pcic_readl(pcic, PCI_VENDOR_ID);
> + vid = word & 0xffff;
> + did = word >> 16;
> + if ((vid != PCI_VENDOR_ID_HITACHI) ||
> + ((did != PCI_DEVICE_ID_SH7751) &&
> + (did != PCI_DEVICE_ID_SH7751R))) {
> + dev_err(&pdev->dev, "This is not an SH7751(R)\n");
error handling missing iounmap(pcic)
> + return -ENODEV;
> + }
> + dev_info(&pdev->dev, "PCI core found at %pR\n", res);
> +
> + /* Set the BCR's to enable PCI access */
> + word = __raw_readl(bsc + BSC_BCR1);
> + word |= BSC_BCR1_BRQEN;
> + __raw_writel(word, bsc + BSC_BCR1);
> +
> + /* Turn the clocks back on (not done in reset)*/
> + pcic_writel(PCIC_WE_KEY | 0, pcic, PCIC_PCICLKR);
> + /* Clear Powerdown IRQ's (not done in reset) */
> + word = PCIC_PCIPINT_D3 | PCIC_PCIPINT_D0;
> + pcic_writel(word, pcic, PCIC_PCIPINT);
> +
> + /* set the command/status */
> + word = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
> + PCI_COMMAND_PARITY | PCI_COMMAND_WAIT;
> + pcic_writel(word, pcic, PCI_COMMAND);
> +
> + /* define this host as the host bridge */
> + word = PCI_BASE_CLASS_BRIDGE << 24;
> + pcic_writel(word, pcic, PCI_CLASS_REVISION);
> +
> + ret = pci_host_common_probe(pdev);
> + if (ret) {
> + dev_err(&pdev->dev, "Initialize failed (%d)\n", ret);
> + return ret;
> + }
> +
> + /* Set IO and Mem windows to local address */
> + if (set_pci_ranges(&pdev->dev, pcic, bsc,
> + did == PCI_DEVICE_ID_SH7751R))
> + return -EINVAL;
error handling to call pci_host_common_remove() ?
> + pcic_writel(0, pcic, PCIC_PCIIOBR);
> +
> + if (of_property_read_bool(pdev->dev.of_node, "renesas,bus-arbit-round-robin"))
> + word |= BIT(0);
> + else
> + word = 0;
> + pcic_writel(word, pcic, PCIC_PCIDMABT);
> +
> + /* SH7751 init done, set central function init complete */
> + /* use round robin mode to stop a device starving/overrunning */
multi-line comment ?
> + word = PCIC_PCICR_CFIN | PCIC_PCICR_ARBM;
> + pcic_writel(PCIC_WE_KEY | word, pcic, PCIC_PCICR);
> +
> + return 0;
> +}
> +
> +/*
> + * Direct access to PCI hardware...
> + */
> +#define CONFIG_CMD(bus, devfn, where) \
> + (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
> +
> +static void __iomem *sh4_pci_map_bus(struct pci_bus *bus,
> + unsigned int devfn, int where)
> +{
> + struct pci_config_window *cfg = bus->sysdata;
> + void __iomem *pcic = (void __iomem *)cfg->res.start;
> +
> + pcic_writel(CONFIG_CMD(bus, devfn, where), pcic, PCIC_PCIPAR);
> + return pcic + PCIC_PCIPDR;
> +}
> +
> +static const struct pci_ecam_ops pci_sh7751_bus_ops = {
> + .pci_ops = {
> + .map_bus = sh4_pci_map_bus,
> + .read = pci_generic_config_read32,
> + .write = pci_generic_config_write32,
> + }
> +};
> +
> +static const struct of_device_id sh7751_pci_of_match[] = {
> + { .compatible = "renesas,sh7751-pci",
> + .data = &pci_sh7751_bus_ops },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, sh7751_pci_of_match);
> +
> +static struct platform_driver sh7751_pci_driver = {
> + .driver = {
> + .name = "sh7751-pci",
> + .of_match_table = sh7751_pci_of_match,
> + },
> + .probe = sh7751_pci_probe,
> +};
> +module_platform_driver(sh7751_pci_driver);
> +
> +MODULE_DESCRIPTION("SH7751 PCI driver");
^ permalink raw reply
* [PATCH v5 00/10] RK3588 USBDP support
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
Hi,
This adds Rockchip RK3588 USBDP PHY support, which is used for two of the three
USB3 controllers in the RK3588 (the third one uses a different PHY, which is
already supported). The USBDP PHY offers USB3 dual-role and DisplayPort. The
driver and bindings being upstreamed contains the DP parts, but only USB3 has
been tested by me (upstream does not yet have a DRM DP bridge driver for this
platform).
What has been tested:
- USB3 Type A ports on Rock 5A, Rock 5B, EVB1
- USB Type C port on EVB1 in Host mode
I did not yet include a patch to enable the Type-C from the Rock 5B, since that
requires enabling proper support for the fusb302. Since the system is usually
supplied via USB-C and without any battery backup, this easily results in
system reset when the power-delivery negotiation happens. As this issue is
independent from the USBDP PHY, I skipped enabling that port on Rock 5B for
now.
You can find a branch with these patches here:
https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux/-/commits/rk3588-usbdp
Changes since PATCHv4:
* https://lore.kernel.org/all/20240325141653.84910-1-sebastian.reichel@collabora.com/
* update copyright
* drop linux/clk-provider.h include
* replace of.h with mod_devicetable.h
* re-check necessity of other included headers
* rk_udphy_setup, rk_udphy_usb3_phy_init: remove redundant init of ret variable
* rk_udphy_parse_dt: directly return rk_udphy_reset_init()
Changes since PATCHv3:
* https://lore.kernel.org/all/20240216170514.75200-1-sebastian.reichel@collabora.com/
* Rebase to v6.9-rc1
* Collect Reviewed-by and Tested-by from Heiko for patch 1 + 2
Changes since PATCHv2:
* https://lore.kernel.org/all/20240213163609.44930-1-sebastian.reichel@collabora.com/
* Drop patch 1+2 (GRF DT bindings got merged by Heiko Stübner)
* USBDP PHY DT binding: more spelling fixes
* USBDP PHY DT binding: add Reviewed-by from Conor Dooley
* USBDP PHY DT binding: specify 3 as maximum value for rockchip,dp-lane-mux items
* all patches: remove child nodes for usb3-port and dp-port and use PHY cell instead
* USBDP PHY driver: drop some header includes
* USBDP PHY driver: rework rk_udphy_grfreg_write to use FIELD_PREP_CONST
* USBDP PHY driver: add newline after break; in switch cases
* USBDP PHY driver: make some functions void
Changes since PATCHv1:
* https://lore.kernel.org/all/20240209181831.104687-1-sebastian.reichel@collabora.com/
* VO GRF DT binding: Collect Acked-by from Conor Dooley
* USB3 syscon DT binding: Collect Acked-by from Conor Dooley
* USBDP PHY DT binding: fix spelling
* USBDP PHY DT binding: add maxItems: 1 to gpios
* USBDP PHY driver: use rk_udphy_ prefix everywhere
* USBDP PHY DT addition: fix nodenames and property order
* USBDP PHY DT addition: fix position of the GRF nodes
* add new patches fixing existing USB2 PHY nodenames/property order
Not changed:
* rockchip,dp-lane-mux: Why "mux" and not "map"?
- This is about muxing DP lanes vs USB3 lanes. I kept mux instead
of map, since that's used downstream and there does not seem to
be a good reason to diverge?
-- Sebastian
Sebastian Reichel (10):
dt-bindings: phy: add rockchip usbdp combo phy document
phy: rockchip: add usbdp combo phy driver
arm64: defconfig: enable Rockchip Samsung USBDP PHY
arm64: dts: rockchip: fix usb2phy nodename for rk3588
arm64: dts: rockchip: reorder usb2phy properties for rk3588
arm64: dts: rockchip: add USBDP phys on rk3588
arm64: dts: rockchip: add USB3 DRD controllers on rk3588
arm64: dts: rockchip: add USB3 to rk3588-evb1
arm64: dts: rockchip: add upper USB3 port to rock-5a
arm64: dts: rockchip: add lower USB3 port to rock-5b
.../bindings/phy/phy-rockchip-usbdp.yaml | 148 ++
.../boot/dts/rockchip/rk3588-evb1-v10.dts | 143 ++
.../boot/dts/rockchip/rk3588-rock-5b.dts | 17 +
arch/arm64/boot/dts/rockchip/rk3588.dtsi | 72 +
.../boot/dts/rockchip/rk3588s-rock-5a.dts | 18 +
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 105 +-
arch/arm64/configs/defconfig | 1 +
drivers/phy/rockchip/Kconfig | 12 +
drivers/phy/rockchip/Makefile | 1 +
drivers/phy/rockchip/phy-rockchip-usbdp.c | 1608 +++++++++++++++++
10 files changed, 2115 insertions(+), 10 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
create mode 100644 drivers/phy/rockchip/phy-rockchip-usbdp.c
--
2.43.0
^ permalink raw reply
* [PATCH v5 03/10] arm64: defconfig: enable Rockchip Samsung USBDP PHY
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
The USBDP Phy is used by RK3588 to handle the Dual-Role USB3
controllers. The Phy also supports Displayport Alt-Mode, but
the necessary DRM driver has not yet been merged.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 2c30d617e180..364795edb94b 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1517,6 +1517,7 @@ CONFIG_PHY_ROCKCHIP_PCIE=m
CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX=m
CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y
CONFIG_PHY_ROCKCHIP_TYPEC=y
+CONFIG_PHY_ROCKCHIP_USBDP=m
CONFIG_PHY_SAMSUNG_UFS=y
CONFIG_PHY_UNIPHIER_USB2=y
CONFIG_PHY_UNIPHIER_USB3=y
--
2.43.0
^ permalink raw reply related
* [PATCH v5 04/10] arm64: dts: rockchip: fix usb2phy nodename for rk3588
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
usb2-phy should be named usb2phy according to the DT binding,
so let's fix it up accordingly.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 87b83c87bd55..5ed0d8c95427 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -543,7 +543,7 @@ usb2phy2_grf: syscon@fd5d8000 {
#address-cells = <1>;
#size-cells = <1>;
- u2phy2: usb2-phy@8000 {
+ u2phy2: usb2phy@8000 {
compatible = "rockchip,rk3588-usb2phy";
reg = <0x8000 0x10>;
interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -568,7 +568,7 @@ usb2phy3_grf: syscon@fd5dc000 {
#address-cells = <1>;
#size-cells = <1>;
- u2phy3: usb2-phy@c000 {
+ u2phy3: usb2phy@c000 {
compatible = "rockchip,rk3588-usb2phy";
reg = <0xc000 0x10>;
interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
--
2.43.0
^ permalink raw reply related
* [PATCH v5 01/10] dt-bindings: phy: add rockchip usbdp combo phy document
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel,
Conor Dooley
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Add device tree binding document for Rockchip USBDP Combo PHY
with Samsung IP block.
Co-developed-by: Frank Wang <frank.wang@rock-chips.com>
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
.../bindings/phy/phy-rockchip-usbdp.yaml | 148 ++++++++++++++++++
1 file changed, 148 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
new file mode 100644
index 000000000000..1f1f8863b80d
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
@@ -0,0 +1,148 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/phy-rockchip-usbdp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip USBDP Combo PHY with Samsung IP block
+
+maintainers:
+ - Frank Wang <frank.wang@rock-chips.com>
+ - Zhang Yubing <yubing.zhang@rock-chips.com>
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3588-usbdp-phy
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ description: |
+ Cell allows setting the type of the PHY. Possible values are:
+ - PHY_TYPE_USB3
+ - PHY_TYPE_DP
+ const: 1
+
+ clocks:
+ maxItems: 4
+
+ clock-names:
+ items:
+ - const: refclk
+ - const: immortal
+ - const: pclk
+ - const: utmi
+
+ resets:
+ maxItems: 5
+
+ reset-names:
+ items:
+ - const: init
+ - const: cmn
+ - const: lane
+ - const: pcs_apb
+ - const: pma_apb
+
+ rockchip,dp-lane-mux:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 2
+ maxItems: 4
+ items:
+ maximum: 3
+ description:
+ An array of physical Type-C lanes indexes. Position of an entry
+ determines the DisplayPort (DP) lane index, while the value of an entry
+ indicates physical Type-C lane. The supported DP lanes number are 2 or 4.
+ e.g. for 2 lanes DP lanes map, we could have "rockchip,dp-lane-mux = <2,
+ 3>;", assuming DP lane0 on Type-C phy lane2, DP lane1 on Type-C phy
+ lane3. For 4 lanes DP lanes map, we could have "rockchip,dp-lane-mux =
+ <0, 1, 2, 3>;", assuming DP lane0 on Type-C phy lane0, DP lane1 on Type-C
+ phy lane1, DP lane2 on Type-C phy lane2, DP lane3 on Type-C phy lane3. If
+ DP lanes are mapped by DisplayPort Alt mode, this property is not needed.
+
+ rockchip,u2phy-grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon managing the 'usb2 phy general register files'.
+
+ rockchip,usb-grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon managing the 'usb general register files'.
+
+ rockchip,usbdpphy-grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon managing the 'usbdp phy general register files'.
+
+ rockchip,vo-grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon managing the 'video output general register files'.
+ When select the DP lane mapping will request its phandle.
+
+ sbu1-dc-gpios:
+ description:
+ GPIO connected to the SBU1 line of the USB-C connector via a big resistor
+ (~100K) to apply a DC offset for signalling the connector orientation.
+ maxItems: 1
+
+ sbu2-dc-gpios:
+ description:
+ GPIO connected to the SBU2 line of the USB-C connector via a big resistor
+ (~100K) to apply a DC offset for signalling the connector orientation.
+ maxItems: 1
+
+ orientation-switch:
+ description: Flag the port as possible handler of orientation switching
+ type: boolean
+
+ mode-switch:
+ description: Flag the port as possible handler of altmode switching
+ type: boolean
+
+ port:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ A port node to link the PHY to a TypeC controller for the purpose of
+ handling orientation switching.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+ #include <dt-bindings/reset/rockchip,rk3588-cru.h>
+
+ usbdp_phy0: phy@fed80000 {
+ compatible = "rockchip,rk3588-usbdp-phy";
+ reg = <0xfed80000 0x10000>;
+ #phy-cells = <1>;
+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
+ <&cru CLK_USBDP_PHY0_IMMORTAL>,
+ <&cru PCLK_USBDPPHY0>,
+ <&u2phy0>;
+ clock-names = "refclk", "immortal", "pclk", "utmi";
+ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>,
+ <&cru SRST_USBDP_COMBO_PHY0_CMN>,
+ <&cru SRST_USBDP_COMBO_PHY0_LANE>,
+ <&cru SRST_USBDP_COMBO_PHY0_PCS>,
+ <&cru SRST_P_USBDPPHY0>;
+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
+ rockchip,u2phy-grf = <&usb2phy0_grf>;
+ rockchip,usb-grf = <&usb_grf>;
+ rockchip,usbdpphy-grf = <&usbdpphy0_grf>;
+ rockchip,vo-grf = <&vo0_grf>;
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v5 02/10] phy: rockchip: add usbdp combo phy driver
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel,
Zhang Yubing
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
This adds a new USBDP combo PHY with Samsung IP block driver.
The driver get lane mux and mapping info in 2 ways, supporting
DisplayPort alternate mode or parsing from DT. When parsing from DT,
the property "rockchip,dp-lane-mux" provide the DP mux and mapping
info. This is needed when the PHY is not used with TypeC Alt-Mode.
For example if the USB3 interface of the PHY is connected to a USB
Type A connector and the DP interface is connected to a DisplayPort
connector.
When do DP link training, need to set lane number, link rate, swing,
and pre-emphasis via PHY configure interface.
Co-developed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Co-developed-by: Zhang Yubing <yubing.zhang@rock-chips.com>
Signed-off-by: Zhang Yubing <yubing.zhang@rock-chips.com>
Co-developed-by: Frank Wang <frank.wang@rock-chips.com>
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/Kconfig | 12 +
drivers/phy/rockchip/Makefile | 1 +
drivers/phy/rockchip/phy-rockchip-usbdp.c | 1608 +++++++++++++++++++++
3 files changed, 1621 insertions(+)
create mode 100644 drivers/phy/rockchip/phy-rockchip-usbdp.c
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index a34f67bb7e61..c3d62243b474 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -115,3 +115,15 @@ config PHY_ROCKCHIP_USB
select GENERIC_PHY
help
Enable this to support the Rockchip USB 2.0 PHY.
+
+config PHY_ROCKCHIP_USBDP
+ tristate "Rockchip USBDP COMBO PHY Driver"
+ depends on ARCH_ROCKCHIP && OF
+ select GENERIC_PHY
+ select TYPEC
+ help
+ Enable this to support the Rockchip USB3.0/DP combo PHY with
+ Samsung IP block. This is required for USB3 support on RK3588.
+
+ To compile this driver as a module, choose M here: the module
+ will be called phy-rockchip-usbdp
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index 3d911304e654..010a824e32ce 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
+obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
new file mode 100644
index 000000000000..32f306459182
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -0,0 +1,1608 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Rockchip USBDP Combo PHY with Samsung IP block driver
+ *
+ * Copyright (C) 2021-2024 Rockchip Electronics Co., Ltd
+ * Copyright (C) 2024 Collabora Ltd
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+
+/* USBDP PHY Register Definitions */
+#define UDPHY_PCS 0x4000
+#define UDPHY_PMA 0x8000
+
+/* VO0 GRF Registers */
+#define DP_SINK_HPD_CFG BIT(11)
+#define DP_SINK_HPD_SEL BIT(10)
+#define DP_AUX_DIN_SEL BIT(9)
+#define DP_AUX_DOUT_SEL BIT(8)
+#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n))
+#define DP_LANE_SEL_ALL GENMASK(7, 0)
+
+/* PMA CMN Registers */
+#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */
+#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4)
+#define CMN_DP_LANE_EN_N(n) BIT(n)
+#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4)
+#define CMN_DP_LANE_EN_ALL GENMASK(3, 0)
+
+#define CMN_DP_LINK_OFFSET 0x28c /* cmn_reg00A3 */
+#define CMN_DP_TX_LINK_BW GENMASK(6, 5)
+#define CMN_DP_TX_LANE_SWAP_EN BIT(2)
+
+#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */
+#define CMN_ROPLL_SSC_EN BIT(1)
+#define CMN_LCPLL_SSC_EN BIT(0)
+
+#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */
+#define CMN_ANA_LCPLL_LOCK_DONE BIT(7)
+#define CMN_ANA_LCPLL_AFC_DONE BIT(6)
+
+#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */
+#define CMN_ANA_ROPLL_LOCK_DONE BIT(1)
+#define CMN_ANA_ROPLL_AFC_DONE BIT(0)
+
+#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */
+#define CMN_DP_INIT_RSTN BIT(3)
+#define CMN_DP_CMN_RSTN BIT(2)
+#define CMN_CDR_WTCHDG_EN BIT(1)
+#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0)
+
+#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */
+#define LN_ANA_TX_SER_TXCLK_INV BIT(1)
+
+#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */
+#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0)
+
+#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */
+#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0)
+
+#define BIT_WRITEABLE_SHIFT 16
+#define PHY_AUX_DP_DATA_POL_NORMAL 0
+#define PHY_AUX_DP_DATA_POL_INVERT 1
+#define PHY_LANE_MUX_USB 0
+#define PHY_LANE_MUX_DP 1
+
+enum {
+ DP_BW_RBR,
+ DP_BW_HBR,
+ DP_BW_HBR2,
+ DP_BW_HBR3,
+};
+
+enum {
+ UDPHY_MODE_NONE = 0,
+ UDPHY_MODE_USB = BIT(0),
+ UDPHY_MODE_DP = BIT(1),
+ UDPHY_MODE_DP_USB = BIT(1) | BIT(0),
+};
+
+struct rk_udphy_grf_reg {
+ unsigned int offset;
+ unsigned int disable;
+ unsigned int enable;
+};
+
+#define _RK_UDPHY_GEN_GRF_REG(offset, mask, disable, enable) \
+{\
+ offset, \
+ FIELD_PREP_CONST(mask, disable) | (mask << BIT_WRITEABLE_SHIFT), \
+ FIELD_PREP_CONST(mask, enable) | (mask << BIT_WRITEABLE_SHIFT), \
+}
+
+#define RK_UDPHY_GEN_GRF_REG(offset, bitend, bitstart, disable, enable) \
+ _RK_UDPHY_GEN_GRF_REG(offset, GENMASK(bitend, bitstart), disable, enable)
+
+struct rk_udphy_grf_cfg {
+ /* u2phy-grf */
+ struct rk_udphy_grf_reg bvalid_phy_con;
+ struct rk_udphy_grf_reg bvalid_grf_con;
+
+ /* usb-grf */
+ struct rk_udphy_grf_reg usb3otg0_cfg;
+ struct rk_udphy_grf_reg usb3otg1_cfg;
+
+ /* usbdpphy-grf */
+ struct rk_udphy_grf_reg low_pwrn;
+ struct rk_udphy_grf_reg rx_lfps;
+};
+
+struct rk_udphy_vogrf_cfg {
+ /* vo-grf */
+ struct rk_udphy_grf_reg hpd_trigger;
+ u32 dp_lane_reg;
+};
+
+struct rk_udphy_dp_tx_drv_ctrl {
+ u32 trsv_reg0204;
+ u32 trsv_reg0205;
+ u32 trsv_reg0206;
+ u32 trsv_reg0207;
+};
+
+struct rk_udphy_cfg {
+ unsigned int num_phys;
+ unsigned int phy_ids[2];
+ /* resets to be requested */
+ const char * const *rst_list;
+ int num_rsts;
+
+ struct rk_udphy_grf_cfg grfcfg;
+ struct rk_udphy_vogrf_cfg vogrfcfg[2];
+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4];
+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg_typec[4])[4];
+};
+
+struct rk_udphy {
+ struct device *dev;
+ struct regmap *pma_regmap;
+ struct regmap *u2phygrf;
+ struct regmap *udphygrf;
+ struct regmap *usbgrf;
+ struct regmap *vogrf;
+ struct typec_switch_dev *sw;
+ struct typec_mux_dev *mux;
+ struct mutex mutex; /* mutex to protect access to individual PHYs */
+
+ /* clocks and rests */
+ int num_clks;
+ struct clk_bulk_data *clks;
+ struct clk *refclk;
+ int num_rsts;
+ struct reset_control_bulk_data *rsts;
+
+ /* PHY status management */
+ bool flip;
+ bool mode_change;
+ u8 mode;
+ u8 status;
+
+ /* utilized for USB */
+ bool hs; /* flag for high-speed */
+
+ /* utilized for DP */
+ struct gpio_desc *sbu1_dc_gpio;
+ struct gpio_desc *sbu2_dc_gpio;
+ u32 lane_mux_sel[4];
+ u32 dp_lane_sel[4];
+ u32 dp_aux_dout_sel;
+ u32 dp_aux_din_sel;
+ bool dp_sink_hpd_sel;
+ bool dp_sink_hpd_cfg;
+ u8 bw;
+ int id;
+
+ bool dp_in_use;
+
+ /* PHY const config */
+ const struct rk_udphy_cfg *cfgs;
+
+ /* PHY devices */
+ struct phy *phy_dp;
+ struct phy *phy_u3;
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x20, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x29, 0x18, 0x42, 0xe5 },
+ { 0x2b, 0x1c, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x23, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x17, 0x43, 0xe7 },
+ { 0x2b, 0x1a, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x27, 0x10, 0x42, 0xe7 },
+ { 0x2b, 0x17, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x29, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr_typec[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x20, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x29, 0x18, 0x42, 0xe5 },
+ { 0x2b, 0x1c, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x23, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x17, 0x43, 0xe7 },
+ { 0x2b, 0x1a, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x27, 0x10, 0x43, 0x67 },
+ { 0x2b, 0x17, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x29, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr2[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x21, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x26, 0x16, 0x43, 0xe5 },
+ { 0x2a, 0x19, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x24, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x17, 0x43, 0xe7 },
+ { 0x2b, 0x1a, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x28, 0x10, 0x42, 0xe7 },
+ { 0x2b, 0x17, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x28, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x21, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x26, 0x16, 0x43, 0xe5 },
+ { 0x29, 0x18, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x24, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x18, 0x43, 0xe7 },
+ { 0x2b, 0x1b, 0x43, 0xe7 }
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x27, 0x10, 0x42, 0xe7 },
+ { 0x2b, 0x18, 0x43, 0xe7 }
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x28, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct reg_sequence rk_udphy_24m_refclk_cfg[] = {
+ {0x0090, 0x68}, {0x0094, 0x68},
+ {0x0128, 0x24}, {0x012c, 0x44},
+ {0x0130, 0x3f}, {0x0134, 0x44},
+ {0x015c, 0xa9}, {0x0160, 0x71},
+ {0x0164, 0x71}, {0x0168, 0xa9},
+ {0x0174, 0xa9}, {0x0178, 0x71},
+ {0x017c, 0x71}, {0x0180, 0xa9},
+ {0x018c, 0x41}, {0x0190, 0x00},
+ {0x0194, 0x05}, {0x01ac, 0x2a},
+ {0x01b0, 0x17}, {0x01b4, 0x17},
+ {0x01b8, 0x2a}, {0x01c8, 0x04},
+ {0x01cc, 0x08}, {0x01d0, 0x08},
+ {0x01d4, 0x04}, {0x01d8, 0x20},
+ {0x01dc, 0x01}, {0x01e0, 0x09},
+ {0x01e4, 0x03}, {0x01f0, 0x29},
+ {0x01f4, 0x02}, {0x01f8, 0x02},
+ {0x01fc, 0x29}, {0x0208, 0x2a},
+ {0x020c, 0x17}, {0x0210, 0x17},
+ {0x0214, 0x2a}, {0x0224, 0x20},
+ {0x03f0, 0x0a}, {0x03f4, 0x07},
+ {0x03f8, 0x07}, {0x03fc, 0x0c},
+ {0x0404, 0x12}, {0x0408, 0x1a},
+ {0x040c, 0x1a}, {0x0410, 0x3f},
+ {0x0ce0, 0x68}, {0x0ce8, 0xd0},
+ {0x0cf0, 0x87}, {0x0cf8, 0x70},
+ {0x0d00, 0x70}, {0x0d08, 0xa9},
+ {0x1ce0, 0x68}, {0x1ce8, 0xd0},
+ {0x1cf0, 0x87}, {0x1cf8, 0x70},
+ {0x1d00, 0x70}, {0x1d08, 0xa9},
+ {0x0a3c, 0xd0}, {0x0a44, 0xd0},
+ {0x0a48, 0x01}, {0x0a4c, 0x0d},
+ {0x0a54, 0xe0}, {0x0a5c, 0xe0},
+ {0x0a64, 0xa8}, {0x1a3c, 0xd0},
+ {0x1a44, 0xd0}, {0x1a48, 0x01},
+ {0x1a4c, 0x0d}, {0x1a54, 0xe0},
+ {0x1a5c, 0xe0}, {0x1a64, 0xa8}
+};
+
+static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = {
+ {0x0830, 0x07}, {0x085c, 0x80},
+ {0x1030, 0x07}, {0x105c, 0x80},
+ {0x1830, 0x07}, {0x185c, 0x80},
+ {0x2030, 0x07}, {0x205c, 0x80},
+ {0x0228, 0x38}, {0x0104, 0x44},
+ {0x0248, 0x44}, {0x038c, 0x02},
+ {0x0878, 0x04}, {0x1878, 0x04},
+ {0x0898, 0x77}, {0x1898, 0x77},
+ {0x0054, 0x01}, {0x00e0, 0x38},
+ {0x0060, 0x24}, {0x0064, 0x77},
+ {0x0070, 0x76}, {0x0234, 0xe8},
+ {0x0af4, 0x15}, {0x1af4, 0x15},
+ {0x081c, 0xe5}, {0x181c, 0xe5},
+ {0x099c, 0x48}, {0x199c, 0x48},
+ {0x09a4, 0x07}, {0x09a8, 0x22},
+ {0x19a4, 0x07}, {0x19a8, 0x22},
+ {0x09b8, 0x3e}, {0x19b8, 0x3e},
+ {0x09e4, 0x02}, {0x19e4, 0x02},
+ {0x0a34, 0x1e}, {0x1a34, 0x1e},
+ {0x0a98, 0x2f}, {0x1a98, 0x2f},
+ {0x0c30, 0x0e}, {0x0c48, 0x06},
+ {0x1c30, 0x0e}, {0x1c48, 0x06},
+ {0x028c, 0x18}, {0x0af0, 0x00},
+ {0x1af0, 0x00}
+};
+
+static const struct reg_sequence rk_udphy_init_sequence[] = {
+ {0x0104, 0x44}, {0x0234, 0xe8},
+ {0x0248, 0x44}, {0x028c, 0x18},
+ {0x081c, 0xe5}, {0x0878, 0x00},
+ {0x0994, 0x1c}, {0x0af0, 0x00},
+ {0x181c, 0xe5}, {0x1878, 0x00},
+ {0x1994, 0x1c}, {0x1af0, 0x00},
+ {0x0428, 0x60}, {0x0d58, 0x33},
+ {0x1d58, 0x33}, {0x0990, 0x74},
+ {0x0d64, 0x17}, {0x08c8, 0x13},
+ {0x1990, 0x74}, {0x1d64, 0x17},
+ {0x18c8, 0x13}, {0x0d90, 0x40},
+ {0x0da8, 0x40}, {0x0dc0, 0x40},
+ {0x0dd8, 0x40}, {0x1d90, 0x40},
+ {0x1da8, 0x40}, {0x1dc0, 0x40},
+ {0x1dd8, 0x40}, {0x03c0, 0x30},
+ {0x03c4, 0x06}, {0x0e10, 0x00},
+ {0x1e10, 0x00}, {0x043c, 0x0f},
+ {0x0d2c, 0xff}, {0x1d2c, 0xff},
+ {0x0d34, 0x0f}, {0x1d34, 0x0f},
+ {0x08fc, 0x2a}, {0x0914, 0x28},
+ {0x0a30, 0x03}, {0x0e38, 0x03},
+ {0x0ecc, 0x27}, {0x0ed0, 0x22},
+ {0x0ed4, 0x26}, {0x18fc, 0x2a},
+ {0x1914, 0x28}, {0x1a30, 0x03},
+ {0x1e38, 0x03}, {0x1ecc, 0x27},
+ {0x1ed0, 0x22}, {0x1ed4, 0x26},
+ {0x0048, 0x0f}, {0x0060, 0x3c},
+ {0x0064, 0xf7}, {0x006c, 0x20},
+ {0x0070, 0x7d}, {0x0074, 0x68},
+ {0x0af4, 0x1a}, {0x1af4, 0x1a},
+ {0x0440, 0x3f}, {0x10d4, 0x08},
+ {0x20d4, 0x08}, {0x00d4, 0x30},
+ {0x0024, 0x6e},
+};
+
+static inline int rk_udphy_grfreg_write(struct regmap *base,
+ const struct rk_udphy_grf_reg *reg, bool en)
+{
+ return regmap_write(base, reg->offset, en ? reg->enable : reg->disable);
+}
+
+static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev)
+{
+ int i;
+
+ udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks);
+ if (udphy->num_clks < 1)
+ return -ENODEV;
+
+ /* used for configure phy reference clock frequency */
+ for (i = 0; i < udphy->num_clks; i++) {
+ if (!strncmp(udphy->clks[i].id, "refclk", 6)) {
+ udphy->refclk = udphy->clks[i].clk;
+ break;
+ }
+ }
+
+ if (!udphy->refclk)
+ return dev_err_probe(udphy->dev, -EINVAL, "no refclk found\n");
+
+ return 0;
+}
+
+static int rk_udphy_reset_assert_all(struct rk_udphy *udphy)
+{
+ return reset_control_bulk_assert(udphy->num_rsts, udphy->rsts);
+}
+
+static int rk_udphy_reset_deassert_all(struct rk_udphy *udphy)
+{
+ return reset_control_bulk_deassert(udphy->num_rsts, udphy->rsts);
+}
+
+static int rk_udphy_reset_deassert(struct rk_udphy *udphy, char *name)
+{
+ struct reset_control_bulk_data *list = udphy->rsts;
+ int idx;
+
+ for (idx = 0; idx < udphy->num_rsts; idx++) {
+ if (!strcmp(list[idx].id, name))
+ return reset_control_deassert(list[idx].rstc);
+ }
+
+ return -EINVAL;
+}
+
+static int rk_udphy_reset_init(struct rk_udphy *udphy, struct device *dev)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ int idx;
+
+ udphy->num_rsts = cfg->num_rsts;
+ udphy->rsts = devm_kcalloc(dev, udphy->num_rsts,
+ sizeof(*udphy->rsts), GFP_KERNEL);
+ if (!udphy->rsts)
+ return -ENOMEM;
+
+ for (idx = 0; idx < cfg->num_rsts; idx++)
+ udphy->rsts[idx].id = cfg->rst_list[idx];
+
+ return devm_reset_control_bulk_get_exclusive(dev, cfg->num_rsts,
+ udphy->rsts);
+}
+
+static void rk_udphy_u3_port_disable(struct rk_udphy *udphy, u8 disable)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ const struct rk_udphy_grf_reg *preg;
+
+ preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg;
+ rk_udphy_grfreg_write(udphy->usbgrf, preg, disable);
+}
+
+static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+
+ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable);
+ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable);
+}
+
+/*
+ * In usb/dp combo phy driver, here are 2 ways to mapping lanes.
+ *
+ * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping)
+ * ---------------------------------------------------------------------------
+ * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3
+ * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * C/E(Normal) dpln3 dpln2 dpln0 dpln1
+ * C/E(Flip ) dpln0 dpln1 dpln3 dpln2
+ * D/F(Normal) usbrx usbtx dpln0 dpln1
+ * D/F(Flip ) dpln0 dpln1 usbrx usbtx
+ * A(Normal ) dpln3 dpln1 dpln2 dpln0
+ * A(Flip ) dpln2 dpln0 dpln3 dpln1
+ * B(Normal ) usbrx usbtx dpln1 dpln0
+ * B(Flip ) dpln1 dpln0 usbrx usbtx
+ * ---------------------------------------------------------------------------
+ *
+ * 2 Mapping the lanes in dtsi
+ * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = <x x x x>;
+ * sample as follow:
+ * ---------------------------------------------------------------------------
+ * B11-B10 A2-A3 A11-A10 B2-B3
+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * <0 1 2 3> dpln0 dpln1 dpln2 dpln3
+ * <2 3 0 1> dpln2 dpln3 dpln0 dpln1
+ * ---------------------------------------------------------------------------
+ * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = <x x>;
+ * sample as follow:
+ * ---------------------------------------------------------------------------
+ * B11-B10 A2-A3 A11-A10 B2-B3
+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * <0 1> dpln0 dpln1 usbrx usbtx
+ * <2 3> usbrx usbtx dpln0 dpln1
+ * ---------------------------------------------------------------------------
+ */
+
+static void rk_udphy_dplane_select(struct rk_udphy *udphy)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ u32 value = 0;
+
+ switch (udphy->mode) {
+ case UDPHY_MODE_DP:
+ value |= 2 << udphy->dp_lane_sel[2] * 2;
+ value |= 3 << udphy->dp_lane_sel[3] * 2;
+ fallthrough;
+
+ case UDPHY_MODE_DP_USB:
+ value |= 0 << udphy->dp_lane_sel[0] * 2;
+ value |= 1 << udphy->dp_lane_sel[1] * 2;
+ break;
+
+ case UDPHY_MODE_USB:
+ break;
+
+ default:
+ break;
+ }
+
+ regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg,
+ ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) |
+ FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) |
+ FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value);
+}
+
+static int rk_udphy_dplane_get(struct rk_udphy *udphy)
+{
+ int dp_lanes;
+
+ switch (udphy->mode) {
+ case UDPHY_MODE_DP:
+ dp_lanes = 4;
+ break;
+
+ case UDPHY_MODE_DP_USB:
+ dp_lanes = 2;
+ break;
+
+ case UDPHY_MODE_USB:
+ default:
+ dp_lanes = 0;
+ break;
+ }
+
+ return dp_lanes;
+}
+
+static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes)
+{
+ u32 val = 0;
+ int i;
+
+ for (i = 0; i < dp_lanes; i++)
+ val |= BIT(udphy->dp_lane_sel[i]);
+
+ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL,
+ FIELD_PREP(CMN_DP_LANE_EN_ALL, val));
+
+ if (!dp_lanes)
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0));
+}
+
+static void rk_udphy_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+
+ udphy->dp_sink_hpd_sel = true;
+ udphy->dp_sink_hpd_cfg = hpd;
+
+ if (!udphy->dp_in_use)
+ return;
+
+ rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd);
+}
+
+static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
+{
+ if (udphy->flip) {
+ udphy->dp_lane_sel[0] = 0;
+ udphy->dp_lane_sel[1] = 1;
+ udphy->dp_lane_sel[2] = 3;
+ udphy->dp_lane_sel[3] = 2;
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
+ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT;
+ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT;
+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1);
+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0);
+ } else {
+ udphy->dp_lane_sel[0] = 2;
+ udphy->dp_lane_sel[1] = 3;
+ udphy->dp_lane_sel[2] = 1;
+ udphy->dp_lane_sel[3] = 0;
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL;
+ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL;
+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0);
+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1);
+ }
+
+ udphy->mode = UDPHY_MODE_DP_USB;
+}
+
+static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
+ enum typec_orientation orien)
+{
+ struct rk_udphy *udphy = typec_switch_get_drvdata(sw);
+
+ mutex_lock(&udphy->mutex);
+
+ if (orien == TYPEC_ORIENTATION_NONE) {
+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0);
+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0);
+ /* unattached */
+ rk_udphy_usb_bvalid_enable(udphy, false);
+ goto unlock_ret;
+ }
+
+ udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false;
+ rk_udphy_set_typec_default_mapping(udphy);
+ rk_udphy_usb_bvalid_enable(udphy, true);
+
+unlock_ret:
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static void rk_udphy_orien_switch_unregister(void *data)
+{
+ struct rk_udphy *udphy = data;
+
+ typec_switch_unregister(udphy->sw);
+}
+
+static int rk_udphy_setup_orien_switch(struct rk_udphy *udphy)
+{
+ struct typec_switch_desc sw_desc = { };
+
+ sw_desc.drvdata = udphy;
+ sw_desc.fwnode = dev_fwnode(udphy->dev);
+ sw_desc.set = rk_udphy_orien_sw_set;
+
+ udphy->sw = typec_switch_register(udphy->dev, &sw_desc);
+ if (IS_ERR(udphy->sw)) {
+ dev_err(udphy->dev, "Error register typec orientation switch: %ld\n",
+ PTR_ERR(udphy->sw));
+ return PTR_ERR(udphy->sw);
+ }
+
+ return devm_add_action_or_reset(udphy->dev,
+ rk_udphy_orien_switch_unregister, udphy);
+}
+
+static int rk_udphy_refclk_set(struct rk_udphy *udphy)
+{
+ unsigned long rate;
+ int ret;
+
+ /* configure phy reference clock */
+ rate = clk_get_rate(udphy->refclk);
+ dev_dbg(udphy->dev, "refclk freq %ld\n", rate);
+
+ switch (rate) {
+ case 24000000:
+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_24m_refclk_cfg,
+ ARRAY_SIZE(rk_udphy_24m_refclk_cfg));
+ if (ret)
+ return ret;
+ break;
+
+ case 26000000:
+ /* register default is 26MHz */
+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_26m_refclk_cfg,
+ ARRAY_SIZE(rk_udphy_26m_refclk_cfg));
+ if (ret)
+ return ret;
+ break;
+
+ default:
+ dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk_udphy_status_check(struct rk_udphy *udphy)
+{
+ unsigned int val;
+ int ret;
+
+ /* LCPLL check */
+ if (udphy->mode & UDPHY_MODE_USB) {
+ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET,
+ val, (val & CMN_ANA_LCPLL_AFC_DONE) &&
+ (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100000);
+ if (ret) {
+ dev_err(udphy->dev, "cmn ana lcpll lock timeout\n");
+ /*
+ * If earlier software (U-Boot) enabled USB once already
+ * the PLL may have problems locking on the first try.
+ * It will be successful on the second try, so for the
+ * time being a -EPROBE_DEFER will solve the issue.
+ *
+ * This requires further investigation to understand the
+ * root cause, especially considering that the driver is
+ * asserting all reset lines at probe time.
+ */
+ return -EPROBE_DEFER;
+ }
+
+ if (!udphy->flip) {
+ ret = regmap_read_poll_timeout(udphy->pma_regmap,
+ TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val,
+ val & TRSV_LN0_MON_RX_CDR_LOCK_DONE,
+ 200, 100000);
+ if (ret)
+ dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n");
+ } else {
+ ret = regmap_read_poll_timeout(udphy->pma_regmap,
+ TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val,
+ val & TRSV_LN2_MON_RX_CDR_LOCK_DONE,
+ 200, 100000);
+ if (ret)
+ dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n");
+ }
+ }
+
+ return 0;
+}
+
+static int rk_udphy_init(struct rk_udphy *udphy)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ int ret;
+
+ rk_udphy_reset_assert_all(udphy);
+ usleep_range(10000, 11000);
+
+ /* enable rx lfps for usb */
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true);
+
+ /* Step 1: power on pma and deassert apb rstn */
+ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true);
+
+ rk_udphy_reset_deassert(udphy, "pma_apb");
+ rk_udphy_reset_deassert(udphy, "pcs_apb");
+
+ /* Step 2: set init sequence and phy refclk */
+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_init_sequence,
+ ARRAY_SIZE(rk_udphy_init_sequence));
+ if (ret) {
+ dev_err(udphy->dev, "init sequence set error %d\n", ret);
+ goto assert_resets;
+ }
+
+ ret = rk_udphy_refclk_set(udphy);
+ if (ret) {
+ dev_err(udphy->dev, "refclk set error %d\n", ret);
+ goto assert_resets;
+ }
+
+ /* Step 3: configure lane mux */
+ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET,
+ CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL,
+ FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) |
+ FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) |
+ FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) |
+ FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) |
+ FIELD_PREP(CMN_DP_LANE_EN_ALL, 0));
+
+ /* Step 4: deassert init rstn and wait for 200ns from datasheet */
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_reset_deassert(udphy, "init");
+
+ if (udphy->mode & UDPHY_MODE_DP) {
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+ CMN_DP_INIT_RSTN,
+ FIELD_PREP(CMN_DP_INIT_RSTN, 0x1));
+ }
+
+ udelay(1);
+
+ /* Step 5: deassert cmn/lane rstn */
+ if (udphy->mode & UDPHY_MODE_USB) {
+ rk_udphy_reset_deassert(udphy, "cmn");
+ rk_udphy_reset_deassert(udphy, "lane");
+ }
+
+ /* Step 6: wait for lock done of pll */
+ ret = rk_udphy_status_check(udphy);
+ if (ret)
+ goto assert_resets;
+
+ return 0;
+
+assert_resets:
+ rk_udphy_reset_assert_all(udphy);
+ return ret;
+}
+
+static int rk_udphy_setup(struct rk_udphy *udphy)
+{
+ int ret;
+
+ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks);
+ if (ret) {
+ dev_err(udphy->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ ret = rk_udphy_init(udphy);
+ if (ret) {
+ dev_err(udphy->dev, "failed to init combophy\n");
+ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rk_udphy_disable(struct rk_udphy *udphy)
+{
+ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks);
+ rk_udphy_reset_assert_all(udphy);
+}
+
+static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy)
+{
+ int ret, i, num_lanes;
+
+ num_lanes = device_property_count_u32(udphy->dev, "rockchip,dp-lane-mux");
+ if (num_lanes < 0) {
+ dev_dbg(udphy->dev, "no dp-lane-mux, following dp alt mode\n");
+ udphy->mode = UDPHY_MODE_USB;
+ return 0;
+ }
+
+ if (num_lanes != 2 && num_lanes != 4)
+ return dev_err_probe(udphy->dev, -EINVAL,
+ "invalid number of lane mux\n");
+
+ ret = device_property_read_u32_array(udphy->dev, "rockchip,dp-lane-mux",
+ udphy->dp_lane_sel, num_lanes);
+ if (ret)
+ return dev_err_probe(udphy->dev, ret, "get dp lane mux failed\n");
+
+ for (i = 0; i < num_lanes; i++) {
+ int j;
+
+ if (udphy->dp_lane_sel[i] > 3)
+ return dev_err_probe(udphy->dev, -EINVAL,
+ "lane mux between 0 and 3, exceeding the range\n");
+
+ udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP;
+
+ for (j = i + 1; j < num_lanes; j++) {
+ if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j])
+ return dev_err_probe(udphy->dev, -EINVAL,
+ "set repeat lane mux value\n");
+ }
+ }
+
+ udphy->mode = UDPHY_MODE_DP;
+ if (num_lanes == 2) {
+ udphy->mode |= UDPHY_MODE_USB;
+ udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP);
+ }
+
+ return 0;
+}
+
+static int rk_udphy_get_initial_status(struct rk_udphy *udphy)
+{
+ int ret;
+ u32 value;
+
+ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks);
+ if (ret) {
+ dev_err(udphy->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ rk_udphy_reset_deassert_all(udphy);
+
+ regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value);
+ if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value))
+ udphy->status = UDPHY_MODE_DP;
+ else
+ rk_udphy_disable(udphy);
+
+ return 0;
+}
+
+static int rk_udphy_parse_dt(struct rk_udphy *udphy)
+{
+ struct device *dev = udphy->dev;
+ struct device_node *np = dev_of_node(dev);
+ enum usb_device_speed maximum_speed;
+ int ret;
+
+ udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf");
+ if (IS_ERR(udphy->u2phygrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->u2phygrf), "failed to get u2phy-grf\n");
+
+ udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf");
+ if (IS_ERR(udphy->udphygrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->udphygrf), "failed to get usbdpphy-grf\n");
+
+ udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf");
+ if (IS_ERR(udphy->usbgrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->usbgrf), "failed to get usb-grf\n");
+
+ udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf");
+ if (IS_ERR(udphy->vogrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->vogrf), "failed to get vo-grf\n");
+
+ ret = rk_udphy_parse_lane_mux_data(udphy);
+ if (ret)
+ return ret;
+
+ udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW);
+ if (IS_ERR(udphy->sbu1_dc_gpio))
+ return PTR_ERR(udphy->sbu1_dc_gpio);
+
+ udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW);
+ if (IS_ERR(udphy->sbu2_dc_gpio))
+ return PTR_ERR(udphy->sbu2_dc_gpio);
+
+ if (device_property_present(dev, "maximum-speed")) {
+ maximum_speed = usb_get_maximum_speed(dev);
+ udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false;
+ }
+
+ ret = rk_udphy_clk_init(udphy, dev);
+ if (ret)
+ return ret;
+
+ return rk_udphy_reset_init(udphy, dev);
+}
+
+static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
+{
+ int ret;
+
+ if (!(udphy->mode & mode)) {
+ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode);
+ return 0;
+ }
+
+ if (udphy->status == UDPHY_MODE_NONE) {
+ udphy->mode_change = false;
+ ret = rk_udphy_setup(udphy);
+ if (ret)
+ return ret;
+
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_u3_port_disable(udphy, false);
+ } else if (udphy->mode_change) {
+ udphy->mode_change = false;
+ udphy->status = UDPHY_MODE_NONE;
+ if (udphy->mode == UDPHY_MODE_DP)
+ rk_udphy_u3_port_disable(udphy, true);
+
+ rk_udphy_disable(udphy);
+ ret = rk_udphy_setup(udphy);
+ if (ret)
+ return ret;
+ }
+
+ udphy->status |= mode;
+
+ return 0;
+}
+
+static void rk_udphy_power_off(struct rk_udphy *udphy, u8 mode)
+{
+ if (!(udphy->mode & mode)) {
+ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode);
+ return;
+ }
+
+ if (!udphy->status)
+ return;
+
+ udphy->status &= ~mode;
+
+ if (udphy->status == UDPHY_MODE_NONE)
+ rk_udphy_disable(udphy);
+}
+
+static int rk_udphy_dp_phy_init(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+
+ udphy->dp_in_use = true;
+ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg);
+
+ mutex_unlock(&udphy->mutex);
+
+ return 0;
+}
+
+static int rk_udphy_dp_phy_exit(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+ udphy->dp_in_use = false;
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static int rk_udphy_dp_phy_power_on(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+ int ret, dp_lanes;
+
+ mutex_lock(&udphy->mutex);
+
+ dp_lanes = rk_udphy_dplane_get(udphy);
+ phy_set_bus_width(phy, dp_lanes);
+
+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP);
+ if (ret)
+ goto unlock;
+
+ rk_udphy_dplane_enable(udphy, dp_lanes);
+
+ rk_udphy_dplane_select(udphy);
+
+unlock:
+ mutex_unlock(&udphy->mutex);
+ /*
+ * If data send by aux channel too fast after phy power on,
+ * the aux may be not ready which will cause aux error. Adding
+ * delay to avoid this issue.
+ */
+ usleep_range(10000, 11000);
+ return ret;
+}
+
+static int rk_udphy_dp_phy_power_off(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+ rk_udphy_dplane_enable(udphy, 0);
+ rk_udphy_power_off(udphy, UDPHY_MODE_DP);
+ mutex_unlock(&udphy->mutex);
+
+ return 0;
+}
+
+static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
+{
+ switch (link_rate) {
+ case 1620:
+ case 2700:
+ case 5400:
+ case 8100:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
+ struct phy_configure_opts_dp *dp)
+{
+ int i, ret;
+
+ /* If changing link rate was required, verify it's supported. */
+ ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
+ if (ret)
+ return ret;
+
+ /* Verify lane count. */
+ switch (dp->lanes) {
+ case 1:
+ case 2:
+ case 4:
+ /* valid lane count. */
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * If changing voltages is required, check swing and pre-emphasis
+ * levels, per-lane.
+ */
+ if (dp->set_voltages) {
+ /* Lane count verified previously. */
+ for (i = 0; i < dp->lanes; i++) {
+ if (dp->voltage[i] > 3 || dp->pre[i] > 3)
+ return -EINVAL;
+
+ /*
+ * Sum of voltage swing and pre-emphasis levels cannot
+ * exceed 3.
+ */
+ if (dp->voltage[i] + dp->pre[i] > 3)
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void rk_udphy_dp_set_voltage(struct rk_udphy *udphy, u8 bw,
+ u32 voltage, u32 pre, u32 lane)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_ctrl)[4];
+ u32 offset = 0x800 * lane;
+ u32 val;
+
+ if (udphy->mux)
+ dp_ctrl = cfg->dp_tx_ctrl_cfg_typec[bw];
+ else
+ dp_ctrl = cfg->dp_tx_ctrl_cfg[bw];
+
+ val = dp_ctrl[voltage][pre].trsv_reg0204;
+ regmap_write(udphy->pma_regmap, 0x0810 + offset, val);
+
+ val = dp_ctrl[voltage][pre].trsv_reg0205;
+ regmap_write(udphy->pma_regmap, 0x0814 + offset, val);
+
+ val = dp_ctrl[voltage][pre].trsv_reg0206;
+ regmap_write(udphy->pma_regmap, 0x0818 + offset, val);
+
+ val = dp_ctrl[voltage][pre].trsv_reg0207;
+ regmap_write(udphy->pma_regmap, 0x081c + offset, val);
+}
+
+static int rk_udphy_dp_phy_configure(struct phy *phy,
+ union phy_configure_opts *opts)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+ struct phy_configure_opts_dp *dp = &opts->dp;
+ u32 i, val, lane;
+ int ret;
+
+ ret = rk_udphy_dp_phy_verify_config(udphy, dp);
+ if (ret)
+ return ret;
+
+ if (dp->set_rate) {
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0));
+
+ switch (dp->link_rate) {
+ case 1620:
+ udphy->bw = DP_BW_RBR;
+ break;
+
+ case 2700:
+ udphy->bw = DP_BW_HBR;
+ break;
+
+ case 5400:
+ udphy->bw = DP_BW_HBR2;
+ break;
+
+ case 8100:
+ udphy->bw = DP_BW_HBR3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW,
+ FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw));
+ regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN,
+ FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc));
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN,
+ FIELD_PREP(CMN_DP_CMN_RSTN, 0x1));
+
+ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val,
+ FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) &&
+ FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val),
+ 0, 1000);
+ if (ret) {
+ dev_err(udphy->dev, "ROPLL is not lock, set_rate failed\n");
+ return ret;
+ }
+ }
+
+ if (dp->set_voltages) {
+ for (i = 0; i < dp->lanes; i++) {
+ lane = udphy->dp_lane_sel[i];
+ switch (dp->link_rate) {
+ case 1620:
+ case 2700:
+ regmap_update_bits(udphy->pma_regmap,
+ TRSV_ANA_TX_CLK_OFFSET_N(lane),
+ LN_ANA_TX_SER_TXCLK_INV,
+ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV,
+ udphy->lane_mux_sel[lane]));
+ break;
+
+ case 5400:
+ case 8100:
+ regmap_update_bits(udphy->pma_regmap,
+ TRSV_ANA_TX_CLK_OFFSET_N(lane),
+ LN_ANA_TX_SER_TXCLK_INV,
+ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0));
+ break;
+ }
+
+ rk_udphy_dp_set_voltage(udphy, udphy->bw, dp->voltage[i],
+ dp->pre[i], lane);
+ }
+ }
+
+ return 0;
+}
+
+static const struct phy_ops rk_udphy_dp_phy_ops = {
+ .init = rk_udphy_dp_phy_init,
+ .exit = rk_udphy_dp_phy_exit,
+ .power_on = rk_udphy_dp_phy_power_on,
+ .power_off = rk_udphy_dp_phy_power_off,
+ .configure = rk_udphy_dp_phy_configure,
+ .owner = THIS_MODULE,
+};
+
+static int rk_udphy_usb3_phy_init(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+ int ret;
+
+ mutex_lock(&udphy->mutex);
+ /* DP only or high-speed, disable U3 port */
+ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) {
+ rk_udphy_u3_port_disable(udphy, true);
+ goto unlock;
+ }
+
+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB);
+
+unlock:
+ mutex_unlock(&udphy->mutex);
+ return ret;
+}
+
+static int rk_udphy_usb3_phy_exit(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+ /* DP only or high-speed */
+ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs)
+ goto unlock;
+
+ rk_udphy_power_off(udphy, UDPHY_MODE_USB);
+
+unlock:
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static const struct phy_ops rk_udphy_usb3_phy_ops = {
+ .init = rk_udphy_usb3_phy_init,
+ .exit = rk_udphy_usb3_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+{
+ struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
+ u8 mode;
+
+ mutex_lock(&udphy->mutex);
+
+ switch (state->mode) {
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ mode = UDPHY_MODE_DP;
+ break;
+
+ case TYPEC_DP_STATE_D:
+ default:
+ if (udphy->flip) {
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
+ } else {
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ }
+ mode = UDPHY_MODE_DP_USB;
+ break;
+ }
+
+ if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) {
+ struct typec_displayport_data *data = state->data;
+
+ if (!data) {
+ rk_udphy_dp_hpd_event_trigger(udphy, false);
+ } else if (data->status & DP_STATUS_IRQ_HPD) {
+ rk_udphy_dp_hpd_event_trigger(udphy, false);
+ usleep_range(750, 800);
+ rk_udphy_dp_hpd_event_trigger(udphy, true);
+ } else if (data->status & DP_STATUS_HPD_STATE) {
+ if (udphy->mode != mode) {
+ udphy->mode = mode;
+ udphy->mode_change = true;
+ }
+ rk_udphy_dp_hpd_event_trigger(udphy, true);
+ } else {
+ rk_udphy_dp_hpd_event_trigger(udphy, false);
+ }
+ }
+
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static void rk_udphy_typec_mux_unregister(void *data)
+{
+ struct rk_udphy *udphy = data;
+
+ typec_mux_unregister(udphy->mux);
+}
+
+static int rk_udphy_setup_typec_mux(struct rk_udphy *udphy)
+{
+ struct typec_mux_desc mux_desc = {};
+
+ mux_desc.drvdata = udphy;
+ mux_desc.fwnode = dev_fwnode(udphy->dev);
+ mux_desc.set = rk_udphy_typec_mux_set;
+
+ udphy->mux = typec_mux_register(udphy->dev, &mux_desc);
+ if (IS_ERR(udphy->mux)) {
+ dev_err(udphy->dev, "Error register typec mux: %ld\n",
+ PTR_ERR(udphy->mux));
+ return PTR_ERR(udphy->mux);
+ }
+
+ return devm_add_action_or_reset(udphy->dev, rk_udphy_typec_mux_unregister,
+ udphy);
+}
+
+static const struct regmap_config rk_udphy_pma_regmap_cfg = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+ .max_register = 0x20dc,
+};
+
+static struct phy *rk_udphy_phy_xlate(struct device *dev, const struct of_phandle_args *args)
+{
+ struct rk_udphy *udphy = dev_get_drvdata(dev);
+
+ if (args->args_count == 0)
+ return ERR_PTR(-EINVAL);
+
+ switch (args->args[0]) {
+ case PHY_TYPE_USB3:
+ return udphy->phy_u3;
+ case PHY_TYPE_DP:
+ return udphy->phy_dp;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static int rk_udphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct resource *res;
+ struct rk_udphy *udphy;
+ void __iomem *base;
+ int id, ret;
+
+ udphy = devm_kzalloc(dev, sizeof(*udphy), GFP_KERNEL);
+ if (!udphy)
+ return -ENOMEM;
+
+ udphy->cfgs = device_get_match_data(dev);
+ if (!udphy->cfgs)
+ return dev_err_probe(dev, -EINVAL, "missing match data\n");
+
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ /* find the phy-id from the io address */
+ udphy->id = -ENODEV;
+ for (id = 0; id < udphy->cfgs->num_phys; id++) {
+ if (res->start == udphy->cfgs->phy_ids[id]) {
+ udphy->id = id;
+ break;
+ }
+ }
+
+ if (udphy->id < 0)
+ return dev_err_probe(dev, -ENODEV, "no matching device found\n");
+
+ udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA,
+ &rk_udphy_pma_regmap_cfg);
+ if (IS_ERR(udphy->pma_regmap))
+ return PTR_ERR(udphy->pma_regmap);
+
+ udphy->dev = dev;
+ ret = rk_udphy_parse_dt(udphy);
+ if (ret)
+ return ret;
+
+ ret = rk_udphy_get_initial_status(udphy);
+ if (ret)
+ return ret;
+
+ mutex_init(&udphy->mutex);
+ platform_set_drvdata(pdev, udphy);
+
+ if (device_property_present(dev, "orientation-switch")) {
+ ret = rk_udphy_setup_orien_switch(udphy);
+ if (ret)
+ return ret;
+ }
+
+ if (device_property_present(dev, "mode-switch")) {
+ ret = rk_udphy_setup_typec_mux(udphy);
+ if (ret)
+ return ret;
+ }
+
+ udphy->phy_u3 = devm_phy_create(dev, dev->of_node, &rk_udphy_usb3_phy_ops);
+ if (IS_ERR(udphy->phy_u3)) {
+ ret = PTR_ERR(udphy->phy_u3);
+ return dev_err_probe(dev, ret, "failed to create USB3 phy\n");
+ }
+ phy_set_drvdata(udphy->phy_u3, udphy);
+
+ udphy->phy_dp = devm_phy_create(dev, dev->of_node, &rk_udphy_dp_phy_ops);
+ if (IS_ERR(udphy->phy_dp)) {
+ ret = PTR_ERR(udphy->phy_dp);
+ return dev_err_probe(dev, ret, "failed to create DP phy\n");
+ }
+ phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy));
+ udphy->phy_dp->attrs.max_link_rate = 8100;
+ phy_set_drvdata(udphy->phy_dp, udphy);
+
+ phy_provider = devm_of_phy_provider_register(dev, rk_udphy_phy_xlate);
+ if (IS_ERR(phy_provider)) {
+ ret = PTR_ERR(phy_provider);
+ return dev_err_probe(dev, ret, "failed to register phy provider\n");
+ }
+
+ return 0;
+}
+
+static int __maybe_unused rk_udphy_resume(struct device *dev)
+{
+ struct rk_udphy *udphy = dev_get_drvdata(dev);
+
+ if (udphy->dp_sink_hpd_sel)
+ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rk_udphy_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rk_udphy_resume)
+};
+
+static const char * const rk_udphy_rst_list[] = {
+ "init", "cmn", "lane", "pcs_apb", "pma_apb"
+};
+
+static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
+ .num_phys = 2,
+ .phy_ids = {
+ 0xfed80000,
+ 0xfed90000,
+ },
+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list),
+ .rst_list = rk_udphy_rst_list,
+ .grfcfg = {
+ /* u2phy-grf */
+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0008, 1, 0, 0x2, 0x3),
+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0010, 3, 2, 0x2, 0x3),
+
+ /* usb-grf */
+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x001c, 15, 0, 0x1100, 0x0188),
+ .usb3otg1_cfg = RK_UDPHY_GEN_GRF_REG(0x0034, 15, 0, 0x1100, 0x0188),
+
+ /* usbdpphy-grf */
+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1),
+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1),
+ },
+ .vogrfcfg = {
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0000,
+ },
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0008, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0008,
+ },
+ },
+ .dp_tx_ctrl_cfg = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+ .dp_tx_ctrl_cfg_typec = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+};
+
+static const struct of_device_id rk_udphy_dt_match[] = {
+ {
+ .compatible = "rockchip,rk3588-usbdp-phy",
+ .data = &rk3588_udphy_cfgs
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rk_udphy_dt_match);
+
+static struct platform_driver rk_udphy_driver = {
+ .probe = rk_udphy_probe,
+ .driver = {
+ .name = "rockchip-usbdp-phy",
+ .of_match_table = rk_udphy_dt_match,
+ .pm = &rk_udphy_pm_ops,
+ },
+};
+module_platform_driver(rk_udphy_driver);
+
+MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
+MODULE_AUTHOR("Zhang Yubing <yubing.zhang@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related
* [PATCH v5 06/10] arm64: dts: rockchip: add USBDP phys on rk3588
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Add both USB3-DisplayPort PHYs to RK3588 SoC DT.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588.dtsi | 52 +++++++++++++++++++
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 63 +++++++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi
index 5519c1430cb7..4fdd047c9eb9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi
@@ -17,6 +17,36 @@ pipe_phy1_grf: syscon@fd5c0000 {
reg = <0x0 0xfd5c0000 0x0 0x100>;
};
+ usbdpphy1_grf: syscon@fd5cc000 {
+ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon";
+ reg = <0x0 0xfd5cc000 0x0 0x4000>;
+ };
+
+ usb2phy1_grf: syscon@fd5d4000 {
+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd5d4000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u2phy1: usb2phy@4000 {
+ compatible = "rockchip,rk3588-usb2phy";
+ reg = <0x4000 0x10>;
+ #clock-cells = <0>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
+ clock-names = "phyclk";
+ clock-output-names = "usb480m_phy1";
+ interrupts = <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>;
+ reset-names = "phy", "apb";
+ status = "disabled";
+
+ u2phy1_otg: otg-port {
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
i2s8_8ch: i2s@fddc8000 {
compatible = "rockchip,rk3588-i2s-tdm";
reg = <0x0 0xfddc8000 0x0 0x1000>;
@@ -310,6 +340,28 @@ sata-port@0 {
};
};
+ usbdp_phy1: phy@fed90000 {
+ compatible = "rockchip,rk3588-usbdp-phy";
+ reg = <0x0 0xfed90000 0x0 0x10000>;
+ #phy-cells = <1>;
+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
+ <&cru CLK_USBDP_PHY1_IMMORTAL>,
+ <&cru PCLK_USBDPPHY1>,
+ <&u2phy1>;
+ clock-names = "refclk", "immortal", "pclk", "utmi";
+ resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>,
+ <&cru SRST_USBDP_COMBO_PHY1_CMN>,
+ <&cru SRST_USBDP_COMBO_PHY1_LANE>,
+ <&cru SRST_USBDP_COMBO_PHY1_PCS>,
+ <&cru SRST_P_USBDPPHY1>;
+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
+ rockchip,u2phy-grf = <&usb2phy1_grf>;
+ rockchip,usb-grf = <&usb_grf>;
+ rockchip,usbdpphy-grf = <&usbdpphy1_grf>;
+ rockchip,vo-grf = <&vo0_grf>;
+ status = "disabled";
+ };
+
combphy1_ps: phy@fee10000 {
compatible = "rockchip,rk3588-naneng-combphy";
reg = <0x0 0xfee10000 0x0 0x100>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 36e0f198f6bd..3a4f433cef5c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -516,12 +516,23 @@ vop_grf: syscon@fd5a4000 {
reg = <0x0 0xfd5a4000 0x0 0x2000>;
};
+ vo0_grf: syscon@fd5a6000 {
+ compatible = "rockchip,rk3588-vo-grf", "syscon";
+ reg = <0x0 0xfd5a6000 0x0 0x2000>;
+ clocks = <&cru PCLK_VO0GRF>;
+ };
+
vo1_grf: syscon@fd5a8000 {
compatible = "rockchip,rk3588-vo-grf", "syscon";
reg = <0x0 0xfd5a8000 0x0 0x100>;
clocks = <&cru PCLK_VO1GRF>;
};
+ usb_grf: syscon@fd5ac000 {
+ compatible = "rockchip,rk3588-usb-grf", "syscon";
+ reg = <0x0 0xfd5ac000 0x0 0x4000>;
+ };
+
php_grf: syscon@fd5b0000 {
compatible = "rockchip,rk3588-php-grf", "syscon";
reg = <0x0 0xfd5b0000 0x0 0x1000>;
@@ -537,6 +548,36 @@ pipe_phy2_grf: syscon@fd5c4000 {
reg = <0x0 0xfd5c4000 0x0 0x100>;
};
+ usbdpphy0_grf: syscon@fd5c8000 {
+ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon";
+ reg = <0x0 0xfd5c8000 0x0 0x4000>;
+ };
+
+ usb2phy0_grf: syscon@fd5d0000 {
+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd5d0000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u2phy0: usb2phy@0 {
+ compatible = "rockchip,rk3588-usb2phy";
+ reg = <0x0 0x10>;
+ #clock-cells = <0>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
+ clock-names = "phyclk";
+ clock-output-names = "usb480m_phy0";
+ interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>;
+ reset-names = "phy", "apb";
+ status = "disabled";
+
+ u2phy0_otg: otg-port {
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
usb2phy2_grf: syscon@fd5d8000 {
compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
reg = <0x0 0xfd5d8000 0x0 0x4000>;
@@ -2380,6 +2421,28 @@ hdptxphy_hdmi0: phy@fed60000 {
status = "disabled";
};
+ usbdp_phy0: phy@fed80000 {
+ compatible = "rockchip,rk3588-usbdp-phy";
+ reg = <0x0 0xfed80000 0x0 0x10000>;
+ #phy-cells = <1>;
+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
+ <&cru CLK_USBDP_PHY0_IMMORTAL>,
+ <&cru PCLK_USBDPPHY0>,
+ <&u2phy0>;
+ clock-names = "refclk", "immortal", "pclk", "utmi";
+ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>,
+ <&cru SRST_USBDP_COMBO_PHY0_CMN>,
+ <&cru SRST_USBDP_COMBO_PHY0_LANE>,
+ <&cru SRST_USBDP_COMBO_PHY0_PCS>,
+ <&cru SRST_P_USBDPPHY0>;
+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
+ rockchip,u2phy-grf = <&usb2phy0_grf>;
+ rockchip,usb-grf = <&usb_grf>;
+ rockchip,usbdpphy-grf = <&usbdpphy0_grf>;
+ rockchip,vo-grf = <&vo0_grf>;
+ status = "disabled";
+ };
+
combphy0_ps: phy@fee00000 {
compatible = "rockchip,rk3588-naneng-combphy";
reg = <0x0 0xfee00000 0x0 0x100>;
--
2.43.0
^ permalink raw reply related
* [PATCH v5 05/10] arm64: dts: rockchip: reorder usb2phy properties for rk3588
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Reorder common DT properties alphabetically for usb2phy, according
to latest DT style rules.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 5ed0d8c95427..36e0f198f6bd 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -546,13 +546,13 @@ usb2phy2_grf: syscon@fd5d8000 {
u2phy2: usb2phy@8000 {
compatible = "rockchip,rk3588-usb2phy";
reg = <0x8000 0x10>;
- interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH 0>;
- resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>;
- reset-names = "phy", "apb";
+ #clock-cells = <0>;
clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
clock-names = "phyclk";
clock-output-names = "usb480m_phy2";
- #clock-cells = <0>;
+ interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>;
+ reset-names = "phy", "apb";
status = "disabled";
u2phy2_host: host-port {
@@ -571,13 +571,13 @@ usb2phy3_grf: syscon@fd5dc000 {
u2phy3: usb2phy@c000 {
compatible = "rockchip,rk3588-usb2phy";
reg = <0xc000 0x10>;
- interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
- resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>;
- reset-names = "phy", "apb";
+ #clock-cells = <0>;
clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
clock-names = "phyclk";
clock-output-names = "usb480m_phy3";
- #clock-cells = <0>;
+ interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>;
+ reset-names = "phy", "apb";
status = "disabled";
u2phy3_host: host-port {
--
2.43.0
^ permalink raw reply related
* [PATCH v5 09/10] arm64: dts: rockchip: add upper USB3 port to rock-5a
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Enable full support (XHCI, EHCI, OHCI) for the upper USB3 port from
Radxa Rock 5 Model A. The lower one is already supported.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
.../boot/dts/rockchip/rk3588s-rock-5a.dts | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 00afb90d4eb1..b8ca3ee4c89a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -697,6 +697,14 @@ regulator-state-mem {
};
};
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
@@ -720,6 +728,11 @@ &uart2 {
status = "okay";
};
+&usbdp_phy0 {
+ status = "okay";
+ rockchip,dp-lane-mux = <2 3>;
+};
+
&usb_host0_ehci {
status = "okay";
pinctrl-names = "default";
@@ -730,6 +743,11 @@ &usb_host0_ohci {
status = "okay";
};
+&usb_host0_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
&usb_host1_ehci {
status = "okay";
};
--
2.43.0
^ permalink raw reply related
* [PATCH v5 07/10] arm64: dts: rockchip: add USB3 DRD controllers on rk3588
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Add both USB3 dual-role controllers to the RK3588 devicetree.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588.dtsi | 20 ++++++++++++++++++++
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 22 ++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi
index 4fdd047c9eb9..5984016b5f96 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi
@@ -7,6 +7,26 @@
#include "rk3588-pinctrl.dtsi"
/ {
+ usb_host1_xhci: usb@fc400000 {
+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
+ reg = <0x0 0xfc400000 0x0 0x400000>;
+ interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>,
+ <&cru ACLK_USB3OTG1>;
+ clock-names = "ref_clk", "suspend_clk", "bus_clk";
+ dr_mode = "otg";
+ phys = <&u2phy1_otg>, <&usbdp_phy1 PHY_TYPE_USB3>;
+ phy-names = "usb2-phy", "usb3-phy";
+ phy_type = "utmi_wide";
+ power-domains = <&power RK3588_PD_USB>;
+ resets = <&cru SRST_A_USB3OTG1>;
+ snps,dis_enblslpm_quirk;
+ snps,dis-u2-freeclk-exists-quirk;
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis-tx-ipgap-linecheck-quirk;
+ status = "disabled";
+ };
+
pcie30_phy_grf: syscon@fd5b8000 {
compatible = "rockchip,rk3588-pcie3-phy-grf", "syscon";
reg = <0x0 0xfd5b8000 0x0 0x10000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 3a4f433cef5c..a8f14a74d471 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -436,6 +436,28 @@ scmi_shmem: sram@0 {
};
};
+ usb_host0_xhci: usb@fc000000 {
+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
+ reg = <0x0 0xfc000000 0x0 0x400000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>,
+ <&cru ACLK_USB3OTG0>;
+ clock-names = "ref_clk", "suspend_clk", "bus_clk";
+ dr_mode = "otg";
+ phys = <&u2phy0_otg>, <&usbdp_phy0 PHY_TYPE_USB3>;
+ phy-names = "usb2-phy", "usb3-phy";
+ phy_type = "utmi_wide";
+ power-domains = <&power RK3588_PD_USB>;
+ resets = <&cru SRST_A_USB3OTG0>;
+ snps,dis_enblslpm_quirk;
+ snps,dis-u1-entry-quirk;
+ snps,dis-u2-entry-quirk;
+ snps,dis-u2-freeclk-exists-quirk;
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis-tx-ipgap-linecheck-quirk;
+ status = "disabled";
+ };
+
usb_host0_ehci: usb@fc800000 {
compatible = "rockchip,rk3588-ehci", "generic-ehci";
reg = <0x0 0xfc800000 0x0 0x40000>;
--
2.43.0
^ permalink raw reply related
* [PATCH v5 08/10] arm64: dts: rockchip: add USB3 to rk3588-evb1
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Add support for the board's USB3 connectors. It has 1x USB Type-A
and 1x USB Type-C.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
.../boot/dts/rockchip/rk3588-evb1-v10.dts | 143 ++++++++++++++++++
1 file changed, 143 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index de30c2632b8e..c3746d3a9b1d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/usb/pd.h>
#include "rk3588.dtsi"
/ {
@@ -224,6 +225,18 @@ vcc5v0_usb: vcc5v0-usb-regulator {
regulator-max-microvolt = <5000000>;
vin-supply = <&vcc5v0_usbdcin>;
};
+
+ vbus5v0_typec: vbus5v0-typec {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus5v0_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&vcc5v0_usb>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ };
};
&combphy0_ps {
@@ -284,6 +297,56 @@ &gmac0_rgmii_clk
&i2c2 {
status = "okay";
+ usbc0: usb-typec@22 {
+ compatible = "fcs,fusb302";
+ reg = <0x22>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbc0_int>;
+ vbus-supply = <&vbus5v0_typec>;
+ status = "okay";
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "source";
+ op-sink-microwatt = <1000000>;
+ sink-pdos =
+ <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
+ source-pdos =
+ <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usbc0_orien_sw: endpoint {
+ remote-endpoint = <&usbdp_phy0_orientation_switch>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ usbc0_role_sw: endpoint {
+ remote-endpoint = <&dwc3_0_role_switch>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ dp_altmode_mux: endpoint {
+ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
+ };
+ };
+ };
+ };
+ };
+
hym8563: rtc@51 {
compatible = "haoyu,hym8563";
reg = <0x51>;
@@ -410,6 +473,16 @@ vcc5v0_host_en: vcc5v0-host-en {
rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
+
+ usb-typec {
+ usbc0_int: usbc0-int {
+ rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
};
&pwm2 {
@@ -1041,6 +1114,22 @@ &sata0 {
status = "okay";
};
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
@@ -1079,3 +1168,57 @@ &usb_host1_ehci {
&usb_host1_ohci {
status = "okay";
};
+
+&usbdp_phy0 {
+ orientation-switch;
+ mode-switch;
+ sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbdp_phy0_orientation_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_orien_sw>;
+ };
+
+ usbdp_phy0_dp_altmode_mux: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dp_altmode_mux>;
+ };
+ };
+};
+
+&usbdp_phy1 {
+ /*
+ * USBDP PHY1 is wired to a female USB3 Type-A connector. Additionally
+ * the differential pairs 2+3 and the aux channel are wired to a RTD2166,
+ * which converts the DP signal into VGA. This is exposed on the
+ * board via a female VGA connector.
+ */
+ rockchip,dp-lane-mux = <2 3>;
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ dr_mode = "otg";
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dwc3_0_role_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_role_sw>;
+ };
+ };
+};
+
+&usb_host1_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v5 10/10] arm64: dts: rockchip: add lower USB3 port to rock-5b
From: Sebastian Reichel @ 2024-04-08 22:50 UTC (permalink / raw)
To: Heiko Stuebner, Vinod Koul, Kishon Vijay Abraham I,
linux-rockchip, linux-phy
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Wang,
Kever Yang, devicetree, linux-kernel, Sebastian Reichel, kernel
In-Reply-To: <20240408225109.128953-1-sebastian.reichel@collabora.com>
Enable full support (XHCI, EHCI, OHCI) for the lower USB3 port from
Radxa Rock 5 Model B. The upper one is already supported.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 1fe8b2a0ed75..bb09d0e1e20c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -742,6 +742,14 @@ &uart2 {
status = "okay";
};
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
@@ -761,6 +769,10 @@ &u2phy3_host {
status = "okay";
};
+&usbdp_phy1 {
+ status = "okay";
+};
+
&usb_host0_ehci {
status = "okay";
};
@@ -777,6 +789,11 @@ &usb_host1_ohci {
status = "okay";
};
+&usb_host1_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
&usb_host2_xhci {
status = "okay";
};
--
2.43.0
^ permalink raw reply related
* [RFC PATCH v1 0/2] fw_devlink overlay fix
From: Saravana Kannan @ 2024-04-08 23:13 UTC (permalink / raw)
To: Herve Codina, Geert Uytterhoeven
Cc: Saravana Kannan, Rob Herring, kernel-team, linux-kernel, imx,
linux-arm-kernel, linux-i2c, devicetree, linux-spi, linux-acpi
Don't bother review this patch. It needs to be refactored better once I
know it works.
Geert and Herve,
This patch serious should hopefully fix both of your use cases. Can you
please check to make sure the device links created to/from the overlay
devices are to/from the right ones?
I've only compile tested it. If I made some obvious mistake, feel free
to fix it and give it a shot.
Cc: Rob Herring <robh@kernel.org>
Thanks,
Saravana
Saravana Kannan (2):
Revert "treewide: Fix probing of devices in DT overlays"
of: dynamic: Fix probing of overlay devices
drivers/base/core.c | 10 ++++++++++
drivers/bus/imx-weim.c | 6 ------
drivers/i2c/i2c-core-of.c | 5 -----
drivers/of/dynamic.c | 9 ++++++++-
drivers/of/platform.c | 5 -----
drivers/spi/spi.c | 5 -----
include/linux/fwnode.h | 2 ++
7 files changed, 20 insertions(+), 22 deletions(-)
--
2.44.0.478.gd926399ef9-goog
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox