Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH] dt-bindings: watchdog: Convert Aspeed binding to DT schema
From: Zev Weiss @ 2024-04-02 23:30 UTC (permalink / raw)
  To: Andrew Jeffery
  Cc: wim, linux, robh, krzysztof.kozlowski+dt, conor+dt, joel,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240402120118.282035-1-andrew@codeconstruct.com.au>

On Tue, Apr 02, 2024 at 05:01:18AM PDT, Andrew Jeffery wrote:
>Squash warnings such as:
>
>```
>arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-galaxy100.dtb: /ahb/apb@1e600000/watchdog@1e785000: failed to match any schema with compatible: ['aspeed,ast2400-wdt']
>```
>
>Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
>---
> .../bindings/watchdog/aspeed,ast2400-wdt.yaml | 130 ++++++++++++++++++
> .../bindings/watchdog/aspeed-wdt.txt          |  73 ----------
> 2 files changed, 130 insertions(+), 73 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> delete mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>
>diff --git a/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
>new file mode 100644
>index 000000000000..10fcb50c4051
>--- /dev/null
>+++ b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
>@@ -0,0 +1,130 @@
>+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>+%YAML 1.2
>+---
>+$id: http://devicetree.org/schemas/watchdog/aspeed,ast2400-wdt.yaml#
>+$schema: http://devicetree.org/meta-schemas/core.yaml#
>+
>+title: Aspeed watchdog timer controllers
>+
>+maintainers:
>+  - Andrew Jeffery <andrew@codeconstruct.com.au>
>+
>+properties:
>+  compatible:
>+    enum:
>+      - aspeed,ast2400-wdt
>+      - aspeed,ast2500-wdt
>+      - aspeed,ast2600-wdt
>+
>+  reg:
>+    maxItems: 1
>+
>+  clocks: true
>+
>+  aspeed,reset-type:
>+    enum:
>+      - cpu
>+      - soc
>+      - system
>+      - none
>+    description: |
>+      Reset behaviour - The watchdog can be programmed to generate one of three
>+      different types of reset when a timeout occcurs.
>+
>+      Specifying 'cpu' will only reset the processor on a timeout event.
>+
>+      Specifying 'soc' will reset a configurable subset of the SoC's controllers

Might be worth clarifying that it's configurable only on ast2500 & 
ast2600, and which property (aspeed,reset-mask) configures it?

>+      on a timeout event. Controllers critical to the SoC's operation may remain untouched.
>+
>+      Specifying 'system' will reset all controllers on a timeout event, as if EXTRST had been asserted.
>+      Specifying "none" will cause the timeout event to have no reset effect.

Tiny nit: quoting (single vs. double) is slightly inconsistent between 
values here.

>+      Another watchdog engine on the chip must be used for chip reset operations.
>+
>+      The default reset type is "system"
>+
>+  aspeed,alt-boot:
>+    $ref: /schemas/types.yaml#/definitions/flag
>+    description: |
>+      Direct the watchdog to configure the SoC to boot from the alternative boot
>+      region if a timeout occurs.
>+
>+  aspeed,external-signal:
>+    $ref: /schemas/types.yaml#/definitions/flag
>+    description: |
>+      Assert the timeout event on an external signal pin associated with the
>+      watchdog controller instance. The pin must be muxed appropriately.
>+
>+  aspeed,ext-pulse-duration:
>+    $ref: /schemas/types.yaml#/definitions/uint32
>+    description: |
>+      The duration, in microseconds, of the pulse emitted on the external signal pin
>+
>+  aspeed,ext-push-pull:
>+    $ref: /schemas/types.yaml#/definitions/flag
>+    description: |
>+      If aspeed,external-signal is specified in the node, set the external
>+      signal pin's drive type to push-pull. If aspeed,ext-push-pull is not
>+      specified then the pin is configured as open-drain.
>+
>+  aspeed,ext-active-high:
>+    $ref: /schemas/types.yaml#/definitions/flag
>+    description: |
>+      If both aspeed,external-signal and aspeed,ext-push-pull are specified in
>+      the node, set the pulse polarity to active-high. If aspeed,ext-active-high
>+      is not specified then the pin is configured as active-low.
>+
>+  aspeed,reset-mask:
>+    $ref: /schemas/types.yaml#/definitions/uint32-array
>+    minItems: 1
>+    maxItems: 2
>+    description: |
>+      A bitmaks indicating which peripherals will be reset if the watchdog

Typo: "bitmask"

>+      timer expires. On AST2500 SoCs this should be a single word defined using
>+      the AST2500_WDT_RESET_* macros; on AST2600 SoCs this should be a two-word
>+      array with the first word defined using the AST2600_WDT_RESET1_* macros,
>+      and the second word defined using the AST2600_WDT_RESET2_* macros.
>+
>+required:
>+  - compatible
>+  - reg
>+
>+allOf:
>+  - if:
>+      anyOf:
>+        - required:
>+            - aspeed,ext-push-pull
>+        - required:
>+            - aspeed,ext-active-high
>+        - required:
>+            - aspeed,reset-mask
>+    then:
>+      properties:
>+        compatible:
>+          enum:
>+            - aspeed,ast2500-wdt
>+            - aspeed,ast2600-wdt
>+  - if:
>+      required:
>+        - aspeed,ext-active-high
>+    then:
>+      required:
>+        - aspeed,ext-push-pull
>+
>+additionalProperties: false
>+
>+examples:
>+  - |
>+    wdt1: watchdog@1e785000 {
>+        compatible = "aspeed,ast2400-wdt";
>+        reg = <0x1e785000 0x1c>;
>+        aspeed,reset-type = "system";
>+        aspeed,external-signal;
>+    };
>+  - |
>+    #include <dt-bindings/watchdog/aspeed-wdt.h>
>+    wdt2: watchdog@1e785040 {
>+        compatible = "aspeed,ast2600-wdt";
>+        reg = <0x1e785040 0x40>;
>+        aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
>+                            (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
>+    };
>diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>deleted file mode 100644
>index 3208adb3e52e..000000000000
>--- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>+++ /dev/null
>@@ -1,73 +0,0 @@
>-Aspeed Watchdog Timer
>-
>-Required properties:
>- - compatible: must be one of:
>-	- "aspeed,ast2400-wdt"
>-	- "aspeed,ast2500-wdt"
>-	- "aspeed,ast2600-wdt"
>-
>- - reg: physical base address of the controller and length of memory mapped
>-   region
>-
>-Optional properties:
>-
>- - aspeed,reset-type = "cpu|soc|system|none"
>-
>-   Reset behavior - Whenever a timeout occurs the watchdog can be programmed
>-   to generate one of three different, mutually exclusive, types of resets.
>-
>-   Type "none" can be specified to indicate that no resets are to be done.
>-   This is useful in situations where another watchdog engine on chip is
>-   to perform the reset.
>-
>-   If 'aspeed,reset-type=' is not specified the default is to enable system
>-   reset.
>-
>-   Reset types:
>-
>-        - cpu: Reset CPU on watchdog timeout
>-
>-        - soc: Reset 'System on Chip' on watchdog timeout
>-
>-        - system: Reset system on watchdog timeout
>-
>-        - none: No reset is performed on timeout. Assumes another watchdog
>-                engine is responsible for this.
>-
>- - aspeed,alt-boot:    If property is present then boot from alternate block.
>- - aspeed,external-signal: If property is present then signal is sent to
>-			external reset counter (only WDT1 and WDT2). If not
>-			specified no external signal is sent.
>- - aspeed,ext-pulse-duration: External signal pulse duration in microseconds
>-
>-Optional properties for AST2500-compatible watchdogs:
>- - aspeed,ext-push-pull: If aspeed,external-signal is present, set the pin's
>-			 drive type to push-pull. The default is open-drain.
>- - aspeed,ext-active-high: If aspeed,external-signal is present and and the pin
>-			   is configured as push-pull, then set the pulse
>-			   polarity to active-high. The default is active-low.
>-
>-Optional properties for AST2500- and AST2600-compatible watchdogs:
>- - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
>-		      the watchdog timer expires.  On AST2500 this should be a
>-		      single word defined using the AST2500_WDT_RESET_* macros;
>-		      on AST2600 this should be a two-word array with the first
>-		      word defined using the AST2600_WDT_RESET1_* macros and the
>-		      second word defined using the AST2600_WDT_RESET2_* macros.
>-
>-Examples:
>-
>-	wdt1: watchdog@1e785000 {
>-		compatible = "aspeed,ast2400-wdt";
>-		reg = <0x1e785000 0x1c>;
>-		aspeed,reset-type = "system";
>-		aspeed,external-signal;
>-	};
>-
>-	#include <dt-bindings/watchdog/aspeed-wdt.h>
>-	wdt2: watchdog@1e785040 {
>-		compatible = "aspeed,ast2600-wdt";
>-		reg = <0x1e785040 0x40>;
>-		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
>-				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
>-	};
>-- 
>2.39.2
>

^ permalink raw reply

* Re: [PATCH] dt-bindings: watchdog: Convert Aspeed binding to DT schema
From: Andrew Jeffery @ 2024-04-02 23:39 UTC (permalink / raw)
  To: Zev Weiss
  Cc: wim, linux, robh, krzysztof.kozlowski+dt, conor+dt, joel,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <65722a59-2e94-4616-81e1-835615b0e600@hatter.bewilderbeest.net>

On Tue, 2024-04-02 at 16:30 -0700, Zev Weiss wrote:
> On Tue, Apr 02, 2024 at 05:01:18AM PDT, Andrew Jeffery wrote:
> > Squash warnings such as:
> > 
> > ```
> > arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-galaxy100.dtb: /ahb/apb@1e600000/watchdog@1e785000: failed to match any schema with compatible: ['aspeed,ast2400-wdt']
> > ```
> > 
> > Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
> > ---
> > .../bindings/watchdog/aspeed,ast2400-wdt.yaml | 130 ++++++++++++++++++
> > .../bindings/watchdog/aspeed-wdt.txt          |  73 ----------
> > 2 files changed, 130 insertions(+), 73 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> > delete mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> > new file mode 100644
> > index 000000000000..10fcb50c4051
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> > @@ -0,0 +1,130 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/watchdog/aspeed,ast2400-wdt.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Aspeed watchdog timer controllers
> > +
> > +maintainers:
> > +  - Andrew Jeffery <andrew@codeconstruct.com.au>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - aspeed,ast2400-wdt
> > +      - aspeed,ast2500-wdt
> > +      - aspeed,ast2600-wdt
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks: true
> > +
> > +  aspeed,reset-type:
> > +    enum:
> > +      - cpu
> > +      - soc
> > +      - system
> > +      - none
> > +    description: |
> > +      Reset behaviour - The watchdog can be programmed to generate one of three
> > +      different types of reset when a timeout occcurs.
> > +
> > +      Specifying 'cpu' will only reset the processor on a timeout event.
> > +
> > +      Specifying 'soc' will reset a configurable subset of the SoC's controllers
> 
> Might be worth clarifying that it's configurable only on ast2500 & 
> ast2600, and which property (aspeed,reset-mask) configures it?

Good point, will do.

> 
> > +      on a timeout event. Controllers critical to the SoC's operation may remain untouched.
> > +
> > +      Specifying 'system' will reset all controllers on a timeout event, as if EXTRST had been asserted.
> > +      Specifying "none" will cause the timeout event to have no reset effect.
> 
> Tiny nit: quoting (single vs. double) is slightly inconsistent between 
> values here.

Ack.

> 
> > +      Another watchdog engine on the chip must be used for chip reset operations.
> > +
> > +      The default reset type is "system"
> > +
> > +  aspeed,alt-boot:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      Direct the watchdog to configure the SoC to boot from the alternative boot
> > +      region if a timeout occurs.
> > +
> > +  aspeed,external-signal:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      Assert the timeout event on an external signal pin associated with the
> > +      watchdog controller instance. The pin must be muxed appropriately.
> > +
> > +  aspeed,ext-pulse-duration:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: |
> > +      The duration, in microseconds, of the pulse emitted on the external signal pin
> > +
> > +  aspeed,ext-push-pull:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      If aspeed,external-signal is specified in the node, set the external
> > +      signal pin's drive type to push-pull. If aspeed,ext-push-pull is not
> > +      specified then the pin is configured as open-drain.
> > +
> > +  aspeed,ext-active-high:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      If both aspeed,external-signal and aspeed,ext-push-pull are specified in
> > +      the node, set the pulse polarity to active-high. If aspeed,ext-active-high
> > +      is not specified then the pin is configured as active-low.
> > +
> > +  aspeed,reset-mask:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    minItems: 1
> > +    maxItems: 2
> > +    description: |
> > +      A bitmaks indicating which peripherals will be reset if the watchdog
> 
> Typo: "bitmask"

Good catch.

Thanks,

Andrew

^ permalink raw reply

* Re: [PATCH v2 3/3] arm64: dts: qcom: msm8998: set qcom,no-msa-ready-indicator for wifi
From: Jeff Johnson @ 2024-04-02 23:32 UTC (permalink / raw)
  To: Alexey Minnekhanov, Dmitry Baryshkov, Marc Gonzalez, Kalle Valo
  Cc: Konrad Dybcio, Krzysztof Kozlowski, ath10k, wireless, DT, MSM,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pierre-Hugues Husson, Arnaud Vrac, Bjorn Andersson, Jami Kettunen,
	Jeffrey Hugo
In-Reply-To: <8ef4f56c-83a3-4b26-877e-f1c7a0307e98@postmarketos.org>

On 4/2/2024 11:25 AM, Alexey Minnekhanov wrote:
> 
> 
> On 02.04.2024 18:55, Dmitry Baryshkov wrote:
>> I'd say, we should take a step back and actually verify how this was
>> handled in the vendor kernel.
> 
> 
> AFAIK there is no such thing in vendor kernel driver for this, as
> this startup procedure is likely handled entirely in userspace in
> cnss_daemon.
> 

So now I'm looking at the cnss-daemon, and there it appears that MSA READY is
always expected to be received.

There is target-specific logic to set the flags sent to firmware:
	if (gdata->instance_id == ADRASTEA_ID) {
		req.msa_ready_enable_valid = 1;
		req.msa_ready_enable = 1;
	} else { /* All targets other than Adrastea */
		req.fw_mem_ready_enable_valid = 1;
		req.fw_mem_ready_enable = 1;
	}

Logic to set an internal flag if the message is received:
	case QMI_WLFW_MSA_READY_IND_V01:
		gdata->state |= CNSS_MSA_READY;

And Adrastea-specific logic to set that flag if it is set in a separate status
indicator:
static int wlfw_adrastea_init(struct wlfw_client_data *gdata)
[...]
	if (fw_status & QMI_WLFW_MSA_READY_V01) {
		wsvc_printf_dbg("MSA is ready");
		gdata->state |= CNSS_MSA_READY;
	}

So that flag is only set by receiving the QMI_WLFW_MSA_READY_IND_V01 message
or, only for Adrastea, if the response to wlfw_send_ind_register_req()
indicates MSA_READY

Later there is a wait for MSA_READY that has no conditions:
	while (!CNSS_IS_MSA_READY(gdata->state))

Truthfully this is code I've never had to deal with before, and I've struggled
to find developers who have the necessary background. The least disruptive
paths seem to either be the DT item or adding a new item for this in struct
ath10k_hw_params.

Kalle, do you have any different guidance?

^ permalink raw reply

* Re: [PATCH v18 2/9] usb: dwc3: core: Access XHCI address space temporarily to read port info
From: Thinh Nguyen @ 2024-04-02 23:32 UTC (permalink / raw)
  To: Krishna Kurapati
  Cc: Krzysztof Kozlowski, Rob Herring, Bjorn Andersson, Wesley Cheng,
	Konrad Dybcio, Greg Kroah-Hartman, Conor Dooley, Thinh Nguyen,
	Felipe Balbi, Johan Hovold, devicetree@vger.kernel.org,
	linux-arm-msm@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org, quic_ppratap@quicinc.com,
	quic_jackp@quicinc.com, Johan Hovold
In-Reply-To: <20240326113253.3010447-3-quic_kriskura@quicinc.com>

On Tue, Mar 26, 2024, Krishna Kurapati wrote:
> All DWC3 Multi Port controllers that exist today only support host mode.
> Temporarily map XHCI address space for host-only controllers and parse
> XHCI Extended Capabilities registers to read number of usb2 ports and
> usb3 ports present on multiport controller. Each USB Port is at least HS
> capable.
> 
> The port info for usb2 and usb3 phy are identified as num_usb2_ports
> and num_usb3_ports. The intention is as follows:
> 
> Wherever we need to perform phy operations like:
> 
> LOOP_OVER_NUMBER_OF_AVAILABLE_PORTS()
> {
> 	phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
> 	phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
> }
> 
> If number of usb2 ports is 3, loop can go from index 0-2 for
> usb2_generic_phy. If number of usb3-ports is 2, we don't know for sure,
> if the first 2 ports are SS capable or some other ports like (2 and 3)
> are SS capable. So instead, num_usb2_ports is used to loop around all
> phy's (both hs and ss) for performing phy operations. If any
> usb3_generic_phy turns out to be NULL, phy operation just bails out.
> num_usb3_ports is used to modify GUSB3PIPECTL registers while setting up
> phy's as we need to know how many SS capable ports are there for this.
> 
> Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
> Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
> ---
>  drivers/usb/dwc3/core.c | 61 +++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/dwc3/core.h |  5 ++++
>  2 files changed, 66 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 3e55838c0001..fab7664c12c0 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -39,6 +39,7 @@
>  #include "io.h"
>  
>  #include "debug.h"
> +#include "../host/xhci-ext-caps.h"
>  
>  #define DWC3_DEFAULT_AUTOSUSPEND_DELAY	5000 /* ms */
>  
> @@ -1879,10 +1880,56 @@ static int dwc3_get_clocks(struct dwc3 *dwc)
>  	return 0;
>  }
>  
> +static int dwc3_read_port_info(struct dwc3 *dwc)
> +{
> +	void __iomem *base;
> +	u8 major_revision;
> +	u32 offset;
> +	u32 val;
> +
> +	/*
> +	 * Remap xHCI address space to access XHCI ext cap regs since it is
> +	 * needed to get information on number of ports present.
> +	 */
> +	base = ioremap(dwc->xhci_resources[0].start,
> +		       resource_size(&dwc->xhci_resources[0]));
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);

Looks like you forgot to address some of the comments you said you'd
update previously if you submit a new version to the series.

[*] https://lore.kernel.org/linux-usb/af73110d-e13e-4183-af11-aed869ac0a31@quicinc.com/

BR,
Thinh

