ipq50xx: Prepare for WiFi

This commit is contained in:
hzy 2023-05-31 21:35:17 +00:00
parent 335372c35d
commit ebb2c02b39
18 changed files with 2520 additions and 1 deletions

View File

@ -1535,7 +1535,7 @@ $(eval $(call KernelPackage,qrtr-tun))
define KernelPackage/qrtr-smd
SUBMENU:=$(NETWORK_SUPPORT_MENU)
TITLE:=SMD IPC Router channels
DEPENDS:=+kmod-qrtr @TARGET_ipq807x
DEPENDS:=+kmod-qrtr @(TARGET_ipq50xx||TARGET_ipq807x)
KCONFIG:=CONFIG_QRTR_SMD
FILES:= $(LINUX_DIR)/net/qrtr/qrtr-smd.ko
AUTOLOAD:=$(call AutoProbe,qrtr-smd)

View File

@ -1297,3 +1297,14 @@ CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT=y
# CONFIG_MTD_UBI_GLUEBI is not set
CONFIG_MDIO_IPQ4019=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_IPQ_APSS_PLL=y
CONFIG_IPQ_APSS_6018=y
CONFIG_MAILBOX=y
CONFIG_RPMSG=y
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=y
CONFIG_QCOM_Q6V5_MPD=y
CONFIG_ARM_CRYPTO=y

View File

