diff mbox

[v3,2/2] regulator: rk808: add dvs support

Message ID 1418612879-16094-3-git-send-email-zyw@rock-chips.com (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Zhong Dec. 15, 2014, 3:07 a.m. UTC
rk808 has a dvs function, there are 3 pins for dvs, dvs1 & dvs2 & dvsok.
Normally, the voltage of DCDC1/DCDC2 are controlled by BUCKn_ON_VSEL, when
we pull dvs1/dvs2 pin to active, they would be controlled by BUCKn_DVS_VSEL.
And the dvsok pin is used to indicate whether regulating has been completed.
When dvs1/dvs2 pin change, dvsok would be pull down, and it would be pull up
once the regulating is complete.

Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Reviewed-by: Doug Anderson <dianders@chromium.org>

---

Changes in v3: None
Changes in v2:
- modify the multiline commenting

 drivers/regulator/rk808-regulator.c | 192 +++++++++++++++++++++++++++++++++---
 1 file changed, 180 insertions(+), 12 deletions(-)

Comments

Mark Brown Dec. 29, 2014, 5:25 p.m. UTC | #1
On Mon, Dec 15, 2014 at 11:07:58AM +0800, Chris Zhong wrote:

> +	sel <<= ffs(rdev->desc->vsel_mask) - 1;
> +	sel |= old_sel & ~rdev->desc->vsel_mask;
> +
> +	ret = regmap_write(rdev->regmap, reg, sel);
> +	if (ret)
> +		return ret;
> +
> +	gpiod_set_value(gpio, !gpio_level);

So, this seems a bit odd.  What we appear to be doing here is
alternating between the two different voltage setting registers which is
all well and good but makes me wonder why we're bothering - it's a bit
more work than just sticking with one.  We do get...

> +	/*
> +	 * dvsok pin would be pull down when dvs1/2 pin changed, and
> +	 * it would be pull up once the voltage regulate complete.
> +	 * No need to wait dvsok signal when voltage falling.
> +	 */

...this but unless the voltage typically ramps much faster than spec
it's never clear to me that we're actually winning by polling the pin
instead of just dead reckoning the time, it's more work for the CPU to
poll the GPIO than to sleep after all.

One thing we can do with hardware like this is to program in a voltage
we're likely to want to switch to quickly and then use the GPIO to get
there.  That can be a bit hard to arrange with the regulator API as it
currently stands since we don't exactly have an interface for it.  

We can just check to see what the two values are current set to before
switching and skip the register write if it's the same (making things
faster since we're typically avoiding an I2C or SPI transaction by doing
that) but that's a bit meh.  We can also try to do things like keep the
top voltage from the voltage ranges we're being given programmed which
for DVS typically ends up doing a reasonable job since governors often
like to jump straight to top speed when things get busy so that's one of
the common cases where we most want to change voltages as quickly as
possible.
Chris Zhong Dec. 30, 2014, 3:07 a.m. UTC | #2
On 12/30/2014 01:25 AM, Mark Brown wrote:
> On Mon, Dec 15, 2014 at 11:07:58AM +0800, Chris Zhong wrote:
>
>> +	sel <<= ffs(rdev->desc->vsel_mask) - 1;
>> +	sel |= old_sel & ~rdev->desc->vsel_mask;
>> +
>> +	ret = regmap_write(rdev->regmap, reg, sel);
>> +	if (ret)
>> +		return ret;
>> +
>> +	gpiod_set_value(gpio, !gpio_level);
> So, this seems a bit odd.  What we appear to be doing here is
> alternating between the two different voltage setting registers which is
> all well and good but makes me wonder why we're bothering - it's a bit
> more work than just sticking with one.  We do get...
you mean check the old_selector and selector? I think
_regulator_do_set_voltage have done it.
>
>> +	/*
>> +	 * dvsok pin would be pull down when dvs1/2 pin changed, and
>> +	 * it would be pull up once the voltage regulate complete.
>> +	 * No need to wait dvsok signal when voltage falling.
>> +	 */
> ...this but unless the voltage typically ramps much faster than spec
> it's never clear to me that we're actually winning by polling the pin
> instead of just dead reckoning the time, it's more work for the CPU to
> poll the GPIO than to sleep after all.
Actually, it's slower than spec, so I think getting this dvsok pin state
is safer than delay.
>
> One thing we can do with hardware like this is to program in a voltage
> we're likely to want to switch to quickly and then use the GPIO to get
> there.  That can be a bit hard to arrange with the regulator API as it
> currently stands since we don't exactly have an interface for it.
>
> We can just check to see what the two values are current set to before
> switching and skip the register write if it's the same (making things
> faster since we're typically avoiding an I2C or SPI transaction by doing
> that) but that's a bit meh.  We can also try to do things like keep the
> top voltage from the voltage ranges we're being given programmed which
> for DVS typically ends up doing a reasonable job since governors often
> like to jump straight to top speed when things get busy so that's one of
> the common cases where we most want to change voltages as quickly as
> possible.
Mark Brown Dec. 30, 2014, 5:04 p.m. UTC | #3
On Tue, Dec 30, 2014 at 11:07:14AM +0800, Chris Zhong wrote:
> On 12/30/2014 01:25 AM, Mark Brown wrote:

> >So, this seems a bit odd.  What we appear to be doing here is
> >alternating between the two different voltage setting registers which is
> >all well and good but makes me wonder why we're bothering - it's a bit
> >more work than just sticking with one.  We do get...

> you mean check the old_selector and selector? I think
> _regulator_do_set_voltage have done it.

No, I mean that we may as well just always write to the same register
and save a bunch of code.

> >...this but unless the voltage typically ramps much faster than spec
> >it's never clear to me that we're actually winning by polling the pin
> >instead of just dead reckoning the time, it's more work for the CPU to
> >poll the GPIO than to sleep after all.

> Actually, it's slower than spec, so I think getting this dvsok pin state
> is safer than delay.

Well, that suggests that the spec is wrong which ought to be fixed
anyway oughtn't it?  Or are you saying that the delay is inconsistent as
well as slower than advertised?
Chris Zhong Dec. 31, 2014, 2:21 a.m. UTC | #4
On 12/31/2014 01:04 AM, Mark Brown wrote:
> On Tue, Dec 30, 2014 at 11:07:14AM +0800, Chris Zhong wrote:
>> On 12/30/2014 01:25 AM, Mark Brown wrote:
>>> So, this seems a bit odd.  What we appear to be doing here is
>>> alternating between the two different voltage setting registers which is
>>> all well and good but makes me wonder why we're bothering - it's a bit
>>> more work than just sticking with one.  We do get...
>> you mean check the old_selector and selector? I think
>> _regulator_do_set_voltage have done it.
> No, I mean that we may as well just always write to the same register
> and save a bunch of code.
No, when we pull down DVSn pin, the voltage value is from 
RK808_BUCK1_ON_VSEL_REG,
and when we pull up DVSn pin, the voltage value if from 
RK808_BUCK1_ON_VSEL_REG+2.
We want to this dvs function for a better voltage wave, avoid overshoot, 
if someone do not
need this function, they could remove the setting of DVSn pin in dts 
file, and at that time,
rk808_regulator will use a same register for setting voltage.


>>> ...this but unless the voltage typically ramps much faster than spec
>>> it's never clear to me that we're actually winning by polling the pin
>>> instead of just dead reckoning the time, it's more work for the CPU to
>>> poll the GPIO than to sleep after all.
>> Actually, it's slower than spec, so I think getting this dvsok pin state
>> is safer than delay.
> Well, that suggests that the spec is wrong which ought to be fixed
> anyway oughtn't it?  Or are you saying that the delay is inconsistent as
> well as slower than advertised?
the spec said 2/4/6/10 mv/us, but the ramp will change depending on the 
load.
So I think the dvsok pin is more accurate, since it It will soon change, 
once the
regulator is completed. the delay is a fixed time. it is faster than 
dvsok pin.
Doug Anderson Jan. 2, 2015, 6:41 p.m. UTC | #5
Mark,