> +
> +	offset = 0;
> +	do {
> +		offset = xhci_find_next_ext_cap(base, offset,
> +						XHCI_EXT_CAPS_PROTOCOL);
> +		if (!offset)
> +			break;
> +
> +		val = readl(base + offset);
> +		major_revision = XHCI_EXT_PORT_MAJOR(val);
> +
> +		val = readl(base + offset + 0x08);
> +		if (major_revision == 0x03) {
> +			dwc->num_usb3_ports += XHCI_EXT_PORT_COUNT(val);
> +		} else if (major_revision <= 0x02) {
> +			dwc->num_usb2_ports += XHCI_EXT_PORT_COUNT(val);
> +		} else {
> +			dev_warn(dwc->dev, "unrecognized port major revision %d\n",
> +				 major_revision);
> +		}
> +	} while (1);
> +
> +	dev_dbg(dwc->dev, "hs-ports: %u ss-ports: %u\n",
> +		dwc->num_usb2_ports, dwc->num_usb3_ports);
> +
> +	iounmap(base);
> +
> +	return 0;
> +}
> +
>  static int dwc3_probe(struct platform_device *pdev)
>  {
>  	struct device		*dev = &pdev->dev;
>  	struct resource		*res, dwc_res;
> +	unsigned int		hw_mode;
>  	void __iomem		*regs;
>  	struct dwc3		*dwc;
>  	int			ret;
> @@ -1966,6 +2013,20 @@ static int dwc3_probe(struct platform_device *pdev)
>  			goto err_disable_clks;
>  	}
>  
> +	/*
> +	 * Currently only DWC3 controllers that are host-only capable
> +	 * can have more than one port.
> +	 */
> +	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
> +	if (hw_mode == DWC3_GHWPARAMS0_MODE_HOST) {
> +		ret = dwc3_read_port_info(dwc);
> +		if (ret)
> +			goto err_disable_clks;
> +	} else {
> +		dwc->num_usb2_ports = 1;
> +		dwc->num_usb3_ports = 1;
> +	}
> +
>  	spin_lock_init(&dwc->lock);
>  	mutex_init(&dwc->mutex);
>  
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index c07edfc954f7..40b00a895a2a 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1039,6 +1039,8 @@ struct dwc3_scratchpad_array {
>   * @usb3_phy: pointer to USB3 PHY
>   * @usb2_generic_phy: pointer to USB2 PHY
>   * @usb3_generic_phy: pointer to USB3 PHY
> + * @num_usb2_ports: number of USB2 ports
> + * @num_usb3_ports: number of USB3 ports
>   * @phys_ready: flag to indicate that PHYs are ready
>   * @ulpi: pointer to ulpi interface
>   * @ulpi_ready: flag to indicate that ULPI is initialized
> @@ -1186,6 +1188,9 @@ struct dwc3 {
>  	struct phy		*usb2_generic_phy;
>  	struct phy		*usb3_generic_phy;
>  
> +	u8			num_usb2_ports;
> +	u8			num_usb3_ports;
> +
>  	bool			phys_ready;
>  
>  	struct ulpi		*ulpi;
> -- 
> 2.34.1
> 

^ permalink raw reply

* Re: Fixing the devicetree of Rock 5 Model B (and possibly others)
From: Pratham Patel @ 2024-04-02 23:32 UTC (permalink / raw)
  To: Saravana Kannan, Dragan Simic
  Cc: sebastian.reichel, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, regressions, stable
In-Reply-To: <CAGETcx89V5CJrAq6XwuGiusQnkR804pTgYAtS94v7Q+v=Cv+qA@mail.gmail.com>

On Tue Apr 2, 2024 at 4:54 AM IST, Saravana Kannan wrote:
> On Sat, Mar 23, 2024 at 10:10 AM Dragan Simic <dsimic@manjaro.org> wrote:
> >
> > Hello Pratham,
> >
> > On 2024-03-23 18:02, Pratham Patel wrote:
> > > I looked at the patch and tried several things, neither resulted in
> > > anything that would point me to the core issue. Then I tried this:
> >
> > Could you, please, clarify a bit what's the actual issue you're
> > experiencing on your Rock 5B?
>
> Pratham, can you reply to this please? I don't really understand what
> your issue is for me to be able to help.

Hi,

I apologize for not replying. Somehow, I did not notice the reply from
Dragan. :(

Since this patch was applied, an issue in the Rock 5B's DT has been
unearthed which now results in the kernel being unable to boot properly.

Following is the relevant call trace from the UART capture:

[   21.595068] Call trace:
[   21.595288]  smp_call_function_many_cond+0x174/0x5f8
[   21.595728]  on_each_cpu_cond_mask+0x2c/0x40
[   21.596109]  cpuidle_register_driver+0x294/0x318
[   21.596524]  cpuidle_register+0x24/0x100
[   21.596875]  psci_cpuidle_probe+0x2e4/0x490
[   21.597247]  platform_probe+0x70/0xd0
[   21.597575]  really_probe+0x18c/0x3d8
[   21.597905]  __driver_probe_device+0x84/0x180
[   21.598294]  driver_probe_device+0x44/0x120
[   21.598669]  __device_attach_driver+0xc4/0x168
[   21.599063]  bus_for_each_drv+0x8c/0xf0
[   21.599408]  __device_attach+0xa4/0x1c0
[   21.599748]  device_initial_probe+0x1c/0x30
[   21.600118]  bus_probe_device+0xb4/0xc0
[   21.600462]  device_add+0x68c/0x888
[   21.600775]  platform_device_add+0x19c/0x270
[   21.601154]  platform_device_register_full+0xdc/0x178
[   21.601602]  psci_idle_init+0xa0/0xc8
[   21.601934]  do_one_initcall+0x60/0x290
[   21.602275]  kernel_init_freeable+0x20c/0x3e0
[   21.602664]  kernel_init+0x2c/0x1f8
[   21.602979]  ret_from_fork+0x10/0x20

> Also, can you give the output of <debugfs>/devices_deferred for the
> good vs bad case?

I can't provide you with requested output from the bad case, since the
kernel never moves past this to an initramfs rescue shell, but following
is the output from v6.8.1 (**with aforementioned patch reverted**).

# cat /sys/kernel/debug/devices_deferred
fc400000.usb    platform: wait for supplier /phy@fed90000/usb3-port
1-0022  typec_fusb302: cannot register tcpm port
fc000000.usb    platform: wait for supplier /phy@fed80000/usb3-port

It seems that v6.8.2 works _without needing to revert the patch_. I will
have to look into this sometime this week but it seems like
a8037ceb8964 (arm64: dts: rockchip: drop rockchip,trcm-sync-tx-only from rk3588 i2s)
seems to be the one that fixed the root issue. I will have to test it
sometime later this week.

 -- Pratham Patel


^ permalink raw reply

* Re: [PATCH v2 17/18] dt-bindings: pci: rockchip,rk3399-pcie-ep: Add ep-gpios property
From: Damien Le Moal @ 2024-04-02 23:23 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Manivannan Sadhasivam, Lorenzo Pieralisi,
	Kishon Vijay Abraham I, Shawn Lin, Krzysztof Wilczyński,
	Bjorn Helgaas, Heiko Stuebner, linux-pci, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, devicetree
  Cc: linux-rockchip, linux-arm-kernel, Rick Wertenbroek,
	Wilfred Mallawa, Niklas Cassel
In-Reply-To: <65b6329a-643c-4adf-9137-281964865d51@linaro.org>

On 4/3/24 03:10, Krzysztof Kozlowski wrote:
>> Thinking more about this, I think moving the ep-gpios description to the common
>> schema is the right thing to do given that the driver uses common code between
>> RC and EP to get that property. But if that is not acceptable, I can rename it
>> and get that property in the controller EP mode initialization code. That will
>> be add a little more code in the driver.
> 
> I forgot that it is actually the same hardware, so if host has
> "ep-gpios" already then EP mode should have the same property. Common
> schema is good idea.

OK. But this will conflict with the patch you sent to add the missing maxItem.
Is that patch a fix or is it for 6.10 ? If it is the former, I can wait for
next week to rebase on rc3 and avoid a conflict.

> 
> 
> Best regards,
> Krzysztof
> 

-- 
Damien Le Moal
Western Digital Research


^ permalink raw reply

* Re: [PATCH] dt-bindings: watchdog: Convert Aspeed binding to DT schema
From: Andrew Jeffery @ 2024-04-02 23:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: wim, linux, krzysztof.kozlowski+dt, conor+dt, joel, zev,
	linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
	linux-kernel
In-Reply-To: <20240402180718.GA358505-robh@kernel.org>

On Tue, 2024-04-02 at 13:07 -0500, Rob Herring wrote:
> On Tue, Apr 02, 2024 at 10:31:18PM +1030, Andrew Jeffery wrote:
> > Squash warnings such as:
> > 
> > ```
> > arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-galaxy100.dtb: /ahb/apb@1e600000/watchdog@1e785000: failed to match any schema with compatible: ['aspeed,ast2400-wdt']
> > ```
> > 
> > Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
> > ---
> >  .../bindings/watchdog/aspeed,ast2400-wdt.yaml | 130 ++++++++++++++++++
> >  .../bindings/watchdog/aspeed-wdt.txt          |  73 ----------
> >  2 files changed, 130 insertions(+), 73 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> >  delete mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> > new file mode 100644
> > index 000000000000..10fcb50c4051
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
> > @@ -0,0 +1,130 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/watchdog/aspeed,ast2400-wdt.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Aspeed watchdog timer controllers
> > +
> > +maintainers:
> > +  - Andrew Jeffery <andrew@codeconstruct.com.au>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - aspeed,ast2400-wdt
> > +      - aspeed,ast2500-wdt
> > +      - aspeed,ast2600-wdt
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks: true
> 
> # and order/function if more than 1 must be defined.

Ack.

> 
> Please note it was missing from the original binding in the commit 
> message.

Ack.

> 
> > +
> > +  aspeed,reset-type:
> > +    enum:
> > +      - cpu
> > +      - soc
> > +      - system
> > +      - none
> > +    description: |
> > +      Reset behaviour - The watchdog can be programmed to generate one of three
> > +      different types of reset when a timeout occcurs.
> > +
> > +      Specifying 'cpu' will only reset the processor on a timeout event.
> > +
> > +      Specifying 'soc' will reset a configurable subset of the SoC's controllers
> > +      on a timeout event. Controllers critical to the SoC's operation may remain untouched.
> > +
> > +      Specifying 'system' will reset all controllers on a timeout event, as if EXTRST had been asserted.
> > +      Specifying "none" will cause the timeout event to have no reset effect.
> > +      Another watchdog engine on the chip must be used for chip reset operations.
> > +
> > +      The default reset type is "system"
> 
> Express as schema:
> 
> default: system

Ack.

> 
> > +
> > +  aspeed,alt-boot:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> 
> Don't need '|' if no formatting to preserve.

Ack.

> 
> > +      Direct the watchdog to configure the SoC to boot from the alternative boot
> > +      region if a timeout occurs.
> > +
> > +  aspeed,external-signal:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      Assert the timeout event on an external signal pin associated with the
> > +      watchdog controller instance. The pin must be muxed appropriately.
> > +
> > +  aspeed,ext-pulse-duration:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: |
> > +      The duration, in microseconds, of the pulse emitted on the external signal pin
> 
> Wrap at <80. Period at end needed.

Ack for both.

> 
> > +
> > +  aspeed,ext-push-pull:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      If aspeed,external-signal is specified in the node, set the external
> > +      signal pin's drive type to push-pull. If aspeed,ext-push-pull is not
> > +      specified then the pin is configured as open-drain.
> > +
> > +  aspeed,ext-active-high:
> > +    $ref: /schemas/types.yaml#/definitions/flag
> > +    description: |
> > +      If both aspeed,external-signal and aspeed,ext-push-pull are specified in
> > +      the node, set the pulse polarity to active-high. If aspeed,ext-active-high
> > +      is not specified then the pin is configured as active-low.
> > +
> > +  aspeed,reset-mask:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    minItems: 1
> > +    maxItems: 2
> > +    description: |
> > +      A bitmaks indicating which peripherals will be reset if the watchdog
> > +      timer expires. On AST2500 SoCs this should be a single word defined using
> > +      the AST2500_WDT_RESET_* macros; on AST2600 SoCs this should be a two-word
> > +      array with the first word defined using the AST2600_WDT_RESET1_* macros,
> > +      and the second word defined using the AST2600_WDT_RESET2_* macros.
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +
> > +allOf:
> > +  - if:
> > +      anyOf:
> > +        - required:
> > +            - aspeed,ext-push-pull
> > +        - required:
> > +            - aspeed,ext-active-high
> > +        - required:
> > +            - aspeed,reset-mask
> > +    then:
> > +      properties:
> > +        compatible:
> > +          enum:
> > +            - aspeed,ast2500-wdt
> > +            - aspeed,ast2600-wdt
> > +  - if:
> > +      required:
> > +        - aspeed,ext-active-high
> > +    then:
> > +      required:
> > +        - aspeed,ext-push-pull
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    wdt1: watchdog@1e785000 {
> 
> Drop unused labels.

Ack.

Thanks for the feedback.

Andrew

^ permalink raw reply

* RE: [PATCH v2 4/4] drm: xlnx: zynqmp_dpsub: Add DP audio support
From: Klymenko, Anatoliy @ 2024-04-02 22:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Lars-Peter Clausen, Jaroslav Kysela, Takashi Iwai,
	Liam Girdwood, Mark Brown, Laurent Pinchart, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Daniel Vetter,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Simek, Michal
  Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Sagar, Vishal,
	Péter Ujfalusi
In-Reply-To: <20240319-xilinx-dp-audio-v2-4-92d6d3a7ca7e@ideasonboard.com>

Hi Tomi,

> -----Original Message-----
> From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> Sent: Tuesday, March 19, 2024 1:23 AM
> To: Lars-Peter Clausen <lars@metafoo.de>; Jaroslav Kysela
> <perex@perex.cz>; Takashi Iwai <tiwai@suse.com>; Liam Girdwood
> <lgirdwood@gmail.com>; Mark Brown <broonie@kernel.org>; Laurent
> Pinchart <laurent.pinchart@ideasonboard.com>; Maarten Lankhorst
> <maarten.lankhorst@linux.intel.com>; Maxime Ripard
> <mripard@kernel.org>; Thomas Zimmermann <tzimmermann@suse.de>;
> David Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Rob
> Herring <robh+dt@kernel.org>; Krzysztof Kozlowski
> <krzysztof.kozlowski+dt@linaro.org>; Conor Dooley
> <conor+dt@kernel.org>; Simek, Michal <michal.simek@amd.com>
> Cc: linux-sound@vger.kernel.org; linux-kernel@vger.kernel.org; dri-
> devel@lists.freedesktop.org; devicetree@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; Sagar, Vishal <vishal.sagar@amd.com>;
> Klymenko, Anatoliy <Anatoliy.Klymenko@amd.com>; Péter Ujfalusi
> <peter.ujfalusi@gmail.com>; Tomi Valkeinen
> <tomi.valkeinen@ideasonboard.com>
> Subject: [PATCH v2 4/4] drm: xlnx: zynqmp_dpsub: Add DP audio support
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> Add basic DisplayPort audio support.
> 
> Support non-live audio playback from two PCMs (DMA channels), and
> the
> volume control in the audio mixer.
> 
> As older dtb files may not have the audio DMA channels defined, the
> driver will just mark the audio support as disabled if the audio DMA is
> missing, and will continue with only display support.
> 
> Note: Reset doesn't seem to work (ZYNQMP_DISP_AUD_SOFT_RESET). If
> we do
> a reset, audio playback won't start again even if, afaics, we do set up
> all the necessary registers. So, at the moment, resetting the audio
> block in dp_dai_hw_free() is commented out.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

Tested-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com>

> ---
>  drivers/gpu/drm/xlnx/Kconfig            |   9 +
>  drivers/gpu/drm/xlnx/Makefile           |   1 +
>  drivers/gpu/drm/xlnx/zynqmp_disp.c      |  50 ----
>  drivers/gpu/drm/xlnx/zynqmp_disp_regs.h |   7 +-
>  drivers/gpu/drm/xlnx/zynqmp_dp.c        |  54 ++--
>  drivers/gpu/drm/xlnx/zynqmp_dp.h        |   7 +
>  drivers/gpu/drm/xlnx/zynqmp_dp_audio.c  | 461
> ++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/xlnx/zynqmp_dpsub.c     |  39 +--
>  drivers/gpu/drm/xlnx/zynqmp_dpsub.h     |  15 +-
>  9 files changed, 540 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xlnx/Kconfig b/drivers/gpu/drm/xlnx/Kconfig
> index 68ee897de9d7..d88cfbaf2863 100644
> --- a/drivers/gpu/drm/xlnx/Kconfig
> +++ b/drivers/gpu/drm/xlnx/Kconfig
> @@ -15,3 +15,12 @@ config DRM_ZYNQMP_DPSUB
>           This is a DRM/KMS driver for ZynqMP DisplayPort controller.
> Choose
>           this option if you have a Xilinx ZynqMP SoC with DisplayPort
>           subsystem.
> +
> +config DRM_ZYNQMP_DPSUB_AUDIO
> +       bool "ZynqMP DisplayPort Audio Support"
> +       depends on DRM_ZYNQMP_DPSUB
> +       depends on SND && SND_SOC
> +       select SND_SOC_GENERIC_DMAENGINE_PCM
> +       help
> +         Choose this option to enable DisplayPort audio support in the
> ZynqMP
> +         DisplayPort driver.
> diff --git a/drivers/gpu/drm/xlnx/Makefile
> b/drivers/gpu/drm/xlnx/Makefile
> index ea1422a39502..ab6e2ffd7e8d 100644
> --- a/drivers/gpu/drm/xlnx/Makefile
> +++ b/drivers/gpu/drm/xlnx/Makefile
> @@ -1,2 +1,3 @@
>  zynqmp-dpsub-y := zynqmp_disp.o zynqmp_dpsub.o zynqmp_dp.o
> zynqmp_kms.o
> +zynqmp-dpsub-$(CONFIG_DRM_ZYNQMP_DPSUB_AUDIO) +=
> zynqmp_dp_audio.o
>  obj-$(CONFIG_DRM_ZYNQMP_DPSUB) += zynqmp-dpsub.o
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c
> b/drivers/gpu/drm/xlnx/zynqmp_disp.c
> index 407bc07cec69..d2bf0e2d0135 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
> @@ -130,7 +130,6 @@ struct zynqmp_disp_layer {
>   * @dpsub: Display subsystem
>   * @blend.base: Register I/O base address for the blender
>   * @avbuf.base: Register I/O base address for the audio/video buffer
> manager
> - * @audio.base: Registers I/O base address for the audio mixer
>   * @layers: Layers (planes)
>   */
>  struct zynqmp_disp {
> @@ -143,9 +142,6 @@ struct zynqmp_disp {
>         struct {
>                 void __iomem *base;
>         } avbuf;
> -       struct {
> -               void __iomem *base;
> -       } audio;
> 
>         struct zynqmp_disp_layer layers[ZYNQMP_DPSUB_NUM_LAYERS];
>  };
> @@ -807,42 +803,6 @@ static void
> zynqmp_disp_blend_layer_disable(struct zynqmp_disp *disp,
>                                         csc_zero_offsets);
>  }
> 
> -/* -----------------------------------------------------------------------------
> - * Audio Mixer
> - */
> -
> -static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg,
> u32 val)
> -{
> -       writel(val, disp->audio.base + reg);
> -}
> -
> -/**
> - * zynqmp_disp_audio_enable - Enable the audio mixer
> - * @disp: Display controller
> - *
> - * Enable the audio mixer by de-asserting the soft reset. The audio state
> is set to
> - * default values by the reset, set the default mixer volume explicitly.
> - */
> -static void zynqmp_disp_audio_enable(struct zynqmp_disp *disp)
> -{
> -       /* Clear the audio soft reset register as it's an non-reset flop. */
> -       zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_SOFT_RESET,
> 0);
> -       zynqmp_disp_audio_write(disp,
> ZYNQMP_DISP_AUD_MIXER_VOLUME,
> -                               ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
> -}
> -
> -/**
> - * zynqmp_disp_audio_disable - Disable the audio mixer
> - * @disp: Display controller
> - *
> - * Disable the audio mixer by asserting its soft reset.
> - */
> -static void zynqmp_disp_audio_disable(struct zynqmp_disp *disp)
> -{
> -       zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_SOFT_RESET,
> -                               ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
> -}
> -
>  /* -----------------------------------------------------------------------------
>   * ZynqMP Display Layer & DRM Plane
>   */
> @@ -1169,8 +1129,6 @@ void zynqmp_disp_enable(struct zynqmp_disp
> *disp)
>                                              true);
>         zynqmp_disp_avbuf_enable_channels(disp);
>         zynqmp_disp_avbuf_enable_audio(disp);
> -
> -       zynqmp_disp_audio_enable(disp);
>  }
> 
>  /**
> @@ -1179,8 +1137,6 @@ void zynqmp_disp_enable(struct zynqmp_disp
> *disp)
>   */
>  void zynqmp_disp_disable(struct zynqmp_disp *disp)
>  {
> -       zynqmp_disp_audio_disable(disp);
> -
>         zynqmp_disp_avbuf_disable_audio(disp);
>         zynqmp_disp_avbuf_disable_channels(disp);
>         zynqmp_disp_avbuf_disable(disp);
> @@ -1249,12 +1205,6 @@ int zynqmp_disp_probe(struct
> zynqmp_dpsub *dpsub)
>                 goto error;
>         }
> 
> -       disp->audio.base =
> devm_platform_ioremap_resource_byname(pdev, "aud");
> -       if (IS_ERR(disp->audio.base)) {
> -               ret = PTR_ERR(disp->audio.base);
> -               goto error;
> -       }
> -
>         ret = zynqmp_disp_create_layers(disp);
>         if (ret)
>                 goto error;
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
> b/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
> index f92a006d5070..77cfa181a615 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
> +++ b/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
> @@ -177,12 +177,7 @@
>  #define ZYNQMP_DISP_AUD_MIXER_VOLUME                   0x0
>  #define ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE
> 0x20002000
>  #define ZYNQMP_DISP_AUD_MIXER_META_DATA                        0x4
> -#define ZYNQMP_DISP_AUD_CH_STATUS0                     0x8
> -#define ZYNQMP_DISP_AUD_CH_STATUS1                     0xc
> -#define ZYNQMP_DISP_AUD_CH_STATUS2                     0x10
> -#define ZYNQMP_DISP_AUD_CH_STATUS3                     0x14
> -#define ZYNQMP_DISP_AUD_CH_STATUS4                     0x18
> -#define ZYNQMP_DISP_AUD_CH_STATUS5                     0x1c
> +#define ZYNQMP_DISP_AUD_CH_STATUS(x)                   (0x8 + ((x) * 4))
>  #define ZYNQMP_DISP_AUD_CH_A_DATA0                     0x20
>  #define ZYNQMP_DISP_AUD_CH_A_DATA1                     0x24
>  #define ZYNQMP_DISP_AUD_CH_A_DATA2                     0x28
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> index a0606fab0e22..4383ea93423c 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> @@ -1227,7 +1227,6 @@ static void
> zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
>  {
>         u8 lane_cnt = dp->mode.lane_cnt;
>         u32 reg, wpl;
> -       unsigned int rate;
> 
>         zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HTOTAL, mode-
> >htotal);
>         zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VTOTAL, mode-
> >vtotal);
> @@ -1252,18 +1251,8 @@ static void
> zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
>                 reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
>                 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_N_VID,
> reg);
>                 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID,
> mode->clock);
> -               rate = zynqmp_dpsub_get_audio_clk_rate(dp->dpsub);
> -               if (rate) {
> -                       dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512);
> -                       zynqmp_dp_write(dp, ZYNQMP_DP_TX_N_AUD, reg);
> -                       zynqmp_dp_write(dp, ZYNQMP_DP_TX_M_AUD, rate /
> 1000);
> -               }
>         }
> 
> -       /* Only 2 channel audio is supported now */
> -       if (zynqmp_dpsub_audio_enabled(dp->dpsub))
> -               zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS, 1);
> -
>         zynqmp_dp_write(dp, ZYNQMP_DP_USER_PIX_WIDTH, 1);
> 
>         /* Translate to the native 16 bit datapath based on IP core spec */
> @@ -1272,6 +1261,44 @@ static void
> zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
>         zynqmp_dp_write(dp, ZYNQMP_DP_USER_DATA_COUNT_PER_LANE,
> reg);
>  }
> 
> +/* -----------------------------------------------------------------------------
> + * Audio
> + */
> +
> +void zynqmp_dp_audio_set_channels(struct zynqmp_dp *dp,
> +                                 unsigned int num_channels)
> +{
> +       zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS,
> num_channels - 1);
> +}
> +
> +void zynqmp_dp_audio_enable(struct zynqmp_dp *dp)
> +{
> +       zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 1);
> +}
> +
> +void zynqmp_dp_audio_disable(struct zynqmp_dp *dp)
> +{
> +       zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
> +}
> +
> +void zynqmp_dp_audio_write_n_m(struct zynqmp_dp *dp)
> +{
> +       unsigned int rate;
> +       u32 link_rate;
> +
> +       if (!(dp->config.misc0 &
> ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK))
> +               return;
> +
> +       link_rate = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
> +
> +       rate = clk_get_rate(dp->dpsub->aud_clk);
> +
> +       dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512);
> +
> +       zynqmp_dp_write(dp, ZYNQMP_DP_TX_N_AUD, link_rate);
> +       zynqmp_dp_write(dp, ZYNQMP_DP_TX_M_AUD, rate / 1000);
> +}
> +
>  /* -----------------------------------------------------------------------------
>   * DISP Configuration
>   */
> @@ -1445,8 +1472,7 @@ static void
> zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge,
>         /* Enable the encoder */
>         dp->enabled = true;
>         zynqmp_dp_update_misc(dp);
> -       if (zynqmp_dpsub_audio_enabled(dp->dpsub))
> -               zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 1);
> +
>         zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, 0);
>         if (dp->status == connector_status_connected) {
>                 for (i = 0; i < 3; i++) {
> @@ -1479,8 +1505,6 @@ static void
> zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
>         drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER,
> DP_SET_POWER_D3);
>         zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
>                         ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
> -       if (zynqmp_dpsub_audio_enabled(dp->dpsub))
> -               zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
> 
>         zynqmp_dp_disp_disable(dp, old_bridge_state);
> 
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.h
> b/drivers/gpu/drm/xlnx/zynqmp_dp.h
> index f077d7fbd0ad..a3257793e23a 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.h
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.h
> @@ -22,4 +22,11 @@ void zynqmp_dp_disable_vblank(struct
> zynqmp_dp *dp);
>  int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub);
>  void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub);
> 
> +void zynqmp_dp_audio_set_channels(struct zynqmp_dp *dp,
> +                                 unsigned int num_channels);
> +void zynqmp_dp_audio_enable(struct zynqmp_dp *dp);
> +void zynqmp_dp_audio_disable(struct zynqmp_dp *dp);
> +
> +void zynqmp_dp_audio_write_n_m(struct zynqmp_dp *dp);
> +
>  #endif /* _ZYNQMP_DP_H_ */
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c
> b/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c
> new file mode 100644
> index 000000000000..8fdab557f3b2
> --- /dev/null
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c
> @@ -0,0 +1,461 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * ZynqMP DisplayPort Subsystem Driver - Audio support
> + *
> + * Copyright (C) 2015 - 2023 Xilinx, Inc.
> + *
> + * Authors:
> + * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
> + * - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <sound/asoundef.h>
> +#include <sound/core.h>
> +#include <sound/dmaengine_pcm.h>
> +#include <sound/initval.h>
> +#include <sound/pcm.h>
> +#include <sound/soc.h>
> +#include <sound/tlv.h>
> +
> +#include "zynqmp_disp_regs.h"
> +#include "zynqmp_dp.h"
> +#include "zynqmp_dpsub.h"
> +
> +#define ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK 512
> +#define ZYNQMP_NUM_PCMS 2
> +
> +struct zynqmp_dpsub_audio {
> +       void __iomem *base;
> +
> +       struct snd_soc_card card;
> +
> +       const char *dai_name;
> +       const char *link_names[ZYNQMP_NUM_PCMS];
> +       const char *pcm_names[ZYNQMP_NUM_PCMS];
> +
> +       struct snd_soc_dai_driver dai_driver;
> +       struct snd_dmaengine_pcm_config pcm_configs[2];
> +
> +       struct snd_soc_dai_link links[ZYNQMP_NUM_PCMS];
> +
> +       struct {
> +               struct snd_soc_dai_link_component cpu;
> +               struct snd_soc_dai_link_component codec;
> +               struct snd_soc_dai_link_component platform;
> +       } components[ZYNQMP_NUM_PCMS];
> +
> +       /*
> +        * Protects:
> +        * - enabled_streams
> +        * - volumes
> +        * - current_rate
> +        */
> +       struct mutex enable_lock;
> +
> +       u32 enabled_streams;
> +       u32 current_rate;
> +
> +       u16 volumes[2];
> +};
> +
> +static const struct snd_pcm_hardware zynqmp_dp_pcm_hw = {
> +       .info = SNDRV_PCM_INFO_MMAP |
> +               SNDRV_PCM_INFO_MMAP_VALID |
> +               SNDRV_PCM_INFO_INTERLEAVED |
> +               SNDRV_PCM_INFO_PAUSE |
> +               SNDRV_PCM_INFO_RESUME |
> +               SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
> +
> +       .buffer_bytes_max       = 128 * 1024,
> +       .period_bytes_min       = 256,
> +       .period_bytes_max       = 1024 * 1024,
> +       .periods_min            = 2,
> +       .periods_max            = 256,
> +};
> +
> +static int zynqmp_dp_startup(struct snd_pcm_substream *substream)
> +{
> +       struct snd_pcm_runtime *runtime = substream->runtime;
> +
> +       snd_pcm_hw_constraint_step(runtime, 0,
> SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
> +                                  256);
> +
> +       return 0;
> +}
> +
> +static const struct snd_soc_ops zynqmp_dp_ops = {
> +       .startup = zynqmp_dp_startup,
> +};
> +
> +static void zynqmp_dp_audio_write(struct zynqmp_dpsub_audio
> *audio, int reg,
> +                                 u32 val)
> +{
> +       writel(val, audio->base + reg);
> +}
> +
> +static int dp_dai_hw_params(struct snd_pcm_substream *substream,
> +                           struct snd_pcm_hw_params *params,
> +                           struct snd_soc_dai *socdai)
> +{
> +       struct snd_soc_pcm_runtime *rtd =
> snd_soc_substream_to_rtd(substream);
> +       struct zynqmp_dpsub *dpsub =
> +               snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
> +       struct zynqmp_dpsub_audio *audio = dpsub->audio;
> +       int ret;
> +       u32 sample_rate;
> +       struct snd_aes_iec958 iec = { 0 };
> +       unsigned long rate;
> +
> +       sample_rate = params_rate(params);
> +
> +       if (sample_rate != 48000 && sample_rate != 44100)
> +               return -EINVAL;
> +
> +       mutex_lock(&audio->enable_lock);
> +
> +       if (audio->enabled_streams && audio->current_rate !=
> sample_rate) {
> +               dev_err(dpsub->dev,
> +                       "Can't change rate while playback enabled\n");
> +               ret = -EINVAL;
> +               goto err_unlock;
> +       }
> +
> +       if (audio->enabled_streams > 0) {
> +               /* Nothing to do */
> +               audio->enabled_streams++;
> +               mutex_unlock(&audio->enable_lock);
> +               return 0;
> +       }
> +
> +       audio->current_rate = sample_rate;
> +
> +       /* Note: clock rate can only be changed if the clock is disabled */
> +       ret = clk_set_rate(dpsub->aud_clk,
> +                          sample_rate *
> ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK);
> +       if (ret) {
> +               dev_err(dpsub->dev, "can't set aud_clk to %u err:%d\n",
> +                       sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK,
> ret);
> +               goto err_unlock;
> +       }
> +
> +       clk_prepare_enable(dpsub->aud_clk);
> +
> +       rate = clk_get_rate(dpsub->aud_clk);
> +
> +       /* Ignore some offset +- 10 */
> +       if (abs(sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK -
> rate) > 10) {
> +               dev_err(dpsub->dev, "aud_clk offset is higher: %ld\n",
> +                       sample_rate * ZYNQMP_DISP_AUD_SMPL_RATE_TO_CLK -
> rate);
> +               clk_disable_unprepare(dpsub->aud_clk);
> +               ret = -EINVAL;
> +               goto err_unlock;
> +       }
> +
> +       pm_runtime_get_sync(dpsub->dev);
> +
> +       zynqmp_dp_audio_write(audio,
> ZYNQMP_DISP_AUD_MIXER_VOLUME,
> +                             audio->volumes[0] | (audio->volumes[1] << 16));
> +
> +       /* Clear the audio soft reset register as it's an non-reset flop. */
> +       zynqmp_dp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET,
> 0);
> +
> +       /* Only 2 channel audio is supported now */
> +       zynqmp_dp_audio_set_channels(dpsub->dp, 2);
> +
> +       zynqmp_dp_audio_write_n_m(dpsub->dp);
> +
> +       /* Channel status */
> +
> +       if (sample_rate == 48000)
> +               iec.status[3] = IEC958_AES3_CON_FS_48000;
> +       else
> +               iec.status[3] = IEC958_AES3_CON_FS_44100;
> +
> +       for (unsigned int i = 0; i < AES_IEC958_STATUS_SIZE / 4; ++i) {
> +               u32 v;
> +
> +               v = (iec.status[(i * 4) + 0] << 0) |
> +                   (iec.status[(i * 4) + 1] << 8) |
> +                   (iec.status[(i * 4) + 2] << 16) |
> +                   (iec.status[(i * 4) + 3] << 24);
> +
> +               zynqmp_dp_audio_write(audio,
> ZYNQMP_DISP_AUD_CH_STATUS(i), v);
> +       }
> +
> +       zynqmp_dp_audio_enable(dpsub->dp);
> +
> +       audio->enabled_streams++;
> +
> +       mutex_unlock(&audio->enable_lock);
> +
> +       return 0;
> +
> +err_unlock:
> +       mutex_unlock(&audio->enable_lock);
> +       return ret;
> +}
> +
> +static int dp_dai_hw_free(struct snd_pcm_substream *substream,
> +                         struct snd_soc_dai *socdai)
> +{
> +       struct snd_soc_pcm_runtime *rtd =
> snd_soc_substream_to_rtd(substream);
> +       struct zynqmp_dpsub *dpsub =
> +               snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
> +       struct zynqmp_dpsub_audio *audio = dpsub->audio;
> +
> +       mutex_lock(&audio->enable_lock);
> +
> +       /* Nothing to do */
> +       if (audio->enabled_streams > 1) {
> +               audio->enabled_streams--;
> +               mutex_unlock(&audio->enable_lock);
> +               return 0;
> +       }
> +
> +       pm_runtime_put(dpsub->dev);
> +
> +       zynqmp_dp_audio_disable(dpsub->dp);
> +
> +       /*
> +        * Reset doesn't work. If we assert reset between audio stop and
> start,
> +        * the audio won't start anymore. Probably we are missing writing
> +        * some audio related registers. A/B buf?
> +        */
> +       /*
> +       zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET,
> +                               ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
> +       */
> +
> +       clk_disable_unprepare(dpsub->aud_clk);
> +
> +       audio->current_rate = 0;
> +       audio->enabled_streams--;
> +
> +       mutex_unlock(&audio->enable_lock);
> +
> +       return 0;
> +}
> +
> +static const struct snd_soc_dai_ops zynqmp_dp_dai_ops = {
> +       .hw_params      = dp_dai_hw_params,
> +       .hw_free        = dp_dai_hw_free,
> +};
> +
> +/*
> + * Min = 10 * log10(0x1 / 0x2000) = -39.13
> + * Max = 10 * log10(0xffffff / 0x2000) = 9.03
> + */
> +static const DECLARE_TLV_DB_RANGE(zynqmp_dp_tlv,
> +       0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, -3913, 1),
> +       0x1, 0x2000, TLV_DB_LINEAR_ITEM(-3913, 0),
> +       0x2000, 0xffff, TLV_DB_LINEAR_ITEM(0, 903),
> +);
> +
> +static const struct snd_kcontrol_new zynqmp_dp_snd_controls[] = {
> +       SOC_SINGLE_TLV("Input0 Playback Volume", 0,
> +                      0, 0xffff, 0, zynqmp_dp_tlv),
> +       SOC_SINGLE_TLV("Input1 Playback Volume", 1,
> +                      0, 0xffff, 0, zynqmp_dp_tlv),
> +};
> +
> +/*
> + * Note: these read & write functions only support two "registers", 0
> and 1,
> + * for volume 0 and 1. In other words, these are not real register
> read/write
> + * functions.
> + *
> + * This is done to support caching the volume value for the case where
> the
> + * hardware is not enabled, and also to support locking as volumes 0
> and 1
> + * are in the same register.
> + */
> +static unsigned int zynqmp_dp_dai_read(struct snd_soc_component
> *component,
> +                                      unsigned int reg)
> +{
> +       struct zynqmp_dpsub *dpsub = dev_get_drvdata(component->dev);
> +       struct zynqmp_dpsub_audio *audio = dpsub->audio;
> +
> +       return audio->volumes[reg];
> +}
> +
> +static int zynqmp_dp_dai_write(struct snd_soc_component
> *component,
> +                              unsigned int reg, unsigned int val)
> +{
> +       struct zynqmp_dpsub *dpsub = dev_get_drvdata(component->dev);
> +       struct zynqmp_dpsub_audio *audio = dpsub->audio;
> +
> +       mutex_lock(&audio->enable_lock);
> +
> +       audio->volumes[reg] = val;
> +
> +       if (audio->enabled_streams)
> +               zynqmp_dp_audio_write(audio,
> ZYNQMP_DISP_AUD_MIXER_VOLUME,
> +                                     audio->volumes[0] |
> +                                     (audio->volumes[1] << 16));
> +
> +       mutex_unlock(&audio->enable_lock);
> +
> +       return 0;
> +}
> +
> +static const struct snd_soc_component_driver
> zynqmp_dp_component_driver = {
> +       .idle_bias_on           = 1,
> +       .use_pmdown_time        = 1,
> +       .endianness             = 1,
> +       .controls               = zynqmp_dp_snd_controls,
> +       .num_controls           = ARRAY_SIZE(zynqmp_dp_snd_controls),
> +       .read                   = zynqmp_dp_dai_read,
> +       .write                  = zynqmp_dp_dai_write,
> +};
> +
> +int zynqmp_audio_init(struct zynqmp_dpsub *dpsub)
> +{
> +       struct platform_device *pdev = to_platform_device(dpsub->dev);
> +       struct device *dev = dpsub->dev;
> +       struct zynqmp_dpsub_audio *audio;
> +       struct snd_soc_card *card;
> +       void *dev_data;
> +       int ret;
> +
> +       if (!dpsub->aud_clk)
> +               return 0;
> +
> +       audio = devm_kzalloc(dev, sizeof(*audio), GFP_KERNEL);
> +       if (!audio)
> +               return -ENOMEM;
> +
> +       dpsub->audio = audio;
> +
> +       mutex_init(&audio->enable_lock);
> +
> +       /* 0x2000 is the zero level, no change */
> +       audio->volumes[0] = 0x2000;
> +       audio->volumes[1] = 0x2000;
> +
> +       audio->dai_name = devm_kasprintf(dev, GFP_KERNEL,
> +                                        "%s-dai", dev_name(dev));
> +
> +       for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) {
> +               audio->link_names[i] = devm_kasprintf(dev, GFP_KERNEL,
> +                                                     "%s-dp-%u", dev_name(dev), i);
> +               audio->pcm_names[i] = devm_kasprintf(dev, GFP_KERNEL,
> +                                                    "%s-pcm-%u", dev_name(dev), i);
> +       }
> +
> +       audio->base = devm_platform_ioremap_resource_byname(pdev,
> "aud");
> +       if (IS_ERR(audio->base))
> +               return PTR_ERR(audio->base);
> +
> +       /* Create CPU DAI */
> +
> +       audio->dai_driver = (struct snd_soc_dai_driver) {
> +               .name           = audio->dai_name,
> +               .ops            = &zynqmp_dp_dai_ops,
> +               .playback       = {
> +                       .channels_min   = 2,
> +                       .channels_max   = 2,
> +                       .rates          = SNDRV_PCM_RATE_44100 |
> SNDRV_PCM_RATE_48000,
> +                       .formats        = SNDRV_PCM_FMTBIT_S16_LE,
> +               },
> +       };
> +
> +       ret = devm_snd_soc_register_component(dev,
> &zynqmp_dp_component_driver,
> +                                             &audio->dai_driver, 1);
> +       if (ret) {
> +               dev_err(dev, "Failed to register CPU DAI\n");
> +               return ret;
> +       }
> +
> +       /* Create PCMs */
> +
> +       for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) {
> +               struct snd_dmaengine_pcm_config *pcm_config =
> +                       &audio->pcm_configs[i];
> +
> +               *pcm_config = (struct snd_dmaengine_pcm_config){
> +                       .name = audio->pcm_names[i],
> +                       .pcm_hardware = &zynqmp_dp_pcm_hw,
> +                       .prealloc_buffer_size = 64 * 1024,
> +                       .chan_names[SNDRV_PCM_STREAM_PLAYBACK] =
> +                               i == 0 ? "aud0" : "aud1",
> +               };
> +
> +               ret = devm_snd_dmaengine_pcm_register(dev, pcm_config, 0);
> +               if (ret) {
> +                       dev_err(dev, "Failed to register PCM %u\n", i);
> +                       return ret;
> +               }
> +       }
> +
> +       /* Create card */
> +
> +       card = &audio->card;
> +       card->name = "DisplayPort";
> +       card->long_name = "DisplayPort Monitor";
> +       card->driver_name = "zynqmp_dpsub";
> +       card->dev = dev;
> +       card->owner = THIS_MODULE;
> +       card->num_links = ZYNQMP_NUM_PCMS;
> +       card->dai_link = audio->links;
> +
> +       for (unsigned int i = 0; i < ZYNQMP_NUM_PCMS; ++i) {
> +               struct snd_soc_dai_link *link = &card->dai_link[i];
> +
> +               link->ops = &zynqmp_dp_ops;
> +
> +               link->name = audio->link_names[i];
> +               link->stream_name = audio->link_names[i];
> +
> +               link->cpus = &audio->components[i].cpu;
> +               link->num_cpus = 1;
> +               link->cpus[0].dai_name = audio->dai_name;
> +
> +               link->codecs = &audio->components[i].codec;
> +               link->num_codecs = 1;
> +               link->codecs[0].name = "snd-soc-dummy";
> +               link->codecs[0].dai_name = "snd-soc-dummy-dai";
> +
> +               link->platforms = &audio->components[i].platform;
> +               link->num_platforms = 1;
> +               link->platforms[0].name = audio->pcm_names[i];
> +       }
> +
> +       /*
> +        * HACK: devm_snd_soc_register_card() overwrites current drvdata
> +        * so we need to hack it back.
> +        */
> +       dev_data = dev_get_drvdata(dev);
> +       ret = devm_snd_soc_register_card(dev, card);
> +       dev_set_drvdata(dev, dev_data);
> +       if (ret) {
> +               /*
> +                * As older dtbs may not have the audio channel dmas
> defined,
> +                * instead of returning an error here we'll continue and just
> +                * mark the audio as disabled.
> +                */
> +               dev_err(dev, "Failed to register sound card, disabling audio
> support\n");
> +
> +               devm_kfree(dev, audio);
> +               dpsub->audio = NULL;
> +
> +               return 0;
> +       }
> +
> +       return 0;
> +}
> +
> +void zynqmp_audio_uninit(struct zynqmp_dpsub *dpsub)
> +{
> +       struct zynqmp_dpsub_audio *audio = dpsub->audio;
> +
> +       if (!audio)
> +               return;
> +
> +       if (!dpsub->aud_clk)
> +               return;
> +
> +       mutex_destroy(&audio->enable_lock);
> +}
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> index 88eb33acd5f0..2b7dd38d3def 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> @@ -56,36 +56,6 @@ static const struct dev_pm_ops
> zynqmp_dpsub_pm_ops = {
>         SET_SYSTEM_SLEEP_PM_OPS(zynqmp_dpsub_suspend,
> zynqmp_dpsub_resume)
>  };
> 
> -/* -----------------------------------------------------------------------------
> - * DPSUB Configuration
> - */
> -
> -/**
> - * zynqmp_dpsub_audio_enabled - If the audio is enabled
> - * @dpsub: DisplayPort subsystem
> - *
> - * Return if the audio is enabled depending on the audio clock.
> - *
> - * Return: true if audio is enabled, or false.
> - */
> -bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub)
> -{
> -       return !!dpsub->aud_clk;
> -}
> -
> -/**
> - * zynqmp_dpsub_get_audio_clk_rate - Get the current audio clock rate
> - * @dpsub: DisplayPort subsystem
> - *
> - * Return: the current audio clock rate.
> - */
> -unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub
> *dpsub)
> -{
> -       if (zynqmp_dpsub_audio_enabled(dpsub))
> -               return 0;
> -       return clk_get_rate(dpsub->aud_clk);
> -}
> -
>  /* -----------------------------------------------------------------------------
>   * Probe & Remove
>   */
> @@ -264,10 +234,17 @@ static int zynqmp_dpsub_probe(struct
> platform_device *pdev)
>                 drm_bridge_add(dpsub->bridge);
>         }
> 
> +       ret = zynqmp_audio_init(dpsub);
> +       if (ret)
> +               goto err_drm_cleanup;
> +
>         dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver
> probed");
> 
>         return 0;
> 
> +err_drm_cleanup:
> +       if (dpsub->drm)
> +               zynqmp_dpsub_drm_cleanup(dpsub);
>  err_disp:
>         zynqmp_disp_remove(dpsub);
>  err_dp:
> @@ -286,6 +263,8 @@ static void zynqmp_dpsub_remove(struct
> platform_device *pdev)
>  {
>         struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
> 
> +       zynqmp_audio_uninit(dpsub);
> +
>         if (dpsub->drm)
>                 zynqmp_dpsub_drm_cleanup(dpsub);
>         else
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
> b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
> index 09ea01878f2a..9951d0176476 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
> @@ -12,6 +12,8 @@
>  #ifndef _ZYNQMP_DPSUB_H_
>  #define _ZYNQMP_DPSUB_H_
> 
> +#include <linux/types.h>
> +
>  struct clk;
>  struct device;
>  struct drm_bridge;
> @@ -39,6 +41,8 @@ enum zynqmp_dpsub_format {
>         ZYNQMP_DPSUB_FORMAT_YONLY,
>  };
> 
> +struct zynqmp_dpsub_audio;
> +
>  /**
>   * struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem
>   * @dev: The physical device
> @@ -76,10 +80,17 @@ struct zynqmp_dpsub {
>         struct zynqmp_dp *dp;
> 
>         unsigned int dma_align;
> +
> +       struct zynqmp_dpsub_audio *audio;
>  };
> 
> -bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub);
> -unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub
> *dpsub);
> +#ifdef CONFIG_DRM_ZYNQMP_DPSUB_AUDIO
> +int zynqmp_audio_init(struct zynqmp_dpsub *dpsub);
> +void zynqmp_audio_uninit(struct zynqmp_dpsub *dpsub);
> +#else
> +static inline int zynqmp_audio_init(struct zynqmp_dpsub *dpsub) {
> return 0; }
> +static inline void zynqmp_audio_uninit(struct zynqmp_dpsub *dpsub) {
> }
> +#endif
> 
>  void zynqmp_dpsub_release(struct zynqmp_dpsub *dpsub);
> 
> 
> --
> 2.34.1

Thank you,
Anatoliy


^ permalink raw reply

* Re: [PATCH v9 00/10] media: Add driver for the Raspberry Pi <5 CSI-2 receiver
From: Florian Fainelli @ 2024-04-02 21:34 UTC (permalink / raw)
  To: Laurent Pinchart, Florian Fainelli
  Cc: linux-media, Dave Stevenson, David Plowman, Jean-Michel Hautbois,
	Hans Verkuil, Naushir Patuck, Sakari Ailus, kernel-list,
	linux-rpi-kernel, Ray Jui, Scott Branden,
	bcm-kernel-feedback-list, Conor Dooley, Krzysztof Kozlowski,
	Rob Herring, devicetree
In-Reply-To: <20240402205310.GC16740@pendragon.ideasonboard.com>

On 4/2/24 13:53, Laurent Pinchart wrote:
> On Tue, Apr 02, 2024 at 01:46:44PM -0700, Florian Fainelli wrote:
>> Hello Laurent,
>>
>> On 4/1/24 17:11, Laurent Pinchart wrote:
>>> Hi Florian,
>>>
>>> I think patches 05/10 ("ARM: dts: bcm2835-rpi: Move duplicate
>>> firmware-clocks to bcm2835-rpi.dtsi"), 07/10 ("ARM: dts: bcm2711-rpi:
>>> Add pinctrl-based multiplexing for I2C0"), 08/10 ("ARM: dts:
>>> bcm2711-rpi-cm4-io: Add RTC on I2C0") and 09/10 ("ARM: dts:
>>> bcm2711-rpi-4-b: Add CAM1 regulator") are ready for you to merge. This
>>> would help reducing further iterations of this series.
>>
>> I could not locate the base commit this series was posted against
>> (58abf3672a73558149fa567eafff8d5b1cc0446b), so patch 5 unfortunately did
>> not apply cleanly due to v6.9-rc1 still having a "dma-ranges" property,
>> fixed that up and the rest applied fine.
> 
> The base is in the rpi/v6.9/unicam/next branch of
> https://git.kernel.org/pub/scm/linux/kernel/git/pinchartl/linux.git.
> This series applies on top of the 3 DT drive-by fixes I've sent
> separately.

Ah Ok, then I will swap the order in which I applied them locally. Thanks!
-- 
Florian


^ permalink raw reply

* Re: [PATCH v3 4/4] drm: panel: Add LG sw43408 panel driver
From: Marijn Suijten @ 2024-04-02 21:17 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Sumit Semwal, Caleb Connolly, Neil Armstrong, Jessica Zhang,
	Sam Ravnborg, David Airlie, Daniel Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, dri-devel, devicetree,
	linux-kernel, linux-arm-msm, Vinod Koul, Caleb Connolly
In-Reply-To: <20240402-lg-sw43408-panel-v3-4-144f17a11a56@linaro.org>

On 2024-04-02 02:51:15, Dmitry Baryshkov wrote:
> From: Sumit Semwal <sumit.semwal@linaro.org>
> 
> LG SW43408 is 1080x2160, 4-lane MIPI-DSI panel, used in some Pixel3
> phones.

@60Hz?

> 
> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
> [vinod: Add DSC support]
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> [caleb: cleanup and support turning off the panel]
> Signed-off-by: Caleb Connolly <caleb@connolly.tech>
> [DB: partially rewrote the driver and fixed DSC programming]
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

Some small nits but I think this deserves a:

Reviewed-by: Marijn Suijten <marijn.suijten@somainline.org>

> ---
>  MAINTAINERS                              |   8 +
>  drivers/gpu/drm/panel/Kconfig            |  11 ++
>  drivers/gpu/drm/panel/Makefile           |   1 +
>  drivers/gpu/drm/panel/panel-lg-sw43408.c | 326 +++++++++++++++++++++++++++++++
>  4 files changed, 346 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d36c19c1bf81..4cc43c16e07e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6789,6 +6789,14 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
>  F:	drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
>  
> +DRM DRIVER FOR LG SW43408 PANELS
> +M:	Sumit Semwal <sumit.semwal@linaro.org>
> +M:	Caleb Connolly <caleb.connolly@linaro.org>
> +S:	Maintained
> +T:	git git://anongit.freedesktop.org/drm/drm-misc
> +F:	Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
> +F:	drivers/gpu/drm/panel/panel-lg-sw43408.c
> +
>  DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER
>  M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
>  S:	Supported
> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> index 6dc451f58a3e..a55e9437c8cf 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -335,6 +335,17 @@ config DRM_PANEL_LG_LG4573
>  	  Say Y here if you want to enable support for LG4573 RGB panel.
>  	  To compile this driver as a module, choose M here.
>  
> +config DRM_PANEL_LG_SW43408
> +	tristate "LG SW43408 panel"
> +	depends on OF
> +	depends on DRM_MIPI_DSI
> +	depends on BACKLIGHT_CLASS_DEVICE
> +	help
> +	  Say Y here if you want to enable support for LG sw43408 panel.
> +	  The panel has a 1080x2160 resolution and uses
> +	  24 bit RGB per pixel. It provides a MIPI DSI interface to
> +	  the host and has a built-in LED backlight.
> +
>  config DRM_PANEL_MAGNACHIP_D53E6EA8966
>  	tristate "Magnachip D53E6EA8966 DSI panel"
>  	depends on OF && SPI
> diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
> index 24a02655d726..0b40b010e8e7 100644
> --- a/drivers/gpu/drm/panel/Makefile
> +++ b/drivers/gpu/drm/panel/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o
>  obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
>  obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
>  obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
> +obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
>  obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o
>  obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
>  obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
> diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c
> new file mode 100644
> index 000000000000..c7611bfa796b
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c
> @@ -0,0 +1,326 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-2024 Linaro Ltd
> + * Author: Sumit Semwal <sumit.semwal@linaro.org>
> + *	 Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> + */
> +
> +#include <linux/backlight.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <video/mipi_display.h>
> +
> +#include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/display/drm_dsc.h>
> +#include <drm/display/drm_dsc_helper.h>
> +
> +#define NUM_SUPPLIES 2
> +
> +struct sw43408_panel {
> +	struct drm_panel base;
> +	struct mipi_dsi_device *link;
> +
> +	const struct drm_display_mode *mode;
> +
> +	struct regulator_bulk_data supplies[NUM_SUPPLIES];
> +
> +	struct gpio_desc *reset_gpio;
> +
> +	struct drm_dsc_config dsc;
> +};
> +
> +static inline struct sw43408_panel *to_panel_info(struct drm_panel *panel)
> +{
> +	return container_of(panel, struct sw43408_panel, base);
> +}
> +
> +static int sw43408_unprepare(struct drm_panel *panel)
> +{
> +	struct sw43408_panel *ctx = to_panel_info(panel);
> +	int ret;
> +
> +	ret = mipi_dsi_dcs_set_display_off(ctx->link);
> +	if (ret < 0)
> +		dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
> +
> +	ret = mipi_dsi_dcs_enter_sleep_mode(ctx->link);
> +	if (ret < 0)
> +		dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
> +
> +	msleep(100);
> +
> +	gpiod_set_value(ctx->reset_gpio, 1);
> +
> +	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
> +}
> +
> +static int sw43408_program(struct drm_panel *panel)
> +{
> +	struct sw43408_panel *ctx = to_panel_info(panel);
> +	struct drm_dsc_picture_parameter_set pps;
> +
> +	mipi_dsi_dcs_write_seq(ctx->link, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
> +
> +	mipi_dsi_dcs_set_tear_on(ctx->link, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
> +
> +	mipi_dsi_dcs_write_seq(ctx->link, 0x53, 0x0c, 0x30);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xf7, 0x01, 0x49, 0x0c);
> +
> +	mipi_dsi_dcs_exit_sleep_mode(ctx->link);
> +
> +	msleep(135);
> +
> +	/* COMPRESSION_MODE moved after setting the PPS */
> +
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xac);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xe5,
> +			       0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0e, 0x10);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xb5,
> +			       0x75, 0x60, 0x2d, 0x5d, 0x80, 0x00, 0x0a, 0x0b,
> +			       0x00, 0x05, 0x0b, 0x00, 0x80, 0x0d, 0x0e, 0x40,
> +			       0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x80,
> +			       0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00,
> +			       0xb8, 0x00, 0x81, 0x00, 0x03, 0x03, 0x03, 0x01,
> +			       0x01);
> +	msleep(85);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xcd,
> +			       0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0x19, 0x19,
> +			       0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
> +			       0x16, 0x16);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xc0, 0x02, 0x02, 0x0f);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
> +	mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xca);
> +
> +	mipi_dsi_dcs_set_display_on(ctx->link);
> +
> +	msleep(50);
> +
> +	ctx->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
> +
> +	drm_dsc_pps_payload_pack(&pps, ctx->link->dsc);
> +	mipi_dsi_picture_parameter_set(ctx->link, &pps);
> +
> +	/* This panel uses shifted PPS selectors:
> +	 * 1 if pps_identifier is 0
> +	 * 2 if pps_identifier is 1
> +	 */
> +	mipi_dsi_compression_mode_ext(ctx->link, true,
> +				      MIPI_DSI_COMPRESSION_DSC, 1);

