Merge tag 'qcom-more-for-2025.07' of https://source.denx.de/u-boot/custodians/u-boot-snapdragon
More Qualcomm fixes for 2025.07
* Adjust fdtfile logic to support more boards
* Support linux,code variable in qcom-pmic button driver
* Minor CLK API adjustments and apq8096/msm8916 fixes
* vbus regulator register fixes
* dragonboard410c KASLR support and other fixes
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index 3ab75f0..5547d6d 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -409,52 +409,39 @@
return;
}
- /* The last compatible is always the SoC compatible */
- ret = ofnode_read_string_index(root, "compatible", compat_count - 1, &last_compat);
- if (ret < 0) {
- log_warning("Can't read second compatible\n");
- return;
- }
-
- /* Copy the second compat (e.g. "qcom,sdm845") into buf */
- strlcpy(buf, last_compat, sizeof(buf) - 1);
- tmp = buf;
-
- /* strsep() is destructive, it replaces the comma with a \0 */
- if (!strsep(&tmp, ",")) {
- log_warning("second compatible '%s' has no ','\n", buf);
- return;
- }
-
- /* tmp now points to just the "sdm845" part of the string */
- env_set("soc", tmp);
-
- /* Now figure out the "board" part from the first compatible */
- memset(buf, 0, sizeof(buf));
strlcpy(buf, first_compat, sizeof(buf) - 1);
tmp = buf;
/* The Qualcomm reference boards (RBx, HDK, etc) */
if (!strncmp("qcom", buf, strlen("qcom"))) {
+ char *soc;
+
/*
* They all have the first compatible as "qcom,<soc>-<board>"
* (e.g. "qcom,qrb5165-rb5"). We extract just the part after
* the dash.
*/
- if (!strsep(&tmp, "-")) {
+ if (!strsep(&tmp, ",")) {
+ log_warning("compatible '%s' has no ','\n", buf);
+ return;
+ }
+ soc = strsep(&tmp, "-");
+ if (!soc) {
log_warning("compatible '%s' has no '-'\n", buf);
return;
}
- /* tmp is now "rb5" */
+
+ env_set("soc", soc);
env_set("board", tmp);
} else {
if (!strsep(&tmp, ",")) {
log_warning("compatible '%s' has no ','\n", buf);
return;
}
- /* for thundercomm we just want the bit after the comma (e.g. "db845c"),
- * for all other boards we replace the comma with a '-' and take both
- * (e.g. "oneplus-enchilada")
+ /*
+ * For thundercomm we just want the bit after the comma
+ * (e.g. "db845c"), for all other boards we replace the comma
+ * with a '-' and take both (e.g. "oneplus-enchilada")
*/
if (!strncmp("thundercomm", buf, strlen("thundercomm"))) {
env_set("board", tmp);
@@ -462,6 +449,28 @@
*(tmp - 1) = '-';
env_set("board", buf);
}
+
+ /* The last compatible is always the SoC compatible */
+ ret = ofnode_read_string_index(root, "compatible",
+ compat_count - 1, &last_compat);
+ if (ret < 0) {
+ log_warning("Can't read second compatible\n");
+ return;
+ }
+
+ /* Copy the last compat (e.g. "qcom,sdm845") into buf */
+ memset(buf, 0, sizeof(buf));
+ strlcpy(buf, last_compat, sizeof(buf) - 1);
+ tmp = buf;
+
+ /* strsep() is destructive, it replaces the comma with a \0 */
+ if (!strsep(&tmp, ",")) {
+ log_warning("second compatible '%s' has no ','\n", buf);
+ return;
+ }
+
+ /* tmp now points to just the "sdm845" part of the string */
+ env_set("soc", tmp);
}
/* Now build the full path name */
diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.env b/board/qualcomm/dragonboard410c/dragonboard410c.env
index 38399d6..ab25343 100644
--- a/board/qualcomm/dragonboard410c/dragonboard410c.env
+++ b/board/qualcomm/dragonboard410c/dragonboard410c.env
@@ -2,5 +2,5 @@
initrd_high=0xffffffffffffffff
fastboot=fastboot -l $fastboot_addr_r usb 0
boot_targets=usb mmc1 mmc0 pxe
-button_cmd_0_name=vol_down
+button_cmd_0_name=Volume Down
button_cmd_0=run fastboot
diff --git a/configs/dragonboard410c_defconfig b/configs/dragonboard410c_defconfig
index 449d48a..d267b6e 100644
--- a/configs/dragonboard410c_defconfig
+++ b/configs/dragonboard410c_defconfig
@@ -4,7 +4,6 @@
CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y
CONFIG_ARCH_SNAPDRAGON=y
CONFIG_TEXT_BASE=0x8f600000
-CONFIG_SYS_MALLOC_LEN=0x802000
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x8007fff0
CONFIG_ENV_SIZE=0x2000
@@ -56,6 +55,8 @@
CONFIG_PINCTRL_QCOM_APQ8016=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_QCOM=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_MSM=y
CONFIG_MSM_SERIAL=y
CONFIG_SPMI_MSM=y
CONFIG_USB=y
diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c
index e3bb9bd..85addfe 100644
--- a/drivers/button/button-qcom-pmic.c
+++ b/drivers/button/button-qcom-pmic.c
@@ -143,6 +143,21 @@
priv->base = base;
+ ret = dev_read_u32(dev, "linux,code", &priv->code);
+ if (ret == 0) {
+ /* convert key, if read OK */
+ switch (priv->code) {
+ case KEY_VOLUMEDOWN:
+ priv->code = KEY_DOWN;
+ uc_plat->label = "Volume Down";
+ break;
+ case KEY_VOLUMEUP:
+ priv->code = KEY_UP;
+ uc_plat->label = "Volume Up";
+ break;
+ }
+ }
+
/* Do a sanity check */
ret = pmic_reg_read(priv->pmic, priv->base + REG_TYPE);
if (ret != 0x1 && ret != 0xb) {
diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c
index 6a53f90..b7bd9c9 100644
--- a/drivers/clk/qcom/clock-apq8016.c
+++ b/drivers/clk/qcom/clock-apq8016.c
@@ -23,10 +23,7 @@
#define APCS_GPLL_ENA_VOTE (0x45000)
#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004)
-#define SDCC_BCR(n) ((n * 0x1000) + 0x41000)
-#define SDCC_CMD_RCGR(n) (((n + 1) * 0x1000) + 0x41004)
-#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018)
-#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C)
+#define SDCC_CMD_RCGR(n) (((n) * 0x1000) + 0x42004)
/* BLSP1 AHB clock (root clock for BLSP) */
#define BLSP1_AHB_CBCR 0x1008
@@ -54,9 +51,13 @@
};
static const struct gate_clk apq8016_clks[] = {
- GATE_CLK(GCC_PRNG_AHB_CLK, 0x45004, BIT(8)),
- GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0)),
- GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0)),
+ GATE_CLK_POLLED(GCC_PRNG_AHB_CLK, 0x45004, BIT(8), 0x13004),
+ GATE_CLK_POLLED(GCC_SDCC1_AHB_CLK, 0x4201c, BIT(0), 0x4201c),
+ GATE_CLK_POLLED(GCC_SDCC1_APPS_CLK, 0x42018, BIT(0), 0x42018),
+ GATE_CLK_POLLED(GCC_SDCC2_AHB_CLK, 0x4301c, BIT(0), 0x4301c),
+ GATE_CLK_POLLED(GCC_SDCC2_APPS_CLK, 0x43018, BIT(0), 0x43018),
+ GATE_CLK_POLLED(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0), 0x41008),
+ GATE_CLK_POLLED(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0), 0x41004),
};
/* SDHCI */
@@ -67,12 +68,10 @@
if (rate == 200000000)
div = 4;
- clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot));
/* 800Mhz/div, gpll0 */
clk_rcg_set_rate_mnd(priv->base, SDCC_CMD_RCGR(slot), div, 0, 0,
CFG_CLK_SRC_GPLL0, 8);
clk_enable_gpll0(priv->base, &gpll0_vote_clk);
- clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot));
return rate;
}
diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c
index 7687bbe..6b46d9d 100644
--- a/drivers/clk/qcom/clock-qcom.c
+++ b/drivers/clk/qcom/clock-qcom.c
@@ -74,6 +74,33 @@
} while ((val != BRANCH_ON_VAL) && (val != BRANCH_NOC_FSM_ON_VAL));
}
+int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
+{
+ if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) {
+ log_err("gcc@%#08llx: unknown clock ID %lu!\n",
+ priv->base, id);
+ return -ENOENT;
+ }
+
+ setbits_le32(priv->base + priv->data->clks[id].reg, priv->data->clks[id].en_val);
+ if (priv->data->clks[id].cbcr_reg) {
+ unsigned int count;
+ u32 val;
+
+ for (count = 0; count < 200; count++) {
+ val = readl(priv->base + priv->data->clks[id].cbcr_reg);
+ val &= BRANCH_CHECK_MASK;
+ if (val == BRANCH_ON_VAL || val == BRANCH_NOC_FSM_ON_VAL)
+ break;
+ udelay(1);
+ }
+ if (WARN(count == 200, "WARNING: Clock @ %#lx [%#010x] stuck at off\n",
+ priv->data->clks[id].cbcr_reg, val))
+ return -EBUSY;
+ }
+ return 0;
+}
+
#define APPS_CMD_RCGR_UPDATE BIT(0)
/* Update clock command via CMD_RCGR */
diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h
index f43edea..1b60882 100644
--- a/drivers/clk/qcom/clock-qcom.h
+++ b/drivers/clk/qcom/clock-qcom.h
@@ -52,13 +52,20 @@
struct gate_clk {
uintptr_t reg;
u32 en_val;
+ uintptr_t cbcr_reg;
const char *name;
};
+/*
+ * GATE_CLK() is deprecated: Use GATE_CLK_POLLED() instead to ensure the clock
+ * is running before we start making use of devices or registers.
+ */
#ifdef DEBUG
-#define GATE_CLK(clk, reg, val) [clk] = { reg, val, #clk }
+#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, #clk }
+#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, #clk }
#else
-#define GATE_CLK(clk, reg, val) [clk] = { reg, val, NULL }
+#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, NULL }
+#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, NULL }
#endif
struct qcom_reset_map {
@@ -107,19 +114,6 @@
int source);
void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled);
-static inline int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
-{
- u32 val;
- if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) {
- log_err("gcc@%#08llx: unknown clock ID %lu!\n",
- priv->base, id);
- return -ENOENT;
- }
-
- val = readl(priv->base + priv->data->clks[id].reg);
- writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg);
-
- return 0;
-}
+int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id);
#endif
diff --git a/drivers/power/regulator/qcom_usb_vbus_regulator.c b/drivers/power/regulator/qcom_usb_vbus_regulator.c
index 2d58ef5..07f118d 100644
--- a/drivers/power/regulator/qcom_usb_vbus_regulator.c
+++ b/drivers/power/regulator/qcom_usb_vbus_regulator.c
@@ -15,14 +15,33 @@
#include <power/pmic.h>
#include <power/regulator.h>
-#define CMD_OTG 0x50
+enum pm8x50b_vbus {
+ PM8150B,
+ PM8550B,
+};
+
#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_otg_regs {
+ u32 otg_cmd;
+ u32 otg_cfg;
+};
struct qcom_usb_vbus_priv {
phys_addr_t base;
+ struct qcom_otg_regs *regs;
+};
+
+static const struct qcom_otg_regs qcom_otg[] = {
+ [PM8150B] = {
+ .otg_cmd = 0x40,
+ .otg_cfg = 0x53,
+ },
+ [PM8550B] = {
+ .otg_cmd = 0x50,
+ .otg_cfg = 0x56,
+ },
};
static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev)
@@ -38,8 +57,9 @@
static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev)
{
+ const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)];
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
- int otg_en_reg = priv->base + CMD_OTG;
+ int otg_en_reg = priv->base + regs->otg_cmd;
int ret;
ret = pmic_reg_read(dev->parent, otg_en_reg);
@@ -53,8 +73,9 @@
static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable)
{
+ const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)];
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
- int otg_en_reg = priv->base + CMD_OTG;
+ int otg_en_reg = priv->base + regs->otg_cmd;
int ret;
if (enable) {
@@ -76,8 +97,9 @@
static int qcom_usb_vbus_regulator_probe(struct udevice *dev)
{
+ const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)];
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
- int otg_cfg_reg = priv->base + OTG_CFG;
+ int otg_cfg_reg = priv->base + regs->otg_cfg;
int ret;
/* Disable HW logic for VBUS enable */
@@ -96,7 +118,8 @@
};
static const struct udevice_id qcom_usb_vbus_regulator_ids[] = {
- { .compatible = "qcom,pm8150b-vbus-reg"},
+ { .compatible = "qcom,pm8150b-vbus-reg", .data = PM8150B },
+ { .compatible = "qcom,pm8550b-vbus-reg", .data = PM8550B },
{ },
};