summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-04-11 09:12:16 -0600
committerTom Rini <[email protected]>2025-04-11 09:12:16 -0600
commitff0b7d741dec48c9d1ce5e80ada5eaeac19b1b93 (patch)
tree8f3952ebeb31a9ce0a35d419121e80cae41b547b /drivers
parent295376ce8a32268a1bb0879eb0448e0c0e580727 (diff)
parentf3563fc30356c8079527b90e532407050dff7c7b (diff)
Merge tag 'qcom-for-2025.07' of https://source.denx.de/u-boot/custodians/u-boot-snapdragon
Qualcomm changes for v2025.07: CI: https://source.denx.de/u-boot/custodians/u-boot-snapdragon/-/pipelines/25653 There's been a surprising amount of activity lately on the Qualcomm side with the two oldest boards getting some fresh attention and a lot of cleanup and polish going on across the board. * SDM660 gets USB phy fixes and a pinctrl driver * The recently added SA8775P/QCS9100 SoC gets a pinctrl driver * The Qualcomm pinctrl driver now handles reserved pins correctly, fixing crashes on some boards when running "gpio status -a" * OF_UPSTREAM_BUILD_VENDOR is enabled in qcom_defconfig * SDM845 and SC7280 get missing clocks added (since we're now stricter about those). This gets USB working more reliably in more cases. * DM_USB_GADGET is enabled for all boards using DWC3 and fasbtoot is enabled too * A bug in the livetree fixup code is fixed (making USB work on a lot more platforms) * Button label lookup is made case insensitive* bootretry becomes more dynamic, allowing it to be hijacked to make a "persistent" boot menu that allows dropping to U-Boot shell later on * A new qcom-phone.config fragment is added along with a phone-specific default environment and phone-specific debugging/bringup docs. These make U-Boot more usable on devices without a serial port or keyboard. * The db820c gets fixed up and updated documentation * The db410c also gets some love and modernisation as well as a new reviewer. * A new driver is added for the USB VBUS regulator found on various Qualcomm PMICs * The Qualcomm SPMI driver gets some fixes and cleanup for SPMI v5 and v7 support.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/button/button-qcom-pmic.c8
-rw-r--r--drivers/button/button-uclass.c2
-rw-r--r--drivers/clk/clk-stub.c3
-rw-r--r--drivers/clk/qcom/clock-apq8096.c5
-rw-r--r--drivers/clk/qcom/clock-sc7280.c11
-rw-r--r--drivers/clk/qcom/clock-sdm845.c3
-rw-r--r--drivers/gpio/msm_gpio.c53
-rw-r--r--drivers/phy/qcom/phy-qcom-qusb2.c44
-rw-r--r--drivers/pinctrl/qcom/Kconfig15
-rw-r--r--drivers/pinctrl/qcom/Makefile2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcom.c67
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sa8775p.c623
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm660.c226
-rw-r--r--drivers/power/regulator/Kconfig7
-rw-r--r--drivers/power/regulator/Makefile1
-rw-r--r--drivers/power/regulator/qcom-rpmh-regulator.c45
-rw-r--r--drivers/power/regulator/qcom_usb_vbus_regulator.c111
-rw-r--r--drivers/spmi/spmi-msm.c59
18 files changed, 1261 insertions, 24 deletions
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",
},
};
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);
}
diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c
index 343fa5cd3fe..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" },
{ }
};
@@ -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" },
diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c
index c77d69128b0..551f52d5197 100644
--- a/drivers/clk/qcom/clock-apq8096.c
+++ b/drivers/clk/qcom/clock-apq8096.c
@@ -83,11 +83,12 @@ 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*/
- return clk_init_uart(priv);
+ clk_init_uart(priv);
+ return 7372800;
default:
return 0;
}
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)
diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c
index 6a0bf16ba2d..5c8702ef2fe 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),
@@ -112,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),
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index cea073b3297..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) {
@@ -172,12 +175,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);
}
@@ -186,19 +196,54 @@ 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);
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);
+ 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 0;
+ return msm_gpio_get_function_special(priv, gpio);
if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE)
return GPIOF_OUTPUT;
diff --git a/drivers/phy/qcom/phy-qcom-qusb2.c b/drivers/phy/qcom/phy-qcom-qusb2.c
index c91ba18c4ab..d98f6108e69 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),
@@ -214,6 +230,19 @@ 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),
+};
+
+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),
@@ -228,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,
};
@@ -316,8 +346,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 +453,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 },
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index f4a3942ee2f..e567cb113a3 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -48,12 +48,25 @@ 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_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"
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 94cdc6e4a62..6ffc6d48c15 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -9,7 +9,9 @@ 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_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-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 <asm/gpio.h>
#include <dm/pinctrl.h>
#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/bug.h>
#include <mach/gpio.h>
#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);
+}
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 <dm.h>
+
+#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,
+};
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 <dm.h>
+#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,
+};
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-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 */ },
};
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 <bitfield.h>
+#include <errno.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <asm/gpio.h>
+#include <linux/bitops.h>
+#include <linux/printk.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#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),
+};
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index 5cc5a9e654c..faae54e9fef 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)
@@ -60,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 {
@@ -114,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;
@@ -183,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;
@@ -246,6 +254,32 @@ 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);
+ 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)
{
struct msm_spmi_priv *priv = dev_get_priv(dev);
@@ -271,13 +305,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");
}
@@ -297,15 +335,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 | SPMI_CHANNEL_VALID;
+ 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;