diff options
Diffstat (limited to 'drivers/regulator/wm831x-dcdc.c')
| -rw-r--r-- | drivers/regulator/wm831x-dcdc.c | 554 |
1 files changed, 216 insertions, 338 deletions
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index a0982e80985..0d88a82ab2a 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -35,7 +35,7 @@ #define WM831X_DCDC_MODE_IDLE 2 #define WM831X_DCDC_MODE_STANDBY 3 -#define WM831X_DCDC_MAX_NAME 6 +#define WM831X_DCDC_MAX_NAME 9 /* Register offsets in control block */ #define WM831X_DCDC_CONTROL_1 0 @@ -50,6 +50,7 @@ struct wm831x_dcdc { char name[WM831X_DCDC_MAX_NAME]; + char supply_name[WM831X_DCDC_MAX_NAME]; struct regulator_desc desc; int base; struct wm831x *wm831x; @@ -60,41 +61,6 @@ struct wm831x_dcdc { int dvs_vsel; }; -static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - int mask = 1 << rdev_get_id(rdev); - int reg; - - reg = wm831x_reg_read(wm831x, WM831X_DCDC_ENABLE); - if (reg < 0) - return reg; - - if (reg & mask) - return 1; - else - return 0; -} - -static int wm831x_dcdc_enable(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - int mask = 1 << rdev_get_id(rdev); - - return wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, mask, mask); -} - -static int wm831x_dcdc_disable(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - int mask = 1 << rdev_get_id(rdev); - - return wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, mask, 0); -} - static unsigned int wm831x_dcdc_get_mode(struct regulator_dev *rdev) { @@ -249,15 +215,15 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev, return -EINVAL; } -static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) +static int wm831x_buckv_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { u16 vsel; if (min_uV < 600000) vsel = 0; else if (min_uV <= 1800000) - vsel = ((min_uV - 600000) / 12500) + 8; + vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8; else return -EINVAL; @@ -267,23 +233,6 @@ static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev, return vsel; } -static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - u16 vsel; - - if (max_uV < 600000 || max_uV > 1800000) - return -EINVAL; - - vsel = ((max_uV - 600000) / 12500) + 8; - - if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV || - wm831x_buckv_list_voltage(rdev, vsel) < max_uV) - return -EINVAL; - - return vsel; -} - static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); @@ -302,20 +251,14 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) return 0; } -static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev, + unsigned vsel) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x *wm831x = dcdc->wm831x; int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG; int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL; - int vsel, ret; - - vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV); - if (vsel < 0) - return vsel; - - *selector = vsel; + int ret; /* If this value is already set then do a GPIO update if we can */ if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) @@ -338,28 +281,23 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, if (ret < 0) return ret; - /* Set the high voltage as the DVS voltage. This is optimised - * for CPUfreq usage, most processors will keep the maximum - * voltage constant and lower the minimum with the frequency. */ - vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV); - if (vsel < 0) { - /* This should never happen - at worst the same vsel - * should be chosen */ - WARN_ON(vsel < 0); - return 0; + /* + * If this VSEL is higher than the last one we've seen then + * remember it as the DVS VSEL. This is optimised for CPUfreq + * usage where we want to get to the highest voltage very + * quickly. + */ + if (vsel > dcdc->dvs_vsel) { + ret = wm831x_set_bits(wm831x, dvs_reg, + WM831X_DC1_DVS_VSEL_MASK, + vsel); + if (ret == 0) + dcdc->dvs_vsel = vsel; + else + dev_warn(wm831x->dev, + "Failed to set DCDC DVS VSEL: %d\n", ret); } - /* Don't bother if it's the same VSEL we're already using */ - if (vsel == dcdc->on_vsel) - return 0; - - ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel); - if (ret == 0) - dcdc->dvs_vsel = vsel; - else - dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n", - ret); - return 0; } @@ -371,7 +309,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; int vsel; - vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV); + vsel = wm831x_buckv_map_voltage(rdev, uV, uV); if (vsel < 0) return vsel; @@ -401,14 +339,15 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2; int i; - for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) { - if (max_uA <= wm831x_dcdc_ilim[i]) - break; + for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) { + if ((min_uA <= wm831x_dcdc_ilim[i]) && + (wm831x_dcdc_ilim[i] <= max_uA)) + return wm831x_set_bits(wm831x, reg, + WM831X_DC1_HC_THR_MASK, + i << WM831X_DC1_HC_THR_SHIFT); } - if (i == ARRAY_SIZE(wm831x_dcdc_ilim)) - return -EINVAL; - return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, i); + return -EINVAL; } static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) @@ -422,20 +361,22 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) if (val < 0) return val; - return wm831x_dcdc_ilim[val & WM831X_DC1_HC_THR_MASK]; + val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT; + return wm831x_dcdc_ilim[val]; } static struct regulator_ops wm831x_buckv_ops = { - .set_voltage = wm831x_buckv_set_voltage, + .set_voltage_sel = wm831x_buckv_set_voltage_sel, .get_voltage_sel = wm831x_buckv_get_voltage_sel, .list_voltage = wm831x_buckv_list_voltage, + .map_voltage = wm831x_buckv_map_voltage, .set_suspend_voltage = wm831x_buckv_set_suspend_voltage, .set_current_limit = wm831x_buckv_set_current_limit, .get_current_limit = wm831x_buckv_get_current_limit, - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_status = wm831x_dcdc_get_status, .get_mode = wm831x_dcdc_get_mode, .set_mode = wm831x_dcdc_set_mode, @@ -446,8 +387,9 @@ static struct regulator_ops wm831x_buckv_ops = { * Set up DVS control. We just log errors since we can still run * (with reduced performance) if we fail. */ -static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, - struct wm831x_buckv_pdata *pdata) +static void wm831x_buckv_dvs_init(struct platform_device *pdev, + struct wm831x_dcdc *dcdc, + struct wm831x_buckv_pdata *pdata) { struct wm831x *wm831x = dcdc->wm831x; int ret; @@ -456,6 +398,22 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, if (!pdata || !pdata->dvs_gpio) return; + /* gpiolib won't let us read the GPIO status so pick the higher + * of the two existing voltages so we take it as platform data. + */ + dcdc->dvs_gpio_state = pdata->dvs_init_state; + + ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio, + dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0, + "DCDC DVS"); + if (ret < 0) { + dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", + dcdc->name, ret); + return; + } + + dcdc->dvs_gpio = pdata->dvs_gpio; + switch (pdata->dvs_control_src) { case 1: ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; @@ -469,62 +427,56 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, return; } + /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL + * to make bootstrapping a bit smoother. + */ + if (!dcdc->dvs_vsel) { + ret = wm831x_set_bits(wm831x, + dcdc->base + WM831X_DCDC_DVS_CONTROL, + WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel); + if (ret == 0) + dcdc->dvs_vsel = dcdc->on_vsel; + else + dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n", + ret); + } + ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_SRC_MASK, ctrl); if (ret < 0) { dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n", dcdc->name, ret); - return; - } - - ret = gpio_request(pdata->dvs_gpio, "DCDC DVS"); - if (ret < 0) { - dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", - dcdc->name, ret); - return; - } - - /* gpiolib won't let us read the GPIO status so pick the higher - * of the two existing voltages so we take it as platform data. - */ - dcdc->dvs_gpio_state = pdata->dvs_init_state; - - ret = gpio_direction_output(pdata->dvs_gpio, dcdc->dvs_gpio_state); - if (ret < 0) { - dev_err(wm831x->dev, "Failed to enable %s DVS GPIO: %d\n", - dcdc->name, ret); - gpio_free(pdata->dvs_gpio); - return; } - - dcdc->dvs_gpio = pdata->dvs_gpio; } -static __devinit int wm831x_buckv_probe(struct platform_device *pdev) +static int wm831x_buckv_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; - int id = pdev->id % ARRAY_SIZE(pdata->dcdc); + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); + struct regulator_config config = { }; + int id; struct wm831x_dcdc *dcdc; struct resource *res; int ret, irq; - dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); + if (pdata && pdata->wm831x_num) + id = (pdata->wm831x_num * 10) + 1; + else + id = 0; + id = pdev->id - id; - if (pdata == NULL || pdata->dcdc[id] == NULL) - return -ENODEV; + dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); - if (dcdc == NULL) { - dev_err(&pdev->dev, "Unable to allocate private data\n"); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), + GFP_KERNEL); + if (!dcdc) return -ENOMEM; - } dcdc->wm831x = wm831x; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); + res = platform_get_resource(pdev, IORESOURCE_REG, 0); if (res == NULL) { - dev_err(&pdev->dev, "No I/O resource\n"); + dev_err(&pdev->dev, "No REG resource\n"); ret = -EINVAL; goto err; } @@ -532,11 +484,18 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1); dcdc->desc.name = dcdc->name; + + snprintf(dcdc->supply_name, sizeof(dcdc->supply_name), + "DC%dVDD", id + 1); + dcdc->desc.supply_name = dcdc->supply_name; + dcdc->desc.id = id; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1; dcdc->desc.ops = &wm831x_buckv_ops; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << id; ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); if (ret < 0) { @@ -545,18 +504,25 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) } dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK; - ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); + ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL); if (ret < 0) { dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret); goto err; } dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK; - if (pdata->dcdc[id]) - wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); + if (pdata && pdata->dcdc[id]) + wm831x_buckv_dvs_init(pdev, dcdc, + pdata->dcdc[id]->driver_data); - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + config.dev = pdev->dev.parent; + if (pdata) + config.init_data = pdata->dcdc[id]; + config.driver_data = dcdc; + config.regmap = wm831x->regmap; + + dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc, + &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -564,58 +530,36 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); - ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, - IRQF_TRIGGER_RISING, dcdc->name, dcdc); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + wm831x_dcdc_uv_irq, + IRQF_TRIGGER_RISING, dcdc->name, dcdc); if (ret != 0) { dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n", irq, ret); - goto err_regulator; + goto err; } - irq = platform_get_irq_byname(pdev, "HC"); - ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq, - IRQF_TRIGGER_RISING, dcdc->name, dcdc); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + wm831x_dcdc_oc_irq, + IRQF_TRIGGER_RISING, dcdc->name, dcdc); if (ret != 0) { dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n", irq, ret); - goto err_uv; + goto err; } platform_set_drvdata(pdev, dcdc); return 0; -err_uv: - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); -err_regulator: - regulator_unregister(dcdc->regulator); err: - if (dcdc->dvs_gpio) - gpio_free(dcdc->dvs_gpio); - kfree(dcdc); return ret; } -static __devexit int wm831x_buckv_remove(struct platform_device *pdev) -{ - struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - - free_irq(platform_get_irq_byname(pdev, "HC"), dcdc); - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); - regulator_unregister(dcdc->regulator); - if (dcdc->dvs_gpio) - gpio_free(dcdc->dvs_gpio); - kfree(dcdc); - - return 0; -} - static struct platform_driver wm831x_buckv_driver = { .probe = wm831x_buckv_probe, - .remove = __devexit_p(wm831x_buckv_remove), .driver = { .name = "wm831x-buckv", .owner = THIS_MODULE, @@ -626,110 +570,64 @@ static struct platform_driver wm831x_buckv_driver = { * BUCKP specifics */ -static int wm831x_buckp_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector <= WM831X_BUCKP_MAX_SELECTOR) - return 850000 + (selector * 25000); - else - return -EINVAL; -} - -static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, - int min_uV, int max_uV, int *selector) +static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x *wm831x = dcdc->wm831x; - u16 vsel; - - if (min_uV <= 34000000) - vsel = (min_uV - 850000) / 25000; - else - return -EINVAL; - - if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV) - return -EINVAL; - - *selector = vsel; - - return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel); -} - -static int wm831x_buckp_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; - - return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV, - selector); -} - -static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, - int uV) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; - unsigned selector; + int sel; - return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector); -} + sel = regulator_map_voltage_linear(rdev, uV, uV); + if (sel < 0) + return sel; -static int wm831x_buckp_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; - int val; - - val = wm831x_reg_read(wm831x, reg); - if (val < 0) - return val; - - return val & WM831X_DC3_ON_VSEL_MASK; + return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel); } static struct regulator_ops wm831x_buckp_ops = { - .set_voltage = wm831x_buckp_set_voltage, - .get_voltage_sel = wm831x_buckp_get_voltage_sel, - .list_voltage = wm831x_buckp_list_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_status = wm831x_dcdc_get_status, .get_mode = wm831x_dcdc_get_mode, .set_mode = wm831x_dcdc_set_mode, .set_suspend_mode = wm831x_dcdc_set_suspend_mode, }; -static __devinit int wm831x_buckp_probe(struct platform_device *pdev) +static int wm831x_buckp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; - int id = pdev->id % ARRAY_SIZE(pdata->dcdc); + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); + struct regulator_config config = { }; + int id; struct wm831x_dcdc *dcdc; struct resource *res; int ret, irq; - dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); + if (pdata && pdata->wm831x_num) + id = (pdata->wm831x_num * 10) + 1; + else + id = 0; + id = pdev->id - id; - if (pdata == NULL || pdata->dcdc[id] == NULL) - return -ENODEV; + dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); - if (dcdc == NULL) { - dev_err(&pdev->dev, "Unable to allocate private data\n"); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), + GFP_KERNEL); + if (!dcdc) return -ENOMEM; - } dcdc->wm831x = wm831x; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); + res = platform_get_resource(pdev, IORESOURCE_REG, 0); if (res == NULL) { - dev_err(&pdev->dev, "No I/O resource\n"); + dev_err(&pdev->dev, "No REG resource\n"); ret = -EINVAL; goto err; } @@ -737,14 +635,31 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1); dcdc->desc.name = dcdc->name; + + snprintf(dcdc->supply_name, sizeof(dcdc->supply_name), + "DC%dVDD", id + 1); + dcdc->desc.supply_name = dcdc->supply_name; + dcdc->desc.id = id; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1; dcdc->desc.ops = &wm831x_buckp_ops; dcdc->desc.owner = THIS_MODULE; - - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG; + dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << id; + dcdc->desc.min_uV = 850000; + dcdc->desc.uV_step = 25000; + + config.dev = pdev->dev.parent; + if (pdata) + config.init_data = pdata->dcdc[id]; + config.driver_data = dcdc; + config.regmap = wm831x->regmap; + + dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc, + &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -752,42 +667,26 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq_byname(pdev, "UV"); - ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, - IRQF_TRIGGER_RISING, dcdc->name, dcdc); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + wm831x_dcdc_uv_irq, + IRQF_TRIGGER_RISING, dcdc->name, dcdc); if (ret != 0) { dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n", irq, ret); - goto err_regulator; + goto err; } platform_set_drvdata(pdev, dcdc); return 0; -err_regulator: - regulator_unregister(dcdc->regulator); err: - kfree(dcdc); return ret; } -static __devexit int wm831x_buckp_remove(struct platform_device *pdev) -{ - struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); - regulator_unregister(dcdc->regulator); - kfree(dcdc); - - return 0; -} - static struct platform_driver wm831x_buckp_driver = { .probe = wm831x_buckp_probe, - .remove = __devexit_p(wm831x_buckp_remove), .driver = { .name = "wm831x-buckp", .owner = THIS_MODULE, @@ -828,15 +727,16 @@ static int wm831x_boostp_get_status(struct regulator_dev *rdev) static struct regulator_ops wm831x_boostp_ops = { .get_status = wm831x_boostp_get_status, - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; -static __devinit int wm831x_boostp_probe(struct platform_device *pdev) +static int wm831x_boostp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); + struct regulator_config config = { }; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); struct wm831x_dcdc *dcdc; struct resource *res; @@ -847,19 +747,16 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) if (pdata == NULL || pdata->dcdc[id] == NULL) return -ENODEV; - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); - if (dcdc == NULL) { - dev_err(&pdev->dev, "Unable to allocate private data\n"); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); + if (!dcdc) return -ENOMEM; - } dcdc->wm831x = wm831x; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); + res = platform_get_resource(pdev, IORESOURCE_REG, 0); if (res == NULL) { - dev_err(&pdev->dev, "No I/O resource\n"); - ret = -EINVAL; - goto err; + dev_err(&pdev->dev, "No REG resource\n"); + return -EINVAL; } dcdc->base = res->start; @@ -869,53 +766,42 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.ops = &wm831x_boostp_ops; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << id; + + config.dev = pdev->dev.parent; + if (pdata) + config.init_data = pdata->dcdc[id]; + config.driver_data = dcdc; + config.regmap = wm831x->regmap; - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc, + &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", id + 1, ret); - goto err; + return ret; } - irq = platform_get_irq_byname(pdev, "UV"); - ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, - IRQF_TRIGGER_RISING, dcdc->name, - dcdc); + irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + wm831x_dcdc_uv_irq, + IRQF_TRIGGER_RISING, dcdc->name, + dcdc); if (ret != 0) { dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n", irq, ret); - goto err_regulator; + return ret; } platform_set_drvdata(pdev, dcdc); return 0; - -err_regulator: - regulator_unregister(dcdc->regulator); -err: - kfree(dcdc); - return ret; -} - -static __devexit int wm831x_boostp_remove(struct platform_device *pdev) -{ - struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - - free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); - regulator_unregister(dcdc->regulator); - kfree(dcdc); - - return 0; } static struct platform_driver wm831x_boostp_driver = { .probe = wm831x_boostp_probe, - .remove = __devexit_p(wm831x_boostp_remove), .driver = { .name = "wm831x-boostp", .owner = THIS_MODULE, @@ -932,30 +818,26 @@ static struct platform_driver wm831x_boostp_driver = { #define WM831X_EPE_BASE 6 static struct regulator_ops wm831x_epe_ops = { - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_status = wm831x_dcdc_get_status, }; -static __devinit int wm831x_epe_probe(struct platform_device *pdev) +static int wm831x_epe_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); + struct regulator_config config = { }; int id = pdev->id % ARRAY_SIZE(pdata->epe); struct wm831x_dcdc *dcdc; int ret; dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1); - if (pdata == NULL || pdata->epe[id] == NULL) - return -ENODEV; - - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); - if (dcdc == NULL) { - dev_err(&pdev->dev, "Unable to allocate private data\n"); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); + if (!dcdc) return -ENOMEM; - } dcdc->wm831x = wm831x; @@ -968,9 +850,17 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.ops = &wm831x_epe_ops; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << dcdc->desc.id; - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->epe[id], dcdc); + config.dev = pdev->dev.parent; + if (pdata) + config.init_data = pdata->epe[id]; + config.driver_data = dcdc; + config.regmap = wm831x->regmap; + + dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc, + &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register EPE%d: %d\n", @@ -983,25 +873,11 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) return 0; err: - kfree(dcdc); return ret; } -static __devexit int wm831x_epe_remove(struct platform_device *pdev) -{ - struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - - regulator_unregister(dcdc->regulator); - kfree(dcdc); - - return 0; -} - static struct platform_driver wm831x_epe_driver = { .probe = wm831x_epe_probe, - .remove = __devexit_p(wm831x_epe_remove), .driver = { .name = "wm831x-epe", .owner = THIS_MODULE, @@ -1046,3 +922,5 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:wm831x-buckv"); MODULE_ALIAS("platform:wm831x-buckp"); +MODULE_ALIAS("platform:wm831x-boostp"); +MODULE_ALIAS("platform:wm831x-epe"); |