On Mon, Dec 29, 2014 at 9:25 AM, Mark Brown <broonie@kernel.org> wrote:
> On Mon, Dec 15, 2014 at 11:07:58AM +0800, Chris Zhong wrote:
>
>> +     sel <<= ffs(rdev->desc->vsel_mask) - 1;
>> +     sel |= old_sel & ~rdev->desc->vsel_mask;
>> +
>> +     ret = regmap_write(rdev->regmap, reg, sel);
>> +     if (ret)
>> +             return ret;
>> +
>> +     gpiod_set_value(gpio, !gpio_level);
>
> So, this seems a bit odd.  What we appear to be doing here is
> alternating between the two different voltage setting registers which is
> all well and good but makes me wonder why we're bothering - it's a bit
> more work than just sticking with one.  We do get...

It's odd, but the rk808 is odd.

Specifically if you don't use the "DVFS" pins like this then the
hardware ignores the ramp rate that's programmed into it.  When I
submitted (8af2522 regulator: rk808: Add function for ramp delay for
buck1/buck2) upstream I verified my change by looking at the register
values that were being set (ran i2cget in userspace).  I didn't
measure the waveforms myself.  Later, Chris found that my change was
not doing anything at all because the ramp delay has no effect if you
are setting the voltage using an i2c write--it only has an effect if
you're setting the voltage using DVFS pins.

If you write the voltage directly using an i2c write the rk808 will
ramp as fast as it possibly can, which will probably lead to an
overshoot.  You could fix this by changing the voltage more slowly in
software, but it seems better to use the DVFS pin if we have it...


>> +     /*
>> +      * dvsok pin would be pull down when dvs1/2 pin changed, and
>> +      * it would be pull up once the voltage regulate complete.
>> +      * No need to wait dvsok signal when voltage falling.
>> +      */
>
> ...this but unless the voltage typically ramps much faster than spec
> it's never clear to me that we're actually winning by polling the pin
> instead of just dead reckoning the time, it's more work for the CPU to
> poll the GPIO than to sleep after all.

Possibly even fewer CPU cycles: we could configure this GPIO as an
interrupt.  Then we can look for the rising edge in hardware.  ...you
might need to make sure that the pin actually falls and goes back up,
though.  If you changed between two voltages that were pretty close to
begin with I wonder if the edge could be missed.  I guess you could
make it high-level sensitive and put the 1us delay before unmasking
it...


> One thing we can do with hardware like this is to program in a voltage
> we're likely to want to switch to quickly and then use the GPIO to get
> there.  That can be a bit hard to arrange with the regulator API as it
> currently stands since we don't exactly have an interface for it.
>
> We can just check to see what the two values are current set to before
> switching and skip the register write if it's the same (making things
> faster since we're typically avoiding an I2C or SPI transaction by doing
> that) but that's a bit meh.  We can also try to do things like keep the
> top voltage from the voltage ranges we're being given programmed which
> for DVS typically ends up doing a reasonable job since governors often
> like to jump straight to top speed when things get busy so that's one of
> the common cases where we most want to change voltages as quickly as
> possible.

You're right that there could be some cool optimizations here, but
since we really need to do a switch from A-to-B on every voltage
change to get the ramp speed right then I don't think we can do them.

Note that the MFD driver sets things up using regcache, so we
shouldn't ever do a needless i2c transaction.

-Doug
Mark Brown Jan. 6, 2015, 12:12 p.m. UTC | #6
On Fri, Jan 02, 2015 at 10:41:13AM -0800, Doug Anderson wrote:
> On Mon, Dec 29, 2014 at 9:25 AM, Mark Brown <broonie@kernel.org> wrote:

> > So, this seems a bit odd.  What we appear to be doing here is
> > alternating between the two different voltage setting registers which is
> > all well and good but makes me wonder why we're bothering - it's a bit
> > more work than just sticking with one.  We do get...

> It's odd, but the rk808 is odd.