@ -0,0 +1,60 @@
From 9bb1a40325c0c4b0489abf8f5dc5cc376ea5d677 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 19 Aug 2022 00:06:20 +0200
Subject: [PATCH 08/11] clk: qcom: clk-rcg2: add rcg2 mux ops
An RCG may act as a mux that switch between 2 parents.
This is the case on IPQ6018 and IPQ8074 where the APCS core clk that feeds
the CPU cluster clock just switches between XO and the PLL that feeds it.
Add the required ops to add support for this special configuration and use
the generic mux function to determine the rate.
This way we dont have to keep a essentially dummy frequency table to use
RCG2 as a mux.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20220818220628.339366-1-robimarko@gmail.com
(cherry picked from commit c5d2c96b3a7bd8987fad9957510034130037fccf)
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/clk/qcom/clk-rcg.h | 1 +
drivers/clk/qcom/clk-rcg2.c | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index c25b57c3cbc8..4ff199e06e4f 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -155,6 +155,7 @@ struct clk_rcg2 {
extern const struct clk_ops clk_rcg2_ops;
extern const struct clk_ops clk_rcg2_floor_ops;
+extern const struct clk_ops clk_rcg2_mux_closest_ops;
extern const struct clk_ops clk_edp_pixel_ops;
extern const struct clk_ops clk_byte_ops;
extern const struct clk_ops clk_byte2_ops;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 89c1adeb84d4..17ab2665bf6e 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -387,6 +387,13 @@ const struct clk_ops clk_rcg2_floor_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
+const struct clk_ops clk_rcg2_mux_closest_ops = {
+ .determine_rate = __clk_mux_determine_rate_closest,
+ .get_parent = clk_rcg2_get_parent,
+ .set_parent = clk_rcg2_set_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_mux_closest_ops);
+
struct frac_entry {
int num;
int den;
--
2.25.1

View File

@ -0,0 +1,70 @@
From 8d0cae8ef89cf131db5bfb9c8f2d584a56ce3825 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Fri, 19 Aug 2022 00:06:21 +0200
Subject: [PATCH 09/11] clk: qcom: apss-ipq6018: fix apcs_alias0_clk_src
While working on IPQ8074 APSS driver it was discovered that IPQ6018 and
IPQ8074 use almost the same PLL and APSS clocks, however APSS driver is
currently broken.
More precisely apcs_alias0_clk_src is broken, it was added as regmap_mux
clock.
However after debugging why it was always stuck at 800Mhz, it was figured
out that its not regmap_mux compatible at all.
It is a simple mux but it uses RCG2 register layout and control bits, so
utilize the new clk_rcg2_mux_closest_ops to correctly drive it while not
having to provide a dummy frequency table.
While we are here, use ARRAY_SIZE for number of parents.
Tested on IPQ6018-CP01-C1 reference board and multiple IPQ8074 boards.
Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller")
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20220818220628.339366-2-robimarko@gmail.com
(cherry picked from commit 43a56cbf2a38170b02db29654607575b1b4b5bc0)
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/clk/qcom/apss-ipq6018.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c
index d78ff2f310bf..be952d417ded 100644
--- a/drivers/clk/qcom/apss-ipq6018.c
+++ b/drivers/clk/qcom/apss-ipq6018.c
@@ -16,7 +16,7 @@
#include "clk-regmap.h"
#include "clk-branch.h"
#include "clk-alpha-pll.h"
-#include "clk-regmap-mux.h"
+#include "clk-rcg.h"
enum {
P_XO,
@@ -33,16 +33,15 @@ static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
{ P_APSS_PLL_EARLY, 5 },
};
-static struct clk_regmap_mux apcs_alias0_clk_src = {
- .reg = 0x0050,
- .width = 3,
- .shift = 7,
+static struct clk_rcg2 apcs_alias0_clk_src = {
+ .cmd_rcgr = 0x0050,
+ .hid_width = 5,
.parent_map = parents_apcs_alias0_clk_src_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "apcs_alias0_clk_src",
.parent_data = parents_apcs_alias0_clk_src,
- .num_parents = 2,
- .ops = &clk_regmap_mux_closest_ops,
+ .num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src),
+ .ops = &clk_rcg2_mux_closest_ops,
.flags = CLK_SET_RATE_PARENT,
},
};
--
2.25.1

View File

@ -0,0 +1,77 @@
From 8c570373e004ff38d1bb4a1a002d05528bb9ad9a Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Fri, 19 Aug 2022 00:06:24 +0200
Subject: [PATCH 11/11] clk: qcom: apss-ipq-pll: use OF match data for Alpha
PLL config
Convert the driver to use OF match data for providing the Alpha PLL config
per compatible.
This is required for IPQ8074 support since it uses a different Alpha PLL
config.
While we are here rename "ipq_pll_config" to "ipq6018_pll_config" to make
it clear that it is for IPQ6018 only.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20220818220628.339366-5-robimarko@gmail.com
(cherry picked from commit 823a117e1d97b57d1ef9932c55cc02d6d7ba0523)
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/clk/qcom/apss-ipq-pll.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
index bef7899ad0d6..ba77749b16c4 100644
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -2,6 +2,7 @@
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
#include <linux/clk-provider.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -36,7 +37,7 @@ static struct clk_alpha_pll ipq_pll = {
},
};
-static const struct alpha_pll_config ipq_pll_config = {
+static const struct alpha_pll_config ipq6018_pll_config = {
.l = 0x37,
.config_ctl_val = 0x04141200,
.config_ctl_hi_val = 0x0,
@@ -54,6 +55,7 @@ static const struct regmap_config ipq_pll_regmap_config = {
static int apss_ipq_pll_probe(struct platform_device *pdev)
{
+ const struct alpha_pll_config *ipq_pll_config;
struct device *dev = &pdev->dev;
struct regmap *regmap;
void __iomem *base;
@@ -67,7 +69,11 @@ static int apss_ipq_pll_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- clk_alpha_pll_configure(&ipq_pll, regmap, &ipq_pll_config);
+ ipq_pll_config = of_device_get_match_data(&pdev->dev);
+ if (!ipq_pll_config)
+ return -ENODEV;
+
+ clk_alpha_pll_configure(&ipq_pll, regmap, ipq_pll_config);
ret = devm_clk_register_regmap(dev, &ipq_pll.clkr);
if (ret)
@@ -78,7 +84,7 @@ static int apss_ipq_pll_probe(struct platform_device *pdev)
}
static const struct of_device_id apss_ipq_pll_match_table[] = {
- { .compatible = "qcom,ipq6018-a53pll" },
+ { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_config },
{ }
};
MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table);
--
2.25.1

View File

@ -0,0 +1,122 @@
From 54d4b22e66cb1df52b4a14bee49aaa198a788439 Mon Sep 17 00:00:00 2001
From: Kathiravan T <quic_kathirav@quicinc.com>
Date: Wed, 8 Feb 2023 09:58:46 +0530
Subject: [PATCH 1/4] clk: qcom: apss-ipq-pll: refactor the driver to
accommodate different PLL types
APSS PLL found on the IPQ8074 and IPQ6018 are of type Huayra PLL. But,
IPQ5332 APSS PLL is of type Stromer Plus. To accommodate both these PLLs,
refactor the driver to take the clk_alpha_pll, alpha_pll_config via driver
data.
Signed-off-by: Kathiravan T <quic_kathirav@quicinc.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Pick from <20230208042850.1687-2-quic_kathirav@quicinc.com>
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/clk/qcom/apss-ipq-pll.c | 53 ++++++++++++++++++++++-----------
1 file changed, 35 insertions(+), 18 deletions(-)
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
index ba77749b16c4..720df770e79b 100644
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -8,20 +8,27 @@
#include "clk-alpha-pll.h"
-static const u8 ipq_pll_offsets[] = {
- [PLL_OFF_L_VAL] = 0x08,
- [PLL_OFF_ALPHA_VAL] = 0x10,
- [PLL_OFF_USER_CTL] = 0x18,
- [PLL_OFF_CONFIG_CTL] = 0x20,
- [PLL_OFF_CONFIG_CTL_U] = 0x24,
- [PLL_OFF_STATUS] = 0x28,
- [PLL_OFF_TEST_CTL] = 0x30,
- [PLL_OFF_TEST_CTL_U] = 0x34,
+/*
+ * Even though APSS PLL type is of existing one (like Huayra), its offsets
+ * are different from the one mentioned in the clk-alpha-pll.c, since the
+ * PLL is specific to APSS, so lets the define the same.
+ */
+static const u8 ipq_pll_offsets[][PLL_OFF_MAX_REGS] = {
+ [CLK_ALPHA_PLL_TYPE_HUAYRA] = {
+ [PLL_OFF_L_VAL] = 0x08,
+ [PLL_OFF_ALPHA_VAL] = 0x10,
+ [PLL_OFF_USER_CTL] = 0x18,
+ [PLL_OFF_CONFIG_CTL] = 0x20,
+ [PLL_OFF_CONFIG_CTL_U] = 0x24,
+ [PLL_OFF_STATUS] = 0x28,
+ [PLL_OFF_TEST_CTL] = 0x30,
+ [PLL_OFF_TEST_CTL_U] = 0x34,
+ },
};
-static struct clk_alpha_pll ipq_pll = {
+static struct clk_alpha_pll ipq_pll_huayra = {
.offset = 0x0,
- .regs = ipq_pll_offsets,
+ .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_HUAYRA],
.flags = SUPPORTS_DYNAMIC_UPDATE,
.clkr = {
.enable_reg = 0x0,
@@ -45,6 +52,16 @@ static const struct alpha_pll_config ipq6018_pll_config = {
.main_output_mask = BIT(0),
};
+struct apss_pll_data {
+ struct clk_alpha_pll *pll;
+ const struct alpha_pll_config *pll_config;
+};
+
+static struct apss_pll_data ipq6018_pll_data = {
+ .pll = &ipq_pll_huayra,
+ .pll_config = &ipq6018_pll_config,
+};
+
static const struct regmap_config ipq_pll_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -55,7 +72,7 @@ static const struct regmap_config ipq_pll_regmap_config = {
static int apss_ipq_pll_probe(struct platform_device *pdev)
{
- const struct alpha_pll_config *ipq_pll_config;
+ const struct apss_pll_data *data;
struct device *dev = &pdev->dev;
struct regmap *regmap;
void __iomem *base;
@@ -69,22 +86,22 @@ static int apss_ipq_pll_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- ipq_pll_config = of_device_get_match_data(&pdev->dev);
- if (!ipq_pll_config)
+ data = of_device_get_match_data(&pdev->dev);
+ if (!data)
return -ENODEV;
- clk_alpha_pll_configure(&ipq_pll, regmap, ipq_pll_config);
+ clk_alpha_pll_configure(data->pll, regmap, data->pll_config);
- ret = devm_clk_register_regmap(dev, &ipq_pll.clkr);
+ ret = devm_clk_register_regmap(dev, &data->pll->clkr);
if (ret)
return ret;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
- &ipq_pll.clkr.hw);
+ &data->pll->clkr.hw);
}
static const struct of_device_id apss_ipq_pll_match_table[] = {
- { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_config },
+ { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data },
{ }
};
MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table);
--
2.25.1

View File

@ -0,0 +1,94 @@
From c224630bf98c2870e7425eb43a5a965e81a01d32 Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Tue, 14 Mar 2023 17:06:40 +0000
Subject: [PATCH 2/4] clk: qcom: apss-ipq-pll: add support for IPQ5018
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/clk/qcom/apss-ipq-pll.c | 49 +++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
index 720df770e79b..97d6acb0c6b0 100644
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -24,6 +24,17 @@ static const u8 ipq_pll_offsets[][PLL_OFF_MAX_REGS] = {
[PLL_OFF_TEST_CTL] = 0x30,
[PLL_OFF_TEST_CTL_U] = 0x34,
},
+ [CLK_ALPHA_PLL_TYPE_STROMER] = {
+ [PLL_OFF_L_VAL] = 0x08,
+ [PLL_OFF_ALPHA_VAL] = 0x10,
+ [PLL_OFF_ALPHA_VAL_U] = 0x14,
+ [PLL_OFF_USER_CTL] = 0x18,
+ [PLL_OFF_USER_CTL_U] = 0x1c,
+ [PLL_OFF_CONFIG_CTL] = 0x20,
+ [PLL_OFF_STATUS] = 0x28,
+ [PLL_OFF_TEST_CTL] = 0x30,
+ [PLL_OFF_TEST_CTL_U] = 0x34,
+ },
};
static struct clk_alpha_pll ipq_pll_huayra = {
@@ -44,6 +55,38 @@ static struct clk_alpha_pll ipq_pll_huayra = {
},
};
+static struct clk_alpha_pll ipq_pll_stromer = {
+ .offset = 0x0,
+ .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER],
+ // .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .clkr = {
+ .enable_reg = 0x0,
+ .enable_mask = BIT(0),
+ .hw.init = &(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 const struct alpha_pll_config ipq5018_pll_config = {
+ .l = 0x36,
+ .config_ctl_val = 0x4001075b,
+ .alpha_en_mask = BIT(24),
+ .early_output_mask = BIT(3),
+ .aux_output_mask = BIT(1),
+ .main_output_mask = BIT(0),
+ .status_reg_mask = GENMASK(10, 8),
+ .status_reg_val = 0x3,
+ .lock_det = BIT(2),
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00400003,
+};
+
static const struct alpha_pll_config ipq6018_pll_config = {
.l = 0x37,
.config_ctl_val = 0x04141200,
@@ -57,6 +100,11 @@ struct apss_pll_data {
const struct alpha_pll_config *pll_config;
};
+static struct apss_pll_data ipq5018_pll_data = {
+ .pll = &ipq_pll_stromer,
+ .pll_config = &ipq5018_pll_config,
+};
+
static struct apss_pll_data ipq6018_pll_data = {
.pll = &ipq_pll_huayra,
.pll_config = &ipq6018_pll_config,
@@ -101,6 +149,7 @@ static int apss_ipq_pll_probe(struct platform_device *pdev)
}
static const struct of_device_id apss_ipq_pll_match_table[] = {
+ { .compatible = "qcom,ipq5018-a53pll", .data = &ipq5018_pll_data },
{ .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data },
{ }
};
--
2.25.1

View File

@ -0,0 +1,25 @@
From bf7c9ce914d992c3993d2d18c95a2f2ae130ce1e Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Tue, 14 Mar 2023 17:09:04 +0000
Subject: [PATCH 3/4] mailbox: qcom: Add ipq5018 apcs compatible
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/mailbox/qcom-apcs-ipc-mailbox.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
index cec34f0af6ce..4938e60a1a2a 100644
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
@@ -143,6 +143,7 @@ static int qcom_apcs_ipc_remove(struct platform_device *pdev)
/* .data is the offset of the ipc register within the global block */
static const struct of_device_id qcom_apcs_ipc_of_match[] = {
+ { .compatible = "qcom,ipq5018-apcs-apps-global", .data = &ipq6018_apcs_data },
{ .compatible = "qcom,ipq6018-apcs-apps-global", .data = &ipq6018_apcs_data },
{ .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq8074_apcs_data },
{ .compatible = "qcom,msm8916-apcs-kpss-global", .data = &msm8916_apcs_data },
--
2.25.1

View File

@ -0,0 +1,109 @@
From c22fb5533f31593bbc8ffa603c69ec002338ca5a Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Tue, 14 Mar 2023 17:25:13 +0000
Subject: [PATCH 4/4] arm64: dts: qcom: ipq5018: Add APSS mailbox and clock
node
Signed-off-by: hzy <hzyitc@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 54 +++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 668a931c892e..1114a1134202 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
+#include <dt-bindings/clock/qcom,apss-ipq.h>
/ {
#address-cells = <2>;
@@ -37,7 +38,11 @@
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
+ qcom,acc = <&acc0>;
next-level-cache = <&L2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ clock-names = "cpu";
+ operating-points-v2 = <&cpu_opp_table>;
};
CPU1: cpu@1 {
@@ -45,7 +50,11 @@
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x1>;
+ qcom,acc = <&acc1>;
next-level-cache = <&L2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ clock-names = "cpu";
+ operating-points-v2 = <&cpu_opp_table>;
};
L2_0: l2-cache {
@@ -54,6 +63,23 @@
};
};
+ cpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1100>;
+ clock-latency-ns = <200000>;
+ };
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <1100>;
+ clock-latency-ns = <200000>;
+ };
+ };
+
pmuv8: pmu {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(4) |
@@ -143,6 +169,34 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+ apcs_glb: mailbox@b111000 {
+ compatible = "qcom,ipq5018-apcs-apps-global";
+ reg = <0x0b111000 0x1000>;
+ clocks = <&xo>, <&a53pll>;
+ clock-names = "xo", "pll";
+
+ #clock-cells = <1>;
+ #mbox-cells = <1>;
+ };
+
+ a53pll: clock@b116000 {
+ compatible = "qcom,ipq5018-a53pll";
+ reg = <0x0b116000 0x40>;
+ #clock-cells = <0>;
+ clocks = <&xo>;
+ clock-names = "xo";
+ };
+
+ acc0:clock-controller@b188000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b188000 0x1000>;
+ };
+
+ acc1:clock-controller@b198000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b198000 0x1000>;
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
--
2.25.1

View File

@ -0,0 +1,133 @@
From 424c7e86813fc1395ab95f67e0ccd5db314fbca5 Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Tue, 7 Mar 2023 14:41:05 +0000
Subject: [PATCH 1/4] firmware: qcom_scm: Add necessary function to load userpd
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/firmware/qcom_scm.c | 79 +++++++++++++++++++++++++++++++++++++
drivers/firmware/qcom_scm.h | 3 ++
include/linux/qcom_scm.h | 3 ++
3 files changed, 85 insertions(+)
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index a85466cfda58..02aa599ebdcf 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -651,6 +651,85 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = {
.deassert = qcom_scm_pas_reset_deassert,
};
+/**
+ * qcom_scm_pas_power_up() - Bring up internal radio userpd
+ * @peripheral: peripheral id
+ *
+ * Return 0 on success.
+ */
+int qcom_scm_pas_power_up(u32 peripheral)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_PIL_PAS_POWER_UP,
+ .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_pas_power_up);
+
+/**
+ * qcom_scm_pas_power_down() - Shut down internal radio userpd
+ * @peripheral: peripheral id
+ *
+ * Returns 0 on success.
+ */
+int qcom_scm_pas_power_down(u32 peripheral)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_PIL_PAS_POWER_DOWN,
+ .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_pas_power_down);
+
+/**
+ * qcom_scm_pas_load_seg() - copy userpd PIL segments data to dma blocks
+ * @peripheral: peripheral id
+ * @phno: program header no
+ * @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_seg(u32 peripheral, int phno, 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] = phno,
+ .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_seg);
+
int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)
{
struct qcom_scm_desc desc = {
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 343ba3a470b5..eb5268308f2b 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -86,6 +86,9 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#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_PIL_PAS_POWER_UP 0x17
+#define QCOM_SCM_PIL_PAS_POWER_DOWN 0x18
+#define QCOM_SCM_PIL_PAS_LOAD_SEG 0x19
#define QCOM_SCM_SVC_IO 0x05
#define QCOM_SCM_IO_READ 0x01
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index 081dfc69eb8b..503a05f5e629 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -49,6 +49,9 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
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_pas_power_up(u32 peripheral);
+extern int qcom_scm_pas_power_down(u32 peripheral);
+extern int qcom_scm_pas_load_seg(u32 peripheral, int phno, dma_addr_t dma, int seg_cnt);
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);
--
2.25.1

View File

@ -0,0 +1,60 @@
From 5b634205941367936b834b03ed219370e979fbf4 Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Tue, 7 Mar 2023 14:41:05 +0000
Subject: [PATCH 2/4] remoteproc: qcom: Add qcom_get_pd_asid
Spilt from <1678164097-13247-9-git-send-email-quic_mmanikan@quicinc.com>
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/remoteproc/qcom_common.c | 23 +++++++++++++++++++++++
drivers/remoteproc/qcom_common.h | 1 +
2 files changed, 24 insertions(+)
diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 9028cea2d81e..2e17b274db34 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -252,5 +252,28 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
}
EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+/**
+ * qcom_get_pd_asid() - get the pd asid number from DT node
+ * @node: device tree node
+ *
+ * Returns asid if node name has 'pd' string
+ */
+s8 qcom_get_pd_asid(struct device_node *node)
+{
+ char *str;
+ u8 pd_asid;
+
+ if (!node)
+ return -EINVAL;
+
+ str = strstr(node->name, "pd");
+ if (!str)
+ return 0;
+
+ str += strlen("pd");
+ return kstrtos8(str, 10, &pd_asid) ? -EINVAL : pd_asid;
+}
+EXPORT_SYMBOL(qcom_get_pd_asid);
+
MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
index 34e5188187dc..27c913003ce3 100644
--- a/drivers/remoteproc/qcom_common.h
+++ b/drivers/remoteproc/qcom_common.h
@@ -62,5 +62,6 @@ static inline void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon)
{
}
#endif
+s8 qcom_get_pd_asid(struct device_node *node);
#endif
--
2.25.1

