CI: https://git.u-boot-project.org/u-boot/custodians/u-boot-mmc/-/pipelines/781

- Enable MMC CMD23 for multi-block transfers
- Various fixes to mmc core
- Add PF9453 pmic/regulator driver
- Support SCP 4.36 map for renesas-r8a78000
This commit is contained in:
Tom Rini
2026-07-30 08:50:13 -06:00
15 changed files with 593 additions and 24 deletions
+32 -13
View File
@@ -325,7 +325,7 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
if ((status & MMC_STATUS_RDY_FOR_DATA) &&
(status & MMC_STATUS_CURR_STATE) !=
MMC_STATE_PRG)
break;
return 0;
if (status & MMC_STATUS_MASK) {
#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
@@ -340,14 +340,10 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
udelay(1000);
}
if (timeout_ms <= 0) {
#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
log_err("Timeout waiting card ready\n");
log_err("Timeout waiting card ready\n");
#endif
return -ETIMEDOUT;
}
return 0;
return -ETIMEDOUT;
}
int mmc_set_blocklen(struct mmc *mmc, int len)
@@ -461,6 +457,14 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
struct mmc_cmd cmd;
struct mmc_data data;
if (blkcnt > 1 && (mmc->host_caps & MMC_CAP_CMD23)) {
cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
cmd.cmdarg = blkcnt & 0x0000ffff;
cmd.resp_type = MMC_RSP_R1;
if (mmc_send_cmd(mmc, &cmd, NULL))
return 0;
}
if (blkcnt > 1)
cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
else
@@ -481,7 +485,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
if (mmc_send_cmd(mmc, &cmd, &data))
return 0;
if (blkcnt > 1) {
if (blkcnt > 1 && !(mmc->host_caps & MMC_CAP_CMD23)) {
if (mmc_send_stop_transmission(mmc, false)) {
#if !defined(CONFIG_XPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
log_err("mmc fail to send stop cmd\n");
@@ -494,7 +498,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
}
#if !CONFIG_IS_ENABLED(DM_MMC)
static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
{
if (mmc->cfg->ops->get_b_max)
return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt);
@@ -1037,6 +1041,10 @@ static int mmc_get_capabilities(struct mmc *mmc)
mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
/* CMD23(SET_BLOCK_COUNT) requires eMMC spec v3.1 or above */
if (mmc->version < MMC_VERSION_3)
mmc->host_caps &= ~MMC_CAP_CMD23;
if (mmc_host_is_spi(mmc))
return 0;
@@ -1436,6 +1444,8 @@ static int sd_get_capabilities(struct mmc *mmc)
if (mmc->scr[0] & SD_DATA_4BIT)
mmc->card_caps |= MMC_MODE_4BIT;
if (!(mmc->scr[0] & SD_SCR_CMD23_SUPPORT))
mmc->host_caps &= ~MMC_CAP_CMD23;
/* Version 1.0 doesn't support switching */
if (mmc->version == SD_VERSION_1_0)
@@ -3177,10 +3187,19 @@ int mmc_deinit(struct mmc *mmc)
return 0;
if (IS_SD(mmc)) {
caps_filtered = mmc->card_caps &
~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
MMC_CAP(UHS_SDR104));
u32 uhs_mask = UHS_CAPS;
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
/*
* Per SD spec, once a card enters 1.8V signaling it
* cannot revert to 3.3V without a power cycle.
* If the card is operating at 1.8V, keep UHS_SDR12
* as the minimum fallback mode.
*/
if (mmc_sd_card_using_v18(mmc))
uhs_mask &= ~MMC_CAP(UHS_SDR12);
#endif
caps_filtered = mmc->card_caps & ~uhs_mask;
return sd_select_mode_and_width(mmc, caps_filtered);
} else {
+4
View File
@@ -17,6 +17,10 @@ int mmc_poll_for_busy(struct mmc *mmc, int timeout);
int mmc_set_blocklen(struct mmc *mmc, int len);
#if !CONFIG_IS_ENABLED(DM_MMC)
int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt);
#endif
#if CONFIG_IS_ENABLED(BLK)
ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
void *dst);
+19 -6
View File
@@ -165,7 +165,15 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
if (blkcnt == 0)
return 0;
else if (blkcnt == 1)
if (blkcnt > 1 && mmc->host_caps & MMC_CAP_CMD23) {
cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
cmd.cmdarg = blkcnt & 0x0000ffff;
cmd.resp_type = MMC_RSP_R1;
if (mmc_send_cmd(mmc, &cmd, NULL))
return 0;
}
if (blkcnt == 1)
cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
else
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
@@ -191,10 +199,13 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
*/
}
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
/*
* SPI multiblock writes terminate using a special token, not CMD12.
* When CMD23 was issued the card auto-terminates, so CMD12 is also
* skipped in that case.
*/
if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
if (!mmc_host_is_spi(mmc) && blkcnt > 1 &&
!(mmc->host_caps & MMC_CAP_CMD23)) {
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
@@ -228,6 +239,7 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
int dev_num = block_dev->devnum;
lbaint_t cur, blocks_todo = blkcnt;
int err;
uint b_max;
struct mmc *mmc = find_mmc_device(dev_num);
if (!mmc)
@@ -240,9 +252,10 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
if (mmc_set_blocklen(mmc, mmc->write_bl_len))
return 0;
b_max = mmc_get_b_max(mmc, (void *)src, blkcnt);
do {
cur = (blocks_todo > mmc->cfg->b_max) ?
mmc->cfg->b_max : blocks_todo;
cur = (blocks_todo > b_max) ? b_max : blocks_todo;
if (mmc_write_blocks(mmc, start, cur, src) != cur)
return 0;
blocks_todo -= cur;
+1 -1
View File
@@ -452,7 +452,7 @@ static int rpmb_route_frames(struct mmc *mmc, struct s_rpmb *req,
return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
case RPMB_REQ_READ_DATA:
if (req_cnt != 1 || !req_cnt)
if (req_cnt != 1 || !rsp_cnt)
return -EINVAL;
return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
+2 -1
View File
@@ -733,7 +733,8 @@ static int sdhci_init(struct mmc *mmc)
*/
host->force_align_buffer = true;
#else
if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) {
if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
!host->align_buffer) {
host->align_buffer = memalign(8, 512 * 1024);
if (!host->align_buffer) {
log_err("Aligned buffer alloc failed\n");
@@ -166,6 +166,7 @@ struct rst_map_in {
#define GEN5_SCMI_SDK_4_30 0x010c0000
#define GEN5_SCMI_SDK_4_31 0x010d0000
#define GEN5_SCMI_SDK_4_32 0x010e0000
#define GEN5_SCMI_SDK_4_36 0x01100000
static const struct rst_map_in gen5_rst_map_dt_sdk_4_28[] = {
{ SCP_RESET_DOMAIN_ID_UFS0, 202 },
@@ -220,7 +221,8 @@ static int gen5_reset_of_xlate(struct reset_ctl *reset_ctl,
map = gen5_rst_map_dt_sdk_4_28;
map_size = ARRAY_SIZE(gen5_rst_map_dt_sdk_4_28);
} else if (priv->basever == GEN5_SCMI_SDK_4_31 ||
priv->basever == GEN5_SCMI_SDK_4_32) {
priv->basever == GEN5_SCMI_SDK_4_32 ||
priv->basever == GEN5_SCMI_SDK_4_36) {
map = gen5_rst_map_dt_sdk_4_31;
map_size = ARRAY_SIZE(gen5_rst_map_dt_sdk_4_31);
} else {
+15
View File
@@ -171,6 +171,21 @@ config SPL_DM_PMIC_PCA9450
This config enables implementation of driver-model pmic uclass features
for PMIC PCA9450 in SPL. The driver implements read/write operations.
config DM_PMIC_PF9453
bool "Enable Driver Model for PMIC PF9453"
depends on DM_I2C
help
This config enables implementation of driver-model pmic uclass features
for PMIC PF9453. The driver implements read/write operations.
config SPL_DM_PMIC_PF9453
bool "Enable Driver Model for PMIC PF9453 in SPL"
depends on SPL_DM_PMIC
depends on SPL_DM_I2C
help
This config enables implementation of driver-model pmic uclass features
for PMIC PF9453 in SPL. The driver implements read/write operations.
config DM_PMIC_PFUZE100
bool "Enable Driver Model for PMIC PFUZE100"
help
+1
View File
@@ -15,6 +15,7 @@ obj-$(CONFIG_$(PHASE_)DM_PMIC_BD71837) += bd71837.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_MP5416) += mp5416.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_PCA9450) += pca9450.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_PF9453) += pf9453.o
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
obj-$(CONFIG_PMIC_AB8500) += ab8500.o
+170
View File
@@ -0,0 +1,170 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2024 NXP
*/
#include <asm/global_data.h>
#include <asm-generic/gpio.h>
#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <i2c.h>
#include <linux/err.h>
#include <log.h>
#include <power/pmic.h>
#include <power/regulator.h>
#include <power/pf9453.h>
DECLARE_GLOBAL_DATA_PTR;
static const struct pmic_child_info pmic_children_info[] = {
/* buck */
{ .prefix = "b", .driver = PF9453_REGULATOR_DRIVER},
{ .prefix = "B", .driver = PF9453_REGULATOR_DRIVER},
/* ldo */
{ .prefix = "l", .driver = PF9453_REGULATOR_DRIVER},
{ .prefix = "L", .driver = PF9453_REGULATOR_DRIVER},
{ },
};
struct pf9453_priv {
struct gpio_desc *sd_vsel_gpio;
};
static int pf9453_reg_count(struct udevice *dev)
{
return PF9453_REG_NUM;
}
static bool is_reg_protect(uint reg)
{
switch (reg) {
case PF9453_BUCK1OUT:
case PF9453_BUCK2OUT:
case PF9453_BUCK3OUT:
case PF9453_BUCK4OUT:
case PF9453_LDO1OUT_L:
case PF9453_LDO1OUT_H:
case PF9453_LDO2OUT:
case PF9453_LDOSNVS_CFG1:
case PF9453_BUCK2OUT_MAX_LIMIT:
case PF9453_BUCK2OUT_MIN_LIMIT:
return true;
default:
return false;
}
}
static int pf9453_write(struct udevice *dev, uint reg, const uint8_t *buff, int len)
{
bool is_pro;
u32 val = PF9453_UNLOCK_KEY;
is_pro = is_reg_protect(reg);
if (is_pro) {
if (dm_i2c_write(dev, PF9453_REG_LOCK, (uint8_t *)&val, 1)) {
pr_err("write error to device: %p register: %#x!\n", dev, reg);
return -EIO;
}
if (dm_i2c_write(dev, reg, buff, len)) {
pr_err("write error to device: %p register: %#x!\n", dev, reg);
return -EIO;
}
val = PF9453_LOCK_KEY;
if (dm_i2c_write(dev, PF9453_REG_LOCK, (uint8_t *)&val, 1)) {
pr_err("write error to device: %p register: %#x!\n", dev, reg);
return -EIO;
}
} else {
if (dm_i2c_write(dev, reg, buff, len)) {
pr_err("write error to device: %p register: %#x!\n", dev, reg);
return -EIO;
}
}
return 0;
}
static int pf9453_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
{
if (dm_i2c_read(dev, reg, buff, len)) {
pr_err("read error from device: %p register: %#x!\n", dev, reg);
return -EIO;
}
return 0;
}
static int pf9453_bind(struct udevice *dev)
{
int children;
ofnode regulators_node;
regulators_node = dev_read_subnode(dev, "regulators");
if (!ofnode_valid(regulators_node)) {
debug("%s: %s regulators subnode not found!", __func__,
dev->name);
return -ENXIO;
}
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
children = pmic_bind_children(dev, regulators_node,
pmic_children_info);
if (!children)
debug("%s: %s - no child found\n", __func__, dev->name);
/* Always return success for this device */
return 0;
}
static int pf9453_probe(struct udevice *dev)
{
struct pf9453_priv *priv = dev_get_priv(dev);
unsigned int reset_ctrl;
int ret = 0;
if (CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(DM_REGULATOR_PF9453)) {
priv->sd_vsel_gpio = devm_gpiod_get_optional(dev, "sd-vsel",
GPIOD_IS_OUT |
GPIOD_IS_OUT_ACTIVE);
if (IS_ERR(priv->sd_vsel_gpio)) {
ret = PTR_ERR(priv->sd_vsel_gpio);
dev_err(dev, "Failed to request SD_VSEL GPIO: %d\n", ret);
if (ret)
return ret;
}
}
if (ofnode_read_bool(dev_ofnode(dev), "nxp,wdog_b-warm-reset"))
reset_ctrl = PF9453_PMIC_RESET_WDOG_B_CFG_WARM;
else
reset_ctrl = PF9453_PMIC_RESET_WDOG_B_CFG_COLD;
return pmic_clrsetbits(dev, PF9453_RESET_CTRL,
PF9453_PMIC_RESET_WDOG_B_CFG_MASK, reset_ctrl);
}
static struct dm_pmic_ops pf9453_ops = {
.reg_count = pf9453_reg_count,
.read = pf9453_read,
.write = pf9453_write,
};
static const struct udevice_id pf9453_ids[] = {
{ .compatible = "nxp,pf9453", .data = NXP_CHIP_TYPE_PF9453, },
{ }
};
U_BOOT_DRIVER(pmic_pf9453) = {
.name = "pf9453 pmic",
.id = UCLASS_PMIC,
.of_match = pf9453_ids,
.bind = pf9453_bind,
.probe = pf9453_probe,
.ops = &pf9453_ops,
.priv_auto = sizeof(struct pf9453_priv),
};
+15
View File
@@ -103,6 +103,21 @@ config SPL_DM_REGULATOR_PCA9450
This config enables implementation of driver-model regulator uclass
features for regulators on ROHM PCA9450 in SPL.
config DM_REGULATOR_PF9453
bool "Enable Driver Model for NXP PF9453 regulators"
depends on DM_REGULATOR && DM_PMIC_PF9453
help
This config enables implementation of driver-model regulator uclass
features for regulators on NXP PF9453 PMICs. PF9453 contains 6 bucks
and 5 LDOS. The driver implements get/set api for value and enable.
config SPL_DM_REGULATOR_PF9453
bool "Enable Driver Model for NXP PF9453 regulators in SPL"
depends on DM_REGULATOR_PF9453 && SPL
help
This config enables implementation of driver-model regulator uclass
features for regulators on ROHM PF9453 in SPL.
config DM_REGULATOR_DA9063
bool "Enable Driver Model for REGULATOR DA9063"
depends on DM_REGULATOR && DM_PMIC_DA9063
+1
View File
@@ -18,6 +18,7 @@ obj-$(CONFIG_DM_REGULATOR_NPCM8XX) += npcm8xx_regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PFUZE100) += pfuze100.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_BD71837) += bd71837.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PCA9450) += pca9450.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_PF9453) += pf9453.o
obj-$(CONFIG_$(PHASE_)REGULATOR_PWM) += pwm_regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_COMMON) += regulator_common.o
+256
View File
@@ -0,0 +1,256 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* NXP PF9453 regulator driver
* Copyright 2024 NXP
*/
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <linux/bitops.h>
#include <power/pf9453.h>
#include <power/pmic.h>
#include <power/regulator.h>
/**
* struct pf9453_vrange - describe linear range of voltages
*
* @min_volt: smallest voltage in range
* @step: how much voltage changes at each selector step
* @min_sel: smallest selector in the range
* @max_sel: maximum selector in the range
*/
struct pf9453_vrange {
unsigned int min_volt;
unsigned int step;
u8 min_sel;
u8 max_sel;
};
/**
* struct pf9453_plat - describe regulator control registers
*
* @name: name of the regulator. Used for matching the dt-entry
* @enable_reg: register address used to enable/disable regulator
* @enablemask: register mask used to enable/disable regulator
* @volt_reg: register address used to configure regulator voltage
* @volt_mask: register mask used to configure regulator voltage
* @ranges: pointer to ranges of regulator voltages and matching register
* values
* @numranges: number of voltage ranges pointed by ranges
*/
struct pf9453_plat {
const char *name;
u8 enable_reg;
u8 enablemask;
u8 volt_reg;
u8 volt_mask;
struct pf9453_vrange *ranges;
unsigned int numranges;
};
#define PCA_RANGE(_min, _vstep, _sel_low, _sel_hi) \
{ \
.min_volt = (_min), .step = (_vstep), \
.min_sel = (_sel_low), .max_sel = (_sel_hi), \
}
#define PCA_DATA(_name, enreg, enmask, vreg, vmask, _range, _numranges) \
{ \
.name = (_name), .enable_reg = (enreg), .enablemask = (enmask), \
.volt_reg = (vreg), .volt_mask = (vmask), .ranges = (_range), \
.numranges = _numranges \
}
static struct pf9453_vrange pf9453_buck134_vranges[] = {
PCA_RANGE(600000, 25000, 0, 0x7f),
};
static struct pf9453_vrange pf9453_buck2_vranges[] = {
PCA_RANGE(600000, 12500, 0, 0x7f),
};
static struct pf9453_vrange pf9453_ldo1_vranges[] = {
PCA_RANGE(800000, 25000, 0x0, 0x64),
};
static struct pf9453_vrange pf9453_ldo2_vranges[] = {
PCA_RANGE(500000, 25000, 0x0, 0x3a),
};
static struct pf9453_vrange pf9453_ldosnvs_vranges[] = {
PCA_RANGE(800000, 25000, 0x0, 0x58),
};
static struct pf9453_plat pf9453_reg_data[] = {
PCA_DATA("BUCK1", PF9453_BUCK1CTRL, PF9453_EN_MODE_MASK,
PF9453_BUCK1OUT, PF9453_BUCK_RUN_MASK,
pf9453_buck134_vranges, ARRAY_SIZE(pf9453_buck134_vranges)),
PCA_DATA("BUCK2", PF9453_BUCK2CTRL, PF9453_EN_MODE_MASK,
PF9453_BUCK2OUT, PF9453_BUCK_RUN_MASK,
pf9453_buck2_vranges, ARRAY_SIZE(pf9453_buck2_vranges)),
PCA_DATA("BUCK3", PF9453_BUCK3CTRL, PF9453_EN_MODE_MASK,
PF9453_BUCK3OUT, PF9453_BUCK_RUN_MASK,
pf9453_buck134_vranges, ARRAY_SIZE(pf9453_buck134_vranges)),
PCA_DATA("BUCK4", PF9453_BUCK4CTRL, PF9453_EN_MODE_MASK,
PF9453_BUCK4OUT, PF9453_BUCK_RUN_MASK,
pf9453_buck134_vranges, ARRAY_SIZE(pf9453_buck134_vranges)),
/* LDOs */
PCA_DATA("LDO1", PF9453_LDO1CFG, PF9453_EN_MODE_MASK,
PF9453_LDO1OUT_H, PF9453_LDO1_MASK,
pf9453_ldo1_vranges, ARRAY_SIZE(pf9453_ldo1_vranges)),
PCA_DATA("LDO2", PF9453_LDO2CFG, PF9453_EN_MODE_MASK,
PF9453_LDO2OUT, PF9453_LDO2_MASK,
pf9453_ldo2_vranges, ARRAY_SIZE(pf9453_ldo2_vranges)),
PCA_DATA("LDO-SNVS", PF9453_LDOSNVS_CFG2, PF9453_EN_MODE_MASK,
PF9453_LDOSNVS_CFG1, PF9453_LDOSNVS_MASK,
pf9453_ldosnvs_vranges, ARRAY_SIZE(pf9453_ldosnvs_vranges)),
};
static int vrange_find_value(struct pf9453_vrange *r, unsigned int sel,
unsigned int *val)
{
if (!val || sel < r->min_sel || sel > r->max_sel)
return -EINVAL;
*val = r->min_volt + r->step * (sel - r->min_sel);
return 0;
}
static int vrange_find_selector(struct pf9453_vrange *r, int val,
unsigned int *sel)
{
int ret = -EINVAL;
int num_vals = r->max_sel - r->min_sel + 1;
if (val >= r->min_volt &&
val <= r->min_volt + r->step * (num_vals - 1)) {
if (r->step) {
*sel = r->min_sel + ((val - r->min_volt) / r->step);
ret = 0;
} else {
*sel = r->min_sel;
ret = 0;
}
}
return ret;
}
static int pf9453_get_enable(struct udevice *dev)
{
struct pf9453_plat *plat = dev_get_plat(dev);
int val;
val = pmic_reg_read(dev->parent, plat->enable_reg);
if (val < 0)
return val;
return (val & plat->enablemask);
}
static int pf9453_set_enable(struct udevice *dev, bool enable)
{
int val = 0;
struct pf9453_plat *plat = dev_get_plat(dev);
if (enable)
val = plat->enablemask;
return pmic_clrsetbits(dev->parent, plat->enable_reg, plat->enablemask,
val);
}
static int pf9453_get_value(struct udevice *dev)
{
struct pf9453_plat *plat = dev_get_plat(dev);
unsigned int reg, tmp;
int i, ret;
ret = pmic_reg_read(dev->parent, plat->volt_reg);
if (ret < 0)
return ret;
reg = ret;
reg &= plat->volt_mask;
for (i = 0; i < plat->numranges; i++) {
struct pf9453_vrange *r = &plat->ranges[i];
if (!vrange_find_value(r, reg, &tmp))
return tmp;
}
pr_err("Unknown voltage value read from pmic\n");
return -EINVAL;
}
static int pf9453_set_value(struct udevice *dev, int uvolt)
{
struct pf9453_plat *plat = dev_get_plat(dev);
unsigned int sel;
int i, found = 0;
for (i = 0; i < plat->numranges; i++) {
struct pf9453_vrange *r = &plat->ranges[i];
found = !vrange_find_selector(r, uvolt, &sel);
if (found) {
unsigned int tmp;
/*
* We require exactly the requested value to be
* supported - this can be changed later if needed
*/
found = !vrange_find_value(r, sel, &tmp);
if (found && tmp == uvolt)
break;
found = 0;
}
}
if (!found)
return -EINVAL;
return pmic_clrsetbits(dev->parent, plat->volt_reg,
plat->volt_mask, sel);
}
static int pf9453_regulator_probe(struct udevice *dev)
{
struct pf9453_plat *plat = dev_get_plat(dev);
int i, type;
type = dev_get_driver_data(dev_get_parent(dev));
if (type != NXP_CHIP_TYPE_PF9453) {
debug("Unknown PMIC type\n");
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(pf9453_reg_data); i++) {
if (strcmp(dev->name, pf9453_reg_data[i].name))
continue;
*plat = pf9453_reg_data[i];
return 0;
}
pr_err("Unknown regulator '%s'\n", dev->name);
return -ENOENT;
}
static const struct dm_regulator_ops pf9453_regulator_ops = {
.get_value = pf9453_get_value,
.set_value = pf9453_set_value,
.get_enable = pf9453_get_enable,
.set_enable = pf9453_set_enable,
};
U_BOOT_DRIVER(pf9453_regulator) = {
.name = PF9453_REGULATOR_DRIVER,
.id = UCLASS_REGULATOR,
.ops = &pf9453_regulator_ops,
.probe = pf9453_regulator_probe,
.plat_auto = sizeof(struct pf9453_plat),
};
+3
View File
@@ -67,6 +67,7 @@ struct bd_info;
#define MMC_CAP_NONREMOVABLE BIT(14)
#define MMC_CAP_NEEDS_POLL BIT(15)
#define MMC_CAP_CD_ACTIVE_HIGH BIT(16)
#define MMC_CAP_CMD23 BIT(17)
#define MMC_MODE_8BIT BIT(30)
#define MMC_MODE_4BIT BIT(29)
@@ -141,6 +142,8 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define SD_HIGHSPEED_BUSY 0x00020000
#define SD_HIGHSPEED_SUPPORTED 0x00020000
#define SD_SCR_CMD23_SUPPORT BIT(1)
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
-2
View File
@@ -253,8 +253,6 @@
#define MMC_CAP_DRIVER_TYPE_C (1 << 24)
/* Host supports Driver Type D */
#define MMC_CAP_DRIVER_TYPE_D (1 << 25)
/* CMD23 supported. */
#define MMC_CAP_CMD23 (1 << 30)
/* Hardware reset */
#define MMC_CAP_HW_RESET (1 << 31)
+71
View File
@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2024 NXP
*/
#ifndef PF9453_H_
#define PF9453_H_
#define PF9453_REGULATOR_DRIVER "pf9453_regulator"
enum {
PF9453_REG_DEV_ID = 0x00,
PF9453_OTP_VER = 0x01,
PF9453_INT1 = 0x02,
PF9453_INT1_MSK = 0x03,
PF9453_INT1_STATUS = 0x04,
PF9453_VRFLT1_INT = 0x05,
PF9453_VRFLT1_MASK = 0x06,
PF9453_PWRON_STAT = 0x07,
PF9453_RESET_CTRL = 0x08,
PF9453_SW_RST = 0x09,
PF9453_PWR_CTRL = 0x0a,
PF9453_CONFIG1 = 0x0b,
PF9453_CONFIG2 = 0x0c,
PF9453_32K_CONFIG = 0x0d,
PF9453_BUCK1CTRL = 0x10,
PF9453_BUCK1OUT = 0x11,
PF9453_BUCK2CTRL = 0x14,
PF9453_BUCK2OUT = 0x15,
PF9453_BUCK2OUT_STBY = 0x1D,
PF9453_BUCK2OUT_MAX_LIMIT = 0x1F,
PF9453_BUCK2OUT_MIN_LIMIT = 0x20,
PF9453_BUCK3CTRL = 0x21,
PF9453_BUCK3OUT = 0x22,
PF9453_BUCK4CTRL = 0x2e,
PF9453_BUCK4OUT = 0x2f,
PF9453_LDO1OUT_L = 0x36,
PF9453_LDO1CFG = 0x37,
PF9453_LDO1OUT_H = 0x38,
PF9453_LDOSNVS_CFG1 = 0x39,
PF9453_LDOSNVS_CFG2 = 0x3a,
PF9453_LDO2CFG = 0x3b,
PF9453_LDO2OUT = 0x3c,
PF9453_BUCK_POK = 0x3d,
PF9453_LSW_CTRL1 = 0x40,
PF9453_LSW_CTRL2 = 0x41,
PF9453_REG_LOCK = 0x4e,
PF9453_REG_NUM,
};
int power_pf9453_init(unsigned char bus, unsigned char addr);
enum {
NXP_CHIP_TYPE_PF9453 = 0,
NXP_CHIP_TYPE_AMOUNT
};
#define PF9453_UNLOCK_KEY 0x5c
#define PF9453_LOCK_KEY 0x0
#define PF9453_EN_MODE_MASK 0x3
#define PF9453_BUCK_RUN_MASK 0x7f
#define PF9453_LDO1_MASK 0x7f
#define PF9453_LDO2_MASK 0x3f
#define PF9453_LDOSNVS_MASK 0x7f
#define PF9453_PMIC_RESET_WDOG_B_CFG_MASK 0xc0
#define PF9453_PMIC_RESET_WDOG_B_CFG_WARM 0x40
#define PF9453_PMIC_RESET_WDOG_B_CFG_COLD 0x80
#endif