diff options
| author | Tom Rini <[email protected]> | 2025-04-11 09:12:16 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-04-11 09:12:16 -0600 |
| commit | ff0b7d741dec48c9d1ce5e80ada5eaeac19b1b93 (patch) | |
| tree | 8f3952ebeb31a9ce0a35d419121e80cae41b547b /drivers | |
| parent | 295376ce8a32268a1bb0879eb0448e0c0e580727 (diff) | |
| parent | f3563fc30356c8079527b90e532407050dff7c7b (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.c | 8 | ||||
| -rw-r--r-- | drivers/button/button-uclass.c | 2 | ||||
| -rw-r--r-- | drivers/clk/clk-stub.c | 3 | ||||
| -rw-r--r-- | drivers/clk/qcom/clock-apq8096.c | 5 | ||||
| -rw-r--r-- | drivers/clk/qcom/clock-sc7280.c | 11 | ||||
| -rw-r--r-- | drivers/clk/qcom/clock-sdm845.c | 3 | ||||
| -rw-r--r-- | drivers/gpio/msm_gpio.c | 53 | ||||
| -rw-r--r-- | drivers/phy/qcom/phy-qcom-qusb2.c | 44 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/Kconfig | 15 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/Makefile | 2 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-qcom.c | 67 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-sa8775p.c | 623 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-sdm660.c | 226 | ||||
| -rw-r--r-- | drivers/power/regulator/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/power/regulator/Makefile | 1 | ||||
| -rw-r--r-- | drivers/power/regulator/qcom-rpmh-regulator.c | 45 | ||||
| -rw-r--r-- | drivers/power/regulator/qcom_usb_vbus_regulator.c | 111 | ||||
| -rw-r--r-- | drivers/spmi/spmi-msm.c | 59 |
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; |
