From ec2850e40ceb182b81d7ad74686d96585fbedebc Mon Sep 17 00:00:00 2001 From: Alexey Minnekhanov Date: Tue, 25 Mar 2025 11:37:13 +0300 Subject: phy: Add SDM660 support to Qualcomm QUSB2 phy Imported from Linux driver. Note that already existing but previously unused member of struct qusb2_phy::has_se_clk_scheme is now utilized for it's purpose. Signed-off-by: Alexey Minnekhanov Reviewed-by: Caleb Connolly Link: https://lore.kernel.org/r/20250325083713.2425430-1-alexeymin@postmarketos.org Signed-off-by: Caleb Connolly --- drivers/phy/qcom/phy-qcom-qusb2.c | 42 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/phy/qcom/phy-qcom-qusb2.c b/drivers/phy/qcom/phy-qcom-qusb2.c index c91ba18c4ab..cabd05bf5a6 100644 --- a/drivers/phy/qcom/phy-qcom-qusb2.c +++ b/drivers/phy/qcom/phy-qcom-qusb2.c @@ -122,6 +122,9 @@ struct qusb2_phy_cfg { /* true if PHY has PLL_CORE_INPUT_OVERRIDE register to reset PLL */ bool has_pll_override; + + /* true if PHY default clk scheme is single-ended */ + bool se_clk_scheme_default; }; /* set of registers with offsets different per-PHY */ @@ -173,6 +176,19 @@ static const unsigned int sm6115_regs_layout[] = { [QUSB2PHY_PORT_POWERDOWN] = 0xb4, [QUSB2PHY_INTR_CTRL] = 0xbc, }; +static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = { + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), +}; + static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = { QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03), QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c), @@ -219,6 +235,18 @@ static const struct qusb2_phy_cfg sm6115_phy_cfg = { .autoresume_en = BIT(3), }; +static const struct qusb2_phy_cfg sdm660_phy_cfg = { + .tbl = msm8996_init_tbl, + .tbl_num = ARRAY_SIZE(msm8996_init_tbl), + .regs = sm6115_regs_layout, + + .has_pll_test = true, + .se_clk_scheme_default = false, + .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), + .mask_core_ready = PLL_LOCKED, + .autoresume_en = BIT(3), +}; + static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = { .tbl = qusb2_v2_init_tbl, .tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl), @@ -316,8 +344,18 @@ static int qusb2phy_power_on(struct phy *phy) /* Required to get phy pll lock successfully */ udelay(150); + /* + * Not all the SoCs have got a readable TCSR_PHY_CLK_SCHEME + * register in the TCSR so, if there's none, use the default + * value hardcoded in the configuration. + */ + qphy->has_se_clk_scheme = cfg->se_clk_scheme_default; + if (cfg->has_pll_test) { - val |= CLK_REF_SEL; + if (!qphy->has_se_clk_scheme) + val &= ~CLK_REF_SEL; + else + val |= CLK_REF_SEL; writel(val, qphy->base + QUSB2PHY_PLL_TEST); @@ -413,6 +451,8 @@ static const struct udevice_id qusb2phy_ids[] = { { .compatible = "qcom,qusb2-phy" }, { .compatible = "qcom,qcm2290-qusb2-phy", .data = (ulong)&sm6115_phy_cfg }, + { .compatible = "qcom,sdm660-qusb2-phy", + .data = (ulong)&sdm660_phy_cfg }, { .compatible = "qcom,sm6115-qusb2-phy", .data = (ulong)&sm6115_phy_cfg }, { .compatible = "qcom,qusb2-v2-phy", .data = (ulong)&qusb2_v2_phy_cfg }, -- cgit v1.3.1 From ec8209d04a46546c3e58752544413158aebbfae2 Mon Sep 17 00:00:00 2001 From: Sam Day Date: Wed, 19 Mar 2025 15:45:29 +0000 Subject: clk/qcom: sdm845: add missing USB3 clocks These are necessary for USB gadget to come up properly, now that qcom_gate_clk_en fails on unknown clocks. Signed-off-by: Sam Day Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250319-sdm845-usb-clocks-v1-1-ddea854f62ec@samcday.com Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-sdm845.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index 6a0bf16ba2d..7fd875e55d5 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -77,7 +77,9 @@ static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate) } static const struct gate_clk sdm845_clks[] = { + GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, 0x00000001), GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x82020, 0x00000001), + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x0502c, 0x00000001), GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x05030, 0x00000001), GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, 0x00000400), GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, 0x00000800), -- cgit v1.3.1 From 7c07628e5b5ad6a2914613fb3e83797280567ce9 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 24 Mar 2025 19:17:37 +0100 Subject: clk/stub: add sdm845 rpmh clock Necessary for UFS to successfully probe all clocks. Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250324-sdm845-fixes-fastboot-v1-1-d177a10f336d@linaro.org Signed-off-by: Caleb Connolly --- drivers/clk/clk-stub.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c index 343fa5cd3fe..521ecfc5917 100644 --- a/drivers/clk/clk-stub.c +++ b/drivers/clk/clk-stub.c @@ -50,6 +50,7 @@ static struct clk_ops stub_clk_ops = { static const struct udevice_id stub_clk_ids[] = { { .compatible = "qcom,rpmcc" }, + { .compatible = "qcom,sdm845-rpmh-clk" }, { .compatible = "qcom,sc7280-rpmh-clk" }, { .compatible = "qcom,sm8150-rpmh-clk" }, { .compatible = "qcom,sm8250-rpmh-clk" }, -- cgit v1.3.1 From c8db6bdba6dc4ca5f9570994c8640ba08a27e62e Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 24 Mar 2025 19:17:38 +0100 Subject: clk/qcom: sdm845: add GCC_AGGRE_UFS_PHY_AXI_CLK Missing for UFS. Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250324-sdm845-fixes-fastboot-v1-2-d177a10f336d@linaro.org Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-sdm845.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index 7fd875e55d5..5c8702ef2fe 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -114,6 +114,7 @@ static const struct gate_clk sdm845_clks[] = { GATE_CLK(GCC_UFS_CARD_TX_SYMBOL_0_CLK, 0x75014, 0x00000001), GATE_CLK(GCC_UFS_CARD_UNIPRO_CORE_CLK, 0x75054, 0x00000001), GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001), + GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x82024, 0x00000001), GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77010, 0x00000001), GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x7700c, 0x00000001), GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77058, 0x00000001), -- cgit v1.3.1 From 925efba5793d5ab0aca4b0e5f1378f50d228d191 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 27 Feb 2025 09:45:50 +0000 Subject: power: regulator: add qcom-usb-vbus Add regulator driver that allow some Qualcomm PMIC to feed VBUS output to peripherals that are connected. Signed-off-by: Rui Miguel Silva Acked-by: Caleb Connolly Reviewed-by: Neil Armstrong Reviewed-by: Caleb Connolly Link: https://lore.kernel.org/r/20250227094911.497219-3-rui.silva@linaro.org Signed-off-by: Caleb Connolly --- drivers/power/regulator/Kconfig | 7 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/qcom_usb_vbus_regulator.c | 111 ++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 drivers/power/regulator/qcom_usb_vbus_regulator.c (limited to 'drivers') diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 8f102a92c23..bab68317cfa 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -224,6 +224,13 @@ config DM_REGULATOR_QCOM_RPMH implements get/set api for a limited set of regulators used by u-boot. +config DM_REGULATOR_QCOM_USB_VBUS + bool "Enable driver model for Qualcomm USB vbus regulator" + depends on DM_REGULATOR + ---help--- + Enable support for the Qualcomm USB Vbus regulator. The driver + implements get/set api for the regulator to be used by u-boot. + config SPL_DM_REGULATOR_GPIO bool "Enable Driver Model for GPIO REGULATOR in SPL" depends on DM_REGULATOR_GPIO && SPL_GPIO diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 4382d4b3ab9..054a93e129a 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_$(XPL_)DM_REGULATOR_COMMON) += regulator_common.o obj-$(CONFIG_$(XPL_)DM_REGULATOR_FIXED) += fixed.o obj-$(CONFIG_$(XPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_DM_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o +obj-$(CONFIG_DM_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus_regulator.o obj-$(CONFIG_$(PHASE_)REGULATOR_RK8XX) += rk8xx.o obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o diff --git a/drivers/power/regulator/qcom_usb_vbus_regulator.c b/drivers/power/regulator/qcom_usb_vbus_regulator.c new file mode 100644 index 00000000000..2d58ef5e111 --- /dev/null +++ b/drivers/power/regulator/qcom_usb_vbus_regulator.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2025, Linaro Limited + */ +#define pr_fmt(fmt) "qcom_usb_vbus: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMD_OTG 0x50 +#define OTG_EN BIT(0) +// The 0 bit in this register's bit field is undocumented +#define OTG_CFG 0x56 +#define OTG_EN_SRC_CFG BIT(1) + +struct qcom_usb_vbus_priv { + phys_addr_t base; +}; + +static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev) +{ + struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev) +{ + struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); + int otg_en_reg = priv->base + CMD_OTG; + int ret; + + ret = pmic_reg_read(dev->parent, otg_en_reg); + if (ret < 0) + log_err("failed to read usb vbus: %d\n", ret); + else + ret &= OTG_EN; + + return ret; +} + +static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable) +{ + struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); + int otg_en_reg = priv->base + CMD_OTG; + int ret; + + if (enable) { + ret = pmic_clrsetbits(dev->parent, otg_en_reg, 0, OTG_EN); + if (ret < 0) { + log_err("error enabling: %d\n", ret); + return ret; + } + } else { + ret = pmic_clrsetbits(dev->parent, otg_en_reg, OTG_EN, 0); + if (ret < 0) { + log_err("error disabling: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int qcom_usb_vbus_regulator_probe(struct udevice *dev) +{ + struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); + int otg_cfg_reg = priv->base + OTG_CFG; + int ret; + + /* Disable HW logic for VBUS enable */ + ret = pmic_clrsetbits(dev->parent, otg_cfg_reg, OTG_EN_SRC_CFG, 0); + if (ret < 0) { + log_err("error setting EN_SRC_CFG: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct dm_regulator_ops qcom_usb_vbus_regulator_ops = { + .get_enable = qcom_usb_vbus_regulator_get_enable, + .set_enable = qcom_usb_vbus_regulator_set_enable, +}; + +static const struct udevice_id qcom_usb_vbus_regulator_ids[] = { + { .compatible = "qcom,pm8150b-vbus-reg"}, + { }, +}; + +U_BOOT_DRIVER(qcom_usb_vbus_regulator) = { + .name = "qcom-usb-vbus-regulator", + .id = UCLASS_REGULATOR, + .of_match = qcom_usb_vbus_regulator_ids, + .of_to_plat = qcom_usb_vbus_regulator_of_to_plat, + .ops = &qcom_usb_vbus_regulator_ops, + .probe = qcom_usb_vbus_regulator_probe, + .priv_auto = sizeof(struct qcom_usb_vbus_priv), +}; -- cgit v1.3.1 From b2f89b33d3355f009fdaf304985d23df0e428bdf Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Mon, 24 Mar 2025 17:00:30 +0530 Subject: regulator: qcom-rpmh-regulator: add support for pmm8654 regulators Add the PMC8380 regulator data found on the Qualcomm SA8775P platform. The tables are imported from the Linux driver. Signed-off-by: Varadarajan Narayanan Reviewed-by: Caleb Connolly Link: https://lore.kernel.org/r/20250324113030.2597986-1-quic_varada@quicinc.com Signed-off-by: Caleb Connolly --- drivers/power/regulator/qcom-rpmh-regulator.c | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c b/drivers/power/regulator/qcom-rpmh-regulator.c index cd2b1a654c1..954deca5ed7 100644 --- a/drivers/power/regulator/qcom-rpmh-regulator.c +++ b/drivers/power/regulator/qcom-rpmh-regulator.c @@ -466,6 +466,25 @@ static const struct rpmh_vreg_hw_data pmic5_nldo515 = { .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo), }; +static const struct rpmh_vreg_hw_data pmic5_ftsmps527 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), + .n_voltages = 215, + .pmic_mode_map = pmic_mode_map_pmic5_smps, + .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_smps), +}; + +static const struct rpmh_vreg_hw_data pmic5_pldo515_mv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(1800000, 0, 187, 8000), + .n_voltages = 188, + .hpm_min_load_uA = 10000, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, + .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo), +}; + #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \ { \ .name = _name, \ @@ -558,6 +577,28 @@ static const struct rpmh_vreg_init_data pmc8380_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pmm8654au_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps527, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps527, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps527, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps527, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps527, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps527, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps527, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps527, "vdd-s8"), + RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps527, "vdd-s9"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-s9"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2-l3"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l2-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo515, "vdd-s9"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo515, "vdd-s9"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo515, "vdd-l6-l7"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo515, "vdd-l6-l7"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo515_mv, "vdd-l8-l9"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"), + {} +}; + /* probe an individual regulator */ static int rpmh_regulator_probe(struct udevice *dev) { @@ -688,6 +729,10 @@ static const struct udevice_id rpmh_regulator_ids[] = { .compatible = "qcom,pmc8380-rpmh-regulators", .data = (ulong)pmc8380_vreg_data, }, + { + .compatible = "qcom,pmm8654au-rpmh-regulators", + .data = (ulong)pmm8654au_vreg_data, + }, { /* sentinal */ }, }; -- cgit v1.3.1 From 5effb1e62556e5d84c2fc037f7020d26cdf3b9ca Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Mon, 24 Mar 2025 13:35:03 +0530 Subject: pinctrl: qcom: add driver for SA8775P SoC Add pinctrl and GPIO driver for SA8775P. Driver code is based on the similar U-Boot and Linux drivers. Signed-off-by: Varadarajan Narayanan Reviewed-by: Caleb Connolly Link: https://lore.kernel.org/r/20250324080504.2385747-1-quic_varada@quicinc.com Signed-off-by: Caleb Connolly --- drivers/pinctrl/qcom/Kconfig | 8 +- drivers/pinctrl/qcom/Makefile | 1 + drivers/pinctrl/qcom/pinctrl-sa8775p.c | 623 +++++++++++++++++++++++++++++++++ 3 files changed, 631 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/qcom/pinctrl-sa8775p.c (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index f4a3942ee2f..e24287c978f 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -48,12 +48,18 @@ config PINCTRL_QCOM_QCS404 Say Y here to enable support for pinctrl on the Snapdragon QCS404 SoC, as well as the associated GPIO driver. +config PINCTRL_QCOM_SA8775P + bool "Qualcomm SA8775P Pinctrl" + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the Snapdragon SA8775P SoC, + as well as the associated GPIO driver. + config PINCTRL_QCOM_SC7280 bool "Qualcomm SC7280/QCM6490 Pinctrl" select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC, - as well as the associated GPIO driver. config PINCTRL_QCOM_SDM845 bool "Qualcomm SDM845 Pinctrl" diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 94cdc6e4a62..65d1845ea54 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PINCTRL_QCOM_IPQ9574) += pinctrl-ipq9574.o obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o +obj-$(CONFIG_PINCTRL_QCOM_SA8775P) += pinctrl-sa8775p.o obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c new file mode 100644 index 00000000000..cb2496ff1fb --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023, Linaro Limited + */ + +#include + +#include "pinctrl-qcom.h" + +#define MAX_PIN_NAME_LEN 32 +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); + +typedef unsigned int msm_pin_function[10]; +#define SA8775_PIN_OFFSET 0x100000 + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)\ + { \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + } + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = pg_name, \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + } + +#define UFS_RESET(pg_name, ctl) \ + { \ + .name = pg_name, \ + .ctl_reg = ctl, \ + .io_reg = ctl + 0x4, \ + .pull_bit = 3, \ + .drv_bit = 0, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = 0, \ + } + +enum sa8775p_functions { + msm_mux_gpio, + msm_mux_atest_char, + msm_mux_atest_usb2, + msm_mux_audio_ref, + msm_mux_cam_mclk, + msm_mux_cci_async, + msm_mux_cci_i2c, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cci_timer3, + msm_mux_cci_timer4, + msm_mux_cci_timer5, + msm_mux_cci_timer6, + msm_mux_cci_timer7, + msm_mux_cci_timer8, + msm_mux_cci_timer9, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_dbg_out, + msm_mux_ddr_bist, + msm_mux_ddr_pxi0, + msm_mux_ddr_pxi1, + msm_mux_ddr_pxi2, + msm_mux_ddr_pxi3, + msm_mux_ddr_pxi4, + msm_mux_ddr_pxi5, + msm_mux_edp0_hot, + msm_mux_edp0_lcd, + msm_mux_edp1_hot, + msm_mux_edp1_lcd, + msm_mux_edp2_hot, + msm_mux_edp2_lcd, + msm_mux_edp3_hot, + msm_mux_edp3_lcd, + msm_mux_emac0_mcg0, + msm_mux_emac0_mcg1, + msm_mux_emac0_mcg2, + msm_mux_emac0_mcg3, + msm_mux_emac0_mdc, + msm_mux_emac0_mdio, + msm_mux_emac0_ptp_aux, + msm_mux_emac0_ptp_pps, + msm_mux_emac1_mcg0, + msm_mux_emac1_mcg1, + msm_mux_emac1_mcg2, + msm_mux_emac1_mcg3, + msm_mux_emac1_mdc, + msm_mux_emac1_mdio, + msm_mux_emac1_ptp_aux, + msm_mux_emac1_ptp_pps, + msm_mux_gcc_gp1, + msm_mux_gcc_gp2, + msm_mux_gcc_gp3, + msm_mux_gcc_gp4, + msm_mux_gcc_gp5, + msm_mux_hs0_mi2s, + msm_mux_hs1_mi2s, + msm_mux_hs2_mi2s, + msm_mux_ibi_i3c, + msm_mux_jitter_bist, + msm_mux_mdp0_vsync0, + msm_mux_mdp0_vsync1, + msm_mux_mdp0_vsync2, + msm_mux_mdp0_vsync3, + msm_mux_mdp0_vsync4, + msm_mux_mdp0_vsync5, + msm_mux_mdp0_vsync6, + msm_mux_mdp0_vsync7, + msm_mux_mdp0_vsync8, + msm_mux_mdp1_vsync0, + msm_mux_mdp1_vsync1, + msm_mux_mdp1_vsync2, + msm_mux_mdp1_vsync3, + msm_mux_mdp1_vsync4, + msm_mux_mdp1_vsync5, + msm_mux_mdp1_vsync6, + msm_mux_mdp1_vsync7, + msm_mux_mdp1_vsync8, + msm_mux_mdp_vsync, + msm_mux_mi2s1_data0, + msm_mux_mi2s1_data1, + msm_mux_mi2s1_sck, + msm_mux_mi2s1_ws, + msm_mux_mi2s2_data0, + msm_mux_mi2s2_data1, + msm_mux_mi2s2_sck, + msm_mux_mi2s2_ws, + msm_mux_mi2s_mclk0, + msm_mux_mi2s_mclk1, + msm_mux_pcie0_clkreq, + msm_mux_pcie1_clkreq, + msm_mux_phase_flag, + msm_mux_pll_bist, + msm_mux_pll_clk, + msm_mux_prng_rosc0, + msm_mux_prng_rosc1, + msm_mux_prng_rosc2, + msm_mux_prng_rosc3, + msm_mux_qdss_cti, + msm_mux_qdss_gpio, + msm_mux_qup0_se0, + msm_mux_qup0_se1, + msm_mux_qup0_se2, + msm_mux_qup0_se3, + msm_mux_qup0_se4, + msm_mux_qup0_se5, + msm_mux_qup1_se0, + msm_mux_qup1_se1, + msm_mux_qup1_se2, + msm_mux_qup1_se3, + msm_mux_qup1_se4, + msm_mux_qup1_se5, + msm_mux_qup1_se6, + msm_mux_qup2_se0, + msm_mux_qup2_se1, + msm_mux_qup2_se2, + msm_mux_qup2_se3, + msm_mux_qup2_se4, + msm_mux_qup2_se5, + msm_mux_qup2_se6, + msm_mux_qup3_se0, + msm_mux_sail_top, + msm_mux_sailss_emac0, + msm_mux_sailss_ospi, + msm_mux_sgmii_phy, + msm_mux_tb_trig, + msm_mux_tgu_ch0, + msm_mux_tgu_ch1, + msm_mux_tgu_ch2, + msm_mux_tgu_ch3, + msm_mux_tgu_ch4, + msm_mux_tgu_ch5, + msm_mux_tsense_pwm1, + msm_mux_tsense_pwm2, + msm_mux_tsense_pwm3, + msm_mux_tsense_pwm4, + msm_mux_usb2phy_ac, + msm_mux_vsense_trigger, + msm_mux__, +}; + +#define MSM_PIN_FUNCTION(fname) \ + [msm_mux_##fname] = {#fname, msm_mux_##fname} + +static const struct pinctrl_function msm_pinctrl_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(edp0_hot), + MSM_PIN_FUNCTION(edp0_lcd), + MSM_PIN_FUNCTION(edp1_hot), + MSM_PIN_FUNCTION(edp1_lcd), + MSM_PIN_FUNCTION(edp2_hot), + MSM_PIN_FUNCTION(edp2_lcd), + MSM_PIN_FUNCTION(edp3_hot), + MSM_PIN_FUNCTION(edp3_lcd), + MSM_PIN_FUNCTION(emac0_mcg0), + MSM_PIN_FUNCTION(emac0_mcg1), + MSM_PIN_FUNCTION(emac0_mcg2), + MSM_PIN_FUNCTION(emac0_mcg3), + MSM_PIN_FUNCTION(emac0_mdc), + MSM_PIN_FUNCTION(emac0_mdio), + MSM_PIN_FUNCTION(emac0_ptp_aux), + MSM_PIN_FUNCTION(emac0_ptp_pps), + MSM_PIN_FUNCTION(emac1_mcg0), + MSM_PIN_FUNCTION(emac1_mcg1), + MSM_PIN_FUNCTION(emac1_mcg2), + MSM_PIN_FUNCTION(emac1_mcg3), + MSM_PIN_FUNCTION(emac1_mdc), + MSM_PIN_FUNCTION(emac1_mdio), + MSM_PIN_FUNCTION(emac1_ptp_aux), + MSM_PIN_FUNCTION(emac1_ptp_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(hs0_mi2s), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp0_vsync0), + MSM_PIN_FUNCTION(mdp0_vsync1), + MSM_PIN_FUNCTION(mdp0_vsync2), + MSM_PIN_FUNCTION(mdp0_vsync3), + MSM_PIN_FUNCTION(mdp0_vsync4), + MSM_PIN_FUNCTION(mdp0_vsync5), + MSM_PIN_FUNCTION(mdp0_vsync6), + MSM_PIN_FUNCTION(mdp0_vsync7), + MSM_PIN_FUNCTION(mdp0_vsync8), + MSM_PIN_FUNCTION(mdp1_vsync0), + MSM_PIN_FUNCTION(mdp1_vsync1), + MSM_PIN_FUNCTION(mdp1_vsync2), + MSM_PIN_FUNCTION(mdp1_vsync3), + MSM_PIN_FUNCTION(mdp1_vsync4), + MSM_PIN_FUNCTION(mdp1_vsync5), + MSM_PIN_FUNCTION(mdp1_vsync6), + MSM_PIN_FUNCTION(mdp1_vsync7), + MSM_PIN_FUNCTION(mdp1_vsync8), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mi2s_mclk0), + MSM_PIN_FUNCTION(mi2s_mclk1), + MSM_PIN_FUNCTION(pcie0_clkreq), + MSM_PIN_FUNCTION(pcie1_clkreq), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0_se0), + MSM_PIN_FUNCTION(qup0_se1), + MSM_PIN_FUNCTION(qup0_se2), + MSM_PIN_FUNCTION(qup0_se3), + MSM_PIN_FUNCTION(qup0_se4), + MSM_PIN_FUNCTION(qup0_se5), + MSM_PIN_FUNCTION(qup1_se0), + MSM_PIN_FUNCTION(qup1_se1), + MSM_PIN_FUNCTION(qup1_se2), + MSM_PIN_FUNCTION(qup1_se3), + MSM_PIN_FUNCTION(qup1_se4), + MSM_PIN_FUNCTION(qup1_se5), + MSM_PIN_FUNCTION(qup1_se6), + MSM_PIN_FUNCTION(qup2_se0), + MSM_PIN_FUNCTION(qup2_se1), + MSM_PIN_FUNCTION(qup2_se2), + MSM_PIN_FUNCTION(qup2_se3), + MSM_PIN_FUNCTION(qup2_se4), + MSM_PIN_FUNCTION(qup2_se5), + MSM_PIN_FUNCTION(qup2_se6), + MSM_PIN_FUNCTION(qup3_se0), + MSM_PIN_FUNCTION(sail_top), + MSM_PIN_FUNCTION(sailss_emac0), + MSM_PIN_FUNCTION(sailss_ospi), + MSM_PIN_FUNCTION(sgmii_phy), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tgu_ch4), + MSM_PIN_FUNCTION(tgu_ch5), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(tsense_pwm4), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), +}; + +static const msm_pin_function sa8775p_pin_functions[] = { + [0] = PINGROUP(0, _, _, _, _, _, _, _, _, _), + [1] = PINGROUP(1, pcie0_clkreq, _, _, _, _, _, _, _, _), + [2] = PINGROUP(2, _, _, _, _, _, _, _, _, _), + [3] = PINGROUP(3, pcie1_clkreq, _, _, _, _, _, _, _, _), + [4] = PINGROUP(4, _, _, _, _, _, _, _, _, _), + [5] = PINGROUP(5, _, _, _, _, _, _, _, _, _), + [6] = PINGROUP(6, emac0_ptp_aux, emac0_ptp_pps, emac1_ptp_aux, + emac1_ptp_pps, _, _, _, _, _), + [7] = PINGROUP(7, sgmii_phy, _, _, _, _, _, _, _, _), + [8] = PINGROUP(8, emac0_mdc, _, _, _, _, _, _, _, _), + [9] = PINGROUP(9, emac0_mdio, _, _, _, _, _, _, _, _), + [10] = PINGROUP(10, usb2phy_ac, emac0_ptp_aux, emac0_ptp_pps, + emac1_ptp_aux, emac1_ptp_pps, _, _, _, _), + [11] = PINGROUP(11, usb2phy_ac, emac0_ptp_aux, emac0_ptp_pps, + emac1_ptp_aux, emac1_ptp_pps, _, _, _, _), + [12] = PINGROUP(12, usb2phy_ac, emac0_ptp_aux, emac0_ptp_pps, + emac1_ptp_aux, emac1_ptp_pps, emac0_mcg0, _, _, _), + [13] = PINGROUP(13, qup3_se0, emac0_mcg1, _, _, sail_top, _, _, _, _), + [14] = PINGROUP(14, qup3_se0, emac0_mcg2, _, _, sail_top, _, _, _, _), + [15] = PINGROUP(15, qup3_se0, emac0_mcg3, _, _, sail_top, _, _, _, _), + [16] = PINGROUP(16, qup3_se0, emac1_mcg0, _, _, sail_top, _, _, _, _), + [17] = PINGROUP(17, qup3_se0, tb_trig, tb_trig, emac1_mcg1, _, _, _, _, _), + [18] = PINGROUP(18, qup3_se0, emac1_mcg2, _, _, sailss_ospi, sailss_emac0, _, _, _), + [19] = PINGROUP(19, qup3_se0, emac1_mcg3, _, _, sailss_ospi, sailss_emac0, _, _, _), + [20] = PINGROUP(20, qup0_se0, emac1_mdc, qdss_gpio, _, _, _, _, _, _), + [21] = PINGROUP(21, qup0_se0, emac1_mdio, qdss_gpio, _, _, _, _, _, _), + [22] = PINGROUP(22, qup0_se0, qdss_gpio, _, _, _, _, _, _, _), + [23] = PINGROUP(23, qup0_se0, qdss_gpio, _, _, _, _, _, _, _), + [24] = PINGROUP(24, qup0_se1, qdss_gpio, _, _, _, _, _, _, _), + [25] = PINGROUP(25, qup0_se1, phase_flag, _, qdss_gpio, _, _, _, _, _), + [26] = PINGROUP(26, sgmii_phy, qup0_se1, qdss_cti, phase_flag, _, _, _, _, _), + [27] = PINGROUP(27, qup0_se1, qdss_cti, phase_flag, _, atest_char, _, _, _, _), + [28] = PINGROUP(28, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _), + [29] = PINGROUP(29, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _), + [30] = PINGROUP(30, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _), + [31] = PINGROUP(31, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _), + [32] = PINGROUP(32, qup0_se4, phase_flag, _, _, _, _, _, _, _), + [33] = PINGROUP(33, qup0_se4, gcc_gp4, _, ddr_pxi0, _, _, _, _, _), + [34] = PINGROUP(34, qup0_se4, gcc_gp5, _, ddr_pxi0, _, _, _, _, _), + [35] = PINGROUP(35, qup0_se4, phase_flag, _, _, _, _, _, _, _), + [36] = PINGROUP(36, qup0_se2, qup0_se5, phase_flag, tgu_ch2, _, _, _, _, _), + [37] = PINGROUP(37, qup0_se2, qup0_se5, phase_flag, tgu_ch3, _, _, _, _, _), + [38] = PINGROUP(38, qup0_se5, qup0_se2, qdss_cti, phase_flag, tgu_ch4, _, _, _, _), + [39] = PINGROUP(39, qup0_se5, qup0_se2, qdss_cti, phase_flag, tgu_ch5, _, _, _, _), + [40] = PINGROUP(40, qup1_se0, qup1_se1, ibi_i3c, mdp1_vsync0, _, _, _, _, _), + [41] = PINGROUP(41, qup1_se0, qup1_se1, ibi_i3c, mdp1_vsync1, _, _, _, _, _), + [42] = PINGROUP(42, qup1_se1, qup1_se0, ibi_i3c, mdp1_vsync2, gcc_gp5, _, _, _, _), + [43] = PINGROUP(43, qup1_se1, qup1_se0, ibi_i3c, mdp1_vsync3, _, _, _, _, _), + [44] = PINGROUP(44, qup1_se2, qup1_se3, edp0_lcd, _, _, _, _, _, _), + [45] = PINGROUP(45, qup1_se2, qup1_se3, edp1_lcd, _, _, _, _, _, _), + [46] = PINGROUP(46, qup1_se3, qup1_se2, mdp1_vsync4, tgu_ch0, _, _, _, _, _), + [47] = PINGROUP(47, qup1_se3, qup1_se2, mdp1_vsync5, tgu_ch1, _, _, _, _, _), + [48] = PINGROUP(48, qup1_se4, qdss_cti, edp2_lcd, _, _, _, _, _, _), + [49] = PINGROUP(49, qup1_se4, qdss_cti, edp3_lcd, _, _, _, _, _, _), + [50] = PINGROUP(50, qup1_se4, cci_async, qdss_cti, mdp1_vsync8, _, _, _, _, _), + [51] = PINGROUP(51, qup1_se4, qdss_cti, mdp1_vsync6, gcc_gp1, _, _, _, _, _), + [52] = PINGROUP(52, qup1_se5, cci_timer4, cci_i2c, mdp1_vsync7, gcc_gp2, _, ddr_pxi1, _, _), + [53] = PINGROUP(53, qup1_se5, cci_timer5, cci_i2c, gcc_gp3, _, ddr_pxi1, _, _, _), + [54] = PINGROUP(54, qup1_se5, cci_timer6, cci_i2c, _, _, _, _, _, _), + [55] = PINGROUP(55, qup1_se5, cci_timer7, cci_i2c, gcc_gp4, _, ddr_pxi2, _, _, _), + [56] = PINGROUP(56, qup1_se6, qup1_se6, cci_timer8, cci_i2c, phase_flag, ddr_bist, _, _, _), + [57] = PINGROUP(57, qup1_se6, qup1_se6, cci_timer9, cci_i2c, + mdp0_vsync0, phase_flag, ddr_bist, _, _), + [58] = PINGROUP(58, cci_i2c, mdp0_vsync1, ddr_bist, _, atest_usb2, atest_char, _, _, _), + [59] = PINGROUP(59, cci_i2c, mdp0_vsync2, ddr_bist, _, atest_usb2, atest_char, _, _, _), + [60] = PINGROUP(60, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [61] = PINGROUP(61, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [62] = PINGROUP(62, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [63] = PINGROUP(63, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [64] = PINGROUP(64, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [65] = PINGROUP(65, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [66] = PINGROUP(66, cci_i2c, cci_async, qdss_gpio, _, _, _, _, _, _), + [67] = PINGROUP(67, cci_i2c, qdss_gpio, _, _, _, _, _, _, _), + [68] = PINGROUP(68, cci_timer0, cci_async, _, _, _, _, _, _, _), + [69] = PINGROUP(69, cci_timer1, cci_async, _, _, _, _, _, _, _), + [70] = PINGROUP(70, cci_timer2, cci_async, _, _, _, _, _, _, _), + [71] = PINGROUP(71, cci_timer3, cci_async, _, _, _, _, _, _, _), + [72] = PINGROUP(72, cam_mclk, _, _, _, _, _, _, _, _), + [73] = PINGROUP(73, cam_mclk, _, _, _, _, _, _, _, _), + [74] = PINGROUP(74, cam_mclk, _, _, _, _, _, _, _, _), + [75] = PINGROUP(75, cam_mclk, _, _, _, _, _, _, _, _), + [76] = PINGROUP(76, _, _, _, _, _, _, _, _, _), + [77] = PINGROUP(77, _, _, _, _, _, _, _, _, _), + [78] = PINGROUP(78, _, _, _, _, _, _, _, _, _), + [79] = PINGROUP(79, _, _, _, _, _, _, _, _, _), + [80] = PINGROUP(80, qup2_se0, ibi_i3c, mdp0_vsync3, _, _, _, _, _, _), + [81] = PINGROUP(81, qup2_se0, ibi_i3c, mdp0_vsync4, _, _, _, _, _, _), + [82] = PINGROUP(82, qup2_se0, mdp_vsync, gcc_gp1, _, _, _, _, _, _), + [83] = PINGROUP(83, qup2_se0, mdp_vsync, gcc_gp2, _, _, _, _, _, _), + [84] = PINGROUP(84, qup2_se1, qup2_se5, ibi_i3c, mdp_vsync, gcc_gp3, _, _, _, _), + [85] = PINGROUP(85, qup2_se1, qup2_se5, ibi_i3c, _, _, _, _, _, _), + [86] = PINGROUP(86, qup2_se2, jitter_bist, atest_usb2, ddr_pxi2, _, _, _, _, _), + [87] = PINGROUP(87, qup2_se2, pll_clk, atest_usb2, ddr_pxi3, _, _, _, _, _), + [88] = PINGROUP(88, qup2_se2, _, atest_usb2, ddr_pxi3, _, _, _, _, _), + [89] = PINGROUP(89, qup2_se2, _, atest_usb2, ddr_pxi4, atest_char, _, _, _, _), + [90] = PINGROUP(90, qup2_se2, _, atest_usb2, ddr_pxi4, atest_char, _, _, _, _), + [91] = PINGROUP(91, qup2_se3, mdp0_vsync5, _, atest_usb2, _, _, _, _, _), + [92] = PINGROUP(92, qup2_se3, mdp0_vsync6, _, atest_usb2, _, _, _, _, _), + [93] = PINGROUP(93, qup2_se3, mdp0_vsync7, _, atest_usb2, _, _, _, _, _), + [94] = PINGROUP(94, qup2_se3, mdp0_vsync8, _, atest_usb2, _, _, _, _, _), + [95] = PINGROUP(95, qup2_se4, qup2_se6, _, atest_usb2, _, _, _, _, _), + [96] = PINGROUP(96, qup2_se4, qup2_se6, _, atest_usb2, _, _, _, _, _), + [97] = PINGROUP(97, qup2_se6, qup2_se4, cri_trng0, _, atest_usb2, _, _, _, _), + [98] = PINGROUP(98, qup2_se6, qup2_se4, phase_flag, cri_trng1, _, _, _, _, _), + [99] = PINGROUP(99, qup2_se5, qup2_se1, phase_flag, cri_trng, _, _, _, _, _), + [100] = PINGROUP(100, qup2_se5, qup2_se1, _, _, _, _, _, _, _), + [101] = PINGROUP(101, edp0_hot, prng_rosc0, tsense_pwm4, _, _, _, _, _, _), + [102] = PINGROUP(102, edp1_hot, prng_rosc1, tsense_pwm3, _, _, _, _, _, _), + [103] = PINGROUP(103, edp3_hot, prng_rosc2, tsense_pwm2, _, _, _, _, _, _), + [104] = PINGROUP(104, edp2_hot, prng_rosc3, tsense_pwm1, _, _, _, _, _, _), + [105] = PINGROUP(105, mi2s_mclk0, _, qdss_gpio, atest_usb2, _, _, _, _, _), + [106] = PINGROUP(106, mi2s1_sck, phase_flag, _, qdss_gpio, _, _, _, _, _), + [107] = PINGROUP(107, mi2s1_ws, phase_flag, _, qdss_gpio, _, _, _, _, _), + [108] = PINGROUP(108, mi2s1_data0, phase_flag, _, qdss_gpio, _, _, _, _, _), + [109] = PINGROUP(109, mi2s1_data1, phase_flag, _, qdss_gpio, _, _, _, _, _), + [110] = PINGROUP(110, mi2s2_sck, phase_flag, _, qdss_gpio, _, _, _, _, _), + [111] = PINGROUP(111, mi2s2_ws, phase_flag, _, qdss_gpio, vsense_trigger, _, _, _, _), + [112] = PINGROUP(112, mi2s2_data0, phase_flag, _, qdss_gpio, _, _, _, _, _), + [113] = PINGROUP(113, mi2s2_data1, audio_ref, phase_flag, _, qdss_gpio, _, _, _, _), + [114] = PINGROUP(114, hs0_mi2s, pll_bist, phase_flag, _, qdss_gpio, _, _, _, _), + [115] = PINGROUP(115, hs0_mi2s, _, qdss_gpio, _, _, _, _, _, _), + [116] = PINGROUP(116, hs0_mi2s, _, qdss_gpio, _, _, _, _, _, _), + [117] = PINGROUP(117, hs0_mi2s, mi2s_mclk1, _, qdss_gpio, _, _, _, _, _), + [118] = PINGROUP(118, hs1_mi2s, _, qdss_gpio, ddr_pxi5, _, _, _, _, _), + [119] = PINGROUP(119, hs1_mi2s, _, qdss_gpio, ddr_pxi5, _, _, _, _, _), + [120] = PINGROUP(120, hs1_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _), + [121] = PINGROUP(121, hs1_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _), + [122] = PINGROUP(122, hs2_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _), + [123] = PINGROUP(123, hs2_mi2s, phase_flag, _, _, _, _, _, _, _), + [124] = PINGROUP(124, hs2_mi2s, phase_flag, _, _, _, _, _, _, _), + [125] = PINGROUP(125, hs2_mi2s, phase_flag, _, _, _, _, _, _, _), + [126] = PINGROUP(126, _, _, _, _, _, _, _, _, _), + [127] = PINGROUP(127, _, _, _, _, _, _, _, _, _), + [128] = PINGROUP(128, _, _, _, _, _, _, _, _, _), + [129] = PINGROUP(129, _, _, _, _, _, _, _, _, _), + [130] = PINGROUP(130, _, _, _, _, _, _, _, _, _), + [131] = PINGROUP(131, _, _, _, _, _, _, _, _, _), + [132] = PINGROUP(132, _, _, _, _, _, _, _, _, _), + [133] = PINGROUP(133, _, _, _, _, _, _, _, _, _), + [134] = PINGROUP(134, _, _, _, _, _, _, _, _, _), + [135] = PINGROUP(135, _, _, _, _, _, _, _, _, _), + [136] = PINGROUP(136, _, _, _, _, _, _, _, _, _), + [137] = PINGROUP(137, _, _, _, _, _, _, _, _, _), + [138] = PINGROUP(138, _, _, _, _, _, _, _, _, _), + [139] = PINGROUP(139, _, _, _, _, _, _, _, _, _), + [140] = PINGROUP(140, _, _, _, _, _, _, _, _, _), + [141] = PINGROUP(141, _, _, _, _, _, _, _, _, _), + [142] = PINGROUP(142, _, _, _, _, _, _, _, _, _), + [143] = PINGROUP(143, _, _, _, _, _, _, _, _, _), + [144] = PINGROUP(144, dbg_out, _, _, _, _, _, _, _, _), + [145] = PINGROUP(145, _, _, _, _, _, _, _, _, _), + [146] = PINGROUP(146, _, _, _, _, _, _, _, _, _), + [147] = PINGROUP(147, _, _, _, _, _, _, _, _, _), + [148] = PINGROUP(148, _, _, _, _, _, _, _, _, _), +}; + +static const struct msm_special_pin_data msm_special_pins_data[] = { + [0] = UFS_RESET("ufs_reset", 0x1a2000), + [1] = SDC_QDSD_PINGROUP("sdc1_rclk", 0x199000, 15, 0), + [2] = SDC_QDSD_PINGROUP("sdc1_clk", 0x199000, 13, 6), + [3] = SDC_QDSD_PINGROUP("sdc1_cmd", 0x199000, 11, 3), + [4] = SDC_QDSD_PINGROUP("sdc1_data", 0x199000, 9, 0), +}; + +static const char *sa8775p_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return msm_pinctrl_functions[selector].name; +} + +static const char *sa8775p_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + if (selector >= 149 && selector <= 155) + snprintf(pin_name, MAX_PIN_NAME_LEN, + msm_special_pins_data[selector - 149].name); + else + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + + return pin_name; +} + +static int sa8775p_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) +{ + unsigned int i; + const msm_pin_function *func = sa8775p_pin_functions + pin; + + for (i = 0; i < 10; i++) + if ((*func)[i] == selector) + return i; + + pr_err("Can't find requested function for pin %u pin\n", pin); + + return -EINVAL; +} + +static const unsigned int sa8775p_pin_offsets[] = { + [0] = SA8775_PIN_OFFSET, [1] = SA8775_PIN_OFFSET, [2] = SA8775_PIN_OFFSET, + [3] = SA8775_PIN_OFFSET, [4] = SA8775_PIN_OFFSET, [5] = SA8775_PIN_OFFSET, + [6] = SA8775_PIN_OFFSET, [7] = SA8775_PIN_OFFSET, [8] = SA8775_PIN_OFFSET, + [9] = SA8775_PIN_OFFSET, [10] = SA8775_PIN_OFFSET, [11] = SA8775_PIN_OFFSET, + [12] = SA8775_PIN_OFFSET, [13] = SA8775_PIN_OFFSET, [14] = SA8775_PIN_OFFSET, + [15] = SA8775_PIN_OFFSET, [16] = SA8775_PIN_OFFSET, [17] = SA8775_PIN_OFFSET, + [18] = SA8775_PIN_OFFSET, [19] = SA8775_PIN_OFFSET, [20] = SA8775_PIN_OFFSET, + [21] = SA8775_PIN_OFFSET, [22] = SA8775_PIN_OFFSET, [23] = SA8775_PIN_OFFSET, + [24] = SA8775_PIN_OFFSET, [25] = SA8775_PIN_OFFSET, [26] = SA8775_PIN_OFFSET, + [27] = SA8775_PIN_OFFSET, [28] = SA8775_PIN_OFFSET, [29] = SA8775_PIN_OFFSET, + [30] = SA8775_PIN_OFFSET, [31] = SA8775_PIN_OFFSET, [32] = SA8775_PIN_OFFSET, + [33] = SA8775_PIN_OFFSET, [34] = SA8775_PIN_OFFSET, [35] = SA8775_PIN_OFFSET, + [36] = SA8775_PIN_OFFSET, [37] = SA8775_PIN_OFFSET, [38] = SA8775_PIN_OFFSET, + [39] = SA8775_PIN_OFFSET, [40] = SA8775_PIN_OFFSET, [41] = SA8775_PIN_OFFSET, + [42] = SA8775_PIN_OFFSET, [43] = SA8775_PIN_OFFSET, [44] = SA8775_PIN_OFFSET, + [45] = SA8775_PIN_OFFSET, [46] = SA8775_PIN_OFFSET, [47] = SA8775_PIN_OFFSET, + [48] = SA8775_PIN_OFFSET, [49] = SA8775_PIN_OFFSET, [50] = SA8775_PIN_OFFSET, + [51] = SA8775_PIN_OFFSET, [52] = SA8775_PIN_OFFSET, [53] = SA8775_PIN_OFFSET, + [54] = SA8775_PIN_OFFSET, [55] = SA8775_PIN_OFFSET, [56] = SA8775_PIN_OFFSET, + [57] = SA8775_PIN_OFFSET, [58] = SA8775_PIN_OFFSET, [59] = SA8775_PIN_OFFSET, + [60] = SA8775_PIN_OFFSET, [61] = SA8775_PIN_OFFSET, [62] = SA8775_PIN_OFFSET, + [63] = SA8775_PIN_OFFSET, [64] = SA8775_PIN_OFFSET, [65] = SA8775_PIN_OFFSET, + [66] = SA8775_PIN_OFFSET, [67] = SA8775_PIN_OFFSET, [68] = SA8775_PIN_OFFSET, + [69] = SA8775_PIN_OFFSET, [70] = SA8775_PIN_OFFSET, [71] = SA8775_PIN_OFFSET, + [72] = SA8775_PIN_OFFSET, [73] = SA8775_PIN_OFFSET, [74] = SA8775_PIN_OFFSET, + [75] = SA8775_PIN_OFFSET, [76] = SA8775_PIN_OFFSET, [77] = SA8775_PIN_OFFSET, + [78] = SA8775_PIN_OFFSET, [79] = SA8775_PIN_OFFSET, [80] = SA8775_PIN_OFFSET, + [81] = SA8775_PIN_OFFSET, [82] = SA8775_PIN_OFFSET, [83] = SA8775_PIN_OFFSET, + [84] = SA8775_PIN_OFFSET, [85] = SA8775_PIN_OFFSET, [86] = SA8775_PIN_OFFSET, + [87] = SA8775_PIN_OFFSET, [88] = SA8775_PIN_OFFSET, [89] = SA8775_PIN_OFFSET, + [90] = SA8775_PIN_OFFSET, [91] = SA8775_PIN_OFFSET, [92] = SA8775_PIN_OFFSET, + [93] = SA8775_PIN_OFFSET, [94] = SA8775_PIN_OFFSET, [95] = SA8775_PIN_OFFSET, + [96] = SA8775_PIN_OFFSET, [97] = SA8775_PIN_OFFSET, [98] = SA8775_PIN_OFFSET, + [99] = SA8775_PIN_OFFSET, [100] = SA8775_PIN_OFFSET, [101] = SA8775_PIN_OFFSET, + [102] = SA8775_PIN_OFFSET, [103] = SA8775_PIN_OFFSET, [104] = SA8775_PIN_OFFSET, + [105] = SA8775_PIN_OFFSET, [106] = SA8775_PIN_OFFSET, [107] = SA8775_PIN_OFFSET, + [108] = SA8775_PIN_OFFSET, [109] = SA8775_PIN_OFFSET, [110] = SA8775_PIN_OFFSET, + [111] = SA8775_PIN_OFFSET, [112] = SA8775_PIN_OFFSET, [113] = SA8775_PIN_OFFSET, + [114] = SA8775_PIN_OFFSET, [115] = SA8775_PIN_OFFSET, [116] = SA8775_PIN_OFFSET, + [117] = SA8775_PIN_OFFSET, [118] = SA8775_PIN_OFFSET, [119] = SA8775_PIN_OFFSET, + [120] = SA8775_PIN_OFFSET, [121] = SA8775_PIN_OFFSET, [122] = SA8775_PIN_OFFSET, + [123] = SA8775_PIN_OFFSET, [124] = SA8775_PIN_OFFSET, [125] = SA8775_PIN_OFFSET, + [126] = SA8775_PIN_OFFSET, [127] = SA8775_PIN_OFFSET, [128] = SA8775_PIN_OFFSET, + [129] = SA8775_PIN_OFFSET, [130] = SA8775_PIN_OFFSET, [131] = SA8775_PIN_OFFSET, + [132] = SA8775_PIN_OFFSET, [133] = SA8775_PIN_OFFSET, [134] = SA8775_PIN_OFFSET, + [135] = SA8775_PIN_OFFSET, [136] = SA8775_PIN_OFFSET, [137] = SA8775_PIN_OFFSET, + [138] = SA8775_PIN_OFFSET, [139] = SA8775_PIN_OFFSET, [140] = SA8775_PIN_OFFSET, + [141] = SA8775_PIN_OFFSET, [142] = SA8775_PIN_OFFSET, [143] = SA8775_PIN_OFFSET, + [144] = SA8775_PIN_OFFSET, [145] = SA8775_PIN_OFFSET, [146] = SA8775_PIN_OFFSET, + [147] = SA8775_PIN_OFFSET, [148] = SA8775_PIN_OFFSET, [148] = SA8775_PIN_OFFSET, + [149] = SA8775_PIN_OFFSET, [150] = SA8775_PIN_OFFSET, [151] = SA8775_PIN_OFFSET, + [152] = SA8775_PIN_OFFSET, [153] = SA8775_PIN_OFFSET, [154] = SA8775_PIN_OFFSET, +}; + +static const struct msm_pinctrl_data sa8775p_data = { + .pin_data = { + .pin_count = 155, + .special_pins_start = 149, + .special_pins_data = msm_special_pins_data, + .pin_offsets = sa8775p_pin_offsets, + }, + .functions_count = ARRAY_SIZE(msm_pinctrl_functions), + .get_function_name = sa8775p_get_function_name, + .get_function_mux = sa8775p_get_function_mux, + .get_pin_name = sa8775p_get_pin_name, +}; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,sa8775p-tlmm", .data = (ulong)&sa8775p_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_sa8775p) = { + .name = "pinctrl_sa8775p", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.3.1 From 2c1462e38b771c547a1f3ee8bbea5aa9d3719885 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 17 Mar 2025 16:15:02 +0000 Subject: clk/qcom: sc7280: add missing UFS and MMC clocks These are all usually enabled, hence we don't (yet) bother configuring their RCG src clocks. Add them to remove the errors about missing clocks when the UFS and MMC drivers probe. Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250317-sc7280-mmc-ufs-clocks-v1-2-38e05c16511b@linaro.org Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-sc7280.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c index 8691f08109b..9aff8a847ad 100644 --- a/drivers/clk/qcom/clock-sc7280.c +++ b/drivers/clk/qcom/clock-sc7280.c @@ -107,6 +107,17 @@ static const struct gate_clk sc7280_clks[] = { GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x52008, BIT(10)), GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x52008, BIT(11)), GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)), + GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x77010, BIT(0)), + GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x770cc, BIT(0)), + GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77018, BIT(0)), + GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x7705c, BIT(0)), + GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x7709c, BIT(0)), + GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x7701c, BIT(0)), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x77020, BIT(0)), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_1_CLK, 0x770b8, BIT(0)), + GATE_CLK(GCC_UFS_1_CLKREF_EN, 0x8c000, BIT(0)), + GATE_CLK(GCC_SDCC2_AHB_CLK, 0x14008, BIT(0)), + GATE_CLK(GCC_SDCC2_APPS_CLK, 0x14004, BIT(0)), }; static int sc7280_enable(struct clk *clk) -- cgit v1.3.1 From 1a02b7aa58ae1558e2fd5c29e85c20bdf1becaae Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 28 Mar 2025 09:53:21 +0100 Subject: spmi: msm: use real number of channels for v5 & v7 The SPMI_MAX_CHANNELS_Vx are only the maximum channels supported by the controller, but the real number of channels mapped on this system can be read from a register, so take this info. This allows no to overlap on the second controller present on the V7 SPMI arbiter, otherwise we would also parse the mapping of the second SPMI bus and we would bet the wrong IDs. Signed-off-by: Neil Armstrong Tested-by: caleb.connolly@linaro.org # sdm845 Link: https://lore.kernel.org/r/20250328-topic-sm8x50-spmi-fix-v1-1-a7548d3aef0d@linaro.org Signed-off-by: Caleb Connolly --- drivers/spmi/spmi-msm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index 5cc5a9e654c..08be4517df1 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -24,6 +24,9 @@ DECLARE_GLOBAL_DATA_PTR; #define PMIC_ARB_VERSION_V5_MIN 0x50000000 #define PMIC_ARB_VERSION_V7_MIN 0x70000000 +#define PMIC_ARB_FEATURES 0x0004 +#define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0) + #define APID_MAP_OFFSET_V1_V2_V3 (0x800) #define APID_MAP_OFFSET_V5 (0x900) #define APID_MAP_OFFSET_V7 (0x2000) @@ -271,13 +274,17 @@ static int msm_spmi_probe(struct udevice *dev) } else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) { priv->arb_ver = V5; priv->arb_chnl = core_addr + APID_MAP_OFFSET_V5; - priv->max_channels = SPMI_MAX_CHANNELS_V5; + priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) & + PMIC_ARB_FEATURES_PERIPH_MASK, + SPMI_MAX_CHANNELS_V5); priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg"); } else { /* TOFIX: handle second bus */ priv->arb_ver = V7; priv->arb_chnl = core_addr + APID_MAP_OFFSET_V7; - priv->max_channels = SPMI_MAX_CHANNELS_V7; + priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) & + PMIC_ARB_FEATURES_PERIPH_MASK, + SPMI_MAX_CHANNELS_V7); priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg"); } -- cgit v1.3.1 From f252350623326d35a7f7cdf88e1db279f019f5d7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 28 Mar 2025 09:53:22 +0100 Subject: spmi: msm: factor out channel mapping for v5 & v7 The handling of the table mapping for V5 & V7 needs more work to handle the duplicate read-only & read-write mappings, so to make code cleaner add a switch/case and move the v5 & v7 mapping handler in a separate function. Signed-off-by: Neil Armstrong Tested-by: caleb.connolly@linaro.org # sdm845 Link: https://lore.kernel.org/r/20250328-topic-sm8x50-spmi-fix-v1-2-a7548d3aef0d@linaro.org Signed-off-by: Caleb Connolly --- drivers/spmi/spmi-msm.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index 08be4517df1..9b2be1c1b9e 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -249,6 +249,18 @@ static struct dm_spmi_ops msm_spmi_ops = { .write = msm_spmi_write, }; +static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i, + uint8_t slave_id, uint8_t pid) +{ + /* Mark channels read-only when from different owner */ + uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i)); + uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg); + + priv->channel_map[slave_id][pid] = i; + if (owner != priv->owner) + priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY; +} + static int msm_spmi_probe(struct udevice *dev) { struct msm_spmi_priv *priv = dev_get_priv(dev); @@ -304,15 +316,16 @@ static int msm_spmi_probe(struct udevice *dev) uint8_t slave_id = (periph & 0xf0000) >> 16; uint8_t pid = (periph & 0xff00) >> 8; - priv->channel_map[slave_id][pid] = i; - - /* Mark channels read-only when from different owner */ - if (priv->arb_ver == V5 || priv->arb_ver == V7) { - uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i)); - uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg); + switch (priv->arb_ver) { + case V2: + case V3: + priv->channel_map[slave_id][pid] = i; + break; - if (owner != priv->owner) - priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY; + case V5: + case V7: + msm_spmi_channel_map_v5(priv, i, slave_id, pid); + break; } } return 0; -- cgit v1.3.1 From 69400a696cb823075990048eac5c4ed857229daf Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 28 Mar 2025 09:53:23 +0100 Subject: spmi: msm: introduce SPMI_CHANNEL_VALID flag Introduce the SPMI_CHANNEL_VALID flag so we can check if a mapping exists for a SPMI command. Signed-off-by: Neil Armstrong Tested-by: caleb.connolly@linaro.org # sdm845 Link: https://lore.kernel.org/r/20250328-topic-sm8x50-spmi-fix-v1-3-a7548d3aef0d@linaro.org Signed-off-by: Caleb Connolly --- drivers/spmi/spmi-msm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index 9b2be1c1b9e..ee3feaf8b50 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -63,6 +63,7 @@ DECLARE_GLOBAL_DATA_PTR; #define SPMI_MAX_PERIPH 256 #define SPMI_CHANNEL_READ_ONLY BIT(31) +#define SPMI_CHANNEL_VALID BIT(30) #define SPMI_CHANNEL_MASK 0xffff enum arb_ver { @@ -117,6 +118,8 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, return -EIO; if (pid >= SPMI_MAX_PERIPH) return -EIO; + if (!(priv->channel_map[usid][pid] & SPMI_CHANNEL_VALID)) + return -EINVAL; if (priv->channel_map[usid][pid] & SPMI_CHANNEL_READ_ONLY) return -EPERM; @@ -186,6 +189,8 @@ static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off) return -EIO; if (pid >= SPMI_MAX_PERIPH) return -EIO; + if (!(priv->channel_map[usid][pid] & SPMI_CHANNEL_VALID)) + return -EINVAL; channel = priv->channel_map[usid][pid] & SPMI_CHANNEL_MASK; @@ -256,7 +261,7 @@ static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i, uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i)); uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg); - priv->channel_map[slave_id][pid] = i; + priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID; if (owner != priv->owner) priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY; } @@ -319,7 +324,7 @@ static int msm_spmi_probe(struct udevice *dev) switch (priv->arb_ver) { case V2: case V3: - priv->channel_map[slave_id][pid] = i; + priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID; break; case V5: -- cgit v1.3.1 From 5b233442afacde1aca2556c543b1cd8e22946690 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 28 Mar 2025 09:53:24 +0100 Subject: spmi: msm: correctly handle multiple mapping entries On v5 & v7 controllers, multiple mapping for different Execution Environment exists, if the mapping owner is for a different Execution Environment we can only read and not write any data. To allow us to find a Write mapping for our Execution Environment, we can overwritte a mapping if we encounter a new one which we own. Implement this logic, the result is the same mapping table as in Linux. Signed-off-by: Neil Armstrong Tested-by: caleb.connolly@linaro.org # sdm845 Link: https://lore.kernel.org/r/20250328-topic-sm8x50-spmi-fix-v1-4-a7548d3aef0d@linaro.org Signed-off-by: Caleb Connolly --- drivers/spmi/spmi-msm.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index ee3feaf8b50..faae54e9fef 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -254,16 +254,30 @@ static struct dm_spmi_ops msm_spmi_ops = { .write = msm_spmi_write, }; +/* + * In order to allow multiple EEs to write to a single PPID in arbiter + * version 5 and 7, there is more than one APID mapped to each PPID. + * The owner field for each of these mappings specifies the EE which is + * allowed to write to the APID. + */ static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i, uint8_t slave_id, uint8_t pid) { /* Mark channels read-only when from different owner */ uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i)); uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg); - - priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID; - if (owner != priv->owner) - priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY; + bool prev_valid = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_VALID; + uint32_t prev_read_only = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_READ_ONLY; + + if (!prev_valid) { + /* First PPID mapping */ + priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID; + if (owner != priv->owner) + priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY; + } else if ((owner == priv->owner) && prev_read_only) { + /* Read only and we found one we own, switch */ + priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID; + } } static int msm_spmi_probe(struct udevice *dev) -- cgit v1.3.1 From 1561b01a0851e9ada026778c5518f0bef8caa3e3 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 7 Apr 2025 19:56:14 +0200 Subject: clk/qcom: apq8096: fix set rate for the uart clock The function should return a valid rate. Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Neil Armstrong Reviewed-by: Caleb Connolly Reviewed-by: Link: https://lore.kernel.org/r/20250407175617.3494506-2-jorge.ramirez@oss.qualcomm.com Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-apq8096.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index c77d69128b0..bc00826a5e8 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -87,7 +87,8 @@ static ulong apq8096_clk_set_rate(struct clk *clk, ulong rate) return clk_init_sdc(priv, rate); break; case GCC_BLSP2_UART2_APPS_CLK: /*UART2*/ - return clk_init_uart(priv); + clk_init_uart(priv); + return 7372800; default: return 0; } -- cgit v1.3.1 From 8fc48d1a01acec2568b48b2afd6303397af593c8 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 7 Apr 2025 19:56:15 +0200 Subject: clk/qcom: apq8096: fix the sdhci clock Select the right clock for sdhci. Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Caleb Connolly Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250407175617.3494506-3-jorge.ramirez@oss.qualcomm.com Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-apq8096.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index bc00826a5e8..551f52d5197 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -83,7 +83,7 @@ static ulong apq8096_clk_set_rate(struct clk *clk, ulong rate) struct msm_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { - case GCC_SDCC1_APPS_CLK: /* SDC1 */ + case GCC_SDCC2_APPS_CLK: /* SDC2 */ return clk_init_sdc(priv, rate); break; case GCC_BLSP2_UART2_APPS_CLK: /*UART2*/ -- cgit v1.3.1 From 7afddbee3b1f667b9ff752e9779d1eb9e2992ba4 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 7 Apr 2025 19:56:16 +0200 Subject: clk: stub: add qcom,glink-smd-rpm Add support for the resource power manager clocks over SMD/GLINK to be stubbed. Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Sumit Garg Reviewed-by: Neil Armstrong Reviewed-by: Caleb Connolly Link: https://lore.kernel.org/r/20250407175617.3494506-4-jorge.ramirez@oss.qualcomm.com Signed-off-by: Caleb Connolly --- drivers/clk/clk-stub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c index 521ecfc5917..5f5aca41d5b 100644 --- a/drivers/clk/clk-stub.c +++ b/drivers/clk/clk-stub.c @@ -14,7 +14,7 @@ static const struct udevice_id nop_parent_ids[] = { { .compatible = "qcom,rpm-proc" }, { .compatible = "qcom,glink-rpm" }, - { .compatible = "qcom,rpm-sm6115" }, + { .compatible = "qcom,glink-smd-rpm" }, { } }; -- cgit v1.3.1 From 45acd9d2d4ec84775d09c73aab75a4fd989beb41 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 10 Apr 2025 13:30:27 +0530 Subject: phy: phy-qcom-qusb2: Fix USB PHY power on sequence Recent addition of support for SDM660 inadvertently broke USB PHY power on sequence on RB1/RB2 and others with following error: starting USB... Bus usb@4e00000: QUSB2PHY pll lock failed: status reg = 0 qcom-qusb2-phy phy@1613000: PHY: Failed to power on phy@1613000: -16. Can't power on PHY0 probe failed, error -16 No USB controllers found The root cause was the addition of flag se_clk_scheme_default which was configured correctly for SDM660 but incorrect for all other supported SoC. Fix that by properly assignment as per upstream Linux driver. Fixes: 475497dc3c15 ("phy: Add SDM660 support to Qualcomm QUSB2 phy") Signed-off-by: Sumit Garg Reviewed-by: Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250410080027.208674-3-sumit.garg@kernel.org Signed-off-by: Caleb Connolly --- drivers/phy/qcom/phy-qcom-qusb2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/qcom/phy-qcom-qusb2.c b/drivers/phy/qcom/phy-qcom-qusb2.c index cabd05bf5a6..d98f6108e69 100644 --- a/drivers/phy/qcom/phy-qcom-qusb2.c +++ b/drivers/phy/qcom/phy-qcom-qusb2.c @@ -230,6 +230,7 @@ static const struct qusb2_phy_cfg sm6115_phy_cfg = { .regs = sm6115_regs_layout, .has_pll_test = true, + .se_clk_scheme_default = true, .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), .mask_core_ready = PLL_LOCKED, .autoresume_en = BIT(3), @@ -256,6 +257,7 @@ static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = { POWER_DOWN), .mask_core_ready = CORE_READY_STATUS, .has_pll_override = true, + .se_clk_scheme_default = true, .autoresume_en = BIT(0), .update_tune1_with_efuse = true, }; -- cgit v1.3.1 From 0708bdd34d4fdd0680706d2719de34704402719d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 1 Apr 2025 09:45:19 +0200 Subject: gpio: msm: fix get_function return for special pins The get_function callback wrongly returns 0 for special pins, return the appropriate pin function by probing into the special pins data fields to find if the pin is gpio capable. Fixes: f9bb539460d ("gpio: msm: add support for special pins") Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20250401-topic-sm8x50-msm-gpio-special-fixes-v1-1-a1148a02bb16@linaro.org Signed-off-by: Caleb Connolly --- drivers/gpio/msm_gpio.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index cea073b3297..f208eec7e56 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -192,13 +192,41 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio) return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN); } +static int msm_gpio_get_function_special(struct msm_gpio_bank *priv, + unsigned int gpio) +{ + unsigned int offset = gpio - priv->pin_data->special_pins_start; + const struct msm_special_pin_data *data; + + if (!priv->pin_data->special_pins_data) + return GPIOF_UNKNOWN; + + data = &priv->pin_data->special_pins_data[offset]; + + /* No I/O fields, cannot control/read the I/O value */ + if (!data->io_reg || (data->out_bit >= 31 && data->in_bit >= 31)) + return GPIOF_FUNC; + + /* No Output-Enable register, cannot control I/O direction */ + if (!data->ctl_reg || data->oe_bit >= 31) { + if (data->out_bit >= 31) + return GPIOF_INPUT; + else + return GPIOF_OUTPUT; + } + + if (readl(priv->base + data->ctl_reg) & BIT(data->oe_bit)) + return GPIOF_OUTPUT; + + return GPIOF_INPUT; +} + static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); - /* Always NOP for special pins, assume they're in the correct state */ if (qcom_is_special_pin(priv->pin_data, gpio)) - return 0; + return msm_gpio_get_function_special(priv, gpio); if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE) return GPIOF_OUTPUT; -- cgit v1.3.1 From 8803cd6dd782cd66f5978e79da022aa2de9710d9 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 1 Apr 2025 09:45:20 +0200 Subject: gpio: msm: return correct value return for special output pins When a special pin is output only, the current code would return 0, but if the pin is output only we can get the output value. Try to return the output value and in all the other cases return an error instead of 0. Fixes: f9bb539460d ("gpio: msm: add support for special pins") Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20250401-topic-sm8x50-msm-gpio-special-fixes-v1-2-a1148a02bb16@linaro.org Signed-off-by: Caleb Connolly --- drivers/gpio/msm_gpio.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index f208eec7e56..54afd44fbd3 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -172,12 +172,19 @@ static int msm_gpio_get_value_special(struct msm_gpio_bank *priv, unsigned int g const struct msm_special_pin_data *data; if (!priv->pin_data->special_pins_data) - return 0; + return -EINVAL; data = &priv->pin_data->special_pins_data[offset]; - if (!data->io_reg || data->in_bit >= 31) - return 0; + if (!data->io_reg) + return -EINVAL; + + if (data->in_bit >= 31) { + if (data->out_bit >= 31) + return -EINVAL; + + return !!(readl(priv->base + data->io_reg) >> data->out_bit); + } return !!(readl(priv->base + data->io_reg) >> data->in_bit); } -- cgit v1.3.1 From b4420a0c9ed446a9dbb5439d543d7c74344a5099 Mon Sep 17 00:00:00 2001 From: Alexey Minnekhanov Date: Mon, 31 Mar 2025 18:55:31 +0300 Subject: drivers: pinctrl: Add Qualcomm SDM630/660 TLMM driver Add support for TLMM pin controller block (Top Level Mode Multiplexer) on SDM630/660 SoCs, with support for special pins. Correct pin configuration is required for working debug UART and eMMC/SD cards. SDM630 and SDM660 TLMM blocks are the same. Signed-off-by: Alexey Minnekhanov Reviewed-by: Caleb Connolly Link: https://lore.kernel.org/r/20250331155531.3638165-1-alexeymin@postmarketos.org Signed-off-by: Caleb Connolly --- drivers/pinctrl/qcom/Kconfig | 7 ++ drivers/pinctrl/qcom/Makefile | 1 + drivers/pinctrl/qcom/pinctrl-sdm660.c | 226 ++++++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+) create mode 100644 drivers/pinctrl/qcom/pinctrl-sdm660.c (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index e24287c978f..e567cb113a3 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -61,6 +61,13 @@ config PINCTRL_QCOM_SC7280 help Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC, +config PINCTRL_QCOM_SDM660 + bool "Qualcomm SDM630/660 Pinctrl" + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the Snapdragon 630/636/660 + SoCs, as well as the associated GPIO driver. + config PINCTRL_QCOM_SDM845 bool "Qualcomm SDM845 Pinctrl" select PINCTRL_QCOM diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 65d1845ea54..6ffc6d48c15 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o obj-$(CONFIG_PINCTRL_QCOM_SA8775P) += pinctrl-sa8775p.o obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o +obj-$(CONFIG_PINCTRL_QCOM_SDM660) += pinctrl-sdm660.o obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c new file mode 100644 index 00000000000..646d848ffa4 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm SDM630/660 TLMM pinctrl + * + */ + +#include +#include "pinctrl-qcom.h" + +#define TLMM_BASE 0x03100000 +#define SOUTH (0x03100000 - TLMM_BASE) /* 0x0 */ +#define CENTER (0x03500000 - TLMM_BASE) /* 0x400000 */ +#define NORTH (0x03900000 - TLMM_BASE) /* 0x800000 */ + +#define MAX_PIN_NAME_LEN 32 +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); + +static const struct pinctrl_function sdm660_pinctrl_functions[] = { + { "gpio", 0 }, + { "blsp_uart2", 3 }, /* gpio 4 and 5, used for debug uart */ +}; + +static const unsigned int sdm660_pin_offsets[] = { + [0] = SOUTH, + [1] = SOUTH, + [2] = SOUTH, + [3] = SOUTH, + [4] = NORTH, + [5] = SOUTH, + [6] = SOUTH, + [7] = SOUTH, + [8] = NORTH, + [9] = NORTH, + [10] = NORTH, + [11] = NORTH, + [12] = NORTH, + [13] = NORTH, + [14] = NORTH, + [15] = NORTH, + [16] = CENTER, + [17] = CENTER, + [18] = CENTER, + [19] = CENTER, + [20] = SOUTH, + [21] = SOUTH, + [22] = CENTER, + [23] = CENTER, + [24] = NORTH, + [25] = NORTH, + [26] = NORTH, + [27] = NORTH, + [28] = CENTER, + [29] = CENTER, + [30] = CENTER, + [31] = CENTER, + [32] = SOUTH, + [33] = SOUTH, + [34] = SOUTH, + [35] = SOUTH, + [36] = SOUTH, + [37] = SOUTH, + [38] = SOUTH, + [39] = SOUTH, + [40] = SOUTH, + [41] = SOUTH, + [42] = SOUTH, + [43] = SOUTH, + [44] = SOUTH, + [45] = SOUTH, + [46] = SOUTH, + [47] = SOUTH, + [48] = SOUTH, + [49] = SOUTH, + [50] = SOUTH, + [51] = SOUTH, + [52] = SOUTH, + [53] = NORTH, + [54] = NORTH, + [55] = SOUTH, + [56] = SOUTH, + [57] = SOUTH, + [58] = SOUTH, + [59] = NORTH, + [60] = NORTH, + [61] = NORTH, + [62] = NORTH, + [63] = NORTH, + [64] = SOUTH, + [65] = SOUTH, + [66] = NORTH, + [67] = NORTH, + [68] = NORTH, + [69] = NORTH, + [70] = NORTH, + [71] = NORTH, + [72] = NORTH, + [73] = NORTH, + [74] = NORTH, + [75] = NORTH, + [76] = NORTH, + [77] = NORTH, + [78] = NORTH, + [79] = SOUTH, + [80] = SOUTH, + [81] = CENTER, + [82] = CENTER, + [83] = SOUTH, + [84] = SOUTH, + [85] = SOUTH, + [86] = SOUTH, + [87] = SOUTH, + [88] = SOUTH, + [89] = SOUTH, + [90] = SOUTH, + [91] = SOUTH, + [92] = SOUTH, + [93] = SOUTH, + [94] = SOUTH, + [95] = SOUTH, + [96] = SOUTH, + [97] = SOUTH, + [98] = SOUTH, + [99] = SOUTH, + [100] = SOUTH, + [101] = SOUTH, + [102] = SOUTH, + [103] = SOUTH, + [104] = SOUTH, + [105] = SOUTH, + [106] = SOUTH, + [107] = SOUTH, + [108] = SOUTH, + [109] = SOUTH, + [110] = SOUTH, + [111] = SOUTH, + [112] = SOUTH, + [113] = SOUTH, +}; + +/* + * Special pins - eMMC/SD related: [114..120], in total 7 special pins + */ + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = pg_name, \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + } + +/* All SDC pins are in the NORTH tile */ +static const struct msm_special_pin_data sdm660_special_pins_data[] = { + SDC_QDSD_PINGROUP("sdc1_clk", NORTH + 0x9a000, 13, 6), + SDC_QDSD_PINGROUP("sdc1_cmd", NORTH + 0x9a000, 11, 3), + SDC_QDSD_PINGROUP("sdc1_data", NORTH + 0x9a000, 9, 0), + SDC_QDSD_PINGROUP("sdc2_clk", NORTH + 0x9b000, 14, 6), + SDC_QDSD_PINGROUP("sdc2_cmd", NORTH + 0x9b000, 11, 3), + SDC_QDSD_PINGROUP("sdc2_data", NORTH + 0x9b000, 9, 0), + SDC_QDSD_PINGROUP("sdc1_rclk", NORTH + 0x9a000, 15, 0), +}; + +static const char *sdm660_get_function_name(struct udevice *dev, unsigned int selector) +{ + return sdm660_pinctrl_functions[selector].name; +} + +static const char *sdm660_get_pin_name(struct udevice *dev, unsigned int selector) +{ + static const char * const special_pins_names[] = { + "sdc1_clk", "sdc1_cmd", "sdc1_data", + "sdc2_clk", "sdc2_cmd", "sdc2_data", + "sdc1_rclk" + }; + + if (selector >= 114 && selector <= 120) + snprintf(pin_name, MAX_PIN_NAME_LEN, special_pins_names[selector - 114]); + else + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + + return pin_name; +} + +static int sdm660_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector) +{ + if (selector >= 0 && selector < ARRAY_SIZE(sdm660_pinctrl_functions)) + return sdm660_pinctrl_functions[selector].val; + return -EINVAL; +} + +struct msm_pinctrl_data sdm660_data = { + .pin_data = { + .pin_offsets = sdm660_pin_offsets, + .pin_count = ARRAY_SIZE(sdm660_pin_offsets) + ARRAY_SIZE(sdm660_special_pins_data), + .special_pins_start = 114, + .special_pins_data = sdm660_special_pins_data, + }, + .functions_count = ARRAY_SIZE(sdm660_pinctrl_functions), + .get_function_name = sdm660_get_function_name, + .get_function_mux = sdm660_get_function_mux, + .get_pin_name = sdm660_get_pin_name, +}; + +static const struct udevice_id msm_pinctrl_ids[] = { + { + .compatible = "qcom,sdm630-pinctrl", + .data = (ulong)&sdm660_data + }, + { + .compatible = "qcom,sdm660-pinctrl", + .data = (ulong)&sdm660_data + }, + { /* Sentinel */ } +}; + +U_BOOT_DRIVER(pinctrl_ssdm660) = { + .name = "pinctrl_sdm660", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; -- cgit v1.3.1 From 8f5685d5d32f50e8a3634686218e3fd143075d93 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 31 Mar 2025 14:23:22 +0200 Subject: button: qcom-pmic: prettify and standardise button labels Boards using gpio-keys for volume buttons label them "Volume Down", let's match that here, and make the power button nicer too. This simplifies configuring button_cmds in a board-agnostic way. Tested-by: Danila Tikhonov # google-sunfish Tested-by: Jens Reidel # xiaomi-davinci Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250331-qcom-phones-v4-5-f52e57d3b8c6@linaro.org Signed-off-by: Caleb Connolly --- board/qualcomm/dragonboard410c/dragonboard410c.c | 2 +- board/qualcomm/dragonboard820c/dragonboard820c.c | 2 +- drivers/button/button-qcom-pmic.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c index fcbf2c3fe60..d0d82489f53 100644 --- a/board/qualcomm/dragonboard410c/dragonboard410c.c +++ b/board/qualcomm/dragonboard410c/dragonboard410c.c @@ -72,7 +72,7 @@ int misc_init_r(void) int ret; enum button_state_t state; - ret = button_get_by_label("vol_down", &btn); + ret = button_get_by_label("Volume Down", &btn); if (ret < 0) { printf("Couldn't find power button!\n"); return ret; diff --git a/board/qualcomm/dragonboard820c/dragonboard820c.c b/board/qualcomm/dragonboard820c/dragonboard820c.c index d3333a59db0..12a9273ec4b 100644 --- a/board/qualcomm/dragonboard820c/dragonboard820c.c +++ b/board/qualcomm/dragonboard820c/dragonboard820c.c @@ -106,7 +106,7 @@ int misc_init_r(void) int ret; enum button_state_t state; - ret = button_get_by_label("pwrkey", &btn); + ret = button_get_by_label("Power Button", &btn); if (ret < 0) { printf("Couldn't find power button!\n"); return ret; diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index f9f0948ae09..e3bb9bd758a 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -73,25 +73,25 @@ static const struct qcom_pmic_btn_data qcom_pmic_btn_data_table[] = { .compatible = "qcom,pm8941-pwrkey", .status_bit = PON_KPDPWR_N_SET, .code = KEY_ENTER, - .label = "pwrkey", + .label = "Power Button", }, { .compatible = "qcom,pm8941-resin", .status_bit = PON_RESIN_N_SET, .code = KEY_DOWN, - .label = "vol_down", + .label = "Volume Down", }, { .compatible = "qcom,pmk8350-pwrkey", .status_bit = PON_GEN3_KPDPWR_N_SET, .code = KEY_ENTER, - .label = "pwrkey", + .label = "Power Button", }, { .compatible = "qcom,pmk8350-resin", .status_bit = PON_GEN3_RESIN_N_SET, .code = KEY_DOWN, - .label = "vol_down", + .label = "Volume Down", }, }; -- cgit v1.3.1 From 9c607005c51976b5e0301461bfc0f38d5bdebd0e Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 31 Mar 2025 14:23:23 +0200 Subject: button: make button_get_by_label() case insensitive This function is already doing a fuzzy match, since there are no guarantees that a given label is unique. Ignoring case makes it much easier to catch "Volume down" or "Volume Down" in board-agnostic code. Tested-by: Danila Tikhonov # google-sunfish Tested-by: Jens Reidel # xiaomi-davinci Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250331-qcom-phones-v4-6-f52e57d3b8c6@linaro.org Signed-off-by: Caleb Connolly --- drivers/button/button-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/button/button-uclass.c b/drivers/button/button-uclass.c index 729983d5870..025917887e8 100644 --- a/drivers/button/button-uclass.c +++ b/drivers/button/button-uclass.c @@ -21,7 +21,7 @@ int button_get_by_label(const char *label, struct udevice **devp) struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); /* Ignore the top-level button node */ - if (uc_plat->label && !strcmp(label, uc_plat->label)) + if (uc_plat->label && !strcasecmp(label, uc_plat->label)) return uclass_get_device_tail(dev, 0, devp); } -- cgit v1.3.1 From 91ba4976c05882f88232eaa4fc5eb9192701dbe3 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Thu, 10 Apr 2025 10:52:38 +0200 Subject: pinctrl: qcom: handle reserved ranges Some Qualcomm boards feature reserved ranges of pins which are protected by firmware. Attempting to read or write any registers associated with these pins results the board resetting. Add support for parsing these ranges from devicetree and ensure that the pinctrl and GPIO drivers don't try to interact with these pins. Signed-off-by: Neil Armstrong Reviewed-by: Sumit Garg Link: https://lore.kernel.org/r/20250410-topic-sm8x50-pinctrl-reserved-ranges-v2-1-654488392b9a@linaro.org Signed-off-by: Caleb Connolly --- arch/arm/mach-snapdragon/include/mach/gpio.h | 15 +++++++ drivers/gpio/msm_gpio.c | 10 +++++ drivers/pinctrl/qcom/pinctrl-qcom.c | 67 ++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) (limited to 'drivers') diff --git a/arch/arm/mach-snapdragon/include/mach/gpio.h b/arch/arm/mach-snapdragon/include/mach/gpio.h index cc8f405e20b..11e8104baf2 100644 --- a/arch/arm/mach-snapdragon/include/mach/gpio.h +++ b/arch/arm/mach-snapdragon/include/mach/gpio.h @@ -46,4 +46,19 @@ static inline bool qcom_is_special_pin(const struct msm_pin_data *pindata, unsig return pindata->special_pins_start && pin >= pindata->special_pins_start; } +struct udevice; + +/** + * msm_pinctrl_is_reserved() - Check if a pin lies in a reserved range + * + * @dev: pinctrl device + * @pin: Pin number + * + * Returns: true if pin is reserved, otherwise false + * + * Call using dev_get_parent() from the GPIO device, it is a child of + * the pinctrl device. + */ +bool msm_pinctrl_is_reserved(struct udevice *dev, unsigned int pin); + #endif /* _QCOM_GPIO_H_ */ diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index 54afd44fbd3..6783fc756f4 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -151,6 +151,9 @@ static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio, static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flags) { + if (msm_pinctrl_is_reserved(dev_get_parent(dev), gpio)) + return -EPERM; + if (flags & GPIOD_IS_OUT_ACTIVE) { return msm_gpio_direction_output(dev, gpio, 1); } else if (flags & GPIOD_IS_OUT) { @@ -193,6 +196,9 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); + if (msm_pinctrl_is_reserved(dev_get_parent(dev), gpio)) + return -EPERM; + if (qcom_is_special_pin(priv->pin_data, gpio)) return msm_gpio_get_value_special(priv, gpio); @@ -232,6 +238,10 @@ static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); + if (msm_pinctrl_is_reserved(dev_get_parent(dev), gpio)) + return GPIOF_UNKNOWN; + + /* Always NOP for special pins, assume they're in the correct state */ if (qcom_is_special_pin(priv->pin_data, gpio)) return msm_gpio_get_function_special(priv, gpio); diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.c b/drivers/pinctrl/qcom/pinctrl-qcom.c index 24d031947a3..c95db56bc47 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.c +++ b/drivers/pinctrl/qcom/pinctrl-qcom.c @@ -15,14 +15,18 @@ #include #include #include +#include #include #include #include "pinctrl-qcom.h" +#define MSM_PINCTRL_MAX_PINS 256 + struct msm_pinctrl_priv { phys_addr_t base; struct msm_pinctrl_data *data; + DECLARE_BITMAP(reserved_map, MSM_PINCTRL_MAX_PINS); }; #define GPIO_CONFIG_REG(priv, x) \ @@ -71,13 +75,60 @@ static const char *msm_get_function_name(struct udevice *dev, return priv->data->get_function_name(dev, selector); } +static int msm_pinctrl_parse_ranges(struct udevice *dev) +{ + struct msm_pinctrl_priv *priv = dev_get_priv(dev); + ofnode node = dev_ofnode(dev); + int ret, count, i; + u32 *ranges; + + if (ofnode_read_prop(node, "gpio-reserved-ranges", &count)) { + if (count % 2 == 1) { + dev_err(dev, "gpio-reserved-ranges must be a multiple of 2\n"); + return -EINVAL; + } + + ranges = malloc(count); + if (!ranges) + return -ENOMEM; + + ret = ofnode_read_u32_array(node, "gpio-reserved-ranges", ranges, count / 4); + if (ret) { + dev_err(dev, "failed to read gpio-reserved-ranges array (%d)\n", ret); + return ret; + } + + for (i = 0; i < count / 4; i += 2) { + if (ranges[i] >= MSM_PINCTRL_MAX_PINS || + (ranges[i] + ranges[i + 1]) >= MSM_PINCTRL_MAX_PINS) { + dev_err(dev, "invalid reserved-range (%d;%d)\n", + ranges[i], ranges[i + 1]); + return -EINVAL; + } + + bitmap_set(priv->reserved_map, ranges[i], ranges[i + 1]); + } + + free(ranges); + } + + return 0; +} + static int msm_pinctrl_probe(struct udevice *dev) { struct msm_pinctrl_priv *priv = dev_get_priv(dev); + int ret; priv->base = dev_read_addr(dev); priv->data = (struct msm_pinctrl_data *)dev_get_driver_data(dev); + ret = msm_pinctrl_parse_ranges(dev); + if (ret) { + printf("Couldn't parse reserved GPIO ranges!\n"); + return ret; + } + return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; } @@ -97,6 +148,9 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector, if (func < 0) return func; + if (msm_pinctrl_is_reserved(dev, pin_selector)) + return -EPERM; + /* Always NOP for special pins, assume they're in the correct state */ if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) return 0; @@ -145,6 +199,9 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector, { struct msm_pinctrl_priv *priv = dev_get_priv(dev); + if (msm_pinctrl_is_reserved(dev, pin_selector)) + return -EPERM; + if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) return msm_pinconf_set_special(priv, pin_selector, param, argument); @@ -241,3 +298,13 @@ U_BOOT_DRIVER(pinctrl_qcom) = { .ops = &msm_pinctrl_ops, .probe = msm_pinctrl_probe, }; + +bool msm_pinctrl_is_reserved(struct udevice *dev, unsigned int pin) +{ + struct msm_pinctrl_priv *priv = dev_get_priv(dev); + + if (pin >= MSM_PINCTRL_MAX_PINS) + return false; + + return test_bit(pin, priv->reserved_map); +} -- cgit v1.3.1