static irqreturn_t max8998_int_work_func(int irq, void *max8998_chg) { int ret; u8 data = 0; struct chg_data *chg; struct i2c_client *i2c; chg = max8998_chg; i2c = chg->iodev->i2c; ret = max8998_read_reg(i2c, MAX8998_REG_IRQ1, &data); if (ret < 0) goto err; ret = max8998_read_reg(i2c, MAX8998_REG_IRQ3, &data); if (ret < 0) goto err; if ((data & 0x4) || (ret != 0)) { pr_info("%s : pmic battery full interrupt\n", __func__); chg->set_batt_full = 1; chg->bat_info.batt_is_full = true; } wake_lock(&chg->work_wake_lock); queue_work(chg->monitor_wqueue, &chg->bat_work); return IRQ_HANDLED; err: pr_err("%s : pmic read error\n", __func__); return IRQ_HANDLED; }
static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct max8998_rtc_info *info = dev_get_drvdata(dev); u8 data[8]; u8 val; int ret; ret = max8998_bulk_read(info->rtc, MAX8998_ALARM0_SEC, 8, data); if (ret < 0) return ret; max8998_data_to_tm(data, &alrm->time); ret = max8998_read_reg(info->rtc, MAX8998_ALARM0_CONF, &val); if (ret < 0) return ret; alrm->enabled = !!val; ret = max8998_read_reg(info->rtc, MAX8998_RTC_STATUS, &val); if (ret < 0) return ret; if (val & ALARM0_STATUS) alrm->pending = 1; else alrm->pending = 0; return 0; }
static irqreturn_t max8998_int_work_func(int irq, void *max8998_chg) { int ret; u8 data = 0; struct chg_data *chg; chg = max8998_chg; ret = max8998_read_reg(chg->iodev, MAX8998_REG_IRQ1, &data); if (ret < 0) goto err; ret = max8998_read_reg(chg->iodev, MAX8998_REG_IRQ3, &data); if (ret < 0) goto err; if ((data & 0x4) || (ret != 0)) { pr_info("%s : pmic interrupt\n", __func__); chg->set_batt_full = 1; chg->bat_info.batt_is_full = true; if (chg->bat_info.batt_soc > 0) { chg->bat_info.batt_max_soc = chg->bat_info.batt_soc; pr_info("%s : batt_max_soc=%d\n", __func__, chg->bat_info.batt_max_soc); } } wake_lock(&chg->work_wake_lock); queue_work(chg->monitor_wqueue, &chg->bat_work); return IRQ_HANDLED; err: pr_err("%s : pmic read error\n", __func__); return IRQ_HANDLED; }
int max8998_ldo_is_enabled_direct(int ldo) { struct max8998_data *max8998 = client_data_p; int value, shift; if((ldo < MAX8998_LDO1) || (ldo > MAX8998_DCDC4)) { printk("ERROR: Invalid argument passed\n"); return -EINVAL; } DBG("func =%s called for regulator = %d\n",__func__,ldo); if (ldo <= MAX8998_LDO5) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); shift = 5 - ldo; } else if (ldo <= MAX8998_LDO13) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF2); shift = 13 - ldo; } else if (ldo <= MAX8998_LDO17) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF3); shift = 21 - ldo; } else { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); shift = 7 - (ldo - MAX8998_DCDC1); } return (value >> shift) & 0x1; }
/* Save registers before hibernation */ static int max8998_freeze(struct device *dev) { struct i2c_client *i2c = to_i2c_client(dev); int i; for (i = 0; i < ARRAY_SIZE(max8998_dump); i++) max8998_read_reg(i2c, max8998_dump[i].addr, &max8998_dump[i].val); return 0; }
static int max8998_check_charger(struct max8998_power_info *info) { int ret; u8 val; ret = max8998_read_reg(info->i2c, MAX8998_REG_STATUS2, &val); if (ret >= 0) { /* * If battery detection is enabled, ID pin of battery is * connected to MBDET pin of MAX8998. It could be used to * detect battery presence. * Otherwise, we have to assume that battery is always on. */ if (info->batt_detect) info->bat_online = (val & MAX8998_REG_STATUS2_BDET_MASK) ? 0 : 1; else info->bat_online = 1; if (val & MAX8998_REG_STATUS2_VCHGIN_MASK) { info->ac_online = 1; info->usb_online = 1; wake_lock(&info->vbus_wake_lock); } else { info->ac_online = 0; info->usb_online = 0; wake_lock_timeout(&info->vbus_wake_lock, HZ / 2); } } #if 0 if (enable) { /* enable charger in platform */ if (info->set_charger) info->set_charger(1); /* enable charger */ max8998_set_bits(info->i2c, MAX8998_CHG_CNTL1, 1 << 7, 0); } else { /* disable charge */ max8998_set_bits(info->i2c, MAX8998_CHG_CNTL1, 1 << 7, 1 << 7); if (info->set_charger) info->set_charger(0); } dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger" : "Disable charger"); #endif power_supply_changed(&max8998_power_supplies[0]); power_supply_changed(&max8998_power_supplies[1]); power_supply_changed(&max8998_power_supplies[2]); return 0; }
int max8998_ldo_disable_direct(int ldo) { struct max8998_data *max8998 = client_data_p; int value, shift; if((ldo < MAX8998_LDO1) || (ldo > MAX8998_DCDC4)) { printk("ERROR: Invalid argument passed\n"); return -EINVAL; } DBG("func =%s called for regulator = %d\n",__func__,ldo); spin_lock(&pmic_access_lock); if (ldo <= MAX8998_LDO5) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); shift = 5 - ldo; value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF1); } else if (ldo <= MAX8998_LDO13) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF2); shift = 13 - ldo; value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF2); } else if (ldo <= MAX8998_LDO17) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF3); shift = 21 - ldo; value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF3); } else { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); shift = 7 - (ldo - MAX8998_DCDC1); value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF1); } spin_unlock(&pmic_access_lock); return 0; }
static int max8998_ldo_is_enabled(struct regulator_dev *rdev) { struct max8998_data *max8998 = rdev_get_drvdata(rdev); int ldo = max8998_get_ldo(rdev); int value, shift; if (ldo <= MAX8998_LDO5) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); //shift = 6 - ldo; shift = 5 - ldo; } else if (ldo <= MAX8998_LDO13) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF2); shift = 13 - ldo; } else if (ldo <= MAX8998_LDO17) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF3); shift = 21 - ldo; } else { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); shift = 7 - (ldo - MAX8998_DCDC1); } return (value >> shift) & 0x1; }
static bool max8998_check_vdcin(struct chg_data *chg) { u8 data = 0; int ret; ret = max8998_read_reg(chg->iodev->i2c, MAX8998_REG_STATUS2, &data); if (ret < 0) { pr_err("max8998_read_reg error\n"); return ret; } return data & MAX8998_MASK_VDCIN; }
static int max8998_ldo_disable(struct regulator_dev *rdev) { struct max8998_data *max8998 = rdev_get_drvdata(rdev); int ldo = max8998_get_ldo(rdev); int value, shift; DBG("func =%s called for regulator = %d\n",__func__,ldo); spin_lock(&pmic_access_lock); if (ldo <= MAX8998_LDO5) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); //shift = 6 - ldo; shift = 5 - ldo; value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF1); } else if (ldo <= MAX8998_LDO13) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF2); shift = 13 - ldo; value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF2); } else if (ldo <= MAX8998_LDO17) { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF3); shift = 21 - ldo; value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF3); } else { value = max8998_read_reg(max8998, MAX8998_REG_ONOFF1); shift = 7 - (ldo - MAX8998_DCDC1); value &= ~(1 << shift); max8998_write_reg(max8998, value, MAX8998_REG_ONOFF1); } spin_unlock(&pmic_access_lock); return 0; }
static int max8998_check_vdcin(struct chg_data *chg) { struct i2c_client *i2c = chg->iodev->i2c; u8 data = 0; int ret; ret = max8998_read_reg(i2c, MAX8998_REG_STATUS2, &data); if (ret < 0) { pr_err("max8998_read_reg error\n"); return ret; } return (data & MAX8998_MASK_VDCIN) ? 1 : 0; }
static int max8998_check_vdcin(void) { struct max8998_chg_data *chg = max8998_chg; u8 data = 0; int ret; ret = max8998_read_reg(chg->iodev, MAX8998_REG_STATUS2, &data); if (ret < 0) { pr_err("max8998_read_reg error\n"); return ret; } return data & MAX8998_MASK_VDCIN; }
static int max8998_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct max8998_platform_data *pdata = i2c->dev.platform_data; struct max8998_dev *max8998; int ret = 0; u8 val; max8998 = kzalloc(sizeof(struct max8998_dev), GFP_KERNEL); if (max8998 == NULL) return -ENOMEM; i2c_set_clientdata(i2c, max8998); max8998->dev = &i2c->dev; max8998->i2c_client = i2c; max8998->irq = i2c->irq; if (pdata) { max8998->ono = pdata->ono; max8998->irq_base = pdata->irq_base; } max8998->dev_read = max8998_i2c_device_read; max8998->dev_write = max8998_i2c_device_write; max8998->dev_update = max8998_i2c_device_update; mutex_init(&max8998->iolock); max8998_irq_init(max8998); max8998_read_reg(max8998, MAX8998_REG_ONOFF1, &val); val &= ~(MAX8998_MASK_EN1|MAX8998_MASK_EN2|MAX8998_MASK_EN4); max8998_write_reg(max8998, MAX8998_REG_ONOFF1, val); ret = mfd_add_devices(max8998->dev, -1, max8998_devs, ARRAY_SIZE(max8998_devs), NULL, 0); if (ret < 0) goto err; return ret; err: mfd_remove_devices(max8998->dev); kfree(max8998); return ret; }
int max8998_ldo_set_voltage_direct(int ldo, int min_uV, int max_uV) { struct max8998_data *max8998 = client_data_p; int value, shift = 0, mask = 0xff, reg; int min_vol = min_uV / 1000, max_vol = max_uV / 1000; int i = 0; const int *vol_map = NULL; if((ldo < MAX8998_LDO1) || (ldo > MAX8998_DCDC4)) { printk("ERROR: Invalid argument passed\n"); return -EINVAL; } vol_map = ldo_voltage_map[ldo]; DBG("func =%s called for regulator = %d, min_v=%d, max_v=%d\n",__func__,ldo,min_uV,max_uV); if (min_vol < 750 || max_vol > 3600) return -EINVAL; while (vol_map[i]) { if (vol_map[i] >= min_vol) break; i++; } DBG("Found voltage=%d\n",vol_map[i]); if (!vol_map[i]) return -EINVAL; if (vol_map[i] > max_vol) return -EINVAL; if (ldo == MAX8998_LDO3) { reg = MAX8998_REG_LDO23; mask = 0x0F; } else if (ldo == MAX8998_LDO2) { reg = MAX8998_REG_LDO23; shift = 4; mask = 0x0F; } else if (ldo == MAX8998_LDO8) { reg = MAX8998_REG_LDO89; shift = 4; mask = 0x07; } else if (ldo == MAX8998_LDO9) { reg = MAX8998_REG_LDO89; shift = 2; mask = 0x03; } else if (ldo == MAX8998_LDO10) { reg = MAX8998_REG_LDO1011; shift = 5; mask = 0x07; } else if (ldo == MAX8998_LDO11) { reg = MAX8998_REG_LDO1011; mask = 0x1F; } else if (ldo == MAX8998_LDO12) { reg = MAX8998_REG_LDO12; mask = 0xFF; } else if (ldo == MAX8998_LDO13) { reg = MAX8998_REG_LDO13; mask = 0xFF; } else if (ldo == MAX8998_LDO14) { reg = MAX8998_REG_LDO14; mask = 0xFF; } else if (ldo == MAX8998_LDO15) { reg = MAX8998_REG_LDO15; mask = 0xFF; } else if (ldo == MAX8998_LDO16) { reg = MAX8998_REG_LDO16; mask = 0xFF; } else if (ldo == MAX8998_LDO17) { reg = MAX8998_REG_LDO17; mask = 0xFF; } else if (ldo == MAX8998_DCDC1) { //reg = 0x04; reg = MAX8998_REG_DVSARM1; mask = 0x1f; } else if (ldo == MAX8998_DCDC2) { //reg = 0x06; reg = MAX8998_REG_DVSINT1; mask = 0x1f; } else if (ldo == MAX8998_DCDC3) { reg = MAX8998_REG_BUCK3; mask = 0xff; } else if (ldo == MAX8998_DCDC4) { reg = MAX8998_REG_BUCK4; mask = 0xff; } else {// for ldo4,5,6,7 reg = MAX8998_REG_LDO23 + (ldo - MAX8998_LDO3); mask = 0xff; } spin_lock(&pmic_access_lock); value = max8998_read_reg(max8998, reg); value &= ~(mask << shift); value |= (i << shift); max8998_write_reg(max8998, value, reg); spin_unlock(&pmic_access_lock); return 0; }
static int max8998_ldo_get_voltage(struct regulator_dev *rdev) { struct max8998_data *max8998 = rdev_get_drvdata(rdev); int ldo = max8998_get_ldo(rdev); int value, shift = 0, mask = 0xff, reg; DBG("func =%s called for regulator = %d\n",__func__,ldo); if (ldo == MAX8998_LDO3) { reg = MAX8998_REG_LDO23; mask = 0x0F; } else if (ldo == MAX8998_LDO2) { reg = MAX8998_REG_LDO23; shift = 4; mask = 0x0F; } else if (ldo == MAX8998_LDO8) { reg = MAX8998_REG_LDO89; shift = 4; mask = 0x07; } else if (ldo == MAX8998_LDO9) { reg = MAX8998_REG_LDO89; shift = 2; mask = 0x03; } else if (ldo == MAX8998_LDO10) { reg = MAX8998_REG_LDO1011; shift = 5; mask = 0x07; } else if (ldo == MAX8998_LDO11) { reg = MAX8998_REG_LDO1011; mask = 0x1F; } else if (ldo == MAX8998_LDO12) { reg = MAX8998_REG_LDO12; } else if (ldo == MAX8998_LDO13) { reg = MAX8998_REG_LDO13; } else if (ldo == MAX8998_LDO14) { reg = MAX8998_REG_LDO14; } else if (ldo == MAX8998_LDO15) { reg = MAX8998_REG_LDO15; } else if (ldo == MAX8998_LDO16) { reg = MAX8998_REG_LDO16; } else if (ldo == MAX8998_LDO17) { reg = MAX8998_REG_LDO17; } else if (ldo == MAX8998_DCDC1) { //reg = 0x04; reg = MAX8998_REG_DVSARM1; mask = 0x1f; } else if (ldo == MAX8998_DCDC2) { //reg = 0x06; reg = MAX8998_REG_DVSINT1; mask = 0x1f; } else if (ldo == MAX8998_DCDC3) { reg = MAX8998_REG_BUCK3; mask = 0xFF; } else if (ldo == MAX8998_DCDC4) { reg = MAX8998_REG_BUCK4; mask = 0xff; } else {// for ldo4,5,6,7 reg = MAX8998_REG_LDO23 + (ldo - MAX8998_LDO3); mask = 0xff; } value = max8998_read_reg(max8998, reg); value >>= shift; value &= mask; return 1000 * ldo_voltage_map[ldo][value]; }