Let's be careful to watch the order of parameters here whichever way you fix it
up in the patch that introduces this function.

> +
> +	ctx->link->mode_flags |= MIPI_DSI_MODE_LPM;
> +
> +	return 0;
> +}
> +
> +static int sw43408_prepare(struct drm_panel *panel)
> +{
> +	struct sw43408_panel *ctx = to_panel_info(panel);
> +	int ret;
> +
> +	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
> +	if (ret < 0)
> +		return ret;
> +
> +	usleep_range(5000, 6000);
> +
> +	gpiod_set_value(ctx->reset_gpio, 0);
> +	usleep_range(9000, 10000);
> +	gpiod_set_value(ctx->reset_gpio, 1);
> +	usleep_range(1000, 2000);
> +	gpiod_set_value(ctx->reset_gpio, 0);
> +	usleep_range(9000, 10000);
> +
> +	ret = sw43408_program(panel);
> +	if (ret)
> +		goto poweroff;
> +
> +	return 0;
> +
> +poweroff:
> +	gpiod_set_value(ctx->reset_gpio, 1);
> +	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
> +	return ret;
> +}
> +
> +static int sw43408_get_modes(struct drm_panel *panel,
> +			      struct drm_connector *connector)
> +{
> +	struct sw43408_panel *ctx = to_panel_info(panel);
> +
> +	return drm_connector_helper_get_modes_fixed(connector, ctx->mode);
> +}
> +
> +static int sw43408_backlight_update_status(struct backlight_device *bl)
> +{
> +	struct mipi_dsi_device *dsi = bl_get_data(bl);
> +	uint16_t brightness = backlight_get_brightness(bl);
> +
> +	return mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
> +}
> +
> +const struct backlight_ops sw43408_backlight_ops = {
> +	.update_status = sw43408_backlight_update_status,
> +};
> +
> +static int sw43408_backlight_init(struct sw43408_panel *ctx)
> +{
> +	struct device *dev = &ctx->link->dev;
> +	const struct backlight_properties props = {
> +		.type = BACKLIGHT_PLATFORM,
> +		.brightness = 255,
> +		.max_brightness = 255,
> +	};
> +
> +	ctx->base.backlight = devm_backlight_device_register(dev, dev_name(dev), dev,
> +							ctx->link,
> +							&sw43408_backlight_ops,
> +							&props);
> +
> +	if (IS_ERR(ctx->base.backlight))
> +		return dev_err_probe(dev, PTR_ERR(ctx->base.backlight),
> +				     "Failed to create backlight\n");
> +
> +	return 0;
> +}
> +
> +static const struct drm_panel_funcs sw43408_funcs = {
> +	.unprepare = sw43408_unprepare,
> +	.prepare = sw43408_prepare,
> +	.get_modes = sw43408_get_modes,
> +};
> +
> +static const struct drm_display_mode sw43408_default_mode = {
> +	.clock = 152340,

Since this value is calculated from the values below, I prefer to just show the
origin of the value:

	.clock = (1080 + 20 + 32 + 20) * (2160 + 20 + 4 + 20) * 60 / 1000,

> +
> +	.hdisplay = 1080,
> +	.hsync_start = 1080 + 20,
> +	.hsync_end = 1080 + 20 + 32,
> +	.htotal = 1080 + 20 + 32 + 20,
> +
> +	.vdisplay = 2160,
> +	.vsync_start = 2160 + 20,
> +	.vsync_end = 2160 + 20 + 4,
> +	.vtotal = 2160 + 20 + 4 + 20,
> +
> +	.width_mm = 62,
> +	.height_mm = 124,
> +
> +	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +};
> +
> +static const struct of_device_id sw43408_of_match[] = {
> +	{ .compatible = "lg,sw43408", .data = &sw43408_default_mode },

Will you ever use multiple compatibles to select different modes?

For panels that support multiple modes (e.g. a lot of high-end sony devices
with their 4k@120Hz screens) I'm still planning on adding an atomic_prepare() to
drm_bridge and drm_panel to make it possible to program the DSC block and send
DCS relative to the selected mode (and/or perform a fluent mode switch).

> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, sw43408_of_match);
> +
> +static int sw43408_add(struct sw43408_panel *ctx)
> +{
> +	struct device *dev = &ctx->link->dev;
> +	int ret;
> +
> +	ctx->supplies[0].supply = "vddi"; /* 1.88 V */
> +	ctx->supplies[0].init_load_uA = 62000;
> +	ctx->supplies[1].supply = "vpnl"; /* 3.0 V */
> +	ctx->supplies[1].init_load_uA = 857000;
> +
> +	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
> +				      ctx->supplies);
> +	if (ret < 0)
> +		return ret;
> +
> +	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> +	if (IS_ERR(ctx->reset_gpio)) {
> +		dev_err(dev, "cannot get reset gpio %ld\n",
> +			      PTR_ERR(ctx->reset_gpio));
> +		return PTR_ERR(ctx->reset_gpio);
> +	}
> +
> +	ret = sw43408_backlight_init(ctx);
> +	if (ret < 0)
> +		return ret;
> +
> +	ctx->base.prepare_prev_first = true;
> +
> +	drm_panel_init(&ctx->base, dev, &sw43408_funcs, DRM_MODE_CONNECTOR_DSI);
> +
> +	drm_panel_add(&ctx->base);
> +	return ret;
> +}
> +
> +static int sw43408_probe(struct mipi_dsi_device *dsi)
> +{
> +	struct sw43408_panel *ctx;
> +	int ret;
> +
> +	ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx)
> +		return -ENOMEM;
> +
> +	ctx->mode = of_device_get_match_data(&dsi->dev);
> +	dsi->mode_flags = MIPI_DSI_MODE_LPM;
> +	dsi->format = MIPI_DSI_FMT_RGB888;
> +	dsi->lanes = 4;
> +
> +	ctx->link = dsi;
> +	mipi_dsi_set_drvdata(dsi, ctx);
> +
> +	ret = sw43408_add(ctx);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* The panel is DSC panel only, set the dsc params */

