/****************** Teminology used in driver ******************** * Here are some terminology used from datasheet for quick reference: * Flexible Power Sequence (FPS): * The Flexible Power Sequencer (FPS) allows each regulator to power up under * hardware or software control. Additionally, each regulator can power on * independently or among a group of other regulators with an adjustable * power-up and power-down delays (sequencing). GPIO1, GPIO2, and GPIO3 can * be programmed to be part of a sequence allowing external regulators to be * sequenced along with internal regulators. 32KHz clock can be programmed to * be part of a sequence. * There is 3 FPS confguration registers and all resources are configured to * any of these FPS or no FPS.
*/
/* * MAX77620 and MAX20024 has the following steps of the interrupt handling * for TOP interrupts: * 1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting GLBLM. * 2. Read IRQTOP and service the interrupt. * 3. Once all interrupts has been checked and serviced, the interrupt service * routine un-masks the hardware interrupt line by clearing GLBLM.
*/ staticint max77620_irq_global_mask(void *irq_drv_data)
{ struct max77620_chip *chip = irq_drv_data; int ret;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT,
MAX77620_GLBLM_MASK, MAX77620_GLBLM_MASK); if (ret < 0)
dev_err(chip->dev, "Failed to set GLBLM: %d\n", ret);
/* max77620_get_fps_period_reg_value: Get FPS bit field value from * requested periods. * MAX77620 supports the FPS period of 40, 80, 160, 320, 540, 1280, 2560 * and 5120 microseconds. MAX20024 supports the FPS period of 20, 40, 80, * 160, 320, 540, 1280 and 2560 microseconds. * The FPS register has 3 bits field to set the FPS period as * bits max77620 max20024 * 000 40 20 * 001 80 40 * :::
*/ staticint max77620_get_fps_period_reg_value(struct max77620_chip *chip, int tperiod)
{ int fps_min_period; int i;
switch (chip->chip_id) { case MAX20024:
fps_min_period = MAX20024_FPS_PERIOD_MIN_US; break; case MAX77620:
fps_min_period = MAX77620_FPS_PERIOD_MIN_US; break; case MAX77663:
fps_min_period = MAX20024_FPS_PERIOD_MIN_US; break; default: return -EINVAL;
}
for (i = 0; i < 7; i++) { if (fps_min_period >= tperiod) return i;
fps_min_period *= 2;
}
return i;
}
/* max77620_config_fps: Configure FPS configuration registers * based on platform specific information.
*/ staticint max77620_config_fps(struct max77620_chip *chip, struct device_node *fps_np)
{ struct device *dev = chip->dev; unsignedint mask = 0, config = 0;
u32 fps_max_period;
u32 param_val; int tperiod, fps_id; int ret; char fps_name[10];
switch (chip->chip_id) { case MAX20024:
fps_max_period = MAX20024_FPS_PERIOD_MAX_US; break; case MAX77620:
fps_max_period = MAX77620_FPS_PERIOD_MAX_US; break; case MAX77663:
fps_max_period = MAX20024_FPS_PERIOD_MAX_US; break; default: return -EINVAL;
}
for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
sprintf(fps_name, "fps%d", fps_id); if (of_node_name_eq(fps_np, fps_name)) break;
}
if (fps_id == MAX77620_FPS_COUNT) {
dev_err(dev, "FPS node name %pOFn is not valid\n", fps_np); return -EINVAL;
}
fps_np = of_get_child_by_name(dev->of_node, "fps"); if (!fps_np) goto skip_fps;
for_each_child_of_node_scoped(fps_np, fps_child) {
ret = max77620_config_fps(chip, fps_child); if (ret < 0) {
of_node_put(fps_np); return ret;
}
}
of_node_put(fps_np);
config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_SLP_LPM_MSK, config); if (ret < 0) {
dev_err(dev, "Failed to update SLP_LPM: %d\n", ret); return ret;
}
skip_fps: if (chip->chip_id == MAX77663) return 0;
/* Enable wake on EN0 pin */
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_WK_EN0,
MAX77620_ONOFFCNFG2_WK_EN0); if (ret < 0) {
dev_err(dev, "Failed to update WK_EN0: %d\n", ret); return ret;
}
/* For MAX20024, SLPEN will be POR reset if CLRSE is b11 */ if ((chip->chip_id == MAX20024) && chip->sleep_enable) {
config = MAX77620_ONOFFCNFG1_SLPEN | MAX20024_ONOFFCNFG1_CLRSE;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
config, config); if (ret < 0) {
dev_err(dev, "Failed to update SLPEN: %d\n", ret); return ret;
}
}
return 0;
}
staticint max77620_read_es_version(struct max77620_chip *chip)
{ unsignedint val;
u8 cid_val[6]; int i; int ret;
for (i = MAX77620_REG_CID0; i <= MAX77620_REG_CID5; i++) {
ret = regmap_read(chip->rmap, i, &val); if (ret < 0) {
dev_err(chip->dev, "Failed to read CID: %d\n", ret); return ret;
}
dev_dbg(chip->dev, "CID%d: 0x%02x\n",
i - MAX77620_REG_CID0, val);
cid_val[i - MAX77620_REG_CID0] = val;
}
/* CID4 is OTP Version and CID5 is ES version */
dev_info(chip->dev, "PMIC Version OTP:0x%02X and ES:0x%X\n",
cid_val[4], MAX77620_CID5_DIDM(cid_val[5]));
staticint max77620_set_fps_period(struct max77620_chip *chip, int fps_id, int time_period)
{ int period = max77620_get_fps_period_reg_value(chip, time_period); int ret;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id,
MAX77620_FPS_TIME_PERIOD_MASK,
period << MAX77620_FPS_TIME_PERIOD_SHIFT); if (ret < 0) {
dev_err(chip->dev, "Failed to update FPS period: %d\n", ret); return ret;
}
for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) { if (chip->suspend_fps_period[fps] < 0) continue;
ret = max77620_set_fps_period(chip, fps,
chip->suspend_fps_period[fps]); if (ret < 0) return ret;
}
/* * For MAX20024: No need to configure SLPEN on suspend as * it will be configured on Init.
*/ if (chip->chip_id == MAX20024) goto out;
config = (chip->sleep_enable) ? MAX77620_ONOFFCNFG1_SLPEN : 0;
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
MAX77620_ONOFFCNFG1_SLPEN,
config); if (ret < 0) {
dev_err(dev, "Failed to configure sleep in suspend: %d\n", ret); return ret;
}
if (chip->chip_id == MAX77663) goto out;
/* Disable WK_EN0 */
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_WK_EN0, 0); if (ret < 0) {
dev_err(dev, "Failed to configure WK_EN in suspend: %d\n", ret); return ret;
}
out:
disable_irq(client->irq);
return 0;
}
staticint max77620_i2c_resume(struct device *dev)
{ struct max77620_chip *chip = dev_get_drvdata(dev); struct i2c_client *client = to_i2c_client(dev); int ret; int fps;
for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) { if (chip->shutdown_fps_period[fps] < 0) continue;
ret = max77620_set_fps_period(chip, fps,
chip->shutdown_fps_period[fps]); if (ret < 0) return ret;
}
/* * For MAX20024: No need to configure WKEN0 on resume as * it is configured on Init.
*/ if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663) goto out;
/* Enable WK_EN0 */
ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
MAX77620_ONOFFCNFG2_WK_EN0,
MAX77620_ONOFFCNFG2_WK_EN0); if (ret < 0) {
dev_err(dev, "Failed to configure WK_EN0 n resume: %d\n", ret); return ret;
}
¤ 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.0.14Bemerkung:
(vorverarbeitet)
¤
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.