static int act8931_ldo_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV, unsigned *selector) { struct act8931 *act8931 = rdev_get_drvdata(dev); int ldo= rdev_get_id(dev) -ACT8931_LDO1; int min_vol = min_uV / 1000, max_vol = max_uV / 1000; const int *vol_map =ldo_voltage_map; u16 val; int ret = 0; if (min_vol < vol_map[VOL_MIN_IDX] || min_vol > vol_map[VOL_MAX_IDX]) return -EINVAL; for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ if (vol_map[val] >= min_vol) break; } if (vol_map[val] > max_vol) return -EINVAL; ret = act8931_set_bits(act8931, act8931_LDO_SET_VOL_REG(ldo), LDO_VOL_MASK, val); return ret; }
static int act8931_dcdc_enable(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) -ACT8931_DCDC1 ; u16 mask=0x80; return act8931_set_bits(act8931, act8931_BUCK_CONTR_REG(buck), mask, 0x80); }
static int act8931_ldo_disable(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) - ACT8931_LDO1; u16 mask = 0x80; return act8931_set_bits(act8931, act8931_LDO_CONTR_REG(ldo), mask, 0); }
static int act8931_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) { struct act8931 *act8931 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) -ACT8931_DCDC1 ; u16 mask = 0x20; switch(mode) { case REGULATOR_MODE_STANDBY: return act8931_set_bits(act8931, act8931_BUCK_CONTR_REG(buck), mask, 0); case REGULATOR_MODE_NORMAL: return act8931_set_bits(act8931, act8931_BUCK_CONTR_REG(buck), mask, mask); default: printk("error:pmu_act8931 only powersave and pwm mode\n"); return -EINVAL; } }
static int act8931_ldo_set_mode(struct regulator_dev *dev, unsigned int mode) { struct act8931 *act8931 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) -ACT8931_LDO1 ; u16 mask = 0x20; switch(mode) { case REGULATOR_MODE_NORMAL: return act8931_set_bits(act8931, act8931_LDO_CONTR_REG(ldo), mask, 0); case REGULATOR_MODE_STANDBY: return act8931_set_bits(act8931, act8931_LDO_CONTR_REG(ldo), mask, mask); default: printk("error:pmu_act8931 only lowpower and nomal mode\n"); return -EINVAL; } }
int act8931_device_shutdown(void) { int ret; int err = -1; struct act8931 *act8931 = g_act8931; printk("%s\n",__func__); ret = act8931_reg_read(act8931,0x01); ret = act8931_set_bits(act8931, 0x01,(0x1<<5) |(0x3<<0),(0x1<<5) | (0x3<<0)); if (ret < 0) { printk("act8931 set 0x00 error!\n"); return err; } return 0; }
void act8931_device_shutdown(void) { int ret; struct act8931 *act8931 = g_act8931; pr_info("%s\n", __func__); ret = act8931_reg_read(act8931, 0x01); ret = act8931_set_bits(act8931, 0x01, (0x1<<5) | (0x3<<0), (0x1<<5) | (0x3<<0)); if (ret < 0) pr_err("act8931 set 0x01 error!\n"); mdelay(100); arm_pm_restart('h', "charge"); }
static irqreturn_t act8931_irq_thread(int irq, void *dev_id) { struct act8931 *act8931 = (struct act8931 *)dev_id; int ret; u8 val; val = act8931_reg_read(act8931, 0x78); act8931_charge_det = (val & INDAT_MASK) ? 1 : 0; act8931_charge_ok = (val & CHGDAT_MASK) ? 1 : 0; DBG(charge_det ? "connect!" : "disconnect!"); DBG(charge_ok ? "charge ok!\n" : "charging or discharge!\n"); /* reset related regs according to spec */ ret = act8931_set_bits(act8931, 0x78, INSTAT_MASK | CHGSTAT_MASK, INSTAT_MASK | CHGSTAT_MASK); if (ret < 0) pr_err("act8931 set 0x78 error!\n"); return IRQ_HANDLED; }
static irqreturn_t act8931_irq_thread(unsigned int irq, void *dev_id) { struct act8931 *act8931 = (struct act8931 *)dev_id; int ret; u8 val; val = act8931_reg_read(act8931,0x78); act8931_charge_det = (val & INDAT_MASK )? 1:0; act8931_charge_ok = (val & CHGDAT_MASK )? 1:0; DBG("usb is=%s\n",act8931_charge_det? "connect! " : "disconnect "); DBG("usb =%s\n",act8931_charge_ok? "charge ok! \n" : "charging or discharge! \n"); /* reset related regs according to spec */ ret = act8931_set_bits(act8931, 0x78, INSTAT_MASK | CHGSTAT_MASK, INSTAT_MASK | CHGSTAT_MASK); if (ret < 0) { printk("act8931 set 0x78 error!\n"); } /* FIXME: it's better that waking up screen in battery driver */ rk28_send_wakeup_key(); return IRQ_HANDLED; }
static int __devinit act8931_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct act8931 *act8931; struct act8931_platform_data *pdata = i2c->dev.platform_data; int ret; u8 val; act8931 = kzalloc(sizeof(struct act8931), GFP_KERNEL); if (act8931 == NULL) { ret = -ENOMEM; goto err; } act8931->i2c = i2c; act8931->dev = &i2c->dev; i2c_set_clientdata(i2c, act8931); mutex_init(&act8931->io_lock); ret = act8931_reg_read(act8931,0x22); if ((ret < 0) || (ret == 0xff)){ printk("The device is not act8931 \n"); return 0; } if (pdata) { ret = setup_regulators(act8931, pdata); if (ret < 0) goto err; } else dev_warn(act8931->dev, "No platform init data supplied\n"); ret = act8931_reg_read(act8931,0x01); if (ret < 0) goto err; ret = act8931_set_bits(act8931, 0x01,(0x1<<5) | (0x1<<0),(0x1<<0)); if (ret < 0) { printk("act8931 set 0x01 error!\n"); goto err; } g_act8931 = act8931; pdata->set_init(act8931); /* Initialize charge status */ val = act8931_reg_read(act8931,0x78); act8931_charge_det = (val & INDAT_MASK )? 1:0; act8931_charge_ok = (val & CHGDAT_MASK )? 1:0; DBG("usb is=%s\n",act8931_charge_det? "connect! " : "disconnect "); DBG("usb =%s\n",act8931_charge_ok? "charge ok! \n" : "charging or discharge! \n"); #if 0 ret = act8931_set_bits(act8931, 0x78, INSTAT_MASK | CHGSTAT_MASK, INSTAT_MASK | CHGSTAT_MASK); if (ret < 0) { printk("act8931 set 0x78 error!\n"); goto err; } ret = act8931_set_bits(act8931, 0x79, INCON_MASK | CHGEOCIN_MASK | INDIS_MASK | CHGEOCOUT_MASK, INCON_MASK | CHGEOCIN_MASK | INDIS_MASK | CHGEOCOUT_MASK); if (ret < 0) { printk("act8931 set 0x79 error!\n"); goto err; } ret = gpio_request(i2c->irq, "act8931 gpio"); if(ret) { printk("act8931 gpio request fail\n"); gpio_free(i2c->irq); goto err; } act8931->irq = gpio_to_irq(i2c->irq); gpio_pull_updown(i2c->irq,GPIOPullUp); ret = request_threaded_irq(act8931->irq, NULL, act8931_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, i2c->dev.driver->name, act8931); if (ret < 0) { printk("request act8931 irq fail\n"); goto err; } enable_irq_wake(act8931->irq); #endif #if defined(CONFIG_REGULATOR_ACT8931_BATLOW) batlow_irq_config(0); #endif #if defined(CONFIG_REGULATOR_ACT8931_CHARGE) act8931_charge_init(); #endif return 0; err: return ret; }
static int act8931_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { const struct of_device_id *match; struct act8931 *act8931; struct act8931_board *pdata; struct regulator_init_data *reg_data; struct regulator_config config = { }; const char *rail_name = NULL; struct regulator_dev *rdev; u8 val; int i, ret; pr_info("%s,line=%d\n", __func__, __LINE__); if (i2c->dev.of_node) { match = of_match_device(act8931_of_match, &i2c->dev); if (!match) { pr_err("Failed to find matching dt id\n"); return -EINVAL; } } act8931 = devm_kzalloc(&i2c->dev, sizeof(struct act8931), GFP_KERNEL); if (act8931 == NULL) { ret = -ENOMEM; goto err; } act8931->i2c = i2c; act8931->dev = &i2c->dev; g_act8931 = act8931; mutex_init(&act8931->io_lock); ret = act8931_reg_read(act8931, 0x22); if ((ret < 0) || (ret == 0xff)) { pr_err("The device is not act8931\n"); return 0; } if (act8931->dev->of_node) pdata = act8931_parse_dt(act8931); ret = act8931_reg_read(act8931, 0x01); if (ret < 0) goto err; ret = act8931_set_bits(act8931, 0x01, (0x1<<5) | (0x1<<0), (0x1<<0)); if (ret < 0) { pr_err("act8931 set 0x01 error!\n"); goto err; } /* Initialize charge status */ val = act8931_reg_read(act8931, 0x78); act8931_charge_det = (val & INDAT_MASK) ? 1 : 0; act8931_charge_ok = (val & CHGDAT_MASK) ? 1 : 0; DBG(charge_det ? "connect!" : "disconnect!"); DBG(charge_ok ? "charge ok!\n" : "charging or discharge!\n"); ret = act8931_set_bits(act8931, 0x78, INSTAT_MASK | CHGSTAT_MASK, INSTAT_MASK | CHGSTAT_MASK); if (ret < 0) { pr_err("act8931 set 0x78 error!\n"); goto err; } ret = act8931_set_bits(act8931, 0x79, INCON_MASK | CHGEOCIN_MASK | INDIS_MASK | CHGEOCOUT_MASK, INCON_MASK | CHGEOCIN_MASK | INDIS_MASK | CHGEOCOUT_MASK); if (ret < 0) { pr_err("act8931 set 0x79 error!\n"); goto err; } if (pdata) { act8931->num_regulators = ACT8931_NUM_REGULATORS; act8931->rdev = kcalloc(ACT8931_NUM_REGULATORS, sizeof(struct regulator_dev *), GFP_KERNEL); if (!act8931->rdev) return -ENOMEM; /* Instantiate the regulators */ for (i = 0; i < ACT8931_NUM_REGULATORS; i++) { reg_data = pdata->act8931_init_data[i]; if (!reg_data) continue; if (reg_data->constraints.name) rail_name = reg_data->constraints.name; else rail_name = regulators[i].name; reg_data->supply_regulator = rail_name; config.dev = act8931->dev; config.driver_data = act8931; if (act8931->dev->of_node) config.of_node = pdata->of_node[i]; config.init_data = reg_data; rdev = regulator_register(®ulators[i], &config); if (IS_ERR(rdev)) { pr_err("failed to register %d regulator\n", i); continue; } act8931->rdev[i] = rdev; } } if (pdata->pm_off && !pm_power_off) pm_power_off = act8931_device_shutdown; act8931->pwr_hold_gpio = pdata->pwr_hold_gpio; if (act8931->pwr_hold_gpio) { ret = gpio_request(act8931->pwr_hold_gpio, "act8931 pmic_hold"); if (ret < 0) { pr_err("Failed to request gpio %d with ret %d\n", act8931->pwr_hold_gpio, ret); goto err; } gpio_direction_output(act8931->pwr_hold_gpio, 1); ret = gpio_get_value(act8931->pwr_hold_gpio); pr_info("%s: act8931_pmic_hold=%x\n", __func__, ret); } ret = gpio_request(pdata->irq_gpio, "act8931 irq"); if (ret) { pr_err("act8931 irq_gpio request fail\n"); gpio_free(pdata->irq_gpio); goto err; } gpio_direction_input(pdata->irq_gpio); act8931->irq = gpio_to_irq(pdata->irq_gpio); ret = request_threaded_irq(act8931->irq, NULL, act8931_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, i2c->dev.driver->name, act8931); if (ret < 0) { pr_err("request act8931 irq fail\n"); goto err; } enable_irq_wake(act8931->irq); i2c_set_clientdata(i2c, act8931); return 0; err: return ret; }