Grammar?

> +	ctx->dsc.dsc_version_major = 0x1;
> +	ctx->dsc.dsc_version_minor = 0x1;
> +
> +	/* slice_count * slice_width == width */
> +	ctx->dsc.slice_height = 16;
> +	ctx->dsc.slice_width = 540;
> +	ctx->dsc.slice_count = 2;
> +	ctx->dsc.bits_per_component = 8;
> +	ctx->dsc.bits_per_pixel = 8 << 4;
> +	ctx->dsc.block_pred_enable = true;
> +
> +	dsi->dsc = &ctx->dsc;
> +
> +	return mipi_dsi_attach(dsi);
> +}
> +
> +static void sw43408_remove(struct mipi_dsi_device *dsi)
> +{
> +	struct sw43408_panel *ctx = mipi_dsi_get_drvdata(dsi);
> +	int ret;
> +
> +	ret = sw43408_unprepare(&ctx->base);
> +	if (ret < 0)
> +		dev_err(&dsi->dev, "failed to unprepare panel: %d\n",
> +			      ret);
> +
> +	ret = mipi_dsi_detach(dsi);
> +	if (ret < 0)
> +		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
> +
> +	drm_panel_remove(&ctx->base);
> +}
> +
> +static struct mipi_dsi_driver sw43408_driver = {
> +	.driver = {
> +		.name = "panel-lg-sw43408",
> +		.of_match_table = sw43408_of_match,
> +	},
> +	.probe = sw43408_probe,
> +	.remove = sw43408_remove,
> +};
> +module_mipi_dsi_driver(sw43408_driver);
> +
> +MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
> +MODULE_DESCRIPTION("LG SW436408 MIPI-DSI LED panel");
> +MODULE_LICENSE("GPL");
> 
> -- 
> 2.39.2
> 

