Example #1
0
int da9052_read_tjunc(struct da9052 *da9052, char *buf)
{
	struct da9052_ssc_msg msg;
	unsigned char temp;
	int ret;

	msg.addr = DA9052_TJUNCRES_REG;
	msg.data = 0;

	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;

	temp = msg.data;

	msg.addr = DA9052_TOFFSET_REG;
	msg.data = 0;
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);
	/* Calculate Junction temperature */
	temp = (temp - msg.data);
	*buf = temp;
	return 0;
err_ssc_comm:
	da9052_unlock(da9052);
	return -EIO;
}
Example #2
0
static void da9052_onkey_work_func(struct work_struct *work)
{
	struct da9052_onkey_data *da9052_onkey =
		container_of(work, struct da9052_onkey_data, polling_work.work);
	struct da9052_ssc_msg msg;
	unsigned int ret;
	int value;

	da9052_lock(da9052_onkey->da9052);
	msg.addr = DA9052_STATUSA_REG;
	ret = da9052_onkey->da9052->read(da9052_onkey->da9052, &msg);
	if (ret) {
		da9052_unlock(da9052_onkey->da9052);
		return;
	}
	da9052_unlock(da9052_onkey->da9052);
	value = (msg.data & DA9052_STATUSA_NONKEY) ? 0 : 1;

	input_report_key(da9052_onkey->input, KEY_POWER, value);
	input_sync(da9052_onkey->input);

#ifdef CONFIG_CCIMX5X_PM_POWER_BUTTON
	da9052_power_button( da9052_onkey->da9052 , value );
#endif

	/* if key down, polling for up */
	if (value)
		schedule_delayed_work(&da9052_onkey->polling_work, HZ/10);
}
Example #3
0
static int da9052_stop_adc(struct da9052 *da9052, unsigned channel)
{
	int ret;
	struct da9052_ssc_msg msg;

	msg.addr = DA9052_ADCCONT_REG;
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;

	if (channel == DA9052_ADC_VDDOUT)
		msg.data = (msg.data & ~(DA9052_ADCCONT_AUTOVDDEN));
	else if (channel == DA9052_ADC_ADCIN4)
		msg.data = (msg.data & ~(DA9052_ADCCONT_AUTOAD4EN));
	else if (channel == DA9052_ADC_ADCIN5)
		msg.data = (msg.data & ~(DA9052_ADCCONT_AUTOAD5EN));
	else if (channel == DA9052_ADC_ADCIN6)
		msg.data =  (msg.data & ~(DA9052_ADCCONT_AUTOAD6EN));
	else
		return -EINVAL;

	ret = da9052->write(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;
	da9052_unlock(da9052);

	return 0;
err_ssc_comm:
	da9052_unlock(da9052);
	return -EIO;
}
int da9052_ldo_buck_disable(struct regulator_dev *rdev)
{
	struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
	int id = rdev_get_id(rdev);
	int ret;
	struct da9052_ssc_msg ssc_msg;

	ssc_msg.addr = da9052_regulators[id].reg_add;
	ssc_msg.data = 0;

	da9052_lock(priv->da9052);
	ret = priv->da9052->read(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	ssc_msg.data = (ssc_msg.data & ~(da9052_regulators[id].en_bit_mask));

	ret = priv->da9052->write(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}
	da9052_unlock(priv->da9052);

	return 0;
}
Example #5
0
int da9052_read_tbat_ich(struct da9052 *da9052, char *data, int channel_no)
{
	struct da9052_ssc_msg msg;
	int ret;

	/* Read TBAT conversion result */
	switch (channel_no) {
	case DA9052_ADC_TBAT:
		msg.addr = DA9052_TBATRES_REG;
	break;
	case DA9052_ADC_ICH:
		msg.addr = DA9052_ICHGAV_REG;
	break;
	default:
		return -EINVAL;
	}
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);
	*data = msg.data;
	printk(KERN_INFO"msg.data 1= %d\n", msg.data);
	msg.data = 28;
	da9052_lock(da9052);
	ret = da9052->write(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);
	printk(KERN_INFO"msg.data2 = %d\n", msg.data);
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);
	printk(KERN_INFO"msg.data3 = %d\n", msg.data);
	return 0;

err_ssc_comm:
	da9052_unlock(da9052);
	return ret;
}
static int da9052_set_suspend_voltage(struct regulator_dev *rdev, int uV)
{
	struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
	struct da9052_ssc_msg ssc_msg;
	int id = rdev_get_id(rdev);
	int ret;
	int ldo_volt = 0;


	/* Check Minimum/ Maximum voltage range */
	if (uV < da9052_regulators[id].reg_const.min_uV ||
		uV > da9052_regulators[id].reg_const.max_uV)
		return -EINVAL;

	/* Get the ldo register value */
	/* Varying step size for BUCK PERI */
	if ((da9052_regulators[id].reg_desc.id == DA9052_BUCK_PERI) &&
			(uV >= DA9052_BUCK_PERI_VALUES_3000)) {
		ldo_volt = (DA9052_BUCK_PERI_VALUES_3000 -
			da9052_regulators[id].reg_const.min_uV)/
			(da9052_regulators[id].step_uV);
		ldo_volt += (uV - DA9052_BUCK_PERI_VALUES_3000)/
			(DA9052_BUCK_PERI_STEP_ABOVE_3000);
	} else{
		ldo_volt = (uV - da9052_regulators[id].reg_const.min_uV)/
			(da9052_regulators[id].step_uV);
	}
	ldo_volt |= 0x80;
	dev_info(&rdev->dev, "preset to %d %x\n", uV, ldo_volt);

	/* Configure LDO Voltage, CONF bits */
	ssc_msg.addr = da9052_regulators[id].reg_add;
	ssc_msg.data = 0;

	/* Read register */
	da9052_lock(priv->da9052);
	ret = priv->da9052->read(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	ssc_msg.data = (ssc_msg.data & ~(da9052_regulators[id].mask_bits));
	ssc_msg.data |= ldo_volt;

	ret = priv->da9052->write(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	da9052_unlock(priv->da9052);

	return 0;
}
Example #7
0
static ssize_t da9052_adc_read_start_stop(struct device *dev,
	struct device_attribute *devattr, char *buf)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct da9052_adc_priv *priv = platform_get_drvdata(pdev);
	struct da9052_ssc_msg msg;
	int channel = to_sensor_dev_attr(devattr)->index;
	int ret;

	ret = da9052_start_adc(priv->da9052, channel);
	if (ret < 0)
		return ret;

	/* Read the ADC converted value */
	switch (channel) {
	case DA9052_ADC_VDDOUT:
		msg.addr = DA9052_VDDRES_REG;
	break;
#if (DA9052_ADC_CONF_ADC4 == 1)
	case DA9052_ADC_ADCIN4:
		msg.addr = DA9052_ADCIN4RES_REG;
	break;
#endif
#if (DA9052_ADC_CONF_ADC5 == 1)
	case DA9052_ADC_ADCIN5:
		msg.addr = DA9052_ADCIN5RES_REG;
	break;
#endif
#if (DA9052_ADC_CONF_ADC6 == 1)
	case DA9052_ADC_ADCIN6:
		msg.addr = DA9052_ADCIN6RES_REG;
	break;
#endif
	default:
		return -EINVAL;
	}
	msg.data = 0;
	da9052_lock(priv->da9052);
	ret = priv->da9052->read(priv->da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;
	da9052_unlock(priv->da9052);

	ret = da9052_stop_adc(priv->da9052, channel);
	if (ret < 0)
		return ret;

	return sprintf(buf, "%u\n", msg.data);

err_ssc_comm:
	da9052_unlock(priv->da9052);
	return ret;
}
Example #8
0
static void da9052_power_button( struct da9052 *da9052 , int value )
{
	struct da9052_ssc_msg ssc_msg;
	unsigned int ret;

	if( system_state != SYSTEM_RUNNING)
		return;

	switch (pwron_state){
			case PWRON_FROM_RESUME:
				// Are we waking up from a non power button suspend
				// and this is the falling edge already?
				if( !value )
					pwron_state = PWRON_FROM_RESUME;
				else
					// Skipping falling edge
					pwron_state = PWRON_FALLING_EDGE;
				break;
			case PWRON_FALLING_EDGE:
				// Suspend on rising edge
				pm_suspend(PM_SUSPEND_MEM);
				// Did we wake by a power button press?
				da9052_lock(da9052);
				ssc_msg.addr = DA9052_EVENTB_REG;
				ret = da9052->read(da9052, &ssc_msg);
				if (ret) {
					da9052_unlock(da9052);
					pwron_state = PWRON_FROM_RESUME;
					return;
				}
				da9052_unlock(da9052);
				if( ssc_msg.data | DA9052_EVENTB_ENONKEY )
					pwron_state = PWRON_FROM_SUSPEND;
				else
					// Waken by other source
					pwron_state = PWRON_FROM_RESUME;
				break;
			case PWRON_FROM_SUSPEND:
				// Ignoring raising edge
				pwron_state = PWRON_FROM_RESUME;
				break;
			default:
				pr_err("power_on_evt_handler: Unitialized state\n");
	}
}
int da9052_ldo_buck_get_voltage(struct regulator_dev *rdev)
{
	struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
	struct da9052_ssc_msg ssc_msg;
	int id = rdev_get_id(rdev);
	int ldo_volt = 0;
	int ldo_volt_uV = 0;
	int ret;

	ssc_msg.addr = da9052_regulators[id].reg_add;
	ssc_msg.data = 0;
	/* Read register */
	da9052_lock(priv->da9052);
	ret = priv->da9052->read(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}
	da9052_unlock(priv->da9052);

	ldo_volt = ssc_msg.data & da9052_regulators[id].mask_bits;
	if (da9052_regulators[id].reg_desc.id == DA9052_BUCK_PERI) {
		if (ldo_volt >= DA9052_BUCK_PERI_VALUES_UPTO_3000) {
			ldo_volt_uV = ((DA9052_BUCK_PERI_VALUES_UPTO_3000 *
				da9052_regulators[id].step_uV)
				+ da9052_regulators[id].reg_const.min_uV);
			ldo_volt_uV = (ldo_volt_uV +
				(ldo_volt - DA9052_BUCK_PERI_VALUES_UPTO_3000)
				* (DA9052_BUCK_PERI_STEP_ABOVE_3000));
		} else {
			ldo_volt_uV =
				(ldo_volt * da9052_regulators[id].step_uV)
				+ da9052_regulators[id].reg_const.min_uV;
		}
	} else {
		ldo_volt_uV = (ldo_volt * da9052_regulators[id].step_uV) +
				da9052_regulators[id].reg_const.min_uV;
	}
	return ldo_volt_uV;
}
Example #10
0
static int da9052_backlight_brightness_set(struct da9052_backlight_data *data,
			int brightness, enum da9052_led_number led)
{
	/*
	 * Mechanism for brightness control:
	 * For brightness control, current is used.
	 * PWM feature is not used.
	 * To use PWM feature, a fixed value of current should be defined.
	 */

	int ret = 0;

	unsigned int led_ramp_bit;
	unsigned int led_current_register;
	unsigned int led_current_sink_bit;
	unsigned int led_boost_en_bit;

	struct da9052_ssc_msg msg;

	switch (led) {
	case LED1:
		led_ramp_bit = DA9052_LEDCONT_LED1RAMP;
		led_current_register = DA9052_LED1CONF_REG;
		led_current_sink_bit = DA9052_LEDCONT_LED1EN;
		led_boost_en_bit = DA9052_BOOST_LED1INEN;
	break;
	case LED2:
		led_ramp_bit = DA9052_LEDCONT_LED2RAMP;
		led_current_register = DA9052_LED2CONF_REG;
		led_current_sink_bit = DA9052_LEDCONT_LED2EN;
		led_boost_en_bit = DA9052_BOOST_LED2INEN;
	break;
	case LED3:
		led_ramp_bit = DA9052_LEDCONT_LED3RAMP;
		led_current_register = DA9052_LED3CONF_REG;
		led_current_sink_bit = DA9052_LEDCONT_LED3EN;
		led_boost_en_bit = DA9052_BOOST_LED3INEN;
	break;
	default:
		return -EIO;
	}

	/*
	 * 3 registers to be written
	 * 1. LED current for brightness
	 * 2. LED enable/disable depending on the brightness
	 * 3. BOOST enable/disable depending on the brightness
	 */

	/* Configure LED current i.e. brightness */
	msg.addr = led_current_register;
	msg.data = brightness;
	/* Write to the DA9052 register */
	da9052_lock(data->da9052);
	ret = data->da9052->write(data->da9052, &msg);
	if (ret) {
		da9052_unlock(data->da9052);
		return ret;
	}
	da9052_unlock(data->da9052);

	/*
	 * Check if brightness = 0
	 * and decide if led to be disabled
	 */
	msg.addr = DA9052_LEDCONT_REG;
	msg.data = 0;

	/* Read LED_CONT register */
	da9052_lock(data->da9052);
	ret = data->da9052->read(data->da9052, &msg);
	if (ret) {
		da9052_unlock(data->da9052);
		return ret;
	}
	da9052_unlock(data->da9052);

	/* Set/Clear the LED current sink bit */
	msg.data = brightness ? (msg.data | led_current_sink_bit) :
			(msg.data & ~(led_current_sink_bit));
	/* Disable current ramping */
	msg.data = (msg.data & ~(led_ramp_bit));

	/* Write to the DA9052 register */
	da9052_lock(data->da9052);
	ret = data->da9052->write(data->da9052, &msg);
	if (ret) {
		da9052_unlock(data->da9052);
		return ret;
	}
	da9052_unlock(data->da9052);

	/* Configure BOOST */
	msg.addr = DA9052_BOOST_REG;
	msg.data = 0;

	/* Read LED_CONT register */
	da9052_lock(data->da9052);
	ret = data->da9052->read(data->da9052, &msg);
	if (ret) {
		da9052_unlock(data->da9052);
		return ret;
	}
	da9052_unlock(data->da9052);

	/* Set/Clear the LED BOOST enable bit */
	msg.data = brightness ? (msg.data | led_boost_en_bit) :
			(msg.data & ~(led_boost_en_bit));
	/* Set/Clear the BOOST converter enable bit */

	if (0 == (data->is_led1_present | data->is_led2_present |
			data->is_led3_present)) {
		msg.data = msg.data & ~(DA9052_BOOST_BOOSTEN);
	} else
			msg.data = (msg.data | DA9052_BOOST_BOOSTEN);

	/* Write to the DA9052 register */
	da9052_lock(data->da9052);
	ret = data->da9052->write(data->da9052, &msg);
	if (ret) {
		da9052_unlock(data->da9052);
		return ret;
	}
	da9052_unlock(data->da9052);

	return 0;
}
Example #11
0
static int __devinit da9052_onkey_probe(struct platform_device *pdev)
{
	struct da9052_onkey_data *da9052_onkey;
	int error,ret;
	struct da9052_ssc_msg msg;

	da9052_onkey = kzalloc(sizeof(*da9052_onkey), GFP_KERNEL);
	da9052_onkey->input = input_allocate_device();
	if (!da9052_onkey->input) {
		dev_err(&pdev->dev, "failed to allocate data device\n");
		error = -ENOMEM;
		goto fail1;
	}
	da9052_onkey->da9052 = dev_get_drvdata(pdev->dev.parent);

	if (!da9052_onkey->input) {
		dev_err(&pdev->dev, "failed to allocate input device\n");
		error = -ENOMEM;
		goto fail2;
	}

	da9052_onkey->input->evbit[0] = BIT_MASK(EV_KEY);
	da9052_onkey->input->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
	da9052_onkey->input->name = "da9052-onkey";
	da9052_onkey->input->phys = "da9052-onkey/input0";
	da9052_onkey->input->dev.parent = &pdev->dev;
	INIT_DELAYED_WORK(&da9052_onkey->polling_work, da9052_onkey_work_func);

	/* Set the EH structure */
	da9052_onkey->eh_data.eve_type = ONKEY_EVE;
	da9052_onkey->eh_data.call_back = &da9052_onkey_report_event;
	error = da9052_onkey->da9052->register_event_notifier(
				da9052_onkey->da9052,
				&da9052_onkey->eh_data);
	if (error)
		goto fail2;

	error = input_register_device(da9052_onkey->input);
	if (error) {
		dev_err(&pdev->dev, "Unable to register input\
				device,error: %d\n", error);
		goto fail3;
	}

	platform_set_drvdata(pdev, da9052_onkey);

	// Unmask IRQ
	da9052_lock(da9052_onkey->da9052);
	msg.addr = DA9052_IRQMASKB_REG;
	ret = da9052_onkey->da9052->read(da9052_onkey->da9052, &msg);
	if (ret) {
		da9052_unlock(da9052_onkey->da9052);
		return 0;
	}
	msg.data &= ~DA9052_IRQMASKB_MNONKEY;
	da9052_onkey->da9052->write(da9052_onkey->da9052, &msg);
	da9052_unlock(da9052_onkey->da9052);
	return 0;

fail3:
	da9052_onkey->da9052->unregister_event_notifier(da9052_onkey->da9052,
					&da9052_onkey->eh_data);
fail2:
	input_free_device(da9052_onkey->input);
fail1:
	kfree(da9052_onkey);
	return error;
}
Example #12
0
int da9052_manual_read(struct da9052 *da9052,
			unsigned char channel)
{
	unsigned char man_timeout_cnt = DA9052_ADC_MAX_MANCONV_RETRY_COUNT;
	struct da9052_ssc_msg msg;
	unsigned short calc_data;
	unsigned int ret;
	u16 data = 0;

	msg.addr = DA9052_ADCMAN_REG;
	msg.data = channel;
	msg.data =  (msg.data | DA9052_ADCMAN_MANCONV);

	mutex_lock(&da9052->manconv_lock);
	da9052_lock(da9052);

	ret = da9052->write(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);

	/* Wait for the event */
	do {
		msg.addr = DA9052_ADCCONT_REG;
		msg.data = 0;
		da9052_lock(da9052);
		ret = da9052->read(da9052, &msg);
		if (ret)
			goto err_ssc_comm;
		da9052_unlock(da9052);

		if (DA9052_ADCCONT_ADCMODE & msg.data)
			msleep(1);
		else
			msleep(10);

		msg.addr = DA9052_ADCMAN_REG;
		msg.data = 0;
		da9052_lock(da9052);
		ret = da9052->read(da9052, &msg);
		if (ret)
			goto err_ssc_comm;
		da9052_unlock(da9052);

		/* Counter to avoid endless while loop */
		man_timeout_cnt--;
		if (man_timeout_cnt == 1) {
			if (!(msg.data & DA9052_ADCMAN_MANCONV))
				break;
			else
				goto err_ssc_comm;
		}
	/* Wait until the MAN_CONV bit is cleared to zero */
	} while (msg.data & DA9052_ADCMAN_MANCONV);

	msg.addr = DA9052_ADCRESH_REG;
	msg.data = 0;

	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);

	calc_data = (unsigned short)msg.data;
	data = (calc_data << 2);

	msg.addr = DA9052_ADCRESL_REG;
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;
	da9052_unlock(da9052);

	/* Clear first 14 bits before ORing */
	calc_data = (unsigned short)msg.data & 0x0003;
	data |= calc_data;

	mutex_unlock(&da9052->manconv_lock);

	return data;
err_ssc_comm:
	mutex_unlock(&da9052->manconv_lock);
	da9052_unlock(da9052);
	return -EIO;
}
Example #13
0
static int da9052_adc_hw_init(struct da9052 *da9052)
{
	struct da9052_ssc_msg msg;
	int ret;

	/* ADC channel 4 and 5 are by default enabled */
#if (DA9052_ADC_CONF_ADC4 == 1)
	msg.addr = DA9052_GPIO0001_REG;
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;

	msg.data = (msg.data & ~(DA9052_GPIO0001_GPIO0PIN));
	ret = da9052->write(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;
	da9052_unlock(da9052);
#endif

#if (DA9052_ADC_CONF_ADC5 == 1)
	msg.addr = DA9052_GPIO0001_REG;
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;

	msg.data = (msg.data & ~(DA9052_GPIO0001_GPIO0PIN));
	ret = da9052->write(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;
	da9052_unlock(da9052);
#endif

#if (DA9052_ADC_CONF_ADC6 == 1)
	msg.addr = DA9052_GPIO0203_REG;
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret)
		goto err_ssc_comm;

	msg.data = (msg.data & ~(DA9052_GPIO0203_GPIO2PIN));
	ret = da9052->write(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;
	da9052_unlock(da9052);
#endif
#if 0
	/* By default configure the Measurement sequence interval to 10ms */
	msg.addr = DA9052_ADCCONT_REG;
	msg.data = 0;
	da9052_lock(da9052);
	ret = da9052->read(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;

	/* Set the ADC MODE bit for 10msec sampling timer */
	msg.data = (msg.data & ~(DA9052_ADCCONT_ADCMODE));
	ret = da9052->write(da9052, &msg);
	if (ret != 0)
		goto err_ssc_comm;
	da9052_unlock(da9052);
#endif
	return 0;
err_ssc_comm:
	da9052_unlock(da9052);
	return -EIO;
}
int da9052_ldo_buck_set_voltage(struct regulator_dev *rdev,
					int min_uV, int max_uV)
{
	struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
	struct da9052_ssc_msg ssc_msg;
	int id = rdev_get_id(rdev);
	int ret;
	int ldo_volt = 0;

	/* KPIT - Below if condition is there for added setvoltage attribute
	in sysfs */
	if (0 == max_uV)
		max_uV = da9052_regulators[id].reg_const.max_uV;

	/* Compare voltage range */
	if (min_uV > max_uV)
		return -EINVAL;

	/* Check Minimum/ Maximum voltage range */
	if (min_uV < da9052_regulators[id].reg_const.min_uV ||
		min_uV > da9052_regulators[id].reg_const.max_uV)
		return -EINVAL;
	if (max_uV < da9052_regulators[id].reg_const.min_uV ||
		max_uV > da9052_regulators[id].reg_const.max_uV)
		return -EINVAL;

	/* Get the ldo register value */
	/* Varying step size for BUCK PERI */
	if ((da9052_regulators[id].reg_desc.id == DA9052_BUCK_PERI) &&
			(min_uV >= DA9052_BUCK_PERI_VALUES_3000)) {
		ldo_volt = (DA9052_BUCK_PERI_VALUES_3000 -
			da9052_regulators[id].reg_const.min_uV)/
			(da9052_regulators[id].step_uV);
		ldo_volt += (min_uV - DA9052_BUCK_PERI_VALUES_3000)/
			(DA9052_BUCK_PERI_STEP_ABOVE_3000);
	} else{
		ldo_volt = (min_uV - da9052_regulators[id].reg_const.min_uV)/
			(da9052_regulators[id].step_uV);
		/* Check for maximum value */
		if ((ldo_volt * da9052_regulators[id].step_uV) +
			da9052_regulators[id].reg_const.min_uV > max_uV)
			return -EINVAL;
	}

	/* Configure LDO Voltage, CONF bits */
	ssc_msg.addr = da9052_regulators[id].reg_add;
	ssc_msg.data = 0;

	/* Read register */
	da9052_lock(priv->da9052);
	ret = priv->da9052->read(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	ssc_msg.data = (ssc_msg.data & ~(da9052_regulators[id].mask_bits));
	ssc_msg.data |= ldo_volt;

	ret = priv->da9052->write(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	/* Set the GO LDO/BUCk bits so that the voltage changes */
	ssc_msg.addr = DA9052_SUPPLY_REG;
	ssc_msg.data = 0;

	ret = priv->da9052->read(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	switch (id) {
	case DA9052_LDO2:
		ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VLDO2GO);
	break;
	case DA9052_LDO3:
		ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VLDO3GO);
	break;
	case DA9052_BUCK_CORE:
		ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VBCOREGO);
	break;
	case DA9052_BUCK_PRO:
		ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VBPROGO);
	break;
	case DA9052_BUCK_MEM:
		ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VBMEMGO);
	break;
	default:
		da9052_unlock(priv->da9052);
		return -EINVAL;
	}

	ret = priv->da9052->write(priv->da9052, &ssc_msg);
	if (ret) {
		da9052_unlock(priv->da9052);
		return -EIO;
	}

	da9052_unlock(priv->da9052);

	return 0;
}