> Specifically if you don't use the "DVFS" pins like this then the
> hardware ignores the ramp rate that's programmed into it.  When I
> submitted (8af2522 regulator: rk808: Add function for ramp delay for
> buck1/buck2) upstream I verified my change by looking at the register
> values that were being set (ran i2cget in userspace).  I didn't
> measure the waveforms myself.  Later, Chris found that my change was
> not doing anything at all because the ramp delay has no effect if you
> are setting the voltage using an i2c write--it only has an effect if
> you're setting the voltage using DVFS pins.

> If you write the voltage directly using an i2c write the rk808 will
> ramp as fast as it possibly can, which will probably lead to an
> overshoot.  You could fix this by changing the voltage more slowly in
> software, but it seems better to use the DVFS pin if we have it...

OK, so this is all stuff that should go in at *least* the commit log and
most likely comments in the driver since right now it just looks like
it's adding complexity.  It does also sound like the regulation here is
a bit interesting, normally the ramp time control is more about limiting
inrush currents than suppressing transients.

Currrently we'd end up with code that just looks redundant.

> > ...this but unless the voltage typically ramps much faster than spec
> > it's never clear to me that we're actually winning by polling the pin
> > instead of just dead reckoning the time, it's more work for the CPU to
> > poll the GPIO than to sleep after all.

> Possibly even fewer CPU cycles: we could configure this GPIO as an
> interrupt.  Then we can look for the rising edge in hardware.  ...you
> might need to make sure that the pin actually falls and goes back up,
> though.  If you changed between two voltages that were pretty close to
> begin with I wonder if the edge could be missed.  I guess you could
> make it high-level sensitive and put the 1us delay before unmasking
> it...

Yes, if you make it interrupt driven it might be less work though then
you have to worry about interrupt and scheduling latencies.

> > We can just check to see what the two values are current set to before
> > switching and skip the register write if it's the same (making things
> > faster since we're typically avoiding an I2C or SPI transaction by doing
> > that) but that's a bit meh.  We can also try to do things like keep the
> > top voltage from the voltage ranges we're being given programmed which
> > for DVS typically ends up doing a reasonable job since governors often
> > like to jump straight to top speed when things get busy so that's one of
> > the common cases where we most want to change voltages as quickly as
> > possible.

> You're right that there could be some cool optimizations here, but
> since we really need to do a switch from A-to-B on every voltage
> change to get the ramp speed right then I don't think we can do them.

Like I say this needs to be obvious in the code, the combination of
calling this "DVS" (which is normally some sort of performance
optimisation thing for fast voltage changes) and lack of any information
on what it's supposed to achieve mean that the patch as it stands has
no clear goal or benefit.  Someone has to know not to come along and try
to do such optimizations later on if nothing else.

> Note that the MFD driver sets things up using regcache, so we
> shouldn't ever do a needless i2c transaction.

That's not the point really, the point is about doing a better job of
predicting what voltages we might want to transition to.
diff mbox

Patch

diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 33042eb..f31e4fc 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -16,10 +16,13 @@ 
  * more details.
  */
 
-#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/mfd/rk808.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/mfd/rk808.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 
@@ -36,12 +39,23 @@ 
 #define RK808_RAMP_RATE_6MV_PER_US	(2 << RK808_RAMP_RATE_OFFSET)
 #define RK808_RAMP_RATE_10MV_PER_US	(3 << RK808_RAMP_RATE_OFFSET)
 
+#define RK808_DVS2_POL		BIT(2)
+#define RK808_DVS1_POL		BIT(1)
+
 /* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */
 #define RK808_SLP_REG_OFFSET 1
 
+/* Offset from XXX_ON_VSEL to XXX_DVS_VSEL */
+#define RK808_DVS_REG_OFFSET 2
+
 /* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */
 #define RK808_SLP_SET_OFF_REG_OFFSET 2
 
+struct rk808_regulator_data {
+	struct gpio_desc *dvsok_gpio;
+	struct gpio_desc *dvs_gpio[2];
+};
+
 static const int rk808_buck_config_regs[] = {
 	RK808_BUCK1_CONFIG_REG,
 	RK808_BUCK2_CONFIG_REG,
@@ -70,6 +84,97 @@  static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = {
 	REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000),
 };
 
+int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+	struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
+	int id = rdev->desc->id - RK808_ID_DCDC1;
+	struct gpio_desc *gpio = pdata->dvs_gpio[id];
+	unsigned int val;
+	int ret;
+
+	if (IS_ERR(gpio) || gpiod_get_value(gpio) == 0)
+		return regulator_get_voltage_sel_regmap(rdev);
+
+	ret = regmap_read(rdev->regmap,
+			  rdev->desc->vsel_reg + RK808_DVS_REG_OFFSET,
+			  &val);
+	if (ret != 0)
+		return ret;
+
+	val &= rdev->desc->vsel_mask;
+	val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+	return val;
+}
+
+int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
+{
+	struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
+	int id = rdev->desc->id - RK808_ID_DCDC1;
+	struct gpio_desc *gpio = pdata->dvs_gpio[id];
+	unsigned int reg = rdev->desc->vsel_reg;
+	unsigned long timeout;
+	unsigned old_sel;
+	int ret, gpio_level;
+
+	if (IS_ERR(gpio))
+		return regulator_set_voltage_sel_regmap(rdev, sel);
+
+	gpio_level = gpiod_get_value(gpio);
+	if (gpio_level == 0) {
+		reg += RK808_DVS_REG_OFFSET;
+		ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &old_sel);
+	} else {
+		ret = regmap_read(rdev->regmap,
+				  reg + RK808_DVS_REG_OFFSET,
+				  &old_sel);
+	}
+
+	if (ret != 0)
+		return ret;
+
+	sel <<= ffs(rdev->desc->vsel_mask) - 1;
+	sel |= old_sel & ~rdev->desc->vsel_mask;
+
+	ret = regmap_write(rdev->regmap, reg, sel);
+	if (ret)
+		return ret;
+
+	gpiod_set_value(gpio, !gpio_level);
+
+	/*
+	 * dvsok pin would be pull down when dvs1/2 pin changed, and
+	 * it would be pull up once the voltage regulate complete.
+	 * No need to wait dvsok signal when voltage falling.
+	 */
+	if (old_sel < sel && !IS_ERR(pdata->dvsok_gpio)) {
+		timeout = jiffies + msecs_to_jiffies(1);
+		while (!time_after(jiffies, timeout)) {
+			udelay(1);
+			if (gpiod_get_value(pdata->dvsok_gpio))
+				return 0;
+		}
+		gpiod_set_value(gpio, gpio_level);
+		pr_err("%s wait dvsok timeout\n", rdev->desc->name);
+		ret = -EBUSY;
+	}
+
+	return ret;
+}
+
+int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
+				       unsigned int old_selector,
+				       unsigned int new_selector)
+{
+	struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
+
+	/* if there is a dvsok pin, we don't need wait extra time here */
+	if (!IS_ERR(pdata->dvsok_gpio))
+		return 0;
+
+	return regulator_set_voltage_time_sel(rdev, old_selector, new_selector);
+}
+
 static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
 	unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US;