^ permalink raw reply

* [PATCH v9 9/9] MAINTAINERS: add myself as Marvell PXA1908 maintainer
From: Duje Mihanović @ 2024-04-02 21:20 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G . Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add myself as the maintainer for Marvell PXA1908 SoC support.

Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7c121493f43d..a7c19ffb739e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2371,6 +2371,15 @@ F:	drivers/irqchip/irq-mvebu-*
 F:	drivers/pinctrl/mvebu/
 F:	drivers/rtc/rtc-armada38x.c
 
+ARM/Marvell PXA1908 SOC support
+M:	Duje Mihanović <duje.mihanovic@skole.hr>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+T:	git https://gitlab.com/LegoLivesMatter/linux
+F:	arch/arm64/boot/dts/marvell/pxa1908*
+F:	drivers/clk/mmp/clk-of-pxa1908.c
+F:	include/dt-bindings/clock/marvell,pxa1908.h
+
 ARM/Mediatek RTC DRIVER
 M:	Eddie Huang <eddie.huang@mediatek.com>
 M:	Sean Wang <sean.wang@mediatek.com>
-- 
2.44.0



^ permalink raw reply related

* Re: (subset) [PATCH v2 0/2] ASoC: dt-bindings: convert fsl-asoc-card.txt to YAML
From: Mark Brown @ 2024-04-02 21:19 UTC (permalink / raw)
  To: lgirdwood, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	shengjiu.wang, linux-sound, devicetree, linux-kernel, shawnguo,
	s.hauer, kernel, festevam, imx, linux-arm-kernel, Shengjiu Wang
In-Reply-To: <1711976056-19884-1-git-send-email-shengjiu.wang@nxp.com>

On Mon, 01 Apr 2024 20:54:14 +0800, Shengjiu Wang wrote:
> Convert fsl-asoc-card.txt to YAML. In order to pass the checking,
> add some used compatible string from devicetree.
> 
> change cpu-dai in imx6sx-nitrogen6sx to ssi-controller.
> 
> changes in v2:
> - update commit message for reason why add compatible strings
>   which are not in txt file.
> - add deprecated
> - add $ref for bitclock-master and others.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[2/2] ASoC: dt-bindings: fsl-asoc-card: convert to YAML
      commit: 4189b54220e5af15e948a48524b45d5ea2e5660d

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

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

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

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

Thanks,
Mark


^ permalink raw reply

* [PATCH v9 8/9] arm64: dts: Add DTS for Marvell PXA1908 and samsung,coreprimevelte
From: Duje Mihanović @ 2024-04-02 21:16 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G . Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add DTS for Marvell PXA1908 SoC and Samsung Galaxy Core Prime Value
Edition LTE, a smartphone based on said SoC.

Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>

To: Michael Turquette <mturquette@baylibre.com>, 
 Stephen Boyd <sboyd@kernel.org>, Linus Walleij <linus.walleij@linaro.org>, 
 Rob Herring <robh+dt@kernel.org>, 
 Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, 
 Conor Dooley <conor+dt@kernel.org>, Tony Lindgren <tony@atomide.com>, 
 Haojian Zhuang <haojian.zhuang@linaro.org>, 
 =?utf-8?q?Duje_Mihanovi=C4=87?= <duje.mihanovic@skole.hr>, 
 Lubomir Rintel <lkundrak@v3.sk>, Catalin Marinas <catalin.marinas@arm.com>, 
 Will Deacon <will@kernel.org>, Kees Cook <keescook@chromium.org>, 
 Tony Luck <tony.luck@intel.com>, 
 "Guilherme G. Piccoli" <gpiccoli@igalia.com>, Rob Herring <robh@kernel.org>
Cc: phone-devel@vger.kernel.org, ~postmarketos/upstreaming@lists.sr.ht, 
 Karel Balej <balejk@matfyz.cz>, David Wronek <david@mainlining.org>, 
 linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, 
 linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, 
 linux-arm-kernel@lists.infradead.org
---
 arch/arm64/boot/dts/marvell/Makefile          |   3 +
 .../pxa1908-samsung-coreprimevelte.dts        | 336 ++++++++++++++++++
 arch/arm64/boot/dts/marvell/pxa1908.dtsi      | 304 ++++++++++++++++
 3 files changed, 643 insertions(+)
 create mode 100644 arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts
 create mode 100644 arch/arm64/boot/dts/marvell/pxa1908.dtsi

diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile
index 99b8cb3c49e1..687c256d95fe 100644
--- a/arch/arm64/boot/dts/marvell/Makefile
+++ b/arch/arm64/boot/dts/marvell/Makefile
@@ -28,3 +28,6 @@ dtb-$(CONFIG_ARCH_MVEBU) += cn9130-crb-A.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += cn9130-crb-B.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += ac5x-rd-carrier-cn9131.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += ac5-98dx35xx-rd.dtb
+
+# MMP SoC Family
+dtb-$(CONFIG_ARCH_MMP) += pxa1908-samsung-coreprimevelte.dtb
diff --git a/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts
new file mode 100644
index 000000000000..4aac4c120087
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/pxa1908-samsung-coreprimevelte.dts
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include "pxa1908.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+
+/ {
+	model = "Samsung Galaxy Core Prime VE LTE";
+	compatible = "samsung,coreprimevelte", "marvell,pxa1908";
+
+	aliases {
+		mmc0 = &sdh2; /* eMMC */
+		mmc1 = &sdh0; /* SD card */
+		serial0 = &uart0;
+	};
+
+	chosen {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		stdout-path = "serial0:115200n8";
+
+		/* S-Boot places the initramfs here */
+		linux,initrd-start = <0x4d70000>;
+		linux,initrd-end = <0x5000000>;
+
+		fb0: framebuffer@17177000 {
+			compatible = "simple-framebuffer";
+			reg = <0 0x17177000 0 (480 * 800 * 4)>;
+			width = <480>;
+			height = <800>;
+			stride = <(480 * 4)>;
+			format = "a8r8g8b8";
+		};
+	};
+
+	/* Bootloader fills this in */
+	memory {
+		device_type = "memory";
+		reg = <0 0 0 0>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		framebuffer@17000000 {
+			reg = <0 0x17000000 0 0x1800000>;
+			no-map;
+		};
+
+		gpu@9000000 {
+			reg = <0 0x9000000 0 0x1000000>;
+		};
+
+		/* Communications processor, aka modem */
+		cp@5000000 {
+			reg = <0 0x5000000 0 0x3000000>;
+		};
+
+		cm3@a000000 {
+			reg = <0 0xa000000 0 0x80000>;
+		};
+
+		seclog@8000000 {
+			reg = <0 0x8000000 0 0x100000>;
+		};
+
+		ramoops@8100000 {
+			compatible = "ramoops";
+			reg = <0 0x8100000 0 0x40000>;
+			record-size = <0x8000>;
+			console-size = <0x20000>;
+			max-reason = <5>;
+		};
+	};
+
+
+	i2c-muic {
+		compatible = "i2c-gpio";
+		sda-gpios = <&gpio 30 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+		scl-gpios = <&gpio 29 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+		i2c-gpio,delay-us = <3>;
+		i2c-gpio,timeout-ms = <100>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c_muic_pins>;
+
+		muic: extcon@14 {
+			compatible = "siliconmitus,sm5504-muic";
+			reg = <0x14>;
+			interrupt-parent = <&gpio>;
+			interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_keys_pins>;
+		autorepeat;
+
+		key-home {
+			label = "Home";
+			linux,code = <KEY_HOME>;
+			gpios = <&gpio 50 GPIO_ACTIVE_LOW>;
+		};
+
+		key-volup {
+			label = "Volume Up";
+			linux,code = <KEY_VOLUMEUP>;
+			gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
+		};
+
+		key-voldown {
+			label = "Volume Down";
+			linux,code = <KEY_VOLUMEDOWN>;
+			gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&smmu {
+	status = "okay";
+};
+
+&pmx {
+	pinctrl-single,gpio-range = <&range 55 55 0>,
+				    <&range 110 32 0>,
+				    <&range 52 1 0>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&board_pins_1 &board_pins_2 &board_pins_3>;
+
+	board_pins_1: pinmux-board-1 {
+		pinctrl-single,pins = <
+			0x160 0
+			0x164 0
+			0x168 0
+			0x16c 0
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0x8000 0x8000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0x8000 0x8000 0 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0x288 0x388>;
+	};
+
+	board_pins_2: pinmux-board-2 {
+		pinctrl-single,pins = <
+			0x44 1
+			0x48 1
+			0x20 1
+			0x18 1
+			0x14 1
+			0x10 1
+			0xc 1
+			0x8 1
+			0x68 1
+			0x58 0
+			0x54 0
+			0x7c 0
+			0x6c 0
+			0x70 0
+			0x4c 1
+			0x50 1
+			0xac 0
+			0x90 0
+			0x8c 0
+			0x88 0
+			0x84 0
+			0xc8 0
+			0x128 0
+			0x190 0
+			0x194 0
+			0x1a0 0
+			0x114 0
+			0x118 0
+			0x1d8 0
+			0x1e4 0
+			0xe8 0
+			0x100 0
+			0x204 0
+			0x210 0
+			0x218 0
+		>;
+		pinctrl-single,bias-pullup = <0xc000 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0x8000 0xa000 0x8000 0xc000>;
+		pinctrl-single,low-power-mode = <0x288 0x388>;
+	};
+
+	board_pins_3: pinmux-board-3 {
+		pinctrl-single,pins = <
+			0x260 0
+			0x264 0
+			0x268 0
+			0x26c 0
+			0x270 0
+			0x274 0
+			0x78 0
+			0x74 0
+			0xb0 1
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0 0xa000 0 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0 0x388>;
+	};
+
+	uart0_pins: pinmux-uart0 {
+		pinctrl-single,pins = <
+			0x198 6
+			0x19c 6
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0 0xa000 0 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0 0x388>;
+	};
+
+	gpio_keys_pins: pinmux-gpio-keys {
+		pinctrl-single,pins = <
+			0x11c 0
+			0x120 0
+			0x1a4 0
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0xc000 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0x8000 0xa0000 0x8000 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0 0x388>;
+	};
+
+	i2c_muic_pins: pinmux-i2c-muic {
+		pinctrl-single,pins = <
+			0x154 0
+			0x150 0
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0 0xa000 0 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0x288 0x388>;
+	};
+
+	sdh0_pins_1: pinmux-sdh0-1 {
+		pinctrl-single,pins = <
+			0x108 0
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0xc000 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0x8000 0xa000 0x8000 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0 0x388>;
+	};
+
+	sdh0_pins_2: pinmux-sdh0-2 {
+		pinctrl-single,pins = <
+			0x94 0
+			0x98 0
+			0x9c 0
+			0xa0 0
+			0xa4 0
+		>;
+		pinctrl-single,drive-strength = <0x800 0x1800>;
+		pinctrl-single,bias-pullup = <0xc000 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0x8000 0xa000 0x8000 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0 0x388>;
+	};
+
+	sdh0_pins_3: pinmux-sdh0-3 {
+		pinctrl-single,pins = <
+			0xa8 0
+		>;
+		pinctrl-single,drive-strength = <0x1000 0x1800>;
+		pinctrl-single,bias-pullup = <0 0xc000 0 0xc000>;
+		pinctrl-single,bias-pulldown = <0 0xa000 0 0xa000>;
+		pinctrl-single,input-schmitt = <0 0x30>;
+		pinctrl-single,input-schmitt-enable = <0x40 0 0x40 0x40>;
+		pinctrl-single,low-power-mode = <0x208 0x388>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+};
+
+&twsi0 {
+	status = "okay";
+};
+
+&twsi1 {
+	status = "okay";
+};
+
+&twsi2 {
+	status = "okay";
+};
+
+&twsi3 {
+	status = "okay";
+};
+
+&usb {
+	extcon = <&muic>, <&muic>;
+};
+
+&sdh2 {
+	/* Disabled for now because initialization fails with -ETIMEDOUT. */
+	status = "disabled";
+	bus-width = <8>;
+	non-removable;
+	mmc-ddr-1_8v;
+};
+
+&sdh0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdh0_pins_1 &sdh0_pins_2 &sdh0_pins_3>;
+	cd-gpios = <&gpio 11 0>;
+	cd-inverted;
+	bus-width = <4>;
+	wp-inverted;
+};
diff --git a/arch/arm64/boot/dts/marvell/pxa1908.dtsi b/arch/arm64/boot/dts/marvell/pxa1908.dtsi
new file mode 100644
index 000000000000..9933cec5b7d2
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/pxa1908.dtsi
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/marvell,pxa1908.h>
+
+/ {
+	model = "Marvell Armada PXA1908";
+	compatible = "marvell,pxa1908";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0 0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0 1>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0 2>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0 3>;
+			enable-method = "psci";
+		};
+	};
+
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		smmu: iommu@c0010000 {
+			compatible = "arm,mmu-400";
+			reg = <0 0xc0010000 0 0x10000>;
+			#global-interrupts = <1>;
+			#iommu-cells = <1>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller@d1df9000 {
+			compatible = "arm,gic-400";
+			reg = <0 0xd1df9000 0 0x1000>,
+				<0 0xd1dfa000 0 0x2000>,
+				/* The subsequent registers are guesses. */
+				<0 0xd1dfc000 0 0x2000>,
+				<0 0xd1dfe000 0 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		apb@d4000000 {
+			compatible = "simple-bus";
+			reg = <0 0xd4000000 0 0x200000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0 0xd4000000 0x200000>;
+
+			pdma: dma-controller@0 {
+				compatible = "marvell,pdma-1.0";
+				reg = <0 0x10000>;
+				interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				dma-channels = <30>;
+				#dma-cells = <2>;
+			};
+
+			twsi1: i2c@10800 {
+				compatible = "mrvl,mmp-twsi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x10800 0x64>;
+				interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbc PXA1908_CLK_TWSI1>;
+				mrvl,i2c-fast-mode;
+				status = "disabled";
+			};
+
+			twsi0: i2c@11000 {
+				compatible = "mrvl,mmp-twsi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x11000 0x64>;
+				interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbc PXA1908_CLK_TWSI0>;
+				mrvl,i2c-fast-mode;
+				status = "disabled";
+			};
+
+			twsi3: i2c@13800 {
+				compatible = "mrvl,mmp-twsi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x13800 0x64>;
+				interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbc PXA1908_CLK_TWSI3>;
+				mrvl,i2c-fast-mode;
+				status = "disabled";
+			};
+
+			apbc: clock-controller@15000 {
+				compatible = "marvell,pxa1908-apbc";
+				reg = <0x15000 0x1000>;
+				#clock-cells = <1>;
+			};
+
+			uart0: serial@17000 {
+				compatible = "mrvl,mmp-uart", "intel,xscale-uart";
+				reg = <0x17000 0x1000>;
+				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbc PXA1908_CLK_UART0>;
+				reg-shift = <2>;
+			};
+
+			uart1: serial@18000 {
+				compatible = "mrvl,mmp-uart", "intel,xscale-uart";
+				reg = <0x18000 0x1000>;
+				interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbc PXA1908_CLK_UART1>;
+				reg-shift = <2>;
+			};
+
+			gpio: gpio@19000 {
+				compatible = "marvell,mmp-gpio";
+				reg = <0x19000 0x800>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				clocks = <&apbc PXA1908_CLK_GPIO>;
+				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "gpio_mux";
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				ranges = <0 0x19000 0x800>;
+
+				gpio@0 {
+					reg = <0x0 0x4>;
+				};
+
+				gpio@4 {
+					reg = <0x4 0x4>;
+				};
+
+				gpio@8 {
+					reg = <0x8 0x4>;
+				};
+
+				gpio@100 {
+					reg = <0x100 0x4>;
+				};
+			};
+
+			pmx: pinmux@1e000 {
+				compatible = "marvell,pxa1908-padconf", "pinconf-single";
+				reg = <0x1e000 0x330>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				#gpio-range-cells = <3>;
+				ranges;
+
+				#pinctrl-cells = <1>;
+				pinctrl-single,register-width = <32>;
+				pinctrl-single,function-mask = <7>;
+
+				range: gpio-range {
+					#pinctrl-single,gpio-range-cells = <3>;
+				};
+			};
+
+			uart2: serial@36000 {
+				compatible = "mrvl,mmp-uart", "intel,xscale-uart";
+				reg = <0x36000 0x1000>;
+				interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbcp PXA1908_CLK_UART2>;
+				reg-shift = <2>;
+			};
+
+			twsi2: i2c@37000 {
+				compatible = "mrvl,mmp-twsi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x37000 0x64>;
+				interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apbcp PXA1908_CLK_TWSI2>;
+				mrvl,i2c-fast-mode;
+				status = "disabled";
+			};
+
+			apbcp: clock-controller@3b000 {
+				compatible = "marvell,pxa1908-apbcp";
+				reg = <0x3b000 0x1000>;
+				#clock-cells = <1>;
+			};
+
+			mpmu: clock-controller@50000 {
+				compatible = "marvell,pxa1908-mpmu";
+				reg = <0x50000 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+		axi@d4200000 {
+			compatible = "simple-bus";
+			reg = <0 0xd4200000 0 0x200000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0 0xd4200000 0x200000>;
+
+			usbphy: phy@7000 {
+				compatible = "marvell,pxa1928-usb-phy";
+				reg = <0x7000 0x200>;
+				clocks = <&apmu PXA1908_CLK_USB>;
+				#phy-cells = <0>;
+			};
+
+			usb: usb@8000 {
+				compatible = "chipidea,usb2";
+				reg = <0x8000 0x200>;
+				interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apmu PXA1908_CLK_USB>;
+				phys = <&usbphy>;
+				phy-names = "usb-phy";
+			};
+
+			sdh0: mmc@80000 {
+				compatible = "mrvl,pxav3-mmc";
+				reg = <0x80000 0x120>;
+				interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apmu PXA1908_CLK_SDH0>;
+				clock-names = "io";
+				mrvl,clk-delay-cycles = <31>;
+			};
+
+			sdh1: mmc@80800 {
+				compatible = "mrvl,pxav3-mmc";
+				reg = <0x80800 0x120>;
+				interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apmu PXA1908_CLK_SDH1>;
+				clock-names = "io";
+				mrvl,clk-delay-cycles = <31>;
+			};
+
+			sdh2: mmc@81000 {
+				compatible = "mrvl,pxav3-mmc";
+				reg = <0x81000 0x120>;
+				interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&apmu PXA1908_CLK_SDH2>;
+				clock-names = "io";
+				mrvl,clk-delay-cycles = <31>;
+			};
+
+			apmu: clock-controller@82800 {
+				compatible = "marvell,pxa1908-apmu";
+				reg = <0x82800 0x400>;
+				#clock-cells = <1>;
+			};
+		};
+	};
+};
-- 
2.44.0



^ permalink raw reply related

* Re: [PATCH v3 3/4] drm/mipi-dsi: add mipi_dsi_compression_mode_ext()
From: Marijn Suijten @ 2024-04-02 21:09 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Sumit Semwal, Caleb Connolly, Neil Armstrong, Jessica Zhang,
	Sam Ravnborg, David Airlie, Daniel Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, dri-devel, devicetree,
	linux-kernel, linux-arm-msm
In-Reply-To: <20240402-lg-sw43408-panel-v3-3-144f17a11a56@linaro.org>

On 2024-04-02 02:51:14, Dmitry Baryshkov wrote:
> Add the extended version of mipi_dsi_compression_mode(). It provides
> a way to specify the algorithm and PPS selector.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>  drivers/gpu/drm/drm_mipi_dsi.c | 33 +++++++++++++++++++++++++++------
>  include/drm/drm_mipi_dsi.h     |  9 +++++++++
>  2 files changed, 36 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index 9874ff6d4718..0ecbc811eb7a 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -645,19 +645,24 @@ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
>  EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
>  
>  /**
> - * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
> + * mipi_dsi_compression_mode_ext() - enable/disable DSC on the peripheral
>   * @dsi: DSI peripheral device
>   * @enable: Whether to enable or disable the DSC
> + * @algo: Selected algorithm
> + * @pps_selector: The PPS selector

Not a big fan of paraphrasing the parameter name, it adds no value.  How about
describing what this parameter means and what it does?:

	PPS table index to use.  Corresponds to a table pre-programmed on the peripheral
	or a table programmed with &drm_dsc_picture_parameter_set.pps_identifier.

(That should be a valid kernel-doc cross-reference to the field)

>   *
> - * Enable or disable Display Stream Compression on the peripheral using the
> - * default Picture Parameter Set and VESA DSC 1.1 algorithm.
> + * Enable or disable Display Stream Compression on the peripheral.
>   *
>   * Return: 0 on success or a negative error code on failure.
>   */
> -int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
> +int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
> +				  enum mipi_dsi_compression_algo algo,
> +				  unsigned int pps_selector)
>  {
> -	/* Note: Needs updating for non-default PPS or algorithm */
> -	u8 tx[2] = { enable << 0, 0 };
> +	u8 data = (enable << 0) |
> +		(algo << 1) |
> +		(pps_selector << 4);

Do we need some size validation (if > 3 return -EINVAL)?  FIELD_PREP() might be
too heavy though.

> +	u8 tx[2] = { data, 0 };
>  	struct mipi_dsi_msg msg = {
>  		.channel = dsi->channel,
>  		.type = MIPI_DSI_COMPRESSION_MODE,
> @@ -668,6 +673,22 @@ int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
>  
>  	return (ret < 0) ? ret : 0;
>  }
> +EXPORT_SYMBOL(mipi_dsi_compression_mode_ext);
> +
> +/**
> + * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
> + * @dsi: DSI peripheral device
> + * @enable: Whether to enable or disable the DSC
> + *
> + * Enable or disable Display Stream Compression on the peripheral using the
> + * default Picture Parameter Set and VESA DSC 1.1 algorithm.
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
> +{
> +	return mipi_dsi_compression_mode_ext(dsi, enable, 0, MIPI_DSI_COMPRESSION_DSC);

I hope the compiler complains here that it should be MIPI_DSI_COMPRESSION_DSC,0

(Enum algo first, int pps_selector last)

> +}
>  EXPORT_SYMBOL(mipi_dsi_compression_mode);
>  
>  /**
> diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
> index 3011d33eccbd..78cb7b688b1d 100644
> --- a/include/drm/drm_mipi_dsi.h
> +++ b/include/drm/drm_mipi_dsi.h
> @@ -226,6 +226,12 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
>  	return -EINVAL;
>  }
>  
> +enum mipi_dsi_compression_algo {
> +	MIPI_DSI_COMPRESSION_DSC = 0,

Add 1.1?  Or does it also allow 1.2 (when the version is also set via PPS)?

> +	MIPI_DSI_COMPRESSION_VENDOR = 3,
> +	/* other two values are reserved, DSI 1.3 */
> +};
> +
>  struct mipi_dsi_device *
>  mipi_dsi_device_register_full(struct mipi_dsi_host *host,
>  			      const struct mipi_dsi_device_info *info);
> @@ -242,6 +248,9 @@ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
>  int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
>  					    u16 value);
>  int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
> +int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
> +				  unsigned int pps_selector,
> +				  enum mipi_dsi_compression_algo algo);

Oh, this declaration is inverse from the definition...

- Marijn

>  int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
>  				   const struct drm_dsc_picture_parameter_set *pps);
>  
> 
> -- 
> 2.39.2
> 

^ permalink raw reply

* [PATCH 3/3] arm64: dts: imx8dxl-evk: add audio nodes
From: Frank Li @ 2024-04-02 21:02 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20240402-b4-dts_dxl_audio-v1-0-d26d25b84a08@nxp.com>

Add audio nodes for imx8dxl-evk boards.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8dxl-evk.dts | 234 ++++++++++++++++++++++++++
 1 file changed, 234 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
index 2123d431e0613..ba4cdc3534362 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
@@ -125,6 +125,81 @@ mii_select: regulator-4 {
 		enable-active-high;
 		regulator-always-on;
 	};
