From ebb2c02b3943d30edebbacd6963ea72a26802ad7 Mon Sep 17 00:00:00 2001 From: hzy Date: Wed, 31 May 2023 21:35:17 +0000 Subject: [PATCH] ipq50xx: Prepare for WiFi --- package/kernel/linux/modules/netsupport.mk | 2 +- target/linux/ipq50xx/config-5.15 | 11 + ...8-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch | 60 ++ ...apss-ipq6018-fix-apcs_alias0_clk_src.patch | 70 ++ ...q-pll-use-OF-match-data-for-Alpha-PL.patch | 77 ++ ...q-pll-refactor-the-driver-to-accommo.patch | 122 +++ ...apss-ipq-pll-add-support-for-IPQ5018.patch | 94 ++ ...box-qcom-Add-ipq5018-apcs-compatible.patch | 25 + ...pq5018-Add-APSS-mailbox-and-clock-no.patch | 109 +++ ...m-Add-necessary-function-to-load-use.patch | 133 +++ ...remoteproc-qcom-Add-qcom_get_pd_asid.patch | 60 ++ ...der-Add-necessary-function-to-load-u.patch | 382 ++++++++ ...Add-Hexagon-based-multipd-rproc-driv.patch | 924 ++++++++++++++++++ ...qcom-smp2p-add-subsystem-ack-support.patch | 63 ++ ...-qcom-ipq5018-Add-gic-v2m-frame-node.patch | 37 + ...arm64-dts-qcom-ipq5018-Add-smem-node.patch | 59 ++ ...arm64-dts-qcom-ipq5018-Add-Wifi-node.patch | 261 +++++ ...enable-ARM_GIC_V2M-if-PCI-is-defined.patch | 32 + 18 files changed, 2520 insertions(+), 1 deletion(-) create mode 100644 target/linux/ipq50xx/patches/032-08-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch create mode 100644 target/linux/ipq50xx/patches/032-09-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch create mode 100644 target/linux/ipq50xx/patches/032-11-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch create mode 100644 target/linux/ipq50xx/patches/381-clk-qcom-apss-ipq-pll-refactor-the-driver-to-accommo.patch create mode 100644 target/linux/ipq50xx/patches/382-clk-qcom-apss-ipq-pll-add-support-for-IPQ5018.patch create mode 100644 target/linux/ipq50xx/patches/383-mailbox-qcom-Add-ipq5018-apcs-compatible.patch create mode 100644 target/linux/ipq50xx/patches/384-arm64-dts-qcom-ipq5018-Add-APSS-mailbox-and-clock-no.patch create mode 100644 target/linux/ipq50xx/patches/801-firmware-qcom_scm-Add-necessary-function-to-load-use.patch create mode 100644 target/linux/ipq50xx/patches/802-remoteproc-qcom-Add-qcom_get_pd_asid.patch create mode 100644 target/linux/ipq50xx/patches/803-soc-qcom-mdt_loader-Add-necessary-function-to-load-u.patch create mode 100644 target/linux/ipq50xx/patches/804-remoteproc-qcom-Add-Hexagon-based-multipd-rproc-driv.patch create mode 100644 target/linux/ipq50xx/patches/811-qcom-smp2p-add-subsystem-ack-support.patch create mode 100644 target/linux/ipq50xx/patches/821-arm64-dts-qcom-ipq5018-Add-gic-v2m-frame-node.patch create mode 100644 target/linux/ipq50xx/patches/822-arm64-dts-qcom-ipq5018-Add-smem-node.patch create mode 100644 target/linux/ipq50xx/patches/823-arm64-dts-qcom-ipq5018-Add-Wifi-node.patch create mode 100644 target/linux/ipq50xx/patches/824-arm-qcom-enable-ARM_GIC_V2M-if-PCI-is-defined.patch diff --git a/package/kernel/linux/modules/netsupport.mk b/package/kernel/linux/modules/netsupport.mk index 4fcb9ed60d..ab7f711056 100644 --- a/package/kernel/linux/modules/netsupport.mk +++ b/package/kernel/linux/modules/netsupport.mk @@ -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) diff --git a/target/linux/ipq50xx/config-5.15 b/target/linux/ipq50xx/config-5.15 index 4093ea7f14..8091409aa8 100644 --- a/target/linux/ipq50xx/config-5.15 +++ b/target/linux/ipq50xx/config-5.15 @@ -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 diff --git a/target/linux/ipq50xx/patches/032-08-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch b/target/linux/ipq50xx/patches/032-08-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch new file mode 100644 index 0000000000..d18336fba5 --- /dev/null +++ b/target/linux/ipq50xx/patches/032-08-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch @@ -0,0 +1,60 @@ +From 9bb1a40325c0c4b0489abf8f5dc5cc376ea5d677 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +Signed-off-by: Robert Marko +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-1-robimarko@gmail.com +(cherry picked from commit c5d2c96b3a7bd8987fad9957510034130037fccf) +Signed-off-by: hzy +--- + 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 + diff --git a/target/linux/ipq50xx/patches/032-09-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch b/target/linux/ipq50xx/patches/032-09-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch new file mode 100644 index 0000000000..ba44334392 --- /dev/null +++ b/target/linux/ipq50xx/patches/032-09-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch @@ -0,0 +1,70 @@ +From 8d0cae8ef89cf131db5bfb9c8f2d584a56ce3825 Mon Sep 17 00:00:00 2001 +From: Robert Marko +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 +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-2-robimarko@gmail.com +(cherry picked from commit 43a56cbf2a38170b02db29654607575b1b4b5bc0) +Signed-off-by: hzy +--- + 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 + diff --git a/target/linux/ipq50xx/patches/032-11-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch b/target/linux/ipq50xx/patches/032-11-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch new file mode 100644 index 0000000000..cc97a014b7 --- /dev/null +++ b/target/linux/ipq50xx/patches/032-11-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch @@ -0,0 +1,77 @@ +From 8c570373e004ff38d1bb4a1a002d05528bb9ad9a Mon Sep 17 00:00:00 2001 +From: Robert Marko +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 +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-5-robimarko@gmail.com +(cherry picked from commit 823a117e1d97b57d1ef9932c55cc02d6d7ba0523) +Signed-off-by: hzy +--- + 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 + #include ++#include + #include + #include + +@@ -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 + diff --git a/target/linux/ipq50xx/patches/381-clk-qcom-apss-ipq-pll-refactor-the-driver-to-accommo.patch b/target/linux/ipq50xx/patches/381-clk-qcom-apss-ipq-pll-refactor-the-driver-to-accommo.patch new file mode 100644 index 0000000000..7e050a69e4 --- /dev/null +++ b/target/linux/ipq50xx/patches/381-clk-qcom-apss-ipq-pll-refactor-the-driver-to-accommo.patch @@ -0,0 +1,122 @@ +From 54d4b22e66cb1df52b4a14bee49aaa198a788439 Mon Sep 17 00:00:00 2001 +From: Kathiravan T +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 +Reviewed-by: Konrad Dybcio + +Pick from <20230208042850.1687-2-quic_kathirav@quicinc.com> + +Signed-off-by: hzy +--- + 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 + diff --git a/target/linux/ipq50xx/patches/382-clk-qcom-apss-ipq-pll-add-support-for-IPQ5018.patch b/target/linux/ipq50xx/patches/382-clk-qcom-apss-ipq-pll-add-support-for-IPQ5018.patch new file mode 100644 index 0000000000..e9daae3038 --- /dev/null +++ b/target/linux/ipq50xx/patches/382-clk-qcom-apss-ipq-pll-add-support-for-IPQ5018.patch @@ -0,0 +1,94 @@ +From c224630bf98c2870e7425eb43a5a965e81a01d32 Mon Sep 17 00:00:00 2001 +From: hzy +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 +--- + 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 + diff --git a/target/linux/ipq50xx/patches/383-mailbox-qcom-Add-ipq5018-apcs-compatible.patch b/target/linux/ipq50xx/patches/383-mailbox-qcom-Add-ipq5018-apcs-compatible.patch new file mode 100644 index 0000000000..6e76782299 --- /dev/null +++ b/target/linux/ipq50xx/patches/383-mailbox-qcom-Add-ipq5018-apcs-compatible.patch @@ -0,0 +1,25 @@ +From bf7c9ce914d992c3993d2d18c95a2f2ae130ce1e Mon Sep 17 00:00:00 2001 +From: hzy +Date: Tue, 14 Mar 2023 17:09:04 +0000 +Subject: [PATCH 3/4] mailbox: qcom: Add ipq5018 apcs compatible + +Signed-off-by: hzy +--- + 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 + diff --git a/target/linux/ipq50xx/patches/384-arm64-dts-qcom-ipq5018-Add-APSS-mailbox-and-clock-no.patch b/target/linux/ipq50xx/patches/384-arm64-dts-qcom-ipq5018-Add-APSS-mailbox-and-clock-no.patch new file mode 100644 index 0000000000..aaa5c9d722 --- /dev/null +++ b/target/linux/ipq50xx/patches/384-arm64-dts-qcom-ipq5018-Add-APSS-mailbox-and-clock-no.patch @@ -0,0 +1,109 @@ +From c22fb5533f31593bbc8ffa603c69ec002338ca5a Mon Sep 17 00:00:00 2001 +From: hzy +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 +--- + 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 + #include + #include ++#include + + / { + #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 = ; + }; + ++ 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 = , +-- +2.25.1 + diff --git a/target/linux/ipq50xx/patches/801-firmware-qcom_scm-Add-necessary-function-to-load-use.patch b/target/linux/ipq50xx/patches/801-firmware-qcom_scm-Add-necessary-function-to-load-use.patch new file mode 100644 index 0000000000..2e3681bae7 --- /dev/null +++ b/target/linux/ipq50xx/patches/801-firmware-qcom_scm-Add-necessary-function-to-load-use.patch @@ -0,0 +1,133 @@ +From 424c7e86813fc1395ab95f67e0ccd5db314fbca5 Mon Sep 17 00:00:00 2001 +From: hzy +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 +--- + 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 + diff --git a/target/linux/ipq50xx/patches/802-remoteproc-qcom-Add-qcom_get_pd_asid.patch b/target/linux/ipq50xx/patches/802-remoteproc-qcom-Add-qcom_get_pd_asid.patch new file mode 100644 index 0000000000..49be3c7afc --- /dev/null +++ b/target/linux/ipq50xx/patches/802-remoteproc-qcom-Add-qcom_get_pd_asid.patch @@ -0,0 +1,60 @@ +From 5b634205941367936b834b03ed219370e979fbf4 Mon Sep 17 00:00:00 2001 +From: hzy +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 +--- + 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 + diff --git a/target/linux/ipq50xx/patches/803-soc-qcom-mdt_loader-Add-necessary-function-to-load-u.patch b/target/linux/ipq50xx/patches/803-soc-qcom-mdt_loader-Add-necessary-function-to-load-u.patch new file mode 100644 index 0000000000..603133ca5c --- /dev/null +++ b/target/linux/ipq50xx/patches/803-soc-qcom-mdt_loader-Add-necessary-function-to-load-u.patch @@ -0,0 +1,382 @@ +From 68d53f540aa5d433b395b4f4f583de8035639ebd Mon Sep 17 00:00:00 2001 +From: hzy +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 +--- + 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 + #include + #include ++#include ++ ++#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 + diff --git a/target/linux/ipq50xx/patches/804-remoteproc-qcom-Add-Hexagon-based-multipd-rproc-driv.patch b/target/linux/ipq50xx/patches/804-remoteproc-qcom-Add-Hexagon-based-multipd-rproc-driv.patch new file mode 100644 index 0000000000..98978bca68 --- /dev/null +++ b/target/linux/ipq50xx/patches/804-remoteproc-qcom-Add-Hexagon-based-multipd-rproc-driv.patch @@ -0,0 +1,924 @@ +From dd894fe4e3973e20f63e881641e854932ca8b4af Mon Sep 17 00:00:00 2001 +From: Manikanta Mylavarapu +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 + +Spilt from <1678164097-13247-9-git-send-email-quic_mmanikan@quicinc.com> + +Remove uncessary member - remote_id + +Signed-off-by: hzy +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 + diff --git a/target/linux/ipq50xx/patches/811-qcom-smp2p-add-subsystem-ack-support.patch b/target/linux/ipq50xx/patches/811-qcom-smp2p-add-subsystem-ack-support.patch new file mode 100644 index 0000000000..1d5440f013 --- /dev/null +++ b/target/linux/ipq50xx/patches/811-qcom-smp2p-add-subsystem-ack-support.patch @@ -0,0 +1,63 @@ +From c75fc58f0f506f2e4bcdebdb0f85977fae1099e9 Mon Sep 17 00:00:00 2001 +From: Sivaprakash Murugesan +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 +Change-Id: Ic596ed07b0886a50240c3ff2ac140d904621eb20 + +Pick from https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/27084c62072d4a7db112a9761ba49be384ae09dd + +Signed-off-by: hzy +--- + 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 + diff --git a/target/linux/ipq50xx/patches/821-arm64-dts-qcom-ipq5018-Add-gic-v2m-frame-node.patch b/target/linux/ipq50xx/patches/821-arm64-dts-qcom-ipq5018-Add-gic-v2m-frame-node.patch new file mode 100644 index 0000000000..2d6b54468b --- /dev/null +++ b/target/linux/ipq50xx/patches/821-arm64-dts-qcom-ipq5018-Add-gic-v2m-frame-node.patch @@ -0,0 +1,37 @@ +From fcfe319cdebc5d7c505cff0c0884c3eb79ab38e0 Mon Sep 17 00:00:00 2001 +From: hzy +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 +--- + 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 = ; ++ 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 + diff --git a/target/linux/ipq50xx/patches/822-arm64-dts-qcom-ipq5018-Add-smem-node.patch b/target/linux/ipq50xx/patches/822-arm64-dts-qcom-ipq5018-Add-smem-node.patch new file mode 100644 index 0000000000..37d680db80 --- /dev/null +++ b/target/linux/ipq50xx/patches/822-arm64-dts-qcom-ipq5018-Add-smem-node.patch @@ -0,0 +1,59 @@ +From 1b4d56e98b31c26648209291a3747fe27ee8707a Mon Sep 17 00:00:00 2001 +From: hzy +Date: Fri, 17 Mar 2023 21:46:49 +0000 +Subject: [PATCH 2/4] arm64: dts: qcom: ipq5018: Add smem node + +Signed-off-by: hzy +--- + 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 + diff --git a/target/linux/ipq50xx/patches/823-arm64-dts-qcom-ipq5018-Add-Wifi-node.patch b/target/linux/ipq50xx/patches/823-arm64-dts-qcom-ipq5018-Add-Wifi-node.patch new file mode 100644 index 0000000000..9986da76bc --- /dev/null +++ b/target/linux/ipq50xx/patches/823-arm64-dts-qcom-ipq5018-Add-Wifi-node.patch @@ -0,0 +1,261 @@ +From 263e16c91fa3386e8a0776b0bdcd4adde74b68c8 Mon Sep 17 00:00:00 2001 +From: hzy +Date: Fri, 17 Mar 2023 21:47:05 +0000 +Subject: [PATCH 3/4] arm64: dts: qcom: ipq5018: Add Wifi node + +Signed-off-by: hzy +--- + 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 = ; ++ 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 = , /* o_wcss_apps_intr[0] = */ ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , /* o_wcss_apps_intr[25] */ ++ ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ++ , ++ ++ , ++ , ++ , ++ , ++ , ++ , ++ ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; /* 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 = ; ++ status = "disabled"; ++ }; ++ ++ wifi2: wifi2@c000000 { ++ compatible = "qcom,cnss-qcn6122", "qcom,qcn6122-wifi"; ++ msi-parent = <&v2m0>; ++ interrupts = ; ++ 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 = ; ++ ++ 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 + diff --git a/target/linux/ipq50xx/patches/824-arm-qcom-enable-ARM_GIC_V2M-if-PCI-is-defined.patch b/target/linux/ipq50xx/patches/824-arm-qcom-enable-ARM_GIC_V2M-if-PCI-is-defined.patch new file mode 100644 index 0000000000..086dae411c --- /dev/null +++ b/target/linux/ipq50xx/patches/824-arm-qcom-enable-ARM_GIC_V2M-if-PCI-is-defined.patch @@ -0,0 +1,32 @@ +From 8be6129cc81dd8eb9a110a1b12afbc1334bf621c Mon Sep 17 00:00:00 2001 +From: Kathiravan T +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 +Change-Id: I18789ec868d4dfd58cf90f933fe71edc44bdafb4 + +Pick from https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/e09e0034811ae7007b533cc89c4c81d8e47bff77 + +Signed-off-by: hzy +--- + 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 +