/* * Table of valid charger currents for different Maxim chipsets. * It is placed here because it is used by both charger and regulator driver.
*/ conststruct maxim_charger_current maxim_charger_currents[] = {
[MAXIM_DEVICE_TYPE_UNKNOWN] = { 0, 0, 0, 0 },
[MAXIM_DEVICE_TYPE_MAX14577] = {
.min = MAX14577_CHARGER_CURRENT_LIMIT_MIN,
.high_start = MAX14577_CHARGER_CURRENT_LIMIT_HIGH_START,
.high_step = MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP,
.max = MAX14577_CHARGER_CURRENT_LIMIT_MAX,
},
[MAXIM_DEVICE_TYPE_MAX77836] = {
.min = MAX77836_CHARGER_CURRENT_LIMIT_MIN,
.high_start = MAX77836_CHARGER_CURRENT_LIMIT_HIGH_START,
.high_step = MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP,
.max = MAX77836_CHARGER_CURRENT_LIMIT_MAX,
},
};
EXPORT_SYMBOL_GPL(maxim_charger_currents);
/* * maxim_charger_calc_reg_current - Calculate register value for current * @limits: constraints for charger, matching the MBCICHWRC register * @min_ua: minimal requested current, micro Amps * @max_ua: maximum requested current, micro Amps * @dst: destination to store calculated register value * * Calculates the value of MBCICHWRC (Fast Battery Charge Current) register * for given current and stores it under pointed 'dst'. The stored value * combines low bit (MBCICHWRCL) and high bits (MBCICHWRCH). It is also * properly shifted. * * The calculated register value matches the current which: * - is always between <limits.min, limits.max>; * - is always less or equal to max_ua; * - is the highest possible value; * - may be lower than min_ua. * * On success returns 0. On error returns -EINVAL (requested min/max current * is outside of given charger limits) and 'dst' is not set.
*/ int maxim_charger_calc_reg_current(conststruct maxim_charger_current *limits, unsignedint min_ua, unsignedint max_ua, u8 *dst)
{ unsignedint current_bits;
if (min_ua > max_ua) return -EINVAL;
if (min_ua > limits->max || max_ua < limits->min) return -EINVAL;
if (max_ua < limits->high_start) { /* * Less than high_start, so set the minimal current * (turn Low Bit off, 0 as high bits).
*/
*dst = 0x0; return 0;
}
/* max_ua is in range: <high_start, infinite>, cut it to limits.max */
max_ua = min(limits->max, max_ua);
max_ua -= limits->high_start; /* * There is no risk of overflow 'max_ua' here because: * - max_ua >= limits.high_start * - BUILD_BUG checks that 'limits' are: max >= high_start + high_step
*/
current_bits = max_ua / limits->high_step;
/* Turn Low Bit on (use range <limits.high_start, limits.max>) ... */
*dst = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT; /* and set proper High Bits */
*dst |= current_bits << CHGCTRL4_MBCICHWRCH_SHIFT;
staticbool max77836_muic_volatile_reg(struct device *dev, unsignedint reg)
{ /* Any max14577 volatile registers are also max77836 volatile. */ if (max14577_muic_volatile_reg(dev, reg)) returntrue;
switch (reg) { case MAX77836_FG_REG_VCELL_MSB ... MAX77836_FG_REG_SOC_LSB: case MAX77836_FG_REG_CRATE_MSB ... MAX77836_FG_REG_CRATE_LSB: case MAX77836_FG_REG_STATUS_H ... MAX77836_FG_REG_STATUS_L: case MAX77836_PMIC_REG_INTSRC: case MAX77836_PMIC_REG_TOPSYS_INT: case MAX77836_PMIC_REG_TOPSYS_STAT: returntrue; default: break;
} returnfalse;
}
/* * Max77836 specific initialization code for driver probe. * Adds new I2C dummy device, regmap and regmap IRQ chip. * Unmasks Interrupt Source register. * * On success returns 0. * On failure returns errno and reverts any changes done so far (e.g. remove * I2C dummy device), except masking the INT SRC register.
*/ staticint max77836_init(struct max14577 *max14577)
{ int ret;
u8 intsrc_mask;
max14577->i2c_pmic = i2c_new_dummy_device(max14577->i2c->adapter,
I2C_ADDR_PMIC); if (IS_ERR(max14577->i2c_pmic)) {
dev_err(max14577->dev, "Failed to register PMIC I2C device\n"); return PTR_ERR(max14577->i2c_pmic);
}
i2c_set_clientdata(max14577->i2c_pmic, max14577);
max14577->regmap_pmic = devm_regmap_init_i2c(max14577->i2c_pmic,
&max77836_pmic_regmap_config); if (IS_ERR(max14577->regmap_pmic)) {
ret = PTR_ERR(max14577->regmap_pmic);
dev_err(max14577->dev, "Failed to allocate PMIC register map: %d\n",
ret); goto err;
}
/* Un-mask MAX77836 Interrupt Source register */
ret = max14577_read_reg(max14577->regmap_pmic,
MAX77836_PMIC_REG_INTSRC_MASK, &intsrc_mask); if (ret < 0) {
dev_err(max14577->dev, "Failed to read PMIC register\n"); goto err;
}
intsrc_mask &= ~(MAX77836_INTSRC_MASK_TOP_INT_MASK);
intsrc_mask &= ~(MAX77836_INTSRC_MASK_MUIC_CHG_INT_MASK);
ret = max14577_write_reg(max14577->regmap_pmic,
MAX77836_PMIC_REG_INTSRC_MASK, intsrc_mask); if (ret < 0) {
dev_err(max14577->dev, "Failed to write PMIC register\n"); goto err;
}
ret = regmap_add_irq_chip(max14577->regmap_pmic, max14577->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &max77836_pmic_irq_chip,
&max14577->irq_data_pmic); if (ret != 0) {
dev_err(max14577->dev, "Failed to request PMIC IRQ %d: %d\n",
max14577->irq, ret); goto err;
}
return 0;
err:
i2c_unregister_device(max14577->i2c_pmic);
return ret;
}
/* * Max77836 specific de-initialization code for driver remove.
*/ staticvoid max77836_remove(struct max14577 *max14577)
{
regmap_del_irq_chip(max14577->irq, max14577->irq_data_pmic);
i2c_unregister_device(max14577->i2c_pmic);
}
if (device_may_wakeup(dev))
enable_irq_wake(max14577->irq); /* * MUIC IRQ must be disabled during suspend because if it happens * while suspended it will be handled before resuming I2C. * * When device is woken up from suspend (e.g. by ADC change), * an interrupt occurs before resuming I2C bus controller. * Interrupt handler tries to read registers but this read * will fail because I2C is still suspended.
*/
disable_irq(max14577->irq);
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.