+
+	bt_sco_codec: bt_sco_codec {
+		#sound-dai-cells = <1>;
+		compatible = "linux,bt-sco";
+	};
+
+	sound-bt-sco {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "bt-sco-audio";
+		simple-audio-card,format = "dsp_a";
+		simple-audio-card,bitclock-inversion;
+		simple-audio-card,frame-master = <&btcpu>;
+		simple-audio-card,bitclock-master = <&btcpu>;
+
+		btcpu: simple-audio-card,cpu {
+			sound-dai = <&sai0>;
+			dai-tdm-slot-num = <2>;
+			dai-tdm-slot-width = <16>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&bt_sco_codec 1>;
+		};
+	};
+
+	sound-wm8960-1 {
+		compatible = "fsl,imx7d-evk-wm8960", "fsl,imx-audio-wm8960";
+		model = "wm8960-audio";
+		audio-cpu = <&sai1>;
+		audio-codec = <&wm8960_1>;
+		audio-asrc = <&asrc0>;
+		audio-routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Ext Spk", "SPK_LP",
+			"Ext Spk", "SPK_LN",
+			"Ext Spk", "SPK_RP",
+			"Ext Spk", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"Mic Jack", "MICB";
+	};
+
+	sound-wm8960-2 {
+		compatible = "fsl,imx7d-evk-wm8960", "fsl,imx-audio-wm8960";
+		model = "wm8960-audio-2";
+		audio-cpu = <&sai2>;
+		audio-codec = <&wm8960_2>;
+		capture-only;
+		audio-routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Ext Spk", "SPK_LP",
+			"Ext Spk", "SPK_LN",
+			"Ext Spk", "SPK_RP",
+			"Ext Spk", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"Mic Jack", "MICB";
+	};
+
+	sound-wm8960-3 {
+		compatible = "fsl,imx7d-evk-wm8960", "fsl,imx-audio-wm8960";
+		model = "wm8960-audio-3";
+		audio-cpu = <&sai3>;
+		audio-codec = <&wm8960_3>;
+		capture-only;
+		audio-routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Ext Spk", "SPK_LP",
+			"Ext Spk", "SPK_LN",
+			"Ext Spk", "SPK_RP",
+			"Ext Spk", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"Mic Jack", "MICB";
+	};
 };
 
 &adc0 {
@@ -132,6 +207,11 @@ &adc0 {
 	status = "okay";
 };
 
+&asrc0 {
+	fsl,asrc-rate  = <48000>;
+	status = "okay";
+};
+
 &eqos {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_eqos>;
@@ -259,6 +339,78 @@ max7322: gpio@68 {
 			};
 		};
 
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x1>;
+
+			wm8960_1: wm8960@1a {
+				compatible = "wlf,wm8960";
+				reg = <0x1a>;
+				clocks = <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+				clock-names = "mclk";
+				wlf,shared-lrclk;
+				wlf,hp-cfg = <2 2 3>;
+				wlf,gpio-cfg = <1 3>;
+				assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+						  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+						  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+						  <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+				assigned-clock-rates = <786432000>,
+						       <49152000>,
+						       <12288000>,
+						       <12288000>;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x2>;
+
+			wm8960_2: wm8960@1a {
+				compatible = "wlf,wm8960";
+				reg = <0x1a>;
+				clocks = <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+				clock-names = "mclk";
+				wlf,shared-lrclk;
+				wlf,hp-cfg = <2 2 3>;
+				wlf,gpio-cfg = <1 3>;
+				assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+						  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+						  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+						  <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+				assigned-clock-rates = <786432000>,
+						       <49152000>,
+						       <12288000>,
+						       <12288000>;
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x3>;
+
+			wm8960_3: wm8960@1a {
+				compatible = "wlf,wm8960";
+				reg = <0x1a>;
+				clocks = <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+				clock-names = "mclk";
+				wlf,shared-lrclk;
+				wlf,hp-cfg = <2 2 3>;
+				wlf,gpio-cfg = <1 3>;
+				assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+						  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+						  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+						  <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+				assigned-clock-rates = <786432000>,
+						       <49152000>,
+						       <12288000>,
+						       <12288000>;
+			};
+		};
+
 		i2c@4 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -362,6 +514,53 @@ &lsio_gpio5 {
 	status = "okay";
 };
 
+&sai0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai0>;
+	#sound-dai-cells = <0>;
+	assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+			<&sai0_lpcg IMX_LPCG_CLK_0>;
+	assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+	status = "okay";
+};
+
+&sai1 {
+	assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+			<&sai1_lpcg IMX_LPCG_CLK_0>;
+	assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai1>;
+	status = "okay";
+};
+
+&sai2 {
+	assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+			<&sai2_lpcg IMX_LPCG_CLK_0>;
+	assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
+	fsl,sai-asynchronous;
+	status = "okay";
+};
+
+&sai3 {
+	assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+			<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+			<&sai3_lpcg IMX_LPCG_CLK_0>;
+	assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai3>;
+	fsl,sai-asynchronous;
+	status = "okay";
+};
+
 &thermal_zones {
 	pmic-thermal {
 		polling-delay-passive = <250>;
@@ -595,6 +794,41 @@ IMX8DXL_UART0_TX_ADMA_UART0_TX		0x06000020
 		>;
 	};
 
+	pinctrl_sai0: sai0grp {
+		fsl,pins = <
+			IMX8DXL_SPI0_CS0_ADMA_SAI0_RXD		0x06000060
+			IMX8DXL_SPI0_CS1_ADMA_SAI0_RXC		0x06000040
+			IMX8DXL_SPI0_SCK_ADMA_SAI0_TXC		0x06000060
+			IMX8DXL_SPI0_SDI_ADMA_SAI0_TXD		0x06000060
+			IMX8DXL_SPI0_SDO_ADMA_SAI0_TXFS		0x06000040
+		>;
+	};
+
+	pinctrl_sai1: sai1grp {
+		fsl,pins = <
+			IMX8DXL_FLEXCAN0_RX_ADMA_SAI1_TXC     0x06000040
+			IMX8DXL_FLEXCAN0_TX_ADMA_SAI1_TXFS    0x06000040
+			IMX8DXL_FLEXCAN1_RX_ADMA_SAI1_TXD     0x06000060
+			IMX8DXL_FLEXCAN1_TX_ADMA_SAI1_RXD     0x06000060
+		>;
+	};
+
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			IMX8DXL_SNVS_TAMPER_OUT3_ADMA_SAI2_RXC   0x06000040
+			IMX8DXL_SNVS_TAMPER_IN0_ADMA_SAI2_RXFS   0x06000040
+			IMX8DXL_SNVS_TAMPER_OUT4_ADMA_SAI2_RXD   0x06000060
+		>;
+	};
+
+	pinctrl_sai3: sai3grp {
+		fsl,pins = <
+			IMX8DXL_SNVS_TAMPER_IN1_ADMA_SAI3_RXC    0x06000040
+			IMX8DXL_SNVS_TAMPER_IN3_ADMA_SAI3_RXFS   0x06000040
+			IMX8DXL_SNVS_TAMPER_IN2_ADMA_SAI3_RXD    0x06000060
+		>;
+	};
+
 	pinctrl_usdhc1: usdhc1grp {
 		fsl,pins = <
 			IMX8DXL_EMMC0_CLK_CONN_EMMC0_CLK	0x06000041

-- 
2.34.1


^ permalink raw reply related

* [PATCH 2/3] arm64: dts: imx8dxl-ss-adma: update audio node power domains and IRQ number
From: Frank Li @ 2024-04-02 21:02 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20240402-b4-dts_dxl_audio-v1-0-d26d25b84a08@nxp.com>

The power domains of i.MX8DXL's acm is difference i.MX8QXP. IRQ number of
sai[0..3] and spdif0 are also difference.

Update power domains information for i.MX8DXL.

Update sai[0..3] and spdif0's IRQ number for i.MX8DXL.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
index f5dcdd9405928..72434529f78e6 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
@@ -17,6 +17,49 @@
 /delete-node/ &sai5;
 /delete-node/ &sai5_lpcg;
 
+&acm {
+	compatible = "fsl,imx8dxl-acm";
+	power-domains = <&pd IMX_SC_R_AUDIO_CLK_0>,
+			<&pd IMX_SC_R_AUDIO_CLK_1>,
+			<&pd IMX_SC_R_MCLK_OUT_0>,
+			<&pd IMX_SC_R_MCLK_OUT_1>,
+			<&pd IMX_SC_R_AUDIO_PLL_0>,
+			<&pd IMX_SC_R_AUDIO_PLL_1>,
+			<&pd IMX_SC_R_ASRC_0>,
+			<&pd IMX_SC_R_SAI_0>,
+			<&pd IMX_SC_R_SAI_1>,
+			<&pd IMX_SC_R_SAI_2>,
+			<&pd IMX_SC_R_SAI_3>,
+			<&pd IMX_SC_R_SPDIF_0>,
+			<&pd IMX_SC_R_MQS_0>;
+	clocks = <&aud_rec0_lpcg IMX_LPCG_CLK_0>,
+		 <&aud_rec1_lpcg IMX_LPCG_CLK_0>,
+		 <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>,
+		 <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>,
+		 <&clk_ext_aud_mclk0>,
+		 <&clk_ext_aud_mclk1>,
+		 <&clk_spdif0_rx>,
+		 <&clk_sai0_rx_bclk>,
+		 <&clk_sai0_tx_bclk>,
+		 <&clk_sai1_rx_bclk>,
+		 <&clk_sai1_tx_bclk>,
+		 <&clk_sai2_rx_bclk>,
+		 <&clk_sai3_rx_bclk>;
+	clock-names = "aud_rec_clk0_lpcg_clk",
+		      "aud_rec_clk1_lpcg_clk",
+		      "aud_pll_div_clk0_lpcg_clk",
+		      "aud_pll_div_clk1_lpcg_clk",
+		      "ext_aud_mclk0",
+		      "ext_aud_mclk1",
+		      "spdif0_rx",
+		      "sai0_rx_bclk",
+		      "sai0_tx_bclk",
+		      "sai1_rx_bclk",
+		      "sai1_tx_bclk",
+		      "sai2_rx_bclk",
+		      "sai3_rx_bclk";
+};
+
 &audio_ipg_clk {
 	clock-frequency = <160000000>;
 };
@@ -191,3 +234,24 @@ &lpspi2 {
 &lpspi3 {
 	interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
 };
+
+&sai0 {
+	interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai1 {
+	interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai2 {
+	interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai3 {
+	interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&spdif0 {
+	interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, /* rx */
+		     <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>; /* tx */
+};

-- 
2.34.1


^ permalink raw reply related

* [PATCH 1/3] arm64: dts: imx8dxl-ss-adma: delete unused node
From: Frank Li @ 2024-04-02 21:02 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20240402-b4-dts_dxl_audio-v1-0-d26d25b84a08@nxp.com>

Delete unused node in adma subsystem.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
index 5d012c95222f5..f5dcdd9405928 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
@@ -3,6 +3,20 @@
  * Copyright 2019~2020, 2022 NXP
  */
 
+/delete-node/ &asrc1;
+/delete-node/ &asrc1_lpcg;
+/delete-node/ &adc1;
+/delete-node/ &adc1_lpcg;
+/delete-node/ &amix;
+/delete-node/ &amix_lpcg;
+/delete-node/ &edma1;
+/delete-node/ &esai0;
+/delete-node/ &esai0_lpcg;
+/delete-node/ &sai4;
+/delete-node/ &sai4_lpcg;
+/delete-node/ &sai5;
+/delete-node/ &sai5_lpcg;
+
 &audio_ipg_clk {
 	clock-frequency = <160000000>;
 };

-- 
2.34.1


^ permalink raw reply related

* [PATCH 0/3] arm64: dts: imx8dxl: add audio support for imx8dxl
From: Frank Li @ 2024-04-02 21:02 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li

This patches depend on dts part in
https://lore.kernel.org/imx/20240328-asrc_8qxp-v8-0-801cd6bb5be2@nxp.com/T/#t

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Frank Li (3):
      arm64: dts: imx8dxl-ss-adma: delete unused node
      arm64: dts: imx8dxl-ss-adma: update audio node power domains and IRQ number
      arm64: dts: imx8dxl-evk: add audio nodes

 arch/arm64/boot/dts/freescale/imx8dxl-evk.dts      | 234 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi |  78 +++++++
 2 files changed, 312 insertions(+)
---
base-commit: 2d13a7797c3970a4eea160844d8905c93065634f
change-id: 20240402-b4-dts_dxl_audio-74ba02030a72

Best regards,
---
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* [PATCH v9 5/9] clk: mmp: Add Marvell PXA1908 clock driver
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add driver for Marvell PXA1908 clock controller blocks. The SoC has
numerous clock controller blocks, currently supporting APBC, APBCP, MPMU
and APMU.

Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 drivers/clk/mmp/Makefile         |   2 +-
 drivers/clk/mmp/clk-of-pxa1908.c | 328 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 329 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 441bf83080a1..69f9c3afde83 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -11,4 +11,4 @@ obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
 obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
 obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o
 
-obj-y += clk-of-pxa1928.o
+obj-$(CONFIG_ARCH_MMP) += clk-of-pxa1928.o clk-of-pxa1908.o
diff --git a/drivers/clk/mmp/clk-of-pxa1908.c b/drivers/clk/mmp/clk-of-pxa1908.c
new file mode 100644
index 000000000000..6f1f6e25a718
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa1908.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/units.h>
+
+#include <dt-bindings/clock/marvell,pxa1908.h>
+
+#include "clk.h"
+
+#define APMU_CLK_GATE_CTRL	0x40
+#define MPMU_UART_PLL		0x14
+
+#define APBC_UART0		0x0
+#define APBC_UART1		0x4
+#define APBC_GPIO		0x8
+#define APBC_PWM0		0xc
+#define APBC_PWM1		0x10
+#define APBC_PWM2		0x14
+#define APBC_PWM3		0x18
+#define APBC_SSP0		0x1c
+#define APBC_SSP1		0x20
+#define APBC_IPC_RST		0x24
+#define APBC_RTC		0x28
+#define APBC_TWSI0		0x2c
+#define APBC_KPC		0x30
+#define APBC_SWJTAG		0x40
+#define APBC_SSP2		0x4c
+#define APBC_TWSI1		0x60
+#define APBC_THERMAL		0x6c
+#define APBC_TWSI3		0x70
+
+#define APBCP_UART2		0x1c
+#define APBCP_TWSI2		0x28
+#define APBCP_AICER		0x38
+
+#define APMU_CCIC1		0x24
+#define APMU_ISP		0x38
+#define APMU_DSI1		0x44
+#define APMU_DISP1		0x4c
+#define APMU_CCIC0		0x50
+#define APMU_SDH0		0x54
+#define APMU_SDH1		0x58
+#define APMU_USB		0x5c
+#define APMU_NF			0x60
+#define APMU_VPU		0xa4
+#define APMU_GC			0xcc
+#define APMU_SDH2		0xe0
+#define APMU_GC2D		0xf4
+#define APMU_TRACE		0x108
+#define APMU_DVC_DFC_DEBUG	0x140
+
+#define MPMU_NR_CLKS		39
+#define APBC_NR_CLKS		19
+#define APBCP_NR_CLKS		4
+#define APMU_NR_CLKS		17
+
+struct pxa1908_clk_unit {
+	struct mmp_clk_unit unit;
+	void __iomem *mpmu_base;
+	void __iomem *apmu_base;
+	void __iomem *apbc_base;
+	void __iomem *apbcp_base;
+	void __iomem *apbs_base;
+	void __iomem *ciu_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+	{PXA1908_CLK_CLK32, "clk32", NULL, 0, 32768},
+	{PXA1908_CLK_VCTCXO, "vctcxo", NULL, 0, 26 * HZ_PER_MHZ},
+	{PXA1908_CLK_PLL1_624, "pll1_624", NULL, 0, 624 * HZ_PER_MHZ},
+	{PXA1908_CLK_PLL1_416, "pll1_416", NULL, 0, 416 * HZ_PER_MHZ},
+	{PXA1908_CLK_PLL1_499, "pll1_499", NULL, 0, 499 * HZ_PER_MHZ},
+	{PXA1908_CLK_PLL1_832, "pll1_832", NULL, 0, 832 * HZ_PER_MHZ},
+	{PXA1908_CLK_PLL1_1248, "pll1_1248", NULL, 0, 1248 * HZ_PER_MHZ},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+	{PXA1908_CLK_PLL1_D2, "pll1_d2", "pll1_624", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D4, "pll1_d4", "pll1_d2", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D6, "pll1_d6", "pll1_d2", 1, 3, 0},
+	{PXA1908_CLK_PLL1_D8, "pll1_d8", "pll1_d4", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D12, "pll1_d12", "pll1_d6", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D13, "pll1_d13", "pll1_624", 1, 13, 0},
+	{PXA1908_CLK_PLL1_D16, "pll1_d16", "pll1_d8", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D24, "pll1_d24", "pll1_d12", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D48, "pll1_d48", "pll1_d24", 1, 2, 0},
+	{PXA1908_CLK_PLL1_D96, "pll1_d96", "pll1_d48", 1, 2, 0},
+	{PXA1908_CLK_PLL1_32, "pll1_32", "pll1_d13", 2, 3, 0},
+	{PXA1908_CLK_PLL1_208, "pll1_208", "pll1_d2", 2, 3, 0},
+	{PXA1908_CLK_PLL1_117, "pll1_117", "pll1_624", 3, 16, 0},
+};
+
+static struct mmp_clk_factor_masks uart_factor_masks = {
+	.factor = 2,
+	.num_mask = GENMASK(12, 0),
+	.den_mask = GENMASK(12, 0),
+	.num_shift = 16,
+	.den_shift = 0,
+};
+
+static struct u32_fract uart_factor_tbl[] = {
+	{.numerator = 8125, .denominator = 1536},	/* 14.745MHz */
+};
+
+static DEFINE_SPINLOCK(pll1_lock);
+static struct mmp_param_general_gate_clk pll1_gate_clks[] = {
+	{PXA1908_CLK_PLL1_D2_GATE, "pll1_d2_gate", "pll1_d2", 0, APMU_CLK_GATE_CTRL, 29, 0, &pll1_lock},
+	{PXA1908_CLK_PLL1_416_GATE, "pll1_416_gate", "pll1_416", 0, APMU_CLK_GATE_CTRL, 27, 0, &pll1_lock},
+	{PXA1908_CLK_PLL1_624_GATE, "pll1_624_gate", "pll1_624", 0, APMU_CLK_GATE_CTRL, 26, 0, &pll1_lock},
+	{PXA1908_CLK_PLL1_832_GATE, "pll1_832_gate", "pll1_832", 0, APMU_CLK_GATE_CTRL, 30, 0, &pll1_lock},
+	{PXA1908_CLK_PLL1_1248_GATE, "pll1_1248_gate", "pll1_1248", 0, APMU_CLK_GATE_CTRL, 28, 0, &pll1_lock},
+};
+
+static void pxa1908_pll_init(struct pxa1908_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
+					ARRAY_SIZE(fixed_rate_clks));
+
+	mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
+					ARRAY_SIZE(fixed_factor_clks));
+
+	mmp_clk_register_factor("uart_pll", "pll1_d4",
+			CLK_SET_RATE_PARENT,
+			pxa_unit->mpmu_base + MPMU_UART_PLL,
+			&uart_factor_masks, uart_factor_tbl,
+			ARRAY_SIZE(uart_factor_tbl), NULL);
+
+}
+
+static DEFINE_SPINLOCK(pwm0_lock);
+static DEFINE_SPINLOCK(pwm2_lock);
+
+static DEFINE_SPINLOCK(uart0_lock);
+static DEFINE_SPINLOCK(uart1_lock);
+static DEFINE_SPINLOCK(uart2_lock);
+
+static const char * const uart_parent_names[] = {"pll1_117", "uart_pll"};
+static const char * const ssp_parent_names[] = {"pll1_d16", "pll1_d48", "pll1_d24", "pll1_d12"};
+
+static struct mmp_param_gate_clk apbc_gate_clks[] = {
+	{PXA1908_CLK_TWSI0, "twsi0_clk", "pll1_32", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x7, 3, 0, 0, NULL},
+	{PXA1908_CLK_TWSI1, "twsi1_clk", "pll1_32", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x7, 3, 0, 0, NULL},
+	{PXA1908_CLK_TWSI3, "twsi3_clk", "pll1_32", CLK_SET_RATE_PARENT, APBC_TWSI3, 0x7, 3, 0, 0, NULL},
+	{PXA1908_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x7, 3, 0, 0, NULL},
+	{PXA1908_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x7, 3, 0, MMP_CLK_GATE_NEED_DELAY, NULL},
+	{PXA1908_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x87, 0x83, 0, MMP_CLK_GATE_NEED_DELAY, NULL},
+	{PXA1908_CLK_PWM0, "pwm0_clk", "pwm01_apb_share", CLK_SET_RATE_PARENT, APBC_PWM0, 0x2, 2, 0, 0, &pwm0_lock},
+	{PXA1908_CLK_PWM1, "pwm1_clk", "pwm01_apb_share", CLK_SET_RATE_PARENT, APBC_PWM1, 0x6, 2, 0, 0, NULL},
+	{PXA1908_CLK_PWM2, "pwm2_clk", "pwm23_apb_share", CLK_SET_RATE_PARENT, APBC_PWM2, 0x2, 2, 0, 0, NULL},
+	{PXA1908_CLK_PWM3, "pwm3_clk", "pwm23_apb_share", CLK_SET_RATE_PARENT, APBC_PWM3, 0x6, 2, 0, 0, NULL},
+	{PXA1908_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x7, 3, 0, 0, &uart0_lock},
+	{PXA1908_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x7, 3, 0, 0, &uart1_lock},
+};
+
+static struct mmp_param_mux_clk apbc_mux_clks[] = {
+	{0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock},
+	{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
+	{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 0, APBC_SSP0, 4, 3, 0, NULL},
+	{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 0, APBC_SSP2, 4, 3, 0, NULL},
+};
+
+static void pxa1908_apb_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_clk_register_gate(NULL, "pwm01_apb_share", "pll1_d48",
+			CLK_SET_RATE_PARENT,
+			pxa_unit->apbc_base + APBC_PWM0,
+			0x5, 1, 0, 0, &pwm0_lock);
+	mmp_clk_register_gate(NULL, "pwm23_apb_share", "pll1_d48",
+			CLK_SET_RATE_PARENT,
+			pxa_unit->apbc_base + APBC_PWM2,
+			0x5, 1, 0, 0, &pwm2_lock);
+	mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base,
+			ARRAY_SIZE(apbc_mux_clks));
+	mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
+			ARRAY_SIZE(apbc_gate_clks));
+}
+
+static struct mmp_param_gate_clk apbcp_gate_clks[] = {
+	{PXA1908_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBCP_UART2, 0x7, 0x3, 0x0, 0, &uart2_lock},
+	{PXA1908_CLK_TWSI2, "twsi2_clk", "pll1_32", CLK_SET_RATE_PARENT, APBCP_TWSI2, 0x7, 0x3, 0x0, 0, NULL},
+	{PXA1908_CLK_AICER, "ripc_clk", NULL, 0, APBCP_AICER, 0x7, 0x2, 0x0, 0, NULL},
+};
+
+static struct mmp_param_mux_clk apbcp_mux_clks[] = {
+	{0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBCP_UART2, 4, 3, 0, &uart2_lock},
+};
+
+static void pxa1908_apb_p_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_mux_clks(unit, apbcp_mux_clks, pxa_unit->apbcp_base,
+			ARRAY_SIZE(apbcp_mux_clks));
+	mmp_register_gate_clks(unit, apbcp_gate_clks, pxa_unit->apbcp_base,
+			ARRAY_SIZE(apbcp_gate_clks));
+}
+
+static DEFINE_SPINLOCK(sdh0_lock);
+static DEFINE_SPINLOCK(sdh1_lock);
+static DEFINE_SPINLOCK(sdh2_lock);
+
+static const char * const sdh_parent_names[] = {"pll1_416", "pll1_624"};
+
+static struct mmp_clk_mix_config sdh_mix_config = {
+	.reg_info = DEFINE_MIX_REG_INFO(3, 8, 2, 6, 11),
+};
+
+static struct mmp_param_gate_clk apmu_gate_clks[] = {
+	{PXA1908_CLK_USB, "usb_clk", NULL, 0, APMU_USB, 0x9, 0x9, 0x1, 0, NULL},
+	{PXA1908_CLK_SDH0, "sdh0_clk", "sdh0_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH0, 0x12, 0x12, 0x0, 0, &sdh0_lock},
+	{PXA1908_CLK_SDH1, "sdh1_clk", "sdh1_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH1, 0x12, 0x12, 0x0, 0, &sdh1_lock},
+	{PXA1908_CLK_SDH2, "sdh2_clk", "sdh2_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH2, 0x12, 0x12, 0x0, 0, &sdh2_lock}
+};
+
+static void pxa1908_axi_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_general_gate_clks(unit, pll1_gate_clks,
+			pxa_unit->apmu_base, ARRAY_SIZE(pll1_gate_clks));
+
+	sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH0;
+	mmp_clk_register_mix(NULL, "sdh0_mix_clk", sdh_parent_names,
+			ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
+			&sdh_mix_config, &sdh0_lock);
+	sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH1;
+	mmp_clk_register_mix(NULL, "sdh1_mix_clk", sdh_parent_names,
+			ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
+			&sdh_mix_config, &sdh1_lock);
+	sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH2;
+	mmp_clk_register_mix(NULL, "sdh2_mix_clk", sdh_parent_names,
+			ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
+			&sdh_mix_config, &sdh2_lock);
+
+	mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base,
+			ARRAY_SIZE(apmu_gate_clks));
+}
+
+static void __init pxa1908_apbc_clk_init(struct device_node *np)
+{
+	struct pxa1908_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apbc_base = of_iomap(np, 0);
+	if (!pxa_unit->apbc_base) {
+		pr_err("failed to map apbc registers\n");
+		kfree(pxa_unit);
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, APBC_NR_CLKS);
+
+	pxa1908_apb_periph_clk_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1908_apbc, "marvell,pxa1908-apbc", pxa1908_apbc_clk_init);
+
+static void __init pxa1908_apbcp_clk_init(struct device_node *np)
+{
+	struct pxa1908_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apbcp_base = of_iomap(np, 0);
+	if (!pxa_unit->apbcp_base) {
+		pr_err("failed to map apbcp registers\n");
+		kfree(pxa_unit);
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, APBCP_NR_CLKS);
+
+	pxa1908_apb_p_periph_clk_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1908_apbcp, "marvell,pxa1908-apbcp", pxa1908_apbcp_clk_init);
+
+static void __init pxa1908_mpmu_clk_init(struct device_node *np)
+{
+	struct pxa1908_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->mpmu_base = of_iomap(np, 0);
+	if (!pxa_unit->mpmu_base) {
+		pr_err("failed to map mpmu registers\n");
+		kfree(pxa_unit);
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, MPMU_NR_CLKS);
+
+	pxa1908_pll_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1908_mpmu, "marvell,pxa1908-mpmu", pxa1908_mpmu_clk_init);
+
+static void __init pxa1908_apmu_clk_init(struct device_node *np)
+{
+	struct pxa1908_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apmu_base = of_iomap(np, 0);
+	if (!pxa_unit->apmu_base) {
+		pr_err("failed to map apmu registers\n");
+		kfree(pxa_unit);
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, APMU_NR_CLKS);
+
+	pxa1908_axi_periph_clk_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1908_apmu, "marvell,pxa1908-apmu", pxa1908_apmu_clk_init);

-- 
2.44.0



^ permalink raw reply related

* [PATCH v9 1/9] clk: mmp: Switch to use struct u32_fract instead of custom one
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel,
	Andy Shevchenko
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

The struct mmp_clk_factor_tbl repeats the generic struct u32_fract.
Kill the custom one and use the generic one instead.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Tested-by: Duje Mihanović <duje.mihanovic@skole.hr>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 drivers/clk/mmp/clk-frac.c       | 57 ++++++++++++++++++++--------------------
 drivers/clk/mmp/clk-of-mmp2.c    | 26 +++++++++---------
 drivers/clk/mmp/clk-of-pxa168.c  |  4 +--
 drivers/clk/mmp/clk-of-pxa1928.c |  6 ++---
 drivers/clk/mmp/clk-of-pxa910.c  |  4 +--
 drivers/clk/mmp/clk.h            | 10 +++----
 6 files changed, 51 insertions(+), 56 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 1b90867b60c4..6556f6ada2e8 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -26,14 +26,15 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
 {
 	struct mmp_clk_factor *factor = to_clk_factor(hw);
 	u64 rate = 0, prev_rate;
+	struct u32_fract *d;
 	int i;
 
 	for (i = 0; i < factor->ftbl_cnt; i++) {
-		prev_rate = rate;
-		rate = *prate;
-		rate *= factor->ftbl[i].den;
-		do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+		d = &factor->ftbl[i];
 
+		prev_rate = rate;
+		rate = (u64)(*prate) * d->denominator;
+		do_div(rate, d->numerator * factor->masks->factor);
 		if (rate > drate)
 			break;
 	}
@@ -52,23 +53,22 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 {
 	struct mmp_clk_factor *factor = to_clk_factor(hw);
 	struct mmp_clk_factor_masks *masks = factor->masks;
-	unsigned int val, num, den;
+	struct u32_fract d;
+	unsigned int val;
 	u64 rate;
 
 	val = readl_relaxed(factor->base);
 
 	/* calculate numerator */
-	num = (val >> masks->num_shift) & masks->num_mask;
+	d.numerator = (val >> masks->num_shift) & masks->num_mask;
 
 	/* calculate denominator */
-	den = (val >> masks->den_shift) & masks->den_mask;
-
-	if (!den)
+	d.denominator = (val >> masks->den_shift) & masks->den_mask;
+	if (!d.denominator)
 		return 0;
 
-	rate = parent_rate;
-	rate *= den;
-	do_div(rate, num * factor->masks->factor);
+	rate = (u64)parent_rate * d.denominator;
+	do_div(rate, d.numerator * factor->masks->factor);
 
 	return rate;
 }
@@ -82,18 +82,18 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 	int i;
 	unsigned long val;
 	unsigned long flags = 0;
+	struct u32_fract *d;
 	u64 rate = 0;
 
 	for (i = 0; i < factor->ftbl_cnt; i++) {
-		rate = prate;
-		rate *= factor->ftbl[i].den;
-		do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+		d = &factor->ftbl[i];
 
+		rate = (u64)prate * d->denominator;
+		do_div(rate, d->numerator * factor->masks->factor);
 		if (rate > drate)
 			break;
 	}
-	if (i > 0)
-		i--;
+	d = i ? &factor->ftbl[i - 1] : &factor->ftbl[0];
 
 	if (factor->lock)
 		spin_lock_irqsave(factor->lock, flags);
@@ -101,10 +101,10 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 	val = readl_relaxed(factor->base);
 
 	val &= ~(masks->num_mask << masks->num_shift);
-	val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift;
+	val |= (d->numerator & masks->num_mask) << masks->num_shift;
 
 	val &= ~(masks->den_mask << masks->den_shift);
-	val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift;
+	val |= (d->denominator & masks->den_mask) << masks->den_shift;
 
 	writel_relaxed(val, factor->base);
 
@@ -118,7 +118,8 @@ static int clk_factor_init(struct clk_hw *hw)
 {
 	struct mmp_clk_factor *factor = to_clk_factor(hw);
 	struct mmp_clk_factor_masks *masks = factor->masks;
-	u32 val, num, den;
+	struct u32_fract d;
+	u32 val;
 	int i;
 	unsigned long flags = 0;
 
@@ -128,23 +129,22 @@ static int clk_factor_init(struct clk_hw *hw)
 	val = readl(factor->base);
 
 	/* calculate numerator */
-	num = (val >> masks->num_shift) & masks->num_mask;
+	d.numerator = (val >> masks->num_shift) & masks->num_mask;
 
 	/* calculate denominator */
-	den = (val >> masks->den_shift) & masks->den_mask;
+	d.denominator = (val >> masks->den_shift) & masks->den_mask;
 
 	for (i = 0; i < factor->ftbl_cnt; i++)
-		if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+		if (d.denominator == factor->ftbl[i].denominator &&
+		    d.numerator == factor->ftbl[i].numerator)
 			break;
 
 	if (i >= factor->ftbl_cnt) {
 		val &= ~(masks->num_mask << masks->num_shift);
-		val |= (factor->ftbl[0].num & masks->num_mask) <<
-			masks->num_shift;
+		val |= (factor->ftbl[0].numerator & masks->num_mask) << masks->num_shift;
 
 		val &= ~(masks->den_mask << masks->den_shift);
-		val |= (factor->ftbl[0].den & masks->den_mask) <<
-			masks->den_shift;
+		val |= (factor->ftbl[0].denominator & masks->den_mask) << masks->den_shift;
 	}
 
 	if (!(val & masks->enable_mask) || i >= factor->ftbl_cnt) {
@@ -168,8 +168,7 @@ static const struct clk_ops clk_factor_ops = {
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
 		unsigned long flags, void __iomem *base,
 		struct mmp_clk_factor_masks *masks,
-		struct mmp_clk_factor_tbl *ftbl,
-		unsigned int ftbl_cnt, spinlock_t *lock)
+		struct u32_fract *ftbl, unsigned int ftbl_cnt, spinlock_t *lock)
 {
 	struct mmp_clk_factor *factor;
 	struct clk_init_data init;
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index eaad36ee323d..a4f15cee630e 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -143,9 +143,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 8125, .den = 1536},	/*14.745MHZ */
-	{.num = 3521, .den = 689},	/*19.23MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+	{ .numerator = 8125, .denominator = 1536 },	/* 14.745MHZ */
+	{ .numerator = 3521, .denominator =  689 },	/* 19.23MHZ */
 };
 
 static struct mmp_clk_factor_masks i2s_factor_masks = {
@@ -157,16 +157,16 @@ static struct mmp_clk_factor_masks i2s_factor_masks = {
 	.enable_mask = 0xd0000000,
 };
 
-static struct mmp_clk_factor_tbl i2s_factor_tbl[] = {
-	{.num = 24868, .den =  511},	/*  2.0480 MHz */
-	{.num = 28003, .den =  793},	/*  2.8224 MHz */
-	{.num = 24941, .den = 1025},	/*  4.0960 MHz */
-	{.num = 28003, .den = 1586},	/*  5.6448 MHz */
-	{.num = 31158, .den = 2561},	/*  8.1920 MHz */
-	{.num = 16288, .den = 1845},	/* 11.2896 MHz */
-	{.num = 20772, .den = 2561},	/* 12.2880 MHz */
-	{.num =  8144, .den = 1845},	/* 22.5792 MHz */
-	{.num = 10386, .den = 2561},	/* 24.5760 MHz */
+static struct u32_fract i2s_factor_tbl[] = {
+	{ .numerator = 24868, .denominator =  511 },	/*  2.0480 MHz */
+	{ .numerator = 28003, .denominator =  793 },	/*  2.8224 MHz */
+	{ .numerator = 24941, .denominator = 1025 },	/*  4.0960 MHz */
+	{ .numerator = 28003, .denominator = 1586 },	/*  5.6448 MHz */
+	{ .numerator = 31158, .denominator = 2561 },	/*  8.1920 MHz */
+	{ .numerator = 16288, .denominator = 1845 },	/* 11.2896 MHz */
+	{ .numerator = 20772, .denominator = 2561 },	/* 12.2880 MHz */
+	{ .numerator =  8144, .denominator = 1845 },	/* 22.5792 MHz */
+	{ .numerator = 10386, .denominator = 2561 },	/* 24.5760 MHz */
 };
 
 static DEFINE_SPINLOCK(acgr_lock);
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index c5a7ba1deaa3..5f250427e60d 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -106,8 +106,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 8125, .den = 1536},	/*14.745MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+	{ .numerator = 8125, .denominator = 1536 },	/* 14.745MHZ */
 };
 
 static void pxa168_pll_init(struct pxa168_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c
index 9def4b5f10e9..ebb6e278eda3 100644
--- a/drivers/clk/mmp/clk-of-pxa1928.c
+++ b/drivers/clk/mmp/clk-of-pxa1928.c
@@ -61,9 +61,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 832, .den = 234},	/*58.5MHZ */
-	{.num = 1, .den = 1},		/*26MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+	{ .numerator = 832, .denominator = 234 },	/* 58.5MHZ */
+	{ .numerator =   1, .denominator =   1 },	/* 26MHZ */
 };
 
 static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 7a38c424782e..fe65e7bdb411 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -86,8 +86,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 	.den_shift = 0,
 };
 
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 8125, .den = 1536},	/*14.745MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+	{ .numerator = 8125, .denominator = 1536 },	/* 14.745MHZ */
 };
 
 static void pxa910_pll_init(struct pxa910_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 55ac05379781..c83cec169ddc 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -3,6 +3,7 @@
 #define __MACH_MMP_CLK_H
 
 #include <linux/clk-provider.h>
+#include <linux/math.h>
 #include <linux/pm_domain.h>
 #include <linux/clkdev.h>
 
@@ -20,16 +21,11 @@ struct mmp_clk_factor_masks {
 	unsigned int enable_mask;
 };
 
-struct mmp_clk_factor_tbl {
-	unsigned int num;
-	unsigned int den;
-};
-
 struct mmp_clk_factor {
 	struct clk_hw hw;
 	void __iomem *base;
 	struct mmp_clk_factor_masks *masks;
-	struct mmp_clk_factor_tbl *ftbl;
+	struct u32_fract *ftbl;
 	unsigned int ftbl_cnt;
 	spinlock_t *lock;
 };
@@ -37,7 +33,7 @@ struct mmp_clk_factor {
 extern struct clk *mmp_clk_register_factor(const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *base, struct mmp_clk_factor_masks *masks,
-		struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+		struct u32_fract *ftbl, unsigned int ftbl_cnt,
 		spinlock_t *lock);
 
 /* Clock type "mix" */

-- 
2.44.0



^ permalink raw reply related

* [PATCH v9 3/9] pinctrl: single: add marvell,pxa1908-padconf compatible
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add the "marvell,pxa1908-padconf" compatible to allow migrating to a
separate pinctrl driver later.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 drivers/pinctrl/pinctrl-single.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 19cc0db771a5..c15bf3cbabd7 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1967,6 +1967,7 @@ static const struct pcs_soc_data pinconf_single = {
 };
 
 static const struct of_device_id pcs_of_match[] = {
+	{ .compatible = "marvell,pxa1908-padconf", .data = &pinconf_single },
 	{ .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x },
 	{ .compatible = "ti,am654-padconf", .data = &pinctrl_single_am654 },
 	{ .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 },

-- 
2.44.0



^ permalink raw reply related

* [PATCH v9 7/9] arm64: Kconfig.platforms: Add config for Marvell PXA1908 platform
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add ARCH_MMP configuration option for Marvell PXA1908 SoC.

Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 arch/arm64/Kconfig.platforms | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 24335565bad5..d71b0b6e75aa 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -168,6 +168,14 @@ config ARCH_MESON
 	  This enables support for the arm64 based Amlogic SoCs
 	  such as the s905, S905X/D, S912, A113X/D or S905X/D2
 
+config ARCH_MMP
+	bool "Marvell MMP SoC Family"
+	select PINCTRL
+	select PINCTRL_SINGLE
+	help
+	  This enables support for Marvell MMP SoC family, currently
+	  supporting PXA1908 aka IAP140.
+
 config ARCH_MVEBU
 	bool "Marvell EBU SoC Family"
 	select ARMADA_AP806_SYSCON

-- 
2.44.0



^ permalink raw reply related

* [PATCH v9 2/9] dt-bindings: pinctrl: pinctrl-single: add marvell,pxa1908-padconf compatible
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add the "marvell,pxa1908-padconf" compatible to allow migrating to a
separate pinctrl driver later.

Reviewed-by: Rob Herring <robh@kernel.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml
index c11495524dd2..1ce24ad8bc73 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml
@@ -33,6 +33,10 @@ properties:
               - ti,omap5-padconf
               - ti,j7200-padconf
           - const: pinctrl-single
+      - items:
+          - enum:
+              - marvell,pxa1908-padconf
+          - const: pinconf-single
 
   reg:
     maxItems: 1

-- 
2.44.0



^ permalink raw reply related

* [PATCH v9 4/9] dt-bindings: clock: Add Marvell PXA1908 clock bindings
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel,
	Conor Dooley
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add dt bindings and documentation for the Marvell PXA1908 clock
controller.

Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 .../devicetree/bindings/clock/marvell,pxa1908.yaml | 48 ++++++++++++
 include/dt-bindings/clock/marvell,pxa1908.h        | 88 ++++++++++++++++++++++
 2 files changed, 136 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml b/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml
new file mode 100644
index 000000000000..4e78933232b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/marvell,pxa1908.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell PXA1908 Clock Controllers
+
+maintainers:
+  - Duje Mihanović <duje.mihanovic@skole.hr>
+
+description: |
+  The PXA1908 clock subsystem generates and supplies clock to various
+  controllers within the PXA1908 SoC. The PXA1908 contains numerous clock
+  controller blocks, with the ones currently supported being APBC, APBCP, MPMU
+  and APMU roughly corresponding to internal buses.
+
+  All these clock identifiers could be found in <include/dt-bindings/marvell,pxa1908.h>.
+
+properties:
+  compatible:
+    enum:
+      - marvell,pxa1908-apbc
+      - marvell,pxa1908-apbcp
+      - marvell,pxa1908-mpmu
+      - marvell,pxa1908-apmu
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  # APMU block:
+  - |
+    clock-controller@d4282800 {
+      compatible = "marvell,pxa1908-apmu";
+      reg = <0xd4282800 0x400>;
+      #clock-cells = <1>;
+    };
diff --git a/include/dt-bindings/clock/marvell,pxa1908.h b/include/dt-bindings/clock/marvell,pxa1908.h
new file mode 100644
index 000000000000..fb15b0d0cd4c
--- /dev/null
+++ b/include/dt-bindings/clock/marvell,pxa1908.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+#ifndef __DTS_MARVELL_PXA1908_CLOCK_H
+#define __DTS_MARVELL_PXA1908_CLOCK_H
+
+/* plls */
+#define PXA1908_CLK_CLK32		1
+#define PXA1908_CLK_VCTCXO		2
+#define PXA1908_CLK_PLL1_624		3
+#define PXA1908_CLK_PLL1_416		4
+#define PXA1908_CLK_PLL1_499		5
+#define PXA1908_CLK_PLL1_832		6
+#define PXA1908_CLK_PLL1_1248		7
+#define PXA1908_CLK_PLL1_D2		8
+#define PXA1908_CLK_PLL1_D4		9
+#define PXA1908_CLK_PLL1_D8		10
+#define PXA1908_CLK_PLL1_D16		11
+#define PXA1908_CLK_PLL1_D6		12
+#define PXA1908_CLK_PLL1_D12		13
+#define PXA1908_CLK_PLL1_D24		14
+#define PXA1908_CLK_PLL1_D48		15
+#define PXA1908_CLK_PLL1_D96		16
+#define PXA1908_CLK_PLL1_D13		17
+#define PXA1908_CLK_PLL1_32		18
+#define PXA1908_CLK_PLL1_208		19
+#define PXA1908_CLK_PLL1_117		20
+#define PXA1908_CLK_PLL1_416_GATE	21
+#define PXA1908_CLK_PLL1_624_GATE	22
+#define PXA1908_CLK_PLL1_832_GATE	23
+#define PXA1908_CLK_PLL1_1248_GATE	24
+#define PXA1908_CLK_PLL1_D2_GATE	25
+#define PXA1908_CLK_PLL1_499_EN		26
+#define PXA1908_CLK_PLL2VCO		27
+#define PXA1908_CLK_PLL2		28
+#define PXA1908_CLK_PLL2P		29
+#define PXA1908_CLK_PLL2VCODIV3		30
+#define PXA1908_CLK_PLL3VCO		31
+#define PXA1908_CLK_PLL3		32
+#define PXA1908_CLK_PLL3P		33
+#define PXA1908_CLK_PLL3VCODIV3		34
+#define PXA1908_CLK_PLL4VCO		35
+#define PXA1908_CLK_PLL4		36
+#define PXA1908_CLK_PLL4P		37
+#define PXA1908_CLK_PLL4VCODIV3		38
+
+/* apb (apbc) peripherals */
+#define PXA1908_CLK_UART0		1
+#define PXA1908_CLK_UART1		2
+#define PXA1908_CLK_GPIO		3
+#define PXA1908_CLK_PWM0		4
+#define PXA1908_CLK_PWM1		5
+#define PXA1908_CLK_PWM2		6
+#define PXA1908_CLK_PWM3		7
+#define PXA1908_CLK_SSP0		8
+#define PXA1908_CLK_SSP1		9
+#define PXA1908_CLK_IPC_RST		10
+#define PXA1908_CLK_RTC			11
+#define PXA1908_CLK_TWSI0		12
+#define PXA1908_CLK_KPC			13
+#define PXA1908_CLK_SWJTAG		14
+#define PXA1908_CLK_SSP2		15
+#define PXA1908_CLK_TWSI1		16
+#define PXA1908_CLK_THERMAL		17
+#define PXA1908_CLK_TWSI3		18
+
+/* apb (apbcp) peripherals */
+#define PXA1908_CLK_UART2		1
+#define PXA1908_CLK_TWSI2		2
+#define PXA1908_CLK_AICER		3
+
+/* axi (apmu) peripherals */
+#define PXA1908_CLK_CCIC1		1
+#define PXA1908_CLK_ISP			2
+#define PXA1908_CLK_DSI1		3
+#define PXA1908_CLK_DISP1		4
+#define PXA1908_CLK_CCIC0		5
+#define PXA1908_CLK_SDH0		6
+#define PXA1908_CLK_SDH1		7
+#define PXA1908_CLK_USB			8
+#define PXA1908_CLK_NF			9
+#define PXA1908_CLK_CORE_DEBUG		10
+#define PXA1908_CLK_VPU			11
+#define PXA1908_CLK_GC			12
+#define PXA1908_CLK_SDH2		13
+#define PXA1908_CLK_GC2D		14
+#define PXA1908_CLK_TRACE		15
+#define PXA1908_CLK_DVC_DFC_DEBUG	16
+
+#endif

-- 
2.44.0



^ permalink raw reply related

* [PATCH v9 6/9] dt-bindings: marvell: Document PXA1908 SoC
From: Duje Mihanović @ 2024-04-02 20:55 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Tony Lindgren, Haojian Zhuang,
	Duje Mihanović, Lubomir Rintel, Catalin Marinas, Will Deacon,
	Kees Cook, Tony Luck, Guilherme G. Piccoli, Rob Herring
  Cc: phone-devel, ~postmarketos/upstreaming, Karel Balej, David Wronek,
	linux-clk, linux-kernel, linux-gpio, devicetree, linux-arm-kernel,
	Krzysztof Kozlowski
In-Reply-To: <20240402-pxa1908-lkml-v9-0-25a003e83c6f@skole.hr>

Add dt binding for the Marvell PXA1908 SoC.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr>
---
 Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml b/Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml
index 4c43eaf3632e..f73bb8ec3a1a 100644
--- a/Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml
+++ b/Documentation/devicetree/bindings/arm/mrvl/mrvl.yaml
@@ -35,6 +35,11 @@ properties:
           - enum:
               - dell,wyse-ariel
           - const: marvell,mmp3
+      - description: PXA1908 based boards
+        items:
+          - enum:
+              - samsung,coreprimevelte
+          - const: marvell,pxa1908
 
 additionalProperties: true
 

-- 
2.44.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox