Beispiel #1
0
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;

}
Beispiel #2
0
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);
}
Beispiel #4
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;
	}


}
Beispiel #5
0
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;
	}


}
Beispiel #6
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;
}
Beispiel #9
0
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;
}
Beispiel #10
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;	

}
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(&regulators[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;
}