"Das U-Boot" Source Tree

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

Tom Rini fdc0dcbb d1555de5

+129 -61
+36 -27
arch/arm/mach-snapdragon/board.c
··· 409 409 return; 410 410 } 411 411 412 - /* The last compatible is always the SoC compatible */ 413 - ret = ofnode_read_string_index(root, "compatible", compat_count - 1, &last_compat); 414 - if (ret < 0) { 415 - log_warning("Can't read second compatible\n"); 416 - return; 417 - } 418 - 419 - /* Copy the second compat (e.g. "qcom,sdm845") into buf */ 420 - strlcpy(buf, last_compat, sizeof(buf) - 1); 421 - tmp = buf; 422 - 423 - /* strsep() is destructive, it replaces the comma with a \0 */ 424 - if (!strsep(&tmp, ",")) { 425 - log_warning("second compatible '%s' has no ','\n", buf); 426 - return; 427 - } 428 - 429 - /* tmp now points to just the "sdm845" part of the string */ 430 - env_set("soc", tmp); 431 - 432 - /* Now figure out the "board" part from the first compatible */ 433 - memset(buf, 0, sizeof(buf)); 434 412 strlcpy(buf, first_compat, sizeof(buf) - 1); 435 413 tmp = buf; 436 414 437 415 /* The Qualcomm reference boards (RBx, HDK, etc) */ 438 416 if (!strncmp("qcom", buf, strlen("qcom"))) { 417 + char *soc; 418 + 439 419 /* 440 420 * They all have the first compatible as "qcom,<soc>-<board>" 441 421 * (e.g. "qcom,qrb5165-rb5"). We extract just the part after 442 422 * the dash. 443 423 */ 444 - if (!strsep(&tmp, "-")) { 424 + if (!strsep(&tmp, ",")) { 425 + log_warning("compatible '%s' has no ','\n", buf); 426 + return; 427 + } 428 + soc = strsep(&tmp, "-"); 429 + if (!soc) { 445 430 log_warning("compatible '%s' has no '-'\n", buf); 446 431 return; 447 432 } 448 - /* tmp is now "rb5" */ 433 + 434 + env_set("soc", soc); 449 435 env_set("board", tmp); 450 436 } else { 451 437 if (!strsep(&tmp, ",")) { 452 438 log_warning("compatible '%s' has no ','\n", buf); 453 439 return; 454 440 } 455 - /* for thundercomm we just want the bit after the comma (e.g. "db845c"), 456 - * for all other boards we replace the comma with a '-' and take both 457 - * (e.g. "oneplus-enchilada") 441 + /* 442 + * For thundercomm we just want the bit after the comma 443 + * (e.g. "db845c"), for all other boards we replace the comma 444 + * with a '-' and take both (e.g. "oneplus-enchilada") 458 445 */ 459 446 if (!strncmp("thundercomm", buf, strlen("thundercomm"))) { 460 447 env_set("board", tmp); ··· 462 449 *(tmp - 1) = '-'; 463 450 env_set("board", buf); 464 451 } 452 + 453 + /* The last compatible is always the SoC compatible */ 454 + ret = ofnode_read_string_index(root, "compatible", 455 + compat_count - 1, &last_compat); 456 + if (ret < 0) { 457 + log_warning("Can't read second compatible\n"); 458 + return; 459 + } 460 + 461 + /* Copy the last compat (e.g. "qcom,sdm845") into buf */ 462 + memset(buf, 0, sizeof(buf)); 463 + strlcpy(buf, last_compat, sizeof(buf) - 1); 464 + tmp = buf; 465 + 466 + /* strsep() is destructive, it replaces the comma with a \0 */ 467 + if (!strsep(&tmp, ",")) { 468 + log_warning("second compatible '%s' has no ','\n", buf); 469 + return; 470 + } 471 + 472 + /* tmp now points to just the "sdm845" part of the string */ 473 + env_set("soc", tmp); 465 474 } 466 475 467 476 /* Now build the full path name */
+1 -1
board/qualcomm/dragonboard410c/dragonboard410c.env
··· 2 2 initrd_high=0xffffffffffffffff 3 3 fastboot=fastboot -l $fastboot_addr_r usb 0 4 4 boot_targets=usb mmc1 mmc0 pxe 5 - button_cmd_0_name=vol_down 5 + button_cmd_0_name=Volume Down 6 6 button_cmd_0=run fastboot
+2 -1
configs/dragonboard410c_defconfig
··· 4 4 CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y 5 5 CONFIG_ARCH_SNAPDRAGON=y 6 6 CONFIG_TEXT_BASE=0x8f600000 7 - CONFIG_SYS_MALLOC_LEN=0x802000 8 7 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y 9 8 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x8007fff0 10 9 CONFIG_ENV_SIZE=0x2000 ··· 56 55 CONFIG_PINCTRL_QCOM_APQ8016=y 57 56 CONFIG_DM_PMIC=y 58 57 CONFIG_PMIC_QCOM=y 58 + CONFIG_DM_RNG=y 59 + CONFIG_RNG_MSM=y 59 60 CONFIG_MSM_SERIAL=y 60 61 CONFIG_SPMI_MSM=y 61 62 CONFIG_USB=y
+15
drivers/button/button-qcom-pmic.c
··· 143 143 144 144 priv->base = base; 145 145 146 + ret = dev_read_u32(dev, "linux,code", &priv->code); 147 + if (ret == 0) { 148 + /* convert key, if read OK */ 149 + switch (priv->code) { 150 + case KEY_VOLUMEDOWN: 151 + priv->code = KEY_DOWN; 152 + uc_plat->label = "Volume Down"; 153 + break; 154 + case KEY_VOLUMEUP: 155 + priv->code = KEY_UP; 156 + uc_plat->label = "Volume Up"; 157 + break; 158 + } 159 + } 160 + 146 161 /* Do a sanity check */ 147 162 ret = pmic_reg_read(priv->pmic, priv->base + REG_TYPE); 148 163 if (ret != 0x1 && ret != 0xb) {
+8 -9
drivers/clk/qcom/clock-apq8016.c
··· 23 23 #define APCS_GPLL_ENA_VOTE (0x45000) 24 24 #define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) 25 25 26 - #define SDCC_BCR(n) ((n * 0x1000) + 0x41000) 27 - #define SDCC_CMD_RCGR(n) (((n + 1) * 0x1000) + 0x41004) 28 - #define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018) 29 - #define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C) 26 + #define SDCC_CMD_RCGR(n) (((n) * 0x1000) + 0x42004) 30 27 31 28 /* BLSP1 AHB clock (root clock for BLSP) */ 32 29 #define BLSP1_AHB_CBCR 0x1008 ··· 54 51 }; 55 52 56 53 static const struct gate_clk apq8016_clks[] = { 57 - GATE_CLK(GCC_PRNG_AHB_CLK, 0x45004, BIT(8)), 58 - GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0)), 59 - GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0)), 54 + GATE_CLK_POLLED(GCC_PRNG_AHB_CLK, 0x45004, BIT(8), 0x13004), 55 + GATE_CLK_POLLED(GCC_SDCC1_AHB_CLK, 0x4201c, BIT(0), 0x4201c), 56 + GATE_CLK_POLLED(GCC_SDCC1_APPS_CLK, 0x42018, BIT(0), 0x42018), 57 + GATE_CLK_POLLED(GCC_SDCC2_AHB_CLK, 0x4301c, BIT(0), 0x4301c), 58 + GATE_CLK_POLLED(GCC_SDCC2_APPS_CLK, 0x43018, BIT(0), 0x43018), 59 + GATE_CLK_POLLED(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0), 0x41008), 60 + GATE_CLK_POLLED(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0), 0x41004), 60 61 }; 61 62 62 63 /* SDHCI */ ··· 67 68 if (rate == 200000000) 68 69 div = 4; 69 70 70 - clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot)); 71 71 /* 800Mhz/div, gpll0 */ 72 72 clk_rcg_set_rate_mnd(priv->base, SDCC_CMD_RCGR(slot), div, 0, 0, 73 73 CFG_CLK_SRC_GPLL0, 8); 74 74 clk_enable_gpll0(priv->base, &gpll0_vote_clk); 75 - clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot)); 76 75 77 76 return rate; 78 77 }
+27
drivers/clk/qcom/clock-qcom.c
··· 74 74 } while ((val != BRANCH_ON_VAL) && (val != BRANCH_NOC_FSM_ON_VAL)); 75 75 } 76 76 77 + int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) 78 + { 79 + if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) { 80 + log_err("gcc@%#08llx: unknown clock ID %lu!\n", 81 + priv->base, id); 82 + return -ENOENT; 83 + } 84 + 85 + setbits_le32(priv->base + priv->data->clks[id].reg, priv->data->clks[id].en_val); 86 + if (priv->data->clks[id].cbcr_reg) { 87 + unsigned int count; 88 + u32 val; 89 + 90 + for (count = 0; count < 200; count++) { 91 + val = readl(priv->base + priv->data->clks[id].cbcr_reg); 92 + val &= BRANCH_CHECK_MASK; 93 + if (val == BRANCH_ON_VAL || val == BRANCH_NOC_FSM_ON_VAL) 94 + break; 95 + udelay(1); 96 + } 97 + if (WARN(count == 200, "WARNING: Clock @ %#lx [%#010x] stuck at off\n", 98 + priv->data->clks[id].cbcr_reg, val)) 99 + return -EBUSY; 100 + } 101 + return 0; 102 + } 103 + 77 104 #define APPS_CMD_RCGR_UPDATE BIT(0) 78 105 79 106 /* Update clock command via CMD_RCGR */
+10 -16
drivers/clk/qcom/clock-qcom.h
··· 52 52 struct gate_clk { 53 53 uintptr_t reg; 54 54 u32 en_val; 55 + uintptr_t cbcr_reg; 55 56 const char *name; 56 57 }; 57 58 59 + /* 60 + * GATE_CLK() is deprecated: Use GATE_CLK_POLLED() instead to ensure the clock 61 + * is running before we start making use of devices or registers. 62 + */ 58 63 #ifdef DEBUG 59 - #define GATE_CLK(clk, reg, val) [clk] = { reg, val, #clk } 64 + #define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, #clk } 65 + #define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, #clk } 60 66 #else 61 - #define GATE_CLK(clk, reg, val) [clk] = { reg, val, NULL } 67 + #define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, NULL } 68 + #define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, NULL } 62 69 #endif 63 70 64 71 struct qcom_reset_map { ··· 107 114 int source); 108 115 void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled); 109 116 110 - static inline int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) 111 - { 112 - u32 val; 113 - if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) { 114 - log_err("gcc@%#08llx: unknown clock ID %lu!\n", 115 - priv->base, id); 116 - return -ENOENT; 117 - } 118 - 119 - val = readl(priv->base + priv->data->clks[id].reg); 120 - writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg); 121 - 122 - return 0; 123 - } 117 + int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id); 124 118 125 119 #endif
+30 -7
drivers/power/regulator/qcom_usb_vbus_regulator.c
··· 15 15 #include <power/pmic.h> 16 16 #include <power/regulator.h> 17 17 18 - #define CMD_OTG 0x50 18 + enum pm8x50b_vbus { 19 + PM8150B, 20 + PM8550B, 21 + }; 22 + 19 23 #define OTG_EN BIT(0) 20 - // The 0 bit in this register's bit field is undocumented 21 - #define OTG_CFG 0x56 24 + 22 25 #define OTG_EN_SRC_CFG BIT(1) 23 26 27 + struct qcom_otg_regs { 28 + u32 otg_cmd; 29 + u32 otg_cfg; 30 + }; 24 31 struct qcom_usb_vbus_priv { 25 32 phys_addr_t base; 33 + struct qcom_otg_regs *regs; 34 + }; 35 + 36 + static const struct qcom_otg_regs qcom_otg[] = { 37 + [PM8150B] = { 38 + .otg_cmd = 0x40, 39 + .otg_cfg = 0x53, 40 + }, 41 + [PM8550B] = { 42 + .otg_cmd = 0x50, 43 + .otg_cfg = 0x56, 44 + }, 26 45 }; 27 46 28 47 static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev) ··· 38 57 39 58 static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev) 40 59 { 60 + const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)]; 41 61 struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); 42 - int otg_en_reg = priv->base + CMD_OTG; 62 + int otg_en_reg = priv->base + regs->otg_cmd; 43 63 int ret; 44 64 45 65 ret = pmic_reg_read(dev->parent, otg_en_reg); ··· 53 73 54 74 static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable) 55 75 { 76 + const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)]; 56 77 struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); 57 - int otg_en_reg = priv->base + CMD_OTG; 78 + int otg_en_reg = priv->base + regs->otg_cmd; 58 79 int ret; 59 80 60 81 if (enable) { ··· 76 97 77 98 static int qcom_usb_vbus_regulator_probe(struct udevice *dev) 78 99 { 100 + const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)]; 79 101 struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); 80 - int otg_cfg_reg = priv->base + OTG_CFG; 102 + int otg_cfg_reg = priv->base + regs->otg_cfg; 81 103 int ret; 82 104 83 105 /* Disable HW logic for VBUS enable */ ··· 96 118 }; 97 119 98 120 static const struct udevice_id qcom_usb_vbus_regulator_ids[] = { 99 - { .compatible = "qcom,pm8150b-vbus-reg"}, 121 + { .compatible = "qcom,pm8150b-vbus-reg", .data = PM8150B }, 122 + { .compatible = "qcom,pm8550b-vbus-reg", .data = PM8550B }, 100 123 { }, 101 124 }; 102 125