View File

@ -0,0 +1,382 @@
From 68d53f540aa5d433b395b4f4f583de8035639ebd Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Tue, 14 Mar 2023 18:28:06 +0000
Subject: [PATCH 3/4] soc: qcom: mdt_loader: Add necessary function to load
userpd
Spilt from <1678164097-13247-9-git-send-email-quic_mmanikan@quicinc.com>
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/soc/qcom/mdt_loader.c | 314 ++++++++++++++++++++++++++++
include/linux/soc/qcom/mdt_loader.h | 9 +
2 files changed, 323 insertions(+)
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 6034cd8992b0..3e3146add4ae 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -16,6 +16,40 @@
#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 PDSEG_PAS_ID 0xD
+
+/**
+ * struct region - structure passed to TrustZone
+ * @addr: address of dma region, where dma blocks/chunks address resides
+ * @blk_size: size of each block
+ */
+struct region {
+ u64 addr;
+ unsigned blk_size;
+};
+
+/**
+ * struct pdseg_dma_mem_info
+ * @tz_addr: reference to structure passed to trustzone
+ * @blocks: no of blocks
+ * @tz_dma: dma handle of tz_addr
+ * @dma_blk_arr_addr_phys: dma handle of dma_blk_arr_addr
+ * @dma_blk_arr_addr: VA of dma array, where each index points to
+ * dma block PA
+ * @pt: stores VA of each block
+ */
+
+struct pdseg_dma_mem_info {
+ struct region *tz_addr;
+ int blocks;
+ dma_addr_t tz_dma;
+ dma_addr_t dma_blk_arr_addr_phys;
+ u64 *dma_blk_arr_addr;
+ void **pt;
+};
static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
{
@@ -286,6 +320,259 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
return ret;
}
+static int allocate_dma_mem(struct device *dev,
+ struct pdseg_dma_mem_info *pd_dma,
+ int max_size)
+{
+ dma_addr_t dma_tmp = 0;
+ int i;
+
+ pd_dma->blocks = DIV_ROUND_UP(max_size, PAGE_SIZE);
+
+ /* Allocate dma memory for structure passed to trust zone */
+ pd_dma->tz_addr = dma_alloc_coherent(dev, sizeof(struct region),
+ &pd_dma->tz_dma, GFP_DMA);
+ if (!pd_dma->tz_addr) {
+ pr_err("Error in dma alloc\n");
+ return -ENOMEM;
+ }
+
+ /* Allocate dma memory to store array of blocks PA */
+ pd_dma->dma_blk_arr_addr =
+ dma_alloc_coherent(dev, (pd_dma->blocks * sizeof(u64)),
+ &pd_dma->dma_blk_arr_addr_phys, GFP_DMA);
+ if (!pd_dma->dma_blk_arr_addr) {
+ pr_err("Error in dma alloc\n");
+ goto free_tz_dma_alloc;
+ }
+
+ /* Assign dma block array PA to trustzone structure addr variable */
+ memcpy(&pd_dma->tz_addr->addr, &pd_dma->dma_blk_arr_addr_phys,
+ sizeof(dma_addr_t));
+
+ /* Allocate memory to store array of blocks VA */
+ pd_dma->pt = kzalloc(pd_dma->blocks * sizeof(void *), GFP_KERNEL);
+ if (!pd_dma->pt) {
+ pr_err("Error in memory alloc\n");
+ goto free_dma_blk_arr_alloc;
+ }
+
+ for (i = 0; i < pd_dma->blocks; i++) {
+ /* Allocate dma memory for blocks with PAGE_SIZE each */
+ pd_dma->pt[i] = dma_alloc_coherent(dev, PAGE_SIZE,
+ &dma_tmp, GFP_DMA);
+ if (!pd_dma->pt[i]) {
+ pr_err("Error in dma alloc i:%d - blocks:%d\n", i,
+ pd_dma->blocks);
+ goto free_mem_alloc;
+ }
+
+ /* Assign dma block PA to dma_blk_arr_addr */
+ memcpy(&pd_dma->dma_blk_arr_addr[i], &dma_tmp,
+ sizeof(dma_addr_t));
+ }
+ pd_dma->tz_addr->blk_size = PAGE_SIZE;
+ return 0;
+
+free_mem_alloc:
+ i = 0;
+ while (i < pd_dma->blocks && pd_dma->pt[i]) {
+ memcpy(&dma_tmp, &pd_dma->dma_blk_arr_addr[i],
+ sizeof(dma_addr_t));
+ dma_free_coherent(dev, PAGE_SIZE, pd_dma->pt[i], dma_tmp);
+ i++;
+ }
+ kfree(pd_dma->pt);
+free_dma_blk_arr_alloc:
+ dma_free_coherent(dev, (pd_dma->blocks * sizeof(u64)),
+ pd_dma->dma_blk_arr_addr,
+ pd_dma->dma_blk_arr_addr_phys);
+free_tz_dma_alloc:
+ dma_free_coherent(dev, sizeof(struct region), pd_dma->tz_addr,
+ pd_dma->tz_dma);
+
+ return -ENOMEM;
+}
+
+static void free_dma_mem(struct device *dev, struct pdseg_dma_mem_info *pd_dma)
+{
+ int i;
+ dma_addr_t dma_tmp = 0;
+
+ for (i = 0; i < pd_dma->blocks; i++) {
+ memcpy(&dma_tmp, &pd_dma->dma_blk_arr_addr[i],
+ sizeof(dma_addr_t));
+ dma_free_coherent(dev, PAGE_SIZE, pd_dma->pt[i],
+ dma_tmp);
+ }
+
+ dma_free_coherent(dev, (pd_dma->blocks * sizeof(u64)),
+ pd_dma->dma_blk_arr_addr,
+ pd_dma->dma_blk_arr_addr_phys);
+
+ dma_free_coherent(dev, sizeof(struct region), pd_dma->tz_addr,
+ pd_dma->tz_dma);
+ kfree(pd_dma->pt);
+}
+
+static int memcpy_pdseg_to_dma_blk(const char *fw_name, struct device *dev,
+ int ph_no, struct pdseg_dma_mem_info *pd_dma)
+{
+ const struct firmware *seg_fw;
+ int ret, offset_tmp = 0, tmp = 0;
+ size_t size = 0;
+
+ ret = request_firmware(&seg_fw, fw_name, dev);
+ if (ret) {
+ dev_err(dev, "failed to load %s\n", fw_name);
+ return ret;
+ }
+ size = seg_fw->size < PAGE_SIZE ?
+ seg_fw->size : PAGE_SIZE;
+ while (tmp < pd_dma->blocks && size) {
+ memset_io(pd_dma->pt[tmp], 0, PAGE_SIZE);
+ memcpy_toio(pd_dma->pt[tmp], seg_fw->data + offset_tmp, size);
+ tmp++;
+ offset_tmp += size;
+ if ((seg_fw->size - offset_tmp) < PAGE_SIZE)
+ size = seg_fw->size - offset_tmp;
+ }
+ release_firmware(seg_fw);
+ ret = qcom_scm_pas_load_seg(PDSEG_PAS_ID, ph_no, pd_dma->tz_dma,
+ tmp);
+ if (ret) {
+ dev_err(dev, "pd seg memcpy scm failed\n");
+ return ret;
+ }
+ return ret;
+}
+
+static int __qcom_mdt_load_pd_seg(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)
+{
+ const struct elf32_phdr *phdrs;
+ const struct elf32_phdr *phdr;
+ const struct elf32_hdr *ehdr;
+ phys_addr_t mem_reloc;
+ phys_addr_t min_addr = PHYS_ADDR_MAX;
+ ssize_t offset;
+ bool relocate = false;
+ int ret = 0;
+ int i;
+ u8 pd_asid;
+ int max_size = 0;
+ struct pdseg_dma_mem_info pd_dma = {0};
+ char *firmware_name;
+ size_t fw_name_len = strlen(fw_name);
+
+ if (!fw || !mem_region || !mem_phys || !mem_size)
+ return -EINVAL;
+
+ firmware_name = kstrdup(fw_name, GFP_KERNEL);
+ if (!firmware_name)
+ return -ENOMEM;
+
+ pd_asid = qcom_get_pd_asid(dev->of_node);
+
+ ehdr = (struct elf32_hdr *)fw->data;
+ phdrs = (struct elf32_phdr *)(ehdr + 1);
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &phdrs[i];
+
+ if (!mdt_phdr_valid(phdr))
+ continue;
+ /*
+ * While doing PD specific reloading, load only that PD
+ * specific writeable entries. Skip others
+ */
+ if ((QCOM_MDT_PF_ASID(phdr->p_flags) != pd_asid) ||
+ ((phdr->p_flags & PF_W) == 0))
+ continue;
+
+ if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
+ relocate = true;
+
+ if (phdr->p_paddr < min_addr)
+ min_addr = phdr->p_paddr;
+
+ if (max_size < phdr->p_memsz)
+ max_size = phdr->p_memsz;
+ }
+
+ /**
+ * During userpd PIL segments reloading, Q6 is live. Due to
+ * this we can't access memory region of PIL segments. So
+ * create DMA chunks/blocks to store PIL segments data.
+ */
+ ret = allocate_dma_mem(dev, &pd_dma, max_size);
+ if (ret)
+ goto out;
+
+ if (relocate) {
+ /*
+ * The image is relocatable, so offset each segment based on
+ * the lowest segment address.
+ */
+ mem_reloc = min_addr;
+ } else {
+ /*
+ * Image is not relocatable, so offset each segment based on
+ * the allocated physical chunk of memory.
+ */
+ mem_reloc = mem_phys;
+ }
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &phdrs[i];
+
+ if (!mdt_phdr_valid(phdr))
+ continue;
+
+ /*
+ * While doing PD specific reloading, load only that PD
+ * specific writeable entries. Skip others
+ */
+ if ((QCOM_MDT_PF_ASID(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");
+ ret = -EINVAL;
+ break;
+ }
+
+ if (phdr->p_filesz > phdr->p_memsz) {
+ dev_err(dev,
+ "refusing to load segment %d with p_filesz > p_memsz\n",
+ i);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (phdr->p_filesz) {
+ snprintf(firmware_name + fw_name_len - 3, 4, "b%02d", i);
+
+ /* copy PIL segments data to dma blocks */
+ ret = memcpy_pdseg_to_dma_blk(firmware_name, dev, i, &pd_dma);
+ if (ret)
+ goto free_dma;
+ }
+ }
+free_dma:
+ free_dma_mem(dev, &pd_dma);
+
+out:
+ if (reloc_base)
+ *reloc_base = mem_reloc;
+
+ return ret;
+}
+
/**
* qcom_mdt_load() - load the firmware which header is loaded as fw
* @dev: device handle to associate resources with
@@ -332,5 +619,32 @@ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw,
}
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, void *mem_region,
+ phys_addr_t mem_phys, size_t mem_size,
+ phys_addr_t *reloc_base)
+{
+ return __qcom_mdt_load_pd_seg(dev, fw, firmware, pas_id, mem_region, mem_phys,
+ mem_size, reloc_base, true);
+}
+EXPORT_SYMBOL_GPL(qcom_mdt_load_pd_seg);
+
MODULE_DESCRIPTION("Firmware parser for Qualcomm MDT format");
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h
index e600baec6825..1c63b0922ee4 100644
--- a/include/linux/soc/qcom/mdt_loader.h
+++ b/include/linux/soc/qcom/mdt_loader.h
@@ -7,6 +7,11 @@
#define QCOM_MDT_TYPE_MASK (7 << 24)
#define QCOM_MDT_TYPE_HASH (2 << 24)
#define QCOM_MDT_RELOCATABLE BIT(27)
+#define QCOM_MDT_ASID_MASK 0xfu
+#define QCOM_MDT_PF_ASID_SHIFT 16
+#define QCOM_MDT_PF_ASID_MASK (QCOM_MDT_ASID_MASK << QCOM_MDT_PF_ASID_SHIFT)
+#define QCOM_MDT_PF_ASID(x) \
+ (((x) >> QCOM_MDT_PF_ASID_SHIFT) & QCOM_MDT_ASID_MASK)
struct device;
struct firmware;
@@ -21,6 +26,10 @@ int qcom_mdt_load_no_init(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);
+int qcom_mdt_load_pd_seg(struct device *dev, const struct firmware *fw,
+ const char *firmware, int pas_id, void *mem_region,
+ phys_addr_t mem_phys, size_t mem_size,
+ phys_addr_t *reloc_base);
void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len);
#endif
--
2.25.1

View File

@ -0,0 +1,924 @@
From dd894fe4e3973e20f63e881641e854932ca8b4af Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Tue, 7 Mar 2023 10:11:34 +0530
Subject: [PATCH 4/4] remoteproc: qcom: Add Hexagon based multipd rproc driver
APSS brings Q6 out of reset and then Q6 brings
WCSS block (wifi radio's) out of reset.
---------------
--> |WiFi 2G radio|
| --------------
|
-------- ------- |
| APSS | ---> |QDSP6| -----|
--------- ------- |
|
|
| --------------
--> |WiFi 5G radio|
--------------
Problem here is if any radio crashes, subsequently other
radio also should crash because Q6 crashed. Let's say
2G radio crashed, Q6 should pass this info to APSS. Only
Q6 processor interrupts registered with APSS. Obviously
Q6 should crash and raise fatal interrupt to APSS. Due
to this 5G radio also crashed. But no issue in 5G radio,
because of 2G radio crash 5G radio also impacted.
In multi pd model, this problem is resolved. Here WCSS
functionality (WiFi radio's) moved out from Q6 root pd
to a separate user pd. Due to this, radio's independently
pass their status info to APPS with out crashing Q6. So
other radio's won't be impacted.
---------
|WiFi |
--> |2G radio|
| ---------
------ Start Q6 ------- |
| | ------------------> | | |
| | Start WCSS PD1 (2G) | | |
|APSS| ----------------------->|QDSP6|-----|
| | Start WCSS PD1 (5G) | |
| | ----------------------->| |-----|
------ ------- |
|
| -----------
|-->|WiFi |
|5G radio |
-----------
According to linux terminology, here consider Q6 as root
i.e it provide all services, WCSS (wifi radio's) as user
i.e it uses services provided by root.
Since Q6 root & WCSS user pd's able to communicate with
APSS individually, multipd remoteproc driver registers
each PD with rproc framework. Here clients (Wifi host drivers)
intrested on WCSS PD rproc, so multipd driver start's root
pd in the context of WCSS user pd rproc start. Similarly
on down path, root pd will be stopped after wcss user pd
stopped.
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.
rproc->ops->start(userpd_rproc) {
/* Boot root pd rproc */
rproc_boot(upd_dev->parent);
---
/* user pd rproc start sequence */
---
---
}
With this way we ensure that root pd brought up before userpd.
rproc->ops->stop(userpd_rproc) {
---
---
/* user pd rproc stop sequence */
---
---
/* Shutdown root pd rproc */
rproc_shutdown(upd_dev->parent);
}
After userpd rproc stops, root pd rproc will be stopped.
IPQ5018, IPQ9574 supports multipd remoteproc driver.
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Spilt from <1678164097-13247-9-git-send-email-quic_mmanikan@quicinc.com>
Remove uncessary member - remote_id
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/remoteproc/Kconfig | 20 +
drivers/remoteproc/Makefile | 1 +
drivers/remoteproc/qcom_q6v5.c | 37 +-
drivers/remoteproc/qcom_q6v5.h | 12 +
drivers/remoteproc/qcom_q6v5_mpd.c | 655 +++++++++++++++++++++++++++++
5 files changed, 722 insertions(+), 3 deletions(-)
create mode 100644 drivers/remoteproc/qcom_q6v5_mpd.c
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 94afdde4bc9f..6c1e4a0f7419 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -141,6 +141,26 @@ config QCOM_Q6V5_PAS
for the Qualcomm Hexagon v5 based remote processors. This is commonly
used to control subsystems such as ADSP, Compute and Sensor.
+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 y || RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on y || QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
+ select MFD_SYSCON
+ 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
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 00f09e658cb3..a195539b0972 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o
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
diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c
index fd6fd36268d9..8a2fa7aaf74d 100644
--- a/drivers/remoteproc/qcom_q6v5.c
+++ b/drivers/remoteproc/qcom_q6v5.c
@@ -74,7 +74,7 @@ static irqreturn_t q6v5_wdog_interrupt(int irq, void *data)
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;
@@ -92,7 +92,7 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t q6v5_ready_interrupt(int irq, void *data)
+irqreturn_t q6v5_ready_interrupt(int irq, void *data)
{
struct qcom_q6v5 *q6v5 = data;
@@ -134,7 +134,16 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *data)
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;
+}
+
+irqreturn_t q6v5_stop_interrupt(int irq, void *data)
{
struct qcom_q6v5 *q6v5 = data;
@@ -166,6 +175,28 @@ int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5)
}
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
diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h
index c4ed887c1499..9f4c36093985 100644
--- a/drivers/remoteproc/qcom_q6v5.h
+++ b/drivers/remoteproc/qcom_q6v5.h
@@ -14,18 +14,25 @@ struct qcom_q6v5 {
struct rproc *rproc;
struct qcom_smem_state *state;
+ struct qcom_smem_state *shutdown_state;
+ struct qcom_smem_state *spawn_state;
+
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;
@@ -41,7 +48,12 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
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
diff --git a/drivers/remoteproc/qcom_q6v5_mpd.c b/drivers/remoteproc/qcom_q6v5_mpd.c
new file mode 100644
index 000000000000..0e0e39715580
--- /dev/null
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -0,0 +1,655 @@
+// 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/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 <linux/qcom_scm.h>
+#include <linux/interrupt.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
+
+/**
+ * enum state - state of a wcss (private)
+ * @WCSS_NORMAL: subsystem is operating normally
+ * @WCSS_CRASHED: subsystem has crashed and hasn't been shutdown
+ * @WCSS_RESTARTING: subsystem has been shutdown and is now restarting
+ * @WCSS_SHUTDOWN: subsystem has been shutdown
+ *
+ */
+enum q6_wcss_state {
+ WCSS_NORMAL,
+ WCSS_CRASHED,
+ WCSS_RESTARTING,
+ WCSS_SHUTDOWN,
+};
+
+enum {
+ Q6_IPQ,
+ WCSS_AHB_IPQ,
+ WCSS_PCIE_IPQ,
+};
+
+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;
+ int crash_reason_smem;
+ u32 version;
+ s8 pd_asid;
+ enum q6_wcss_state state;
+};
+
+struct wcss_data {
+ int (*init_irq)(struct qcom_q6v5 *q6, struct platform_device *pdev,
+ struct rproc *rproc, int crash_reason,
+ void (*handover)(struct qcom_q6v5 *q6));
+ const char *q6_firmware_name;
+ int crash_reason_smem;
+ u32 version;
+ const char *ssr_name;
+ const struct rproc_ops *ops;
+ bool need_auto_boot;
+ bool glink_subdev_required;
+ s8 pd_asid;
+ bool reset_seq;
+ u32 pasid;
+ int (*mdt_load_sec)(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);
+};
+
+static int q6_wcss_start(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ int ret;
+ struct device_node *upd_np;
+ struct platform_device *upd_pdev;
+ struct rproc *upd_rproc;
+ struct q6_wcss *upd_wcss;
+ const struct wcss_data *desc;
+
+ desc = of_device_get_match_data(wcss->dev);
+ if (!desc)
+ return -EINVAL;
+
+ 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");
+
+ /* Bring userpd wcss state to default value */
+ for_each_available_child_of_node(wcss->dev->of_node, upd_np) {
+ if (!strstr(upd_np->name, "pd"))
+ continue;
+ upd_pdev = of_find_device_by_node(upd_np);
+ upd_rproc = platform_get_drvdata(upd_pdev);
+ upd_wcss = upd_rproc->priv;
+ upd_wcss->state = WCSS_NORMAL;
+ }
+ 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) {
+ pr_err("%s spawn timedout\n", rproc->name);
+ return ret;
+ }
+
+ ret = qcom_q6v5_wait_for_start(&wcss->q6, msecs_to_jiffies(10000));
+ if (ret == -ETIMEDOUT) {
+ pr_err("%s start timedout\n", rproc->name);
+ wcss->q6.running = false;
+ return ret;
+ }
+ wcss->q6.running = true;
+ return ret;
+}
+
+static int wcss_ahb_pcie_pd_start(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ const struct wcss_data *desc = of_device_get_match_data(wcss->dev);
+ int ret;
+
+ if (desc->reset_seq) {
+ ret = qcom_scm_pas_power_up(desc->pasid);
+ if (ret) {
+ dev_err(wcss->dev, "failed to power up ahb pd\n");
+ return ret;
+ }
+ }
+
+ if (wcss->q6.spawn_bit) {
+ ret = q6_wcss_spawn_pd(rproc);
+ if (ret)
+ return ret;
+ }
+
+ wcss->state = WCSS_NORMAL;
+ return 0;
+}
+
+static int q6_wcss_stop(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ int ret;
+ const struct wcss_data *desc =
+ of_device_get_match_data(wcss->dev);
+
+ if (!desc)
+ return -EINVAL;
+
+ ret = qcom_scm_pas_power_down(desc->pasid);
+ if (ret) {
+ dev_err(wcss->dev, "not able to shutdown\n");
+ return ret;
+ }
+ qcom_q6v5_unprepare(&wcss->q6);
+
+ return 0;
+}
+
+static int wcss_ahb_pcie_pd_stop(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
+ const struct wcss_data *desc = of_device_get_match_data(wcss->dev);
+ 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;
+ }
+ }
+
+ if (desc->reset_seq) {
+ ret = qcom_scm_pas_power_down(desc->pasid);
+ if (ret) {
+ dev_err(wcss->dev, "failed to power down pd\n");
+ return ret;
+ }
+ }
+
+ if (rproc->state != RPROC_CRASHED)
+ rproc_shutdown(rpd_rproc);
+
+ wcss->state = WCSS_SHUTDOWN;
+ 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;
+}
+
+static int q6_wcss_load(struct rproc *rproc, const struct firmware *fw)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ const struct firmware *m3_fw;
+ int ret;
+ const char *m3_fw_name;
+ struct device_node *upd_np;
+ struct platform_device *upd_pdev;
+ const struct wcss_data *desc =
+ of_device_get_match_data(wcss->dev);
+
+ if (!desc)
+ return -EINVAL;
+
+ /* load m3 firmware */
+ for_each_available_child_of_node(wcss->dev->of_node, upd_np) {
+ if (!strstr(upd_np->name, "pd"))
+ continue;
+ upd_pdev = of_find_device_by_node(upd_np);
+
+ ret = of_property_read_string(upd_np, "m3_firmware",
+ &m3_fw_name);
+ if (!ret && m3_fw_name) {
+ ret = request_firmware(&m3_fw, m3_fw_name,
+ &upd_pdev->dev);
+ if (ret)
+ continue;
+
+ ret = qcom_mdt_load_no_init(wcss->dev, m3_fw,
+ m3_fw_name, 0,
+ wcss->mem_region,
+ wcss->mem_phys,
+ wcss->mem_size,
+ &wcss->mem_reloc);
+
+ release_firmware(m3_fw);
+
+ if (ret) {
+ dev_err(wcss->dev,
+ "can't load m3_fw.bXX ret:%d\n", ret);
+ return ret;
+ }
+ }
+ }
+
+ return qcom_mdt_load(wcss->dev, fw, rproc->firmware,
+ desc->pasid, wcss->mem_region,
+ wcss->mem_phys, wcss->mem_size,
+ &wcss->mem_reloc);
+}
+
+static int wcss_ahb_pcie_pd_load(struct rproc *rproc, const struct firmware *fw)
+{
+ struct q6_wcss *wcss = rproc->priv, *wcss_rpd;
+ struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
+ int ret;
+ const struct wcss_data *desc =
+ of_device_get_match_data(wcss->dev);
+
+ if (!desc)
+ return -EINVAL;
+
+ wcss_rpd = rpd_rproc->priv;
+
+ /* Boot rootpd rproc */
+ ret = rproc_boot(rpd_rproc);
+ if (ret || wcss->state == WCSS_NORMAL)
+ return ret;
+
+ return desc->mdt_load_sec(wcss->dev, fw, rproc->firmware,
+ desc->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_ahb_pcie_ipq5018_ops = {
+ .start = wcss_ahb_pcie_pd_start,
+ .stop = wcss_ahb_pcie_pd_stop,
+ .load = wcss_ahb_pcie_pd_load,
+};
+
+static const struct rproc_ops q6_wcss_ipq5018_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,
+ 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_byname(pdev, int_name);
+ if (irq < 0) {
+ if (irq != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "failed to retrieve %s IRQ: %d\n",
+ int_name, irq);
+ return irq;
+ }
+
+ if (!strcmp(int_name, "fatal")) {
+ q6->fatal_irq = irq;
+ } else if (!strcmp(int_name, "stop-ack")) {
+ q6->stop_irq = irq;
+ tmp = "stop_ack";
+ } else if (!strcmp(int_name, "ready")) {
+ q6->ready_irq = irq;
+ } else if (!strcmp(int_name, "handover")) {
+ q6->handover_irq = irq;
+ } else if (!strcmp(int_name, "spawn-ack")) {
+ q6->spawn_irq = irq;
+ tmp = "spawn_ack";
+ } else {
+ dev_err(&pdev->dev, "unknown interrupt\n");
+ return -EINVAL;
+ }
+
+ interrupt = devm_kzalloc(&pdev->dev, BUF_SIZE, GFP_KERNEL);
+ if (!interrupt)
+ return -ENOMEM;
+
+ snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d", wcss->pd_asid);
+ strlcat(interrupt, "_", BUF_SIZE);
+ strlcat(interrupt, tmp, BUF_SIZE);
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq,
+ NULL, handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ interrupt, q6);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to acquire %s irq\n", interrupt);
+ return ret;
+ }
+ 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)) {
+ dev_err(&pdev->dev, "failed to acquire %s state\n", int_name);
+ return PTR_ERR(tmp_state);
+ }
+
+ 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, void (*handover)(struct qcom_q6v5 *q6))
+{
+ int ret;
+
+ 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_inbound_irq(q6, pdev, "fatal",
+ q6v5_fatal_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_inbound_irq(q6, pdev, "ready",
+ q6v5_ready_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_inbound_irq(q6, pdev, "stop-ack",
+ q6v5_stop_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_inbound_irq(q6, pdev, "spawn-ack",
+ q6v5_spawn_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_outbound_irq(q6, pdev, "stop");
+ if (ret)
+ return ret;
+
+ ret = q6_get_outbound_irq(q6, pdev, "spawn");
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int q6_wcss_probe(struct platform_device *pdev)
+{
+ const struct wcss_data *desc;
+ struct q6_wcss *wcss;
+ struct rproc *rproc;
+ int ret;
+ char *subdev_name;
+
+ desc = of_device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ rproc = rproc_alloc(&pdev->dev, pdev->name, desc->ops,
+ desc->q6_firmware_name, sizeof(*wcss));
+ if (!rproc) {
+ dev_err(&pdev->dev, "failed to allocate rproc\n");
+ return -ENOMEM;
+ }
+ wcss = rproc->priv;
+ wcss->dev = &pdev->dev;
+ wcss->version = desc->version;
+
+ ret = q6_alloc_memory_region(wcss);
+ if (ret)
+ goto free_rproc;
+
+ wcss->pd_asid = qcom_get_pd_asid(wcss->dev->of_node);
+ if (wcss->pd_asid < 0)
+ goto free_rproc;
+
+ if (desc->init_irq) {
+ ret = desc->init_irq(&wcss->q6, pdev, rproc,
+ desc->crash_reason_smem, NULL);
+ if (ret) {
+ if (wcss->version == Q6_IPQ)
+ goto free_rproc;
+ else
+ dev_info(wcss->dev,
+ "userpd irq registration failed\n");
+ }
+ }
+
+ if (desc->glink_subdev_required)
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, desc->ssr_name);
+
+ subdev_name = (char *)(desc->ssr_name ? desc->ssr_name : pdev->name);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, subdev_name);
+
+ rproc->auto_boot = desc->need_auto_boot;
+ ret = rproc_add(rproc);
+ if (ret)
+ goto free_rproc;
+
+ platform_set_drvdata(pdev, rproc);
+
+ ret = of_platform_populate(wcss->dev->of_node, NULL,
+ NULL, wcss->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to populate wcss pd nodes\n");
+ goto free_rproc;
+ }
+ 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);
+
+ rproc_del(rproc);
+ rproc_free(rproc);
+
+ return 0;
+}
+
+static const struct wcss_data q6_ipq5018_res_init = {
+ .init_irq = qcom_q6v5_init,
+ .q6_firmware_name = "IPQ5018/q6_fw.mdt",
+ .crash_reason_smem = WCSS_CRASH_REASON,
+ .ssr_name = "q6wcss",
+ .ops = &q6_wcss_ipq5018_ops,
+ .version = Q6_IPQ,
+ .glink_subdev_required = true,
+ .pasid = MPD_WCNSS_PAS_ID,
+};
+
+static const struct wcss_data q6_ipq9574_res_init = {
+ .init_irq = qcom_q6v5_init,
+ .q6_firmware_name = "IPQ9574/q6_fw.mdt",
+ .crash_reason_smem = WCSS_CRASH_REASON,
+ .ssr_name = "q6wcss",
+ .ops = &q6_wcss_ipq5018_ops,
+ .version = Q6_IPQ,
+ .glink_subdev_required = true,
+ .pasid = WCNSS_PAS_ID,
+};
+
+static const struct wcss_data wcss_ahb_ipq5018_res_init = {
+ .init_irq = init_irq,
+ .q6_firmware_name = "IPQ5018/q6_fw.mdt",
+ .crash_reason_smem = WCSS_CRASH_REASON,
+ .ops = &wcss_ahb_pcie_ipq5018_ops,
+ .version = WCSS_AHB_IPQ,
+ .pasid = MPD_WCNSS_PAS_ID,
+ .reset_seq = true,
+ .mdt_load_sec = qcom_mdt_load_pd_seg,
+};
+
+static const struct wcss_data wcss_ahb_ipq9574_res_init = {
+ .init_irq = init_irq,
+ .q6_firmware_name = "IPQ9574/q6_fw.mdt",
+ .crash_reason_smem = WCSS_CRASH_REASON,
+ .ops = &wcss_ahb_pcie_ipq5018_ops,
+ .version = WCSS_AHB_IPQ,
+ .pasid = WCNSS_PAS_ID,
+ .mdt_load_sec = qcom_mdt_load,
+};
+
+static const struct wcss_data wcss_pcie_ipq5018_res_init = {
+ .init_irq = init_irq,
+ .q6_firmware_name = "IPQ5018/q6_fw.mdt",
+ .crash_reason_smem = WCSS_CRASH_REASON,
+ .ops = &wcss_ahb_pcie_ipq5018_ops,
+ .version = WCSS_PCIE_IPQ,
+ .mdt_load_sec = qcom_mdt_load_pd_seg,
+ .pasid = MPD_WCNSS_PAS_ID,
+};
+
+static const struct of_device_id q6_wcss_of_match[] = {
+ { .compatible = "qcom,ipq5018-q6-mpd", .data = &q6_ipq5018_res_init },
+ { .compatible = "qcom,ipq9574-q6-mpd", .data = &q6_ipq9574_res_init },
+ { .compatible = "qcom,ipq5018-wcss-ahb-mpd",
+ .data = &wcss_ahb_ipq5018_res_init },
+ { .compatible = "qcom,ipq9574-wcss-ahb-mpd",
+ .data = &wcss_ahb_ipq9574_res_init },
+ { .compatible = "qcom,ipq5018-wcss-pcie-mpd",
+ .data = &wcss_pcie_ipq5018_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");
--
2.25.1

View File

@ -0,0 +1,63 @@
From c75fc58f0f506f2e4bcdebdb0f85977fae1099e9 Mon Sep 17 00:00:00 2001
From: Sivaprakash Murugesan <sivaprak@codeaurora.org>
Date: Mon, 18 May 2020 14:00:32 +0530
Subject: [PATCH 1/1] qcom: smp2p: add subsystem ack support
when subsystem ack support is added the APSS will ack for every smp2p
interrupt it received.
this is required for subsystem restart to re-negotiate the smp2p
features.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
Change-Id: Ic596ed07b0886a50240c3ff2ac140d904621eb20
Pick from https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/27084c62072d4a7db112a9761ba49be384ae09dd
Signed-off-by: hzy <hzyitc@outlook.com>
---
drivers/soc/qcom/smp2p.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index d42bcca3b98e..82ef4edb8ded 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -123,6 +123,7 @@ struct smp2p_entry {
* @mbox_chan: apcs ipc mailbox channel handle
* @inbound: list of inbound entries
* @outbound: list of outbound entries
+ * @need_ssr_ack fw expects ack for irq
*/
struct qcom_smp2p {
struct device *dev;
@@ -146,6 +147,7 @@ struct qcom_smp2p {
struct list_head inbound;
struct list_head outbound;
+ bool need_ssr_ack;
};
static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
@@ -236,6 +238,9 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data)
}
}
+ if (smp2p->need_ssr_ack)
+ qcom_smp2p_kick(smp2p);
+
return IRQ_HANDLED;
}
@@ -352,6 +357,8 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p,
/* Make the logical entry reference the physical value */
entry->value = &out->entries[out->valid_entries].value;
+ smp2p->need_ssr_ack = of_property_read_bool(node,
+ "qcom,smp2p-feature-ssr-ack");
out->valid_entries++;
--
2.25.1

View File

@ -0,0 +1,37 @@
From fcfe319cdebc5d7c505cff0c0884c3eb79ab38e0 Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Fri, 17 Mar 2023 21:46:22 +0000
Subject: [PATCH 1/4] arm64: dts: qcom: ipq5018: Add gic-v2m-frame node
Signed-off-by: hzy <hzyitc@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 8acf0ca6f470..5389f90fb46c 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -172,6 +172,19 @@
<0x0b001000 0x1000>, /*GICH*/
<0x0b004000 0x1000>; /*GICV*/
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ ranges = <0x0 0xb00a000 0x1ffa>;
+
+ v2m0: v2m@0 {
+ compatible = "arm,gic-v2m-frame";
+ msi-controller;
+ reg = <0x0 0xffd>;
+ };
+
+ v2m1: v2m@1000 {
+ compatible = "arm,gic-v2m-frame";
+ msi-controller;
+ reg = <0x1000 0xffd>;
+ };
};
apcs_glb: mailbox@b111000 {
--
2.25.1

View File

@ -0,0 +1,59 @@
From 1b4d56e98b31c26648209291a3747fe27ee8707a Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Fri, 17 Mar 2023 21:46:49 +0000
Subject: [PATCH 2/4] arm64: dts: qcom: ipq5018: Add smem node
Signed-off-by: hzy <hzyitc@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 5389f90fb46c..6d0746e0486c 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -108,12 +108,29 @@
no-map;
};
+ smem_region:smem@4ab00000 {
+ no-map;
+ reg = <0x0 0x4ab00000 0x0 0x00100000>;
+ };
+
tz: tz@4ac00000 {
reg = <0x0 0x4ac00000 0x0 0x00400000>;
no-map;
};
};
+ tcsr_mutex: hwlock {
+ compatible = "qcom,tcsr-mutex";
+ syscon = <&tcsr_mutex_regs 0 0x80>;
+ #hwlock-cells = <1>;
+ };
+
+ smem {
+ compatible = "qcom,smem";
+ memory-region = <&smem_region>;
+ hwlocks = <&tcsr_mutex 0>;
+ };
+
soc: soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -153,6 +170,11 @@
reg = <0x0193d100 0x4>;
};
+ tcsr_mutex_regs: syscon@1905000 {
+ compatible = "syscon";
+ reg = <0x01905000 0x8000>;
+ };
+
blsp1_uart1: serial@78af000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x078af000 0x200>;
--
2.25.1

View File

@ -0,0 +1,261 @@
From 263e16c91fa3386e8a0776b0bdcd4adde74b68c8 Mon Sep 17 00:00:00 2001
From: hzy <hzyitc@outlook.com>
Date: Fri, 17 Mar 2023 21:47:05 +0000
Subject: [PATCH 3/4] arm64: dts: qcom: ipq5018: Add Wifi node
Signed-off-by: hzy <hzyitc@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 238 ++++++++++++++++++++++++++
1 file changed, 238 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 6d0746e0486c..1ef5d33d2234 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -506,5 +506,243 @@
qcom,pvxlan-enabled;
qcom,udp-st-enabled;
};
+
+ q6v5_wcss: remoteproc@cd00000 {
+ compatible = "qcom,ipq5018-q6-mpd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ reg = <0x0cd00000 0x4040>;
+
+ interrupts-extended = <&intc GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
+ <&wcss_smp2p_in 0 0>,
+ <&wcss_smp2p_in 1 0>,
+ <&wcss_smp2p_in 2 0>,
+ <&wcss_smp2p_in 3 0>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ resets = <&gcc GCC_WCSSAON_RESET>,
+ <&gcc GCC_WCSS_BCR>,
+ <&gcc GCC_WCSS_Q6_BCR>,
+ <&gcc GCC_CE_BCR>;
+ reset-names = "wcss_aon_reset",
+ "wcss_reset",
+ "wcss_q6_reset",
+ "ce_reset";
+
+ clocks = <&gcc GCC_Q6_AXIS_CLK>,
+ <&gcc GCC_WCSS_AHB_S_CLK>,
+ <&gcc GCC_WCSS_ECAHB_CLK>,
+ <&gcc GCC_WCSS_ACMT_CLK>,
+ <&gcc GCC_WCSS_AXI_M_CLK>,
+ <&gcc GCC_Q6_AXIM_CLK>,
+ <&gcc GCC_Q6_AXIM2_CLK>,
+ <&gcc GCC_Q6_AHB_CLK>,
+ <&gcc GCC_Q6_AHB_S_CLK>,
+ <&gcc GCC_WCSS_AXI_S_CLK>;
+ clock-names = "gcc_q6_axis_clk",
+ "gcc_wcss_ahb_s_clk",
+ "gcc_wcss_ecahb_clk",
+ "gcc_wcss_acmt_clk",
+ "gcc_wcss_axi_m_clk",
+ "gcc_q6_axim_clk",
+ "gcc_q6_axim2_clk",
+ "gcc_q6_ahb_clk",
+ "gcc_q6_ahb_s_clk",
+ "gcc_wcss_axi_s_clk";
+
+ qcom,smem-states = <&wcss_smp2p_out 0>,
+ <&wcss_smp2p_out 1>;
+ qcom,smem-state-names = "shutdown",
+ "stop";
+
+ glink-edge {
+ interrupts = <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>;
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 8>;
+
+ qrtr_requests {
+ qcom,glink-channels = "IPCRTR";
+ };
+ };
+ };
+
+ wifi0: wifi@c000000 {
+ compatible = "qcom,cnss-qca5018", "qcom,ipq5018-wifi";
+ reg = <0xc000000 0x1000000>;
+
+ qcom,rproc = <&q6v5_wcss>;
+ interrupts = <GIC_SPI 288 IRQ_TYPE_EDGE_RISING>, /* o_wcss_apps_intr[0] = */
+ <GIC_SPI 289 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 290 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>, /* o_wcss_apps_intr[25] */
+
+ <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 342 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>; /* o_wcss_apps_intr[51] */
+
+ interrupt-names = "misc-pulse1",
+ "misc-latch",
+ "sw-exception",
+ "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-ring4",
+ "wbm2host-tx-completions-ring3",
+ "wbm2host-tx-completions-ring2",
+ "wbm2host-tx-completions-ring1",
+ "tcl2host-status-ring";
+
+ status = "disabled";
+ };
+
+ wifi1: wifi1@c000000 {
+ compatible = "qcom,cnss-qcn6122", "qcom,qcn6122-wifi";
+ msi-parent = <&v2m0>;
+ interrupts = <GIC_SPI 416 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ wifi2: wifi2@c000000 {
+ compatible = "qcom,cnss-qcn6122", "qcom,qcn6122-wifi";
+ msi-parent = <&v2m0>;
+ interrupts = <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ wifi3: wifi3@f00000 {
+ compatible = "qcom,cnss-qcn9000";
+ qcom,wlan-ramdump-dynamic = <0x400000>;
+ qrtr_node_id = <0x20>;
+ qca,auto-restart;
+ status = "disabled";
+ };
+
+ wifi4: wifi4@f00000 {
+ compatible = "qcom,cnss-qcn9000";
+ qcom,wlan-ramdump-dynamic = <0x400000>;
+ qrtr_node_id = <0x21>;
+ qca,auto-restart;
+ status = "disabled";
+ };
+
+ wcss: wcss-smp2p {
+ 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>;
+ };
+ };
};
};
--
2.25.1

View File

@ -0,0 +1,32 @@
From 8be6129cc81dd8eb9a110a1b12afbc1334bf621c Mon Sep 17 00:00:00 2001
From: Kathiravan T <kathirav@codeaurora.org>
Date: Tue, 16 Mar 2021 13:35:57 +0530
Subject: [PATCH 4/4] arm: qcom: enable ARM_GIC_V2M if PCI is defined
Enable ARM_GIC_V2M if PCI is enabled in ARCH_QCOM.
Signed-off-by: Kathiravan T <kathirav@codeaurora.org>
Change-Id: I18789ec868d4dfd58cf90f933fe71edc44bdafb4
Pick from https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/e09e0034811ae7007b533cc89c4c81d8e47bff77
Signed-off-by: hzy <hzyitc@outlook.com>
---
arch/arm/mach-qcom/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index ecbf3c4eb878..3b5efbf250af 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -7,6 +7,7 @@ menuconfig ARCH_QCOM
select ARM_AMBA
select PINCTRL
select QCOM_SCM if SMP
+ select ARM_GIC_V2M if PCI
help
Support for Qualcomm's devicetree based systems.
--
2.25.1