staticbool is_reg_protect(uint reg)
{ switch (reg) { case PF9453_REG_BUCK1OUT: case PF9453_REG_BUCK2OUT: case PF9453_REG_BUCK3OUT: case PF9453_REG_BUCK4OUT: case PF9453_REG_LDO1OUT_L: case PF9453_REG_LDO1OUT_H: case PF9453_REG_LDO2OUT: case PF9453_REG_LDOSNVS_CFG1: case PF9453_REG_BUCK2OUT_MAX_LIMIT: case PF9453_REG_BUCK2OUT_MIN_LIMIT: returntrue; default: returnfalse;
}
}
staticint pf9453_pmic_write(struct pf9453 *pf9453, unsignedint reg, u8 mask, unsignedintval)
{ int ret = -EINVAL;
u8 data, key;
u32 rxBuf;
/* If not updating entire register, perform a read-mod-write */
data = val;
key = PF9453_UNLOCK_KEY;
if (mask != 0xffU) { /* Read data */
ret = regmap_read(pf9453->regmap, reg, &rxBuf); if (ret) {
dev_err(pf9453->dev, "Read reg=%0x error!\n", reg); return ret;
}
data = (val & mask) | (rxBuf & (~mask));
}
if (reg < PF9453_MAX_REG) { if (is_reg_protect(reg)) {
ret = regmap_raw_write(pf9453->regmap, PF9453_REG_LOCK, &key, 1U); if (ret) {
dev_err(pf9453->dev, "Write reg=%0x error!\n", reg); return ret;
}
ret = regmap_raw_write(pf9453->regmap, reg, &data, 1U); if (ret) {
dev_err(pf9453->dev, "Write reg=%0x error!\n", reg); return ret;
}
/** * pf9453_regulator_enable_regmap for regmap users * * @rdev: regulator to operate on * * Regulators that use regmap for their register I/O can set the * enable_reg and enable_mask fields in their descriptor and then use * this as their enable() operation, saving some code.
*/ staticint pf9453_regulator_enable_regmap(struct regulator_dev *rdev)
{ struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent); unsignedint val;
if (rdev->desc->enable_is_inverted) {
val = rdev->desc->disable_val;
} else {
val = rdev->desc->enable_val; if (!val)
val = rdev->desc->enable_mask;
}
/** * pf9453_regulator_disable_regmap for regmap users * * @rdev: regulator to operate on * * Regulators that use regmap for their register I/O can set the * enable_reg and enable_mask fields in their descriptor and then use * this as their disable() operation, saving some code.
*/ staticint pf9453_regulator_disable_regmap(struct regulator_dev *rdev)
{ struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent); unsignedint val;
if (rdev->desc->enable_is_inverted) {
val = rdev->desc->enable_val; if (!val)
val = rdev->desc->enable_mask;
} else {
val = rdev->desc->disable_val;
}
/** * pf9453_regulator_set_voltage_sel_regmap for regmap users * * @rdev: regulator to operate on * @sel: Selector to set * * Regulators that use regmap for their register I/O can set the * vsel_reg and vsel_mask fields in their descriptor and then use this * as their set_voltage_vsel operation, saving some code.
*/ staticint pf9453_regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsignedint sel)
{ struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent); int ret;
sel <<= ffs(rdev->desc->vsel_mask) - 1;
ret = pf9453_pmic_write(pf9453, rdev->desc->vsel_reg, rdev->desc->vsel_mask, sel); if (ret) return ret;
if (rdev->desc->apply_bit)
ret = pf9453_pmic_write(pf9453, rdev->desc->apply_reg,
rdev->desc->apply_bit, rdev->desc->apply_bit); return ret;
}
for (s = 0; s < num_sel; s++) { if (table[s] > max) {
max = table[s];
maxsel = s;
} if (table[s] >= target) { if (!found || table[s] - target < tmp - target) {
tmp = table[s];
*sel = s;
found = true; if (tmp == target) break;
}
}
}
if (!found) {
*sel = maxsel; return -EINVAL;
}
return 0;
}
/** * pf9453_regulator_set_ramp_delay_regmap * * @rdev: regulator to operate on * @ramp_delay: desired ramp delay value in microseconds * * Regulators that use regmap for their register I/O can set the ramp_reg * and ramp_mask fields in their descriptor and then use this as their * set_ramp_delay operation, saving some code.
*/ staticint pf9453_regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
{ struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent); unsignedint sel; int ret;
if (WARN_ON(!rdev->desc->n_ramp_values || !rdev->desc->ramp_delay_table)) return -EINVAL;
ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
rdev->desc->n_ramp_values, &sel);
if (ret) {
dev_warn(rdev_get_dev(rdev), "Can't set ramp-delay %u, setting %u\n", ramp_delay,
rdev->desc->ramp_delay_table[sel]);
}
ret = of_property_read_u32(np, prop, &uv); if (ret == -EINVAL) return 0; elseif (ret) return ret;
for (i = 0; i < desc->n_voltages; i++) {
ret = regulator_desc_list_voltage_linear_range(desc, i); if (ret < 0) continue; if (ret == uv) {
i <<= ffs(desc->vsel_mask) - 1;
ret = pf9453_pmic_write(pf9453, reg, mask, i); break;
}
}
/* Enable DVS control through PMIC_STBY_REQ for this BUCK */
ret = pf9453_pmic_write(pf9453, regulator->desc.enable_reg,
BUCK2_LPMODE, BUCK2_LPMODE);
} return ret;
}
ret = regmap_read(pf9453->regmap, PF9453_REG_DEV_ID, &device_id); if (ret) return dev_err_probe(&i2c->dev, ret, "Read device id error\n");
/* Check your board and dts for match the right pmic */ if ((device_id >> 4) != 0xb) return dev_err_probe(&i2c->dev, -EINVAL, "Device id(%x) mismatched\n",
device_id >> 4);
while (regulator_desc->desc.name) { conststruct regulator_desc *desc; struct regulator_dev *rdev;
if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
reset_ctrl = WDOG_B_CFG_WARM; else
reset_ctrl = WDOG_B_CFG_COLD;
/* Set reset behavior on assertion of WDOG_B signal */
ret = pf9453_pmic_write(pf9453, PF9453_REG_RESET_CTRL, WDOG_B_CFG_MASK, reset_ctrl); if (ret) return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n");
/* * The driver uses the LDO1OUT_H register to control the LDO1 regulator. * This is only valid if the SD_VSEL input of the PMIC is high. Let's * check if the pin is available as GPIO and set it to high.
*/
pf9453->sd_vsel_gpio = gpiod_get_optional(pf9453->dev, "sd-vsel", GPIOD_OUT_HIGH);
if (IS_ERR(pf9453->sd_vsel_gpio)) return dev_err_probe(&i2c->dev, PTR_ERR(pf9453->sd_vsel_gpio), "Failed to get SD_VSEL GPIO\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.