static int act8931_ldo_get_voltage(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int ldo= rdev_get_id(dev) -ACT8931_LDO1; u16 reg = 0; int val; reg = act8931_reg_read(act8931,act8931_LDO_SET_VOL_REG(ldo)); reg &= LDO_VOL_MASK; val = 1000 * ldo_voltage_map[reg]; return val; }
static int act8931_dcdc_get_voltage(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) -ACT8931_DCDC1 ; u16 reg = 0; int val; reg = act8931_reg_read(act8931,act8931_BUCK_SET_VOL_REG(buck)); reg &= BUCK_VOL_MASK; DBG("%d\n", reg); val = 1000 * buck_voltage_map[reg]; DBG("%d\n", val); return val; }
static unsigned int act8931_dcdc_get_mode(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) -ACT8931_DCDC1 ; u16 mask = 0xcf; u16 val; val = act8931_reg_read(act8931, act8931_BUCK_CONTR_REG(buck)); val=val|mask; if (val== mask) return REGULATOR_MODE_STANDBY; else return REGULATOR_MODE_NORMAL; }
static unsigned int act8931_ldo_get_mode(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) -ACT8931_LDO1 ; u16 mask = 0xcf; u16 val; val = act8931_reg_read(act8931, act8931_LDO_CONTR_REG(ldo)); val=val|mask; if (val== mask) return REGULATOR_MODE_NORMAL; else return REGULATOR_MODE_STANDBY; }
static int act8931_dcdc_is_enabled(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) -ACT8931_DCDC1; u16 val; u16 mask=0x80; val = act8931_reg_read(act8931, act8931_BUCK_CONTR_REG(buck)); if (val < 0) return val; val=val&~0x7f; if (val & mask) return 1; else return 0; }
static int act8931_ldo_is_enabled(struct regulator_dev *dev) { struct act8931 *act8931 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) -ACT8931_LDO1; u16 val; u16 mask=0x80; val = act8931_reg_read(act8931, act8931_LDO_CONTR_REG(ldo)); if (val < 0) return val; val=val&~0x7f; if (val & mask) return 1; else return 0; }
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 pmu_show(struct seq_file *s, void *unused) { struct act8931 *act8931 = g_act8931; seq_printf(s, "\n"); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_SYS_0, act8931_reg_read(act8931, ACT_SYS_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_SYS_1, act8931_reg_read(act8931, ACT_SYS_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG1_0, act8931_reg_read(act8931, ACT_REG1_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG1_1, act8931_reg_read(act8931, ACT_REG1_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG1_2, act8931_reg_read(act8931, ACT_REG1_2)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG2_0, act8931_reg_read(act8931, ACT_REG2_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG2_1, act8931_reg_read(act8931, ACT_REG2_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG2_2, act8931_reg_read(act8931, ACT_REG2_2)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG3_0, act8931_reg_read(act8931, ACT_REG3_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG3_1, act8931_reg_read(act8931, ACT_REG3_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG3_2, act8931_reg_read(act8931, ACT_REG3_2)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG4_0, act8931_reg_read(act8931, ACT_REG4_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG4_1, act8931_reg_read(act8931, ACT_REG4_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG5_0, act8931_reg_read(act8931, ACT_REG5_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG5_1, act8931_reg_read(act8931, ACT_REG5_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG6_0, act8931_reg_read(act8931, ACT_REG6_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG7_0, act8931_reg_read(act8931, ACT_REG7_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_REG7_1, act8931_reg_read(act8931, ACT_REG7_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_APCH_0, act8931_reg_read(act8931, ACT_APCH_0)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_APCH_1, act8931_reg_read(act8931, ACT_APCH_1)); seq_printf(s, "reg=0x%02x, value=0x%02x\n", ACT_APCH_2, act8931_reg_read(act8931, ACT_APCH_2)); return 0; }
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; }
/* 0000 2.3 0001 2.4 0010 2.5 0011 2.6 0100 2.7 0101 2.8 0110 2.9 0111 3.0 1000 3.1 1001 3.2 1010 3.3 1011 3.4 1100 3.5 1101 3.6 1110 3.7 1111 3.8 */ static int act8931_sys_read(void) { return act8931_reg_read(g_act8931, ACT_SYS_0); }
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; }