mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-04 20:26:13 +02:00
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEtlGhRjxqvtBpDFXNBYMxKxlfZLYFAmg/DEUACgkQBYMxKxlf ZLaJ6A//awuGA5mY6mPRuk0HrSKMl+5JM7Vw//mLaZaNUl/1FnPVh/cWiiO74hRA OaUZqDd31Hkf9ow3of1xhyriQnw29bc8mfEWCAa4Zau2RZmIK8Ej3NP5fLg1ynsW Oq5VifegyuCTpBy1Dlh8FtLIZ+oK9aHe1DTg/8yKbMYJPtfWP0FlJznYyA0niQGD SHhm696ubPvDuozllln9ctoLjqCLQfunfCJXz+95HiXz9XSBZrm4374LcjhVm6CC NJmnLCDwNibwjPRBOydZ6ErjHc8CY8hi9yMd7jxtkrtyn6vldLbbNLHAplSzqXvD 2k25NginU8u8sMePpCPIJaEx0uMdyCsf/DbFVZM7xEg/xApq47JRfiS9QqTVBDqD tQr7/Tr5HSF4EtcejIkcTS01OtzQszePY4b9qlSKpkRT4EnnwD66ao27Kry6MqOg TpXm25WLJuApZiORwlfDoOa2kdCBVbrwf1hrQyq7yZ1OwD/3ywIzrGrvuOo2d4J4 dJPDmYxwOFXmzc8EUwGD0U65f/no90vWXsQ9jo2hrx873d+Yu6l/TvxGsI3W+92j Wlg2I5InIi/DcW98YjrZT5kcf50m4YIgiWVEQh0AnvpIOmtlt6PTKRr1niwSK9fo gwjgclB1RG9fc5lT+B7vH4jN9JwjOJcUYn5HY5knsMVNQ3H6r+4= =OiS4 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
fdc0dcbb2c
@ -409,52 +409,39 @@ static void configure_env(void)
|
||||
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 @@ static void configure_env(void)
|
||||
*(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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -4,7 +4,6 @@ CONFIG_COUNTER_FREQUENCY=19200000
|
||||
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_PINCONF=y
|
||||
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
|
||||
|
||||
@ -143,6 +143,21 @@ static int qcom_pwrkey_probe(struct udevice *dev)
|
||||
|
||||
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) {
|
||||
|
||||
@ -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 struct vote_clk gcc_blsp1_ahb_clk = {
|
||||
};
|
||||
|
||||
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 @@ static int apq8016_clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -74,6 +74,33 @@ void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk)
|
||||
} 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 */
|
||||
|
||||
@ -52,13 +52,20 @@ struct freq_tbl {
|
||||
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 @@ void clk_rcg_set_rate(phys_addr_t base, uint32_t cmd_rcgr, int div,
|
||||
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
|
||||
|
||||
@ -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_of_to_plat(struct udevice *dev)
|
||||
|
||||
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_get_enable(struct udevice *dev)
|
||||
|
||||
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_set_enable(struct udevice *dev, bool enable)
|
||||
|
||||
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 dm_regulator_ops qcom_usb_vbus_regulator_ops = {
|
||||
};
|
||||
|
||||
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 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user