brintos

brintos / linux-shallow public Read only

0
0
Text · 21.7 KiB · 834d7c1 Raw
859 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// wm831x-dcdc.c  --  DC-DC buck converter driver for the WM831x series4//5// Copyright 2009 Wolfson Microelectronics PLC.6//7// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>8 9#include <linux/module.h>10#include <linux/moduleparam.h>11#include <linux/init.h>12#include <linux/bitops.h>13#include <linux/err.h>14#include <linux/i2c.h>15#include <linux/platform_device.h>16#include <linux/regulator/driver.h>17#include <linux/regulator/machine.h>18#include <linux/gpio/consumer.h>19#include <linux/slab.h>20 21#include <linux/mfd/wm831x/core.h>22#include <linux/mfd/wm831x/regulator.h>23#include <linux/mfd/wm831x/pdata.h>24 25#define WM831X_BUCKV_MAX_SELECTOR 0x6826#define WM831X_BUCKP_MAX_SELECTOR 0x6627 28#define WM831X_DCDC_MODE_FAST    029#define WM831X_DCDC_MODE_NORMAL  130#define WM831X_DCDC_MODE_IDLE    231#define WM831X_DCDC_MODE_STANDBY 332 33#define WM831X_DCDC_MAX_NAME 934 35/* Register offsets in control block */36#define WM831X_DCDC_CONTROL_1     037#define WM831X_DCDC_CONTROL_2     138#define WM831X_DCDC_ON_CONFIG     239#define WM831X_DCDC_SLEEP_CONTROL 340#define WM831X_DCDC_DVS_CONTROL   441 42/*43 * Shared44 */45 46struct wm831x_dcdc {47	char name[WM831X_DCDC_MAX_NAME];48	char supply_name[WM831X_DCDC_MAX_NAME];49	struct regulator_desc desc;50	int base;51	struct wm831x *wm831x;52	struct regulator_dev *regulator;53	struct gpio_desc *dvs_gpiod;54	int dvs_gpio_state;55	int on_vsel;56	int dvs_vsel;57};58 59static unsigned int wm831x_dcdc_get_mode(struct regulator_dev *rdev)60 61{62	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);63	struct wm831x *wm831x = dcdc->wm831x;64	u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;65	int val;66 67	val = wm831x_reg_read(wm831x, reg);68	if (val < 0)69		return val;70 71	val = (val & WM831X_DC1_ON_MODE_MASK) >> WM831X_DC1_ON_MODE_SHIFT;72 73	switch (val) {74	case WM831X_DCDC_MODE_FAST:75		return REGULATOR_MODE_FAST;76	case WM831X_DCDC_MODE_NORMAL:77		return REGULATOR_MODE_NORMAL;78	case WM831X_DCDC_MODE_STANDBY:79		return REGULATOR_MODE_STANDBY;80	case WM831X_DCDC_MODE_IDLE:81		return REGULATOR_MODE_IDLE;82	default:83		BUG();84		return -EINVAL;85	}86}87 88static int wm831x_dcdc_set_mode_int(struct wm831x *wm831x, int reg,89				    unsigned int mode)90{91	int val;92 93	switch (mode) {94	case REGULATOR_MODE_FAST:95		val = WM831X_DCDC_MODE_FAST;96		break;97	case REGULATOR_MODE_NORMAL:98		val = WM831X_DCDC_MODE_NORMAL;99		break;100	case REGULATOR_MODE_STANDBY:101		val = WM831X_DCDC_MODE_STANDBY;102		break;103	case REGULATOR_MODE_IDLE:104		val = WM831X_DCDC_MODE_IDLE;105		break;106	default:107		return -EINVAL;108	}109 110	return wm831x_set_bits(wm831x, reg, WM831X_DC1_ON_MODE_MASK,111			       val << WM831X_DC1_ON_MODE_SHIFT);112}113 114static int wm831x_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)115{116	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);117	struct wm831x *wm831x = dcdc->wm831x;118	u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;119 120	return wm831x_dcdc_set_mode_int(wm831x, reg, mode);121}122 123static int wm831x_dcdc_set_suspend_mode(struct regulator_dev *rdev,124					unsigned int mode)125{126	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);127	struct wm831x *wm831x = dcdc->wm831x;128	u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;129 130	return wm831x_dcdc_set_mode_int(wm831x, reg, mode);131}132 133static int wm831x_dcdc_get_status(struct regulator_dev *rdev)134{135	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);136	struct wm831x *wm831x = dcdc->wm831x;137	int ret;138 139	/* First, check for errors */140	ret = wm831x_reg_read(wm831x, WM831X_DCDC_UV_STATUS);141	if (ret < 0)142		return ret;143 144	if (ret & (1 << rdev_get_id(rdev))) {145		dev_dbg(wm831x->dev, "DCDC%d under voltage\n",146			rdev_get_id(rdev) + 1);147		return REGULATOR_STATUS_ERROR;148	}149 150	/* DCDC1 and DCDC2 can additionally detect high voltage/current */151	if (rdev_get_id(rdev) < 2) {152		if (ret & (WM831X_DC1_OV_STS << rdev_get_id(rdev))) {153			dev_dbg(wm831x->dev, "DCDC%d over voltage\n",154				rdev_get_id(rdev) + 1);155			return REGULATOR_STATUS_ERROR;156		}157 158		if (ret & (WM831X_DC1_HC_STS << rdev_get_id(rdev))) {159			dev_dbg(wm831x->dev, "DCDC%d over current\n",160				rdev_get_id(rdev) + 1);161			return REGULATOR_STATUS_ERROR;162		}163	}164 165	/* Is the regulator on? */166	ret = wm831x_reg_read(wm831x, WM831X_DCDC_STATUS);167	if (ret < 0)168		return ret;169	if (!(ret & (1 << rdev_get_id(rdev))))170		return REGULATOR_STATUS_OFF;171 172	/* TODO: When we handle hardware control modes so we can report the173	 * current mode. */174	return REGULATOR_STATUS_ON;175}176 177static irqreturn_t wm831x_dcdc_uv_irq(int irq, void *data)178{179	struct wm831x_dcdc *dcdc = data;180 181	regulator_notifier_call_chain(dcdc->regulator,182				      REGULATOR_EVENT_UNDER_VOLTAGE,183				      NULL);184 185	return IRQ_HANDLED;186}187 188static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data)189{190	struct wm831x_dcdc *dcdc = data;191 192	regulator_notifier_call_chain(dcdc->regulator,193				      REGULATOR_EVENT_OVER_CURRENT,194				      NULL);195 196	return IRQ_HANDLED;197}198 199/*200 * BUCKV specifics201 */202 203static const struct linear_range wm831x_buckv_ranges[] = {204	REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),205	REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),206};207 208static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)209{210	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);211 212	if (state == dcdc->dvs_gpio_state)213		return 0;214 215	dcdc->dvs_gpio_state = state;216	gpiod_set_value(dcdc->dvs_gpiod, state);217 218	/* Should wait for DVS state change to be asserted if we have219	 * a GPIO for it, for now assume the device is configured220	 * for the fastest possible transition.221	 */222 223	return 0;224}225 226static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,227					unsigned vsel)228{229	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);230	struct wm831x *wm831x = dcdc->wm831x;231	int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;232	int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;233	int ret;234 235	/* If this value is already set then do a GPIO update if we can */236	if (dcdc->dvs_gpiod && dcdc->on_vsel == vsel)237		return wm831x_buckv_set_dvs(rdev, 0);238 239	if (dcdc->dvs_gpiod && dcdc->dvs_vsel == vsel)240		return wm831x_buckv_set_dvs(rdev, 1);241 242	/* Always set the ON status to the minimum voltage */243	ret = wm831x_set_bits(wm831x, on_reg, WM831X_DC1_ON_VSEL_MASK, vsel);244	if (ret < 0)245		return ret;246	dcdc->on_vsel = vsel;247 248	if (!dcdc->dvs_gpiod)249		return ret;250 251	/* Kick the voltage transition now */252	ret = wm831x_buckv_set_dvs(rdev, 0);253	if (ret < 0)254		return ret;255 256	/*257	 * If this VSEL is higher than the last one we've seen then258	 * remember it as the DVS VSEL.  This is optimised for CPUfreq259	 * usage where we want to get to the highest voltage very260	 * quickly.261	 */262	if (vsel > dcdc->dvs_vsel) {263		ret = wm831x_set_bits(wm831x, dvs_reg,264				      WM831X_DC1_DVS_VSEL_MASK,265				      vsel);266		if (ret == 0)267			dcdc->dvs_vsel = vsel;268		else269			dev_warn(wm831x->dev,270				 "Failed to set DCDC DVS VSEL: %d\n", ret);271	}272 273	return 0;274}275 276static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,277					    int uV)278{279	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);280	struct wm831x *wm831x = dcdc->wm831x;281	u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;282	int vsel;283 284	vsel = regulator_map_voltage_linear_range(rdev, uV, uV);285	if (vsel < 0)286		return vsel;287 288	return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel);289}290 291static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)292{293	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);294 295	if (dcdc->dvs_gpiod && dcdc->dvs_gpio_state)296		return dcdc->dvs_vsel;297	else298		return dcdc->on_vsel;299}300 301/* Current limit options */302static const unsigned int wm831x_dcdc_ilim[] = {303	125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000304};305 306static const struct regulator_ops wm831x_buckv_ops = {307	.set_voltage_sel = wm831x_buckv_set_voltage_sel,308	.get_voltage_sel = wm831x_buckv_get_voltage_sel,309	.list_voltage = regulator_list_voltage_linear_range,310	.map_voltage = regulator_map_voltage_linear_range,311	.set_suspend_voltage = wm831x_buckv_set_suspend_voltage,312	.set_current_limit = regulator_set_current_limit_regmap,313	.get_current_limit = regulator_get_current_limit_regmap,314 315	.is_enabled = regulator_is_enabled_regmap,316	.enable = regulator_enable_regmap,317	.disable = regulator_disable_regmap,318	.get_status = wm831x_dcdc_get_status,319	.get_mode = wm831x_dcdc_get_mode,320	.set_mode = wm831x_dcdc_set_mode,321	.set_suspend_mode = wm831x_dcdc_set_suspend_mode,322};323 324/*325 * Set up DVS control.  We just log errors since we can still run326 * (with reduced performance) if we fail.327 */328static void wm831x_buckv_dvs_init(struct platform_device *pdev,329				  struct wm831x_dcdc *dcdc,330				  struct wm831x_buckv_pdata *pdata)331{332	struct wm831x *wm831x = dcdc->wm831x;333	int ret;334	u16 ctrl;335 336	if (!pdata)337		return;338 339	/* gpiolib won't let us read the GPIO status so pick the higher340	 * of the two existing voltages so we take it as platform data.341	 */342	dcdc->dvs_gpio_state = pdata->dvs_init_state;343 344	dcdc->dvs_gpiod = devm_gpiod_get(&pdev->dev, "dvs",345			dcdc->dvs_gpio_state ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);346	if (IS_ERR(dcdc->dvs_gpiod)) {347		dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %ld\n",348			dcdc->name, PTR_ERR(dcdc->dvs_gpiod));349		return;350	}351 352	switch (pdata->dvs_control_src) {353	case 1:354		ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;355		break;356	case 2:357		ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;358		break;359	default:360		dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",361			pdata->dvs_control_src, dcdc->name);362		return;363	}364 365	/* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL366	 * to make bootstrapping a bit smoother.367	 */368	if (!dcdc->dvs_vsel) {369		ret = wm831x_set_bits(wm831x,370				      dcdc->base + WM831X_DCDC_DVS_CONTROL,371				      WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel);372		if (ret == 0)373			dcdc->dvs_vsel = dcdc->on_vsel;374		else375			dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n",376				 ret);377	}378 379	ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,380			      WM831X_DC1_DVS_SRC_MASK, ctrl);381	if (ret < 0) {382		dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",383			dcdc->name, ret);384	}385}386 387static int wm831x_buckv_probe(struct platform_device *pdev)388{389	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);390	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);391	struct regulator_config config = { };392	int id;393	struct wm831x_dcdc *dcdc;394	struct resource *res;395	int ret, irq;396 397	if (pdata && pdata->wm831x_num)398		id = (pdata->wm831x_num * 10) + 1;399	else400		id = 0;401	id = pdev->id - id;402 403	dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);404 405	dcdc = devm_kzalloc(&pdev->dev,  sizeof(struct wm831x_dcdc),406			    GFP_KERNEL);407	if (!dcdc)408		return -ENOMEM;409 410	dcdc->wm831x = wm831x;411 412	res = platform_get_resource(pdev, IORESOURCE_REG, 0);413	if (res == NULL) {414		dev_err(&pdev->dev, "No REG resource\n");415		ret = -EINVAL;416		goto err;417	}418	dcdc->base = res->start;419 420	snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);421	dcdc->desc.name = dcdc->name;422 423	snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),424		 "DC%dVDD", id + 1);425	dcdc->desc.supply_name = dcdc->supply_name;426 427	dcdc->desc.id = id;428	dcdc->desc.type = REGULATOR_VOLTAGE;429	dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1;430	dcdc->desc.linear_ranges = wm831x_buckv_ranges;431	dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges);432	dcdc->desc.ops = &wm831x_buckv_ops;433	dcdc->desc.owner = THIS_MODULE;434	dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;435	dcdc->desc.enable_mask = 1 << id;436	dcdc->desc.csel_reg = dcdc->base + WM831X_DCDC_CONTROL_2;437	dcdc->desc.csel_mask = WM831X_DC1_HC_THR_MASK;438	dcdc->desc.n_current_limits = ARRAY_SIZE(wm831x_dcdc_ilim);439	dcdc->desc.curr_table = wm831x_dcdc_ilim;440 441	ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);442	if (ret < 0) {443		dev_err(wm831x->dev, "Failed to read ON VSEL: %d\n", ret);444		goto err;445	}446	dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;447 448	ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL);449	if (ret < 0) {450		dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);451		goto err;452	}453	dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;454 455	if (pdata && pdata->dcdc[id])456		wm831x_buckv_dvs_init(pdev, dcdc,457				      pdata->dcdc[id]->driver_data);458 459	config.dev = pdev->dev.parent;460	if (pdata)461		config.init_data = pdata->dcdc[id];462	config.driver_data = dcdc;463	config.regmap = wm831x->regmap;464 465	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,466						  &config);467	if (IS_ERR(dcdc->regulator)) {468		ret = PTR_ERR(dcdc->regulator);469		dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",470			id + 1, ret);471		goto err;472	}473 474	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));475	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,476					wm831x_dcdc_uv_irq,477					IRQF_TRIGGER_RISING | IRQF_ONESHOT,478					dcdc->name, dcdc);479	if (ret != 0) {480		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",481			irq, ret);482		goto err;483	}484 485	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));486	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,487					wm831x_dcdc_oc_irq,488					IRQF_TRIGGER_RISING | IRQF_ONESHOT,489					dcdc->name, dcdc);490	if (ret != 0) {491		dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",492			irq, ret);493		goto err;494	}495 496	platform_set_drvdata(pdev, dcdc);497 498	return 0;499 500err:501	return ret;502}503 504static struct platform_driver wm831x_buckv_driver = {505	.probe = wm831x_buckv_probe,506	.driver		= {507		.name	= "wm831x-buckv",508		.probe_type = PROBE_PREFER_ASYNCHRONOUS,509	},510};511 512/*513 * BUCKP specifics514 */515 516static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)517{518	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);519	struct wm831x *wm831x = dcdc->wm831x;520	u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;521	int sel;522 523	sel = regulator_map_voltage_linear(rdev, uV, uV);524	if (sel < 0)525		return sel;526 527	return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);528}529 530static const struct regulator_ops wm831x_buckp_ops = {531	.set_voltage_sel = regulator_set_voltage_sel_regmap,532	.get_voltage_sel = regulator_get_voltage_sel_regmap,533	.list_voltage = regulator_list_voltage_linear,534	.map_voltage = regulator_map_voltage_linear,535	.set_suspend_voltage = wm831x_buckp_set_suspend_voltage,536 537	.is_enabled = regulator_is_enabled_regmap,538	.enable = regulator_enable_regmap,539	.disable = regulator_disable_regmap,540	.get_status = wm831x_dcdc_get_status,541	.get_mode = wm831x_dcdc_get_mode,542	.set_mode = wm831x_dcdc_set_mode,543	.set_suspend_mode = wm831x_dcdc_set_suspend_mode,544};545 546static int wm831x_buckp_probe(struct platform_device *pdev)547{548	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);549	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);550	struct regulator_config config = { };551	int id;552	struct wm831x_dcdc *dcdc;553	struct resource *res;554	int ret, irq;555 556	if (pdata && pdata->wm831x_num)557		id = (pdata->wm831x_num * 10) + 1;558	else559		id = 0;560	id = pdev->id - id;561 562	dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);563 564	dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),565			    GFP_KERNEL);566	if (!dcdc)567		return -ENOMEM;568 569	dcdc->wm831x = wm831x;570 571	res = platform_get_resource(pdev, IORESOURCE_REG, 0);572	if (res == NULL) {573		dev_err(&pdev->dev, "No REG resource\n");574		ret = -EINVAL;575		goto err;576	}577	dcdc->base = res->start;578 579	snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);580	dcdc->desc.name = dcdc->name;581 582	snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),583		 "DC%dVDD", id + 1);584	dcdc->desc.supply_name = dcdc->supply_name;585 586	dcdc->desc.id = id;587	dcdc->desc.type = REGULATOR_VOLTAGE;588	dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1;589	dcdc->desc.ops = &wm831x_buckp_ops;590	dcdc->desc.owner = THIS_MODULE;591	dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;592	dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;593	dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;594	dcdc->desc.enable_mask = 1 << id;595	dcdc->desc.min_uV = 850000;596	dcdc->desc.uV_step = 25000;597 598	config.dev = pdev->dev.parent;599	if (pdata)600		config.init_data = pdata->dcdc[id];601	config.driver_data = dcdc;602	config.regmap = wm831x->regmap;603 604	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,605						  &config);606	if (IS_ERR(dcdc->regulator)) {607		ret = PTR_ERR(dcdc->regulator);608		dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",609			id + 1, ret);610		goto err;611	}612 613	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));614	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,615					wm831x_dcdc_uv_irq,616					IRQF_TRIGGER_RISING | IRQF_ONESHOT,617					dcdc->name, dcdc);618	if (ret != 0) {619		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",620			irq, ret);621		goto err;622	}623 624	platform_set_drvdata(pdev, dcdc);625 626	return 0;627 628err:629	return ret;630}631 632static struct platform_driver wm831x_buckp_driver = {633	.probe = wm831x_buckp_probe,634	.driver		= {635		.name	= "wm831x-buckp",636		.probe_type = PROBE_PREFER_ASYNCHRONOUS,637	},638};639 640/*641 * DCDC boost convertors642 */643 644static int wm831x_boostp_get_status(struct regulator_dev *rdev)645{646	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);647	struct wm831x *wm831x = dcdc->wm831x;648	int ret;649 650	/* First, check for errors */651	ret = wm831x_reg_read(wm831x, WM831X_DCDC_UV_STATUS);652	if (ret < 0)653		return ret;654 655	if (ret & (1 << rdev_get_id(rdev))) {656		dev_dbg(wm831x->dev, "DCDC%d under voltage\n",657			rdev_get_id(rdev) + 1);658		return REGULATOR_STATUS_ERROR;659	}660 661	/* Is the regulator on? */662	ret = wm831x_reg_read(wm831x, WM831X_DCDC_STATUS);663	if (ret < 0)664		return ret;665	if (ret & (1 << rdev_get_id(rdev)))666		return REGULATOR_STATUS_ON;667	else668		return REGULATOR_STATUS_OFF;669}670 671static const struct regulator_ops wm831x_boostp_ops = {672	.get_status = wm831x_boostp_get_status,673 674	.is_enabled = regulator_is_enabled_regmap,675	.enable = regulator_enable_regmap,676	.disable = regulator_disable_regmap,677};678 679static int wm831x_boostp_probe(struct platform_device *pdev)680{681	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);682	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);683	struct regulator_config config = { };684	int id = pdev->id % ARRAY_SIZE(pdata->dcdc);685	struct wm831x_dcdc *dcdc;686	struct resource *res;687	int ret, irq;688 689	dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);690 691	if (pdata == NULL || pdata->dcdc[id] == NULL)692		return -ENODEV;693 694	dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);695	if (!dcdc)696		return -ENOMEM;697 698	dcdc->wm831x = wm831x;699 700	res = platform_get_resource(pdev, IORESOURCE_REG, 0);701	if (res == NULL) {702		dev_err(&pdev->dev, "No REG resource\n");703		return -EINVAL;704	}705	dcdc->base = res->start;706 707	snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);708	dcdc->desc.name = dcdc->name;709	dcdc->desc.id = id;710	dcdc->desc.type = REGULATOR_VOLTAGE;711	dcdc->desc.ops = &wm831x_boostp_ops;712	dcdc->desc.owner = THIS_MODULE;713	dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;714	dcdc->desc.enable_mask = 1 << id;715 716	config.dev = pdev->dev.parent;717	if (pdata)718		config.init_data = pdata->dcdc[id];719	config.driver_data = dcdc;720	config.regmap = wm831x->regmap;721 722	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,723						  &config);724	if (IS_ERR(dcdc->regulator)) {725		ret = PTR_ERR(dcdc->regulator);726		dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",727			id + 1, ret);728		return ret;729	}730 731	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));732	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,733					wm831x_dcdc_uv_irq,734					IRQF_TRIGGER_RISING | IRQF_ONESHOT,735					dcdc->name,736					dcdc);737	if (ret != 0) {738		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",739			irq, ret);740		return ret;741	}742 743	platform_set_drvdata(pdev, dcdc);744 745	return 0;746}747 748static struct platform_driver wm831x_boostp_driver = {749	.probe = wm831x_boostp_probe,750	.driver		= {751		.name	= "wm831x-boostp",752		.probe_type = PROBE_PREFER_ASYNCHRONOUS,753	},754};755 756/*757 * External Power Enable758 *759 * These aren't actually DCDCs but look like them in hardware so share760 * code.761 */762 763#define WM831X_EPE_BASE 6764 765static const struct regulator_ops wm831x_epe_ops = {766	.is_enabled = regulator_is_enabled_regmap,767	.enable = regulator_enable_regmap,768	.disable = regulator_disable_regmap,769	.get_status = wm831x_dcdc_get_status,770};771 772static int wm831x_epe_probe(struct platform_device *pdev)773{774	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);775	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);776	struct regulator_config config = { };777	int id = pdev->id % ARRAY_SIZE(pdata->epe);778	struct wm831x_dcdc *dcdc;779	int ret;780 781	dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1);782 783	dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);784	if (!dcdc)785		return -ENOMEM;786 787	dcdc->wm831x = wm831x;788 789	/* For current parts this is correct; probably need to revisit790	 * in future.791	 */792	snprintf(dcdc->name, sizeof(dcdc->name), "EPE%d", id + 1);793	dcdc->desc.name = dcdc->name;794	dcdc->desc.id = id + WM831X_EPE_BASE; /* Offset in DCDC registers */795	dcdc->desc.ops = &wm831x_epe_ops;796	dcdc->desc.type = REGULATOR_VOLTAGE;797	dcdc->desc.owner = THIS_MODULE;798	dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;799	dcdc->desc.enable_mask = 1 << dcdc->desc.id;800 801	config.dev = pdev->dev.parent;802	if (pdata)803		config.init_data = pdata->epe[id];804	config.driver_data = dcdc;805	config.regmap = wm831x->regmap;806 807	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,808						  &config);809	if (IS_ERR(dcdc->regulator)) {810		ret = PTR_ERR(dcdc->regulator);811		dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",812			id + 1, ret);813		goto err;814	}815 816	platform_set_drvdata(pdev, dcdc);817 818	return 0;819 820err:821	return ret;822}823 824static struct platform_driver wm831x_epe_driver = {825	.probe = wm831x_epe_probe,826	.driver		= {827		.name	= "wm831x-epe",828		.probe_type = PROBE_PREFER_ASYNCHRONOUS,829	},830};831 832static struct platform_driver * const drivers[] = {833	&wm831x_buckv_driver,834	&wm831x_buckp_driver,835	&wm831x_boostp_driver,836	&wm831x_epe_driver,837};838 839static int __init wm831x_dcdc_init(void)840{841	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));842}843subsys_initcall(wm831x_dcdc_init);844 845static void __exit wm831x_dcdc_exit(void)846{847	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));848}849module_exit(wm831x_dcdc_exit);850 851/* Module information */852MODULE_AUTHOR("Mark Brown");853MODULE_DESCRIPTION("WM831x DC-DC convertor driver");854MODULE_LICENSE("GPL");855MODULE_ALIAS("platform:wm831x-buckv");856MODULE_ALIAS("platform:wm831x-buckp");857MODULE_ALIAS("platform:wm831x-boostp");858MODULE_ALIAS("platform:wm831x-epe");859