@@ -137,8 +242,9 @@  static int rk808_set_suspend_disable(struct regulator_dev *rdev)
 static struct regulator_ops rk808_buck1_2_ops = {
 	.list_voltage		= regulator_list_voltage_linear_range,
 	.map_voltage		= regulator_map_voltage_linear_range,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= rk808_buck1_2_get_voltage_sel_regmap,
+	.set_voltage_sel	= rk808_buck1_2_set_voltage_sel,
+	.set_voltage_time_sel	= rk808_buck1_2_set_voltage_time_sel,
 	.enable			= regulator_enable_regmap,
 	.disable		= regulator_disable_regmap,
 	.is_enabled		= regulator_is_enabled_regmap,
@@ -372,25 +478,86 @@  static struct of_regulator_match rk808_reg_matches[] = {
 	[RK808_ID_SWITCH2]	= { .name = "SWITCH_REG2" },
 };
 
+int rk808_regulator_dt_parse_pdata(struct device *dev,
+				   struct device *client_dev,
+				   struct regmap *map,
+				   struct rk808_regulator_data *pdata)
+{
+	struct device_node *np;
+	int tmp, ret, i;
+
+	np = of_get_child_by_name(client_dev->of_node, "regulators");
+	if (!np)
+		return -ENXIO;
+
+	ret = of_regulator_match(dev, np, rk808_reg_matches,
+				 RK808_NUM_REGULATORS);
+	if (ret < 0)
+		goto dt_parse_end;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
+		pdata->dvs_gpio[i] = gpiod_get_index(client_dev, "dvs", i);
+		if (IS_ERR(pdata->dvs_gpio[i])) {
+			dev_warn(dev, "there is no dvs%d gpio\n", i);
+			continue;
+		}
+
+		gpiod_direction_output(pdata->dvs_gpio[i], 0);
+
+		tmp = i ? RK808_DVS2_POL : RK808_DVS1_POL;
+		ret = regmap_update_bits(map, RK808_IO_POL_REG, tmp,
+				gpiod_is_active_low(pdata->dvs_gpio[i]) ?
+				0 : tmp);
+	}
+
+	pdata->dvsok_gpio = gpiod_get_index(client_dev, "dvsok", 0);
+	if (IS_ERR(pdata->dvsok_gpio)) {
+		dev_warn(dev, "there is no dvs ok gpio\n");
+		goto dt_parse_end;
+	}
+
+	gpiod_direction_input(pdata->dvsok_gpio);
+
+dt_parse_end:
+	of_node_put(np);
+	return ret;
+}
+
+static int rk808_regulator_remove(struct platform_device *pdev)
+{
+	struct rk808_regulator_data *pdata = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
+		if (!IS_ERR(pdata->dvs_gpio[i]))
+			gpiod_put(pdata->dvs_gpio[i]);
+	}
+
+	if (!IS_ERR(pdata->dvsok_gpio))
+			gpiod_put(pdata->dvsok_gpio);
+	return 0;
+}
+
 static int rk808_regulator_probe(struct platform_device *pdev)
 {
 	struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
 	struct i2c_client *client = rk808->i2c;
-	struct device_node *reg_np;
 	struct regulator_config config = {};
 	struct regulator_dev *rk808_rdev;
+	struct rk808_regulator_data *pdata;
 	int ret, i;
 
-	reg_np = of_get_child_by_name(client->dev.of_node, "regulators");
-	if (!reg_np)
-		return -ENXIO;
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
 
-	ret = of_regulator_match(&pdev->dev, reg_np, rk808_reg_matches,
-				 RK808_NUM_REGULATORS);
-	of_node_put(reg_np);
+	ret = rk808_regulator_dt_parse_pdata(&pdev->dev, &client->dev,
+					     rk808->regmap, pdata);
 	if (ret < 0)
 		return ret;
 
+	platform_set_drvdata(pdev, pdata);
+
 	/* Instantiate the regulators */
 	for (i = 0; i < RK808_NUM_REGULATORS; i++) {
 		if (!rk808_reg_matches[i].init_data ||
@@ -398,7 +565,7 @@  static int rk808_regulator_probe(struct platform_device *pdev)
 			continue;
 
 		config.dev = &client->dev;
-		config.driver_data = rk808;
+		config.driver_data = pdata;
 		config.regmap = rk808->regmap;
 		config.of_node = rk808_reg_matches[i].of_node;
 		config.init_data = rk808_reg_matches[i].init_data;
@@ -417,6 +584,7 @@  static int rk808_regulator_probe(struct platform_device *pdev)
 
 static struct platform_driver rk808_regulator_driver = {
 	.probe = rk808_regulator_probe,
+	.remove = rk808_regulator_remove,
 	.driver = {
 		.name = "rk808-regulator",
 		.owner = THIS_MODULE,