mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-15 07:02:09 +00:00
qualcommax: add ipq50xx target
Introduce support for the Qualcomm IPQ50xx SoC. This series adds support for the following components: - minimal boot support: GCC/pinctrl/watchdog/CPUFreq/SDI (upstreamed) - USB2 (upstreamed) - Thermal/Tsens - PCIe gen2 1&2-lane PHY and controller - PWM and PWM LED - QPIC SPI NAND controller - CMN PLL Block (provider of fixed rate clocks to GCC/ethernet/more.) - Ethernet: IPQ5018 Internal GE PHY (1 gbps) - Remoteproc MPD driver for IPQ5018 (2.4G) & QCN6122 (5/6G) Wifi Co-developed-by: Ziyang Huang <hzyitc@outlook.com> Signed-off-by: Ziyang Huang <hzyitc@outlook.com> Signed-off-by: George Moussalem <george.moussalem@outlook.com> Link: https://github.com/openwrt/openwrt/pull/17182 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
39750798f7
commit
34d9172655
@ -6,7 +6,7 @@ BOARDNAME:=Qualcomm Atheros 802.11ax WiSoC-s
|
||||
FEATURES:=squashfs ramdisk fpu nand rtc emmc
|
||||
KERNELNAME:=Image
|
||||
CPU_TYPE:=cortex-a53
|
||||
SUBTARGETS:=ipq807x ipq60xx
|
||||
SUBTARGETS:=ipq807x ipq60xx ipq50xx
|
||||
|
||||
KERNEL_PATCHVER:=6.6
|
||||
|
||||
|
@ -0,0 +1,116 @@
|
||||
#include <dt-bindings/net/qcom-ipq-ess.h>
|
||||
|
||||
&soc {
|
||||
ess_instance: ess-instance {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
num_devices = <1>;
|
||||
|
||||
switch: ess-switch@39c00000 {
|
||||
compatible = "qcom,ess-switch-ipq50xx";
|
||||
device_id = <0>;
|
||||
cmnblk_clk = "internal_96MHz";
|
||||
reg = <0x39c00000 0x200000>;
|
||||
switch_access_mode = "local bus";
|
||||
clocks = <&gcc GCC_CMN_BLK_AHB_CLK>,
|
||||
<&gcc GCC_CMN_BLK_SYS_CLK>,
|
||||
<&gcc GCC_UNIPHY_AHB_CLK>,
|
||||
<&gcc GCC_UNIPHY_SYS_CLK>,
|
||||
<&gcc GCC_MDIO0_AHB_CLK>,
|
||||
<&gcc GCC_MDIO1_AHB_CLK>,
|
||||
<&gcc GCC_GMAC0_CFG_CLK>,
|
||||
<&gcc GCC_GMAC0_SYS_CLK>,
|
||||
<&gcc GCC_GMAC1_CFG_CLK>,
|
||||
<&gcc GCC_GMAC1_SYS_CLK>,
|
||||
<&gcc GCC_GEPHY_RX_CLK>,
|
||||
<&gcc GCC_GEPHY_TX_CLK>,
|
||||
<&gcc GCC_UNIPHY_RX_CLK>,
|
||||
<&gcc GCC_UNIPHY_TX_CLK>,
|
||||
<&gcc GCC_GMAC0_RX_CLK>,
|
||||
<&gcc GCC_GMAC0_TX_CLK>,
|
||||
<&gcc GCC_GMAC1_RX_CLK>,
|
||||
<&gcc GCC_GMAC1_TX_CLK>,
|
||||
<&gcc GCC_SNOC_GMAC0_AHB_CLK>,
|
||||
<&gcc GCC_SNOC_GMAC1_AHB_CLK>,
|
||||
<&gcc GCC_GMAC0_PTP_CLK>,
|
||||
<&gcc GCC_GMAC1_PTP_CLK>;
|
||||
clock-names = "cmn_ahb_clk",
|
||||
"cmn_sys_clk",
|
||||
"uniphy_ahb_clk",
|
||||
"uniphy_sys_clk",
|
||||
"gcc_mdio0_ahb_clk",
|
||||
"gcc_mdio1_ahb_clk",
|
||||
"gcc_gmac0_cfg_clk",
|
||||
"gcc_gmac0_sys_clk",
|
||||
"gcc_gmac1_cfg_clk",
|
||||
"gcc_gmac1_sys_clk",
|
||||
"uniphy0_port1_rx_clk",
|
||||
"uniphy0_port1_tx_clk",
|
||||
"uniphy1_port5_rx_clk",
|
||||
"uniphy1_port5_tx_clk",
|
||||
"nss_port1_rx_clk",
|
||||
"nss_port1_tx_clk",
|
||||
"nss_port2_rx_clk",
|
||||
"nss_port2_tx_clk",
|
||||
"gcc_snoc_gmac0_ahb_clk",
|
||||
"gcc_snoc_gmac1_ahb_clk",
|
||||
"gcc_gmac0_ptp_clk",
|
||||
"gcc_gmac1_ptp_clk";
|
||||
resets = <&gcc GCC_GMAC0_BCR>,
|
||||
<&gcc GCC_GMAC1_BCR>,
|
||||
<&gcc GCC_UNIPHY_BCR>,
|
||||
<&gcc GCC_UNIPHY_SOFT_RESET>;
|
||||
reset-names = "gmac0_bcr_rst",
|
||||
"gmac1_bcr_rst",
|
||||
"uniphy_bcr_rst",
|
||||
"uniphy1_soft_rst";
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
ess-uniphy@98000 {
|
||||
compatible = "qcom,ess-uniphy";
|
||||
reg = <0x98000 0x800>;
|
||||
uniphy_access_mode = "local bus";
|
||||
};
|
||||
|
||||
nss-dp-common {
|
||||
compatible = "qcom,nss-dp-common";
|
||||
qcom,tcsr-base = <0x01937000>;
|
||||
};
|
||||
|
||||
dp1: dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <1>;
|
||||
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
|
||||
qcom,mactype = <2>; /* GMAC_HAL_TYPE_SYN_GMAC */
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&ge_phy>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dp2: dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
qcom,id = <2>;
|
||||
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
|
||||
qcom,mactype = <2>; /* GMAC_HAL_TYPE_SYN_GMAC */
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
0
target/linux/qualcommax/image/ipq50xx.mk
Normal file
0
target/linux/qualcommax/image/ipq50xx.mk
Normal file
26
target/linux/qualcommax/ipq50xx/config-default
Normal file
26
target/linux/qualcommax/ipq50xx/config-default
Normal file
@ -0,0 +1,26 @@
|
||||
CONFIG_QCOM_APM=y
|
||||
CONFIG_IPQ_GCC_5018=y
|
||||
CONFIG_PINCTRL_IPQ5018=y
|
||||
|
||||
CONFIG_MTD_SPI_NAND=y
|
||||
CONFIG_SPI_QPIC_SNAND=y
|
||||
|
||||
CONFIG_IPQ_CMN_PLL=y
|
||||
CONFIG_IPQ5018_PHY=y
|
||||
CONFIG_NET_DSA=y
|
||||
CONFIG_NET_DSA_QCA8K=y
|
||||
CONFIG_NET_DSA_TAG_QCA=y
|
||||
CONFIG_QCA83XX_PHY=y
|
||||
|
||||
CONFIG_QCOM_Q6V5_MPD=y
|
||||
CONFIG_QCOM_QMI_HELPERS=y
|
||||
|
||||
CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP=y
|
||||
CONFIG_PCIE_QCOM=y
|
||||
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_IPQ=y
|
||||
CONFIG_LEDS_PWM=y
|
||||
|
||||
CONFIG_PHY_QCOM_M31_USB=y
|
||||
CONFIG_USB_DWC3_QCOM=y
|
7
target/linux/qualcommax/ipq50xx/target.mk
Normal file
7
target/linux/qualcommax/ipq50xx/target.mk
Normal file
@ -0,0 +1,7 @@
|
||||
SUBTARGET:=ipq50xx
|
||||
BOARDNAME:=Qualcomm Atheros IPQ50xx
|
||||
DEFAULT_PACKAGES += ath11k-firmware-ipq5018
|
||||
|
||||
define Target/Description
|
||||
Build firmware images for Qualcomm Atheros IPQ50xx based boards.
|
||||
endef
|
@ -0,0 +1,31 @@
|
||||
From 9cbaee8379e620f82112002f973adde19679df31 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Wed, 16 Aug 2023 18:14:00 +0200
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: add watchdog
|
||||
|
||||
Add the required DT node for watchdog operation.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230816161455.3310629-2-robimarko@gmail.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -181,6 +181,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ watchdog: watchdog@b017000 {
|
||||
+ compatible = "qcom,apss-wdt-ipq5018", "qcom,kpss-wdt";
|
||||
+ reg = <0x0b017000 0x40>;
|
||||
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
|
||||
+ clocks = <&sleep_clk>;
|
||||
+ };
|
||||
+
|
||||
timer@b120000 {
|
||||
compatible = "arm,armv7-timer-mem";
|
||||
reg = <0x0b120000 0x1000>;
|
@ -0,0 +1,41 @@
|
||||
From 92dab9ea5f389c12828283146c60054642453a91 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Wed, 16 Aug 2023 18:45:38 +0200
|
||||
Subject: [PATCH] dt-bindings: firmware: qcom,scm: support indicating SDI
|
||||
default state
|
||||
|
||||
IPQ5018 has SDI (Secure Debug Image) enabled by TZ by default, and that
|
||||
means that WDT being asserted or just trying to reboot will hang the board
|
||||
in the debug mode and only pulling the power and repowering will help.
|
||||
Some IPQ4019 boards like Google WiFI have it enabled as well.
|
||||
|
||||
So, lets add a boolean property to indicate that SDI is enabled by default
|
||||
and thus needs to be disabled by the kernel.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Acked-by: Mukesh Ojha <quic_mojha@quicinc.com>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20230816164641.3371878-1-robimarko@gmail.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
|
||||
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
|
||||
@@ -89,6 +89,14 @@ properties:
|
||||
protocol to handle sleeping SCM calls.
|
||||
maxItems: 1
|
||||
|
||||
+ qcom,sdi-enabled:
|
||||
+ description:
|
||||
+ Indicates that the SDI (Secure Debug Image) has been enabled by TZ
|
||||
+ by default and it needs to be disabled.
|
||||
+ If not disabled WDT assertion or reboot will cause the board to hang
|
||||
+ in the debug mode.
|
||||
+ type: boolean
|
||||
+
|
||||
qcom,dload-mode:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
@ -0,0 +1,83 @@
|
||||
From ff4aa3bc98258a240b9bbab53fd8d2fb8184c485 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Wed, 16 Aug 2023 18:45:39 +0200
|
||||
Subject: [PATCH] firmware: qcom_scm: disable SDI if required
|
||||
|
||||
IPQ5018 has SDI (Secure Debug Image) enabled by TZ by default, and that
|
||||
means that WDT being asserted or just trying to reboot will hang the board
|
||||
in the debug mode and only pulling the power and repowering will help.
|
||||
Some IPQ4019 boards like Google WiFI have it enabled as well.
|
||||
|
||||
Luckily, SDI can be disabled via an SCM call.
|
||||
|
||||
So, lets use the boolean DT property to identify boards that have SDI
|
||||
enabled by default and use the SCM call to disable SDI during SCM probe.
|
||||
It is important to disable it as soon as possible as we might have a WDT
|
||||
assertion at any time which would then leave the board in debug mode,
|
||||
thus disabling it during SCM removal is not enough.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Reviewed-by: Guru Das Srinagesh <quic_gurus@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20230816164641.3371878-2-robimarko@gmail.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
drivers/firmware/qcom_scm.c | 30 ++++++++++++++++++++++++++++++
|
||||
drivers/firmware/qcom_scm.h | 1 +
|
||||
2 files changed, 31 insertions(+)
|
||||
|
||||
--- a/drivers/firmware/qcom_scm.c
|
||||
+++ b/drivers/firmware/qcom_scm.c
|
||||
@@ -410,6 +410,29 @@ int qcom_scm_set_remote_state(u32 state,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_set_remote_state);
|
||||
|
||||
+static int qcom_scm_disable_sdi(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct qcom_scm_desc desc = {
|
||||
+ .svc = QCOM_SCM_SVC_BOOT,
|
||||
+ .cmd = QCOM_SCM_BOOT_SDI_CONFIG,
|
||||
+ .args[0] = 1, /* Disable watchdog debug */
|
||||
+ .args[1] = 0, /* Disable SDI */
|
||||
+ .arginfo = QCOM_SCM_ARGS(2),
|
||||
+ .owner = ARM_SMCCC_OWNER_SIP,
|
||||
+ };
|
||||
+ struct qcom_scm_res res;
|
||||
+
|
||||
+ ret = qcom_scm_clk_enable();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
+
|
||||
+ qcom_scm_clk_disable();
|
||||
+
|
||||
+ return ret ? : res.result[0];
|
||||
+}
|
||||
+
|
||||
static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
|
||||
{
|
||||
struct qcom_scm_desc desc = {
|
||||
@@ -1473,6 +1496,13 @@ static int qcom_scm_probe(struct platfor
|
||||
|
||||
__get_convention();
|
||||
|
||||
+
|
||||
+ /*
|
||||
+ * Disable SDI if indicated by DT that it is enabled by default.
|
||||
+ */
|
||||
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled"))
|
||||
+ qcom_scm_disable_sdi();
|
||||
+
|
||||
/*
|
||||
* If requested enable "download mode", from this point on warmboot
|
||||
* will cause the boot stages to enter download mode, unless
|
||||
--- a/drivers/firmware/qcom_scm.h
|
||||
+++ b/drivers/firmware/qcom_scm.h
|
||||
@@ -80,6 +80,7 @@ extern int scm_legacy_call(struct device
|
||||
#define QCOM_SCM_SVC_BOOT 0x01
|
||||
#define QCOM_SCM_BOOT_SET_ADDR 0x01
|
||||
#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
|
||||
+#define QCOM_SCM_BOOT_SDI_CONFIG 0x09
|
||||
#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10
|
||||
#define QCOM_SCM_BOOT_SET_ADDR_MC 0x11
|
||||
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
|
@ -0,0 +1,25 @@
|
||||
From f6aa7386bc40b552eea8ec1b1d2168afe3b31110 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Wed, 16 Aug 2023 18:45:40 +0200
|
||||
Subject: [PATCH] dt-bindings: firmware: qcom,scm: document IPQ5018 compatible
|
||||
|
||||
It seems that IPQ5018 compatible was never documented in the bindings.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230816164641.3371878-3-robimarko@gmail.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
|
||||
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
|
||||
@@ -24,6 +24,7 @@ properties:
|
||||
- qcom,scm-apq8064
|
||||
- qcom,scm-apq8084
|
||||
- qcom,scm-ipq4019
|
||||
+ - qcom,scm-ipq5018
|
||||
- qcom,scm-ipq5332
|
||||
- qcom,scm-ipq6018
|
||||
- qcom,scm-ipq806x
|
@ -0,0 +1,26 @@
|
||||
From 79796e87215db9587d6c66ec6f6781e091bc6464 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Wed, 16 Aug 2023 18:45:41 +0200
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: indicate that SDI should be
|
||||
disabled
|
||||
|
||||
Now that SCM has support for indicating that SDI has been enabled by
|
||||
default, lets set the property so SCM disables it during probing.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20230816164641.3371878-4-robimarko@gmail.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -57,6 +57,7 @@
|
||||
firmware {
|
||||
scm {
|
||||
compatible = "qcom,scm-ipq5018", "qcom,scm";
|
||||
+ qcom,sdi-enabled;
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,28 @@
|
||||
From 1852dfaacd3f4358bbfca134b63a02bbb30c1136 Mon Sep 17 00:00:00 2001
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Date: Mon, 4 Sep 2023 12:06:32 +0530
|
||||
Subject: [PATCH] dt-bindings: phy: qcom,m31: Add IPQ5018 compatible
|
||||
|
||||
IPQ5332 qcom,m31 phy driver can support IPQ5018.
|
||||
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20230904063635.24975-2-quic_nsekar@quicinc.com
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
.../devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
|
||||
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
|
||||
@@ -17,7 +17,9 @@ description:
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- - const: qcom,ipq5332-usb-hsphy
|
||||
+ - enum:
|
||||
+ - qcom,ipq5018-usb-hsphy
|
||||
+ - qcom,ipq5332-usb-hsphy
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
@ -0,0 +1,89 @@
|
||||
From 68320e35f8cb1987b4ad34347fc7033832da99e3 Mon Sep 17 00:00:00 2001
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Date: Mon, 4 Sep 2023 12:06:33 +0530
|
||||
Subject: [PATCH] phy: qcom-m31: Add compatible, phy init sequence for IPQ5018
|
||||
|
||||
Add phy init sequence and compatible string for IPQ5018
|
||||
chipset.
|
||||
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20230904063635.24975-3-quic_nsekar@quicinc.com
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/qualcomm/phy-qcom-m31.c | 51 +++++++++++++++++++++++++++++
|
||||
1 file changed, 51 insertions(+)
|
||||
|
||||
--- a/drivers/phy/qualcomm/phy-qcom-m31.c
|
||||
+++ b/drivers/phy/qualcomm/phy-qcom-m31.c
|
||||
@@ -82,6 +82,50 @@ struct m31_priv_data {
|
||||
unsigned int nregs;
|
||||
};
|
||||
|
||||
+static const struct m31_phy_regs m31_ipq5018_regs[] = {
|
||||
+ {
|
||||
+ .off = USB_PHY_CFG0,
|
||||
+ .val = UTMI_PHY_OVERRIDE_EN
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_UTMI_CTRL5,
|
||||
+ .val = POR_EN,
|
||||
+ .delay = 15
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_FSEL_SEL,
|
||||
+ .val = FREQ_SEL
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_HS_PHY_CTRL_COMMON0,
|
||||
+ .val = COMMONONN | FSEL | RETENABLEN
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_REFCLK_CTRL,
|
||||
+ .val = CLKCORE
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_UTMI_CTRL5,
|
||||
+ .val = POR_EN
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_HS_PHY_CTRL2,
|
||||
+ .val = USB2_SUSPEND_N_SEL | USB2_SUSPEND_N | USB2_UTMI_CLK_EN
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_UTMI_CTRL5,
|
||||
+ .val = 0x0
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_HS_PHY_CTRL2,
|
||||
+ .val = USB2_SUSPEND_N | USB2_UTMI_CLK_EN
|
||||
+ },
|
||||
+ {
|
||||
+ .off = USB_PHY_CFG0,
|
||||
+ .val = 0x0
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static struct m31_phy_regs m31_ipq5332_regs[] = {
|
||||
{
|
||||
USB_PHY_CFG0,
|
||||
@@ -267,6 +311,12 @@ static int m31usb_phy_probe(struct platf
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
+static const struct m31_priv_data m31_ipq5018_data = {
|
||||
+ .ulpi_mode = false,
|
||||
+ .regs = m31_ipq5018_regs,
|
||||
+ .nregs = ARRAY_SIZE(m31_ipq5018_regs),
|
||||
+};
|
||||
+
|
||||
static const struct m31_priv_data m31_ipq5332_data = {
|
||||
.ulpi_mode = false,
|
||||
.regs = m31_ipq5332_regs,
|
||||
@@ -274,6 +324,7 @@ static const struct m31_priv_data m31_ip
|
||||
};
|
||||
|
||||
static const struct of_device_id m31usb_phy_id_table[] = {
|
||||
+ { .compatible = "qcom,ipq5018-usb-hsphy", .data = &m31_ipq5018_data },
|
||||
{ .compatible = "qcom,ipq5332-usb-hsphy", .data = &m31_ipq5332_data },
|
||||
{ },
|
||||
};
|
@ -0,0 +1,41 @@
|
||||
From 3865a64284cc4845c61cf3dc6c7246349d80cc49 Mon Sep 17 00:00:00 2001
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Date: Thu, 31 Aug 2023 08:35:03 +0530
|
||||
Subject: [PATCH] dt-bindings: usb: dwc3: Add IPQ5018 compatible
|
||||
|
||||
Document the IPQ5018 dwc3 compatible.
|
||||
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20230831030503.17100-1-quic_nsekar@quicinc.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
|
||||
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
|
||||
@@ -14,6 +14,7 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,ipq4019-dwc3
|
||||
+ - qcom,ipq5018-dwc3
|
||||
- qcom,ipq5332-dwc3
|
||||
- qcom,ipq6018-dwc3
|
||||
- qcom,ipq8064-dwc3
|
||||
@@ -238,6 +239,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
+ - qcom,ipq5018-dwc3
|
||||
- qcom,ipq5332-dwc3
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,qcs404-dwc3
|
||||
@@ -411,6 +413,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
+ - qcom,ipq5018-dwc3
|
||||
- qcom,ipq5332-dwc3
|
||||
- qcom,sdm660-dwc3
|
||||
then:
|
@ -0,0 +1,86 @@
|
||||
From e7166f2774aafefd29ff26ffbbb7f6d40ac8ea1c Mon Sep 17 00:00:00 2001
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Date: Mon, 4 Sep 2023 12:06:34 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add USB related nodes
|
||||
|
||||
Add USB phy and controller nodes.
|
||||
|
||||
Co-developed-by: Amandeep Singh <quic_amansing@quicinc.com>
|
||||
Signed-off-by: Amandeep Singh <quic_amansing@quicinc.com>
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20230904063635.24975-4-quic_nsekar@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 54 +++++++++++++++++++++++++++
|
||||
1 file changed, 54 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -94,6 +94,19 @@
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0 0 0xffffffff>;
|
||||
|
||||
+ usbphy0: phy@5b000 {
|
||||
+ compatible = "qcom,ipq5018-usb-hsphy";
|
||||
+ reg = <0x0005b000 0x120>;
|
||||
+
|
||||
+ clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>;
|
||||
+
|
||||
+ resets = <&gcc GCC_QUSB2_0_PHY_BCR>;
|
||||
+
|
||||
+ #phy-cells = <0>;
|
||||
+
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
tlmm: pinctrl@1000000 {
|
||||
compatible = "qcom,ipq5018-tlmm";
|
||||
reg = <0x01000000 0x300000>;
|
||||
@@ -156,6 +169,47 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ usb: usb@8af8800 {
|
||||
+ compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
|
||||
+ reg = <0x08af8800 0x400>;
|
||||
+
|
||||
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "hs_phy_irq";
|
||||
+
|
||||
+ clocks = <&gcc GCC_USB0_MASTER_CLK>,
|
||||
+ <&gcc GCC_SYS_NOC_USB0_AXI_CLK>,
|
||||
+ <&gcc GCC_USB0_SLEEP_CLK>,
|
||||
+ <&gcc GCC_USB0_MOCK_UTMI_CLK>;
|
||||
+ clock-names = "core",
|
||||
+ "iface",
|
||||
+ "sleep",
|
||||
+ "mock_utmi";
|
||||
+
|
||||
+ resets = <&gcc GCC_USB0_BCR>;
|
||||
+
|
||||
+ qcom,select-utmi-as-pipe-clk;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ ranges;
|
||||
+
|
||||
+ status = "disabled";
|
||||
+
|
||||
+ usb_dwc: usb@8a00000 {
|
||||
+ compatible = "snps,dwc3";
|
||||
+ reg = <0x08a00000 0xe000>;
|
||||
+ clocks = <&gcc GCC_USB0_MOCK_UTMI_CLK>;
|
||||
+ clock-names = "ref";
|
||||
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ phy-names = "usb2-phy";
|
||||
+ phys = <&usbphy0>;
|
||||
+ tx-fifo-resize;
|
||||
+ snps,is-utmi-l1-suspend;
|
||||
+ snps,hird-threshold = /bits/ 8 <0x0>;
|
||||
+ snps,dis_u2_susphy_quirk;
|
||||
+ snps,dis_u3_susphy_quirk;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
intc: interrupt-controller@b000000 {
|
||||
compatible = "qcom,msm-qgic2";
|
||||
reg = <0x0b000000 0x1000>, /* GICD */
|
@ -0,0 +1,56 @@
|
||||
From a1f42e08f0f04b72a6597f080db4bfbb3737910c Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Wed, 4 Oct 2023 21:12:30 +0200
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: add QUP1 SPI controller
|
||||
|
||||
Add the required BAM and QUP nodes for the QUP1 SPI controller on IPQ5018.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Reviewed-by: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20231004191303.331055-1-robimarko@gmail.com
|
||||
[bjorn: Padded address to 8 digits, fixed node sort order]
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -159,6 +159,16 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ blsp_dma: dma-controller@7884000 {
|
||||
+ compatible = "qcom,bam-v1.7.0";
|
||||
+ reg = <0x07884000 0x1d000>;
|
||||
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>;
|
||||
+ clock-names = "bam_clk";
|
||||
+ #dma-cells = <1>;
|
||||
+ qcom,ee = <0>;
|
||||
+ };
|
||||
+
|
||||
blsp1_uart1: serial@78af000 {
|
||||
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
|
||||
reg = <0x078af000 0x200>;
|
||||
@@ -169,6 +179,20 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ blsp1_spi1: spi@78b5000 {
|
||||
+ compatible = "qcom,spi-qup-v2.2.1";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ reg = <0x078b5000 0x600>;
|
||||
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>,
|
||||
+ <&gcc GCC_BLSP1_AHB_CLK>;
|
||||
+ clock-names = "core", "iface";
|
||||
+ dmas = <&blsp_dma 4>, <&blsp_dma 5>;
|
||||
+ dma-names = "tx", "rx";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
usb: usb@8af8800 {
|
||||
compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
|
||||
reg = <0x08af8800 0x400>;
|
@ -0,0 +1,25 @@
|
||||
From 4d45d56e17348c6b6bb2bce126a4a5ea97b19900 Mon Sep 17 00:00:00 2001
|
||||
From: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
|
||||
Date: Mon, 25 Sep 2023 15:58:24 +0530
|
||||
Subject: [PATCH] dt-bindings: clock: qcom,a53pll: add IPQ5018 compatible
|
||||
|
||||
Add IPQ5018 compatible to A53 PLL bindings.
|
||||
|
||||
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230925102826.405446-2-quic_gokulsri@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
Documentation/devicetree/bindings/clock/qcom,a53pll.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
|
||||
+++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
|
||||
@@ -16,6 +16,7 @@ description:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
+ - qcom,ipq5018-a53pll
|
||||
- qcom,ipq5332-a53pll
|
||||
- qcom,ipq6018-a53pll
|
||||
- qcom,ipq8074-a53pll
|
@ -0,0 +1,62 @@
|
||||
From 50492f929486c044b43cb3e2c0e040aa9b61ea2b Mon Sep 17 00:00:00 2001
|
||||
From: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
|
||||
Date: Mon, 25 Sep 2023 15:58:25 +0530
|
||||
Subject: [PATCH] clk: qcom: apss-ipq-pll: add support for IPQ5018
|
||||
|
||||
IPQ5018 APSS PLL is of type Stromer. Reuse Stromer Plus PLL offsets,
|
||||
add configuration values and the compatible.
|
||||
|
||||
Co-developed-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
|
||||
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230925102826.405446-3-quic_gokulsri@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
drivers/clk/qcom/apss-ipq-pll.c | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
--- a/drivers/clk/qcom/apss-ipq-pll.c
|
||||
+++ b/drivers/clk/qcom/apss-ipq-pll.c
|
||||
@@ -73,6 +73,20 @@ static struct clk_alpha_pll ipq_pll_stro
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct alpha_pll_config ipq5018_pll_config = {
|
||||
+ .l = 0x32,
|
||||
+ .config_ctl_val = 0x4001075b,
|
||||
+ .config_ctl_hi_val = 0x304,
|
||||
+ .main_output_mask = BIT(0),
|
||||
+ .aux_output_mask = BIT(1),
|
||||
+ .early_output_mask = BIT(3),
|
||||
+ .alpha_en_mask = BIT(24),
|
||||
+ .status_val = 0x3,
|
||||
+ .status_mask = GENMASK(10, 8),
|
||||
+ .lock_det = BIT(2),
|
||||
+ .test_ctl_hi_val = 0x00400003,
|
||||
+};
|
||||
+
|
||||
static const struct alpha_pll_config ipq5332_pll_config = {
|
||||
.l = 0x2d,
|
||||
.config_ctl_val = 0x4001075b,
|
||||
@@ -129,6 +143,12 @@ struct apss_pll_data {
|
||||
const struct alpha_pll_config *pll_config;
|
||||
};
|
||||
|
||||
+static const struct apss_pll_data ipq5018_pll_data = {
|
||||
+ .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
|
||||
+ .pll = &ipq_pll_stromer_plus,
|
||||
+ .pll_config = &ipq5018_pll_config,
|
||||
+};
|
||||
+
|
||||
static struct apss_pll_data ipq5332_pll_data = {
|
||||
.pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
|
||||
.pll = &ipq_pll_stromer_plus,
|
||||
@@ -195,6 +215,7 @@ static int apss_ipq_pll_probe(struct pla
|
||||
}
|
||||
|
||||
static const struct of_device_id apss_ipq_pll_match_table[] = {
|
||||
+ { .compatible = "qcom,ipq5018-a53pll", .data = &ipq5018_pll_data },
|
||||
{ .compatible = "qcom,ipq5332-a53pll", .data = &ipq5332_pll_data },
|
||||
{ .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data },
|
||||
{ .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_data },
|
@ -0,0 +1,98 @@
|
||||
From 3e4b53e04281ed3d9c7a4329c027097265c04d54 Mon Sep 17 00:00:00 2001
|
||||
From: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
|
||||
Date: Mon, 25 Sep 2023 15:58:26 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: enable the CPUFreq support
|
||||
|
||||
Add the APCS, A53 PLL, cpu-opp-table nodes to set
|
||||
the CPU frequency at 800MHz (idle) or 1.008GHz.
|
||||
|
||||
Co-developed-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
|
||||
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20230925102826.405446-4-quic_gokulsri@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 40 +++++++++++++++++++++++++++
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -5,6 +5,7 @@
|
||||
* Copyright (c) 2023 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
+#include <dt-bindings/clock/qcom,apss-ipq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
|
||||
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
|
||||
@@ -36,6 +37,8 @@
|
||||
reg = <0x0>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_0>;
|
||||
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
|
||||
+ operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
CPU1: cpu@1 {
|
||||
@@ -44,6 +47,8 @@
|
||||
reg = <0x1>;
|
||||
enable-method = "psci";
|
||||
next-level-cache = <&L2_0>;
|
||||
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
|
||||
+ operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
L2_0: l2-cache {
|
||||
@@ -54,6 +59,25 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ cpu_opp_table: opp-table-cpu {
|
||||
+ compatible = "operating-points-v2";
|
||||
+ opp-shared;
|
||||
+
|
||||
+ /*
|
||||
+ opp-800000000 {
|
||||
+ opp-hz = /bits/ 64 <800000000>;
|
||||
+ opp-microvolt = <1100000>;
|
||||
+ clock-latency-ns = <200000>;
|
||||
+ };
|
||||
+ */
|
||||
+
|
||||
+ opp-1008000000 {
|
||||
+ opp-hz = /bits/ 64 <1008000000>;
|
||||
+ opp-microvolt = <1100000>;
|
||||
+ clock-latency-ns = <200000>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
firmware {
|
||||
scm {
|
||||
compatible = "qcom,scm-ipq5018", "qcom,scm";
|
||||
@@ -267,6 +291,24 @@
|
||||
clocks = <&sleep_clk>;
|
||||
};
|
||||
|
||||
+ apcs_glb: mailbox@b111000 {
|
||||
+ compatible = "qcom,ipq5018-apcs-apps-global",
|
||||
+ "qcom,ipq6018-apcs-apps-global";
|
||||
+ reg = <0x0b111000 0x1000>;
|
||||
+ #clock-cells = <1>;
|
||||
+ clocks = <&a53pll>, <&xo_board_clk>, <&gcc GPLL0>;
|
||||
+ clock-names = "pll", "xo", "gpll0";
|
||||
+ #mbox-cells = <1>;
|
||||
+ };
|
||||
+
|
||||
+ a53pll: clock@b116000 {
|
||||
+ compatible = "qcom,ipq5018-a53pll";
|
||||
+ reg = <0x0b116000 0x40>;
|
||||
+ #clock-cells = <0>;
|
||||
+ clocks = <&xo_board_clk>;
|
||||
+ clock-names = "xo";
|
||||
+ };
|
||||
+
|
||||
timer@b120000 {
|
||||
compatible = "arm,armv7-timer-mem";
|
||||
reg = <0x0b120000 0x1000>;
|
@ -0,0 +1,66 @@
|
||||
From a427dd16e61f3d145bc24f0ed09692fc25931250 Mon Sep 17 00:00:00 2001
|
||||
From: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
|
||||
Date: Wed, 25 Oct 2023 22:12:12 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: add few more reserved memory
|
||||
regions
|
||||
|
||||
Like all other IPQ SoCs, bootloader will collect the system RAM contents
|
||||
upon crash for the post morterm analysis. If we don't reserve the memory
|
||||
region used by bootloader, obviously linux will consume it and upon next
|
||||
boot on crash, bootloader will be loaded in the same region, which will
|
||||
lead to loose some of the data, sometimes we may miss out critical
|
||||
information. So lets reserve the region used by the bootloader.
|
||||
|
||||
Similarly SBL copies some data into the reserved region and it will be
|
||||
used in the crash scenario. So reserve 1MB for SBL as well.
|
||||
|
||||
While at it, enable the SMEM support along with TCSR mutex.
|
||||
|
||||
Signed-off-by: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
|
||||
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20231025-ipq5018-misc-v1-1-7d14fde97fe7@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -106,6 +106,24 @@
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
+ bootloader@4a800000 {
|
||||
+ reg = <0x0 0x4a800000 0x0 0x200000>;
|
||||
+ no-map;
|
||||
+ };
|
||||
+
|
||||
+ sbl@4aa00000 {
|
||||
+ reg = <0x0 0x4aa00000 0x0 0x100000>;
|
||||
+ no-map;
|
||||
+ };
|
||||
+
|
||||
+ smem@4ab00000 {
|
||||
+ compatible = "qcom,smem";
|
||||
+ reg = <0x0 0x4ab00000 0x0 0x100000>;
|
||||
+ no-map;
|
||||
+
|
||||
+ hwlocks = <&tcsr_mutex 3>;
|
||||
+ };
|
||||
+
|
||||
tz_region: tz@4ac00000 {
|
||||
reg = <0x0 0x4ac00000 0x0 0x200000>;
|
||||
no-map;
|
||||
@@ -166,6 +184,12 @@
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
+ tcsr_mutex: hwlock@1905000 {
|
||||
+ compatible = "qcom,tcsr-mutex";
|
||||
+ reg = <0x01905000 0x20000>;
|
||||
+ #hwlock-cells = <1>;
|
||||
+ };
|
||||
+
|
||||
sdhc_1: mmc@7804000 {
|
||||
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
|
||||
reg = <0x7804000 0x1000>;
|
@ -0,0 +1,83 @@
|
||||
From: Gabor Juhos <j4g8y7@gmail.com>
|
||||
Subject: [PATCH] clk: qcom: apss-ipq-pll: use stromer ops for IPQ5018 to fix boot failure
|
||||
Date: Fri, 15 Mar 2024 17:16:41 +0100
|
||||
|
||||
Booting v6.8 results in a hang on various IPQ5018 based boards.
|
||||
Investigating the problem showed that the hang happens when the
|
||||
clk_alpha_pll_stromer_plus_set_rate() function tries to write
|
||||
into the PLL_MODE register of the APSS PLL.
|
||||
|
||||
Checking the downstream code revealed that it uses [1] stromer
|
||||
specific operations for IPQ5018, whereas in the current code
|
||||
the stromer plus specific operations are used.
|
||||
|
||||
The ops in the 'ipq_pll_stromer_plus' clock definition can't be
|
||||
changed since that is needed for IPQ5332, so add a new alpha pll
|
||||
clock declaration which uses the correct stromer ops and use this
|
||||
new clock for IPQ5018 to avoid the boot failure.
|
||||
|
||||
Also, change pll_type in 'ipq5018_pll_data' to
|
||||
CLK_ALPHA_PLL_TYPE_STROMER to better reflect that it is a Stromer
|
||||
PLL and change the apss_ipq_pll_probe() function accordingly.
|
||||
|
||||
1. https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4/drivers/clk/qcom/apss-ipq5018.c#L67
|
||||
|
||||
Fixes: 50492f929486 ("clk: qcom: apss-ipq-pll: add support for IPQ5018")
|
||||
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
|
||||
---
|
||||
drivers/clk/qcom/apss-ipq-pll.c | 30 +++++++++++++++++++++++++++---
|
||||
1 file changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/clk/qcom/apss-ipq-pll.c
|
||||
+++ b/drivers/clk/qcom/apss-ipq-pll.c
|
||||
@@ -55,6 +55,29 @@ static struct clk_alpha_pll ipq_pll_huay
|
||||
},
|
||||
};
|
||||
|
||||
+static struct clk_alpha_pll ipq_pll_stromer = {
|
||||
+ .offset = 0x0,
|
||||
+ /*
|
||||
+ * Reuse CLK_ALPHA_PLL_TYPE_STROMER_PLUS register offsets.
|
||||
+ * Although this is a bit confusing, but the offset values
|
||||
+ * are correct nevertheless.
|
||||
+ */
|
||||
+ .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS],
|
||||
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
|
||||
+ .clkr = {
|
||||
+ .enable_reg = 0x0,
|
||||
+ .enable_mask = BIT(0),
|
||||
+ .hw.init = &(const struct clk_init_data) {
|
||||
+ .name = "a53pll",
|
||||
+ .parent_data = &(const struct clk_parent_data) {
|
||||
+ .fw_name = "xo",
|
||||
+ },
|
||||
+ .num_parents = 1,
|
||||
+ .ops = &clk_alpha_pll_stromer_ops,
|
||||
+ },
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static struct clk_alpha_pll ipq_pll_stromer_plus = {
|
||||
.offset = 0x0,
|
||||
.regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS],
|
||||
@@ -144,8 +167,8 @@ struct apss_pll_data {
|
||||
};
|
||||
|
||||
static const struct apss_pll_data ipq5018_pll_data = {
|
||||
- .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
|
||||
- .pll = &ipq_pll_stromer_plus,
|
||||
+ .pll_type = CLK_ALPHA_PLL_TYPE_STROMER,
|
||||
+ .pll = &ipq_pll_stromer,
|
||||
.pll_config = &ipq5018_pll_config,
|
||||
};
|
||||
|
||||
@@ -203,7 +226,8 @@ static int apss_ipq_pll_probe(struct pla
|
||||
|
||||
if (data->pll_type == CLK_ALPHA_PLL_TYPE_HUAYRA)
|
||||
clk_alpha_pll_configure(data->pll, regmap, data->pll_config);
|
||||
- else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS)
|
||||
+ else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER ||
|
||||
+ data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS)
|
||||
clk_stromer_pll_configure(data->pll, regmap, data->pll_config);
|
||||
|
||||
ret = devm_clk_register_regmap(dev, &data->pll->clkr);
|
@ -0,0 +1,32 @@
|
||||
From: Gabor Juhos <j4g8y7@gmail.com>
|
||||
Subject: [PATCH] clk: qcom: apss-ipq-pll: fix PLL rate for IPQ5018
|
||||
Date: Tue, 26 Mar 2024 14:34:11 +0100
|
||||
|
||||
According to ipq5018.dtsi, the maximum supported rate by the
|
||||
CPU is 1.008 GHz on the IPQ5018 platform, however the current
|
||||
configuration of the PLL results in 1.2 GHz rate.
|
||||
|
||||
Change the 'L' value in the PLL configuration to limit the
|
||||
rate to 1.008 GHz. The downstream kernel also uses the same
|
||||
value [1]. Also add a comment to indicate the desired
|
||||
frequency.
|
||||
|
||||
[1] https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4/drivers/clk/qcom/apss-ipq5018.c?ref_type=heads#L151
|
||||
|
||||
Fixes: 50492f929486 ("clk: qcom: apss-ipq-pll: add support for IPQ5018")
|
||||
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
|
||||
---
|
||||
drivers/clk/qcom/apss-ipq-pll.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/clk/qcom/apss-ipq-pll.c
|
||||
+++ b/drivers/clk/qcom/apss-ipq-pll.c
|
||||
@@ -97,7 +97,7 @@ static struct clk_alpha_pll ipq_pll_stro
|
||||
};
|
||||
|
||||
static const struct alpha_pll_config ipq5018_pll_config = {
|
||||
- .l = 0x32,
|
||||
+ .l = 0x2a,
|
||||
.config_ctl_val = 0x4001075b,
|
||||
.config_ctl_hi_val = 0x304,
|
||||
.main_output_mask = BIT(0),
|
@ -0,0 +1,60 @@
|
||||
From: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Date: Thu, 5 Oct 2023 21:35:48 +0530
|
||||
Subject: [PATCH] dt-bindings: pwm: add IPQ6018 binding
|
||||
|
||||
DT binding for the PWM block in Qualcomm IPQ6018 SoC.
|
||||
|
||||
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
|
||||
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
|
||||
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
|
||||
---
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
|
||||
@@ -0,0 +1,45 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/pwm/qcom,ipq6018-pwm.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Qualcomm IPQ6018 PWM controller
|
||||
+
|
||||
+maintainers:
|
||||
+ - Baruch Siach <baruch@tkos.co.il>
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ const: qcom,ipq6018-pwm
|
||||
+
|
||||
+ reg:
|
||||
+ description: Offset of PWM register in the TCSR block.
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ clocks:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ "#pwm-cells":
|
||||
+ const: 2
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - clocks
|
||||
+ - "#pwm-cells"
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/clock/qcom,gcc-ipq6018.h>
|
||||
+
|
||||
+ pwm: pwm@a010 {
|
||||
+ compatible = "qcom,ipq6018-pwm";
|
||||
+ reg = <0xa010 0x20>;
|
||||
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
|
||||
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
|
||||
+ assigned-clock-rates = <100000000>;
|
||||
+ #pwm-cells = <2>;
|
||||
+ };
|
@ -0,0 +1,330 @@
|
||||
From: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Date: Thu, 5 Oct 2023 21:35:47 +0530
|
||||
Subject: [PATCH] pwm: driver for qualcomm ipq6018 pwm block
|
||||
|
||||
Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on
|
||||
driver from downstream Codeaurora kernel tree. Removed support for older
|
||||
(V1) variants because I have no access to that hardware.
|
||||
|
||||
Tested on IPQ6010 based hardware.
|
||||
|
||||
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
|
||||
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
|
||||
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
|
||||
---
|
||||
--- a/drivers/pwm/Kconfig
|
||||
+++ b/drivers/pwm/Kconfig
|
||||
@@ -282,6 +282,18 @@ config PWM_INTEL_LGM
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pwm-intel-lgm.
|
||||
|
||||
+config PWM_IPQ
|
||||
+ tristate "IPQ PWM support"
|
||||
+ depends on ARCH_QCOM || COMPILE_TEST
|
||||
+ depends on HAVE_CLK && HAS_IOMEM
|
||||
+ help
|
||||
+ Generic PWM framework driver for IPQ PWM block which supports
|
||||
+ 4 pwm channels. Each of the these channels can be configured
|
||||
+ independent of each other.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called pwm-ipq.
|
||||
+
|
||||
config PWM_IQS620A
|
||||
tristate "Azoteq IQS620A PWM support"
|
||||
depends on MFD_IQS62X || COMPILE_TEST
|
||||
--- a/drivers/pwm/Makefile
|
||||
+++ b/drivers/pwm/Makefile
|
||||
@@ -24,6 +24,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o
|
||||
obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o
|
||||
obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o
|
||||
obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o
|
||||
+obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o
|
||||
obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o
|
||||
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
|
||||
obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pwm/pwm-ipq.c
|
||||
@@ -0,0 +1,282 @@
|
||||
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pwm.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/math64.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/units.h>
|
||||
+
|
||||
+/* The frequency range supported is 1 Hz to clock rate */
|
||||
+#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC)
|
||||
+
|
||||
+/*
|
||||
+ * The max value specified for each field is based on the number of bits
|
||||
+ * in the pwm control register for that field
|
||||
+ */
|
||||
+#define IPQ_PWM_MAX_DIV 0xFFFF
|
||||
+
|
||||
+/*
|
||||
+ * Two 32-bit registers for each PWM: REG0, and REG1.
|
||||
+ * Base offset for PWM #i is at 8 * #i.
|
||||
+ */
|
||||
+#define IPQ_PWM_REG0 0
|
||||
+#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0)
|
||||
+#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16)
|
||||
+
|
||||
+#define IPQ_PWM_REG1 4
|
||||
+#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0)
|
||||
+/*
|
||||
+ * Enable bit is set to enable output toggling in pwm device.
|
||||
+ * Update bit is set to reflect the changed divider and high duration
|
||||
+ * values in register.
|
||||
+ */
|
||||
+#define IPQ_PWM_REG1_UPDATE BIT(30)
|
||||
+#define IPQ_PWM_REG1_ENABLE BIT(31)
|
||||
+
|
||||
+struct ipq_pwm_chip {
|
||||
+ struct pwm_chip chip;
|
||||
+ struct clk *clk;
|
||||
+ void __iomem *mem;
|
||||
+};
|
||||
+
|
||||
+static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip)
|
||||
+{
|
||||
+ return container_of(chip, struct ipq_pwm_chip, chip);
|
||||
+}
|
||||
+
|
||||
+static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg)
|
||||
+{
|
||||
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);
|
||||
+ unsigned int off = 8 * pwm->hwpwm + reg;
|
||||
+
|
||||
+ return readl(ipq_chip->mem + off);
|
||||
+}
|
||||
+
|
||||
+static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg,
|
||||
+ unsigned int val)
|
||||
+{
|
||||
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);
|
||||
+ unsigned int off = 8 * pwm->hwpwm + reg;
|
||||
+
|
||||
+ writel(val, ipq_chip->mem + off);
|
||||
+}
|
||||
+
|
||||
+static void config_div_and_duty(struct pwm_device *pwm, unsigned int pre_div,
|
||||
+ unsigned int pwm_div, unsigned long rate, u64 duty_ns,
|
||||
+ bool enable)
|
||||
+{
|
||||
+ unsigned long hi_dur;
|
||||
+ unsigned long val = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * high duration = pwm duty * (pwm div + 1)
|
||||
+ * pwm duty = duty_ns / period_ns
|
||||
+ */
|
||||
+ hi_dur = div64_u64(duty_ns * rate, (pre_div + 1) * NSEC_PER_SEC);
|
||||
+
|
||||
+ val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) |
|
||||
+ FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div);
|
||||
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val);
|
||||
+
|
||||
+ val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div);
|
||||
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
|
||||
+
|
||||
+ /* PWM enable toggle needs a separate write to REG1 */
|
||||
+ val |= IPQ_PWM_REG1_UPDATE;
|
||||
+ if (enable)
|
||||
+ val |= IPQ_PWM_REG1_ENABLE;
|
||||
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
|
||||
+}
|
||||
+
|
||||
+static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ const struct pwm_state *state)
|
||||
+{
|
||||
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
|
||||
+ unsigned int pre_div, pwm_div, best_pre_div, best_pwm_div;
|
||||
+ unsigned long rate = clk_get_rate(ipq_chip->clk);
|
||||
+ u64 period_ns, duty_ns, period_rate;
|
||||
+ u64 min_diff;
|
||||
+
|
||||
+ if (state->polarity != PWM_POLARITY_NORMAL)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (state->period < DIV64_U64_ROUND_UP(NSEC_PER_SEC, rate))
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS);
|
||||
+ duty_ns = min(state->duty_cycle, period_ns);
|
||||
+
|
||||
+ /*
|
||||
+ * period_ns is 1G or less. As long as rate is less than 16 GHz,
|
||||
+ * period_rate does not overflow. Make that explicit.
|
||||
+ */
|
||||
+ if ((unsigned long long)rate > 16ULL * GIGA)
|
||||
+ return -EINVAL;
|
||||
+ period_rate = period_ns * rate;
|
||||
+ best_pre_div = IPQ_PWM_MAX_DIV;
|
||||
+ best_pwm_div = IPQ_PWM_MAX_DIV;
|
||||
+ /*
|
||||
+ * We don't need to consider pre_div values smaller than
|
||||
+ *
|
||||
+ * period_rate
|
||||
+ * pre_div_min := ------------------------------------
|
||||
+ * NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1)
|
||||
+ *
|
||||
+ * because pre_div = pre_div_min results in a better
|
||||
+ * approximation.
|
||||
+ */
|
||||
+ pre_div = div64_u64(period_rate,
|
||||
+ (u64)NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1));
|
||||
+ min_diff = period_rate;
|
||||
+
|
||||
+ for (; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) {
|
||||
+ u64 remainder;
|
||||
+
|
||||
+ pwm_div = div64_u64_rem(period_rate,
|
||||
+ (u64)NSEC_PER_SEC * (pre_div + 1), &remainder);
|
||||
+ /* pwm_div is unsigned; the check below catches underflow */
|
||||
+ pwm_div--;
|
||||
+
|
||||
+ /*
|
||||
+ * Swapping values for pre_div and pwm_div produces the same
|
||||
+ * period length. So we can skip all settings with pre_div >
|
||||
+ * pwm_div which results in bigger constraints for selecting
|
||||
+ * the duty_cycle than with the two values swapped.
|
||||
+ */
|
||||
+ if (pre_div > pwm_div)
|
||||
+ break;
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure we can do 100% duty cycle where
|
||||
+ * hi_dur == pwm_div + 1
|
||||
+ */
|
||||
+ if (pwm_div > IPQ_PWM_MAX_DIV - 1)
|
||||
+ continue;
|
||||
+
|
||||
+ if (remainder < min_diff) {
|
||||
+ best_pre_div = pre_div;
|
||||
+ best_pwm_div = pwm_div;
|
||||
+ min_diff = remainder;
|
||||
+
|
||||
+ if (min_diff == 0) /* bingo */
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* config divider values for the closest possible frequency */
|
||||
+ config_div_and_duty(pwm, best_pre_div, best_pwm_div,
|
||||
+ rate, duty_ns, state->enabled);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ struct pwm_state *state)
|
||||
+{
|
||||
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
|
||||
+ unsigned long rate = clk_get_rate(ipq_chip->clk);
|
||||
+ unsigned int pre_div, pwm_div, hi_dur;
|
||||
+ u64 effective_div, hi_div;
|
||||
+ u32 reg0, reg1;
|
||||
+
|
||||
+ reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0);
|
||||
+ reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1);
|
||||
+
|
||||
+ state->polarity = PWM_POLARITY_NORMAL;
|
||||
+ state->enabled = reg1 & IPQ_PWM_REG1_ENABLE;
|
||||
+
|
||||
+ pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0);
|
||||
+ hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0);
|
||||
+ pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1);
|
||||
+
|
||||
+ /* No overflow here, both pre_div and pwm_div <= 0xffff */
|
||||
+ effective_div = (u64)(pre_div + 1) * (pwm_div + 1);
|
||||
+ state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, rate);
|
||||
+
|
||||
+ hi_div = hi_dur * (pre_div + 1);
|
||||
+ state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, rate);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct pwm_ops ipq_pwm_ops = {
|
||||
+ .apply = ipq_pwm_apply,
|
||||
+ .get_state = ipq_pwm_get_state,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int ipq_pwm_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct ipq_pwm_chip *pwm;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ int ret;
|
||||
+
|
||||
+ pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL);
|
||||
+ if (!pwm)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pwm);
|
||||
+
|
||||
+ pwm->mem = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(pwm->mem))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pwm->mem),
|
||||
+ "regs map failed");
|
||||
+
|
||||
+ pwm->clk = devm_clk_get(dev, NULL);
|
||||
+ if (IS_ERR(pwm->clk))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pwm->clk),
|
||||
+ "failed to get clock");
|
||||
+
|
||||
+ ret = clk_prepare_enable(pwm->clk);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "clock enable failed");
|
||||
+
|
||||
+ pwm->chip.dev = dev;
|
||||
+ pwm->chip.ops = &ipq_pwm_ops;
|
||||
+ pwm->chip.npwm = 4;
|
||||
+
|
||||
+ ret = pwmchip_add(&pwm->chip);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err_probe(dev, ret, "pwmchip_add() failed\n");
|
||||
+ clk_disable_unprepare(pwm->clk);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ipq_pwm_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct ipq_pwm_chip *pwm = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ pwmchip_remove(&pwm->chip);
|
||||
+ clk_disable_unprepare(pwm->clk);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id pwm_ipq_dt_match[] = {
|
||||
+ { .compatible = "qcom,ipq6018-pwm", },
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match);
|
||||
+
|
||||
+static struct platform_driver ipq_pwm_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "ipq-pwm",
|
||||
+ .of_match_table = pwm_ipq_dt_match,
|
||||
+ },
|
||||
+ .probe = ipq_pwm_probe,
|
||||
+ .remove = ipq_pwm_remove,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(ipq_pwm_driver);
|
||||
+
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
@ -0,0 +1,148 @@
|
||||
From: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Subject: [PATCH] dt-bindings: mfd: qcom,tcsr: Add simple-mfd support for IPQ6018
|
||||
Date: Thu, 5 Oct 2023 21:35:49 +0530
|
||||
|
||||
Update the binding to include pwm as the child node to TCSR block and
|
||||
add simple-mfd support for IPQ6018.
|
||||
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
|
||||
---
|
||||
.../devicetree/bindings/mfd/qcom,tcsr.yaml | 112 +++++++++++++-----
|
||||
1 file changed, 81 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
|
||||
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
|
||||
@@ -15,49 +15,101 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
- items:
|
||||
- - enum:
|
||||
- - qcom,msm8976-tcsr
|
||||
- - qcom,msm8998-tcsr
|
||||
- - qcom,qcs404-tcsr
|
||||
- - qcom,sc7180-tcsr
|
||||
- - qcom,sc7280-tcsr
|
||||
- - qcom,sc8280xp-tcsr
|
||||
- - qcom,sdm630-tcsr
|
||||
- - qcom,sdm845-tcsr
|
||||
- - qcom,sdx55-tcsr
|
||||
- - qcom,sdx65-tcsr
|
||||
- - qcom,sm8150-tcsr
|
||||
- - qcom,sm8450-tcsr
|
||||
- - qcom,tcsr-apq8064
|
||||
- - qcom,tcsr-apq8084
|
||||
- - qcom,tcsr-ipq5332
|
||||
- - qcom,tcsr-ipq6018
|
||||
- - qcom,tcsr-ipq8064
|
||||
- - qcom,tcsr-ipq8074
|
||||
- - qcom,tcsr-ipq9574
|
||||
- - qcom,tcsr-mdm9615
|
||||
- - qcom,tcsr-msm8226
|
||||
- - qcom,tcsr-msm8660
|
||||
- - qcom,tcsr-msm8916
|
||||
- - qcom,tcsr-msm8953
|
||||
- - qcom,tcsr-msm8960
|
||||
- - qcom,tcsr-msm8974
|
||||
- - qcom,tcsr-msm8996
|
||||
- - const: syscon
|
||||
+ oneOf:
|
||||
+ - items:
|
||||
+ - enum:
|
||||
+ - qcom,msm8976-tcsr
|
||||
+ - qcom,msm8998-tcsr
|
||||
+ - qcom,qcs404-tcsr
|
||||
+ - qcom,sc7180-tcsr
|
||||
+ - qcom,sc7280-tcsr
|
||||
+ - qcom,sc8280xp-tcsr
|
||||
+ - qcom,sdm630-tcsr
|
||||
+ - qcom,sdm845-tcsr
|
||||
+ - qcom,sdx55-tcsr
|
||||
+ - qcom,sdx65-tcsr
|
||||
+ - qcom,sm4450-tcsr
|
||||
+ - qcom,sm8150-tcsr
|
||||
+ - qcom,sm8450-tcsr
|
||||
+ - qcom,tcsr-apq8064
|
||||
+ - qcom,tcsr-apq8084
|
||||
+ - qcom,tcsr-ipq5332
|
||||
+ - qcom,tcsr-ipq8064
|
||||
+ - qcom,tcsr-ipq8074
|
||||
+ - qcom,tcsr-ipq9574
|
||||
+ - qcom,tcsr-mdm9615
|
||||
+ - qcom,tcsr-msm8226
|
||||
+ - qcom,tcsr-msm8660
|
||||
+ - qcom,tcsr-msm8916
|
||||
+ - qcom,tcsr-msm8953
|
||||
+ - qcom,tcsr-msm8960
|
||||
+ - qcom,tcsr-msm8974
|
||||
+ - qcom,tcsr-msm8996
|
||||
+ - const: syscon
|
||||
+ - items:
|
||||
+ - const: qcom,tcsr-ipq6018
|
||||
+ - const: syscon
|
||||
+ - const: simple-mfd
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
+ ranges: true
|
||||
+
|
||||
+ "#address-cells":
|
||||
+ const: 1
|
||||
+
|
||||
+ "#size-cells":
|
||||
+ const: 1
|
||||
+
|
||||
+patternProperties:
|
||||
+ "pwm@[a-f0-9]+$":
|
||||
+ type: object
|
||||
+ $ref: /schemas/pwm/qcom,ipq6018-pwm.yaml
|
||||
+
|
||||
+
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
+allOf:
|
||||
+ - if:
|
||||
+ not:
|
||||
+ properties:
|
||||
+ compatible:
|
||||
+ contains:
|
||||
+ enum:
|
||||
+ - qcom,tcsr-ipq6018
|
||||
+ then:
|
||||
+ patternProperties:
|
||||
+ "pwm@[a-f0-9]+$": false
|
||||
+
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
+ # Example 1 - Syscon node found on MSM8960
|
||||
- |
|
||||
syscon@1a400000 {
|
||||
compatible = "qcom,tcsr-msm8960", "syscon";
|
||||
reg = <0x1a400000 0x100>;
|
||||
};
|
||||
+ # Example 2 - Syscon node found on IPQ6018
|
||||
+ - |
|
||||
+ #include <dt-bindings/clock/qcom,gcc-ipq6018.h>
|
||||
+
|
||||
+ syscon@1937000 {
|
||||
+ compatible = "qcom,tcsr-ipq6018", "syscon", "simple-mfd";
|
||||
+ reg = <0x01937000 0x21000>;
|
||||
+ ranges = <0 0x1937000 0x21000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ pwm: pwm@a010 {
|
||||
+ compatible = "qcom,ipq6018-pwm";
|
||||
+ reg = <0xa010 0x20>;
|
||||
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
|
||||
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
|
||||
+ assigned-clock-rates = <100000000>;
|
||||
+ #pwm-cells = <2>;
|
||||
+ };
|
||||
+ };
|
||||
\ No newline at end of file
|
@ -0,0 +1,22 @@
|
||||
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Subject: [PATCH V2 1/1] dt-bindings: nvmem: Add compatible for IPQ5018
|
||||
Date: Fri, 15 Sep 2023 17:31:20 +0530
|
||||
|
||||
Document the QFPROM on IPQ5018.
|
||||
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
---
|
||||
Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
|
||||
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
|
||||
@@ -18,6 +18,7 @@ properties:
|
||||
- enum:
|
||||
- qcom,apq8064-qfprom
|
||||
- qcom,apq8084-qfprom
|
||||
+ - qcom,ipq5018-qfprom
|
||||
- qcom,ipq5332-qfprom
|
||||
- qcom,ipq6018-qfprom
|
||||
- qcom,ipq8064-qfprom
|
@ -0,0 +1,26 @@
|
||||
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Date: Fri, 22 Sep 2023 17:21:13 +0530
|
||||
Subject: [PATCH] dt-bindings: thermal: qcom-tsens: Add ipq5018 compatible
|
||||
|
||||
IPQ5018 has tsens v1.0 block with 4 sensors and 1 interrupt.
|
||||
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
---
|
||||
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
|
||||
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
|
||||
@@ -39,6 +39,7 @@ properties:
|
||||
- description: v1 of TSENS
|
||||
items:
|
||||
- enum:
|
||||
+ - qcom,ipq5018-tsens
|
||||
- qcom,msm8956-tsens
|
||||
- qcom,msm8976-tsens
|
||||
- qcom,qcs404-tsens
|
||||
@@ -232,6 +233,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
+ - qcom,ipq5018-tsens
|
||||
- qcom,ipq8064-tsens
|
||||
- qcom,msm8960-tsens
|
||||
- qcom,tsens-v0_1
|
@ -0,0 +1,45 @@
|
||||
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Subject: [PATCH] thermal/drivers/qcom: Add new feat for soc without rpm
|
||||
Date: Fri, 22 Sep 2023 17:21:14 +0530
|
||||
|
||||
In IPQ5018, Tsens IP doesn't have RPM. Hence the early init to
|
||||
enable tsens would not be done. So add a flag for that in feat
|
||||
and skip enable checks. Without this, tsens probe fails.
|
||||
|
||||
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
---
|
||||
drivers/thermal/qcom/tsens.c | 2 +-
|
||||
drivers/thermal/qcom/tsens.h | 3 +++
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/thermal/qcom/tsens.c
|
||||
+++ b/drivers/thermal/qcom/tsens.c
|
||||
@@ -974,7 +974,7 @@ int __init init_common(struct tsens_priv
|
||||
ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
- if (!enabled) {
|
||||
+ if (!enabled && !(priv->feat->ignore_enable)) {
|
||||
dev_err(dev, "%s: device not enabled\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto err_put_device;
|
||||
--- a/drivers/thermal/qcom/tsens.h
|
||||
+++ b/drivers/thermal/qcom/tsens.h
|
||||
@@ -505,6 +505,8 @@ enum regfield_ids {
|
||||
* @srot_split: does the IP neatly splits the register space into SROT and TM,
|
||||
* with SROT only being available to secure boot firmware?
|
||||
* @has_watchdog: does this IP support watchdog functionality?
|
||||
+ * @ignore_enable: does this IP reside in a soc that does not have rpm to
|
||||
+ * do pre-init.
|
||||
* @max_sensors: maximum sensors supported by this version of the IP
|
||||
* @trip_min_temp: minimum trip temperature supported by this version of the IP
|
||||
* @trip_max_temp: maximum trip temperature supported by this version of the IP
|
||||
@@ -516,6 +518,7 @@ struct tsens_features {
|
||||
unsigned int adc:1;
|
||||
unsigned int srot_split:1;
|
||||
unsigned int has_watchdog:1;
|
||||
+ unsigned int ignore_enable:1;
|
||||
unsigned int max_sensors;
|
||||
int trip_min_temp;
|
||||
int trip_max_temp;
|
@ -0,0 +1,118 @@
|
||||
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Subject: [PATCH] thermal/drivers/tsens: Add support for IPQ5018 tsens
|
||||
Date: Fri, 22 Sep 2023 17:21:15 +0530
|
||||
|
||||
IPQ5018 has tsens IP V1.0, 4 sensors and 1 interrupt.
|
||||
The soc does not have a RPM, hence tsens has to be reset and
|
||||
enabled in the driver init. Adding the driver support for same.
|
||||
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
---
|
||||
drivers/thermal/qcom/tsens-v1.c | 60 +++++++++++++++++++++++++++++++++
|
||||
drivers/thermal/qcom/tsens.c | 3 ++
|
||||
drivers/thermal/qcom/tsens.h | 2 +-
|
||||
3 files changed, 64 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/thermal/qcom/tsens-v1.c
|
||||
+++ b/drivers/thermal/qcom/tsens-v1.c
|
||||
@@ -79,6 +79,18 @@ static struct tsens_features tsens_v1_fe
|
||||
.trip_max_temp = 120000,
|
||||
};
|
||||
|
||||
+static struct tsens_features tsens_v1_ipq5018_feat = {
|
||||
+ .ver_major = VER_1_X,
|
||||
+ .crit_int = 0,
|
||||
+ .combo_int = 0,
|
||||
+ .adc = 1,
|
||||
+ .srot_split = 1,
|
||||
+ .max_sensors = 11,
|
||||
+ .trip_min_temp = -40000,
|
||||
+ .trip_max_temp = 120000,
|
||||
+ .ignore_enable = 1,
|
||||
+};
|
||||
+
|
||||
static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
|
||||
/* ----- SROT ------ */
|
||||
/* VERSION */
|
||||
@@ -150,6 +162,41 @@ static int __init init_8956(struct tsens
|
||||
return init_common(priv);
|
||||
}
|
||||
|
||||
+static int __init init_ipq5018(struct tsens_priv *priv)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u32 mask;
|
||||
+
|
||||
+ ret = init_common(priv);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(priv->dev, "Init common failed %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_field_write(priv->rf[TSENS_SW_RST], 1);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "Reset failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ mask = GENMASK(priv->num_sensors, 0);
|
||||
+ ret = regmap_field_update_bits(priv->rf[SENSOR_EN], mask, mask);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "Sensor Enable failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_field_write(priv->rf[TSENS_EN], 1);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "Enable failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_field_write(priv->rf[TSENS_SW_RST], 0);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static const struct tsens_ops ops_generic_v1 = {
|
||||
.init = init_common,
|
||||
.calibrate = calibrate_v1,
|
||||
@@ -194,3 +241,16 @@ struct tsens_plat_data data_8976 = {
|
||||
.feat = &tsens_v1_feat,
|
||||
.fields = tsens_v1_regfields,
|
||||
};
|
||||
+
|
||||
+const struct tsens_ops ops_ipq5018 = {
|
||||
+ .init = init_ipq5018,
|
||||
+ .calibrate = tsens_calibrate_common,
|
||||
+ .get_temp = get_temp_tsens_valid,
|
||||
+};
|
||||
+
|
||||
+struct tsens_plat_data data_ipq5018 = {
|
||||
+ .num_sensors = 5,
|
||||
+ .ops = &ops_ipq5018,
|
||||
+ .feat = &tsens_v1_ipq5018_feat,
|
||||
+ .fields = tsens_v1_regfields,
|
||||
+};
|
||||
--- a/drivers/thermal/qcom/tsens.c
|
||||
+++ b/drivers/thermal/qcom/tsens.c
|
||||
@@ -1101,6 +1101,9 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, t
|
||||
|
||||
static const struct of_device_id tsens_table[] = {
|
||||
{
|
||||
+ .compatible = "qcom,ipq5018-tsens",
|
||||
+ .data = &data_ipq5018,
|
||||
+ }, {
|
||||
.compatible = "qcom,ipq8064-tsens",
|
||||
.data = &data_8960,
|
||||
}, {
|
||||
--- a/drivers/thermal/qcom/tsens.h
|
||||
+++ b/drivers/thermal/qcom/tsens.h
|
||||
@@ -645,7 +645,7 @@ extern struct tsens_plat_data data_8960;
|
||||
extern struct tsens_plat_data data_8226, data_8909, data_8916, data_8939, data_8974, data_9607;
|
||||
|
||||
/* TSENS v1 targets */
|
||||
-extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956;
|
||||
+extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956, data_ipq5018;
|
||||
|
||||
/* TSENS v2 targets */
|
||||
extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
|
@ -0,0 +1,200 @@
|
||||
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add tsens node
|
||||
Date: Fri, 22 Sep 2023 17:21:16 +0530
|
||||
|
||||
IPQ5018 has tsens V1.0 IP with 4 sensors.
|
||||
There is no RPM, so tsens has to be manually enabled. Adding the tsens
|
||||
and nvmem node and IPQ5018 has 4 thermal sensors (zones). With the
|
||||
critical temperature being 120'C and action is to reboot. Adding all
|
||||
the 4 zones here.
|
||||
|
||||
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 169 ++++++++++++++++++++++++++
|
||||
1 file changed, 169 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -149,6 +149,117 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ qfprom: qfprom@a0000 {
|
||||
+ compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
|
||||
+ reg = <0xa0000 0x1000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ tsens_mode: mode@249 {
|
||||
+ reg = <0x249 1>;
|
||||
+ bits = <0 3>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_base1: base1@249 {
|
||||
+ reg = <0x249 2>;
|
||||
+ bits = <3 8>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_base2: base2@24a {
|
||||
+ reg = <0x24a 2>;
|
||||
+ bits = <3 8>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s0_p1: s0-p1@24b {
|
||||
+ reg = <0x24b 0x2>;
|
||||
+ bits = <2 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s0_p2: s0-p2@24c {
|
||||
+ reg = <0x24c 0x1>;
|
||||
+ bits = <1 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s1_p1: s1-p1@24c {
|
||||
+ reg = <0x24c 0x2>;
|
||||
+ bits = <7 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s1_p2: s1-p2@24d {
|
||||
+ reg = <0x24d 0x2>;
|
||||
+ bits = <5 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s2_p1: s2-p1@24e {
|
||||
+ reg = <0x24e 0x2>;
|
||||
+ bits = <3 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s2_p2: s2-p2@24f {
|
||||
+ reg = <0x24f 0x1>;
|
||||
+ bits = <1 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s3_p1: s3-p1@24f {
|
||||
+ reg = <0x24f 0x2>;
|
||||
+ bits = <7 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s3_p2: s3-p2@250 {
|
||||
+ reg = <0x250 0x2>;
|
||||
+ bits = <5 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s4_p1: s4-p1@251 {
|
||||
+ reg = <0x251 0x2>;
|
||||
+ bits = <3 6>;
|
||||
+ };
|
||||
+
|
||||
+ tsens_s4_p2: s4-p2@254 {
|
||||
+ reg = <0x254 0x1>;
|
||||
+ bits = <0 6>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ tsens: thermal-sensor@4a9000 {
|
||||
+ compatible = "qcom,ipq5018-tsens";
|
||||
+ reg = <0x4a9000 0x1000>, /* TM */
|
||||
+ <0x4a8000 0x1000>; /* SROT */
|
||||
+
|
||||
+ nvmem-cells = <&tsens_mode>,
|
||||
+ <&tsens_base1>,
|
||||
+ <&tsens_base2>,
|
||||
+ <&tsens_s0_p1>,
|
||||
+ <&tsens_s0_p2>,
|
||||
+ <&tsens_s1_p1>,
|
||||
+ <&tsens_s1_p2>,
|
||||
+ <&tsens_s2_p1>,
|
||||
+ <&tsens_s2_p2>,
|
||||
+ <&tsens_s3_p1>,
|
||||
+ <&tsens_s3_p2>,
|
||||
+ <&tsens_s4_p1>,
|
||||
+ <&tsens_s4_p2>;
|
||||
+
|
||||
+ nvmem-cell-names = "mode",
|
||||
+ "base1",
|
||||
+ "base2",
|
||||
+ "s0_p1",
|
||||
+ "s0_p2",
|
||||
+ "s1_p1",
|
||||
+ "s1_p2",
|
||||
+ "s2_p1",
|
||||
+ "s2_p2",
|
||||
+ "s3_p1",
|
||||
+ "s3_p2",
|
||||
+ "s4_p1",
|
||||
+ "s4_p2";
|
||||
+
|
||||
+ interrupts = <GIC_SPI 184 IRQ_TYPE_EDGE_RISING>;
|
||||
+ interrupt-names = "uplow";
|
||||
+ #qcom,sensors = <5>;
|
||||
+ #thermal-sensor-cells = <1>;
|
||||
+ };
|
||||
+
|
||||
tlmm: pinctrl@1000000 {
|
||||
compatible = "qcom,ipq5018-tlmm";
|
||||
reg = <0x01000000 0x300000>;
|
||||
@@ -391,6 +502,64 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ thermal-zones {
|
||||
+ cpu-thermal {
|
||||
+ polling-delay-passive = <0>;
|
||||
+ polling-delay = <0>;
|
||||
+ thermal-sensors = <&tsens 2>;
|
||||
+
|
||||
+ trips {
|
||||
+ cpu-critical {
|
||||
+ temperature = <120000>;
|
||||
+ hysteresis = <2>;
|
||||
+ type = "critical";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gephy-thermal {
|
||||
+ polling-delay-passive = <0>;
|
||||
+ polling-delay = <0>;
|
||||
+ thermal-sensors = <&tsens 4>;
|
||||
+
|
||||
+ trips {
|
||||
+ gephy-critical {
|
||||
+ temperature = <120000>;
|
||||
+ hysteresis = <2>;
|
||||
+ type = "critical";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ top-glue-thermal {
|
||||
+ polling-delay-passive = <0>;
|
||||
+ polling-delay = <0>;
|
||||
+ thermal-sensors = <&tsens 3>;
|
||||
+
|
||||
+ trips {
|
||||
+ top_glue-critical {
|
||||
+ temperature = <120000>;
|
||||
+ hysteresis = <2>;
|
||||
+ type = "critical";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ ubi32-thermal {
|
||||
+ polling-delay-passive = <0>;
|
||||
+ polling-delay = <0>;
|
||||
+ thermal-sensors = <&tsens 1>;
|
||||
+
|
||||
+ trips {
|
||||
+ ubi32-critical {
|
||||
+ temperature = <120000>;
|
||||
+ hysteresis = <2>;
|
||||
+ type = "critical";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv8-timer";
|
@ -0,0 +1,85 @@
|
||||
From: Varadarajan Narayanan <quic_varada@quicinc.com>
|
||||
Date: Thu, 2 Jan 2025 17:00:15 +0530
|
||||
Subject: [PATCH] dt-bindings: phy: qcom,uniphy-pcie: Document PCIe uniphy
|
||||
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
|
||||
Document the Qualcomm UNIPHY PCIe 28LP present in IPQ5332.
|
||||
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
|
||||
---
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
|
||||
@@ -0,0 +1,71 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/phy/qcom,ipq5332-uniphy-pcie-phy.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Qualcomm UNIPHY PCIe 28LP PHY
|
||||
+
|
||||
+maintainers:
|
||||
+ - Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
+ - Varadarajan Narayanan <quic_varada@quicinc.com>
|
||||
+
|
||||
+description:
|
||||
+ PCIe and USB combo PHY found in Qualcomm IPQ5332 SoC
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - qcom,ipq5332-uniphy-pcie-phy
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ clocks:
|
||||
+ items:
|
||||
+ - description: pcie pipe clock
|
||||
+ - description: pcie ahb clock
|
||||
+
|
||||
+ resets:
|
||||
+ items:
|
||||
+ - description: phy reset
|
||||
+ - description: ahb reset
|
||||
+ - description: cfg reset
|
||||
+
|
||||
+ "#phy-cells":
|
||||
+ const: 0
|
||||
+
|
||||
+ "#clock-cells":
|
||||
+ const: 0
|
||||
+
|
||||
+ num-lanes: true
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - clocks
|
||||
+ - resets
|
||||
+ - "#phy-cells"
|
||||
+ - "#clock-cells"
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/clock/qcom,ipq5332-gcc.h>
|
||||
+
|
||||
+ pcie0_phy: phy@4b0000 {
|
||||
+ compatible = "qcom,ipq5332-uniphy-pcie-phy";
|
||||
+ reg = <0x004b0000 0x800>;
|
||||
+
|
||||
+ clocks = <&gcc GCC_PCIE3X1_0_PIPE_CLK>,
|
||||
+ <&gcc GCC_PCIE3X1_PHY_AHB_CLK>;
|
||||
+
|
||||
+ resets = <&gcc GCC_PCIE3X1_0_PHY_BCR>,
|
||||
+ <&gcc GCC_PCIE3X1_PHY_AHB_CLK_ARES>,
|
||||
+ <&gcc GCC_PCIE3X1_0_PHY_PHY_BCR>;
|
||||
+
|
||||
+ #clock-cells = <0>;
|
||||
+
|
||||
+ #phy-cells = <0>;
|
||||
+ };
|
@ -0,0 +1,332 @@
|
||||
From: Varadarajan Narayanan <quic_varada@quicinc.com>
|
||||
Date: Thu, 2 Jan 2025 17:00:16 +0530
|
||||
Subject: [PATCH] phy: qcom: Introduce PCIe UNIPHY 28LP driver
|
||||
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
|
||||
Add Qualcomm PCIe UNIPHY 28LP driver support present
|
||||
in Qualcomm IPQ5332 SoC and the phy init sequence.
|
||||
|
||||
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
|
||||
---
|
||||
--- a/drivers/phy/qualcomm/Kconfig
|
||||
+++ b/drivers/phy/qualcomm/Kconfig
|
||||
@@ -154,6 +154,18 @@ config PHY_QCOM_M31_USB
|
||||
management. This driver is required even for peripheral only or
|
||||
host only mode configurations.
|
||||
|
||||
+config PHY_QCOM_UNIPHY_PCIE_28LP
|
||||
+ bool "PCIE UNIPHY 28LP PHY driver"
|
||||
+ depends on ARCH_QCOM
|
||||
+ depends on HAS_IOMEM
|
||||
+ depends on OF
|
||||
+ select GENERIC_PHY
|
||||
+ help
|
||||
+ Enable this to support the PCIe UNIPHY 28LP phy transceiver that
|
||||
+ is used with PCIe controllers on Qualcomm IPQ5332 chips. It
|
||||
+ handles PHY initialization, clock management required after
|
||||
+ resetting the hardware and power management.
|
||||
+
|
||||
config PHY_QCOM_USB_HS
|
||||
tristate "Qualcomm USB HS PHY module"
|
||||
depends on USB_ULPI_BUS
|
||||
--- a/drivers/phy/qualcomm/Makefile
|
||||
+++ b/drivers/phy/qualcomm/Makefile
|
||||
@@ -17,6 +17,7 @@ obj-$(CONFIG_PHY_QCOM_QMP_USB_LEGACY) +=
|
||||
obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
|
||||
obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2) += phy-qcom-snps-eusb2.o
|
||||
obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER) += phy-qcom-eusb2-repeater.o
|
||||
+obj-$(CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP) += phy-qcom-uniphy-pcie-28lp.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
|
||||
@@ -0,0 +1,285 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Copyright (c) 2025, The Linux Foundation. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/phy/phy.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/reset.h>
|
||||
+
|
||||
+#define RST_ASSERT_DELAY_MIN_US 100
|
||||
+#define RST_ASSERT_DELAY_MAX_US 150
|
||||
+#define PIPE_CLK_DELAY_MIN_US 5000
|
||||
+#define PIPE_CLK_DELAY_MAX_US 5100
|
||||
+#define CLK_EN_DELAY_MIN_US 30
|
||||
+#define CLK_EN_DELAY_MAX_US 50
|
||||
+#define CDR_CTRL_REG_1 0x80
|
||||
+#define CDR_CTRL_REG_2 0x84
|
||||
+#define CDR_CTRL_REG_3 0x88
|
||||
+#define CDR_CTRL_REG_4 0x8c
|
||||
+#define CDR_CTRL_REG_5 0x90
|
||||
+#define CDR_CTRL_REG_6 0x94
|
||||
+#define CDR_CTRL_REG_7 0x98
|
||||
+#define SSCG_CTRL_REG_1 0x9c
|
||||
+#define SSCG_CTRL_REG_2 0xa0
|
||||
+#define SSCG_CTRL_REG_3 0xa4
|
||||
+#define SSCG_CTRL_REG_4 0xa8
|
||||
+#define SSCG_CTRL_REG_5 0xac
|
||||
+#define SSCG_CTRL_REG_6 0xb0
|
||||
+#define PCS_INTERNAL_CONTROL_2 0x2d8
|
||||
+
|
||||
+#define PHY_CFG_PLLCFG 0x220
|
||||
+#define PHY_CFG_EIOS_DTCT_REG 0x3e4
|
||||
+#define PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME 0x3e8
|
||||
+
|
||||
+#define PHY_MODE_FIXED 0x1
|
||||
+
|
||||
+enum qcom_uniphy_pcie_type {
|
||||
+ PHY_TYPE_PCIE = 1,
|
||||
+ PHY_TYPE_PCIE_GEN2,
|
||||
+ PHY_TYPE_PCIE_GEN3,
|
||||
+};
|
||||
+
|
||||
+struct qcom_uniphy_pcie_regs {
|
||||
+ u32 offset;
|
||||
+ u32 val;
|
||||
+};
|
||||
+
|
||||
+struct qcom_uniphy_pcie_data {
|
||||
+ int lane_offset; /* offset between the lane register bases */
|
||||
+ u32 phy_type;
|
||||
+ const struct qcom_uniphy_pcie_regs *init_seq;
|
||||
+ u32 init_seq_num;
|
||||
+ u32 pipe_clk_rate;
|
||||
+};
|
||||
+
|
||||
+struct qcom_uniphy_pcie {
|
||||
+ struct phy phy;
|
||||
+ struct device *dev;
|
||||
+ const struct qcom_uniphy_pcie_data *data;
|
||||
+ struct clk_bulk_data *clks;
|
||||
+ int num_clks;
|
||||
+ struct reset_control *resets;
|
||||
+ void __iomem *base;
|
||||
+ int lanes;
|
||||
+};
|
||||
+
|
||||
+#define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy)
|
||||
+
|
||||
+static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
|
||||
+ {
|
||||
+ .offset = PHY_CFG_PLLCFG,
|
||||
+ .val = 0x30,
|
||||
+ }, {
|
||||
+ .offset = PHY_CFG_EIOS_DTCT_REG,
|
||||
+ .val = 0x53ef,
|
||||
+ }, {
|
||||
+ .offset = PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME,
|
||||
+ .val = 0xcf,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct qcom_uniphy_pcie_data ipq5332_data = {
|
||||
+ .lane_offset = 0x800,
|
||||
+ .phy_type = PHY_TYPE_PCIE_GEN3,
|
||||
+ .init_seq = ipq5332_regs,
|
||||
+ .init_seq_num = ARRAY_SIZE(ipq5332_regs),
|
||||
+ .pipe_clk_rate = 250000000,
|
||||
+};
|
||||
+
|
||||
+static void qcom_uniphy_pcie_init(struct qcom_uniphy_pcie *phy)
|
||||
+{
|
||||
+ const struct qcom_uniphy_pcie_data *data = phy->data;
|
||||
+ const struct qcom_uniphy_pcie_regs *init_seq;
|
||||
+ void __iomem *base = phy->base;
|
||||
+ int lane, i;
|
||||
+
|
||||
+ for (lane = 0; lane < phy->lanes; lane++) {
|
||||
+ init_seq = data->init_seq;
|
||||
+
|
||||
+ for (i = 0; i < data->init_seq_num; i++)
|
||||
+ writel(init_seq[i].val, base + init_seq[i].offset);
|
||||
+
|
||||
+ base += data->lane_offset;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int qcom_uniphy_pcie_power_off(struct phy *x)
|
||||
+{
|
||||
+ struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
|
||||
+
|
||||
+ clk_bulk_disable_unprepare(phy->num_clks, phy->clks);
|
||||
+
|
||||
+ return reset_control_assert(phy->resets);
|
||||
+}
|
||||
+
|
||||
+static int qcom_uniphy_pcie_power_on(struct phy *x)
|
||||
+{
|
||||
+ struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reset_control_assert(phy->resets);
|
||||
+ if (ret) {
|
||||
+ dev_err(phy->dev, "reset assert failed (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ usleep_range(RST_ASSERT_DELAY_MIN_US, RST_ASSERT_DELAY_MAX_US);
|
||||
+
|
||||
+ ret = reset_control_deassert(phy->resets);
|
||||
+ if (ret) {
|
||||
+ dev_err(phy->dev, "reset deassert failed (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ usleep_range(PIPE_CLK_DELAY_MIN_US, PIPE_CLK_DELAY_MAX_US);
|
||||
+
|
||||
+ ret = clk_bulk_prepare_enable(phy->num_clks, phy->clks);
|
||||
+ if (ret) {
|
||||
+ dev_err(phy->dev, "clk prepare and enable failed %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ usleep_range(CLK_EN_DELAY_MIN_US, CLK_EN_DELAY_MAX_US);
|
||||
+
|
||||
+ qcom_uniphy_pcie_init(phy);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int qcom_uniphy_pcie_get_resources(struct platform_device *pdev,
|
||||
+ struct qcom_uniphy_pcie *phy)
|
||||
+{
|
||||
+ struct resource *res;
|
||||
+
|
||||
+ phy->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
+ if (IS_ERR(phy->base))
|
||||
+ return PTR_ERR(phy->base);
|
||||
+
|
||||
+ phy->num_clks = devm_clk_bulk_get_all(phy->dev, &phy->clks);
|
||||
+ if (phy->num_clks < 0)
|
||||
+ return phy->num_clks;
|
||||
+
|
||||
+ phy->resets = devm_reset_control_array_get_exclusive(phy->dev);
|
||||
+ if (IS_ERR(phy->resets))
|
||||
+ return PTR_ERR(phy->resets);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Register a fixed rate pipe clock.
|
||||
+ *
|
||||
+ * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
|
||||
+ * controls it. The <s>_pipe_clk coming out of the GCC is requested
|
||||
+ * by the PHY driver for its operations.
|
||||
+ * We register the <s>_pipe_clksrc here. The gcc driver takes care
|
||||
+ * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
|
||||
+ * Below picture shows this relationship.
|
||||
+ *
|
||||
+ * +---------------+
|
||||
+ * | PHY block |<<---------------------------------------+
|
||||
+ * | | |
|
||||
+ * | +-------+ | +-----+ |
|
||||
+ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
|
||||
+ * clk | +-------+ | +-----+
|
||||
+ * +---------------+
|
||||
+ */
|
||||
+static inline int phy_pipe_clk_register(struct qcom_uniphy_pcie *phy, int id)
|
||||
+{
|
||||
+ const struct qcom_uniphy_pcie_data *data = phy->data;
|
||||
+ struct clk_hw *hw;
|
||||
+ char name[64];
|
||||
+
|
||||
+ snprintf(name, sizeof(name), "phy%d_pipe_clk_src", id);
|
||||
+ hw = devm_clk_hw_register_fixed_rate(phy->dev, name, NULL, 0,
|
||||
+ data->pipe_clk_rate);
|
||||
+ if (IS_ERR(hw))
|
||||
+ return dev_err_probe(phy->dev, PTR_ERR(hw),
|
||||
+ "Unable to register %s\n", name);
|
||||
+
|
||||
+ return devm_of_clk_add_hw_provider(phy->dev, of_clk_hw_simple_get, hw);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
|
||||
+ {
|
||||
+ .compatible = "qcom,ipq5332-uniphy-pcie-phy",
|
||||
+ .data = &ipq5332_data,
|
||||
+ }, {
|
||||
+ /* Sentinel */
|
||||
+ },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, qcom_uniphy_pcie_id_table);
|
||||
+
|
||||
+static const struct phy_ops pcie_ops = {
|
||||
+ .power_on = qcom_uniphy_pcie_power_on,
|
||||
+ .power_off = qcom_uniphy_pcie_power_off,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int qcom_uniphy_pcie_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct phy_provider *phy_provider;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct qcom_uniphy_pcie *phy;
|
||||
+ struct phy *generic_phy;
|
||||
+ int ret;
|
||||
+
|
||||
+ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
|
||||
+ if (!phy)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, phy);
|
||||
+ phy->dev = &pdev->dev;
|
||||
+
|
||||
+ phy->data = of_device_get_match_data(dev);
|
||||
+ if (!phy->data)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ phy->lanes = 1;
|
||||
+ ret = of_property_read_u32(dev->of_node, "num-lanes", &phy->lanes);
|
||||
+
|
||||
+ ret = qcom_uniphy_pcie_get_resources(pdev, phy);
|
||||
+ if (ret < 0)
|
||||
+ return dev_err_probe(&pdev->dev, ret,
|
||||
+ "failed to get resources: %d\n", ret);
|
||||
+
|
||||
+ generic_phy = devm_phy_create(phy->dev, NULL, &pcie_ops);
|
||||
+ if (IS_ERR(generic_phy))
|
||||
+ return PTR_ERR(generic_phy);
|
||||
+
|
||||
+ phy_set_drvdata(generic_phy, phy);
|
||||
+
|
||||
+ ret = phy_pipe_clk_register(phy, generic_phy->id);
|
||||
+ if (ret)
|
||||
+ dev_err(&pdev->dev, "failed to register phy pipe clk\n");
|
||||
+
|
||||
+ phy_provider = devm_of_phy_provider_register(phy->dev,
|
||||
+ of_phy_simple_xlate);
|
||||
+ if (IS_ERR(phy_provider))
|
||||
+ return PTR_ERR(phy_provider);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver qcom_uniphy_pcie_driver = {
|
||||
+ .probe = qcom_uniphy_pcie_probe,
|
||||
+ .driver = {
|
||||
+ .name = "qcom-uniphy-pcie",
|
||||
+ .of_match_table = qcom_uniphy_pcie_id_table,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(qcom_uniphy_pcie_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("PCIE QCOM UNIPHY driver");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,25 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Tue, 07 Jan 2025 17:34:13 +0400
|
||||
Subject: [PATCH] phy: qualcomm: qcom-uniphy-pcie add IPQ5018 compatible
|
||||
|
||||
The Qualcomm UNIPHY PCIe PHY 28lp part of the IPQ5332 SoC is also present on
|
||||
the IPQ5018 SoC, so adding the compatible for IPQ5018.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
|
||||
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
|
||||
@@ -11,11 +11,12 @@ maintainers:
|
||||
- Varadarajan Narayanan <quic_varada@quicinc.com>
|
||||
|
||||
description:
|
||||
- PCIe and USB combo PHY found in Qualcomm IPQ5332 SoC
|
||||
+ PCIe and USB combo PHY found in Qualcomm IPQ5018 and IPQ5332 SoCs
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
+ - qcom,ipq5018-uniphy-pcie-phy
|
||||
- qcom,ipq5332-uniphy-pcie-phy
|
||||
|
||||
reg:
|
@ -0,0 +1,77 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Tue, 07 Jan 2025 17:34:13 +0400
|
||||
Subject: [PATCH] phy: qualcomm: qcom-uniphy-pcie 28lp add support for IPQ5018
|
||||
|
||||
The Qualcomm UNIPHY PCIe PHY 28lp is found on both IPQ5332 and IPQ5018.
|
||||
Adding the PHY init sequence, pipe clock rate, and compatible for IPQ5018.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
|
||||
+++ b/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
|
||||
@@ -76,6 +76,40 @@ struct qcom_uniphy_pcie {
|
||||
|
||||
#define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy)
|
||||
|
||||
+static const struct qcom_uniphy_pcie_regs ipq5018_regs[] = {
|
||||
+ {
|
||||
+ .offset = SSCG_CTRL_REG_4,
|
||||
+ .val = 0x1cb9,
|
||||
+ }, {
|
||||
+ .offset = SSCG_CTRL_REG_5,
|
||||
+ .val = 0x023a,
|
||||
+ }, {
|
||||
+ .offset = SSCG_CTRL_REG_3,
|
||||
+ .val = 0xd360,
|
||||
+ }, {
|
||||
+ .offset = SSCG_CTRL_REG_1,
|
||||
+ .val = 0x1,
|
||||
+ }, {
|
||||
+ .offset = SSCG_CTRL_REG_2,
|
||||
+ .val = 0xeb,
|
||||
+ }, {
|
||||
+ .offset = CDR_CTRL_REG_4,
|
||||
+ .val = 0x3f9,
|
||||
+ }, {
|
||||
+ .offset = CDR_CTRL_REG_5,
|
||||
+ .val = 0x1c9,
|
||||
+ }, {
|
||||
+ .offset = CDR_CTRL_REG_2,
|
||||
+ .val = 0x419,
|
||||
+ }, {
|
||||
+ .offset = CDR_CTRL_REG_1,
|
||||
+ .val = 0x200,
|
||||
+ }, {
|
||||
+ .offset = PCS_INTERNAL_CONTROL_2,
|
||||
+ .val = 0xf101,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
|
||||
{
|
||||
.offset = PHY_CFG_PLLCFG,
|
||||
@@ -89,6 +123,14 @@ static const struct qcom_uniphy_pcie_reg
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct qcom_uniphy_pcie_data ipq5018_data = {
|
||||
+ .lane_offset = 0x800,
|
||||
+ .phy_type = PHY_TYPE_PCIE_GEN2,
|
||||
+ .init_seq = ipq5018_regs,
|
||||
+ .init_seq_num = ARRAY_SIZE(ipq5018_regs),
|
||||
+ .pipe_clk_rate = 125000000,
|
||||
+};
|
||||
+
|
||||
static const struct qcom_uniphy_pcie_data ipq5332_data = {
|
||||
.lane_offset = 0x800,
|
||||
.phy_type = PHY_TYPE_PCIE_GEN3,
|
||||
@@ -212,6 +254,9 @@ static inline int phy_pipe_clk_register(
|
||||
|
||||
static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
|
||||
{
|
||||
+ .compatible = "qcom,ipq5018-uniphy-pcie-phy",
|
||||
+ .data = &ipq5018_data,
|
||||
+ }, {
|
||||
.compatible = "qcom,ipq5332-uniphy-pcie-phy",
|
||||
.data = &ipq5332_data,
|
||||
}, {
|
@ -0,0 +1,78 @@
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Date: Tue, 3 Oct 2023 17:38:42 +0530
|
||||
Subject: [PATCH] dt-bindings: PCI: qcom: Add IPQ5108 SoC
|
||||
|
||||
Add support for the PCIe controller on the Qualcomm
|
||||
IPQ5108 SoC to the bindings.
|
||||
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
---
|
||||
.../devicetree/bindings/pci/qcom,pcie.yaml | 36 +++++++++++++++++++
|
||||
1 file changed, 36 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
|
||||
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
|
||||
@@ -21,6 +21,7 @@ properties:
|
||||
- qcom,pcie-apq8064
|
||||
- qcom,pcie-apq8084
|
||||
- qcom,pcie-ipq4019
|
||||
+ - qcom,pcie-ipq5018
|
||||
- qcom,pcie-ipq6018
|
||||
- qcom,pcie-ipq8064
|
||||
- qcom,pcie-ipq8064-v2
|
||||
@@ -170,6 +171,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
+ - qcom,pcie-ipq5018
|
||||
- qcom,pcie-ipq6018
|
||||
- qcom,pcie-ipq8074-gen3
|
||||
then:
|
||||
@@ -337,6 +339,39 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
+ - qcom,pcie-ipq5018
|
||||
+ then:
|
||||
+ properties:
|
||||
+ clocks:
|
||||
+ minItems: 6
|
||||
+ maxItems: 6
|
||||
+ clock-names:
|
||||
+ items:
|
||||
+ - const: iface # PCIe to SysNOC BIU clock
|
||||
+ - const: axi_m # AXI Master clock
|
||||
+ - const: axi_s # AXI Slave clock
|
||||
+ - const: ahb # AHB clock
|
||||
+ - const: aux # Auxiliary clock
|
||||
+ - const: axi_bridge # AXI bridge clock
|
||||
+ resets:
|
||||
+ minItems: 8
|
||||
+ maxItems: 8
|
||||
+ reset-names:
|
||||
+ items:
|
||||
+ - const: pipe # PIPE reset
|
||||
+ - const: sleep # Sleep reset
|
||||
+ - const: sticky # Core sticky reset
|
||||
+ - const: axi_m # AXI master reset
|
||||
+ - const: axi_s # AXI slave reset
|
||||
+ - const: ahb # AHB reset
|
||||
+ - const: axi_m_sticky # AXI master sticky reset
|
||||
+ - const: axi_s_sticky # AXI slave sticky reset
|
||||
+
|
||||
+ - if:
|
||||
+ properties:
|
||||
+ compatible:
|
||||
+ contains:
|
||||
+ enum:
|
||||
- qcom,pcie-msm8996
|
||||
then:
|
||||
properties:
|
||||
@@ -875,6 +910,7 @@ allOf:
|
||||
- qcom,pcie-apq8064
|
||||
- qcom,pcie-apq8084
|
||||
- qcom,pcie-ipq4019
|
||||
+ - qcom,pcie-ipq5018
|
||||
- qcom,pcie-ipq6018
|
||||
- qcom,pcie-ipq8064
|
||||
- qcom,pcie-ipq8064-v2
|
@ -0,0 +1,77 @@
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Subject: [PATCH] PCI: qcom: Add support for IPQ5018
|
||||
Date: Tue, 3 Oct 2023 17:38:44 +0530
|
||||
|
||||
Added a new compatible 'qcom,pcie-ipq5018' and modified
|
||||
get_resources of 'ops 2_9_0' to get the clocks from the
|
||||
device-tree.
|
||||
|
||||
Co-developed-by: Anusha Rao <quic_anusha@quicinc.com>
|
||||
Signed-off-by: Anusha Rao <quic_anusha@quicinc.com>
|
||||
Co-developed-by: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
---
|
||||
drivers/pci/controller/dwc/pcie-qcom.c | 22 ++++++++--------------
|
||||
1 file changed, 8 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/dwc/pcie-qcom.c
|
||||
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
|
||||
@@ -202,8 +202,9 @@ struct qcom_pcie_resources_2_7_0 {
|
||||
|
||||
#define QCOM_PCIE_2_9_0_MAX_CLOCKS 5
|
||||
struct qcom_pcie_resources_2_9_0 {
|
||||
- struct clk_bulk_data clks[QCOM_PCIE_2_9_0_MAX_CLOCKS];
|
||||
+ struct clk_bulk_data *clks;
|
||||
struct reset_control *rst;
|
||||
+ int num_clks;
|
||||
};
|
||||
|
||||
union qcom_pcie_resources {
|
||||
@@ -1073,17 +1074,10 @@ static int qcom_pcie_get_resources_2_9_0
|
||||
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
- int ret;
|
||||
-
|
||||
- res->clks[0].id = "iface";
|
||||
- res->clks[1].id = "axi_m";
|
||||
- res->clks[2].id = "axi_s";
|
||||
- res->clks[3].id = "axi_bridge";
|
||||
- res->clks[4].id = "rchng";
|
||||
|
||||
- ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
+ res->num_clks = devm_clk_bulk_get_all(dev, &res->clks);
|
||||
+ if (res->num_clks < 0)
|
||||
+ return res->num_clks;
|
||||
|
||||
res->rst = devm_reset_control_array_get_exclusive(dev);
|
||||
if (IS_ERR(res->rst))
|
||||
@@ -1096,7 +1090,7 @@ static void qcom_pcie_deinit_2_9_0(struc
|
||||
{
|
||||
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
|
||||
|
||||
- clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
|
||||
+ clk_bulk_disable_unprepare(res->num_clks, res->clks);
|
||||
}
|
||||
|
||||
static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie)
|
||||
@@ -1125,7 +1119,7 @@ static int qcom_pcie_init_2_9_0(struct q
|
||||
|
||||
usleep_range(2000, 2500);
|
||||
|
||||
- return clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
|
||||
+ return clk_bulk_prepare_enable(res->num_clks, res->clks);
|
||||
}
|
||||
|
||||
static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
|
||||
@@ -1641,6 +1635,7 @@ static const struct of_device_id qcom_pc
|
||||
{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
|
||||
{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
|
||||
{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
|
||||
+ { .compatible = "qcom,pcie-ipq5018", .data = &cfg_2_9_0 },
|
||||
{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
|
||||
{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
|
||||
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },
|
@ -0,0 +1,216 @@
|
||||
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PCIe related nodes
|
||||
Date: Tue, 3 Oct 2023 17:38:45 +0530
|
||||
|
||||
Add phy and controller nodes for PCIe0 and PCIe1.
|
||||
PCIe0 is 2-lane Gen2 and PCIe1 is 1-lane Gen2.
|
||||
|
||||
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 186 +++++++++++++++++++++++++-
|
||||
1 file changed, 184 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -149,6 +149,42 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ pcie1_phy: phy@7e000{
|
||||
+ compatible = "qcom,ipq5018-uniphy-pcie-phy";
|
||||
+ reg = <0x0007e000 0x800>;
|
||||
+
|
||||
+ clocks = <&gcc GCC_PCIE1_PIPE_CLK>;
|
||||
+
|
||||
+ resets = <&gcc GCC_PCIE1_PHY_BCR>,
|
||||
+ <&gcc GCC_PCIE1PHY_PHY_BCR>;
|
||||
+
|
||||
+ #clock-cells = <0>;
|
||||
+
|
||||
+ #phy-cells = <0>;
|
||||
+
|
||||
+ num-lanes = <1>;
|
||||
+
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ pcie0_phy: phy@86000{
|
||||
+ compatible = "qcom,ipq5018-uniphy-pcie-phy";
|
||||
+ reg = <0x00086000 0x800>;
|
||||
+
|
||||
+ clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
|
||||
+
|
||||
+ resets = <&gcc GCC_PCIE0_PHY_BCR>,
|
||||
+ <&gcc GCC_PCIE0PHY_PHY_BCR>;
|
||||
+
|
||||
+ #clock-cells = <0>;
|
||||
+
|
||||
+ #phy-cells = <0>;
|
||||
+
|
||||
+ num-lanes = <2>;
|
||||
+
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
qfprom: qfprom@a0000 {
|
||||
compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
|
||||
reg = <0xa0000 0x1000>;
|
||||
@@ -283,8 +319,8 @@
|
||||
reg = <0x01800000 0x80000>;
|
||||
clocks = <&xo_board_clk>,
|
||||
<&sleep_clk>,
|
||||
- <0>,
|
||||
- <0>,
|
||||
+ <&pcie0_phy>,
|
||||
+ <&pcie1_phy>,
|
||||
<0>,
|
||||
<0>,
|
||||
<0>,
|
||||
@@ -501,6 +537,146 @@
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ pcie1: pcie@80000000 {
|
||||
+ compatible = "qcom,pcie-ipq5018";
|
||||
+ reg = <0x80000000 0xf1d>,
|
||||
+ <0x80000f20 0xa8>,
|
||||
+ <0x80001000 0x1000>,
|
||||
+ <0x00078000 0x3000>,
|
||||
+ <0x80100000 0x1000>;
|
||||
+ reg-names = "dbi",
|
||||
+ "elbi",
|
||||
+ "atu",
|
||||
+ "parf",
|
||||
+ "config";
|
||||
+ device_type = "pci";
|
||||
+ linux,pci-domain = <0>;
|
||||
+ bus-range = <0x00 0xff>;
|
||||
+ num-lanes = <1>;
|
||||
+ max-link-speed = <2>;
|
||||
+ #address-cells = <3>;
|
||||
+ #size-cells = <2>;
|
||||
+
|
||||
+ phys = <&pcie1_phy>;
|
||||
+ phy-names ="pciephy";
|
||||
+
|
||||
+ ranges = <0x81000000 0 0x80200000 0x80200000 0 0x00100000>, /* I/O */
|
||||
+ <0x82000000 0 0x80300000 0x80300000 0 0x10000000>; /* MEM */
|
||||
+
|
||||
+ #interrupt-cells = <1>;
|
||||
+ interrupt-map-mask = <0 0 0 0x7>;
|
||||
+ interrupt-map = <0 0 0 1 &intc 0 142 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
|
||||
+ <0 0 0 2 &intc 0 143 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
|
||||
+ <0 0 0 3 &intc 0 144 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
|
||||
+ <0 0 0 4 &intc 0 145 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
|
||||
+
|
||||
+ interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "global_irq";
|
||||
+
|
||||
+ clocks = <&gcc GCC_SYS_NOC_PCIE1_AXI_CLK>,
|
||||
+ <&gcc GCC_PCIE1_AXI_M_CLK>,
|
||||
+ <&gcc GCC_PCIE1_AXI_S_CLK>,
|
||||
+ <&gcc GCC_PCIE1_AHB_CLK>,
|
||||
+ <&gcc GCC_PCIE1_AUX_CLK>,
|
||||
+ <&gcc GCC_PCIE1_AXI_S_BRIDGE_CLK>;
|
||||
+ clock-names = "iface",
|
||||
+ "axi_m",
|
||||
+ "axi_s",
|
||||
+ "ahb",
|
||||
+ "aux",
|
||||
+ "axi_bridge";
|
||||
+
|
||||
+ resets = <&gcc GCC_PCIE1_PIPE_ARES>,
|
||||
+ <&gcc GCC_PCIE1_SLEEP_ARES>,
|
||||
+ <&gcc GCC_PCIE1_CORE_STICKY_ARES>,
|
||||
+ <&gcc GCC_PCIE1_AXI_MASTER_ARES>,
|
||||
+ <&gcc GCC_PCIE1_AXI_SLAVE_ARES>,
|
||||
+ <&gcc GCC_PCIE1_AHB_ARES>,
|
||||
+ <&gcc GCC_PCIE1_AXI_MASTER_STICKY_ARES>,
|
||||
+ <&gcc GCC_PCIE1_AXI_SLAVE_STICKY_ARES>;
|
||||
+ reset-names = "pipe",
|
||||
+ "sleep",
|
||||
+ "sticky",
|
||||
+ "axi_m",
|
||||
+ "axi_s",
|
||||
+ "ahb",
|
||||
+ "axi_m_sticky",
|
||||
+ "axi_s_sticky";
|
||||
+
|
||||
+ msi-map = <0x0 &v2m0 0x0 0xff8>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ pcie0: pcie@a0000000 {
|
||||
+ compatible = "qcom,pcie-ipq5018";
|
||||
+ reg = <0xa0000000 0xf1d>,
|
||||
+ <0xa0000f20 0xa8>,
|
||||
+ <0xa0001000 0x1000>,
|
||||
+ <0x00080000 0x3000>,
|
||||
+ <0xa0100000 0x1000>;
|
||||
+ reg-names = "dbi",
|
||||
+ "elbi",
|
||||
+ "atu",
|
||||
+ "parf",
|
||||
+ "config";
|
||||
+ device_type = "pci";
|
||||
+ linux,pci-domain = <1>;
|
||||
+ bus-range = <0x00 0xff>;
|
||||
+ num-lanes = <2>;
|
||||
+ max-link-speed = <2>;
|
||||
+ #address-cells = <3>;
|
||||
+ #size-cells = <2>;
|
||||
+
|
||||
+ phys = <&pcie0_phy>;
|
||||
+ phy-names ="pciephy";
|
||||
+
|
||||
+ ranges = <0x81000000 0 0xa0200000 0xa0200000 0 0x00100000>, /* I/O */
|
||||
+ <0x82000000 0 0xa0300000 0xa0300000 0 0x10000000>; /* MEM */
|
||||
+
|
||||
+ #interrupt-cells = <1>;
|
||||
+ interrupt-map-mask = <0 0 0 0x7>;
|
||||
+ interrupt-map = <0 0 0 1 &intc 0 75 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
|
||||
+ <0 0 0 2 &intc 0 78 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
|
||||
+ <0 0 0 3 &intc 0 79 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
|
||||
+ <0 0 0 4 &intc 0 83 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
|
||||
+
|
||||
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "global_irq";
|
||||
+
|
||||
+ clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>,
|
||||
+ <&gcc GCC_PCIE0_AXI_M_CLK>,
|
||||
+ <&gcc GCC_PCIE0_AXI_S_CLK>,
|
||||
+ <&gcc GCC_PCIE0_AHB_CLK>,
|
||||
+ <&gcc GCC_PCIE0_AUX_CLK>,
|
||||
+ <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>;
|
||||
+ clock-names = "iface",
|
||||
+ "axi_m",
|
||||
+ "axi_s",
|
||||
+ "ahb",
|
||||
+ "aux",
|
||||
+ "axi_bridge";
|
||||
+
|
||||
+ resets = <&gcc GCC_PCIE0_PIPE_ARES>,
|
||||
+ <&gcc GCC_PCIE0_SLEEP_ARES>,
|
||||
+ <&gcc GCC_PCIE0_CORE_STICKY_ARES>,
|
||||
+ <&gcc GCC_PCIE0_AXI_MASTER_ARES>,
|
||||
+ <&gcc GCC_PCIE0_AXI_SLAVE_ARES>,
|
||||
+ <&gcc GCC_PCIE0_AHB_ARES>,
|
||||
+ <&gcc GCC_PCIE0_AXI_MASTER_STICKY_ARES>,
|
||||
+ <&gcc GCC_PCIE0_AXI_SLAVE_STICKY_ARES>;
|
||||
+ reset-names = "pipe",
|
||||
+ "sleep",
|
||||
+ "sticky",
|
||||
+ "axi_m",
|
||||
+ "axi_s",
|
||||
+ "ahb",
|
||||
+ "axi_m_sticky",
|
||||
+ "axi_s_sticky";
|
||||
+
|
||||
+ msi-map = <0x0 &v2m0 0x0 0xff8>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
};
|
||||
|
||||
thermal-zones {
|
@ -0,0 +1,18 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] dt-bindings: mfd: qcom,tcsr: Add IPQ5018 compatible
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Document the qcom,tcsr-ipq5018 compatible.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
|
||||
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
|
||||
@@ -33,6 +33,7 @@ properties:
|
||||
- qcom,sm8450-tcsr
|
||||
- qcom,tcsr-apq8064
|
||||
- qcom,tcsr-apq8084
|
||||
+ - qcom,tcsr-ipq5018
|
||||
- qcom,tcsr-ipq5332
|
||||
- qcom,tcsr-ipq8064
|
||||
- qcom,tcsr-ipq8074
|
@ -0,0 +1,22 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add TCSR node
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add TCSR node.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -337,6 +337,11 @@
|
||||
#hwlock-cells = <1>;
|
||||
};
|
||||
|
||||
+ tcsr: syscon@1937000 {
|
||||
+ compatible = "qcom,tcsr-ipq5018", "syscon", "simple-mfd";
|
||||
+ reg = <0x01937000 0x21000>;
|
||||
+ };
|
||||
+
|
||||
sdhc_1: mmc@7804000 {
|
||||
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
|
||||
reg = <0x7804000 0x1000>;
|
@ -0,0 +1,19 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: enable the download mode support
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
IPQ5018 also supports the download mode to collect the RAM dumps if system crashes, to perform
|
||||
the post mortem analysis. Add support for the same.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -82,6 +82,7 @@
|
||||
scm {
|
||||
compatible = "qcom,scm-ipq5018", "qcom,scm";
|
||||
qcom,sdi-enabled;
|
||||
+ qcom,dload-mode = <&tcsr 0x6100>;
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,22 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] dt-bindings: mfd: qcom,tcsr: Add IPQ5018 compatible
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add compatible for IPQ5018.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
|
||||
+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
|
||||
@@ -11,7 +11,10 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
- const: qcom,ipq6018-pwm
|
||||
+ items:
|
||||
+ - enum:
|
||||
+ - qcom,ipq5018-pwm
|
||||
+ - const: qcom,ipq6018-pwm
|
||||
|
||||
reg:
|
||||
description: Offset of PWM register in the TCSR block.
|
@ -0,0 +1,65 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] pinctrl: qcom: IPQ5018: update pwm groups
|
||||
Date: Wed, 27 Nov 2024 09:14:11 +0400
|
||||
|
||||
GPIO 1, 30, and 46 are used to control PWM1, PWM3, and PWM0 respectively which
|
||||
in turn drive the PWM led, so let's update the pwm# and pingroups accordingly.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c
|
||||
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
|
||||
@@ -541,7 +541,7 @@ static const char * const qdss_tracectl_
|
||||
};
|
||||
|
||||
static const char * const pwm0_groups[] = {
|
||||
- "gpio42",
|
||||
+ "gpio42", "gpio46",
|
||||
};
|
||||
|
||||
static const char * const qdss_cti_trig_out_b0_groups[] = {
|
||||
@@ -549,7 +549,7 @@ static const char * const qdss_cti_trig_
|
||||
};
|
||||
|
||||
static const char * const pwm1_groups[] = {
|
||||
- "gpio43",
|
||||
+ "gpio43", "gpio1",
|
||||
};
|
||||
|
||||
static const char * const qdss_cti_trig_in_b0_groups[] = {
|
||||
@@ -565,7 +565,7 @@ static const char * const qdss_cti_trig_
|
||||
};
|
||||
|
||||
static const char * const pwm3_groups[] = {
|
||||
- "gpio45",
|
||||
+ "gpio45", "gpio30",
|
||||
};
|
||||
|
||||
static const char * const qdss_cti_trig_in_b1_groups[] = {
|
||||
@@ -679,7 +679,7 @@ static const struct pinfunction ipq5018_
|
||||
|
||||
static const struct msm_pingroup ipq5018_groups[] = {
|
||||
PINGROUP(0, atest_char, _, qdss_cti_trig_out_a0, wci_txd, wci_rxd, xfem, _, _, _),
|
||||
- PINGROUP(1, atest_char, _, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
|
||||
+ PINGROUP(1, atest_char, pwm1, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
|
||||
PINGROUP(2, atest_char, _, qdss_cti_trig_out_a1, wci_txd, wci_rxd, xfem, _, _, _),
|
||||
PINGROUP(3, atest_char, _, qdss_cti_trig_in_a1, wci_txd, wci_rxd, xfem, _, _, _),
|
||||
PINGROUP(4, sdc1_data, qspi_data, blsp1_spi1, btss, dbg_out, qdss_traceclk_a, _, burn0, _),
|
||||
@@ -708,7 +708,7 @@ static const struct msm_pingroup ipq5018
|
||||
PINGROUP(27, audio_txmclk, wsa_swrm, audio_txmclk, blsp2_spi, btss, _, qdss_tracedata_b, _, _),
|
||||
PINGROUP(28, audio_txbclk, wsa_swrm, blsp0_uart1, btss, qdss_tracedata_b, _, _, _, _),
|
||||
PINGROUP(29, audio_txfsync, _, blsp0_uart1, _, qdss_tracedata_b, _, _, _, _),
|
||||
- PINGROUP(30, audio_txd, led2, led0, _, _, _, _, _, _),
|
||||
+ PINGROUP(30, audio_txd, led2, led0, pwm3, _, _, _, _, _),
|
||||
PINGROUP(31, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
|
||||
PINGROUP(32, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
|
||||
PINGROUP(33, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _),
|
||||
@@ -724,7 +724,7 @@ static const struct msm_pingroup ipq5018
|
||||
PINGROUP(43, pwm1, qdss_cti_trig_in_b0, wci_txd, wci_rxd, xfem, _, _, _, _),
|
||||
PINGROUP(44, pwm2, qdss_cti_trig_out_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
|
||||
PINGROUP(45, pwm3, qdss_cti_trig_in_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
|
||||
- PINGROUP(46, led0, _, _, _, _, _, _, _, _),
|
||||
+ PINGROUP(46, led0, pwm0, _, _, _, _, _, _, _),
|
||||
};
|
||||
|
||||
static const struct msm_pinctrl_soc_data ipq5018_pinctrl = {
|
@ -0,0 +1,27 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PWM node
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add PWM node.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -343,6 +343,16 @@
|
||||
reg = <0x01937000 0x21000>;
|
||||
};
|
||||
|
||||
+ pwm: pwm@1941010 {
|
||||
+ compatible = "qcom,ipq5018-pwm", "qcom,ipq6018-pwm";
|
||||
+ reg = <0x01941010 0x20>;
|
||||
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
|
||||
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
|
||||
+ assigned-clock-rates = <100000000>;
|
||||
+ #pwm-cells = <2>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
sdhc_1: mmc@7804000 {
|
||||
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
|
||||
reg = <0x7804000 0x1000>;
|
@ -0,0 +1,41 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add crypto nodes
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add dma controller and crypto nodes.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -297,6 +297,30 @@
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
+ cryptobam: dma-controller@704000 {
|
||||
+ compatible = "qcom,bam-v1.7.0";
|
||||
+ reg = <0x00704000 0x20000>;
|
||||
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
|
||||
+ clock-names = "bam_clk";
|
||||
+ #dma-cells = <1>;
|
||||
+ qcom,ee = <1>;
|
||||
+ qcom,controlled-remotely;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ crypto: crypto@73a000 {
|
||||
+ compatible = "qcom,crypto-v5.1";
|
||||
+ reg = <0x0073a000 0x6000>;
|
||||
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>,
|
||||
+ <&gcc GCC_CRYPTO_AXI_CLK>,
|
||||
+ <&gcc GCC_CRYPTO_CLK>;
|
||||
+ clock-names = "iface", "bus", "core";
|
||||
+ dmas = <&cryptobam 2>, <&cryptobam 3>;
|
||||
+ dma-names = "rx", "tx";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
tlmm: pinctrl@1000000 {
|
||||
compatible = "qcom,ipq5018-tlmm";
|
||||
reg = <0x01000000 0x300000>;
|
@ -0,0 +1,25 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PRNG node
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add PRNG node.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -258,6 +258,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ prng: rng@e3000 {
|
||||
+ compatible = "qcom,prng-ee";
|
||||
+ reg = <0x000e3000 0x1000>;
|
||||
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
|
||||
+ clock-names = "core";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
tsens: thermal-sensor@4a9000 {
|
||||
compatible = "qcom,ipq5018-tsens";
|
||||
reg = <0x4a9000 0x1000>, /* TM */
|
@ -0,0 +1,27 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add QUP1-UART2 node
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add QUP1-UART2 node.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -422,6 +422,16 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ blsp1_uart2: serial@78b0000 {
|
||||
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
|
||||
+ reg = <0x078b0000 0x200>;
|
||||
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>,
|
||||
+ <&gcc GCC_BLSP1_AHB_CLK>;
|
||||
+ clock-names = "core", "iface";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
blsp1_spi1: spi@78b5000 {
|
||||
compatible = "qcom,spi-qup-v2.2.1";
|
||||
#address-cells = <1>;
|
@ -0,0 +1,32 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add QUP3 I2C node
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
Add QUP3-I2C node.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -446,6 +446,21 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ blsp1_i2c3: i2c@78b7000 {
|
||||
+ compatible = "qcom,i2c-qup-v2.2.1";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ reg = <0x078b7000 0x600>;
|
||||
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>,
|
||||
+ <&gcc GCC_BLSP1_AHB_CLK>;
|
||||
+ clock-names = "core", "iface";
|
||||
+ clock-frequency = <400000>;
|
||||
+ dmas = <&blsp_dma 9>, <&blsp_dma 8>;
|
||||
+ dma-names = "tx", "rx";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
usb: usb@8af8800 {
|
||||
compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
|
||||
reg = <0x08af8800 0x400>;
|
@ -0,0 +1,97 @@
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Sun, 22 Sep 2024 17:03:44 +0530
|
||||
Subject: [PATCH] spi: dt-bindings: Introduce qcom,spi-qpic-snand
|
||||
|
||||
Document the QPIC-SPI-NAND flash controller present in the IPQ SoCs.
|
||||
It can work both in serial and parallel mode and supports typical
|
||||
SPI-NAND page cache operations.
|
||||
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
---
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qpic-snand.yaml
|
||||
@@ -0,0 +1,83 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/spi/qcom,spi-qpic-snand.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Qualcomm QPIC NAND controller
|
||||
+
|
||||
+maintainers:
|
||||
+ - Md sadre Alam <quic_mdalam@quicinc.com>
|
||||
+
|
||||
+description:
|
||||
+ The QCOM QPIC-SPI-NAND flash controller is an extended version of
|
||||
+ the QCOM QPIC NAND flash controller. It can work both in serial
|
||||
+ and parallel mode. It supports typical SPI-NAND page cache
|
||||
+ operations in single, dual or quad IO mode with pipelined ECC
|
||||
+ encoding/decoding using the QPIC ECC HW engine.
|
||||
+
|
||||
+allOf:
|
||||
+ - $ref: /schemas/spi/spi-controller.yaml#
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - qcom,spi-qpic-snand
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ clocks:
|
||||
+ maxItems: 3
|
||||
+
|
||||
+ clock-names:
|
||||
+ items:
|
||||
+ - const: core
|
||||
+ - const: aon
|
||||
+ - const: iom
|
||||
+
|
||||
+ dmas:
|
||||
+ items:
|
||||
+ - description: tx DMA channel
|
||||
+ - description: rx DMA channel
|
||||
+ - description: cmd DMA channel
|
||||
+
|
||||
+ dma-names:
|
||||
+ items:
|
||||
+ - const: tx
|
||||
+ - const: rx
|
||||
+ - const: cmd
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - clocks
|
||||
+ - clock-names
|
||||
+
|
||||
+unevaluatedProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/clock/qcom,ipq9574-gcc.h>
|
||||
+ spi@79b0000 {
|
||||
+ compatible = "qcom,spi-qpic-snand";
|
||||
+ reg = <0x1ac00000 0x800>;
|
||||
+
|
||||
+ clocks = <&gcc GCC_QPIC_CLK>,
|
||||
+ <&gcc GCC_QPIC_AHB_CLK>,
|
||||
+ <&gcc GCC_QPIC_IO_MACRO_CLK>;
|
||||
+ clock-names = "core", "aon", "iom";
|
||||
+
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+
|
||||
+ flash@0 {
|
||||
+ compatible = "spi-nand";
|
||||
+ reg = <0>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ nand-ecc-engine = <&qpic_nand>;
|
||||
+ nand-ecc-strength = <4>;
|
||||
+ nand-ecc-step-size = <512>;
|
||||
+ };
|
||||
+ };
|
@ -0,0 +1,983 @@
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Sun, 22 Sep 2024 17:03:45 +0530
|
||||
Subject: [PATCH] mtd: rawnand: qcom: cleanup qcom_nandc driver
|
||||
|
||||
cleanup qcom_nandc driver as below
|
||||
|
||||
- Remove register value indirection api
|
||||
|
||||
- Remove set_reg() api
|
||||
|
||||
- Convert read_loc_first & read_loc_last macro to function
|
||||
|
||||
- Renamed multiple variables
|
||||
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
---
|
||||
--- a/drivers/mtd/nand/raw/qcom_nandc.c
|
||||
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
|
||||
@@ -189,17 +189,6 @@
|
||||
#define ECC_BCH_4BIT BIT(2)
|
||||
#define ECC_BCH_8BIT BIT(3)
|
||||
|
||||
-#define nandc_set_read_loc_first(chip, reg, cw_offset, read_size, is_last_read_loc) \
|
||||
-nandc_set_reg(chip, reg, \
|
||||
- ((cw_offset) << READ_LOCATION_OFFSET) | \
|
||||
- ((read_size) << READ_LOCATION_SIZE) | \
|
||||
- ((is_last_read_loc) << READ_LOCATION_LAST))
|
||||
-
|
||||
-#define nandc_set_read_loc_last(chip, reg, cw_offset, read_size, is_last_read_loc) \
|
||||
-nandc_set_reg(chip, reg, \
|
||||
- ((cw_offset) << READ_LOCATION_OFFSET) | \
|
||||
- ((read_size) << READ_LOCATION_SIZE) | \
|
||||
- ((is_last_read_loc) << READ_LOCATION_LAST))
|
||||
/*
|
||||
* Returns the actual register address for all NAND_DEV_ registers
|
||||
* (i.e. NAND_DEV_CMD0, NAND_DEV_CMD1, NAND_DEV_CMD2 and NAND_DEV_CMD_VLD)
|
||||
@@ -257,8 +246,6 @@ nandc_set_reg(chip, reg, \
|
||||
* @tx_sgl_start - start index in data sgl for tx.
|
||||
* @rx_sgl_pos - current index in data sgl for rx.
|
||||
* @rx_sgl_start - start index in data sgl for rx.
|
||||
- * @wait_second_completion - wait for second DMA desc completion before making
|
||||
- * the NAND transfer completion.
|
||||
*/
|
||||
struct bam_transaction {
|
||||
struct bam_cmd_element *bam_ce;
|
||||
@@ -275,7 +262,6 @@ struct bam_transaction {
|
||||
u32 tx_sgl_start;
|
||||
u32 rx_sgl_pos;
|
||||
u32 rx_sgl_start;
|
||||
- bool wait_second_completion;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -471,9 +457,9 @@ struct qcom_op {
|
||||
unsigned int data_instr_idx;
|
||||
unsigned int rdy_timeout_ms;
|
||||
unsigned int rdy_delay_ns;
|
||||
- u32 addr1_reg;
|
||||
- u32 addr2_reg;
|
||||
- u32 cmd_reg;
|
||||
+ __le32 addr1_reg;
|
||||
+ __le32 addr2_reg;
|
||||
+ __le32 cmd_reg;
|
||||
u8 flag;
|
||||
};
|
||||
|
||||
@@ -549,17 +535,17 @@ struct qcom_nand_host {
|
||||
* among different NAND controllers.
|
||||
* @ecc_modes - ecc mode for NAND
|
||||
* @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset
|
||||
- * @is_bam - whether NAND controller is using BAM
|
||||
- * @is_qpic - whether NAND CTRL is part of qpic IP
|
||||
- * @qpic_v2 - flag to indicate QPIC IP version 2
|
||||
+ * @supports_bam - whether NAND controller is using BAM
|
||||
+ * @nandc_part_of_qpic - whether NAND controller is part of qpic IP
|
||||
+ * @qpic_version2 - flag to indicate QPIC IP version 2
|
||||
* @use_codeword_fixup - whether NAND has different layout for boot partitions
|
||||
*/
|
||||
struct qcom_nandc_props {
|
||||
u32 ecc_modes;
|
||||
u32 dev_cmd_reg_start;
|
||||
- bool is_bam;
|
||||
- bool is_qpic;
|
||||
- bool qpic_v2;
|
||||
+ bool supports_bam;
|
||||
+ bool nandc_part_of_qpic;
|
||||
+ bool qpic_version2;
|
||||
bool use_codeword_fixup;
|
||||
};
|
||||
|
||||
@@ -613,19 +599,11 @@ static void clear_bam_transaction(struct
|
||||
{
|
||||
struct bam_transaction *bam_txn = nandc->bam_txn;
|
||||
|
||||
- if (!nandc->props->is_bam)
|
||||
+ if (!nandc->props->supports_bam)
|
||||
return;
|
||||
|
||||
- bam_txn->bam_ce_pos = 0;
|
||||
- bam_txn->bam_ce_start = 0;
|
||||
- bam_txn->cmd_sgl_pos = 0;
|
||||
- bam_txn->cmd_sgl_start = 0;
|
||||
- bam_txn->tx_sgl_pos = 0;
|
||||
- bam_txn->tx_sgl_start = 0;
|
||||
- bam_txn->rx_sgl_pos = 0;
|
||||
- bam_txn->rx_sgl_start = 0;
|
||||
+ memset(&bam_txn->bam_ce_pos, 0, sizeof(u32) * 8);
|
||||
bam_txn->last_data_desc = NULL;
|
||||
- bam_txn->wait_second_completion = false;
|
||||
|
||||
sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage *
|
||||
QPIC_PER_CW_CMD_SGL);
|
||||
@@ -640,17 +618,7 @@ static void qpic_bam_dma_done(void *data
|
||||
{
|
||||
struct bam_transaction *bam_txn = data;
|
||||
|
||||
- /*
|
||||
- * In case of data transfer with NAND, 2 callbacks will be generated.
|
||||
- * One for command channel and another one for data channel.
|
||||
- * If current transaction has data descriptors
|
||||
- * (i.e. wait_second_completion is true), then set this to false
|
||||
- * and wait for second DMA descriptor completion.
|
||||
- */
|
||||
- if (bam_txn->wait_second_completion)
|
||||
- bam_txn->wait_second_completion = false;
|
||||
- else
|
||||
- complete(&bam_txn->txn_done);
|
||||
+ complete(&bam_txn->txn_done);
|
||||
}
|
||||
|
||||
static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip)
|
||||
@@ -676,10 +644,9 @@ static inline void nandc_write(struct qc
|
||||
iowrite32(val, nandc->base + offset);
|
||||
}
|
||||
|
||||
-static inline void nandc_read_buffer_sync(struct qcom_nand_controller *nandc,
|
||||
- bool is_cpu)
|
||||
+static inline void nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu)
|
||||
{
|
||||
- if (!nandc->props->is_bam)
|
||||
+ if (!nandc->props->supports_bam)
|
||||
return;
|
||||
|
||||
if (is_cpu)
|
||||
@@ -694,93 +661,90 @@ static inline void nandc_read_buffer_syn
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
-static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset)
|
||||
-{
|
||||
- switch (offset) {
|
||||
- case NAND_FLASH_CMD:
|
||||
- return ®s->cmd;
|
||||
- case NAND_ADDR0:
|
||||
- return ®s->addr0;
|
||||
- case NAND_ADDR1:
|
||||
- return ®s->addr1;
|
||||
- case NAND_FLASH_CHIP_SELECT:
|
||||
- return ®s->chip_sel;
|
||||
- case NAND_EXEC_CMD:
|
||||
- return ®s->exec;
|
||||
- case NAND_FLASH_STATUS:
|
||||
- return ®s->clrflashstatus;
|
||||
- case NAND_DEV0_CFG0:
|
||||
- return ®s->cfg0;
|
||||
- case NAND_DEV0_CFG1:
|
||||
- return ®s->cfg1;
|
||||
- case NAND_DEV0_ECC_CFG:
|
||||
- return ®s->ecc_bch_cfg;
|
||||
- case NAND_READ_STATUS:
|
||||
- return ®s->clrreadstatus;
|
||||
- case NAND_DEV_CMD1:
|
||||
- return ®s->cmd1;
|
||||
- case NAND_DEV_CMD1_RESTORE:
|
||||
- return ®s->orig_cmd1;
|
||||
- case NAND_DEV_CMD_VLD:
|
||||
- return ®s->vld;
|
||||
- case NAND_DEV_CMD_VLD_RESTORE:
|
||||
- return ®s->orig_vld;
|
||||
- case NAND_EBI2_ECC_BUF_CFG:
|
||||
- return ®s->ecc_buf_cfg;
|
||||
- case NAND_READ_LOCATION_0:
|
||||
- return ®s->read_location0;
|
||||
- case NAND_READ_LOCATION_1:
|
||||
- return ®s->read_location1;
|
||||
- case NAND_READ_LOCATION_2:
|
||||
- return ®s->read_location2;
|
||||
- case NAND_READ_LOCATION_3:
|
||||
- return ®s->read_location3;
|
||||
- case NAND_READ_LOCATION_LAST_CW_0:
|
||||
- return ®s->read_location_last0;
|
||||
- case NAND_READ_LOCATION_LAST_CW_1:
|
||||
- return ®s->read_location_last1;
|
||||
- case NAND_READ_LOCATION_LAST_CW_2:
|
||||
- return ®s->read_location_last2;
|
||||
- case NAND_READ_LOCATION_LAST_CW_3:
|
||||
- return ®s->read_location_last3;
|
||||
- default:
|
||||
- return NULL;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void nandc_set_reg(struct nand_chip *chip, int offset,
|
||||
- u32 val)
|
||||
-{
|
||||
- struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
- struct nandc_regs *regs = nandc->regs;
|
||||
- __le32 *reg;
|
||||
-
|
||||
- reg = offset_to_nandc_reg(regs, offset);
|
||||
-
|
||||
- if (reg)
|
||||
- *reg = cpu_to_le32(val);
|
||||
-}
|
||||
-
|
||||
/* Helper to check the code word, whether it is last cw or not */
|
||||
static bool qcom_nandc_is_last_cw(struct nand_ecc_ctrl *ecc, int cw)
|
||||
{
|
||||
return cw == (ecc->steps - 1);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * nandc_set_read_loc_first() - to set read location first register
|
||||
+ * @chip: NAND Private Flash Chip Data
|
||||
+ * @reg_base: location register base
|
||||
+ * @cw_offset: code word offset
|
||||
+ * @read_size: code word read length
|
||||
+ * @is_last_read_loc: is this the last read location
|
||||
+ *
|
||||
+ * This function will set location register value
|
||||
+ */
|
||||
+static void nandc_set_read_loc_first(struct nand_chip *chip,
|
||||
+ int reg_base, u32 cw_offset,
|
||||
+ u32 read_size, u32 is_last_read_loc)
|
||||
+{
|
||||
+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
+ __le32 locreg_val;
|
||||
+ u32 val = (((cw_offset) << READ_LOCATION_OFFSET) |
|
||||
+ ((read_size) << READ_LOCATION_SIZE) |
|
||||
+ ((is_last_read_loc) << READ_LOCATION_LAST));
|
||||
+
|
||||
+ locreg_val = cpu_to_le32(val);
|
||||
+
|
||||
+ if (reg_base == NAND_READ_LOCATION_0)
|
||||
+ nandc->regs->read_location0 = locreg_val;
|
||||
+ else if (reg_base == NAND_READ_LOCATION_1)
|
||||
+ nandc->regs->read_location1 = locreg_val;
|
||||
+ else if (reg_base == NAND_READ_LOCATION_2)
|
||||
+ nandc->regs->read_location2 = locreg_val;
|
||||
+ else if (reg_base == NAND_READ_LOCATION_3)
|
||||
+ nandc->regs->read_location3 = locreg_val;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * nandc_set_read_loc_last - to set read location last register
|
||||
+ * @chip: NAND Private Flash Chip Data
|
||||
+ * @reg_base: location register base
|
||||
+ * @cw_offset: code word offset
|
||||
+ * @read_size: code word read length
|
||||
+ * @is_last_read_loc: is this the last read location
|
||||
+ *
|
||||
+ * This function will set location last register value
|
||||
+ */
|
||||
+static void nandc_set_read_loc_last(struct nand_chip *chip,
|
||||
+ int reg_base, u32 cw_offset,
|
||||
+ u32 read_size, u32 is_last_read_loc)
|
||||
+{
|
||||
+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
+ __le32 locreg_val;
|
||||
+ u32 val = (((cw_offset) << READ_LOCATION_OFFSET) |
|
||||
+ ((read_size) << READ_LOCATION_SIZE) |
|
||||
+ ((is_last_read_loc) << READ_LOCATION_LAST));
|
||||
+
|
||||
+ locreg_val = cpu_to_le32(val);
|
||||
+
|
||||
+ if (reg_base == NAND_READ_LOCATION_LAST_CW_0)
|
||||
+ nandc->regs->read_location_last0 = locreg_val;
|
||||
+ else if (reg_base == NAND_READ_LOCATION_LAST_CW_1)
|
||||
+ nandc->regs->read_location_last1 = locreg_val;
|
||||
+ else if (reg_base == NAND_READ_LOCATION_LAST_CW_2)
|
||||
+ nandc->regs->read_location_last2 = locreg_val;
|
||||
+ else if (reg_base == NAND_READ_LOCATION_LAST_CW_3)
|
||||
+ nandc->regs->read_location_last3 = locreg_val;
|
||||
+}
|
||||
+
|
||||
/* helper to configure location register values */
|
||||
static void nandc_set_read_loc(struct nand_chip *chip, int cw, int reg,
|
||||
- int cw_offset, int read_size, int is_last_read_loc)
|
||||
+ u32 cw_offset, u32 read_size, u32 is_last_read_loc)
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
int reg_base = NAND_READ_LOCATION_0;
|
||||
|
||||
- if (nandc->props->qpic_v2 && qcom_nandc_is_last_cw(ecc, cw))
|
||||
+ if (nandc->props->qpic_version2 && qcom_nandc_is_last_cw(ecc, cw))
|
||||
reg_base = NAND_READ_LOCATION_LAST_CW_0;
|
||||
|
||||
reg_base += reg * 4;
|
||||
|
||||
- if (nandc->props->qpic_v2 && qcom_nandc_is_last_cw(ecc, cw))
|
||||
+ if (nandc->props->qpic_version2 && qcom_nandc_is_last_cw(ecc, cw))
|
||||
return nandc_set_read_loc_last(chip, reg_base, cw_offset,
|
||||
read_size, is_last_read_loc);
|
||||
else
|
||||
@@ -792,12 +756,13 @@ static void nandc_set_read_loc(struct na
|
||||
static void set_address(struct qcom_nand_host *host, u16 column, int page)
|
||||
{
|
||||
struct nand_chip *chip = &host->chip;
|
||||
+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
if (chip->options & NAND_BUSWIDTH_16)
|
||||
column >>= 1;
|
||||
|
||||
- nandc_set_reg(chip, NAND_ADDR0, page << 16 | column);
|
||||
- nandc_set_reg(chip, NAND_ADDR1, page >> 16 & 0xff);
|
||||
+ nandc->regs->addr0 = cpu_to_le32(page << 16 | column);
|
||||
+ nandc->regs->addr1 = cpu_to_le32(page >> 16 & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -811,41 +776,43 @@ static void set_address(struct qcom_nand
|
||||
static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, int cw)
|
||||
{
|
||||
struct nand_chip *chip = &host->chip;
|
||||
- u32 cmd, cfg0, cfg1, ecc_bch_cfg;
|
||||
+ __le32 cmd, cfg0, cfg1, ecc_bch_cfg;
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
if (read) {
|
||||
if (host->use_ecc)
|
||||
- cmd = OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE;
|
||||
+ cmd = cpu_to_le32(OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE);
|
||||
else
|
||||
- cmd = OP_PAGE_READ | PAGE_ACC | LAST_PAGE;
|
||||
+ cmd = cpu_to_le32(OP_PAGE_READ | PAGE_ACC | LAST_PAGE);
|
||||
} else {
|
||||
- cmd = OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE;
|
||||
+ cmd = cpu_to_le32(OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE);
|
||||
}
|
||||
|
||||
if (host->use_ecc) {
|
||||
- cfg0 = (host->cfg0 & ~(7U << CW_PER_PAGE)) |
|
||||
- (num_cw - 1) << CW_PER_PAGE;
|
||||
+ cfg0 = cpu_to_le32((host->cfg0 & ~(7U << CW_PER_PAGE)) |
|
||||
+ (num_cw - 1) << CW_PER_PAGE);
|
||||
|
||||
- cfg1 = host->cfg1;
|
||||
- ecc_bch_cfg = host->ecc_bch_cfg;
|
||||
+ cfg1 = cpu_to_le32(host->cfg1);
|
||||
+ ecc_bch_cfg = cpu_to_le32(host->ecc_bch_cfg);
|
||||
} else {
|
||||
- cfg0 = (host->cfg0_raw & ~(7U << CW_PER_PAGE)) |
|
||||
- (num_cw - 1) << CW_PER_PAGE;
|
||||
+ cfg0 = cpu_to_le32((host->cfg0_raw & ~(7U << CW_PER_PAGE)) |
|
||||
+ (num_cw - 1) << CW_PER_PAGE);
|
||||
|
||||
- cfg1 = host->cfg1_raw;
|
||||
- ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE;
|
||||
+ cfg1 = cpu_to_le32(host->cfg1_raw);
|
||||
+ ecc_bch_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE);
|
||||
}
|
||||
|
||||
- nandc_set_reg(chip, NAND_FLASH_CMD, cmd);
|
||||
- nandc_set_reg(chip, NAND_DEV0_CFG0, cfg0);
|
||||
- nandc_set_reg(chip, NAND_DEV0_CFG1, cfg1);
|
||||
- nandc_set_reg(chip, NAND_DEV0_ECC_CFG, ecc_bch_cfg);
|
||||
- if (!nandc->props->qpic_v2)
|
||||
- nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg);
|
||||
- nandc_set_reg(chip, NAND_FLASH_STATUS, host->clrflashstatus);
|
||||
- nandc_set_reg(chip, NAND_READ_STATUS, host->clrreadstatus);
|
||||
- nandc_set_reg(chip, NAND_EXEC_CMD, 1);
|
||||
+ nandc->regs->cmd = cmd;
|
||||
+ nandc->regs->cfg0 = cfg0;
|
||||
+ nandc->regs->cfg1 = cfg1;
|
||||
+ nandc->regs->ecc_bch_cfg = ecc_bch_cfg;
|
||||
+
|
||||
+ if (!nandc->props->qpic_version2)
|
||||
+ nandc->regs->ecc_buf_cfg = cpu_to_le32(host->ecc_buf_cfg);
|
||||
+
|
||||
+ nandc->regs->clrflashstatus = cpu_to_le32(host->clrflashstatus);
|
||||
+ nandc->regs->clrreadstatus = cpu_to_le32(host->clrreadstatus);
|
||||
+ nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
if (read)
|
||||
nandc_set_read_loc(chip, cw, 0, 0, host->use_ecc ?
|
||||
@@ -1121,7 +1088,7 @@ static int read_reg_dma(struct qcom_nand
|
||||
if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1)
|
||||
first = dev_cmd_reg_addr(nandc, first);
|
||||
|
||||
- if (nandc->props->is_bam)
|
||||
+ if (nandc->props->supports_bam)
|
||||
return prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
|
||||
num_regs, flags);
|
||||
|
||||
@@ -1136,25 +1103,16 @@ static int read_reg_dma(struct qcom_nand
|
||||
* write_reg_dma: prepares a descriptor to write a given number of
|
||||
* contiguous registers
|
||||
*
|
||||
+ * @vaddr: contnigeous memory from where register value will
|
||||
+ * be written
|
||||
* @first: offset of the first register in the contiguous block
|
||||
* @num_regs: number of registers to write
|
||||
* @flags: flags to control DMA descriptor preparation
|
||||
*/
|
||||
-static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
|
||||
- int num_regs, unsigned int flags)
|
||||
+static int write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr,
|
||||
+ int first, int num_regs, unsigned int flags)
|
||||
{
|
||||
bool flow_control = false;
|
||||
- struct nandc_regs *regs = nandc->regs;
|
||||
- void *vaddr;
|
||||
-
|
||||
- vaddr = offset_to_nandc_reg(regs, first);
|
||||
-
|
||||
- if (first == NAND_ERASED_CW_DETECT_CFG) {
|
||||
- if (flags & NAND_ERASED_CW_SET)
|
||||
- vaddr = ®s->erased_cw_detect_cfg_set;
|
||||
- else
|
||||
- vaddr = ®s->erased_cw_detect_cfg_clr;
|
||||
- }
|
||||
|
||||
if (first == NAND_EXEC_CMD)
|
||||
flags |= NAND_BAM_NWD;
|
||||
@@ -1165,7 +1123,7 @@ static int write_reg_dma(struct qcom_nan
|
||||
if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD)
|
||||
first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD);
|
||||
|
||||
- if (nandc->props->is_bam)
|
||||
+ if (nandc->props->supports_bam)
|
||||
return prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
|
||||
num_regs, flags);
|
||||
|
||||
@@ -1188,7 +1146,7 @@ static int write_reg_dma(struct qcom_nan
|
||||
static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
|
||||
const u8 *vaddr, int size, unsigned int flags)
|
||||
{
|
||||
- if (nandc->props->is_bam)
|
||||
+ if (nandc->props->supports_bam)
|
||||
return prep_bam_dma_desc_data(nandc, true, vaddr, size, flags);
|
||||
|
||||
return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false);
|
||||
@@ -1206,7 +1164,7 @@ static int read_data_dma(struct qcom_nan
|
||||
static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
|
||||
const u8 *vaddr, int size, unsigned int flags)
|
||||
{
|
||||
- if (nandc->props->is_bam)
|
||||
+ if (nandc->props->supports_bam)
|
||||
return prep_bam_dma_desc_data(nandc, false, vaddr, size, flags);
|
||||
|
||||
return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false);
|
||||
@@ -1220,13 +1178,14 @@ static void config_nand_page_read(struct
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
- write_reg_dma(nandc, NAND_ADDR0, 2, 0);
|
||||
- write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
|
||||
- if (!nandc->props->qpic_v2)
|
||||
- write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0);
|
||||
- write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, 0);
|
||||
- write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1,
|
||||
- NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0);
|
||||
+ if (!nandc->props->qpic_version2)
|
||||
+ write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_clr,
|
||||
+ NAND_ERASED_CW_DETECT_CFG, 1, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_set,
|
||||
+ NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1239,16 +1198,16 @@ config_nand_cw_read(struct nand_chip *ch
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
|
||||
- int reg = NAND_READ_LOCATION_0;
|
||||
+ __le32 *reg = &nandc->regs->read_location0;
|
||||
|
||||
- if (nandc->props->qpic_v2 && qcom_nandc_is_last_cw(ecc, cw))
|
||||
- reg = NAND_READ_LOCATION_LAST_CW_0;
|
||||
+ if (nandc->props->qpic_version2 && qcom_nandc_is_last_cw(ecc, cw))
|
||||
+ reg = &nandc->regs->read_location_last0;
|
||||
|
||||
- if (nandc->props->is_bam)
|
||||
- write_reg_dma(nandc, reg, 4, NAND_BAM_NEXT_SGL);
|
||||
+ if (nandc->props->supports_bam)
|
||||
+ write_reg_dma(nandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
if (use_ecc) {
|
||||
read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0);
|
||||
@@ -1279,10 +1238,10 @@ static void config_nand_page_write(struc
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
- write_reg_dma(nandc, NAND_ADDR0, 2, 0);
|
||||
- write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
|
||||
- if (!nandc->props->qpic_v2)
|
||||
- write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1,
|
||||
+ write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0);
|
||||
+ if (!nandc->props->qpic_version2)
|
||||
+ write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1,
|
||||
NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
@@ -1294,13 +1253,13 @@ static void config_nand_cw_write(struct
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
- write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- write_reg_dma(nandc, NAND_FLASH_STATUS, 1, 0);
|
||||
- write_reg_dma(nandc, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->clrreadstatus, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
/* helpers to submit/free our list of dma descriptors */
|
||||
@@ -1311,7 +1270,7 @@ static int submit_descs(struct qcom_nand
|
||||
struct bam_transaction *bam_txn = nandc->bam_txn;
|
||||
int ret = 0;
|
||||
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) {
|
||||
ret = prepare_bam_async_desc(nandc, nandc->rx_chan, 0);
|
||||
if (ret)
|
||||
@@ -1336,14 +1295,9 @@ static int submit_descs(struct qcom_nand
|
||||
list_for_each_entry(desc, &nandc->desc_list, node)
|
||||
cookie = dmaengine_submit(desc->dma_desc);
|
||||
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
bam_txn->last_cmd_desc->callback = qpic_bam_dma_done;
|
||||
bam_txn->last_cmd_desc->callback_param = bam_txn;
|
||||
- if (bam_txn->last_data_desc) {
|
||||
- bam_txn->last_data_desc->callback = qpic_bam_dma_done;
|
||||
- bam_txn->last_data_desc->callback_param = bam_txn;
|
||||
- bam_txn->wait_second_completion = true;
|
||||
- }
|
||||
|
||||
dma_async_issue_pending(nandc->tx_chan);
|
||||
dma_async_issue_pending(nandc->rx_chan);
|
||||
@@ -1365,7 +1319,7 @@ err_unmap_free_desc:
|
||||
list_for_each_entry_safe(desc, n, &nandc->desc_list, node) {
|
||||
list_del(&desc->node);
|
||||
|
||||
- if (nandc->props->is_bam)
|
||||
+ if (nandc->props->supports_bam)
|
||||
dma_unmap_sg(nandc->dev, desc->bam_sgl,
|
||||
desc->sgl_cnt, desc->dir);
|
||||
else
|
||||
@@ -1382,7 +1336,7 @@ err_unmap_free_desc:
|
||||
static void clear_read_regs(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
nandc->reg_read_pos = 0;
|
||||
- nandc_read_buffer_sync(nandc, false);
|
||||
+ nandc_dev_to_mem(nandc, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1446,7 +1400,7 @@ static int check_flash_errors(struct qco
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
int i;
|
||||
|
||||
- nandc_read_buffer_sync(nandc, true);
|
||||
+ nandc_dev_to_mem(nandc, true);
|
||||
|
||||
for (i = 0; i < cw_cnt; i++) {
|
||||
u32 flash = le32_to_cpu(nandc->reg_read_buf[i]);
|
||||
@@ -1476,7 +1430,7 @@ qcom_nandc_read_cw_raw(struct mtd_info *
|
||||
clear_read_regs(nandc);
|
||||
host->use_ecc = false;
|
||||
|
||||
- if (nandc->props->qpic_v2)
|
||||
+ if (nandc->props->qpic_version2)
|
||||
raw_cw = ecc->steps - 1;
|
||||
|
||||
clear_bam_transaction(nandc);
|
||||
@@ -1497,7 +1451,7 @@ qcom_nandc_read_cw_raw(struct mtd_info *
|
||||
oob_size2 = host->ecc_bytes_hw + host->spare_bytes;
|
||||
}
|
||||
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
nandc_set_read_loc(chip, cw, 0, read_loc, data_size1, 0);
|
||||
read_loc += data_size1;
|
||||
|
||||
@@ -1621,7 +1575,7 @@ static int parse_read_errors(struct qcom
|
||||
u8 *data_buf_start = data_buf, *oob_buf_start = oob_buf;
|
||||
|
||||
buf = (struct read_stats *)nandc->reg_read_buf;
|
||||
- nandc_read_buffer_sync(nandc, true);
|
||||
+ nandc_dev_to_mem(nandc, true);
|
||||
|
||||
for (i = 0; i < ecc->steps; i++, buf++) {
|
||||
u32 flash, buffer, erased_cw;
|
||||
@@ -1734,7 +1688,7 @@ static int read_page_ecc(struct qcom_nan
|
||||
oob_size = host->ecc_bytes_hw + host->spare_bytes;
|
||||
}
|
||||
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
if (data_buf && oob_buf) {
|
||||
nandc_set_read_loc(chip, i, 0, 0, data_size, 0);
|
||||
nandc_set_read_loc(chip, i, 1, data_size,
|
||||
@@ -2455,14 +2409,14 @@ static int qcom_nand_attach_chip(struct
|
||||
|
||||
mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops);
|
||||
/* Free the initially allocated BAM transaction for reading the ONFI params */
|
||||
- if (nandc->props->is_bam)
|
||||
+ if (nandc->props->supports_bam)
|
||||
free_bam_transaction(nandc);
|
||||
|
||||
nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage,
|
||||
cwperpage);
|
||||
|
||||
/* Now allocate the BAM transaction based on updated max_cwperpage */
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
nandc->bam_txn = alloc_bam_transaction(nandc);
|
||||
if (!nandc->bam_txn) {
|
||||
dev_err(nandc->dev,
|
||||
@@ -2522,7 +2476,7 @@ static int qcom_nand_attach_chip(struct
|
||||
| ecc_mode << ECC_MODE
|
||||
| host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH;
|
||||
|
||||
- if (!nandc->props->qpic_v2)
|
||||
+ if (!nandc->props->qpic_version2)
|
||||
host->ecc_buf_cfg = 0x203 << NUM_STEPS;
|
||||
|
||||
host->clrflashstatus = FS_READY_BSY_N;
|
||||
@@ -2556,7 +2510,7 @@ static int qcom_op_cmd_mapping(struct na
|
||||
cmd = OP_FETCH_ID;
|
||||
break;
|
||||
case NAND_CMD_PARAM:
|
||||
- if (nandc->props->qpic_v2)
|
||||
+ if (nandc->props->qpic_version2)
|
||||
cmd = OP_PAGE_READ_ONFI_READ;
|
||||
else
|
||||
cmd = OP_PAGE_READ;
|
||||
@@ -2609,7 +2563,7 @@ static int qcom_parse_instructions(struc
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- q_op->cmd_reg = ret;
|
||||
+ q_op->cmd_reg = cpu_to_le32(ret);
|
||||
q_op->rdy_delay_ns = instr->delay_ns;
|
||||
break;
|
||||
|
||||
@@ -2619,10 +2573,10 @@ static int qcom_parse_instructions(struc
|
||||
addrs = &instr->ctx.addr.addrs[offset];
|
||||
|
||||
for (i = 0; i < min_t(unsigned int, 4, naddrs); i++)
|
||||
- q_op->addr1_reg |= addrs[i] << (i * 8);
|
||||
+ q_op->addr1_reg |= cpu_to_le32(addrs[i] << (i * 8));
|
||||
|
||||
if (naddrs > 4)
|
||||
- q_op->addr2_reg |= addrs[4];
|
||||
+ q_op->addr2_reg |= cpu_to_le32(addrs[4]);
|
||||
|
||||
q_op->rdy_delay_ns = instr->delay_ns;
|
||||
break;
|
||||
@@ -2663,7 +2617,7 @@ static int qcom_wait_rdy_poll(struct nan
|
||||
unsigned long start = jiffies + msecs_to_jiffies(time_ms);
|
||||
u32 flash;
|
||||
|
||||
- nandc_read_buffer_sync(nandc, true);
|
||||
+ nandc_dev_to_mem(nandc, true);
|
||||
|
||||
do {
|
||||
flash = le32_to_cpu(nandc->reg_read_buf[0]);
|
||||
@@ -2706,11 +2660,11 @@ static int qcom_read_status_exec(struct
|
||||
clear_read_regs(nandc);
|
||||
clear_bam_transaction(nandc);
|
||||
|
||||
- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
|
||||
- nandc_set_reg(chip, NAND_EXEC_CMD, 1);
|
||||
+ nandc->regs->cmd = q_op.cmd_reg;
|
||||
+ nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
- write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
ret = submit_descs(nandc);
|
||||
@@ -2719,7 +2673,7 @@ static int qcom_read_status_exec(struct
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
- nandc_read_buffer_sync(nandc, true);
|
||||
+ nandc_dev_to_mem(nandc, true);
|
||||
|
||||
for (i = 0; i < num_cw; i++) {
|
||||
flash_status = le32_to_cpu(nandc->reg_read_buf[i]);
|
||||
@@ -2763,16 +2717,14 @@ static int qcom_read_id_type_exec(struct
|
||||
clear_read_regs(nandc);
|
||||
clear_bam_transaction(nandc);
|
||||
|
||||
- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
|
||||
- nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
|
||||
- nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
|
||||
- nandc_set_reg(chip, NAND_FLASH_CHIP_SELECT,
|
||||
- nandc->props->is_bam ? 0 : DM_EN);
|
||||
+ nandc->regs->cmd = q_op.cmd_reg;
|
||||
+ nandc->regs->addr0 = q_op.addr1_reg;
|
||||
+ nandc->regs->addr1 = q_op.addr2_reg;
|
||||
+ nandc->regs->chip_sel = cpu_to_le32(nandc->props->supports_bam ? 0 : DM_EN);
|
||||
+ nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
- nandc_set_reg(chip, NAND_EXEC_CMD, 1);
|
||||
-
|
||||
- write_reg_dma(nandc, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
@@ -2786,7 +2738,7 @@ static int qcom_read_id_type_exec(struct
|
||||
op_id = q_op.data_instr_idx;
|
||||
len = nand_subop_get_data_len(subop, op_id);
|
||||
|
||||
- nandc_read_buffer_sync(nandc, true);
|
||||
+ nandc_dev_to_mem(nandc, true);
|
||||
memcpy(instr->ctx.data.buf.in, nandc->reg_read_buf, len);
|
||||
|
||||
err_out:
|
||||
@@ -2807,15 +2759,14 @@ static int qcom_misc_cmd_type_exec(struc
|
||||
|
||||
if (q_op.flag == OP_PROGRAM_PAGE) {
|
||||
goto wait_rdy;
|
||||
- } else if (q_op.cmd_reg == OP_BLOCK_ERASE) {
|
||||
- q_op.cmd_reg |= PAGE_ACC | LAST_PAGE;
|
||||
- nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
|
||||
- nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
|
||||
- nandc_set_reg(chip, NAND_DEV0_CFG0,
|
||||
- host->cfg0_raw & ~(7 << CW_PER_PAGE));
|
||||
- nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw);
|
||||
+ } else if (q_op.cmd_reg == cpu_to_le32(OP_BLOCK_ERASE)) {
|
||||
+ q_op.cmd_reg |= cpu_to_le32(PAGE_ACC | LAST_PAGE);
|
||||
+ nandc->regs->addr0 = q_op.addr1_reg;
|
||||
+ nandc->regs->addr1 = q_op.addr2_reg;
|
||||
+ nandc->regs->cfg0 = cpu_to_le32(host->cfg0_raw & ~(7 << CW_PER_PAGE));
|
||||
+ nandc->regs->cfg1 = cpu_to_le32(host->cfg1_raw);
|
||||
instrs = 3;
|
||||
- } else if (q_op.cmd_reg != OP_RESET_DEVICE) {
|
||||
+ } else if (q_op.cmd_reg != cpu_to_le32(OP_RESET_DEVICE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2826,14 +2777,14 @@ static int qcom_misc_cmd_type_exec(struc
|
||||
clear_read_regs(nandc);
|
||||
clear_bam_transaction(nandc);
|
||||
|
||||
- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
|
||||
- nandc_set_reg(chip, NAND_EXEC_CMD, 1);
|
||||
+ nandc->regs->cmd = q_op.cmd_reg;
|
||||
+ nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
- write_reg_dma(nandc, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
|
||||
- if (q_op.cmd_reg == OP_BLOCK_ERASE)
|
||||
- write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
|
||||
+ if (q_op.cmd_reg == cpu_to_le32(OP_BLOCK_ERASE))
|
||||
+ write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
ret = submit_descs(nandc);
|
||||
@@ -2864,7 +2815,7 @@ static int qcom_param_page_type_exec(str
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- q_op.cmd_reg |= PAGE_ACC | LAST_PAGE;
|
||||
+ q_op.cmd_reg |= cpu_to_le32(PAGE_ACC | LAST_PAGE);
|
||||
|
||||
nandc->buf_count = 0;
|
||||
nandc->buf_start = 0;
|
||||
@@ -2872,38 +2823,38 @@ static int qcom_param_page_type_exec(str
|
||||
clear_read_regs(nandc);
|
||||
clear_bam_transaction(nandc);
|
||||
|
||||
- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
|
||||
+ nandc->regs->cmd = q_op.cmd_reg;
|
||||
+ nandc->regs->addr0 = 0;
|
||||
+ nandc->regs->addr1 = 0;
|
||||
+
|
||||
+ nandc->regs->cfg0 = cpu_to_le32(0 << CW_PER_PAGE
|
||||
+ | 512 << UD_SIZE_BYTES
|
||||
+ | 5 << NUM_ADDR_CYCLES
|
||||
+ | 0 << SPARE_SIZE_BYTES);
|
||||
+
|
||||
+ nandc->regs->cfg1 = cpu_to_le32(7 << NAND_RECOVERY_CYCLES
|
||||
+ | 0 << CS_ACTIVE_BSY
|
||||
+ | 17 << BAD_BLOCK_BYTE_NUM
|
||||
+ | 1 << BAD_BLOCK_IN_SPARE_AREA
|
||||
+ | 2 << WR_RD_BSY_GAP
|
||||
+ | 0 << WIDE_FLASH
|
||||
+ | 1 << DEV0_CFG1_ECC_DISABLE);
|
||||
|
||||
- nandc_set_reg(chip, NAND_ADDR0, 0);
|
||||
- nandc_set_reg(chip, NAND_ADDR1, 0);
|
||||
- nandc_set_reg(chip, NAND_DEV0_CFG0, 0 << CW_PER_PAGE
|
||||
- | 512 << UD_SIZE_BYTES
|
||||
- | 5 << NUM_ADDR_CYCLES
|
||||
- | 0 << SPARE_SIZE_BYTES);
|
||||
- nandc_set_reg(chip, NAND_DEV0_CFG1, 7 << NAND_RECOVERY_CYCLES
|
||||
- | 0 << CS_ACTIVE_BSY
|
||||
- | 17 << BAD_BLOCK_BYTE_NUM
|
||||
- | 1 << BAD_BLOCK_IN_SPARE_AREA
|
||||
- | 2 << WR_RD_BSY_GAP
|
||||
- | 0 << WIDE_FLASH
|
||||
- | 1 << DEV0_CFG1_ECC_DISABLE);
|
||||
- if (!nandc->props->qpic_v2)
|
||||
- nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE);
|
||||
+ if (!nandc->props->qpic_version2)
|
||||
+ nandc->regs->ecc_buf_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE);
|
||||
|
||||
/* configure CMD1 and VLD for ONFI param probing in QPIC v1 */
|
||||
- if (!nandc->props->qpic_v2) {
|
||||
- nandc_set_reg(chip, NAND_DEV_CMD_VLD,
|
||||
- (nandc->vld & ~READ_START_VLD));
|
||||
- nandc_set_reg(chip, NAND_DEV_CMD1,
|
||||
- (nandc->cmd1 & ~(0xFF << READ_ADDR))
|
||||
- | NAND_CMD_PARAM << READ_ADDR);
|
||||
+ if (!nandc->props->qpic_version2) {
|
||||
+ nandc->regs->vld = cpu_to_le32((nandc->vld & ~READ_START_VLD));
|
||||
+ nandc->regs->cmd1 = cpu_to_le32((nandc->cmd1 & ~(0xFF << READ_ADDR))
|
||||
+ | NAND_CMD_PARAM << READ_ADDR);
|
||||
}
|
||||
|
||||
- nandc_set_reg(chip, NAND_EXEC_CMD, 1);
|
||||
-
|
||||
- if (!nandc->props->qpic_v2) {
|
||||
- nandc_set_reg(chip, NAND_DEV_CMD1_RESTORE, nandc->cmd1);
|
||||
- nandc_set_reg(chip, NAND_DEV_CMD_VLD_RESTORE, nandc->vld);
|
||||
+ nandc->regs->exec = cpu_to_le32(1);
|
||||
+
|
||||
+ if (!nandc->props->qpic_version2) {
|
||||
+ nandc->regs->orig_cmd1 = cpu_to_le32(nandc->cmd1);
|
||||
+ nandc->regs->orig_vld = cpu_to_le32(nandc->vld);
|
||||
}
|
||||
|
||||
instr = q_op.data_instr;
|
||||
@@ -2912,9 +2863,9 @@ static int qcom_param_page_type_exec(str
|
||||
|
||||
nandc_set_read_loc(chip, 0, 0, 0, len, 1);
|
||||
|
||||
- if (!nandc->props->qpic_v2) {
|
||||
- write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1, 0);
|
||||
- write_reg_dma(nandc, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
|
||||
+ if (!nandc->props->qpic_version2) {
|
||||
+ write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
nandc->buf_count = len;
|
||||
@@ -2926,9 +2877,10 @@ static int qcom_param_page_type_exec(str
|
||||
nandc->buf_count, 0);
|
||||
|
||||
/* restore CMD1 and VLD regs */
|
||||
- if (!nandc->props->qpic_v2) {
|
||||
- write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1, 0);
|
||||
- write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1, NAND_BAM_NEXT_SGL);
|
||||
+ if (!nandc->props->qpic_version2) {
|
||||
+ write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0);
|
||||
+ write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1,
|
||||
+ NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
ret = submit_descs(nandc);
|
||||
@@ -3017,7 +2969,7 @@ static const struct nand_controller_ops
|
||||
|
||||
static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma))
|
||||
dma_unmap_single(nandc->dev, nandc->reg_read_dma,
|
||||
MAX_REG_RD *
|
||||
@@ -3070,7 +3022,7 @@ static int qcom_nandc_alloc(struct qcom_
|
||||
if (!nandc->reg_read_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
nandc->reg_read_dma =
|
||||
dma_map_single(nandc->dev, nandc->reg_read_buf,
|
||||
MAX_REG_RD *
|
||||
@@ -3151,15 +3103,15 @@ static int qcom_nandc_setup(struct qcom_
|
||||
u32 nand_ctrl;
|
||||
|
||||
/* kill onenand */
|
||||
- if (!nandc->props->is_qpic)
|
||||
+ if (!nandc->props->nandc_part_of_qpic)
|
||||
nandc_write(nandc, SFLASHC_BURST_CFG, 0);
|
||||
|
||||
- if (!nandc->props->qpic_v2)
|
||||
+ if (!nandc->props->qpic_version2)
|
||||
nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD),
|
||||
NAND_DEV_CMD_VLD_VAL);
|
||||
|
||||
/* enable ADM or BAM DMA */
|
||||
- if (nandc->props->is_bam) {
|
||||
+ if (nandc->props->supports_bam) {
|
||||
nand_ctrl = nandc_read(nandc, NAND_CTRL);
|
||||
|
||||
/*
|
||||
@@ -3176,7 +3128,7 @@ static int qcom_nandc_setup(struct qcom_
|
||||
}
|
||||
|
||||
/* save the original values of these registers */
|
||||
- if (!nandc->props->qpic_v2) {
|
||||
+ if (!nandc->props->qpic_version2) {
|
||||
nandc->cmd1 = nandc_read(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD1));
|
||||
nandc->vld = NAND_DEV_CMD_VLD_VAL;
|
||||
}
|
||||
@@ -3349,7 +3301,7 @@ static int qcom_nandc_parse_dt(struct pl
|
||||
struct device_node *np = nandc->dev->of_node;
|
||||
int ret;
|
||||
|
||||
- if (!nandc->props->is_bam) {
|
||||
+ if (!nandc->props->supports_bam) {
|
||||
ret = of_property_read_u32(np, "qcom,cmd-crci",
|
||||
&nandc->cmd_crci);
|
||||
if (ret) {
|
||||
@@ -3474,30 +3426,30 @@ static void qcom_nandc_remove(struct pla
|
||||
|
||||
static const struct qcom_nandc_props ipq806x_nandc_props = {
|
||||
.ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT),
|
||||
- .is_bam = false,
|
||||
+ .supports_bam = false,
|
||||
.use_codeword_fixup = true,
|
||||
.dev_cmd_reg_start = 0x0,
|
||||
};
|
||||
|
||||
static const struct qcom_nandc_props ipq4019_nandc_props = {
|
||||
.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
|
||||
- .is_bam = true,
|
||||
- .is_qpic = true,
|
||||
+ .supports_bam = true,
|
||||
+ .nandc_part_of_qpic = true,
|
||||
.dev_cmd_reg_start = 0x0,
|
||||
};
|
||||
|
||||
static const struct qcom_nandc_props ipq8074_nandc_props = {
|
||||
.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
|
||||
- .is_bam = true,
|
||||
- .is_qpic = true,
|
||||
+ .supports_bam = true,
|
||||
+ .nandc_part_of_qpic = true,
|
||||
.dev_cmd_reg_start = 0x7000,
|
||||
};
|
||||
|
||||
static const struct qcom_nandc_props sdx55_nandc_props = {
|
||||
.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
|
||||
- .is_bam = true,
|
||||
- .is_qpic = true,
|
||||
- .qpic_v2 = true,
|
||||
+ .supports_bam = true,
|
||||
+ .nandc_part_of_qpic = true,
|
||||
+ .qpic_version2 = true,
|
||||
.dev_cmd_reg_start = 0x7000,
|
||||
};
|
||||
|
@ -0,0 +1,874 @@
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Sun, 22 Sep 2024 17:03:46 +0530
|
||||
Subject: [PATCH] mtd: rawnand: qcom: Add qcom prefix to common api
|
||||
|
||||
Add qcom prefix to all the api which will be commonly
|
||||
used by spi nand driver and raw nand driver.
|
||||
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
---
|
||||
--- a/drivers/mtd/nand/raw/qcom_nandc.c
|
||||
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
|
||||
@@ -53,7 +53,7 @@
|
||||
#define NAND_READ_LOCATION_LAST_CW_2 0xf48
|
||||
#define NAND_READ_LOCATION_LAST_CW_3 0xf4c
|
||||
|
||||
-/* dummy register offsets, used by write_reg_dma */
|
||||
+/* dummy register offsets, used by qcom_write_reg_dma */
|
||||
#define NAND_DEV_CMD1_RESTORE 0xdead
|
||||
#define NAND_DEV_CMD_VLD_RESTORE 0xbeef
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
|
||||
/*
|
||||
* Flags used in DMA descriptor preparation helper functions
|
||||
- * (i.e. read_reg_dma/write_reg_dma/read_data_dma/write_data_dma)
|
||||
+ * (i.e. qcom_read_reg_dma/qcom_write_reg_dma/qcom_read_data_dma/qcom_write_data_dma)
|
||||
*/
|
||||
/* Don't set the EOT in current tx BAM sgl */
|
||||
#define NAND_BAM_NO_EOT BIT(0)
|
||||
@@ -550,7 +550,7 @@ struct qcom_nandc_props {
|
||||
};
|
||||
|
||||
/* Frees the BAM transaction memory */
|
||||
-static void free_bam_transaction(struct qcom_nand_controller *nandc)
|
||||
+static void qcom_free_bam_transaction(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
struct bam_transaction *bam_txn = nandc->bam_txn;
|
||||
|
||||
@@ -559,7 +559,7 @@ static void free_bam_transaction(struct
|
||||
|
||||
/* Allocates and Initializes the BAM transaction */
|
||||
static struct bam_transaction *
|
||||
-alloc_bam_transaction(struct qcom_nand_controller *nandc)
|
||||
+qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
struct bam_transaction *bam_txn;
|
||||
size_t bam_txn_size;
|
||||
@@ -595,7 +595,7 @@ alloc_bam_transaction(struct qcom_nand_c
|
||||
}
|
||||
|
||||
/* Clears the BAM transaction indexes */
|
||||
-static void clear_bam_transaction(struct qcom_nand_controller *nandc)
|
||||
+static void qcom_clear_bam_transaction(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
struct bam_transaction *bam_txn = nandc->bam_txn;
|
||||
|
||||
@@ -614,7 +614,7 @@ static void clear_bam_transaction(struct
|
||||
}
|
||||
|
||||
/* Callback for DMA descriptor completion */
|
||||
-static void qpic_bam_dma_done(void *data)
|
||||
+static void qcom_qpic_bam_dma_done(void *data)
|
||||
{
|
||||
struct bam_transaction *bam_txn = data;
|
||||
|
||||
@@ -644,7 +644,7 @@ static inline void nandc_write(struct qc
|
||||
iowrite32(val, nandc->base + offset);
|
||||
}
|
||||
|
||||
-static inline void nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu)
|
||||
+static inline void qcom_nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu)
|
||||
{
|
||||
if (!nandc->props->supports_bam)
|
||||
return;
|
||||
@@ -824,9 +824,9 @@ static void update_rw_regs(struct qcom_n
|
||||
* for BAM. This descriptor will be added in the NAND DMA descriptor queue
|
||||
* which will be submitted to DMA engine.
|
||||
*/
|
||||
-static int prepare_bam_async_desc(struct qcom_nand_controller *nandc,
|
||||
- struct dma_chan *chan,
|
||||
- unsigned long flags)
|
||||
+static int qcom_prepare_bam_async_desc(struct qcom_nand_controller *nandc,
|
||||
+ struct dma_chan *chan,
|
||||
+ unsigned long flags)
|
||||
{
|
||||
struct desc_info *desc;
|
||||
struct scatterlist *sgl;
|
||||
@@ -903,9 +903,9 @@ static int prepare_bam_async_desc(struct
|
||||
* NAND_BAM_NEXT_SGL will be used for starting the separate SGL
|
||||
* after the current command element.
|
||||
*/
|
||||
-static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
|
||||
- int reg_off, const void *vaddr,
|
||||
- int size, unsigned int flags)
|
||||
+static int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
|
||||
+ int reg_off, const void *vaddr,
|
||||
+ int size, unsigned int flags)
|
||||
{
|
||||
int bam_ce_size;
|
||||
int i, ret;
|
||||
@@ -943,9 +943,9 @@ static int prep_bam_dma_desc_cmd(struct
|
||||
bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
|
||||
|
||||
if (flags & NAND_BAM_NWD) {
|
||||
- ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
|
||||
- DMA_PREP_FENCE |
|
||||
- DMA_PREP_CMD);
|
||||
+ ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan,
|
||||
+ DMA_PREP_FENCE |
|
||||
+ DMA_PREP_CMD);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -958,9 +958,8 @@ static int prep_bam_dma_desc_cmd(struct
|
||||
* Prepares the data descriptor for BAM DMA which will be used for NAND
|
||||
* data reads and writes.
|
||||
*/
|
||||
-static int prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read,
|
||||
- const void *vaddr,
|
||||
- int size, unsigned int flags)
|
||||
+static int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read,
|
||||
+ const void *vaddr, int size, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
struct bam_transaction *bam_txn = nandc->bam_txn;
|
||||
@@ -979,8 +978,8 @@ static int prep_bam_dma_desc_data(struct
|
||||
* is not set, form the DMA descriptor
|
||||
*/
|
||||
if (!(flags & NAND_BAM_NO_EOT)) {
|
||||
- ret = prepare_bam_async_desc(nandc, nandc->tx_chan,
|
||||
- DMA_PREP_INTERRUPT);
|
||||
+ ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan,
|
||||
+ DMA_PREP_INTERRUPT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -989,9 +988,9 @@ static int prep_bam_dma_desc_data(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
|
||||
- int reg_off, const void *vaddr, int size,
|
||||
- bool flow_control)
|
||||
+static int qcom_prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
|
||||
+ int reg_off, const void *vaddr, int size,
|
||||
+ bool flow_control)
|
||||
{
|
||||
struct desc_info *desc;
|
||||
struct dma_async_tx_descriptor *dma_desc;
|
||||
@@ -1069,15 +1068,15 @@ err:
|
||||
}
|
||||
|
||||
/*
|
||||
- * read_reg_dma: prepares a descriptor to read a given number of
|
||||
+ * qcom_read_reg_dma: prepares a descriptor to read a given number of
|
||||
* contiguous registers to the reg_read_buf pointer
|
||||
*
|
||||
* @first: offset of the first register in the contiguous block
|
||||
* @num_regs: number of registers to read
|
||||
* @flags: flags to control DMA descriptor preparation
|
||||
*/
|
||||
-static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
|
||||
- int num_regs, unsigned int flags)
|
||||
+static int qcom_read_reg_dma(struct qcom_nand_controller *nandc, int first,
|
||||
+ int num_regs, unsigned int flags)
|
||||
{
|
||||
bool flow_control = false;
|
||||
void *vaddr;
|
||||
@@ -1089,18 +1088,18 @@ static int read_reg_dma(struct qcom_nand
|
||||
first = dev_cmd_reg_addr(nandc, first);
|
||||
|
||||
if (nandc->props->supports_bam)
|
||||
- return prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
|
||||
+ return qcom_prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
|
||||
num_regs, flags);
|
||||
|
||||
if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
|
||||
flow_control = true;
|
||||
|
||||
- return prep_adm_dma_desc(nandc, true, first, vaddr,
|
||||
+ return qcom_prep_adm_dma_desc(nandc, true, first, vaddr,
|
||||
num_regs * sizeof(u32), flow_control);
|
||||
}
|
||||
|
||||
/*
|
||||
- * write_reg_dma: prepares a descriptor to write a given number of
|
||||
+ * qcom_write_reg_dma: prepares a descriptor to write a given number of
|
||||
* contiguous registers
|
||||
*
|
||||
* @vaddr: contnigeous memory from where register value will
|
||||
@@ -1109,8 +1108,8 @@ static int read_reg_dma(struct qcom_nand
|
||||
* @num_regs: number of registers to write
|
||||
* @flags: flags to control DMA descriptor preparation
|
||||
*/
|
||||
-static int write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr,
|
||||
- int first, int num_regs, unsigned int flags)
|
||||
+static int qcom_write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr,
|
||||
+ int first, int num_regs, unsigned int flags)
|
||||
{
|
||||
bool flow_control = false;
|
||||
|
||||
@@ -1124,18 +1123,18 @@ static int write_reg_dma(struct qcom_nan
|
||||
first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD);
|
||||
|
||||
if (nandc->props->supports_bam)
|
||||
- return prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
|
||||
+ return qcom_prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
|
||||
num_regs, flags);
|
||||
|
||||
if (first == NAND_FLASH_CMD)
|
||||
flow_control = true;
|
||||
|
||||
- return prep_adm_dma_desc(nandc, false, first, vaddr,
|
||||
+ return qcom_prep_adm_dma_desc(nandc, false, first, vaddr,
|
||||
num_regs * sizeof(u32), flow_control);
|
||||
}
|
||||
|
||||
/*
|
||||
- * read_data_dma: prepares a DMA descriptor to transfer data from the
|
||||
+ * qcom_read_data_dma: prepares a DMA descriptor to transfer data from the
|
||||
* controller's internal buffer to the buffer 'vaddr'
|
||||
*
|
||||
* @reg_off: offset within the controller's data buffer
|
||||
@@ -1143,17 +1142,17 @@ static int write_reg_dma(struct qcom_nan
|
||||
* @size: DMA transaction size in bytes
|
||||
* @flags: flags to control DMA descriptor preparation
|
||||
*/
|
||||
-static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
|
||||
- const u8 *vaddr, int size, unsigned int flags)
|
||||
+static int qcom_read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
|
||||
+ const u8 *vaddr, int size, unsigned int flags)
|
||||
{
|
||||
if (nandc->props->supports_bam)
|
||||
- return prep_bam_dma_desc_data(nandc, true, vaddr, size, flags);
|
||||
+ return qcom_prep_bam_dma_desc_data(nandc, true, vaddr, size, flags);
|
||||
|
||||
- return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false);
|
||||
+ return qcom_prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false);
|
||||
}
|
||||
|
||||
/*
|
||||
- * write_data_dma: prepares a DMA descriptor to transfer data from
|
||||
+ * qcom_write_data_dma: prepares a DMA descriptor to transfer data from
|
||||
* 'vaddr' to the controller's internal buffer
|
||||
*
|
||||
* @reg_off: offset within the controller's data buffer
|
||||
@@ -1161,13 +1160,13 @@ static int read_data_dma(struct qcom_nan
|
||||
* @size: DMA transaction size in bytes
|
||||
* @flags: flags to control DMA descriptor preparation
|
||||
*/
|
||||
-static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
|
||||
- const u8 *vaddr, int size, unsigned int flags)
|
||||
+static int qcom_write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
|
||||
+ const u8 *vaddr, int size, unsigned int flags)
|
||||
{
|
||||
if (nandc->props->supports_bam)
|
||||
- return prep_bam_dma_desc_data(nandc, false, vaddr, size, flags);
|
||||
+ return qcom_prep_bam_dma_desc_data(nandc, false, vaddr, size, flags);
|
||||
|
||||
- return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false);
|
||||
+ return qcom_prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1178,14 +1177,14 @@ static void config_nand_page_read(struct
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0);
|
||||
if (!nandc->props->qpic_version2)
|
||||
- write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_clr,
|
||||
- NAND_ERASED_CW_DETECT_CFG, 1, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_set,
|
||||
- NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_clr,
|
||||
+ NAND_ERASED_CW_DETECT_CFG, 1, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_set,
|
||||
+ NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1204,17 +1203,17 @@ config_nand_cw_read(struct nand_chip *ch
|
||||
reg = &nandc->regs->read_location_last0;
|
||||
|
||||
if (nandc->props->supports_bam)
|
||||
- write_reg_dma(nandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
if (use_ecc) {
|
||||
- read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0);
|
||||
- read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1,
|
||||
- NAND_BAM_NEXT_SGL);
|
||||
+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0);
|
||||
+ qcom_read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1,
|
||||
+ NAND_BAM_NEXT_SGL);
|
||||
} else {
|
||||
- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,11 +1237,11 @@ static void config_nand_page_write(struc
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0);
|
||||
if (!nandc->props->qpic_version2)
|
||||
- write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1,
|
||||
- NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1,
|
||||
+ NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1253,17 +1252,18 @@ static void config_nand_cw_write(struct
|
||||
{
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->clrreadstatus, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->clrreadstatus, NAND_READ_STATUS, 1,
|
||||
+ NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
/* helpers to submit/free our list of dma descriptors */
|
||||
-static int submit_descs(struct qcom_nand_controller *nandc)
|
||||
+static int qcom_submit_descs(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
struct desc_info *desc, *n;
|
||||
dma_cookie_t cookie = 0;
|
||||
@@ -1272,21 +1272,21 @@ static int submit_descs(struct qcom_nand
|
||||
|
||||
if (nandc->props->supports_bam) {
|
||||
if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) {
|
||||
- ret = prepare_bam_async_desc(nandc, nandc->rx_chan, 0);
|
||||
+ ret = qcom_prepare_bam_async_desc(nandc, nandc->rx_chan, 0);
|
||||
if (ret)
|
||||
goto err_unmap_free_desc;
|
||||
}
|
||||
|
||||
if (bam_txn->tx_sgl_pos > bam_txn->tx_sgl_start) {
|
||||
- ret = prepare_bam_async_desc(nandc, nandc->tx_chan,
|
||||
- DMA_PREP_INTERRUPT);
|
||||
+ ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan,
|
||||
+ DMA_PREP_INTERRUPT);
|
||||
if (ret)
|
||||
goto err_unmap_free_desc;
|
||||
}
|
||||
|
||||
if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) {
|
||||
- ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
|
||||
- DMA_PREP_CMD);
|
||||
+ ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan,
|
||||
+ DMA_PREP_CMD);
|
||||
if (ret)
|
||||
goto err_unmap_free_desc;
|
||||
}
|
||||
@@ -1296,7 +1296,7 @@ static int submit_descs(struct qcom_nand
|
||||
cookie = dmaengine_submit(desc->dma_desc);
|
||||
|
||||
if (nandc->props->supports_bam) {
|
||||
- bam_txn->last_cmd_desc->callback = qpic_bam_dma_done;
|
||||
+ bam_txn->last_cmd_desc->callback = qcom_qpic_bam_dma_done;
|
||||
bam_txn->last_cmd_desc->callback_param = bam_txn;
|
||||
|
||||
dma_async_issue_pending(nandc->tx_chan);
|
||||
@@ -1314,7 +1314,7 @@ static int submit_descs(struct qcom_nand
|
||||
err_unmap_free_desc:
|
||||
/*
|
||||
* Unmap the dma sg_list and free the desc allocated by both
|
||||
- * prepare_bam_async_desc() and prep_adm_dma_desc() functions.
|
||||
+ * qcom_prepare_bam_async_desc() and qcom_prep_adm_dma_desc() functions.
|
||||
*/
|
||||
list_for_each_entry_safe(desc, n, &nandc->desc_list, node) {
|
||||
list_del(&desc->node);
|
||||
@@ -1333,10 +1333,10 @@ err_unmap_free_desc:
|
||||
}
|
||||
|
||||
/* reset the register read buffer for next NAND operation */
|
||||
-static void clear_read_regs(struct qcom_nand_controller *nandc)
|
||||
+static void qcom_clear_read_regs(struct qcom_nand_controller *nandc)
|
||||
{
|
||||
nandc->reg_read_pos = 0;
|
||||
- nandc_dev_to_mem(nandc, false);
|
||||
+ qcom_nandc_dev_to_mem(nandc, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1400,7 +1400,7 @@ static int check_flash_errors(struct qco
|
||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||
int i;
|
||||
|
||||
- nandc_dev_to_mem(nandc, true);
|
||||
+ qcom_nandc_dev_to_mem(nandc, true);
|
||||
|
||||
for (i = 0; i < cw_cnt; i++) {
|
||||
u32 flash = le32_to_cpu(nandc->reg_read_buf[i]);
|
||||
@@ -1427,13 +1427,13 @@ qcom_nandc_read_cw_raw(struct mtd_info *
|
||||
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||
nandc->buf_count = 0;
|
||||
nandc->buf_start = 0;
|
||||
- clear_read_regs(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
host->use_ecc = false;
|
||||
|
||||
if (nandc->props->qpic_version2)
|
||||
raw_cw = ecc->steps - 1;
|
||||
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
set_address(host, host->cw_size * cw, page);
|
||||
update_rw_regs(host, 1, true, raw_cw);
|
||||
config_nand_page_read(chip);
|
||||
@@ -1466,18 +1466,18 @@ qcom_nandc_read_cw_raw(struct mtd_info *
|
||||
|
||||
config_nand_cw_read(chip, false, raw_cw);
|
||||
|
||||
- read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
|
||||
+ qcom_read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
|
||||
reg_off += data_size1;
|
||||
|
||||
- read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0);
|
||||
+ qcom_read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0);
|
||||
reg_off += oob_size1;
|
||||
|
||||
- read_data_dma(nandc, reg_off, data_buf + data_size1, data_size2, 0);
|
||||
+ qcom_read_data_dma(nandc, reg_off, data_buf + data_size1, data_size2, 0);
|
||||
reg_off += data_size2;
|
||||
|
||||
- read_data_dma(nandc, reg_off, oob_buf + oob_size1, oob_size2, 0);
|
||||
+ qcom_read_data_dma(nandc, reg_off, oob_buf + oob_size1, oob_size2, 0);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure to read raw cw %d\n", cw);
|
||||
return ret;
|
||||
@@ -1575,7 +1575,7 @@ static int parse_read_errors(struct qcom
|
||||
u8 *data_buf_start = data_buf, *oob_buf_start = oob_buf;
|
||||
|
||||
buf = (struct read_stats *)nandc->reg_read_buf;
|
||||
- nandc_dev_to_mem(nandc, true);
|
||||
+ qcom_nandc_dev_to_mem(nandc, true);
|
||||
|
||||
for (i = 0; i < ecc->steps; i++, buf++) {
|
||||
u32 flash, buffer, erased_cw;
|
||||
@@ -1704,8 +1704,8 @@ static int read_page_ecc(struct qcom_nan
|
||||
config_nand_cw_read(chip, true, i);
|
||||
|
||||
if (data_buf)
|
||||
- read_data_dma(nandc, FLASH_BUF_ACC, data_buf,
|
||||
- data_size, 0);
|
||||
+ qcom_read_data_dma(nandc, FLASH_BUF_ACC, data_buf,
|
||||
+ data_size, 0);
|
||||
|
||||
/*
|
||||
* when ecc is enabled, the controller doesn't read the real
|
||||
@@ -1720,8 +1720,8 @@ static int read_page_ecc(struct qcom_nan
|
||||
for (j = 0; j < host->bbm_size; j++)
|
||||
*oob_buf++ = 0xff;
|
||||
|
||||
- read_data_dma(nandc, FLASH_BUF_ACC + data_size,
|
||||
- oob_buf, oob_size, 0);
|
||||
+ qcom_read_data_dma(nandc, FLASH_BUF_ACC + data_size,
|
||||
+ oob_buf, oob_size, 0);
|
||||
}
|
||||
|
||||
if (data_buf)
|
||||
@@ -1730,7 +1730,7 @@ static int read_page_ecc(struct qcom_nan
|
||||
oob_buf += oob_size;
|
||||
}
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure to read page/oob\n");
|
||||
return ret;
|
||||
@@ -1751,7 +1751,7 @@ static int copy_last_cw(struct qcom_nand
|
||||
int size;
|
||||
int ret;
|
||||
|
||||
- clear_read_regs(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
|
||||
size = host->use_ecc ? host->cw_data : host->cw_size;
|
||||
|
||||
@@ -1763,9 +1763,9 @@ static int copy_last_cw(struct qcom_nand
|
||||
|
||||
config_nand_single_cw_page_read(chip, host->use_ecc, ecc->steps - 1);
|
||||
|
||||
- read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0);
|
||||
+ qcom_read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret)
|
||||
dev_err(nandc->dev, "failed to copy last codeword\n");
|
||||
|
||||
@@ -1851,14 +1851,14 @@ static int qcom_nandc_read_page(struct n
|
||||
nandc->buf_count = 0;
|
||||
nandc->buf_start = 0;
|
||||
host->use_ecc = true;
|
||||
- clear_read_regs(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
set_address(host, 0, page);
|
||||
update_rw_regs(host, ecc->steps, true, 0);
|
||||
|
||||
data_buf = buf;
|
||||
oob_buf = oob_required ? chip->oob_poi : NULL;
|
||||
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
return read_page_ecc(host, data_buf, oob_buf, page);
|
||||
}
|
||||
@@ -1899,8 +1899,8 @@ static int qcom_nandc_read_oob(struct na
|
||||
if (host->nr_boot_partitions)
|
||||
qcom_nandc_codeword_fixup(host, page);
|
||||
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
host->use_ecc = true;
|
||||
set_address(host, 0, page);
|
||||
@@ -1927,8 +1927,8 @@ static int qcom_nandc_write_page(struct
|
||||
set_address(host, 0, page);
|
||||
nandc->buf_count = 0;
|
||||
nandc->buf_start = 0;
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
data_buf = (u8 *)buf;
|
||||
oob_buf = chip->oob_poi;
|
||||
@@ -1949,8 +1949,8 @@ static int qcom_nandc_write_page(struct
|
||||
oob_size = ecc->bytes;
|
||||
}
|
||||
|
||||
- write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size,
|
||||
- i == (ecc->steps - 1) ? NAND_BAM_NO_EOT : 0);
|
||||
+ qcom_write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size,
|
||||
+ i == (ecc->steps - 1) ? NAND_BAM_NO_EOT : 0);
|
||||
|
||||
/*
|
||||
* when ECC is enabled, we don't really need to write anything
|
||||
@@ -1962,8 +1962,8 @@ static int qcom_nandc_write_page(struct
|
||||
if (qcom_nandc_is_last_cw(ecc, i)) {
|
||||
oob_buf += host->bbm_size;
|
||||
|
||||
- write_data_dma(nandc, FLASH_BUF_ACC + data_size,
|
||||
- oob_buf, oob_size, 0);
|
||||
+ qcom_write_data_dma(nandc, FLASH_BUF_ACC + data_size,
|
||||
+ oob_buf, oob_size, 0);
|
||||
}
|
||||
|
||||
config_nand_cw_write(chip);
|
||||
@@ -1972,7 +1972,7 @@ static int qcom_nandc_write_page(struct
|
||||
oob_buf += oob_size;
|
||||
}
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure to write page\n");
|
||||
return ret;
|
||||
@@ -1997,8 +1997,8 @@ static int qcom_nandc_write_page_raw(str
|
||||
qcom_nandc_codeword_fixup(host, page);
|
||||
|
||||
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
data_buf = (u8 *)buf;
|
||||
oob_buf = chip->oob_poi;
|
||||
@@ -2024,28 +2024,28 @@ static int qcom_nandc_write_page_raw(str
|
||||
oob_size2 = host->ecc_bytes_hw + host->spare_bytes;
|
||||
}
|
||||
|
||||
- write_data_dma(nandc, reg_off, data_buf, data_size1,
|
||||
- NAND_BAM_NO_EOT);
|
||||
+ qcom_write_data_dma(nandc, reg_off, data_buf, data_size1,
|
||||
+ NAND_BAM_NO_EOT);
|
||||
reg_off += data_size1;
|
||||
data_buf += data_size1;
|
||||
|
||||
- write_data_dma(nandc, reg_off, oob_buf, oob_size1,
|
||||
- NAND_BAM_NO_EOT);
|
||||
+ qcom_write_data_dma(nandc, reg_off, oob_buf, oob_size1,
|
||||
+ NAND_BAM_NO_EOT);
|
||||
reg_off += oob_size1;
|
||||
oob_buf += oob_size1;
|
||||
|
||||
- write_data_dma(nandc, reg_off, data_buf, data_size2,
|
||||
- NAND_BAM_NO_EOT);
|
||||
+ qcom_write_data_dma(nandc, reg_off, data_buf, data_size2,
|
||||
+ NAND_BAM_NO_EOT);
|
||||
reg_off += data_size2;
|
||||
data_buf += data_size2;
|
||||
|
||||
- write_data_dma(nandc, reg_off, oob_buf, oob_size2, 0);
|
||||
+ qcom_write_data_dma(nandc, reg_off, oob_buf, oob_size2, 0);
|
||||
oob_buf += oob_size2;
|
||||
|
||||
config_nand_cw_write(chip);
|
||||
}
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure to write raw page\n");
|
||||
return ret;
|
||||
@@ -2075,7 +2075,7 @@ static int qcom_nandc_write_oob(struct n
|
||||
qcom_nandc_codeword_fixup(host, page);
|
||||
|
||||
host->use_ecc = true;
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
/* calculate the data and oob size for the last codeword/step */
|
||||
data_size = ecc->size - ((ecc->steps - 1) << 2);
|
||||
@@ -2090,11 +2090,11 @@ static int qcom_nandc_write_oob(struct n
|
||||
update_rw_regs(host, 1, false, 0);
|
||||
|
||||
config_nand_page_write(chip);
|
||||
- write_data_dma(nandc, FLASH_BUF_ACC,
|
||||
- nandc->data_buffer, data_size + oob_size, 0);
|
||||
+ qcom_write_data_dma(nandc, FLASH_BUF_ACC,
|
||||
+ nandc->data_buffer, data_size + oob_size, 0);
|
||||
config_nand_cw_write(chip);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure to write oob\n");
|
||||
return ret;
|
||||
@@ -2121,7 +2121,7 @@ static int qcom_nandc_block_bad(struct n
|
||||
*/
|
||||
host->use_ecc = false;
|
||||
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
ret = copy_last_cw(host, page);
|
||||
if (ret)
|
||||
goto err;
|
||||
@@ -2148,8 +2148,8 @@ static int qcom_nandc_block_markbad(stru
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
int page, ret;
|
||||
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
/*
|
||||
* to mark the BBM as bad, we flash the entire last codeword with 0s.
|
||||
@@ -2166,11 +2166,11 @@ static int qcom_nandc_block_markbad(stru
|
||||
update_rw_regs(host, 1, false, ecc->steps - 1);
|
||||
|
||||
config_nand_page_write(chip);
|
||||
- write_data_dma(nandc, FLASH_BUF_ACC,
|
||||
- nandc->data_buffer, host->cw_size, 0);
|
||||
+ qcom_write_data_dma(nandc, FLASH_BUF_ACC,
|
||||
+ nandc->data_buffer, host->cw_size, 0);
|
||||
config_nand_cw_write(chip);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure to update BBM\n");
|
||||
return ret;
|
||||
@@ -2410,14 +2410,14 @@ static int qcom_nand_attach_chip(struct
|
||||
mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops);
|
||||
/* Free the initially allocated BAM transaction for reading the ONFI params */
|
||||
if (nandc->props->supports_bam)
|
||||
- free_bam_transaction(nandc);
|
||||
+ qcom_free_bam_transaction(nandc);
|
||||
|
||||
nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage,
|
||||
cwperpage);
|
||||
|
||||
/* Now allocate the BAM transaction based on updated max_cwperpage */
|
||||
if (nandc->props->supports_bam) {
|
||||
- nandc->bam_txn = alloc_bam_transaction(nandc);
|
||||
+ nandc->bam_txn = qcom_alloc_bam_transaction(nandc);
|
||||
if (!nandc->bam_txn) {
|
||||
dev_err(nandc->dev,
|
||||
"failed to allocate bam transaction\n");
|
||||
@@ -2617,7 +2617,7 @@ static int qcom_wait_rdy_poll(struct nan
|
||||
unsigned long start = jiffies + msecs_to_jiffies(time_ms);
|
||||
u32 flash;
|
||||
|
||||
- nandc_dev_to_mem(nandc, true);
|
||||
+ qcom_nandc_dev_to_mem(nandc, true);
|
||||
|
||||
do {
|
||||
flash = le32_to_cpu(nandc->reg_read_buf[0]);
|
||||
@@ -2657,23 +2657,23 @@ static int qcom_read_status_exec(struct
|
||||
nandc->buf_start = 0;
|
||||
host->use_ecc = false;
|
||||
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
nandc->regs->cmd = q_op.cmd_reg;
|
||||
nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure in submitting status descriptor\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
- nandc_dev_to_mem(nandc, true);
|
||||
+ qcom_nandc_dev_to_mem(nandc, true);
|
||||
|
||||
for (i = 0; i < num_cw; i++) {
|
||||
flash_status = le32_to_cpu(nandc->reg_read_buf[i]);
|
||||
@@ -2714,8 +2714,8 @@ static int qcom_read_id_type_exec(struct
|
||||
nandc->buf_start = 0;
|
||||
host->use_ecc = false;
|
||||
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
nandc->regs->cmd = q_op.cmd_reg;
|
||||
nandc->regs->addr0 = q_op.addr1_reg;
|
||||
@@ -2723,12 +2723,12 @@ static int qcom_read_id_type_exec(struct
|
||||
nandc->regs->chip_sel = cpu_to_le32(nandc->props->supports_bam ? 0 : DM_EN);
|
||||
nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL);
|
||||
- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure in submitting read id descriptor\n");
|
||||
goto err_out;
|
||||
@@ -2738,7 +2738,7 @@ static int qcom_read_id_type_exec(struct
|
||||
op_id = q_op.data_instr_idx;
|
||||
len = nand_subop_get_data_len(subop, op_id);
|
||||
|
||||
- nandc_dev_to_mem(nandc, true);
|
||||
+ qcom_nandc_dev_to_mem(nandc, true);
|
||||
memcpy(instr->ctx.data.buf.in, nandc->reg_read_buf, len);
|
||||
|
||||
err_out:
|
||||
@@ -2774,20 +2774,20 @@ static int qcom_misc_cmd_type_exec(struc
|
||||
nandc->buf_start = 0;
|
||||
host->use_ecc = false;
|
||||
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
nandc->regs->cmd = q_op.cmd_reg;
|
||||
nandc->regs->exec = cpu_to_le32(1);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
|
||||
if (q_op.cmd_reg == cpu_to_le32(OP_BLOCK_ERASE))
|
||||
- write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure in submitting misc descriptor\n");
|
||||
goto err_out;
|
||||
@@ -2820,8 +2820,8 @@ static int qcom_param_page_type_exec(str
|
||||
nandc->buf_count = 0;
|
||||
nandc->buf_start = 0;
|
||||
host->use_ecc = false;
|
||||
- clear_read_regs(nandc);
|
||||
- clear_bam_transaction(nandc);
|
||||
+ qcom_clear_read_regs(nandc);
|
||||
+ qcom_clear_bam_transaction(nandc);
|
||||
|
||||
nandc->regs->cmd = q_op.cmd_reg;
|
||||
nandc->regs->addr0 = 0;
|
||||
@@ -2864,8 +2864,8 @@ static int qcom_param_page_type_exec(str
|
||||
nandc_set_read_loc(chip, 0, 0, 0, len, 1);
|
||||
|
||||
if (!nandc->props->qpic_version2) {
|
||||
- write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
nandc->buf_count = len;
|
||||
@@ -2873,17 +2873,17 @@ static int qcom_param_page_type_exec(str
|
||||
|
||||
config_nand_single_cw_page_read(chip, false, 0);
|
||||
|
||||
- read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer,
|
||||
- nandc->buf_count, 0);
|
||||
+ qcom_read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer,
|
||||
+ nandc->buf_count, 0);
|
||||
|
||||
/* restore CMD1 and VLD regs */
|
||||
if (!nandc->props->qpic_version2) {
|
||||
- write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0);
|
||||
- write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1,
|
||||
- NAND_BAM_NEXT_SGL);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0);
|
||||
+ qcom_write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1,
|
||||
+ NAND_BAM_NEXT_SGL);
|
||||
}
|
||||
|
||||
- ret = submit_descs(nandc);
|
||||
+ ret = qcom_submit_descs(nandc);
|
||||
if (ret) {
|
||||
dev_err(nandc->dev, "failure in submitting param page descriptor\n");
|
||||
goto err_out;
|
||||
@@ -3067,7 +3067,7 @@ static int qcom_nandc_alloc(struct qcom_
|
||||
* maximum codeword size
|
||||
*/
|
||||
nandc->max_cwperpage = 1;
|
||||
- nandc->bam_txn = alloc_bam_transaction(nandc);
|
||||
+ nandc->bam_txn = qcom_alloc_bam_transaction(nandc);
|
||||
if (!nandc->bam_txn) {
|
||||
dev_err(nandc->dev,
|
||||
"failed to allocate bam transaction\n");
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,191 @@
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Sun, 22 Sep 2024 17:03:48 +0530
|
||||
Subject: [PATCH] mtd: rawnand: qcom: use FIELD_PREP and GENMASK
|
||||
|
||||
Use the bitfield macro FIELD_PREP, and GENMASK to
|
||||
do the shift and mask in one go. This makes the code
|
||||
more readable.
|
||||
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
---
|
||||
--- a/drivers/mtd/nand/raw/qcom_nandc.c
|
||||
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
|
||||
@@ -281,7 +281,7 @@ static void update_rw_regs(struct qcom_n
|
||||
(num_cw - 1) << CW_PER_PAGE);
|
||||
|
||||
cfg1 = cpu_to_le32(host->cfg1_raw);
|
||||
- ecc_bch_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE);
|
||||
+ ecc_bch_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE);
|
||||
}
|
||||
|
||||
nandc->regs->cmd = cmd;
|
||||
@@ -1494,42 +1494,41 @@ static int qcom_nand_attach_chip(struct
|
||||
host->cw_size = host->cw_data + ecc->bytes;
|
||||
bad_block_byte = mtd->writesize - host->cw_size * (cwperpage - 1) + 1;
|
||||
|
||||
- host->cfg0 = (cwperpage - 1) << CW_PER_PAGE
|
||||
- | host->cw_data << UD_SIZE_BYTES
|
||||
- | 0 << DISABLE_STATUS_AFTER_WRITE
|
||||
- | 5 << NUM_ADDR_CYCLES
|
||||
- | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_RS
|
||||
- | 0 << STATUS_BFR_READ
|
||||
- | 1 << SET_RD_MODE_AFTER_STATUS
|
||||
- | host->spare_bytes << SPARE_SIZE_BYTES;
|
||||
-
|
||||
- host->cfg1 = 7 << NAND_RECOVERY_CYCLES
|
||||
- | 0 << CS_ACTIVE_BSY
|
||||
- | bad_block_byte << BAD_BLOCK_BYTE_NUM
|
||||
- | 0 << BAD_BLOCK_IN_SPARE_AREA
|
||||
- | 2 << WR_RD_BSY_GAP
|
||||
- | wide_bus << WIDE_FLASH
|
||||
- | host->bch_enabled << ENABLE_BCH_ECC;
|
||||
-
|
||||
- host->cfg0_raw = (cwperpage - 1) << CW_PER_PAGE
|
||||
- | host->cw_size << UD_SIZE_BYTES
|
||||
- | 5 << NUM_ADDR_CYCLES
|
||||
- | 0 << SPARE_SIZE_BYTES;
|
||||
-
|
||||
- host->cfg1_raw = 7 << NAND_RECOVERY_CYCLES
|
||||
- | 0 << CS_ACTIVE_BSY
|
||||
- | 17 << BAD_BLOCK_BYTE_NUM
|
||||
- | 1 << BAD_BLOCK_IN_SPARE_AREA
|
||||
- | 2 << WR_RD_BSY_GAP
|
||||
- | wide_bus << WIDE_FLASH
|
||||
- | 1 << DEV0_CFG1_ECC_DISABLE;
|
||||
-
|
||||
- host->ecc_bch_cfg = !host->bch_enabled << ECC_CFG_ECC_DISABLE
|
||||
- | 0 << ECC_SW_RESET
|
||||
- | host->cw_data << ECC_NUM_DATA_BYTES
|
||||
- | 1 << ECC_FORCE_CLK_OPEN
|
||||
- | ecc_mode << ECC_MODE
|
||||
- | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH;
|
||||
+ host->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) |
|
||||
+ FIELD_PREP(UD_SIZE_BYTES_MASK, host->cw_data) |
|
||||
+ FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 0) |
|
||||
+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) |
|
||||
+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_RS, host->ecc_bytes_hw) |
|
||||
+ FIELD_PREP(STATUS_BFR_READ, 0) |
|
||||
+ FIELD_PREP(SET_RD_MODE_AFTER_STATUS, 1) |
|
||||
+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, host->spare_bytes);
|
||||
+
|
||||
+ host->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) |
|
||||
+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, bad_block_byte) |
|
||||
+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 0) |
|
||||
+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) |
|
||||
+ FIELD_PREP(WIDE_FLASH, wide_bus) |
|
||||
+ FIELD_PREP(ENABLE_BCH_ECC, host->bch_enabled);
|
||||
+
|
||||
+ host->cfg0_raw = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) |
|
||||
+ FIELD_PREP(UD_SIZE_BYTES_MASK, host->cw_size) |
|
||||
+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) |
|
||||
+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0);
|
||||
+
|
||||
+ host->cfg1_raw = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) |
|
||||
+ FIELD_PREP(CS_ACTIVE_BSY, 0) |
|
||||
+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) |
|
||||
+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) |
|
||||
+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) |
|
||||
+ FIELD_PREP(WIDE_FLASH, wide_bus) |
|
||||
+ FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1);
|
||||
+
|
||||
+ host->ecc_bch_cfg = FIELD_PREP(ECC_CFG_ECC_DISABLE, !host->bch_enabled) |
|
||||
+ FIELD_PREP(ECC_SW_RESET, 0) |
|
||||
+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, host->cw_data) |
|
||||
+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
|
||||
+ FIELD_PREP(ECC_MODE_MASK, ecc_mode) |
|
||||
+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, host->ecc_bytes_hw);
|
||||
|
||||
if (!nandc->props->qpic_version2)
|
||||
host->ecc_buf_cfg = 0x203 << NUM_STEPS;
|
||||
@@ -1882,21 +1881,21 @@ static int qcom_param_page_type_exec(str
|
||||
nandc->regs->addr0 = 0;
|
||||
nandc->regs->addr1 = 0;
|
||||
|
||||
- nandc->regs->cfg0 = cpu_to_le32(0 << CW_PER_PAGE
|
||||
- | 512 << UD_SIZE_BYTES
|
||||
- | 5 << NUM_ADDR_CYCLES
|
||||
- | 0 << SPARE_SIZE_BYTES);
|
||||
-
|
||||
- nandc->regs->cfg1 = cpu_to_le32(7 << NAND_RECOVERY_CYCLES
|
||||
- | 0 << CS_ACTIVE_BSY
|
||||
- | 17 << BAD_BLOCK_BYTE_NUM
|
||||
- | 1 << BAD_BLOCK_IN_SPARE_AREA
|
||||
- | 2 << WR_RD_BSY_GAP
|
||||
- | 0 << WIDE_FLASH
|
||||
- | 1 << DEV0_CFG1_ECC_DISABLE);
|
||||
+ host->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, 0) |
|
||||
+ FIELD_PREP(UD_SIZE_BYTES_MASK, 512) |
|
||||
+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) |
|
||||
+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0);
|
||||
+
|
||||
+ host->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) |
|
||||
+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) |
|
||||
+ FIELD_PREP(CS_ACTIVE_BSY, 0) |
|
||||
+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) |
|
||||
+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) |
|
||||
+ FIELD_PREP(WIDE_FLASH, 0) |
|
||||
+ FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1);
|
||||
|
||||
if (!nandc->props->qpic_version2)
|
||||
- nandc->regs->ecc_buf_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE);
|
||||
+ nandc->regs->ecc_buf_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE);
|
||||
|
||||
/* configure CMD1 and VLD for ONFI param probing in QPIC v1 */
|
||||
if (!nandc->props->qpic_version2) {
|
||||
--- a/include/linux/mtd/nand-qpic-common.h
|
||||
+++ b/include/linux/mtd/nand-qpic-common.h
|
||||
@@ -70,35 +70,42 @@
|
||||
#define BS_CORRECTABLE_ERR_MSK 0x1f
|
||||
|
||||
/* NAND_DEVn_CFG0 bits */
|
||||
-#define DISABLE_STATUS_AFTER_WRITE 4
|
||||
+#define DISABLE_STATUS_AFTER_WRITE BIT(4)
|
||||
#define CW_PER_PAGE 6
|
||||
+#define CW_PER_PAGE_MASK GENMASK(8, 6)
|
||||
#define UD_SIZE_BYTES 9
|
||||
#define UD_SIZE_BYTES_MASK GENMASK(18, 9)
|
||||
-#define ECC_PARITY_SIZE_BYTES_RS 19
|
||||
+#define ECC_PARITY_SIZE_BYTES_RS GENMASK(22, 19)
|
||||
#define SPARE_SIZE_BYTES 23
|
||||
#define SPARE_SIZE_BYTES_MASK GENMASK(26, 23)
|
||||
#define NUM_ADDR_CYCLES 27
|
||||
-#define STATUS_BFR_READ 30
|
||||
-#define SET_RD_MODE_AFTER_STATUS 31
|
||||
+#define NUM_ADDR_CYCLES_MASK GENMASK(29, 27)
|
||||
+#define STATUS_BFR_READ BIT(30)
|
||||
+#define SET_RD_MODE_AFTER_STATUS BIT(31)
|
||||
|
||||
/* NAND_DEVn_CFG0 bits */
|
||||
-#define DEV0_CFG1_ECC_DISABLE 0
|
||||
-#define WIDE_FLASH 1
|
||||
+#define DEV0_CFG1_ECC_DISABLE BIT(0)
|
||||
+#define WIDE_FLASH BIT(1)
|
||||
#define NAND_RECOVERY_CYCLES 2
|
||||
-#define CS_ACTIVE_BSY 5
|
||||
+#define NAND_RECOVERY_CYCLES_MASK GENMASK(4, 2)
|
||||
+#define CS_ACTIVE_BSY BIT(5)
|
||||
#define BAD_BLOCK_BYTE_NUM 6
|
||||
-#define BAD_BLOCK_IN_SPARE_AREA 16
|
||||
+#define BAD_BLOCK_BYTE_NUM_MASK GENMASK(15, 6)
|
||||
+#define BAD_BLOCK_IN_SPARE_AREA BIT(16)
|
||||
#define WR_RD_BSY_GAP 17
|
||||
-#define ENABLE_BCH_ECC 27
|
||||
+#define WR_RD_BSY_GAP_MASK GENMASK(22, 17)
|
||||
+#define ENABLE_BCH_ECC BIT(27)
|
||||
|
||||
/* NAND_DEV0_ECC_CFG bits */
|
||||
-#define ECC_CFG_ECC_DISABLE 0
|
||||
-#define ECC_SW_RESET 1
|
||||
+#define ECC_CFG_ECC_DISABLE BIT(0)
|
||||
+#define ECC_SW_RESET BIT(1)
|
||||
#define ECC_MODE 4
|
||||
+#define ECC_MODE_MASK GENMASK(5, 4)
|
||||
#define ECC_PARITY_SIZE_BYTES_BCH 8
|
||||
+#define ECC_PARITY_SIZE_BYTES_BCH_MASK GENMASK(12, 8)
|
||||
#define ECC_NUM_DATA_BYTES 16
|
||||
#define ECC_NUM_DATA_BYTES_MASK GENMASK(25, 16)
|
||||
-#define ECC_FORCE_CLK_OPEN 30
|
||||
+#define ECC_FORCE_CLK_OPEN BIT(30)
|
||||
|
||||
/* NAND_DEV_CMD1 bits */
|
||||
#define READ_ADDR 0
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Subject: [PATCH] spi: spi-qpic: fix compilation issues
|
||||
Date: Sun, 06 Oct 2024 16:34:11 +0400
|
||||
|
||||
The compiler will throw a warning when freeing a variable, setting values
|
||||
of u32 to zero using memset, when the number of bytes is greater than the
|
||||
size of the variable passed, so let's set each of the 8 variables
|
||||
contiguously set in memory as part of the structure to zero.
|
||||
|
||||
The output type of the remove function is void while it should return an
|
||||
integer indicating success (0) or a negative number as an error. So let's
|
||||
switch to use the new .remove_new function which expects nothing to be
|
||||
returned
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/drivers/mtd/nand/qpic_common.c
|
||||
+++ b/drivers/mtd/nand/qpic_common.c
|
||||
@@ -82,7 +82,14 @@ void qcom_clear_bam_transaction(struct q
|
||||
if (!nandc->props->supports_bam)
|
||||
return;
|
||||
|
||||
- memset(&bam_txn->bam_ce_pos, 0, sizeof(u32) * 8);
|
||||
+ bam_txn->bam_ce_pos = 0;
|
||||
+ bam_txn->bam_ce_start = 0;
|
||||
+ bam_txn->cmd_sgl_pos = 0;
|
||||
+ bam_txn->cmd_sgl_start = 0;
|
||||
+ bam_txn->tx_sgl_pos = 0;
|
||||
+ bam_txn->tx_sgl_start = 0;
|
||||
+ bam_txn->rx_sgl_pos = 0;
|
||||
+ bam_txn->rx_sgl_start = 0;
|
||||
bam_txn->last_data_desc = NULL;
|
||||
|
||||
sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage *
|
||||
--- a/drivers/spi/spi-qpic-snand.c
|
||||
+++ b/drivers/spi/spi-qpic-snand.c
|
||||
@@ -1624,7 +1624,7 @@ static struct platform_driver qcom_spi_d
|
||||
.of_match_table = qcom_snandc_of_match,
|
||||
},
|
||||
.probe = qcom_spi_probe,
|
||||
- .remove = qcom_spi_remove,
|
||||
+ .remove_new = qcom_spi_remove,
|
||||
};
|
||||
module_platform_driver(qcom_spi_driver);
|
||||
|
@ -0,0 +1,53 @@
|
||||
From 396886e8644d5b601126b97e0b36c40c5fb5cecf Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH 1/2] spi: spi-qpic-snand: support BCH8
|
||||
|
||||
Add BCH8 error-correcting code support for QPIC SPI Nand controller.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/spi/spi-qpic-snand.c | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-qpic-snand.c
|
||||
+++ b/drivers/spi/spi-qpic-snand.c
|
||||
@@ -252,6 +252,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
|
||||
struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
|
||||
struct mtd_info *mtd = nanddev_to_mtd(nand);
|
||||
int cwperpage, bad_block_byte;
|
||||
+ int ecc_mode;
|
||||
struct qpic_ecc *ecc_cfg;
|
||||
|
||||
cwperpage = mtd->writesize / NANDC_STEP_SIZE;
|
||||
@@ -270,14 +271,17 @@ static int qcom_spi_ecc_init_ctx_pipelin
|
||||
nand->ecc.ctx.priv = ecc_cfg;
|
||||
snandc->qspi->mtd = mtd;
|
||||
|
||||
- ecc_cfg->ecc_bytes_hw = 7;
|
||||
- ecc_cfg->spare_bytes = 4;
|
||||
+ /* BCH8 or BCH4 */
|
||||
+ ecc_mode = mtd->oobsize > 64 ? 1 : 0;
|
||||
+
|
||||
+ ecc_cfg->ecc_bytes_hw = ecc_mode ? 13 : 7;
|
||||
+ ecc_cfg->spare_bytes = ecc_mode ? 2 : 4;
|
||||
ecc_cfg->bbm_size = 1;
|
||||
ecc_cfg->bch_enabled = true;
|
||||
ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
|
||||
|
||||
ecc_cfg->steps = 4;
|
||||
- ecc_cfg->strength = 4;
|
||||
+ ecc_cfg->strength = ecc_mode ? 8 : 4;
|
||||
ecc_cfg->step_size = 512;
|
||||
ecc_cfg->cw_data = 516;
|
||||
ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes;
|
||||
@@ -319,7 +323,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
|
||||
FIELD_PREP(ECC_SW_RESET, 0) |
|
||||
FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
|
||||
FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
|
||||
- FIELD_PREP(ECC_MODE_MASK, 0) |
|
||||
+ FIELD_PREP(ECC_MODE_MASK, ecc_mode) |
|
||||
FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw);
|
||||
|
||||
ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS;
|
@ -0,0 +1,25 @@
|
||||
From 3d550dc3eb4eaa2fe1d0668ed67e835c91487d61 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH 2/2] mtd: spinand: qpic only support max 4 bytes ID
|
||||
|
||||
The QPIC SPI NAND controller supports a max of 4 bytes of device ID.
|
||||
As such, set a maximum of 4 bytes.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/core.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -1087,7 +1087,7 @@ int spinand_match_and_init(struct spinan
|
||||
if (rdid_method != info->devid.method)
|
||||
continue;
|
||||
|
||||
- if (memcmp(id + 1, info->devid.id, info->devid.len))
|
||||
+ if (memcmp(id + 1, info->devid.id, min(3, info->devid.len)))
|
||||
continue;
|
||||
|
||||
nand->memorg = table[i].memorg;
|
@ -0,0 +1,52 @@
|
||||
From c2019f64539dd24e6e0da3cea2219d6f9e6b03e4 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add SPI nand node
|
||||
|
||||
Add SPI NAND support for IPQ5018 SoC.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 40 +++++++++++++++++++++++++++
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -461,6 +461,36 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ qpic_bam: dma@7984000 {
|
||||
+ compatible = "qcom,bam-v1.7.0";
|
||||
+ reg = <0x07984000 0x1c000>;
|
||||
+ interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_QPIC_AHB_CLK>;
|
||||
+ clock-names = "bam_clk";
|
||||
+ #dma-cells = <1>;
|
||||
+ qcom,ee = <0>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ qpic_nand: qpic-nand@79b0000 {
|
||||
+ compatible = "qcom,spi-qpic-snand";
|
||||
+ reg = <0x079b0000 0x10000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ clocks = <&gcc GCC_QPIC_CLK>,
|
||||
+ <&gcc GCC_QPIC_AHB_CLK>,
|
||||
+ <&gcc GCC_QPIC_IO_MACRO_CLK>;
|
||||
+ clock-names = "core", "aon", "iom";
|
||||
+
|
||||
+ dmas = <&qpic_bam 0>,
|
||||
+ <&qpic_bam 1>,
|
||||
+ <&qpic_bam 2>,
|
||||
+ <&qpic_bam 3>;
|
||||
+ dma-names = "tx", "rx", "cmd", "status";
|
||||
+
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
usb: usb@8af8800 {
|
||||
compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
|
||||
reg = <0x08af8800 0x400>;
|
@ -0,0 +1,23 @@
|
||||
From b76a7649402d3eb1245ab463832133fc7efda194 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add more nand compatible for
|
||||
uboot to fix partitions
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -473,7 +473,7 @@
|
||||
};
|
||||
|
||||
qpic_nand: qpic-nand@79b0000 {
|
||||
- compatible = "qcom,spi-qpic-snand";
|
||||
+ compatible = "qcom,spi-qpic-snand", "qcom,ebi2-nandc-bam-v2.1.1";
|
||||
reg = <0x079b0000 0x10000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
@ -0,0 +1,113 @@
|
||||
From 7b89dbf5c7dcd8a9c131721e93c1292e5993968b Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Tue, 20 Aug 2024 22:02:42 +0800
|
||||
Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL clock controller
|
||||
for IPQ SoC
|
||||
|
||||
The CMN PLL controller provides clocks to networking hardware blocks
|
||||
on Qualcomm IPQ9574 SoC. It receives input clock from the on-chip Wi-Fi,
|
||||
and produces output clocks at fixed rates. These output rates are
|
||||
predetermined, and are unrelated to the input clock rate. The output
|
||||
clocks are supplied to the Ethernet hardware such as PPE (packet
|
||||
process engine) and the externally connected switch or PHY device.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
---
|
||||
.../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 70 +++++++++++++++++++
|
||||
include/dt-bindings/clock/qcom,ipq-cmn-pll.h | 15 ++++
|
||||
2 files changed, 85 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
|
||||
create mode 100644 include/dt-bindings/clock/qcom,ipq-cmn-pll.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
|
||||
@@ -0,0 +1,70 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-cmn-pll.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Qualcomm CMN PLL Clock Controller on IPQ SoC
|
||||
+
|
||||
+maintainers:
|
||||
+ - Bjorn Andersson <andersson@kernel.org>
|
||||
+ - Luo Jie <quic_luoj@quicinc.com>
|
||||
+
|
||||
+description:
|
||||
+ The CMN PLL clock controller expects a reference input clock.
|
||||
+ This reference clock is from the on-board Wi-Fi. The CMN PLL
|
||||
+ supplies a number of fixed rate output clocks to the Ethernet
|
||||
+ devices including PPE (packet process engine) and the connected
|
||||
+ switch or PHY device.
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - qcom,ipq9574-cmn-pll
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ clocks:
|
||||
+ items:
|
||||
+ - description: The reference clock. The supported clock rates include
|
||||
+ 25000000, 31250000, 40000000, 48000000, 50000000 and 96000000 HZ.
|
||||
+ - description: The AHB clock
|
||||
+ - description: The SYS clock
|
||||
+ description:
|
||||
+ The reference clock is the source clock of CMN PLL, which is from the
|
||||
+ Wi-Fi. The AHB and SYS clocks must be enabled to access CMN PLL
|
||||
+ clock registers.
|
||||
+
|
||||
+ clock-names:
|
||||
+ items:
|
||||
+ - const: ref
|
||||
+ - const: ahb
|
||||
+ - const: sys
|
||||
+
|
||||
+ "#clock-cells":
|
||||
+ const: 1
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - clocks
|
||||
+ - clock-names
|
||||
+ - "#clock-cells"
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/clock/qcom,ipq9574-gcc.h>
|
||||
+
|
||||
+ clock-controller@9b000 {
|
||||
+ compatible = "qcom,ipq9574-cmn-pll";
|
||||
+ reg = <0x0009b000 0x800>;
|
||||
+ clocks = <&cmn_pll_ref_clk>,
|
||||
+ <&gcc GCC_CMN_12GPLL_AHB_CLK>,
|
||||
+ <&gcc GCC_CMN_12GPLL_SYS_CLK>;
|
||||
+ clock-names = "ref", "ahb", "sys";
|
||||
+ #clock-cells = <1>;
|
||||
+ };
|
||||
+...
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/clock/qcom,ipq-cmn-pll.h
|
||||
@@ -0,0 +1,15 @@
|
||||
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
+/*
|
||||
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H
|
||||
+#define _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H
|
||||
+
|
||||
+/* The output clocks from CMN PLL of IPQ9574. */
|
||||
+#define PPE_353MHZ_CLK 0
|
||||
+#define ETH0_50MHZ_CLK 1
|
||||
+#define ETH1_50MHZ_CLK 2
|
||||
+#define ETH2_50MHZ_CLK 3
|
||||
+#define ETH_25MHZ_CLK 4
|
||||
+#endif
|
@ -0,0 +1,288 @@
|
||||
From a7e8397e2db6133e3435054a3f312dbd9cab05ed Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Tue, 20 Aug 2024 22:02:43 +0800
|
||||
Subject: [PATCH] clk: qcom: Add CMN PLL clock controller driver for IPQ
|
||||
SoC
|
||||
|
||||
The CMN PLL clock controller supplies clocks to the hardware
|
||||
blocks that together make up the Ethernet function on Qualcomm
|
||||
IPQ SoCs. The driver is initially supported for IPQ9574 SoC.
|
||||
|
||||
The CMN PLL clock controller expects a reference input clock
|
||||
from the on-board Wi-Fi block acting as clock source. The input
|
||||
reference clock needs to be configured to one of the supported
|
||||
clock rates.
|
||||
|
||||
The controller supplies a number of fixed-rate output clocks.
|
||||
For the IPQ9574, there is one output clock of 353 MHZ to PPE
|
||||
(Packet Process Engine) hardware block, three 50 MHZ output
|
||||
clocks and an additional 25 MHZ output clock supplied to the
|
||||
connected Ethernet devices.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
drivers/clk/qcom/Kconfig | 10 ++
|
||||
drivers/clk/qcom/Makefile | 1 +
|
||||
drivers/clk/qcom/clk-ipq-cmn-pll.c | 227 +++++++++++++++++++++++++++++
|
||||
3 files changed, 238 insertions(+)
|
||||
create mode 100644 drivers/clk/qcom/clk-ipq-cmn-pll.c
|
||||
|
||||
--- a/drivers/clk/qcom/Kconfig
|
||||
+++ b/drivers/clk/qcom/Kconfig
|
||||
@@ -139,6 +139,16 @@ config IPQ_APSS_6018
|
||||
Say Y if you want to support CPU frequency scaling on
|
||||
ipq based devices.
|
||||
|
||||
+config IPQ_CMN_PLL
|
||||
+ tristate "IPQ CMN PLL Clock Controller"
|
||||
+ depends on IPQ_GCC_9574
|
||||
+ help
|
||||
+ Support for CMN PLL clock controller on IPQ platform. The
|
||||
+ CMN PLL feeds the reference clocks to the Ethernet devices
|
||||
+ based on IPQ SoC.
|
||||
+ Say Y or M if you want to support CMN PLL clock on the IPQ
|
||||
+ based devices.
|
||||
+
|
||||
config IPQ_GCC_4019
|
||||
tristate "IPQ4019 Global Clock Controller"
|
||||
help
|
||||
--- a/drivers/clk/qcom/Makefile
|
||||
+++ b/drivers/clk/qcom/Makefile
|
||||
@@ -23,6 +23,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8
|
||||
obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
|
||||
obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
|
||||
obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
|
||||
+obj-$(CONFIG_IPQ_CMN_PLL) += clk-ipq-cmn-pll.o
|
||||
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
|
||||
obj-$(CONFIG_IPQ_GCC_5018) += gcc-ipq5018.o
|
||||
obj-$(CONFIG_IPQ_GCC_5332) += gcc-ipq5332.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/clk/qcom/clk-ipq-cmn-pll.c
|
||||
@@ -0,0 +1,227 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * CMN PLL block expects the reference clock from on-board Wi-Fi block, and
|
||||
+ * supplies fixed rate clocks as output to the Ethernet hardware blocks.
|
||||
+ * The Ethernet related blocks include PPE (packet process engine) and the
|
||||
+ * external connected PHY (or switch) chip receiving clocks from the CMN PLL.
|
||||
+ *
|
||||
+ * On the IPQ9574 SoC, There are three clocks with 50 MHZ, one clock with
|
||||
+ * 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch),
|
||||
+ * and one clock with 353 MHZ to PPE.
|
||||
+ *
|
||||
+ * +---------+
|
||||
+ * | GCC |
|
||||
+ * +--+---+--+
|
||||
+ * AHB CLK| |SYS CLK
|
||||
+ * V V
|
||||
+ * +-------+---+------+
|
||||
+ * | +-------------> eth0-50mhz
|
||||
+ * REF CLK | IPQ9574 |
|
||||
+ * -------->+ +-------------> eth1-50mhz
|
||||
+ * | CMN PLL block |
|
||||
+ * | +-------------> eth2-50mhz
|
||||
+ * | |
|
||||
+ * +---------+--------+-------------> eth-25mhz
|
||||
+ * |
|
||||
+ * V
|
||||
+ * ppe-353mhz
|
||||
+ */
|
||||
+
|
||||
+#include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
|
||||
+#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8)
|
||||
+
|
||||
+#define CMN_PLL_REFCLK_CONFIG 0x784
|
||||
+#define CMN_PLL_REFCLK_EXTERNAL BIT(9)
|
||||
+#define CMN_PLL_REFCLK_DIV GENMASK(8, 4)
|
||||
+#define CMN_PLL_REFCLK_INDEX GENMASK(3, 0)
|
||||
+
|
||||
+#define CMN_PLL_POWER_ON_AND_RESET 0x780
|
||||
+#define CMN_ANA_EN_SW_RSTN BIT(6)
|
||||
+
|
||||
+/**
|
||||
+ * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information
|
||||
+ * @id: Clock specifier to be supplied
|
||||
+ * @name: Clock name to be registered
|
||||
+ * @rate: Clock rate
|
||||
+ */
|
||||
+struct cmn_pll_fixed_output_clk {
|
||||
+ unsigned int id;
|
||||
+ const char *name;
|
||||
+ const unsigned long rate;
|
||||
+};
|
||||
+
|
||||
+#define CLK_PLL_OUTPUT(_id, _name, _rate) { \
|
||||
+ .id = _id, \
|
||||
+ .name = _name, \
|
||||
+ .rate = _rate, \
|
||||
+}
|
||||
+
|
||||
+static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = {
|
||||
+ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL),
|
||||
+ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
|
||||
+ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
|
||||
+ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
|
||||
+ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
|
||||
+};
|
||||
+
|
||||
+static int ipq_cmn_pll_config(struct device *dev, unsigned long parent_rate)
|
||||
+{
|
||||
+ void __iomem *base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ base = devm_of_iomap(dev, dev->of_node, 0, NULL);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ val = readl(base + CMN_PLL_REFCLK_CONFIG);
|
||||
+ val &= ~(CMN_PLL_REFCLK_EXTERNAL | CMN_PLL_REFCLK_INDEX);
|
||||
+
|
||||
+ /*
|
||||
+ * Configure the reference input clock selection as per the given rate.
|
||||
+ * The output clock rates are always of fixed value.
|
||||
+ */
|
||||
+ switch (parent_rate) {
|
||||
+ case 25000000:
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 3);
|
||||
+ break;
|
||||
+ case 31250000:
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 4);
|
||||
+ break;
|
||||
+ case 40000000:
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 6);
|
||||
+ break;
|
||||
+ case 48000000:
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 7);
|
||||
+ break;
|
||||
+ case 50000000:
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 8);
|
||||
+ break;
|
||||
+ case 96000000:
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 7);
|
||||
+ val &= ~CMN_PLL_REFCLK_DIV;
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_DIV, 2);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ writel(val, base + CMN_PLL_REFCLK_CONFIG);
|
||||
+
|
||||
+ /* Update the source clock rate selection. Only 96 MHZ uses 0. */
|
||||
+ val = readl(base + CMN_PLL_REFCLK_SRC_SELECTION);
|
||||
+ val &= ~CMN_PLL_REFCLK_SRC_DIV;
|
||||
+ if (parent_rate != 96000000)
|
||||
+ val |= FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 1);
|
||||
+
|
||||
+ writel(val, base + CMN_PLL_REFCLK_SRC_SELECTION);
|
||||
+
|
||||
+ /*
|
||||
+ * Reset the CMN PLL block by asserting/de-asserting for 100 ms
|
||||
+ * each, to ensure the updated configurations take effect.
|
||||
+ */
|
||||
+ val = readl(base + CMN_PLL_POWER_ON_AND_RESET);
|
||||
+ val &= ~CMN_ANA_EN_SW_RSTN;
|
||||
+ writel(val, base);
|
||||
+ msleep(100);
|
||||
+
|
||||
+ val |= CMN_ANA_EN_SW_RSTN;
|
||||
+ writel(val, base + CMN_PLL_POWER_ON_AND_RESET);
|
||||
+ msleep(100);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq_cmn_pll_clk_register(struct device *dev, const char *parent)
|
||||
+{
|
||||
+ const struct cmn_pll_fixed_output_clk *fixed_clk;
|
||||
+ struct clk_hw_onecell_data *data;
|
||||
+ unsigned int num_clks;
|
||||
+ struct clk_hw *hw;
|
||||
+ int i;
|
||||
+
|
||||
+ num_clks = ARRAY_SIZE(ipq9574_output_clks);
|
||||
+ fixed_clk = ipq9574_output_clks;
|
||||
+
|
||||
+ data = devm_kzalloc(dev, struct_size(data, hws, num_clks), GFP_KERNEL);
|
||||
+ if (!data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ for (i = 0; i < num_clks; i++) {
|
||||
+ hw = devm_clk_hw_register_fixed_rate(dev, fixed_clk[i].name,
|
||||
+ parent, 0,
|
||||
+ fixed_clk[i].rate);
|
||||
+ if (IS_ERR(hw))
|
||||
+ return PTR_ERR(hw);
|
||||
+
|
||||
+ data->hws[fixed_clk[i].id] = hw;
|
||||
+ }
|
||||
+ data->num = num_clks;
|
||||
+
|
||||
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
|
||||
+}
|
||||
+
|
||||
+static int ipq_cmn_pll_clk_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct clk *clk;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * To access the CMN PLL registers, the GCC AHB & SYSY clocks
|
||||
+ * for CMN PLL block need to be enabled.
|
||||
+ */
|
||||
+ clk = devm_clk_get_enabled(dev, "ahb");
|
||||
+ if (IS_ERR(clk))
|
||||
+ return dev_err_probe(dev, PTR_ERR(clk),
|
||||
+ "Enable AHB clock failed\n");
|
||||
+
|
||||
+ clk = devm_clk_get_enabled(dev, "sys");
|
||||
+ if (IS_ERR(clk))
|
||||
+ return dev_err_probe(dev, PTR_ERR(clk),
|
||||
+ "Enable SYS clock failed\n");
|
||||
+
|
||||
+ clk = devm_clk_get(dev, "ref");
|
||||
+ if (IS_ERR(clk))
|
||||
+ return dev_err_probe(dev, PTR_ERR(clk),
|
||||
+ "Get reference clock failed\n");
|
||||
+
|
||||
+ /* Configure CMN PLL to apply the reference clock. */
|
||||
+ ret = ipq_cmn_pll_config(dev, clk_get_rate(clk));
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Configure CMN PLL failed\n");
|
||||
+
|
||||
+ return ipq_cmn_pll_clk_register(dev, __clk_get_name(clk));
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id ipq_cmn_pll_clk_ids[] = {
|
||||
+ { .compatible = "qcom,ipq9574-cmn-pll", },
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver ipq_cmn_pll_clk_driver = {
|
||||
+ .probe = ipq_cmn_pll_clk_probe,
|
||||
+ .driver = {
|
||||
+ .name = "ipq_cmn_pll",
|
||||
+ .of_match_table = ipq_cmn_pll_clk_ids,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(ipq_cmn_pll_clk_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,78 @@
|
||||
From a28797563b8c97c9abced82e0cf89302fcd2bf37 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH 1/2] clk: qcom: cmn-pll: add IPQ5018 support
|
||||
|
||||
Add support for IPQ5018 (and removing dependency on the IPQ9574 platform).
|
||||
The common network block in IPQ5018 must be enabled first through a
|
||||
specific register at a fixed offset in the TCSR area, set in the DTS.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/clk/qcom/Kconfig | 1 -
|
||||
drivers/clk/qcom/clk-ipq-cmn-pll.c | 29 +++++++++++++++++++++++++++++
|
||||
2 files changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/clk/qcom/Kconfig
|
||||
+++ b/drivers/clk/qcom/Kconfig
|
||||
@@ -141,7 +141,6 @@ config IPQ_APSS_6018
|
||||
|
||||
config IPQ_CMN_PLL
|
||||
tristate "IPQ CMN PLL Clock Controller"
|
||||
- depends on IPQ_GCC_9574
|
||||
help
|
||||
Support for CMN PLL clock controller on IPQ platform. The
|
||||
CMN PLL feeds the reference clocks to the Ethernet devices
|
||||
--- a/drivers/clk/qcom/clk-ipq-cmn-pll.c
|
||||
+++ b/drivers/clk/qcom/clk-ipq-cmn-pll.c
|
||||
@@ -42,6 +42,9 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
+#define TCSR_ETH_CMN 0x0
|
||||
+#define TCSR_ETH_CMN_ENABLE BIT(0)
|
||||
+
|
||||
#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
|
||||
#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8)
|
||||
|
||||
@@ -79,6 +82,28 @@ static const struct cmn_pll_fixed_output
|
||||
CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
|
||||
};
|
||||
|
||||
+static int ipq_cmn_pll_tcsr_enable(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct resource *res;
|
||||
+ void __iomem *tcsr_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* For IPQ50xx, tcsr is necessary to enable cmn block */
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcsr");
|
||||
+ if (!res)
|
||||
+ return 0;
|
||||
+
|
||||
+ tcsr_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR_OR_NULL(tcsr_base))
|
||||
+ return PTR_ERR(tcsr_base);
|
||||
+
|
||||
+ val = readl(tcsr_base + TCSR_ETH_CMN);
|
||||
+ val |= TCSR_ETH_CMN_ENABLE;
|
||||
+ writel(val, (tcsr_base + TCSR_ETH_CMN));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ipq_cmn_pll_config(struct device *dev, unsigned long parent_rate)
|
||||
{
|
||||
void __iomem *base;
|
||||
@@ -181,6 +206,10 @@ static int ipq_cmn_pll_clk_probe(struct
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
+ ret = ipq_cmn_pll_tcsr_enable(pdev);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Enable CMN PLL failed\n");
|
||||
+
|
||||
/*
|
||||
* To access the CMN PLL registers, the GCC AHB & SYSY clocks
|
||||
* for CMN PLL block need to be enabled.
|
@ -0,0 +1,45 @@
|
||||
From 1b625a37b96b0448aac126d7720eec38de8e5956 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH 2/2] arm64: dts: qcom: ipq5018: Add ethernet cmn node
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -16,6 +16,12 @@
|
||||
#size-cells = <2>;
|
||||
|
||||
clocks {
|
||||
+ cmn_pll_ref_clk: cmn-pll-ref-clk {
|
||||
+ compatible = "fixed-clock";
|
||||
+ clock-frequency = <96000000>;
|
||||
+ #clock-cells = <0>;
|
||||
+ };
|
||||
+
|
||||
sleep_clk: sleep-clk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
@@ -186,6 +192,19 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ cmn_pll: clock-controller@9b000 {
|
||||
+ compatible = "qcom,ipq9574-cmn-pll";
|
||||
+ reg = <0x0009b000 0x800>,
|
||||
+ <0x19475c4 0x4>;
|
||||
+ reg-names = "cmn",
|
||||
+ "tcsr";
|
||||
+ clocks = <&cmn_pll_ref_clk>,
|
||||
+ <&gcc GCC_CMN_BLK_AHB_CLK>,
|
||||
+ <&gcc GCC_CMN_BLK_SYS_CLK>;
|
||||
+ clock-names = "ref", "ahb", "sys";
|
||||
+ #clock-cells = <1>;
|
||||
+ };
|
||||
+
|
||||
qfprom: qfprom@a0000 {
|
||||
compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
|
||||
reg = <0xa0000 0x1000>;
|
@ -0,0 +1,184 @@
|
||||
From 77ad12b3a5e21cae859247c0b82cf9a5b661e531 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:11 +0800
|
||||
Subject: [PATCH 1/3] net: phy: qcom: Introduce IPQ5018 internal PHY driver
|
||||
|
||||
Introduce the internal GE PHY driver, part of the Qualcomm IPQ50xx SoC.
|
||||
The driver registers two clock providers needed and referenced by the GCC
|
||||
using DT properties and phandles.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/net/phy/qcom/Kconfig | 6 ++
|
||||
drivers/net/phy/qcom/Makefile | 1 +
|
||||
drivers/net/phy/qcom/ipq5018.c | 138 +++++++++++++++++++++++++++++++++
|
||||
3 files changed, 145 insertions(+)
|
||||
create mode 100644 drivers/net/phy/qcom/ipq5018.c
|
||||
|
||||
--- a/drivers/net/phy/qcom/Kconfig
|
||||
+++ b/drivers/net/phy/qcom/Kconfig
|
||||
@@ -9,6 +9,12 @@ config AT803X_PHY
|
||||
help
|
||||
Currently supports the AR8030, AR8031, AR8033, AR8035 model
|
||||
|
||||
+config IPQ5018_PHY
|
||||
+ tristate "Qualcomm IPQ5018 internal PHYs"
|
||||
+ select QCOM_NET_PHYLIB
|
||||
+ help
|
||||
+ Currently supports the Qualcomm IPQ5018 internal PHY
|
||||
+
|
||||
config QCA83XX_PHY
|
||||
tristate "Qualcomm Atheros QCA833x PHYs"
|
||||
select QCOM_NET_PHYLIB
|
||||
--- a/drivers/net/phy/qcom/Makefile
|
||||
+++ b/drivers/net/phy/qcom/Makefile
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o
|
||||
obj-$(CONFIG_AT803X_PHY) += at803x.o
|
||||
+obj-$(CONFIG_IPQ5018_PHY) += ipq5018.o
|
||||
obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o
|
||||
obj-$(CONFIG_QCA808X_PHY) += qca808x.o
|
||||
obj-$(CONFIG_QCA807X_PHY) += qca807x.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/phy/qcom/ipq5018.c
|
||||
@@ -0,0 +1,138 @@
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/phy.h>
|
||||
+#include <linux/reset.h>
|
||||
+
|
||||
+#include "qcom.h"
|
||||
+
|
||||
+#define IPQ5018_PHY_ID 0x004dd0c0
|
||||
+
|
||||
+#define TX_RX_CLK_RATE 125000000 /* 125M */
|
||||
+
|
||||
+#define IPQ5018_PHY_FIFO_CONTROL 0x19
|
||||
+#define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
|
||||
+
|
||||
+struct ipq5018_phy {
|
||||
+ int num_clks;
|
||||
+ struct clk_bulk_data *clks;
|
||||
+ struct reset_control *rst;
|
||||
+
|
||||
+ struct clk_hw *clk_rx, *clk_tx;
|
||||
+ struct clk_hw_onecell_data *clk_data;
|
||||
+};
|
||||
+
|
||||
+static int ipq5018_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct ipq5018_phy *priv;
|
||||
+ struct device *dev = &phydev->mdio.dev;
|
||||
+ char name[64];
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return dev_err_probe(dev, -ENOMEM,
|
||||
+ "failed to allocate priv\n");
|
||||
+
|
||||
+ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
|
||||
+ if (priv->num_clks < 0)
|
||||
+ return dev_err_probe(dev, priv->num_clks,
|
||||
+ "failed to acquire clocks\n");
|
||||
+
|
||||
+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret,
|
||||
+ "failed to enable clocks\n");
|
||||
+
|
||||
+ priv->rst = devm_reset_control_array_get_exclusive(dev);
|
||||
+ if (IS_ERR_OR_NULL(priv->rst))
|
||||
+ return dev_err_probe(dev, PTR_ERR(priv->rst),
|
||||
+ "failed to acquire reset\n");
|
||||
+
|
||||
+ ret = reset_control_reset(priv->rst);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret,
|
||||
+ "failed to reset\n");
|
||||
+
|
||||
+ snprintf(name, sizeof(name), "%s#rx", dev_name(dev));
|
||||
+ priv->clk_rx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
|
||||
+ TX_RX_CLK_RATE);
|
||||
+ if (IS_ERR_OR_NULL(priv->clk_rx))
|
||||
+ return dev_err_probe(dev, PTR_ERR(priv->clk_rx),
|
||||
+ "failed to register rx clock\n");
|
||||
+
|
||||
+ snprintf(name, sizeof(name), "%s#tx", dev_name(dev));
|
||||
+ priv->clk_tx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
|
||||
+ TX_RX_CLK_RATE);
|
||||
+ if (IS_ERR_OR_NULL(priv->clk_tx))
|
||||
+ return dev_err_probe(dev, PTR_ERR(priv->clk_tx),
|
||||
+ "failed to register tx clock\n");
|
||||
+
|
||||
+ priv->clk_data = devm_kzalloc(dev,
|
||||
+ struct_size(priv->clk_data, hws, 2),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!priv->clk_data)
|
||||
+ return dev_err_probe(dev, -ENOMEM,
|
||||
+ "failed to allocate clk_data\n");
|
||||
+
|
||||
+ priv->clk_data->num = 2;
|
||||
+ priv->clk_data->hws[0] = priv->clk_rx;
|
||||
+ priv->clk_data->hws[1] = priv->clk_tx;
|
||||
+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
+ priv->clk_data);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret,
|
||||
+ "fail to register clock provider\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq5018_soft_reset(struct phy_device *phydev)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
|
||||
+ IPQ5018_PHY_FIFO_RESET, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ msleep(50);
|
||||
+
|
||||
+ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
|
||||
+ IPQ5018_PHY_FIFO_RESET, IPQ5018_PHY_FIFO_RESET);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ipq5018_cable_test_start(struct phy_device *phydev)
|
||||
+{
|
||||
+ /* we do all the (time consuming) work later */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct phy_driver ipq5018_internal_phy_driver[] = {
|
||||
+ {
|
||||
+ PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
|
||||
+ .name = "Qualcomm IPQ5018 internal PHY",
|
||||
+ .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
|
||||
+ .probe = ipq5018_probe,
|
||||
+ .soft_reset = ipq5018_soft_reset,
|
||||
+ .read_status = at803x_read_status,
|
||||
+ .config_intr = at803x_config_intr,
|
||||
+ .handle_interrupt = at803x_handle_interrupt,
|
||||
+ .cable_test_start = ipq5018_cable_test_start,
|
||||
+ .cable_test_get_status = qca808x_cable_test_get_status,
|
||||
+ },
|
||||
+};
|
||||
+module_phy_driver(ipq5018_internal_phy_driver);
|
||||
+
|
||||
+static struct mdio_device_id __maybe_unused ipq5018_internal_phy_ids[] = {
|
||||
+ { PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID) },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(mdio, ipq5018_internal_phy_ids);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Qualcomm IPQ5018 internal PHY driver");
|
||||
+MODULE_AUTHOR("Ziyang Huang <hzyitc@outlook.com>");
|
@ -0,0 +1,43 @@
|
||||
From d2cdc83fb2c7360856e598810b88211d815fc851 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH 2/3] arm64: dts: qcom: ipq5018: add mdio node
|
||||
|
||||
The IPQ5018 SoC contains two MDIO controllers. MDIO0 is used to control
|
||||
its internal GE Phy, while MDIO1 is wired to external PHYs/switch.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -192,6 +192,26 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ mdio0: mdio@88000 {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ compatible = "qcom,ipq5018-mdio", "qcom,qca-mdio";
|
||||
+ reg = <0x88000 0x64>;
|
||||
+ clocks = <&gcc GCC_MDIO0_AHB_CLK>;
|
||||
+ clock-names = "gcc_mdio_ahb_clk";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mdio1: mdio@90000 {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ compatible = "qcom,ipq5018-mdio";
|
||||
+ reg = <0x90000 0x64>;
|
||||
+ clocks = <&gcc GCC_MDIO1_AHB_CLK>;
|
||||
+ clock-names = "gcc_mdio_ahb_clk";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
cmn_pll: clock-controller@9b000 {
|
||||
compatible = "qcom,ipq9574-cmn-pll";
|
||||
reg = <0x0009b000 0x800>,
|
@ -0,0 +1,45 @@
|
||||
From 28490d95fe9e059c5ce74b2289d66e0d7ede2d50 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH 3/3] arm64: dts: qcom: ipq5018: add ge_phy node
|
||||
|
||||
Add the GE PHY node and register the output clocks in the GCC node.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -200,6 +200,18 @@
|
||||
clocks = <&gcc GCC_MDIO0_AHB_CLK>;
|
||||
clock-names = "gcc_mdio_ahb_clk";
|
||||
status = "disabled";
|
||||
+
|
||||
+ ge_phy: ethernet-phy@7 {
|
||||
+ compatible = "ethernet-phy-id004d.d0c0";
|
||||
+ reg = <7>;
|
||||
+ resets = <&gcc GCC_GEPHY_BCR>,
|
||||
+ <&gcc GCC_GEPHY_MDC_SW_ARES>,
|
||||
+ <&gcc GCC_GEPHY_DSP_HW_ARES>,
|
||||
+ <&gcc GCC_GEPHY_RX_ARES>,
|
||||
+ <&gcc GCC_GEPHY_TX_ARES>;
|
||||
+ clocks = <&gcc GCC_GEPHY_RX_CLK>,
|
||||
+ <&gcc GCC_GEPHY_TX_CLK>;
|
||||
+ };
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
@@ -394,8 +406,8 @@
|
||||
<&pcie0_phy>,
|
||||
<&pcie1_phy>,
|
||||
<0>,
|
||||
- <0>,
|
||||
- <0>,
|
||||
+ <&ge_phy 0>,
|
||||
+ <&ge_phy 1>,
|
||||
<0>,
|
||||
<0>;
|
||||
#clock-cells = <1>;
|
@ -0,0 +1,111 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Sun, 19 Jan 2025 11:25:27 +0400
|
||||
Subject: [PATCH] net: phy: qcom: ipq5018 enable configuration of DAC settings
|
||||
|
||||
Allow setting amplitude and bias current as needed on the IPQ5018 Internal
|
||||
GE PHY. When the "qcom,dac" property is set in the DTS, the driver expects
|
||||
a pair of u32 values:
|
||||
|
||||
(from QCA8337 datasheet)
|
||||
11: follow DSP setting
|
||||
10: bypass half amplitude and follow DSP half bias current
|
||||
01: half amplitude follow DSP and bypass half bias current
|
||||
00: full amplitude and full bias current
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/drivers/net/phy/qcom/ipq5018.c
|
||||
+++ b/drivers/net/phy/qcom/ipq5018.c
|
||||
@@ -13,6 +13,10 @@
|
||||
#define IPQ5018_PHY_FIFO_CONTROL 0x19
|
||||
#define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
|
||||
|
||||
+#define IPQ5018_PHY_DEBUG_EDAC 0x4380
|
||||
+#define IPQ5018_PHY_MMD1_MDAC 0x8100
|
||||
+#define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
|
||||
+
|
||||
struct ipq5018_phy {
|
||||
int num_clks;
|
||||
struct clk_bulk_data *clks;
|
||||
@@ -20,20 +24,35 @@ struct ipq5018_phy {
|
||||
|
||||
struct clk_hw *clk_rx, *clk_tx;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
+
|
||||
+ u32 mdac;
|
||||
+ u32 edac;
|
||||
};
|
||||
|
||||
static int ipq5018_probe(struct phy_device *phydev)
|
||||
{
|
||||
- struct ipq5018_phy *priv;
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
+ struct ipq5018_phy *priv;
|
||||
+ u32 mdac, edac = 0;
|
||||
char name[64];
|
||||
- int ret;
|
||||
+ int ret, cnt;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return dev_err_probe(dev, -ENOMEM,
|
||||
"failed to allocate priv\n");
|
||||
|
||||
+ cnt = of_property_count_u32_elems(dev->of_node, "qcom,dac");
|
||||
+ if (cnt == 2) {
|
||||
+ ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 0, &mdac);
|
||||
+ if (!ret)
|
||||
+ priv->mdac = mdac;
|
||||
+
|
||||
+ ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 1, &edac);
|
||||
+ if (!ret)
|
||||
+ priv->edac = edac;
|
||||
+ }
|
||||
+
|
||||
priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
|
||||
if (priv->num_clks < 0)
|
||||
return dev_err_probe(dev, priv->num_clks,
|
||||
@@ -84,6 +103,8 @@ static int ipq5018_probe(struct phy_devi
|
||||
return dev_err_probe(dev, ret,
|
||||
"fail to register clock provider\n");
|
||||
|
||||
+ phydev->priv = priv;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -112,12 +133,34 @@ static int ipq5018_cable_test_start(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ipq5018_config_init(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct ipq5018_phy *priv = phydev->priv;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* setting mdac in MMD1 */
|
||||
+ if (priv->mdac) {
|
||||
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
|
||||
+ IPQ5018_PHY_DAC_MASK, priv->mdac);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* setting edac in debug register */
|
||||
+ if (priv->edac)
|
||||
+ return at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
|
||||
+ IPQ5018_PHY_DAC_MASK, priv->edac);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver ipq5018_internal_phy_driver[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
|
||||
.name = "Qualcomm IPQ5018 internal PHY",
|
||||
.flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
|
||||
.probe = ipq5018_probe,
|
||||
+ .config_init = ipq5018_config_init,
|
||||
.soft_reset = ipq5018_soft_reset,
|
||||
.read_status = at803x_read_status,
|
||||
.config_intr = at803x_config_intr,
|
@ -0,0 +1,108 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Fri, 24 Jan 2025 17:18:12 +0400
|
||||
Subject: [PATCH] net: phy: qcom: add IPQ5018 initvals and CDT feature
|
||||
|
||||
The Cable Diagnostics Test for IPQ5018 follows the same logic as qca808x.
|
||||
However, the IPQ5018 GE PHY has its own threshold values. So let's set the
|
||||
CDT thresholds for the IPQ5018 internal GE PHY. While add it, add and set
|
||||
thesholds for MSE for signal quality measurement and 8023az for EEE.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/drivers/net/phy/qcom/ipq5018.c
|
||||
+++ b/drivers/net/phy/qcom/ipq5018.c
|
||||
@@ -17,6 +17,38 @@
|
||||
#define IPQ5018_PHY_MMD1_MDAC 0x8100
|
||||
#define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
|
||||
|
||||
+#define IPQ5018_PHY_MMD1_MSE_THRESH1 0x1000
|
||||
+#define IPQ5018_PHY_MMD1_MSE_THRESH2 0x1001
|
||||
+#define IPQ5018_PHY_MMD3_AZ_CTRL1 0x8008
|
||||
+#define IPQ5018_PHY_MMD3_AZ_CTRL2 0x8009
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3 0x8074
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4 0x8075
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5 0x8076
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6 0x8077
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7 0x8078
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9 0x807a
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13 0x807e
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL14 0x807f
|
||||
+
|
||||
+#define IPQ5018_PHY_MMD1_MSE_THRESH1_VAL 0xf1
|
||||
+#define IPQ5018_PHY_MMD1_MSE_THRESH2_VAL 0x1f6
|
||||
+#define IPQ5018_PHY_MMD3_AZ_CTRL1_VAL 0x7880
|
||||
+#define IPQ5018_PHY_MMD3_AZ_CTRL2_VAL 0xc8
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3_VAL 0xc040
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4_VAL 0xa060
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5_VAL 0xc040
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6_VAL 0xa060
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7_VAL 0xc24c
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9_VAL 0xc060
|
||||
+#define IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13_VAL 0xb060
|
||||
+#define IPQ5018_PHY_MMD3_NEAR_ECHO_THRESH_VAL 0x90b0
|
||||
+
|
||||
+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE 0x1
|
||||
+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK GENMASK(7,4)
|
||||
+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT 0x50
|
||||
+
|
||||
+#define IPQ5018_PHY_DEBUG_ANA_DAC_FILTER 0xa080
|
||||
+
|
||||
struct ipq5018_phy {
|
||||
int num_clks;
|
||||
struct clk_bulk_data *clks;
|
||||
@@ -129,6 +161,24 @@ static int ipq5018_soft_reset(struct phy
|
||||
|
||||
static int ipq5018_cable_test_start(struct phy_device *phydev)
|
||||
{
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL4_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL5_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL6_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL7_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL9_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13,
|
||||
+ IPQ5018_PHY_MMD3_CDT_THRESH_CTRL13_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_CDT_THRESH_CTRL3,
|
||||
+ IPQ5018_PHY_MMD3_NEAR_ECHO_THRESH_VAL);
|
||||
+
|
||||
/* we do all the (time consuming) work later */
|
||||
return 0;
|
||||
}
|
||||
@@ -136,8 +186,30 @@ static int ipq5018_cable_test_start(stru
|
||||
static int ipq5018_config_init(struct phy_device *phydev)
|
||||
{
|
||||
struct ipq5018_phy *priv = phydev->priv;
|
||||
+ u16 val = 0;
|
||||
int ret;
|
||||
|
||||
+ /* set LDO efuse: first temporarily store ANA_DAC_FILTER value from
|
||||
+ debug register as it will be reset once the ANA_LDO_EFUSE register
|
||||
+ is written to */
|
||||
+ val = at803x_debug_reg_read(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER);
|
||||
+ at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE,
|
||||
+ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK,
|
||||
+ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT);
|
||||
+ at803x_debug_reg_write(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER, val);
|
||||
+
|
||||
+ /* set 8023AZ CTRL values */
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_AZ_CTRL1,
|
||||
+ IPQ5018_PHY_MMD3_AZ_CTRL1_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_MMD3_AZ_CTRL2,
|
||||
+ IPQ5018_PHY_MMD3_AZ_CTRL2_VAL);
|
||||
+
|
||||
+ /* set MSE threshold values */
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH1,
|
||||
+ IPQ5018_PHY_MMD1_MSE_THRESH1_VAL);
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH2,
|
||||
+ IPQ5018_PHY_MMD1_MSE_THRESH2_VAL);
|
||||
+
|
||||
/* setting mdac in MMD1 */
|
||||
if (priv->mdac) {
|
||||
ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
|
@ -0,0 +1,35 @@
|
||||
From f71366e0530db2c5cecbbbb6edfbf7344bd6f83b Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH 1/2] clk: gcc-ipq5018: remove the unsupported clk
|
||||
combination for gmac
|
||||
|
||||
Comment out the unsupported clock combination in the frequency table
|
||||
for GMAC1.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/clk/qcom/gcc-ipq5018.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/qcom/gcc-ipq5018.c
|
||||
+++ b/drivers/clk/qcom/gcc-ipq5018.c
|
||||
@@ -677,7 +677,7 @@ static const struct freq_tbl ftbl_gmac1_
|
||||
F(2500000, P_UNIPHY_RX, 12.5, 0, 0),
|
||||
F(24000000, P_XO, 1, 0, 0),
|
||||
F(25000000, P_UNIPHY_RX, 2.5, 0, 0),
|
||||
- F(125000000, P_UNIPHY_RX, 2.5, 0, 0),
|
||||
+ /* F(125000000, P_UNIPHY_RX, 2.5, 0, 0), */
|
||||
F(125000000, P_UNIPHY_RX, 1, 0, 0),
|
||||
F(312500000, P_UNIPHY_RX, 1, 0, 0),
|
||||
{ }
|
||||
@@ -717,7 +717,7 @@ static const struct freq_tbl ftbl_gmac1_
|
||||
F(2500000, P_UNIPHY_TX, 12.5, 0, 0),
|
||||
F(24000000, P_XO, 1, 0, 0),
|
||||
F(25000000, P_UNIPHY_TX, 2.5, 0, 0),
|
||||
- F(125000000, P_UNIPHY_TX, 2.5, 0, 0),
|
||||
+ /* F(125000000, P_UNIPHY_TX, 2.5, 0, 0), */
|
||||
F(125000000, P_UNIPHY_TX, 1, 0, 0),
|
||||
F(312500000, P_UNIPHY_TX, 1, 0, 0),
|
||||
{ }
|
@ -0,0 +1,62 @@
|
||||
From ce9e56a436e486690097cfbdda2d0c11b60db4c2 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH] clk: gcc-ipq5018: refer to GE PHY rx and tx clk providers by name
|
||||
|
||||
QCA-SSDK does not register the output clocks of the onboard GE Phy and
|
||||
uniphy so the GCC and DTS can't reference them by their index.
|
||||
The SSDK references them by name, so let's change the GCC driver
|
||||
accordingly.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/clk/qcom/gcc-ipq5018.c | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/clk/qcom/gcc-ipq5018.c
|
||||
+++ b/drivers/clk/qcom/gcc-ipq5018.c
|
||||
@@ -335,8 +335,8 @@ static const struct parent_map gcc_xo_gp
|
||||
|
||||
static const struct clk_parent_data gcc_xo_gephy_gcc_rx_gephy_gcc_tx_ubi32_pll_gpll0[] = {
|
||||
{ .index = DT_XO },
|
||||
- { .index = DT_GEPHY_RX_CLK },
|
||||
- { .index = DT_GEPHY_TX_CLK },
|
||||
+ { .name = "gephy_gcc_rx", .index = -1 },
|
||||
+ { .name = "gephy_gcc_tx", .index = -1 },
|
||||
{ .hw = &ubi32_pll.clkr.hw },
|
||||
{ .hw = &gpll0.clkr.hw },
|
||||
};
|
||||
@@ -351,8 +351,8 @@ static const struct parent_map gcc_xo_ge
|
||||
|
||||
static const struct clk_parent_data gcc_xo_gephy_gcc_tx_gephy_gcc_rx_ubi32_pll_gpll0[] = {
|
||||
{ .index = DT_XO },
|
||||
- { .index = DT_GEPHY_TX_CLK },
|
||||
- { .index = DT_GEPHY_RX_CLK },
|
||||
+ { .name = "gephy_gcc_tx", .index = -1 },
|
||||
+ { .name = "gephy_gcc_rx", .index = -1 },
|
||||
{ .hw = &ubi32_pll.clkr.hw },
|
||||
{ .hw = &gpll0.clkr.hw },
|
||||
};
|
||||
@@ -367,8 +367,8 @@ static const struct parent_map gcc_xo_ge
|
||||
|
||||
static const struct clk_parent_data gcc_xo_uniphy_gcc_rx_uniphy_gcc_tx_ubi32_pll_gpll0[] = {
|
||||
{ .index = DT_XO },
|
||||
- { .index = DT_UNIPHY_RX_CLK },
|
||||
- { .index = DT_UNIPHY_TX_CLK },
|
||||
+ { .name = "uniphy_gcc_rx", .index = -1 },
|
||||
+ { .name = "uniphy_gcc_tx", .index = -1 },
|
||||
{ .hw = &ubi32_pll.clkr.hw },
|
||||
{ .hw = &gpll0.clkr.hw },
|
||||
};
|
||||
@@ -383,8 +383,8 @@ static const struct parent_map gcc_xo_un
|
||||
|
||||
static const struct clk_parent_data gcc_xo_uniphy_gcc_tx_uniphy_gcc_rx_ubi32_pll_gpll0[] = {
|
||||
{ .index = DT_XO },
|
||||
- { .index = DT_UNIPHY_TX_CLK },
|
||||
- { .index = DT_UNIPHY_RX_CLK },
|
||||
+ { .name = "uniphy_gcc_tx", .index = -1 },
|
||||
+ { .name = "uniphy_gcc_rx", .index = -1 },
|
||||
{ .hw = &ubi32_pll.clkr.hw },
|
||||
{ .hw = &gpll0.clkr.hw },
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
From d7a41a3ab6b8e3a3158997cda13f1fe28a37268c Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH] net: dsa: qca8k: always enable SGMII auto-negotiation
|
||||
|
||||
fixed-link can't work well without this
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-8xxx.c | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1545,11 +1545,10 @@ static int qca8k_pcs_config(struct phyli
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* Enable/disable SerDes auto-negotiation as necessary */
|
||||
- val = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ?
|
||||
- 0 : QCA8K_PWS_SERDES_AEN_DIS;
|
||||
-
|
||||
- ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8K_PWS_SERDES_AEN_DIS, val);
|
||||
+ /* Enable SerDes auto-negotiation always.
|
||||
+ * So fixed-link can work.
|
||||
+ */
|
||||
+ ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8K_PWS_SERDES_AEN_DIS, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 8a56ac86c2eed13024413aa23a6cda85613d60f9 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sat, 18 Jan 2025 16:18:40 +0800
|
||||
Subject: [PATCH 1/2] net: dsa: qca8k: support PHY-to-PHY CPU link
|
||||
|
||||
PHY-to-PHY CPU link is a common/demo design in IPQ50xx platform, since it only has a SGMII/SGMII+ link and a MDI link.
|
||||
|
||||
For DSA, CPU tag is the only requirement. Fortunately, qca8337 can enable it on any port. So it's ok to trust a PHY-to-PHY link as a CPU link.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-8xxx.c | 12 +++++++-----
|
||||
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1013,7 +1013,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
return err;
|
||||
}
|
||||
|
||||
- if (!dsa_is_user_port(priv->ds, reg))
|
||||
+ if (reg == 0 || reg == 6)
|
||||
continue;
|
||||
|
||||
of_get_phy_mode(port, &mode);
|
||||
@@ -1088,17 +1088,19 @@ qca8k_setup_mac_pwr_sel(struct qca8k_pri
|
||||
|
||||
static int qca8k_find_cpu_port(struct dsa_switch *ds)
|
||||
{
|
||||
- struct qca8k_priv *priv = ds->priv;
|
||||
+ int i;
|
||||
|
||||
- /* Find the connected cpu port. Valid port are 0 or 6 */
|
||||
if (dsa_is_cpu_port(ds, 0))
|
||||
return 0;
|
||||
|
||||
- dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6");
|
||||
-
|
||||
if (dsa_is_cpu_port(ds, 6))
|
||||
return 6;
|
||||
|
||||
+ /* PHY-to-PHY link */
|
||||
+ for (i = 1; i <= 5; i++)
|
||||
+ if (dsa_is_cpu_port(ds, i))
|
||||
+ return i;
|
||||
+
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -0,0 +1,202 @@
|
||||
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Date: Fri, 10 Nov 2023 14:49:29 +0530
|
||||
Subject: [PATCH] dt-bindings: remoteproc: qcom: Add support for multipd model
|
||||
|
||||
Add new binding document for multipd model remoteproc.
|
||||
IPQ5332, IPQ9574 follows multipd model.
|
||||
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
---
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,multipd-pil.yaml
|
||||
@@ -0,0 +1,189 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/remoteproc/qcom,multipd-pil.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Qualcomm Multipd Secure Peripheral Image Loader
|
||||
+
|
||||
+maintainers:
|
||||
+ - Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
+
|
||||
+description:
|
||||
+ Multipd Peripheral Image Loader loads firmware and boots Q6 protection domain,
|
||||
+ WCSS protection domain remoteproc's on the Qualcomm IPQ9574, IPQ5332 SoC.
|
||||
+ Protection domain is similar to process in Linux. Here QDSP6 processor runs
|
||||
+ each wifi radio functionality on a separate process. One process can't access
|
||||
+ other process resources, so this is termed as PD i.e protection domain.
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - qcom,ipq5332-q6-mpd
|
||||
+ - qcom,ipq9574-q6-mpd
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ firmware-name:
|
||||
+ maxItems: 2
|
||||
+
|
||||
+ interrupts:
|
||||
+ items:
|
||||
+ - description: Watchdog interrupt
|
||||
+ - description: Fatal interrupt
|
||||
+ - description: Ready interrupt
|
||||
+ - description: Handover interrupt
|
||||
+ - description: Stop acknowledge interrupt
|
||||
+
|
||||
+ interrupt-names:
|
||||
+ items:
|
||||
+ - const: wdog
|
||||
+ - const: fatal
|
||||
+ - const: ready
|
||||
+ - const: handover
|
||||
+ - const: stop-ack
|
||||
+
|
||||
+ qcom,smem-states:
|
||||
+ $ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
+ description: States used by the AP to signal the remote processor
|
||||
+ items:
|
||||
+ - description: Shutdown Q6
|
||||
+ - description: Stop Q6
|
||||
+
|
||||
+ qcom,smem-state-names:
|
||||
+ description:
|
||||
+ Names of the states used by the AP to signal the remote processor
|
||||
+ items:
|
||||
+ - const: shutdown
|
||||
+ - const: stop
|
||||
+
|
||||
+ memory-region:
|
||||
+ items:
|
||||
+ - description: Q6 reserved region
|
||||
+
|
||||
+ glink-edge:
|
||||
+ $ref: /schemas/remoteproc/qcom,glink-edge.yaml#
|
||||
+ description:
|
||||
+ Qualcomm G-Link subnode which represents communication edge, channels
|
||||
+ and devices related to the Modem.
|
||||
+ unevaluatedProperties: false
|
||||
+
|
||||
+patternProperties:
|
||||
+ "^pd-1|pd-2|pd-3":
|
||||
+ type: object
|
||||
+ description:
|
||||
+ WCSS means 'wireless connectivity sub system', in simple words it's a
|
||||
+ wifi radio block. In multipd model, Q6 root protection domain will
|
||||
+ provide services to WCSS user protection domain. In other words WCSS
|
||||
+ protection domains depends on Q6 protection domain i.e Q6 should be up
|
||||
+ before WCSS, similarly Q6 should shut down after all WCSS domains are
|
||||
+ down. It can be achieved by building parent-child topology between Q6
|
||||
+ and WCSS domain's i.e keeping wcss node as sub node of Q6 device node.
|
||||
+
|
||||
+ properties:
|
||||
+ firmware-name:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ interrupts:
|
||||
+ items:
|
||||
+ - description: Fatal interrupt
|
||||
+ - description: Ready interrupt
|
||||
+ - description: Spawn acknowledge interrupt
|
||||
+ - description: Stop acknowledge interrupt
|
||||
+
|
||||
+ interrupt-names:
|
||||
+ items:
|
||||
+ - const: fatal
|
||||
+ - const: ready
|
||||
+ - const: spawn-ack
|
||||
+ - const: stop-ack
|
||||
+
|
||||
+ qcom,smem-states:
|
||||
+ $ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
+ description: States used by the AP to signal the remote processor
|
||||
+ items:
|
||||
+ - description: Shutdown WCSS pd
|
||||
+ - description: Stop WCSS pd
|
||||
+ - description: Spawn WCSS pd
|
||||
+
|
||||
+ qcom,smem-state-names:
|
||||
+ description:
|
||||
+ Names of the states used by the AP to signal the remote processor
|
||||
+ items:
|
||||
+ - const: shutdown
|
||||
+ - const: stop
|
||||
+ - const: spawn
|
||||
+
|
||||
+ required:
|
||||
+ - firmware-name
|
||||
+ - interrupts
|
||||
+ - interrupt-names
|
||||
+ - qcom,smem-states
|
||||
+ - qcom,smem-state-names
|
||||
+
|
||||
+ additionalProperties: false
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - firmware-name
|
||||
+ - reg
|
||||
+ - interrupts
|
||||
+ - interrupt-names
|
||||
+ - qcom,smem-states
|
||||
+ - qcom,smem-state-names
|
||||
+ - memory-region
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
+ q6v5_wcss: remoteproc@d100000 {
|
||||
+ compatible = "qcom,ipq5332-q6-mpd";
|
||||
+ reg = <0xd100000 0x4040>;
|
||||
+ firmware-name = "ath11k/IPQ5332/hw1.0/q6_fw0.mdt",
|
||||
+ "ath11k/IPQ5332/hw1.0/iu_fw.mdt";
|
||||
+ interrupts-extended = <&intc GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <&wcss_smp2p_in 0 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 1 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 2 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 3 IRQ_TYPE_NONE>;
|
||||
+ interrupt-names = "wdog",
|
||||
+ "fatal",
|
||||
+ "ready",
|
||||
+ "handover",
|
||||
+ "stop-ack";
|
||||
+
|
||||
+ qcom,smem-states = <&wcss_smp2p_out 0>,
|
||||
+ <&wcss_smp2p_out 1>;
|
||||
+ qcom,smem-state-names = "shutdown",
|
||||
+ "stop";
|
||||
+
|
||||
+ memory-region = <&q6_region>;
|
||||
+
|
||||
+ glink-edge {
|
||||
+ interrupts = <GIC_SPI 417 IRQ_TYPE_EDGE_RISING>;
|
||||
+ label = "rtr";
|
||||
+ qcom,remote-pid = <1>;
|
||||
+ mboxes = <&apcs_glb 8>;
|
||||
+ };
|
||||
+
|
||||
+ pd-1 {
|
||||
+ firmware-name = "ath11k/IPQ5332/hw1.0/q6_fw1.mdt";
|
||||
+ interrupts-extended = <&wcss_smp2p_in 8 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 9 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 12 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 11 IRQ_TYPE_NONE>;
|
||||
+ interrupt-names = "fatal",
|
||||
+ "ready",
|
||||
+ "spawn-ack",
|
||||
+ "stop-ack";
|
||||
+ qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
+ <&wcss_smp2p_out 9>,
|
||||
+ <&wcss_smp2p_out 10>;
|
||||
+ qcom,smem-state-names = "shutdown",
|
||||
+ "stop",
|
||||
+ "spawn";
|
||||
+ };
|
||||
+ };
|
@ -0,0 +1,43 @@
|
||||
From 50799703c6c8ec0860e19b102dd7cca3d29028e1 Mon Sep 17 00:00:00 2001
|
||||
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Date: Fri, 10 Nov 2023 14:49:34 +0530
|
||||
Subject: [PATCH] firmware: qcom_scm: ipq5332: add support to pass
|
||||
metadata size
|
||||
|
||||
IPQ5332 security software running under trustzone
|
||||
requires metadata size. With V2 cmd, pass metadata
|
||||
size as well.
|
||||
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
---
|
||||
drivers/firmware/qcom_scm.c | 8 ++++++++
|
||||
drivers/firmware/qcom_scm.h | 1 +
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/firmware/qcom_scm.c
|
||||
+++ b/drivers/firmware/qcom_scm.c
|
||||
@@ -592,6 +592,14 @@ int qcom_scm_pas_mem_setup(u32 periphera
|
||||
if (ret)
|
||||
goto disable_clk;
|
||||
|
||||
+ if (__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
|
||||
+ QCOM_SCM_PAS_INIT_IMAGE_V2)) {
|
||||
+ desc.cmd = QCOM_SCM_PAS_INIT_IMAGE_V2;
|
||||
+ desc.arginfo =
|
||||
+ QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL);
|
||||
+ desc.args[2] = size;
|
||||
+ }
|
||||
+
|
||||
ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
qcom_scm_bw_disable();
|
||||
|
||||
--- a/drivers/firmware/qcom_scm.h
|
||||
+++ b/drivers/firmware/qcom_scm.h
|
||||
@@ -92,6 +92,7 @@ extern int scm_legacy_call(struct device
|
||||
|
||||
#define QCOM_SCM_SVC_PIL 0x02
|
||||
#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01
|
||||
+#define QCOM_SCM_PAS_INIT_IMAGE_V2 0x1a
|
||||
#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x02
|
||||
#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x05
|
||||
#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
|
@ -0,0 +1,126 @@
|
||||
From 217fbbc122663c5a3dac752cebef44fb3e0cc179 Mon Sep 17 00:00:00 2001
|
||||
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Date: Fri, 10 Nov 2023 14:49:35 +0530
|
||||
Subject: [PATCH] firmware: qcom_scm: ipq5332: add msa lock/unlock
|
||||
support
|
||||
|
||||
IPQ5332 user pd remoteproc firmwares need to be locked
|
||||
with MSA(modem secure access) features. This patch add
|
||||
support to lock/unlock MSA features.
|
||||
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
---
|
||||
drivers/firmware/qcom_scm.c | 78 ++++++++++++++++++++++++++
|
||||
drivers/firmware/qcom_scm.h | 2 +
|
||||
include/linux/firmware/qcom/qcom_scm.h | 2 +
|
||||
3 files changed, 82 insertions(+)
|
||||
|
||||
--- a/drivers/firmware/qcom_scm.c
|
||||
+++ b/drivers/firmware/qcom_scm.c
|
||||
@@ -712,6 +712,84 @@ bool qcom_scm_pas_supported(u32 peripher
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_supported);
|
||||
|
||||
+/**
|
||||
+ * qcom_scm_msa_lock() - Lock given peripheral firmware region as MSA
|
||||
+ *
|
||||
+ * @peripheral: peripheral id
|
||||
+ *
|
||||
+ * Return 0 on success.
|
||||
+ */
|
||||
+int qcom_scm_msa_lock(u32 peripheral)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct qcom_scm_desc desc = {
|
||||
+ .svc = QCOM_SCM_SVC_PIL,
|
||||
+ .cmd = QCOM_SCM_MSA_LOCK,
|
||||
+ .arginfo = QCOM_SCM_ARGS(1),
|
||||
+ .args[0] = peripheral,
|
||||
+ .owner = ARM_SMCCC_OWNER_SIP,
|
||||
+ };
|
||||
+ struct qcom_scm_res res;
|
||||
+
|
||||
+ if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
|
||||
+ QCOM_SCM_MSA_LOCK))
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = qcom_scm_clk_enable();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = qcom_scm_bw_enable();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
+ qcom_scm_bw_disable();
|
||||
+ qcom_scm_clk_disable();
|
||||
+
|
||||
+ return ret ? : res.result[0];
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(qcom_scm_msa_lock);
|
||||
+
|
||||
+/**
|
||||
+ * qcom_scm_msa_unlock() - Unlock given peripheral MSA firmware region
|
||||
+ *
|
||||
+ * @peripheral: peripheral id
|
||||
+ *
|
||||
+ * Return 0 on success.
|
||||
+ */
|
||||
+int qcom_scm_msa_unlock(u32 peripheral)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct qcom_scm_desc desc = {
|
||||
+ .svc = QCOM_SCM_SVC_PIL,
|
||||
+ .cmd = QCOM_SCM_MSA_UNLOCK,
|
||||
+ .arginfo = QCOM_SCM_ARGS(1),
|
||||
+ .args[0] = peripheral,
|
||||
+ .owner = ARM_SMCCC_OWNER_SIP,
|
||||
+ };
|
||||
+ struct qcom_scm_res res;
|
||||
+
|
||||
+ if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
|
||||
+ QCOM_SCM_MSA_UNLOCK))
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = qcom_scm_clk_enable();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = qcom_scm_bw_enable();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
+ qcom_scm_bw_disable();
|
||||
+ qcom_scm_clk_disable();
|
||||
+
|
||||
+ return ret ? : res.result[0];
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(qcom_scm_msa_unlock);
|
||||
+
|
||||
static int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
|
||||
{
|
||||
struct qcom_scm_desc desc = {
|
||||
--- a/drivers/firmware/qcom_scm.h
|
||||
+++ b/drivers/firmware/qcom_scm.h
|
||||
@@ -98,6 +98,8 @@ extern int scm_legacy_call(struct device
|
||||
#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
|
||||
#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
|
||||
#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
|
||||
+#define QCOM_SCM_MSA_LOCK 0x24
|
||||
+#define QCOM_SCM_MSA_UNLOCK 0x25
|
||||
|
||||
#define QCOM_SCM_SVC_IO 0x05
|
||||
#define QCOM_SCM_IO_READ 0x01
|
||||
--- a/include/linux/firmware/qcom/qcom_scm.h
|
||||
+++ b/include/linux/firmware/qcom/qcom_scm.h
|
||||
@@ -81,6 +81,8 @@ extern int qcom_scm_pas_mem_setup(u32 pe
|
||||
extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
|
||||
extern int qcom_scm_pas_shutdown(u32 peripheral);
|
||||
extern bool qcom_scm_pas_supported(u32 peripheral);
|
||||
+extern int qcom_scm_msa_lock(u32 peripheral);
|
||||
+extern int qcom_scm_msa_unlock(u32 peripheral);
|
||||
|
||||
extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
|
||||
extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
|
@ -0,0 +1,148 @@
|
||||
From cae691d32306966065df869fa7424728d1b16b14 Mon Sep 17 00:00:00 2001
|
||||
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Date: Fri, 10 Nov 2023 14:49:36 +0530
|
||||
Subject: [PATCH] remoteproc: qcom: q6v5: Add multipd interrupts support
|
||||
|
||||
In multipd model, root & user pd remoteproc's interrupts are
|
||||
different. User pd needs additional interrupts like spawn.
|
||||
Instead of going with qcom_q6v5_init(), we defined a new
|
||||
function to register userpd rproc interrupts in mpd driver.
|
||||
Since userpd rproc uses some of common interrupts like fatal,
|
||||
ready, static is removed from ISR handler and used in userpd
|
||||
interrupt registration.
|
||||
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
---
|
||||
drivers/remoteproc/qcom_q6v5.c | 41 +++++++++++++++++++++++++++++++---
|
||||
drivers/remoteproc/qcom_q6v5.h | 11 +++++++++
|
||||
2 files changed, 49 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/remoteproc/qcom_q6v5.c
|
||||
+++ b/drivers/remoteproc/qcom_q6v5.c
|
||||
@@ -112,7 +112,7 @@ static irqreturn_t q6v5_wdog_interrupt(i
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
|
||||
+irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
|
||||
{
|
||||
struct qcom_q6v5 *q6v5 = data;
|
||||
size_t len;
|
||||
@@ -132,8 +132,9 @@ static irqreturn_t q6v5_fatal_interrupt(
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(q6v5_fatal_interrupt);
|
||||
|
||||
-static irqreturn_t q6v5_ready_interrupt(int irq, void *data)
|
||||
+irqreturn_t q6v5_ready_interrupt(int irq, void *data)
|
||||
{
|
||||
struct qcom_q6v5 *q6v5 = data;
|
||||
|
||||
@@ -141,6 +142,7 @@ static irqreturn_t q6v5_ready_interrupt(
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(q6v5_ready_interrupt);
|
||||
|
||||
/**
|
||||
* qcom_q6v5_wait_for_start() - wait for remote processor start signal
|
||||
@@ -177,7 +179,17 @@ static irqreturn_t q6v5_handover_interru
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static irqreturn_t q6v5_stop_interrupt(int irq, void *data)
|
||||
+irqreturn_t q6v5_spawn_interrupt(int irq, void *data)
|
||||
+{
|
||||
+ struct qcom_q6v5 *q6v5 = data;
|
||||
+
|
||||
+ complete(&q6v5->spawn_done);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(q6v5_spawn_interrupt);
|
||||
+
|
||||
+irqreturn_t q6v5_stop_interrupt(int irq, void *data)
|
||||
{
|
||||
struct qcom_q6v5 *q6v5 = data;
|
||||
|
||||
@@ -185,6 +197,7 @@ static irqreturn_t q6v5_stop_interrupt(i
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(q6v5_stop_interrupt);
|
||||
|
||||
/**
|
||||
* qcom_q6v5_request_stop() - request the remote processor to stop
|
||||
@@ -215,6 +228,28 @@ int qcom_q6v5_request_stop(struct qcom_q
|
||||
EXPORT_SYMBOL_GPL(qcom_q6v5_request_stop);
|
||||
|
||||
/**
|
||||
+ * qcom_q6v5_request_spawn() - request the remote processor to spawn
|
||||
+ * @q6v5: reference to qcom_q6v5 context
|
||||
+ *
|
||||
+ * Return: 0 on success, negative errno on failure
|
||||
+ */
|
||||
+int qcom_q6v5_request_spawn(struct qcom_q6v5 *q6v5)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qcom_smem_state_update_bits(q6v5->spawn_state,
|
||||
+ BIT(q6v5->spawn_bit), BIT(q6v5->spawn_bit));
|
||||
+
|
||||
+ ret = wait_for_completion_timeout(&q6v5->spawn_done, 5 * HZ);
|
||||
+
|
||||
+ qcom_smem_state_update_bits(q6v5->spawn_state,
|
||||
+ BIT(q6v5->spawn_bit), 0);
|
||||
+
|
||||
+ return ret == 0 ? -ETIMEDOUT : 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(qcom_q6v5_request_spawn);
|
||||
+
|
||||
+/**
|
||||
* qcom_q6v5_panic() - panic handler to invoke a stop on the remote
|
||||
* @q6v5: reference to qcom_q6v5 context
|
||||
*
|
||||
--- a/drivers/remoteproc/qcom_q6v5.h
|
||||
+++ b/drivers/remoteproc/qcom_q6v5.h
|
||||
@@ -18,21 +18,27 @@ struct qcom_q6v5 {
|
||||
|
||||
struct qcom_smem_state *state;
|
||||
struct qmp *qmp;
|
||||
+ struct qcom_smem_state *shutdown_state;
|
||||
+ struct qcom_smem_state *spawn_state;
|
||||
|
||||
struct icc_path *path;
|
||||
|
||||
unsigned stop_bit;
|
||||
+ unsigned shutdown_bit;
|
||||
+ unsigned spawn_bit;
|
||||
|
||||
int wdog_irq;
|
||||
int fatal_irq;
|
||||
int ready_irq;
|
||||
int handover_irq;
|
||||
int stop_irq;
|
||||
+ int spawn_irq;
|
||||
|
||||
bool handover_issued;
|
||||
|
||||
struct completion start_done;
|
||||
struct completion stop_done;
|
||||
+ struct completion spawn_done;
|
||||
|
||||
int crash_reason;
|
||||
|
||||
@@ -50,7 +56,12 @@ void qcom_q6v5_deinit(struct qcom_q6v5 *
|
||||
int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5);
|
||||
int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5);
|
||||
int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon);
|
||||
+int qcom_q6v5_request_spawn(struct qcom_q6v5 *q6v5);
|
||||
int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout);
|
||||
unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5);
|
||||
+irqreturn_t q6v5_fatal_interrupt(int irq, void *data);
|
||||
+irqreturn_t q6v5_ready_interrupt(int irq, void *data);
|
||||
+irqreturn_t q6v5_spawn_interrupt(int irq, void *data);
|
||||
+irqreturn_t q6v5_stop_interrupt(int irq, void *data);
|
||||
|
||||
#endif
|
@ -0,0 +1,901 @@
|
||||
From 3f61ff1fb5c90f8b6c28a3a2b4a29203000ee585 Mon Sep 17 00:00:00 2001
|
||||
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Date: Fri, 10 Nov 2023 14:49:37 +0530
|
||||
Subject: [PATCH] remoteproc: qcom: Add Hexagon based multipd rproc
|
||||
driver
|
||||
|
||||
It adds support to bring up remoteproc's on multipd model.
|
||||
Pd means protection domain. It's similar to process in Linux.
|
||||
Here QDSP6 processor runs each wifi radio functionality on a
|
||||
separate process. One process can't access other process
|
||||
resources, so this is termed as PD i.e protection domain.
|
||||
|
||||
Here we have two pd's called root and user pd. We can correlate
|
||||
Root pd as root and user pd as user in linux. Root pd has more
|
||||
privileges than user pd. Root will provide services to user pd.
|
||||
|
||||
>From remoteproc driver perspective, root pd corresponds to QDSP6
|
||||
processor bring up and user pd corresponds to Wifi radio (WCSS)
|
||||
bring up.
|
||||
|
||||
Here WCSS(user) PD is dependent on Q6(root) PD, so first
|
||||
q6 pd should be up before wcss pd. After wcss pd goes down,
|
||||
q6 pd should be turned off.
|
||||
|
||||
APPS QDSP6
|
||||
------- -------------
|
||||
| | Crash notification | | ------
|
||||
| |<---------------------|----------|-------|User|
|
||||
| | | | |->|PD1 |
|
||||
| | | ------- | | ------
|
||||
| | | | | | |
|
||||
|Root | Start/stop Q6 | | R | | |
|
||||
|PD |<---------------------|->| | | |
|
||||
|rproc| Crash notification | | O | | |
|
||||
| | | | | | |
|
||||
|User |Start/stop UserPD1 | | O | | |
|
||||
|PD1 |----------------------|->| |-|----|
|
||||
|rproc| | | T | | |
|
||||
| | | | | | |
|
||||
|User |Start/stop UserPD2 | | P | | |
|
||||
|PD2 |----------------------|->| |-|----|
|
||||
|rproc| | | D | | |
|
||||
| | | ------- | | ------
|
||||
| | Crash notification | | |->|User|
|
||||
| |<---------------------|----------|-------|PD2 |
|
||||
------- | | ------
|
||||
------------
|
||||
|
||||
IPQ5332, IPQ9574 supports multipd remoteproc driver.
|
||||
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
---
|
||||
drivers/remoteproc/Kconfig | 19 +
|
||||
drivers/remoteproc/Makefile | 1 +
|
||||
drivers/remoteproc/qcom_q6v5_mpd.c | 802 +++++++++++++++++++++++++++++
|
||||
3 files changed, 822 insertions(+)
|
||||
create mode 100644 drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
|
||||
--- a/drivers/remoteproc/Kconfig
|
||||
+++ b/drivers/remoteproc/Kconfig
|
||||
@@ -234,6 +234,25 @@ config QCOM_Q6V5_PAS
|
||||
CDSP (Compute DSP), MPSS (Modem Peripheral SubSystem), and
|
||||
SLPI (Sensor Low Power Island).
|
||||
|
||||
+config QCOM_Q6V5_MPD
|
||||
+ tristate "Qualcomm Hexagon based MPD model Peripheral Image Loader"
|
||||
+ depends on OF && ARCH_QCOM
|
||||
+ depends on QCOM_SMEM
|
||||
+ depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n
|
||||
+ depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
|
||||
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
|
||||
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
|
||||
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
|
||||
+ select QCOM_MDT_LOADER
|
||||
+ select QCOM_PIL_INFO
|
||||
+ select QCOM_Q6V5_COMMON
|
||||
+ select QCOM_RPROC_COMMON
|
||||
+ select QCOM_SCM
|
||||
+ help
|
||||
+ Say y here to support the Qualcomm Secure Peripheral Image Loader
|
||||
+ for the Hexagon based MultiPD model remote processors on e.g. IPQ5018.
|
||||
+ This is trustZone wireless subsystem.
|
||||
+
|
||||
config QCOM_Q6V5_WCSS
|
||||
tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
|
||||
depends on OF && ARCH_QCOM
|
||||
--- a/drivers/remoteproc/Makefile
|
||||
+++ b/drivers/remoteproc/Makefile
|
||||
@@ -25,6 +25,7 @@ obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil
|
||||
obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o
|
||||
obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o
|
||||
obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6v5_adsp.o
|
||||
+obj-$(CONFIG_QCOM_Q6V5_MPD) += qcom_q6v5_mpd.o
|
||||
obj-$(CONFIG_QCOM_Q6V5_MSS) += qcom_q6v5_mss.o
|
||||
obj-$(CONFIG_QCOM_Q6V5_PAS) += qcom_q6v5_pas.o
|
||||
obj-$(CONFIG_QCOM_Q6V5_WCSS) += qcom_q6v5_wcss.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
@@ -0,0 +1,802 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) 2016-2018 Linaro Ltd.
|
||||
+ * Copyright (C) 2014 Sony Mobile Communications AB
|
||||
+ * Copyright (c) 2012-2018, 2021 The Linux Foundation. All rights reserved.
|
||||
+ */
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/firmware/qcom/qcom_scm.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_reserved_mem.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/reset.h>
|
||||
+#include <linux/soc/qcom/mdt_loader.h>
|
||||
+#include <linux/soc/qcom/smem.h>
|
||||
+#include <linux/soc/qcom/smem_state.h>
|
||||
+#include "qcom_common.h"
|
||||
+#include "qcom_q6v5.h"
|
||||
+
|
||||
+#include "remoteproc_internal.h"
|
||||
+
|
||||
+#define WCSS_CRASH_REASON 421
|
||||
+#define WCSS_SMEM_HOST 1
|
||||
+
|
||||
+#define WCNSS_PAS_ID 6
|
||||
+#define MPD_WCNSS_PAS_ID 0xD
|
||||
+
|
||||
+#define BUF_SIZE 35
|
||||
+
|
||||
+#define MAX_FIRMWARE 3
|
||||
+
|
||||
+#define RPD_SWID MPD_WCNSS_PAS_ID
|
||||
+#define UPD_SWID 0x12
|
||||
+#define REMOTE_PID 1
|
||||
+#define UPD_BOOT_INFO_SMEM_SIZE 4096
|
||||
+#define UPD_BOOT_INFO_HEADER_TYPE 0x2
|
||||
+#define UPD_BOOT_INFO_SMEM_ID 507
|
||||
+#define VERSION2 2
|
||||
+
|
||||
+static LIST_HEAD(upd_rproc_list);
|
||||
+enum {
|
||||
+ Q6_IPQ,
|
||||
+ WCSS_IPQ,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct userpd_boot_info_header - header of user pd bootinfo
|
||||
+ * @type: type of bootinfo passing over smem
|
||||
+ * @length: length of header in bytes
|
||||
+ */
|
||||
+struct userpd_boot_info_header {
|
||||
+ u8 type;
|
||||
+ u8 length;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct userpd_boot_info - holds info required to boot user pd
|
||||
+ * @header: pointer to header
|
||||
+ * @pid: unique id represents each user pd process
|
||||
+ * @bootaddr: load address of user pd firmware
|
||||
+ * @data_size: user pd firmware memory size
|
||||
+ */
|
||||
+struct userpd_boot_info {
|
||||
+ struct userpd_boot_info_header header;
|
||||
+ u8 pid;
|
||||
+ u32 bootaddr;
|
||||
+ u32 data_size;
|
||||
+} __packed;
|
||||
+
|
||||
+struct q6_wcss {
|
||||
+ struct device *dev;
|
||||
+ struct qcom_rproc_glink glink_subdev;
|
||||
+ struct qcom_rproc_ssr ssr_subdev;
|
||||
+ struct qcom_q6v5 q6;
|
||||
+ phys_addr_t mem_phys;
|
||||
+ phys_addr_t mem_reloc;
|
||||
+ void *mem_region;
|
||||
+ size_t mem_size;
|
||||
+ u8 pd_asid;
|
||||
+ const struct wcss_data *desc;
|
||||
+ const char **firmware;
|
||||
+ u32 version;
|
||||
+};
|
||||
+
|
||||
+struct wcss_data {
|
||||
+ u32 pasid;
|
||||
+ bool share_upd_info_to_q6;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * qcom_get_pd_asid() - get the pd asid number from PD spawn bit
|
||||
+ * @rproc: rproc handle
|
||||
+ *
|
||||
+ * Returns asid on success
|
||||
+ */
|
||||
+static u8 qcom_get_pd_asid(struct rproc *rproc)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ u8 bit = wcss->q6.spawn_bit;
|
||||
+
|
||||
+ return bit / 8;
|
||||
+}
|
||||
+
|
||||
+static int q6_wcss_start(struct rproc *rproc)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ int ret;
|
||||
+ const struct wcss_data *desc = wcss->desc;
|
||||
+
|
||||
+ qcom_q6v5_prepare(&wcss->q6);
|
||||
+
|
||||
+ ret = qcom_scm_pas_auth_and_reset(desc->pasid);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev, "wcss_reset failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = qcom_q6v5_wait_for_start(&wcss->q6, 5 * HZ);
|
||||
+ if (ret == -ETIMEDOUT)
|
||||
+ dev_err(wcss->dev, "start timed out\n");
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int q6_wcss_spawn_pd(struct rproc *rproc)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+
|
||||
+ ret = qcom_q6v5_request_spawn(&wcss->q6);
|
||||
+ if (ret == -ETIMEDOUT) {
|
||||
+ dev_err(wcss->dev, "%s spawn timedout\n", rproc->name);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = qcom_q6v5_wait_for_start(&wcss->q6, msecs_to_jiffies(10000));
|
||||
+ if (ret == -ETIMEDOUT) {
|
||||
+ dev_err(wcss->dev, "%s start timedout\n", rproc->name);
|
||||
+ wcss->q6.running = false;
|
||||
+ return ret;
|
||||
+ }
|
||||
+ wcss->q6.running = true;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int wcss_pd_start(struct rproc *rproc)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qcom_scm_msa_lock(pasid);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev, "failed to power up pd\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (wcss->q6.spawn_bit) {
|
||||
+ ret = q6_wcss_spawn_pd(rproc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int q6_wcss_stop(struct rproc *rproc)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ const struct wcss_data *desc = wcss->desc;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qcom_scm_pas_shutdown(desc->pasid);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev, "not able to shutdown\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ qcom_q6v5_unprepare(&wcss->q6);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * wcss_pd_stop() - Stop WCSS user pd
|
||||
+ * @rproc: rproc handle
|
||||
+ *
|
||||
+ * Stop root pd after user pd down. Root pd
|
||||
+ * is used to provide services to user pd, so
|
||||
+ * keeping root pd alive when user pd is down
|
||||
+ * is invalid.
|
||||
+ * ---------------------------------------------
|
||||
+ *
|
||||
+ * -----------
|
||||
+ * |-------->| User PD1 |
|
||||
+ * | -----------
|
||||
+ * |
|
||||
+ * |
|
||||
+ * ----- | -----------
|
||||
+ * | Q6 |---------------->| User Pd2 |
|
||||
+ * ----- | -----------
|
||||
+ * |
|
||||
+ * |
|
||||
+ * | -----------
|
||||
+ * |--------->| User Pd3 |
|
||||
+ * -----------
|
||||
+ * ----------------------------------------------
|
||||
+ */
|
||||
+static int wcss_pd_stop(struct rproc *rproc)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
|
||||
+ u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (rproc->state != RPROC_CRASHED && wcss->q6.stop_bit) {
|
||||
+ ret = qcom_q6v5_request_stop(&wcss->q6, NULL);
|
||||
+ if (ret) {
|
||||
+ dev_err(&rproc->dev, "pd not stopped\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = qcom_scm_msa_unlock(pasid);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev, "failed to power down pd\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ rproc_shutdown(rpd_rproc);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void *q6_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len,
|
||||
+ bool *is_iomem)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ int offset;
|
||||
+
|
||||
+ offset = da - wcss->mem_reloc;
|
||||
+ if (offset < 0 || offset + len > wcss->mem_size)
|
||||
+ return NULL;
|
||||
+
|
||||
+ return wcss->mem_region + offset;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * share_upd_bootinfo_to_q6() - Share userpd boot info to Q6 root pd
|
||||
+ * @rproc: rproc handle
|
||||
+ *
|
||||
+ * Q6 needs user pd parameters like loadaddress and
|
||||
+ * PIL size to authenticate user pd with underlying
|
||||
+ * security software. If authenticatoin success then
|
||||
+ * only Q6 spawns user pd and sends spawn ack to rproc
|
||||
+ * driver. This API is passing userpd boot info to Q6
|
||||
+ * over SMEM.
|
||||
+ *
|
||||
+ * User pd boot-info format mentioned below
|
||||
+ * <Version> <No of elements passing over smem> <Header type> <Header Length>
|
||||
+ * <Process Id> <Load address> <firmware mem Size>
|
||||
+ *
|
||||
+ * Returns 0 on success else negative value on failure.
|
||||
+ */
|
||||
+static int share_upd_bootinfo_to_q6(struct rproc *rproc)
|
||||
+{
|
||||
+ int ret;
|
||||
+ size_t size;
|
||||
+ u16 cnt = 0, version;
|
||||
+ void *ptr;
|
||||
+ struct q6_wcss *wcss = rproc->priv, *upd_wcss;
|
||||
+ struct rproc *upd_rproc;
|
||||
+ struct userpd_boot_info upd_bootinfo = {0};
|
||||
+ const struct firmware *fw;
|
||||
+
|
||||
+ ret = qcom_smem_alloc(REMOTE_PID, UPD_BOOT_INFO_SMEM_ID,
|
||||
+ UPD_BOOT_INFO_SMEM_SIZE);
|
||||
+ if (ret && ret != -EEXIST) {
|
||||
+ dev_err(wcss->dev,
|
||||
+ "failed to allocate q6 bootinfo smem segment\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ptr = qcom_smem_get(REMOTE_PID, UPD_BOOT_INFO_SMEM_ID, &size);
|
||||
+ if (IS_ERR(ptr) || size != UPD_BOOT_INFO_SMEM_SIZE) {
|
||||
+ dev_err(wcss->dev,
|
||||
+ "Unable to acquire smp2p item(%d) ret:%ld\n",
|
||||
+ UPD_BOOT_INFO_SMEM_ID, PTR_ERR(ptr));
|
||||
+ return PTR_ERR(ptr);
|
||||
+ }
|
||||
+
|
||||
+ /*Version*/
|
||||
+ version = VERSION2;
|
||||
+ memcpy_toio(ptr, &version, sizeof(version));
|
||||
+ ptr += sizeof(version);
|
||||
+
|
||||
+ list_for_each_entry(upd_rproc, &upd_rproc_list, node)
|
||||
+ cnt++;
|
||||
+
|
||||
+ /* No of elements */
|
||||
+ cnt = (sizeof(upd_bootinfo) * cnt);
|
||||
+ memcpy_toio(ptr, &cnt, sizeof(u16));
|
||||
+ ptr += sizeof(u16);
|
||||
+
|
||||
+ list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
|
||||
+ upd_wcss = upd_rproc->priv;
|
||||
+
|
||||
+ /* TYPE */
|
||||
+ upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
|
||||
+
|
||||
+ /* LENGTH */
|
||||
+ upd_bootinfo.header.length =
|
||||
+ sizeof(upd_bootinfo) - sizeof(upd_bootinfo.header);
|
||||
+
|
||||
+ /* Process ID */
|
||||
+ upd_bootinfo.pid = upd_wcss->pd_asid + 1;
|
||||
+
|
||||
+ ret = request_firmware(&fw, upd_rproc->firmware, upd_wcss->dev);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(upd_wcss->dev, "request_firmware failed: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Load address */
|
||||
+ upd_bootinfo.bootaddr = rproc_get_boot_addr(upd_rproc, fw);
|
||||
+
|
||||
+ /* Firmware mem size */
|
||||
+ upd_bootinfo.data_size = qcom_mdt_get_size(fw);
|
||||
+
|
||||
+ release_firmware(fw);
|
||||
+
|
||||
+ /* copy into smem */
|
||||
+ memcpy_toio(ptr, &upd_bootinfo, sizeof(upd_bootinfo));
|
||||
+ ptr += sizeof(upd_bootinfo);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int q6_wcss_load(struct rproc *rproc, const struct firmware *fw)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ const struct firmware *fw_hdl;
|
||||
+ int ret;
|
||||
+ const struct wcss_data *desc = wcss->desc;
|
||||
+ int loop;
|
||||
+
|
||||
+ /* Share user pd boot info to Q6 remote processor */
|
||||
+ if (desc->share_upd_info_to_q6) {
|
||||
+ ret = share_upd_bootinfo_to_q6(rproc);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev,
|
||||
+ "user pd boot info sharing with q6 failed %d\n",
|
||||
+ ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = qcom_mdt_load(wcss->dev, fw, rproc->firmware,
|
||||
+ desc->pasid, wcss->mem_region,
|
||||
+ wcss->mem_phys, wcss->mem_size,
|
||||
+ &wcss->mem_reloc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (loop = 1; loop < MAX_FIRMWARE; loop++) {
|
||||
+ if (!wcss->firmware[loop])
|
||||
+ continue;
|
||||
+
|
||||
+ ret = request_firmware(&fw_hdl, wcss->firmware[loop],
|
||||
+ wcss->dev);
|
||||
+ if (ret)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = qcom_mdt_load_no_init(wcss->dev, fw_hdl,
|
||||
+ wcss->firmware[loop], 0,
|
||||
+ wcss->mem_region,
|
||||
+ wcss->mem_phys,
|
||||
+ wcss->mem_size,
|
||||
+ &wcss->mem_reloc);
|
||||
+
|
||||
+ release_firmware(fw_hdl);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev,
|
||||
+ "can't load %s ret:%d\n", wcss->firmware[loop], ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * wcss_pd_load() - Load WCSS user pd firmware
|
||||
+ * @rproc: rproc handle
|
||||
+ * @fw: firmware handle
|
||||
+ *
|
||||
+ * User pd get services from root pd. So first
|
||||
+ * bring up root pd and then load userpd firmware.
|
||||
+ * ---------------------------------------------
|
||||
+ *
|
||||
+ * -----------
|
||||
+ * |-------->| User PD1 |
|
||||
+ * | -----------
|
||||
+ * |
|
||||
+ * |
|
||||
+ * ----- | -----------
|
||||
+ * | Q6 |---------------->| User Pd2 |
|
||||
+ * ----- | -----------
|
||||
+ * |
|
||||
+ * |
|
||||
+ * | -----------
|
||||
+ * |--------->| User Pd3 |
|
||||
+ * -----------
|
||||
+ * ----------------------------------------------
|
||||
+ *
|
||||
+ */
|
||||
+static int wcss_pd_load(struct rproc *rproc, const struct firmware *fw)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
|
||||
+ u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = rproc_boot(rpd_rproc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return qcom_mdt_load(wcss->dev, fw, rproc->firmware,
|
||||
+ pasid, wcss->mem_region,
|
||||
+ wcss->mem_phys, wcss->mem_size,
|
||||
+ &wcss->mem_reloc);
|
||||
+}
|
||||
+
|
||||
+static unsigned long q6_wcss_panic(struct rproc *rproc)
|
||||
+{
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+
|
||||
+ return qcom_q6v5_panic(&wcss->q6);
|
||||
+}
|
||||
+
|
||||
+static const struct rproc_ops wcss_ops = {
|
||||
+ .start = wcss_pd_start,
|
||||
+ .stop = wcss_pd_stop,
|
||||
+ .load = wcss_pd_load,
|
||||
+ .get_boot_addr = rproc_elf_get_boot_addr,
|
||||
+};
|
||||
+
|
||||
+static const struct rproc_ops q6_wcss_ops = {
|
||||
+ .start = q6_wcss_start,
|
||||
+ .stop = q6_wcss_stop,
|
||||
+ .da_to_va = q6_wcss_da_to_va,
|
||||
+ .load = q6_wcss_load,
|
||||
+ .get_boot_addr = rproc_elf_get_boot_addr,
|
||||
+ .panic = q6_wcss_panic,
|
||||
+};
|
||||
+
|
||||
+static int q6_alloc_memory_region(struct q6_wcss *wcss)
|
||||
+{
|
||||
+ struct reserved_mem *rmem = NULL;
|
||||
+ struct device_node *node;
|
||||
+ struct device *dev = wcss->dev;
|
||||
+
|
||||
+ if (wcss->version == Q6_IPQ) {
|
||||
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
+ if (node)
|
||||
+ rmem = of_reserved_mem_lookup(node);
|
||||
+
|
||||
+ of_node_put(node);
|
||||
+
|
||||
+ if (!rmem) {
|
||||
+ dev_err(dev, "unable to acquire memory-region\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ struct rproc *rpd_rproc = dev_get_drvdata(dev->parent);
|
||||
+ struct q6_wcss *rpd_wcss = rpd_rproc->priv;
|
||||
+
|
||||
+ wcss->mem_phys = rpd_wcss->mem_phys;
|
||||
+ wcss->mem_reloc = rpd_wcss->mem_reloc;
|
||||
+ wcss->mem_size = rpd_wcss->mem_size;
|
||||
+ wcss->mem_region = rpd_wcss->mem_region;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ wcss->mem_phys = rmem->base;
|
||||
+ wcss->mem_reloc = rmem->base;
|
||||
+ wcss->mem_size = rmem->size;
|
||||
+ wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
|
||||
+ if (!wcss->mem_region) {
|
||||
+ dev_err(dev, "unable to map memory region: %pa+%pa\n",
|
||||
+ &rmem->base, &rmem->size);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int q6_get_inbound_irq(struct qcom_q6v5 *q6,
|
||||
+ struct platform_device *pdev,
|
||||
+ const char *int_name,
|
||||
+ int index, int *pirq,
|
||||
+ irqreturn_t (*handler)(int irq, void *data))
|
||||
+{
|
||||
+ int ret, irq;
|
||||
+ char *interrupt, *tmp = (char *)int_name;
|
||||
+ struct q6_wcss *wcss = q6->rproc->priv;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, index);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ *pirq = irq;
|
||||
+
|
||||
+ interrupt = devm_kzalloc(&pdev->dev, BUF_SIZE, GFP_KERNEL);
|
||||
+ if (!interrupt)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d_%s", wcss->pd_asid, tmp);
|
||||
+
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, *pirq,
|
||||
+ NULL, handler,
|
||||
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
+ interrupt, q6);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(&pdev->dev, ret,
|
||||
+ "failed to acquire %s irq\n", interrupt);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int q6_get_outbound_irq(struct qcom_q6v5 *q6,
|
||||
+ struct platform_device *pdev,
|
||||
+ const char *int_name)
|
||||
+{
|
||||
+ struct qcom_smem_state *tmp_state;
|
||||
+ unsigned bit;
|
||||
+
|
||||
+ tmp_state = qcom_smem_state_get(&pdev->dev, int_name, &bit);
|
||||
+ if (IS_ERR(tmp_state))
|
||||
+ return dev_err_probe(&pdev->dev, PTR_ERR(tmp_state),
|
||||
+ "failed to acquire %s state\n", int_name);
|
||||
+
|
||||
+ if (!strcmp(int_name, "stop")) {
|
||||
+ q6->state = tmp_state;
|
||||
+ q6->stop_bit = bit;
|
||||
+ } else if (!strcmp(int_name, "spawn")) {
|
||||
+ q6->spawn_state = tmp_state;
|
||||
+ q6->spawn_bit = bit;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int init_irq(struct qcom_q6v5 *q6,
|
||||
+ struct platform_device *pdev, struct rproc *rproc,
|
||||
+ int crash_reason, const char *load_state,
|
||||
+ void (*handover)(struct qcom_q6v5 *q6))
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+
|
||||
+ q6->rproc = rproc;
|
||||
+ q6->dev = &pdev->dev;
|
||||
+ q6->crash_reason = crash_reason;
|
||||
+ q6->handover = handover;
|
||||
+
|
||||
+ init_completion(&q6->start_done);
|
||||
+ init_completion(&q6->stop_done);
|
||||
+ init_completion(&q6->spawn_done);
|
||||
+
|
||||
+ ret = q6_get_outbound_irq(q6, pdev, "stop");
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = q6_get_outbound_irq(q6, pdev, "spawn");
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Get pd_asid to prepare interrupt names */
|
||||
+ wcss->pd_asid = qcom_get_pd_asid(rproc);
|
||||
+
|
||||
+ ret = q6_get_inbound_irq(q6, pdev, "fatal", 0, &q6->fatal_irq,
|
||||
+ q6v5_fatal_interrupt);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = q6_get_inbound_irq(q6, pdev, "ready", 1, &q6->ready_irq,
|
||||
+ q6v5_ready_interrupt);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = q6_get_inbound_irq(q6, pdev, "stop-ack", 3, &q6->stop_irq,
|
||||
+ q6v5_stop_interrupt);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = q6_get_inbound_irq(q6, pdev, "spawn-ack", 2, &q6->spawn_irq,
|
||||
+ q6v5_spawn_interrupt);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void q6_release_resources(void)
|
||||
+{
|
||||
+ struct rproc *upd_rproc;
|
||||
+
|
||||
+ /* Release userpd resources */
|
||||
+ list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
|
||||
+ rproc_del(upd_rproc);
|
||||
+ rproc_free(upd_rproc);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int q6_register_userpd(struct platform_device *pdev,
|
||||
+ struct device_node *userpd_np)
|
||||
+{
|
||||
+ struct q6_wcss *wcss;
|
||||
+ struct rproc *rproc = NULL;
|
||||
+ int ret;
|
||||
+ struct platform_device *userpd_pdev;
|
||||
+ const char *firmware_name = NULL;
|
||||
+ const char *label = NULL;
|
||||
+
|
||||
+ ret = of_property_read_string(userpd_np, "firmware-name",
|
||||
+ &firmware_name);
|
||||
+ if (ret < 0) {
|
||||
+ /* All userpd's who want to register as rproc must have firmware.
|
||||
+ * Other than userpd like glink they don't need any firmware.
|
||||
+ * So for glink child simply return success.
|
||||
+ */
|
||||
+ if (ret == -EINVAL) {
|
||||
+ /* Confirming userpd_np is glink node or not */
|
||||
+ if (!of_property_read_string(userpd_np, "label", &label))
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&pdev->dev, "%s node found\n", userpd_np->name);
|
||||
+
|
||||
+ userpd_pdev = of_platform_device_create(userpd_np, userpd_np->name,
|
||||
+ &pdev->dev);
|
||||
+ if (!userpd_pdev)
|
||||
+ return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
+ "failed to create %s platform device\n",
|
||||
+ userpd_np->name);
|
||||
+
|
||||
+ userpd_pdev->dev.driver = pdev->dev.driver;
|
||||
+ rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
|
||||
+ firmware_name, sizeof(*wcss));
|
||||
+ if (!rproc) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto free_rproc;
|
||||
+ }
|
||||
+
|
||||
+ wcss = rproc->priv;
|
||||
+ wcss->dev = &userpd_pdev->dev;
|
||||
+ wcss->version = WCSS_IPQ;
|
||||
+
|
||||
+ ret = q6_alloc_memory_region(wcss);
|
||||
+ if (ret)
|
||||
+ goto free_rproc;
|
||||
+
|
||||
+ ret = init_irq(&wcss->q6, userpd_pdev, rproc,
|
||||
+ WCSS_CRASH_REASON, NULL, NULL);
|
||||
+ if (ret)
|
||||
+ goto free_rproc;
|
||||
+
|
||||
+ rproc->auto_boot = false;
|
||||
+ ret = rproc_add(rproc);
|
||||
+ if (ret)
|
||||
+ goto free_rproc;
|
||||
+
|
||||
+ list_add(&rproc->node, &upd_rproc_list);
|
||||
+ platform_set_drvdata(userpd_pdev, rproc);
|
||||
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, userpd_pdev->name);
|
||||
+ return 0;
|
||||
+
|
||||
+free_rproc:
|
||||
+ kfree(rproc);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int q6_wcss_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ const struct wcss_data *desc;
|
||||
+ struct q6_wcss *wcss;
|
||||
+ struct rproc *rproc;
|
||||
+ int ret;
|
||||
+ const char **firmware;
|
||||
+ struct device_node *userpd_np;
|
||||
+ const struct rproc_ops *ops = &q6_wcss_ops;
|
||||
+
|
||||
+ desc = of_device_get_match_data(&pdev->dev);
|
||||
+ if (!desc)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ firmware = devm_kcalloc(&pdev->dev, MAX_FIRMWARE,
|
||||
+ sizeof(*firmware), GFP_KERNEL);
|
||||
+ if (!firmware)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = of_property_read_string_array(pdev->dev.of_node, "firmware-name",
|
||||
+ firmware, MAX_FIRMWARE);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ rproc = rproc_alloc(&pdev->dev, pdev->name, ops,
|
||||
+ firmware[0], sizeof(*wcss));
|
||||
+ if (!rproc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ wcss = rproc->priv;
|
||||
+ wcss->dev = &pdev->dev;
|
||||
+ wcss->desc = desc;
|
||||
+ wcss->firmware = firmware;
|
||||
+ wcss->version = Q6_IPQ;
|
||||
+
|
||||
+ ret = q6_alloc_memory_region(wcss);
|
||||
+ if (ret)
|
||||
+ goto free_rproc;
|
||||
+
|
||||
+ ret = qcom_q6v5_init(&wcss->q6, pdev, rproc,
|
||||
+ WCSS_CRASH_REASON, NULL, NULL);
|
||||
+ if (ret)
|
||||
+ goto free_rproc;
|
||||
+
|
||||
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
|
||||
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
|
||||
+
|
||||
+ rproc->auto_boot = false;
|
||||
+ ret = rproc_add(rproc);
|
||||
+ if (ret)
|
||||
+ goto free_rproc;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, rproc);
|
||||
+
|
||||
+ /* Iterate over userpd child's and register with rproc */
|
||||
+ for_each_available_child_of_node(pdev->dev.of_node, userpd_np) {
|
||||
+ ret = q6_register_userpd(pdev, userpd_np);
|
||||
+ if (ret) {
|
||||
+ /* release resources of successfully allocated userpd rproc's */
|
||||
+ q6_release_resources();
|
||||
+ return dev_err_probe(&pdev->dev, ret,
|
||||
+ "Failed to register userpd(%s)\n",
|
||||
+ userpd_np->name);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
+free_rproc:
|
||||
+ rproc_free(rproc);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int q6_wcss_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct rproc *rproc = platform_get_drvdata(pdev);
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+
|
||||
+ qcom_q6v5_deinit(&wcss->q6);
|
||||
+
|
||||
+ rproc_del(rproc);
|
||||
+ rproc_free(rproc);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct wcss_data q6_ipq5332_res_init = {
|
||||
+ .pasid = MPD_WCNSS_PAS_ID,
|
||||
+ .share_upd_info_to_q6 = true,
|
||||
+};
|
||||
+
|
||||
+static const struct wcss_data q6_ipq9574_res_init = {
|
||||
+ .pasid = WCNSS_PAS_ID,
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id q6_wcss_of_match[] = {
|
||||
+ { .compatible = "qcom,ipq5332-q6-mpd", .data = &q6_ipq5332_res_init },
|
||||
+ { .compatible = "qcom,ipq9574-q6-mpd", .data = &q6_ipq9574_res_init },
|
||||
+ { },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, q6_wcss_of_match);
|
||||
+
|
||||
+static struct platform_driver q6_wcss_driver = {
|
||||
+ .probe = q6_wcss_probe,
|
||||
+ .remove = q6_wcss_remove,
|
||||
+ .driver = {
|
||||
+ .name = "qcom-q6-mpd",
|
||||
+ .of_match_table = q6_wcss_of_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(q6_wcss_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Hexagon WCSS Multipd Peripheral Image Loader");
|
||||
+MODULE_LICENSE("GPL v2");
|
@ -0,0 +1,321 @@
|
||||
From 6c66dff196cbba8515380110dd3599cde31dd896 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH 1/2] rproc: qcom_q6v5_mpd: split q6_wcss to rootpd and
|
||||
userpd
|
||||
|
||||
Split the q6_wcss structure and create a separate userpd struct to clearly
|
||||
differentiate between the process to bring up the QDSP6 processor vs
|
||||
process(es) to bring up the Wifi radio(s) (WCSS) for better readability.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/remoteproc/qcom_q6v5_mpd.c | 126 +++++++++++++----------------
|
||||
1 file changed, 56 insertions(+), 70 deletions(-)
|
||||
|
||||
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
@@ -44,10 +44,6 @@
|
||||
#define VERSION2 2
|
||||
|
||||
static LIST_HEAD(upd_rproc_list);
|
||||
-enum {
|
||||
- Q6_IPQ,
|
||||
- WCSS_IPQ,
|
||||
-};
|
||||
|
||||
/**
|
||||
* struct userpd_boot_info_header - header of user pd bootinfo
|
||||
@@ -82,10 +78,15 @@ struct q6_wcss {
|
||||
phys_addr_t mem_reloc;
|
||||
void *mem_region;
|
||||
size_t mem_size;
|
||||
- u8 pd_asid;
|
||||
const struct wcss_data *desc;
|
||||
const char **firmware;
|
||||
- u32 version;
|
||||
+};
|
||||
+
|
||||
+struct userpd {
|
||||
+ u8 pd_asid;
|
||||
+ struct device *dev;
|
||||
+ struct qcom_rproc_ssr ssr_subdev;
|
||||
+ struct qcom_q6v5 q6;
|
||||
};
|
||||
|
||||
struct wcss_data {
|
||||
@@ -101,8 +102,8 @@ struct wcss_data {
|
||||
*/
|
||||
static u8 qcom_get_pd_asid(struct rproc *rproc)
|
||||
{
|
||||
- struct q6_wcss *wcss = rproc->priv;
|
||||
- u8 bit = wcss->q6.spawn_bit;
|
||||
+ struct userpd *upd = rproc->priv;
|
||||
+ u8 bit = upd->q6.spawn_bit;
|
||||
|
||||
return bit / 8;
|
||||
}
|
||||
@@ -131,37 +132,37 @@ static int q6_wcss_start(struct rproc *r
|
||||
static int q6_wcss_spawn_pd(struct rproc *rproc)
|
||||
{
|
||||
int ret;
|
||||
- struct q6_wcss *wcss = rproc->priv;
|
||||
+ struct userpd *upd = rproc->priv;
|
||||
|
||||
- ret = qcom_q6v5_request_spawn(&wcss->q6);
|
||||
+ ret = qcom_q6v5_request_spawn(&upd->q6);
|
||||
if (ret == -ETIMEDOUT) {
|
||||
- dev_err(wcss->dev, "%s spawn timedout\n", rproc->name);
|
||||
+ dev_err(upd->dev, "%s spawn timedout\n", rproc->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ret = qcom_q6v5_wait_for_start(&wcss->q6, msecs_to_jiffies(10000));
|
||||
+ ret = qcom_q6v5_wait_for_start(&upd->q6, msecs_to_jiffies(10000));
|
||||
if (ret == -ETIMEDOUT) {
|
||||
- dev_err(wcss->dev, "%s start timedout\n", rproc->name);
|
||||
- wcss->q6.running = false;
|
||||
+ dev_err(upd->dev, "%s start timedout\n", rproc->name);
|
||||
+ upd->q6.running = false;
|
||||
return ret;
|
||||
}
|
||||
- wcss->q6.running = true;
|
||||
+ upd->q6.running = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcss_pd_start(struct rproc *rproc)
|
||||
{
|
||||
- struct q6_wcss *wcss = rproc->priv;
|
||||
- u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
|
||||
+ struct userpd *upd = rproc->priv;
|
||||
+ u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
|
||||
int ret;
|
||||
|
||||
ret = qcom_scm_msa_lock(pasid);
|
||||
if (ret) {
|
||||
- dev_err(wcss->dev, "failed to power up pd\n");
|
||||
+ dev_err(upd->dev, "failed to power up pd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
- if (wcss->q6.spawn_bit) {
|
||||
+ if (upd->q6.spawn_bit) {
|
||||
ret = q6_wcss_spawn_pd(rproc);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -213,22 +214,22 @@ static int q6_wcss_stop(struct rproc *rp
|
||||
*/
|
||||
static int wcss_pd_stop(struct rproc *rproc)
|
||||
{
|
||||
- struct q6_wcss *wcss = rproc->priv;
|
||||
- struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
|
||||
- u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
|
||||
+ struct userpd *upd = rproc->priv;
|
||||
+ struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
|
||||
+ u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
|
||||
int ret;
|
||||
|
||||
- if (rproc->state != RPROC_CRASHED && wcss->q6.stop_bit) {
|
||||
- ret = qcom_q6v5_request_stop(&wcss->q6, NULL);
|
||||
+ if (rproc->state != RPROC_CRASHED && upd->q6.stop_bit) {
|
||||
+ ret = qcom_q6v5_request_stop(&upd->q6, NULL);
|
||||
if (ret) {
|
||||
- dev_err(&rproc->dev, "pd not stopped\n");
|
||||
+ dev_err(upd->dev, "pd not stopped\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = qcom_scm_msa_unlock(pasid);
|
||||
if (ret) {
|
||||
- dev_err(wcss->dev, "failed to power down pd\n");
|
||||
+ dev_err(upd->dev, "failed to power down pd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -273,7 +274,8 @@ static int share_upd_bootinfo_to_q6(stru
|
||||
size_t size;
|
||||
u16 cnt = 0, version;
|
||||
void *ptr;
|
||||
- struct q6_wcss *wcss = rproc->priv, *upd_wcss;
|
||||
+ struct q6_wcss *wcss = rproc->priv;
|
||||
+ struct userpd *upd;
|
||||
struct rproc *upd_rproc;
|
||||
struct userpd_boot_info upd_bootinfo = {0};
|
||||
const struct firmware *fw;
|
||||
@@ -308,7 +310,7 @@ static int share_upd_bootinfo_to_q6(stru
|
||||
ptr += sizeof(u16);
|
||||
|
||||
list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
|
||||
- upd_wcss = upd_rproc->priv;
|
||||
+ upd = upd_rproc->priv;
|
||||
|
||||
/* TYPE */
|
||||
upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
|
||||
@@ -318,11 +320,11 @@ static int share_upd_bootinfo_to_q6(stru
|
||||
sizeof(upd_bootinfo) - sizeof(upd_bootinfo.header);
|
||||
|
||||
/* Process ID */
|
||||
- upd_bootinfo.pid = upd_wcss->pd_asid + 1;
|
||||
+ upd_bootinfo.pid = upd->pd_asid + 1;
|
||||
|
||||
- ret = request_firmware(&fw, upd_rproc->firmware, upd_wcss->dev);
|
||||
+ ret = request_firmware(&fw, upd_rproc->firmware, upd->dev);
|
||||
if (ret < 0) {
|
||||
- dev_err(upd_wcss->dev, "request_firmware failed: %d\n", ret);
|
||||
+ dev_err(upd->dev, "request_firmware failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -421,19 +423,20 @@ static int q6_wcss_load(struct rproc *rp
|
||||
*/
|
||||
static int wcss_pd_load(struct rproc *rproc, const struct firmware *fw)
|
||||
{
|
||||
- struct q6_wcss *wcss = rproc->priv;
|
||||
- struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
|
||||
- u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
|
||||
+ struct userpd *upd = rproc->priv;
|
||||
+ struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
|
||||
+ struct q6_wcss *wcss = rpd_rproc->priv;
|
||||
+ u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
|
||||
int ret;
|
||||
|
||||
ret = rproc_boot(rpd_rproc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return qcom_mdt_load(wcss->dev, fw, rproc->firmware,
|
||||
+ return qcom_mdt_load(upd->dev, fw, rproc->firmware,
|
||||
pasid, wcss->mem_region,
|
||||
wcss->mem_phys, wcss->mem_size,
|
||||
- &wcss->mem_reloc);
|
||||
+ NULL);
|
||||
}
|
||||
|
||||
static unsigned long q6_wcss_panic(struct rproc *rproc)
|
||||
@@ -465,26 +468,15 @@ static int q6_alloc_memory_region(struct
|
||||
struct device_node *node;
|
||||
struct device *dev = wcss->dev;
|
||||
|
||||
- if (wcss->version == Q6_IPQ) {
|
||||
- node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
- if (node)
|
||||
- rmem = of_reserved_mem_lookup(node);
|
||||
-
|
||||
- of_node_put(node);
|
||||
-
|
||||
- if (!rmem) {
|
||||
- dev_err(dev, "unable to acquire memory-region\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
- } else {
|
||||
- struct rproc *rpd_rproc = dev_get_drvdata(dev->parent);
|
||||
- struct q6_wcss *rpd_wcss = rpd_rproc->priv;
|
||||
-
|
||||
- wcss->mem_phys = rpd_wcss->mem_phys;
|
||||
- wcss->mem_reloc = rpd_wcss->mem_reloc;
|
||||
- wcss->mem_size = rpd_wcss->mem_size;
|
||||
- wcss->mem_region = rpd_wcss->mem_region;
|
||||
- return 0;
|
||||
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
+ if (node)
|
||||
+ rmem = of_reserved_mem_lookup(node);
|
||||
+
|
||||
+ of_node_put(node);
|
||||
+
|
||||
+ if (!rmem) {
|
||||
+ dev_err(dev, "unable to acquire memory-region\n");
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
wcss->mem_phys = rmem->base;
|
||||
@@ -508,7 +500,7 @@ static int q6_get_inbound_irq(struct qco
|
||||
{
|
||||
int ret, irq;
|
||||
char *interrupt, *tmp = (char *)int_name;
|
||||
- struct q6_wcss *wcss = q6->rproc->priv;
|
||||
+ struct userpd *upd = q6->rproc->priv;
|
||||
|
||||
irq = platform_get_irq(pdev, index);
|
||||
if (irq < 0)
|
||||
@@ -520,7 +512,7 @@ static int q6_get_inbound_irq(struct qco
|
||||
if (!interrupt)
|
||||
return -ENOMEM;
|
||||
|
||||
- snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d_%s", wcss->pd_asid, tmp);
|
||||
+ snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d_%s", upd->pd_asid, tmp);
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, *pirq,
|
||||
NULL, handler,
|
||||
@@ -561,7 +553,7 @@ static int init_irq(struct qcom_q6v5 *q6
|
||||
void (*handover)(struct qcom_q6v5 *q6))
|
||||
{
|
||||
int ret;
|
||||
- struct q6_wcss *wcss = rproc->priv;
|
||||
+ struct userpd *upd = rproc->priv;
|
||||
|
||||
q6->rproc = rproc;
|
||||
q6->dev = &pdev->dev;
|
||||
@@ -581,7 +573,7 @@ static int init_irq(struct qcom_q6v5 *q6
|
||||
return ret;
|
||||
|
||||
/* Get pd_asid to prepare interrupt names */
|
||||
- wcss->pd_asid = qcom_get_pd_asid(rproc);
|
||||
+ upd->pd_asid = qcom_get_pd_asid(rproc);
|
||||
|
||||
ret = q6_get_inbound_irq(q6, pdev, "fatal", 0, &q6->fatal_irq,
|
||||
q6v5_fatal_interrupt);
|
||||
@@ -619,7 +611,7 @@ static void q6_release_resources(void)
|
||||
static int q6_register_userpd(struct platform_device *pdev,
|
||||
struct device_node *userpd_np)
|
||||
{
|
||||
- struct q6_wcss *wcss;
|
||||
+ struct userpd *upd;
|
||||
struct rproc *rproc = NULL;
|
||||
int ret;
|
||||
struct platform_device *userpd_pdev;
|
||||
@@ -652,21 +644,16 @@ static int q6_register_userpd(struct pla
|
||||
|
||||
userpd_pdev->dev.driver = pdev->dev.driver;
|
||||
rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
|
||||
- firmware_name, sizeof(*wcss));
|
||||
+ firmware_name, sizeof(*upd));
|
||||
if (!rproc) {
|
||||
ret = -ENOMEM;
|
||||
goto free_rproc;
|
||||
}
|
||||
|
||||
- wcss = rproc->priv;
|
||||
- wcss->dev = &userpd_pdev->dev;
|
||||
- wcss->version = WCSS_IPQ;
|
||||
-
|
||||
- ret = q6_alloc_memory_region(wcss);
|
||||
- if (ret)
|
||||
- goto free_rproc;
|
||||
+ upd = rproc->priv;
|
||||
+ upd->dev = &userpd_pdev->dev;
|
||||
|
||||
- ret = init_irq(&wcss->q6, userpd_pdev, rproc,
|
||||
+ ret = init_irq(&upd->q6, userpd_pdev, rproc,
|
||||
WCSS_CRASH_REASON, NULL, NULL);
|
||||
if (ret)
|
||||
goto free_rproc;
|
||||
@@ -678,7 +665,7 @@ static int q6_register_userpd(struct pla
|
||||
|
||||
list_add(&rproc->node, &upd_rproc_list);
|
||||
platform_set_drvdata(userpd_pdev, rproc);
|
||||
- qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, userpd_pdev->name);
|
||||
+ qcom_add_ssr_subdev(rproc, &upd->ssr_subdev, userpd_pdev->name);
|
||||
return 0;
|
||||
|
||||
free_rproc:
|
||||
@@ -719,7 +706,6 @@ static int q6_wcss_probe(struct platform
|
||||
wcss->dev = &pdev->dev;
|
||||
wcss->desc = desc;
|
||||
wcss->firmware = firmware;
|
||||
- wcss->version = Q6_IPQ;
|
||||
|
||||
ret = q6_alloc_memory_region(wcss);
|
||||
if (ret)
|
@ -0,0 +1,206 @@
|
||||
From 0fa7bdb855247b738d1d227d6f4b3417ebdf21a8 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH 2/2] remoteproc: qcom_q6v5_mpd: fix incorrent use of
|
||||
rproc->node
|
||||
|
||||
1.817524] list_add corruption. next->prev should be prev (ffffffc0814bbfc8), but was ffffffc0814bc358. (next=ffffff8003b56800).
|
||||
[ 1.822435] WARNING: CPU: 1 PID: 24 at lib/list_debug.c:29 __list_add_valid_or_report+0x8c/0xdc
|
||||
[ 1.833923] Modules linked in:
|
||||
[ 1.842425] CPU: 1 PID: 24 Comm: kworker/u4:1 Not tainted 6.6.47 #0
|
||||
[ 1.845552] Hardware name: Qualcomm MP03 (DT)
|
||||
[ 1.851716] Workqueue: events_unbound deferred_probe_work_func
|
||||
[ 1.856229] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
|
||||
[ 1.861959] pc : __list_add_valid_or_report+0x8c/0xdc
|
||||
[ 1.868816] lr : __list_add_valid_or_report+0x8c/0xdc
|
||||
[ 1.874022] sp : ffffffc081603a50
|
||||
[ 1.879055] x29: ffffffc081603a50 x28: ffffff8000fa2810 x27: ffffff8003cba800
|
||||
[ 1.882358] x26: ffffff8000fa2800 x25: ffffff8003cbac80 x24: 0000000000000000
|
||||
[ 1.889476] x23: ffffffc08088b968 x22: ffffffc0814bb000 x21: ffffffc0814bbfc8
|
||||
[ 1.896593] x20: ffffffc08088b8e8 x19: ffffff8003cba800 x18: 00000000000000b1
|
||||
[ 1.903713] x17: 3863666262343138 x16: 3063666666666666 x15: ffffffc081416e20
|
||||
[ 1.910830] x14: 0000000000000213 x13: 00000000000000b1 x12: 00000000ffffffea
|
||||
[ 1.917948] x11: 00000000ffffefff x10: ffffffc08146ee20 x9 : ffffffc081416dc8
|
||||
[ 1.925066] x8 : 0000000000017fe8 x7 : c0000000ffffefff x6 : 0000000000057fa8
|
||||
[ 1.932184] x5 : 0000000000000fff x4 : 0000000000000000 x3 : ffffffc081603850
|
||||
[ 1.939302] x2 : ffffffc081416d60 x1 : ffffffc081416d60 x0 : 0000000000000075
|
||||
[ 1.946422] Call trace:
|
||||
[ 1.953535] __list_add_valid_or_report+0x8c/0xdc
|
||||
[ 1.955793] rproc_add+0x1f4/0x25c
|
||||
[ 1.960653] q6_wcss_probe+0x510/0x634
|
||||
[ 1.963950] platform_probe+0x68/0xc4
|
||||
[ 1.967684] really_probe+0x148/0x2b0
|
||||
[ 1.971417] __driver_probe_device+0x78/0x128
|
||||
[ 1.975063] driver_probe_device+0x40/0xdc
|
||||
[ 1.979402] __device_attach_driver+0xb8/0xf8
|
||||
[ 1.983397] bus_for_each_drv+0x70/0xb8
|
||||
[ 1.987823] __device_attach+0xa0/0x184
|
||||
[ 1.991468] device_initial_probe+0x14/0x20
|
||||
[ 1.995289] bus_probe_device+0xac/0xb0
|
||||
[ 1.999455] deferred_probe_work_func+0xa4/0xec
|
||||
[ 2.003275] process_one_work+0x178/0x2d4
|
||||
[ 2.007788] worker_thread+0x2ec/0x4d8
|
||||
[ 2.011954] kthread+0xdc/0xe0
|
||||
[ 2.015600] ret_from_fork+0x10/0x20
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
---
|
||||
drivers/remoteproc/qcom_q6v5_mpd.c | 53 +++++++++++++++++-------------
|
||||
1 file changed, 30 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#define BUF_SIZE 35
|
||||
|
||||
+#define MAX_UPD 3
|
||||
#define MAX_FIRMWARE 3
|
||||
|
||||
#define RPD_SWID MPD_WCNSS_PAS_ID
|
||||
@@ -43,8 +44,6 @@
|
||||
#define UPD_BOOT_INFO_SMEM_ID 507
|
||||
#define VERSION2 2
|
||||
|
||||
-static LIST_HEAD(upd_rproc_list);
|
||||
-
|
||||
/**
|
||||
* struct userpd_boot_info_header - header of user pd bootinfo
|
||||
* @type: type of bootinfo passing over smem
|
||||
@@ -80,6 +79,7 @@ struct q6_wcss {
|
||||
size_t mem_size;
|
||||
const struct wcss_data *desc;
|
||||
const char **firmware;
|
||||
+ struct userpd *upd[MAX_UPD];
|
||||
};
|
||||
|
||||
struct userpd {
|
||||
@@ -270,13 +270,12 @@ static void *q6_wcss_da_to_va(struct rpr
|
||||
*/
|
||||
static int share_upd_bootinfo_to_q6(struct rproc *rproc)
|
||||
{
|
||||
- int ret;
|
||||
+ int i, ret;
|
||||
size_t size;
|
||||
u16 cnt = 0, version;
|
||||
void *ptr;
|
||||
struct q6_wcss *wcss = rproc->priv;
|
||||
struct userpd *upd;
|
||||
- struct rproc *upd_rproc;
|
||||
struct userpd_boot_info upd_bootinfo = {0};
|
||||
const struct firmware *fw;
|
||||
|
||||
@@ -301,16 +300,19 @@ static int share_upd_bootinfo_to_q6(stru
|
||||
memcpy_toio(ptr, &version, sizeof(version));
|
||||
ptr += sizeof(version);
|
||||
|
||||
- list_for_each_entry(upd_rproc, &upd_rproc_list, node)
|
||||
- cnt++;
|
||||
+ for (i = 0; i < ARRAY_SIZE(wcss->upd); i++)
|
||||
+ if (wcss->upd[i])
|
||||
+ cnt++;
|
||||
|
||||
/* No of elements */
|
||||
cnt = (sizeof(upd_bootinfo) * cnt);
|
||||
memcpy_toio(ptr, &cnt, sizeof(u16));
|
||||
ptr += sizeof(u16);
|
||||
|
||||
- list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
|
||||
- upd = upd_rproc->priv;
|
||||
+ for (i = 0; i < ARRAY_SIZE(wcss->upd); i++) {
|
||||
+ upd = wcss->upd[i];
|
||||
+ if (!upd)
|
||||
+ continue;
|
||||
|
||||
/* TYPE */
|
||||
upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
|
||||
@@ -322,14 +324,14 @@ static int share_upd_bootinfo_to_q6(stru
|
||||
/* Process ID */
|
||||
upd_bootinfo.pid = upd->pd_asid + 1;
|
||||
|
||||
- ret = request_firmware(&fw, upd_rproc->firmware, upd->dev);
|
||||
+ ret = request_firmware(&fw, upd->q6.rproc->firmware, upd->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(upd->dev, "request_firmware failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Load address */
|
||||
- upd_bootinfo.bootaddr = rproc_get_boot_addr(upd_rproc, fw);
|
||||
+ upd_bootinfo.bootaddr = rproc_get_boot_addr(upd->q6.rproc, fw);
|
||||
|
||||
/* Firmware mem size */
|
||||
upd_bootinfo.data_size = qcom_mdt_get_size(fw);
|
||||
@@ -597,18 +599,23 @@ static int init_irq(struct qcom_q6v5 *q6
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void q6_release_resources(void)
|
||||
+static void q6_release_resources(struct q6_wcss *wcss)
|
||||
{
|
||||
- struct rproc *upd_rproc;
|
||||
+ struct userpd *upd;
|
||||
+ int i;
|
||||
|
||||
/* Release userpd resources */
|
||||
- list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
|
||||
- rproc_del(upd_rproc);
|
||||
- rproc_free(upd_rproc);
|
||||
+ for (i = 0; i < ARRAY_SIZE(wcss->upd); i++) {
|
||||
+ upd = wcss->upd[i];
|
||||
+ if (!upd)
|
||||
+ continue;
|
||||
+
|
||||
+ rproc_del(upd->q6.rproc);
|
||||
+ rproc_free(upd->q6.rproc);
|
||||
}
|
||||
}
|
||||
|
||||
-static int q6_register_userpd(struct platform_device *pdev,
|
||||
+static int q6_register_userpd(struct q6_wcss *wcss,
|
||||
struct device_node *userpd_np)
|
||||
{
|
||||
struct userpd *upd;
|
||||
@@ -633,16 +640,16 @@ static int q6_register_userpd(struct pla
|
||||
return ret;
|
||||
}
|
||||
|
||||
- dev_info(&pdev->dev, "%s node found\n", userpd_np->name);
|
||||
+ dev_info(wcss->dev, "%s node found\n", userpd_np->name);
|
||||
|
||||
userpd_pdev = of_platform_device_create(userpd_np, userpd_np->name,
|
||||
- &pdev->dev);
|
||||
+ wcss->dev);
|
||||
if (!userpd_pdev)
|
||||
- return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
+ return dev_err_probe(wcss->dev, -ENODEV,
|
||||
"failed to create %s platform device\n",
|
||||
userpd_np->name);
|
||||
|
||||
- userpd_pdev->dev.driver = pdev->dev.driver;
|
||||
+ userpd_pdev->dev.driver = wcss->dev->driver;
|
||||
rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
|
||||
firmware_name, sizeof(*upd));
|
||||
if (!rproc) {
|
||||
@@ -663,7 +670,7 @@ static int q6_register_userpd(struct pla
|
||||
if (ret)
|
||||
goto free_rproc;
|
||||
|
||||
- list_add(&rproc->node, &upd_rproc_list);
|
||||
+ wcss->upd[upd->pd_asid] = upd;
|
||||
platform_set_drvdata(userpd_pdev, rproc);
|
||||
qcom_add_ssr_subdev(rproc, &upd->ssr_subdev, userpd_pdev->name);
|
||||
return 0;
|
||||
@@ -728,10 +735,10 @@ static int q6_wcss_probe(struct platform
|
||||
|
||||
/* Iterate over userpd child's and register with rproc */
|
||||
for_each_available_child_of_node(pdev->dev.of_node, userpd_np) {
|
||||
- ret = q6_register_userpd(pdev, userpd_np);
|
||||
+ ret = q6_register_userpd(wcss, userpd_np);
|
||||
if (ret) {
|
||||
/* release resources of successfully allocated userpd rproc's */
|
||||
- q6_release_resources();
|
||||
+ q6_release_resources(wcss);
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"Failed to register userpd(%s)\n",
|
||||
userpd_np->name);
|
@ -0,0 +1,128 @@
|
||||
From 6553d598cdb507f7ede020f25da646ba084a23c6 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH] firmware: qcom_scm: support MPD
|
||||
|
||||
Add SCM calls to power up / down the SoC's internal WiFi radio and to
|
||||
load PIL segments to support the MPD architecture.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/firmware/qcom_scm.c | 79 ++++++++++++++++++++++++++
|
||||
drivers/firmware/qcom_scm.h | 3 +
|
||||
include/linux/firmware/qcom/qcom_scm.h | 3 +
|
||||
3 files changed, 85 insertions(+)
|
||||
|
||||
--- a/drivers/firmware/qcom_scm.c
|
||||
+++ b/drivers/firmware/qcom_scm.c
|
||||
@@ -713,6 +713,85 @@ bool qcom_scm_pas_supported(u32 peripher
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_supported);
|
||||
|
||||
/**
|
||||
+ * qcom_scm_internal_wifi_powerup() - Bring up internal wifi
|
||||
+ * @peripheral: peripheral id
|
||||
+ *
|
||||
+ * Return 0 on success.
|
||||
+ */
|
||||
+int qcom_scm_internal_wifi_powerup(u32 peripheral)
|
||||
+{
|
||||
+ struct qcom_scm_desc desc = {
|
||||
+ .svc = QCOM_SCM_SVC_PIL,
|
||||
+ .cmd = QCOM_SCM_INTERNAL_WIFI_POWERUP,
|
||||
+ .arginfo = QCOM_SCM_ARGS(1),
|
||||
+ .args[0] = peripheral,
|
||||
+ .owner = ARM_SMCCC_OWNER_SIP,
|
||||
+ };
|
||||
+ struct qcom_scm_res res;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
+
|
||||
+ return ret ? : res.result[0];
|
||||
+}
|
||||
+EXPORT_SYMBOL(qcom_scm_internal_wifi_powerup);
|
||||
+
|
||||
+/**
|
||||
+ * qcom_scm_internal_wifi_shutdown() - Shut down internal wifi
|
||||
+ * @peripheral: peripheral id
|
||||
+ *
|
||||
+ * Returns 0 on success.
|
||||
+ */
|
||||
+int qcom_scm_internal_wifi_shutdown(u32 peripheral)
|
||||
+{
|
||||
+ struct qcom_scm_desc desc = {
|
||||
+ .svc = QCOM_SCM_SVC_PIL,
|
||||
+ .cmd = QCOM_SCM_INTERNAL_WIFI_SHUTDOWN,
|
||||
+ .arginfo = QCOM_SCM_ARGS(1),
|
||||
+ .args[0] = peripheral,
|
||||
+ .owner = ARM_SMCCC_OWNER_SIP,
|
||||
+ };
|
||||
+ struct qcom_scm_res res;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
+
|
||||
+ return ret ? : res.result[0];
|
||||
+}
|
||||
+EXPORT_SYMBOL(qcom_scm_internal_wifi_shutdown);
|
||||
+
|
||||
+/**
|
||||
+ * qcom_scm_pas_load_segment() - copy userpd PIL segments data to dma blocks
|
||||
+ * @peripheral: peripheral id
|
||||
+ * @segment: segment id
|
||||
+ * @dma: handle of dma region
|
||||
+ * @seg_cnt: no of dma blocks
|
||||
+ *
|
||||
+ * Returns 0 if trustzone successfully loads userpd PIL segments from dma
|
||||
+ * blocks to DDR
|
||||
+ */
|
||||
+int qcom_scm_pas_load_segment(u32 peripheral, int segment, dma_addr_t dma, int seg_cnt)
|
||||
+{
|
||||
+ struct qcom_scm_desc desc = {
|
||||
+ .svc = QCOM_SCM_SVC_PIL,
|
||||
+ .cmd = QCOM_SCM_PIL_PAS_LOAD_SEG,
|
||||
+ .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL),
|
||||
+ .args[0] = peripheral,
|
||||
+ .args[1] = segment,
|
||||
+ .args[2] = dma,
|
||||
+ .args[3] = seg_cnt,
|
||||
+ .owner = ARM_SMCCC_OWNER_SIP,
|
||||
+ };
|
||||
+ struct qcom_scm_res res;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
|
||||
+
|
||||
+ return ret ? : res.result[0];
|
||||
+}
|
||||
+EXPORT_SYMBOL(qcom_scm_pas_load_segment);
|
||||
+
|
||||
+/**
|
||||
* qcom_scm_msa_lock() - Lock given peripheral firmware region as MSA
|
||||
*
|
||||
* @peripheral: peripheral id
|
||||
--- a/drivers/firmware/qcom_scm.h
|
||||
+++ b/drivers/firmware/qcom_scm.h
|
||||
@@ -98,6 +98,9 @@ extern int scm_legacy_call(struct device
|
||||
#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
|
||||
#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
|
||||
#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
|
||||
+#define QCOM_SCM_INTERNAL_WIFI_POWERUP 0x17
|
||||
+#define QCOM_SCM_INTERNAL_WIFI_SHUTDOWN 0x18
|
||||
+#define QCOM_SCM_PIL_PAS_LOAD_SEG 0x19
|
||||
#define QCOM_SCM_MSA_LOCK 0x24
|
||||
#define QCOM_SCM_MSA_UNLOCK 0x25
|
||||
|
||||
--- a/include/linux/firmware/qcom/qcom_scm.h
|
||||
+++ b/include/linux/firmware/qcom/qcom_scm.h
|
||||
@@ -81,6 +81,9 @@ extern int qcom_scm_pas_mem_setup(u32 pe
|
||||
extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
|
||||
extern int qcom_scm_pas_shutdown(u32 peripheral);
|
||||
extern bool qcom_scm_pas_supported(u32 peripheral);
|
||||
+extern int qcom_scm_internal_wifi_powerup(u32 peripheral);
|
||||
+extern int qcom_scm_internal_wifi_shutdown(u32 peripheral);
|
||||
+extern int qcom_scm_pas_load_segment(u32 peripheral, int segment, dma_addr_t dma, int seg_cnt);
|
||||
extern int qcom_scm_msa_lock(u32 peripheral);
|
||||
extern int qcom_scm_msa_unlock(u32 peripheral);
|
||||
|
@ -0,0 +1,199 @@
|
||||
From bf42d84868bc82a9cb334a33930f2d1da24f7070 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH] soc: qcom: mdt_loader: support MPD
|
||||
|
||||
Add support for loading user PD specific PIL segments as required by the
|
||||
MPD architecture.
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
drivers/soc/qcom/mdt_loader.c | 110 ++++++++++++++++++++++++++--
|
||||
include/linux/soc/qcom/mdt_loader.h | 5 ++
|
||||
2 files changed, 110 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/soc/qcom/mdt_loader.c
|
||||
+++ b/drivers/soc/qcom/mdt_loader.c
|
||||
@@ -16,6 +16,16 @@
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/mdt_loader.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+
|
||||
+#include "../../remoteproc/qcom_common.h"
|
||||
+
|
||||
+#define QCOM_MDT_PF_ASID_MASK GENMASK(19, 16)
|
||||
+
|
||||
+struct segment_load_args {
|
||||
+ __le64 addr;
|
||||
+ __le64 blk_size;
|
||||
+};
|
||||
|
||||
static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
|
||||
{
|
||||
@@ -69,6 +79,56 @@ static ssize_t mdt_load_split_segment(vo
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int mdt_load_split_segment_dma(int pas_id, unsigned int segment,
|
||||
+ const struct elf32_phdr *phdrs,
|
||||
+ const char *fw_name,
|
||||
+ struct device *dev)
|
||||
+{
|
||||
+ const struct elf32_phdr *phdr = &phdrs[segment];
|
||||
+ struct segment_load_args *args;
|
||||
+ dma_addr_t *addrs;
|
||||
+ void *ptr;
|
||||
+ dma_addr_t dma_args, dma_addrs, dma_ptr;
|
||||
+ int ret;
|
||||
+
|
||||
+ args = dma_alloc_coherent(dev, sizeof(*args) + sizeof(*addrs), &dma_args, GFP_DMA);
|
||||
+ if (!args) {
|
||||
+ dev_err(dev, "Error in dma alloc regin: %ld\n", sizeof(*args));
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ addrs = (void *) args + sizeof(*args);
|
||||
+ dma_addrs = dma_args + sizeof(*args);
|
||||
+
|
||||
+ ptr = dma_alloc_coherent(dev, phdr->p_filesz, &dma_ptr, GFP_DMA);
|
||||
+ if (!ptr) {
|
||||
+ dev_err(dev, "Error in dma alloc ptr: %d\n", phdr->p_filesz);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ args->addr = dma_addrs;
|
||||
+ args->blk_size = phdr->p_filesz;
|
||||
+
|
||||
+ addrs[0] = dma_ptr;
|
||||
+
|
||||
+ ret = mdt_load_split_segment(ptr, phdrs, segment, fw_name, dev);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "Error in mdt_load_split_segment: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = qcom_scm_pas_load_segment(pas_id, segment, dma_args, 1);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "Error in qcom_scm_pas_load_segment: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dma_free_coherent(dev, phdr->p_filesz, ptr, dma_ptr);
|
||||
+ dma_free_coherent(dev, sizeof(*args) + sizeof(*addrs), args, dma_args);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* qcom_mdt_get_size() - acquire size of the memory region needed to load mdt
|
||||
* @fw: firmware object for the mdt file
|
||||
@@ -295,7 +355,8 @@ static bool qcom_mdt_bins_are_split(cons
|
||||
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
|
||||
const char *fw_name, int pas_id, void *mem_region,
|
||||
phys_addr_t mem_phys, size_t mem_size,
|
||||
- phys_addr_t *reloc_base, bool pas_init)
|
||||
+ phys_addr_t *reloc_base, bool pas_init,
|
||||
+ bool dma_require, int pd_asid)
|
||||
{
|
||||
const struct elf32_phdr *phdrs;
|
||||
const struct elf32_phdr *phdr;
|
||||
@@ -349,6 +410,14 @@ static int __qcom_mdt_load(struct device
|
||||
if (!mdt_phdr_valid(phdr))
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * While doing PD specific reloading, load only that PD
|
||||
+ * specific writeable entries. Skip others
|
||||
+ */
|
||||
+ if (pd_asid && (FIELD_GET(QCOM_MDT_PF_ASID_MASK, phdr->p_flags) != pd_asid ||
|
||||
+ (phdr->p_flags & PF_W) == 0))
|
||||
+ continue;
|
||||
+
|
||||
offset = phdr->p_paddr - mem_reloc;
|
||||
if (offset < 0 || offset + phdr->p_memsz > mem_size) {
|
||||
dev_err(dev, "segment outside memory range\n");
|
||||
@@ -366,7 +435,11 @@ static int __qcom_mdt_load(struct device
|
||||
|
||||
ptr = mem_region + offset;
|
||||
|
||||
- if (phdr->p_filesz && !is_split) {
|
||||
+ if (dma_require && phdr->p_filesz) {
|
||||
+ ret = mdt_load_split_segment_dma(pas_id, i, phdrs, fw_name, dev);
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+ } else if (phdr->p_filesz && !is_split) {
|
||||
/* Firmware is large enough to be non-split */
|
||||
if (phdr->p_offset + phdr->p_filesz > fw->size) {
|
||||
dev_err(dev, "file %s segment %d would be truncated\n",
|
||||
@@ -383,7 +456,7 @@ static int __qcom_mdt_load(struct device
|
||||
break;
|
||||
}
|
||||
|
||||
- if (phdr->p_memsz > phdr->p_filesz)
|
||||
+ if (!dma_require && phdr->p_memsz > phdr->p_filesz)
|
||||
memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
|
||||
}
|
||||
|
||||
@@ -418,7 +491,7 @@ int qcom_mdt_load(struct device *dev, co
|
||||
return ret;
|
||||
|
||||
return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
|
||||
- mem_size, reloc_base, true);
|
||||
+ mem_size, reloc_base, true, false, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_mdt_load);
|
||||
|
||||
@@ -441,9 +514,36 @@ int qcom_mdt_load_no_init(struct device
|
||||
size_t mem_size, phys_addr_t *reloc_base)
|
||||
{
|
||||
return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
|
||||
- mem_size, reloc_base, false);
|
||||
+ mem_size, reloc_base, false, false, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_mdt_load_no_init);
|
||||
|
||||
+/**
|
||||
+ * qcom_mdt_load_pd_seg() - load userpd specific PIL segements
|
||||
+ * @dev: device handle to associate resources with
|
||||
+ * @fw: firmware object for the mdt file
|
||||
+ * @firmware: name of the firmware, for construction of segment file names
|
||||
+ * @pas_id: PAS identifier
|
||||
+ * @mem_region: allocated memory region to load firmware into
|
||||
+ * @mem_phys: physical address of allocated memory region
|
||||
+ * @mem_size: size of the allocated memory region
|
||||
+ * @reloc_base: adjusted physical address after relocation
|
||||
+ *
|
||||
+ * Here userpd PIL segements are stitched with rootpd firmware.
|
||||
+ * This function reloads userpd specific PIL segments during SSR
|
||||
+ * of userpd.
|
||||
+ *
|
||||
+ * Returns 0 on success, negative errno otherwise.
|
||||
+ */
|
||||
+int qcom_mdt_load_pd_seg(struct device *dev, const struct firmware *fw,
|
||||
+ const char *firmware, int pas_id, int pd_asid, void *mem_region,
|
||||
+ phys_addr_t mem_phys, size_t mem_size,
|
||||
+ phys_addr_t *reloc_base)
|
||||
+{
|
||||
+ return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
|
||||
+ mem_size, reloc_base, false, true, pd_asid);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(qcom_mdt_load_pd_seg);
|
||||
+
|
||||
MODULE_DESCRIPTION("Firmware parser for Qualcomm MDT format");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
--- a/include/linux/soc/qcom/mdt_loader.h
|
||||
+++ b/include/linux/soc/qcom/mdt_loader.h
|
||||
@@ -30,6 +30,11 @@ int qcom_mdt_load_no_init(struct device
|
||||
void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
|
||||
const char *fw_name, struct device *dev);
|
||||
|
||||
+int qcom_mdt_load_pd_seg(struct device *dev, const struct firmware *fw,
|
||||
+ const char *firmware, int pas_id, int pd_asid, void *mem_region,
|
||||
+ phys_addr_t mem_phys, size_t mem_size,
|
||||
+ phys_addr_t *reloc_base);
|
||||
+
|
||||
#else /* !IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */
|
||||
|
||||
static inline ssize_t qcom_mdt_get_size(const struct firmware *fw)
|
@ -0,0 +1,38 @@
|
||||
From e83215d5d22946885fa388d375b12f1b991a43c1 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH 3/5] remoteproc: qcom_q6v5_mpd: enable clocks
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
---
|
||||
drivers/remoteproc/qcom_q6v5_mpd.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
@@ -77,6 +77,8 @@ struct q6_wcss {
|
||||
phys_addr_t mem_reloc;
|
||||
void *mem_region;
|
||||
size_t mem_size;
|
||||
+ struct clk_bulk_data *clks;
|
||||
+ int num_clks;
|
||||
const struct wcss_data *desc;
|
||||
const char **firmware;
|
||||
struct userpd *upd[MAX_UPD];
|
||||
@@ -718,6 +720,16 @@ static int q6_wcss_probe(struct platform
|
||||
if (ret)
|
||||
goto free_rproc;
|
||||
|
||||
+ wcss->num_clks = devm_clk_bulk_get_all(wcss->dev, &wcss->clks);
|
||||
+ if (wcss->num_clks < 0)
|
||||
+ return dev_err_probe(wcss->dev, wcss->num_clks,
|
||||
+ "failed to acquire clocks\n");
|
||||
+
|
||||
+ ret = clk_bulk_prepare_enable(wcss->num_clks, wcss->clks);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(wcss->dev, ret,
|
||||
+ "failed to enable clocks\n");
|
||||
+
|
||||
ret = qcom_q6v5_init(&wcss->q6, pdev, rproc,
|
||||
WCSS_CRASH_REASON, NULL, NULL);
|
||||
if (ret)
|
@ -0,0 +1,111 @@
|
||||
From 4ae334127f073aa5f7c9209c9f0a17fd9e331db1 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Huang <hzyitc@outlook.com>
|
||||
Date: Sun, 8 Sep 2024 16:40:12 +0800
|
||||
Subject: [PATCH] remoteproc: qcom_q6v5_mpd: support ipq5018
|
||||
|
||||
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
---
|
||||
drivers/remoteproc/qcom_q6v5_mpd.c | 37 +++++++++++++++++++++++++++---
|
||||
1 file changed, 34 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
@@ -155,6 +155,8 @@ static int q6_wcss_spawn_pd(struct rproc
|
||||
static int wcss_pd_start(struct rproc *rproc)
|
||||
{
|
||||
struct userpd *upd = rproc->priv;
|
||||
+ struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
|
||||
+ struct q6_wcss *wcss = rpd_rproc->priv;
|
||||
u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
|
||||
int ret;
|
||||
|
||||
@@ -170,6 +172,14 @@ static int wcss_pd_start(struct rproc *r
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ if (upd->pd_asid == 1) {
|
||||
+ ret = qcom_scm_internal_wifi_powerup(wcss->desc->pasid);
|
||||
+ if (ret) {
|
||||
+ dev_err(upd->dev, "failed to power up internal radio\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -179,6 +189,12 @@ static int q6_wcss_stop(struct rproc *rp
|
||||
const struct wcss_data *desc = wcss->desc;
|
||||
int ret;
|
||||
|
||||
+ ret = qcom_q6v5_request_stop(&wcss->q6, NULL);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev, "pd not stopped\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
ret = qcom_scm_pas_shutdown(desc->pasid);
|
||||
if (ret) {
|
||||
dev_err(wcss->dev, "not able to shutdown\n");
|
||||
@@ -218,6 +234,7 @@ static int wcss_pd_stop(struct rproc *rp
|
||||
{
|
||||
struct userpd *upd = rproc->priv;
|
||||
struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
|
||||
+ struct q6_wcss *wcss = rpd_rproc->priv;
|
||||
u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
|
||||
int ret;
|
||||
|
||||
@@ -229,6 +246,14 @@ static int wcss_pd_stop(struct rproc *rp
|
||||
}
|
||||
}
|
||||
|
||||
+ if (upd->pd_asid == 1) {
|
||||
+ ret = qcom_scm_internal_wifi_shutdown(wcss->desc->pasid);
|
||||
+ if (ret) {
|
||||
+ dev_err(upd->dev, "failed to power down internal radio\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = qcom_scm_msa_unlock(pasid);
|
||||
if (ret) {
|
||||
dev_err(upd->dev, "failed to power down pd\n");
|
||||
@@ -430,15 +455,14 @@ static int wcss_pd_load(struct rproc *rp
|
||||
struct userpd *upd = rproc->priv;
|
||||
struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
|
||||
struct q6_wcss *wcss = rpd_rproc->priv;
|
||||
- u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
|
||||
int ret;
|
||||
|
||||
ret = rproc_boot(rpd_rproc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return qcom_mdt_load(upd->dev, fw, rproc->firmware,
|
||||
- pasid, wcss->mem_region,
|
||||
+ return qcom_mdt_load_pd_seg(upd->dev, fw, rproc->firmware,
|
||||
+ wcss->desc->pasid, upd->pd_asid, wcss->mem_region,
|
||||
wcss->mem_phys, wcss->mem_size,
|
||||
NULL);
|
||||
}
|
||||
@@ -777,6 +801,12 @@ static int q6_wcss_remove(struct platfor
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const struct wcss_data q6_ipq5018_res_init = {
|
||||
+ .pasid = MPD_WCNSS_PAS_ID,
|
||||
+ // .share_upd_info_to_q6 = true, /* Version 1 */
|
||||
+ // .mdt_load_sec = qcom_mdt_load_pd_seg,
|
||||
+};
|
||||
+
|
||||
static const struct wcss_data q6_ipq5332_res_init = {
|
||||
.pasid = MPD_WCNSS_PAS_ID,
|
||||
.share_upd_info_to_q6 = true,
|
||||
@@ -787,6 +817,7 @@ static const struct wcss_data q6_ipq9574
|
||||
};
|
||||
|
||||
static const struct of_device_id q6_wcss_of_match[] = {
|
||||
+ { .compatible = "qcom,ipq5018-q6-mpd", .data = &q6_ipq5018_res_init },
|
||||
{ .compatible = "qcom,ipq5332-q6-mpd", .data = &q6_ipq5332_res_init },
|
||||
{ .compatible = "qcom,ipq9574-q6-mpd", .data = &q6_ipq9574_res_init },
|
||||
{ },
|
@ -0,0 +1,163 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Mon, 09 Dec 2024 09:59:38 +0400
|
||||
Subject: [PATCH] remoteproc: qcom_q6v5_mpd: add support for passing v1 bootargs
|
||||
|
||||
On multi-PD platforms such as IPQ5018, boot args are passed to the root PD
|
||||
run on the Q6 processor which in turn boots the user PDs for internal
|
||||
(IPQ5018) and external wifi radios (such as QCN6122). These boot args
|
||||
let the user PD process know details like what PCIE index, user PD ID, and
|
||||
reset GPIO is used. These are otherwise hardcoded in the firmware.
|
||||
|
||||
Below is the structure expected of the version 1 boot args including the
|
||||
default values hardcoded in the firmware for IPQ5018:
|
||||
|
||||
+------------+------+--------------+--------------+
|
||||
| Argument | type | def val UPD2 | def val UPD3 |
|
||||
+------------+------+--------------+--------------+
|
||||
| PCIE Index | u32 | 0x02 (PCIE1) | 0x01 (PCIE0) |
|
||||
| Length | u32 | 0x04 | 0x04 |
|
||||
| User PD ID | u32 | 0x02 | 0x03 |
|
||||
| Reset GPIO | u32 | 0x12 | 0x0f |
|
||||
| Reserved 1 | u32 | 0x00 | 0x00 |
|
||||
| Reserved 2 | u32 | 0x00 | 0x00 |
|
||||
+------------+------+--------------+--------------+
|
||||
|
||||
On IPQ5018/QCN6122 boards, the default mapping is as follows:
|
||||
|
||||
+-> UPD1 ----> IPQ5018 Internal 2.4G Radio
|
||||
/
|
||||
/
|
||||
Root PD +---> UPD2 ----> QCN6122 6G Radio on PCIE1 (if available)
|
||||
\
|
||||
\
|
||||
+-> UPD3 ----> QCN6102 5G Radio on PCIE0
|
||||
|
||||
To support (future) boards with other mappings or control what UPD ID is
|
||||
used, let's add support for passing boot args for more flexibility.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
|
||||
@@ -42,7 +42,11 @@
|
||||
#define UPD_BOOT_INFO_SMEM_SIZE 4096
|
||||
#define UPD_BOOT_INFO_HEADER_TYPE 0x2
|
||||
#define UPD_BOOT_INFO_SMEM_ID 507
|
||||
-#define VERSION2 2
|
||||
+
|
||||
+enum q6_bootargs_version {
|
||||
+ VERSION1 = 1,
|
||||
+ VERSION2,
|
||||
+};
|
||||
|
||||
/**
|
||||
* struct userpd_boot_info_header - header of user pd bootinfo
|
||||
@@ -94,6 +98,7 @@ struct userpd {
|
||||
struct wcss_data {
|
||||
u32 pasid;
|
||||
bool share_upd_info_to_q6;
|
||||
+ u8 bootargs_version;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -298,10 +303,13 @@ static void *q6_wcss_da_to_va(struct rpr
|
||||
static int share_upd_bootinfo_to_q6(struct rproc *rproc)
|
||||
{
|
||||
int i, ret;
|
||||
+ u32 rd_val;
|
||||
size_t size;
|
||||
u16 cnt = 0, version;
|
||||
void *ptr;
|
||||
+ u8 *bootargs_arr;
|
||||
struct q6_wcss *wcss = rproc->priv;
|
||||
+ struct device_node *np = wcss->dev->of_node;
|
||||
struct userpd *upd;
|
||||
struct userpd_boot_info upd_bootinfo = {0};
|
||||
const struct firmware *fw;
|
||||
@@ -323,10 +331,47 @@ static int share_upd_bootinfo_to_q6(stru
|
||||
}
|
||||
|
||||
/*Version*/
|
||||
- version = VERSION2;
|
||||
+ version = (wcss->desc->bootargs_version) ? wcss->desc->bootargs_version : VERSION2;
|
||||
memcpy_toio(ptr, &version, sizeof(version));
|
||||
ptr += sizeof(version);
|
||||
|
||||
+ cnt = ret = of_property_count_u32_elems(np, "boot-args");
|
||||
+ if (ret < 0) {
|
||||
+ if (ret == -ENODATA) {
|
||||
+ dev_err(wcss->dev, "failed to read boot args ret:%d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ cnt = 0;
|
||||
+ }
|
||||
+
|
||||
+ /* No of elements */
|
||||
+ memcpy_toio(ptr, &cnt, sizeof(u16));
|
||||
+ ptr += sizeof(u16);
|
||||
+
|
||||
+ bootargs_arr = kzalloc(cnt, GFP_KERNEL);
|
||||
+ if (!bootargs_arr) {
|
||||
+ dev_err(wcss->dev, "failed to allocate memory\n");
|
||||
+ return PTR_ERR(bootargs_arr);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < cnt; i++) {
|
||||
+ ret = of_property_read_u32_index(np, "boot-args", i, &rd_val);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev, "failed to read boot args\n");
|
||||
+ kfree(bootargs_arr);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ bootargs_arr[i] = (u8)rd_val;
|
||||
+ }
|
||||
+
|
||||
+ /* Copy bootargs */
|
||||
+ memcpy_toio(ptr, bootargs_arr, cnt);
|
||||
+ ptr += (cnt);
|
||||
+
|
||||
+ of_node_put(np);
|
||||
+ kfree(bootargs_arr);
|
||||
+ cnt = 0;
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(wcss->upd); i++)
|
||||
if (wcss->upd[i])
|
||||
cnt++;
|
||||
@@ -382,12 +427,14 @@ static int q6_wcss_load(struct rproc *rp
|
||||
|
||||
/* Share user pd boot info to Q6 remote processor */
|
||||
if (desc->share_upd_info_to_q6) {
|
||||
- ret = share_upd_bootinfo_to_q6(rproc);
|
||||
- if (ret) {
|
||||
- dev_err(wcss->dev,
|
||||
- "user pd boot info sharing with q6 failed %d\n",
|
||||
- ret);
|
||||
- return ret;
|
||||
+ if (of_property_present(wcss->dev->of_node, "boot-args")) {
|
||||
+ ret = share_upd_bootinfo_to_q6(rproc);
|
||||
+ if (ret) {
|
||||
+ dev_err(wcss->dev,
|
||||
+ "user pd boot info sharing with q6 failed %d\n",
|
||||
+ ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,13 +850,15 @@ static int q6_wcss_remove(struct platfor
|
||||
|
||||
static const struct wcss_data q6_ipq5018_res_init = {
|
||||
.pasid = MPD_WCNSS_PAS_ID,
|
||||
- // .share_upd_info_to_q6 = true, /* Version 1 */
|
||||
+ .share_upd_info_to_q6 = true,
|
||||
+ .bootargs_version = VERSION1,
|
||||
// .mdt_load_sec = qcom_mdt_load_pd_seg,
|
||||
};
|
||||
|
||||
static const struct wcss_data q6_ipq5332_res_init = {
|
||||
.pasid = MPD_WCNSS_PAS_ID,
|
||||
.share_upd_info_to_q6 = true,
|
||||
+ .bootargs_version = VERSION2,
|
||||
};
|
||||
|
||||
static const struct wcss_data q6_ipq9574_res_init = {
|
@ -0,0 +1,241 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Wed, 27 Oct 2024 16:34:11 +0400
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: add wifi support
|
||||
|
||||
The IPQ5018 SoC comes with an internal 2x2 2.4Ghz wifi radio.
|
||||
QCN6122 is a PCIe based wifi solution specific to the IPQ5018 platform which
|
||||
comes optinally packed with 1 or 2 QCN6122 chips or with an external
|
||||
PCIe based wifi solution (such as QCN9074) for 5/6 Ghz support.
|
||||
|
||||
As such, add wifi nodes for both IPQ5018 and QCN6122.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -692,6 +692,225 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ wifi0: wifi@c000000 {
|
||||
+ compatible = "qcom,ipq5018-wifi";
|
||||
+ reg = <0xc000000 0x1000000>;
|
||||
+
|
||||
+ interrupts = <GIC_SPI 288 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 289 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 290 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 292 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 293 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 294 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 295 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 296 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 297 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 298 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 299 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 300 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 301 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 302 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 303 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 304 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 305 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 306 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 307 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 308 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 309 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 310 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 311 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 312 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 313 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 314 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 315 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 316 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 317 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 319 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 320 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 321 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 322 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 323 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 325 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 326 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 332 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 333 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 334 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 335 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 336 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 337 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 338 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 339 IRQ_TYPE_EDGE_RISING>;
|
||||
+
|
||||
+ interrupt-names = "misc-pulse1",
|
||||
+ "misc-latch",
|
||||
+ "sw-exception",
|
||||
+ "watchdog",
|
||||
+ "ce0",
|
||||
+ "ce1",
|
||||
+ "ce2",
|
||||
+ "ce3",
|
||||
+ "ce4",
|
||||
+ "ce5",
|
||||
+ "ce6",
|
||||
+ "ce7",
|
||||
+ "ce8",
|
||||
+ "ce9",
|
||||
+ "ce10",
|
||||
+ "ce11",
|
||||
+ "host2wbm-desc-feed",
|
||||
+ "host2reo-re-injection",
|
||||
+ "host2reo-command",
|
||||
+ "host2rxdma-monitor-ring3",
|
||||
+ "host2rxdma-monitor-ring2",
|
||||
+ "host2rxdma-monitor-ring1",
|
||||
+ "reo2ost-exception",
|
||||
+ "wbm2host-rx-release",
|
||||
+ "reo2host-status",
|
||||
+ "reo2host-destination-ring4",
|
||||
+ "reo2host-destination-ring3",
|
||||
+ "reo2host-destination-ring2",
|
||||
+ "reo2host-destination-ring1",
|
||||
+ "rxdma2host-monitor-destination-mac3",
|
||||
+ "rxdma2host-monitor-destination-mac2",
|
||||
+ "rxdma2host-monitor-destination-mac1",
|
||||
+ "ppdu-end-interrupts-mac3",
|
||||
+ "ppdu-end-interrupts-mac2",
|
||||
+ "ppdu-end-interrupts-mac1",
|
||||
+ "rxdma2host-monitor-status-ring-mac3",
|
||||
+ "rxdma2host-monitor-status-ring-mac2",
|
||||
+ "rxdma2host-monitor-status-ring-mac1",
|
||||
+ "host2rxdma-host-buf-ring-mac3",
|
||||
+ "host2rxdma-host-buf-ring-mac2",
|
||||
+ "host2rxdma-host-buf-ring-mac1",
|
||||
+ "rxdma2host-destination-ring-mac3",
|
||||
+ "rxdma2host-destination-ring-mac2",
|
||||
+ "rxdma2host-destination-ring-mac1",
|
||||
+ "host2tcl-input-ring4",
|
||||
+ "host2tcl-input-ring3",
|
||||
+ "host2tcl-input-ring2",
|
||||
+ "host2tcl-input-ring1",
|
||||
+ "wbm2host-tx-completions-ring3",
|
||||
+ "wbm2host-tx-completions-ring2",
|
||||
+ "wbm2host-tx-completions-ring1",
|
||||
+ "tcl2host-status-ring";
|
||||
+
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ //QCN6102 5G
|
||||
+ wifi1: wifi1@c000000 {
|
||||
+ reg = <0x0b00a040 0x0>;
|
||||
+ compatible = "qcom,qcn6122-wifi";
|
||||
+ interrupts = <GIC_SPI 416 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 417 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 418 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 419 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 420 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 421 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 422 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 423 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 424 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 425 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 426 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 427 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 428 IRQ_TYPE_EDGE_RISING>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ //QCN6122 5G/6G
|
||||
+ wifi2: wifi2@c000000 {
|
||||
+ reg = <0x0b00a040 0x0>;
|
||||
+ compatible = "qcom,qcn6122-wifi";
|
||||
+ interrupts = <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 449 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 450 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 451 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 452 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 453 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 454 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 455 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 456 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 457 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 458 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 459 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <GIC_SPI 460 IRQ_TYPE_EDGE_RISING>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ q6v5_wcss: remoteproc@cd00000 {
|
||||
+ compatible = "qcom,ipq5018-q6-mpd";
|
||||
+ reg = <0x0cd00000 0x4040>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ ranges;
|
||||
+
|
||||
+ clocks = <&gcc GCC_XO_CLK>,
|
||||
+ <&gcc GCC_SLEEP_CLK_SRC>,
|
||||
+ <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>;
|
||||
+
|
||||
+ interrupts-extended = <&intc GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
|
||||
+ <&wcss_smp2p_in 0 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 1 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 2 IRQ_TYPE_NONE>,
|
||||
+ <&wcss_smp2p_in 3 IRQ_TYPE_NONE>;
|
||||
+ interrupt-names = "wdog",
|
||||
+ "fatal",
|
||||
+ "ready",
|
||||
+ "handover",
|
||||
+ "stop-ack";
|
||||
+
|
||||
+ qcom,smem-states = <&wcss_smp2p_out 0>,
|
||||
+ <&wcss_smp2p_out 1>;
|
||||
+ qcom,smem-state-names = "shutdown",
|
||||
+ "stop";
|
||||
+
|
||||
+ status = "disabled";
|
||||
+
|
||||
+ glink-edge {
|
||||
+ interrupts = <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>;
|
||||
+ label = "rtr";
|
||||
+ qcom,remote-pid = <1>;
|
||||
+ mboxes = <&apcs_glb 8>;
|
||||
+
|
||||
+ qrtr_requests {
|
||||
+ qcom,glink-channels = "IPCRTR";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ wcss: smp2p-wcss {
|
||||
+ compatible = "qcom,smp2p";
|
||||
+ qcom,smem = <435>, <428>;
|
||||
+
|
||||
+ interrupt-parent = <&intc>;
|
||||
+ interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
|
||||
+
|
||||
+ mboxes = <&apcs_glb 9>;
|
||||
+
|
||||
+ qcom,local-pid = <0>;
|
||||
+ qcom,remote-pid = <1>;
|
||||
+
|
||||
+ wcss_smp2p_out: master-kernel {
|
||||
+ qcom,entry-name = "master-kernel";
|
||||
+ qcom,smp2p-feature-ssr-ack;
|
||||
+ #qcom,smem-state-cells = <1>;
|
||||
+ };
|
||||
+
|
||||
+ wcss_smp2p_in: slave-kernel {
|
||||
+ qcom,entry-name = "slave-kernel";
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
pcie1: pcie@80000000 {
|
||||
compatible = "qcom,pcie-ipq5018";
|
||||
reg = <0x80000000 0xf1d>,
|
@ -0,0 +1,22 @@
|
||||
From: George Moussalem <george.moussalem@outlook.com>
|
||||
Date: Wed, 05 Feb 2025 12:12:47 +0400
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq5018: add tz_apps reserved memory region
|
||||
|
||||
Add tz_apps memory region needed for wifi to work.
|
||||
|
||||
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
---
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
|
||||
@@ -113,6 +113,11 @@
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
+ tz_apps@4a400000 {
|
||||
+ reg = <0x0 0x4a400000 0x0 0x400000>;
|
||||
+ no-map;
|
||||
+ };
|
||||
+
|
||||
bootloader@4a800000 {
|
||||
reg = <0x0 0x4a800000 0x0 0x200000>;
|
||||
no-map;
|
Loading…
x
Reference in New Issue
Block a user