brintos

brintos / linux-shallow public Read only

0
0
Text · 16.5 KiB · 76b89b1 Raw
679 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// wm831x-ldo.c  --  LDO 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/slab.h>18 19#include <linux/mfd/wm831x/core.h>20#include <linux/mfd/wm831x/regulator.h>21#include <linux/mfd/wm831x/pdata.h>22 23#define WM831X_LDO_MAX_NAME 924 25#define WM831X_LDO_CONTROL       026#define WM831X_LDO_ON_CONTROL    127#define WM831X_LDO_SLEEP_CONTROL 228 29#define WM831X_ALIVE_LDO_ON_CONTROL    030#define WM831X_ALIVE_LDO_SLEEP_CONTROL 131 32struct wm831x_ldo {33	char name[WM831X_LDO_MAX_NAME];34	char supply_name[WM831X_LDO_MAX_NAME];35	struct regulator_desc desc;36	int base;37	struct wm831x *wm831x;38	struct regulator_dev *regulator;39};40 41/*42 * Shared43 */44 45static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)46{47	struct wm831x_ldo *ldo = data;48 49	regulator_notifier_call_chain(ldo->regulator,50				      REGULATOR_EVENT_UNDER_VOLTAGE,51				      NULL);52 53	return IRQ_HANDLED;54}55 56/*57 * General purpose LDOs58 */59 60static const struct linear_range wm831x_gp_ldo_ranges[] = {61	REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),62	REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),63};64 65static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,66					     int uV)67{68	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);69	struct wm831x *wm831x = ldo->wm831x;70	int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;71 72	sel = regulator_map_voltage_linear_range(rdev, uV, uV);73	if (sel < 0)74		return sel;75 76	return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, sel);77}78 79static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)80{81	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);82	struct wm831x *wm831x = ldo->wm831x;83	int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;84	int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;85	int ret;86 87	ret = wm831x_reg_read(wm831x, on_reg);88	if (ret < 0)89		return ret;90 91	if (!(ret & WM831X_LDO1_ON_MODE))92		return REGULATOR_MODE_NORMAL;93 94	ret = wm831x_reg_read(wm831x, ctrl_reg);95	if (ret < 0)96		return ret;97 98	if (ret & WM831X_LDO1_LP_MODE)99		return REGULATOR_MODE_STANDBY;100	else101		return REGULATOR_MODE_IDLE;102}103 104static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,105				  unsigned int mode)106{107	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);108	struct wm831x *wm831x = ldo->wm831x;109	int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;110	int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;111	int ret;112 113 114	switch (mode) {115	case REGULATOR_MODE_NORMAL:116		ret = wm831x_set_bits(wm831x, on_reg,117				      WM831X_LDO1_ON_MODE, 0);118		if (ret < 0)119			return ret;120		break;121 122	case REGULATOR_MODE_IDLE:123		ret = wm831x_set_bits(wm831x, ctrl_reg,124				      WM831X_LDO1_LP_MODE, 0);125		if (ret < 0)126			return ret;127 128		ret = wm831x_set_bits(wm831x, on_reg,129				      WM831X_LDO1_ON_MODE,130				      WM831X_LDO1_ON_MODE);131		if (ret < 0)132			return ret;133		break;134 135	case REGULATOR_MODE_STANDBY:136		ret = wm831x_set_bits(wm831x, ctrl_reg,137				      WM831X_LDO1_LP_MODE,138				      WM831X_LDO1_LP_MODE);139		if (ret < 0)140			return ret;141 142		ret = wm831x_set_bits(wm831x, on_reg,143				      WM831X_LDO1_ON_MODE,144				      WM831X_LDO1_ON_MODE);145		if (ret < 0)146			return ret;147		break;148 149	default:150		return -EINVAL;151	}152 153	return 0;154}155 156static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev)157{158	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);159	struct wm831x *wm831x = ldo->wm831x;160	int mask = 1 << rdev_get_id(rdev);161	int ret;162 163	/* Is the regulator on? */164	ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);165	if (ret < 0)166		return ret;167	if (!(ret & mask))168		return REGULATOR_STATUS_OFF;169 170	/* Is it reporting under voltage? */171	ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);172	if (ret < 0)173		return ret;174	if (ret & mask)175		return REGULATOR_STATUS_ERROR;176 177	ret = wm831x_gp_ldo_get_mode(rdev);178	if (ret < 0)179		return ret;180	else181		return regulator_mode_to_status(ret);182}183 184static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,185						   int input_uV,186						   int output_uV, int load_uA)187{188	if (load_uA < 20000)189		return REGULATOR_MODE_STANDBY;190	if (load_uA < 50000)191		return REGULATOR_MODE_IDLE;192	return REGULATOR_MODE_NORMAL;193}194 195 196static const struct regulator_ops wm831x_gp_ldo_ops = {197	.list_voltage = regulator_list_voltage_linear_range,198	.map_voltage = regulator_map_voltage_linear_range,199	.get_voltage_sel = regulator_get_voltage_sel_regmap,200	.set_voltage_sel = regulator_set_voltage_sel_regmap,201	.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,202	.get_mode = wm831x_gp_ldo_get_mode,203	.set_mode = wm831x_gp_ldo_set_mode,204	.get_status = wm831x_gp_ldo_get_status,205	.get_optimum_mode = wm831x_gp_ldo_get_optimum_mode,206	.get_bypass = regulator_get_bypass_regmap,207	.set_bypass = regulator_set_bypass_regmap,208 209	.is_enabled = regulator_is_enabled_regmap,210	.enable = regulator_enable_regmap,211	.disable = regulator_disable_regmap,212};213 214static int wm831x_gp_ldo_probe(struct platform_device *pdev)215{216	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);217	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);218	struct regulator_config config = { };219	int id;220	struct wm831x_ldo *ldo;221	struct resource *res;222	int ret, irq;223 224	if (pdata && pdata->wm831x_num)225		id = (pdata->wm831x_num * 10) + 1;226	else227		id = 0;228	id = pdev->id - id;229 230	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);231 232	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);233	if (!ldo)234		return -ENOMEM;235 236	ldo->wm831x = wm831x;237 238	res = platform_get_resource(pdev, IORESOURCE_REG, 0);239	if (res == NULL) {240		dev_err(&pdev->dev, "No REG resource\n");241		ret = -EINVAL;242		goto err;243	}244	ldo->base = res->start;245 246	snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);247	ldo->desc.name = ldo->name;248 249	snprintf(ldo->supply_name, sizeof(ldo->supply_name),250		 "LDO%dVDD", id + 1);251	ldo->desc.supply_name = ldo->supply_name;252 253	ldo->desc.id = id;254	ldo->desc.type = REGULATOR_VOLTAGE;255	ldo->desc.n_voltages = 32;256	ldo->desc.ops = &wm831x_gp_ldo_ops;257	ldo->desc.owner = THIS_MODULE;258	ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;259	ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK;260	ldo->desc.enable_reg = WM831X_LDO_ENABLE;261	ldo->desc.enable_mask = 1 << id;262	ldo->desc.bypass_reg = ldo->base;263	ldo->desc.bypass_mask = WM831X_LDO1_SWI;264	ldo->desc.linear_ranges = wm831x_gp_ldo_ranges;265	ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges);266 267	config.dev = pdev->dev.parent;268	if (pdata)269		config.init_data = pdata->ldo[id];270	config.driver_data = ldo;271	config.regmap = wm831x->regmap;272 273	ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,274						 &config);275	if (IS_ERR(ldo->regulator)) {276		ret = PTR_ERR(ldo->regulator);277		dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",278			id + 1, ret);279		goto err;280	}281 282	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));283	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,284					wm831x_ldo_uv_irq,285					IRQF_TRIGGER_RISING | IRQF_ONESHOT,286					ldo->name,287					ldo);288	if (ret != 0) {289		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",290			irq, ret);291		goto err;292	}293 294	platform_set_drvdata(pdev, ldo);295 296	return 0;297 298err:299	return ret;300}301 302static struct platform_driver wm831x_gp_ldo_driver = {303	.probe = wm831x_gp_ldo_probe,304	.driver		= {305		.name	= "wm831x-ldo",306		.probe_type = PROBE_PREFER_ASYNCHRONOUS,307	},308};309 310/*311 * Analogue LDOs312 */313 314static const struct linear_range wm831x_aldo_ranges[] = {315	REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),316	REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),317};318 319static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,320					     int uV)321{322	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);323	struct wm831x *wm831x = ldo->wm831x;324	int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;325 326	sel = regulator_map_voltage_linear_range(rdev, uV, uV);327	if (sel < 0)328		return sel;329 330	return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, sel);331}332 333static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)334{335	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);336	struct wm831x *wm831x = ldo->wm831x;337	int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;338	int ret;339 340	ret = wm831x_reg_read(wm831x, on_reg);341	if (ret < 0)342		return 0;343 344	if (ret & WM831X_LDO7_ON_MODE)345		return REGULATOR_MODE_IDLE;346	else347		return REGULATOR_MODE_NORMAL;348}349 350static int wm831x_aldo_set_mode(struct regulator_dev *rdev,351				  unsigned int mode)352{353	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);354	struct wm831x *wm831x = ldo->wm831x;355	int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;356	int ret;357 358 359	switch (mode) {360	case REGULATOR_MODE_NORMAL:361		ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, 0);362		if (ret < 0)363			return ret;364		break;365 366	case REGULATOR_MODE_IDLE:367		ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE,368				      WM831X_LDO7_ON_MODE);369		if (ret < 0)370			return ret;371		break;372 373	default:374		return -EINVAL;375	}376 377	return 0;378}379 380static int wm831x_aldo_get_status(struct regulator_dev *rdev)381{382	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);383	struct wm831x *wm831x = ldo->wm831x;384	int mask = 1 << rdev_get_id(rdev);385	int ret;386 387	/* Is the regulator on? */388	ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);389	if (ret < 0)390		return ret;391	if (!(ret & mask))392		return REGULATOR_STATUS_OFF;393 394	/* Is it reporting under voltage? */395	ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);396	if (ret < 0)397		return ret;398	if (ret & mask)399		return REGULATOR_STATUS_ERROR;400 401	ret = wm831x_aldo_get_mode(rdev);402	if (ret < 0)403		return ret;404	else405		return regulator_mode_to_status(ret);406}407 408static const struct regulator_ops wm831x_aldo_ops = {409	.list_voltage = regulator_list_voltage_linear_range,410	.map_voltage = regulator_map_voltage_linear_range,411	.get_voltage_sel = regulator_get_voltage_sel_regmap,412	.set_voltage_sel = regulator_set_voltage_sel_regmap,413	.set_suspend_voltage = wm831x_aldo_set_suspend_voltage,414	.get_mode = wm831x_aldo_get_mode,415	.set_mode = wm831x_aldo_set_mode,416	.get_status = wm831x_aldo_get_status,417	.set_bypass = regulator_set_bypass_regmap,418	.get_bypass = regulator_get_bypass_regmap,419 420	.is_enabled = regulator_is_enabled_regmap,421	.enable = regulator_enable_regmap,422	.disable = regulator_disable_regmap,423};424 425static int wm831x_aldo_probe(struct platform_device *pdev)426{427	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);428	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);429	struct regulator_config config = { };430	int id;431	struct wm831x_ldo *ldo;432	struct resource *res;433	int ret, irq;434 435	if (pdata && pdata->wm831x_num)436		id = (pdata->wm831x_num * 10) + 1;437	else438		id = 0;439	id = pdev->id - id;440 441	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);442 443	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);444	if (!ldo)445		return -ENOMEM;446 447	ldo->wm831x = wm831x;448 449	res = platform_get_resource(pdev, IORESOURCE_REG, 0);450	if (res == NULL) {451		dev_err(&pdev->dev, "No REG resource\n");452		ret = -EINVAL;453		goto err;454	}455	ldo->base = res->start;456 457	snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);458	ldo->desc.name = ldo->name;459 460	snprintf(ldo->supply_name, sizeof(ldo->supply_name),461		 "LDO%dVDD", id + 1);462	ldo->desc.supply_name = ldo->supply_name;463 464	ldo->desc.id = id;465	ldo->desc.type = REGULATOR_VOLTAGE;466	ldo->desc.n_voltages = 32;467	ldo->desc.linear_ranges = wm831x_aldo_ranges;468	ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges);469	ldo->desc.ops = &wm831x_aldo_ops;470	ldo->desc.owner = THIS_MODULE;471	ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;472	ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK;473	ldo->desc.enable_reg = WM831X_LDO_ENABLE;474	ldo->desc.enable_mask = 1 << id;475	ldo->desc.bypass_reg = ldo->base;476	ldo->desc.bypass_mask = WM831X_LDO7_SWI;477 478	config.dev = pdev->dev.parent;479	if (pdata)480		config.init_data = pdata->ldo[id];481	config.driver_data = ldo;482	config.regmap = wm831x->regmap;483 484	ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,485						 &config);486	if (IS_ERR(ldo->regulator)) {487		ret = PTR_ERR(ldo->regulator);488		dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",489			id + 1, ret);490		goto err;491	}492 493	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));494	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,495					wm831x_ldo_uv_irq,496					IRQF_TRIGGER_RISING | IRQF_ONESHOT,497					ldo->name, ldo);498	if (ret != 0) {499		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",500			irq, ret);501		goto err;502	}503 504	platform_set_drvdata(pdev, ldo);505 506	return 0;507 508err:509	return ret;510}511 512static struct platform_driver wm831x_aldo_driver = {513	.probe = wm831x_aldo_probe,514	.driver		= {515		.name	= "wm831x-aldo",516		.probe_type = PROBE_PREFER_ASYNCHRONOUS,517	},518};519 520/*521 * Alive LDO522 */523 524#define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf525 526static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,527					     int uV)528{529	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);530	struct wm831x *wm831x = ldo->wm831x;531	int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;532 533	sel = regulator_map_voltage_linear(rdev, uV, uV);534	if (sel < 0)535		return sel;536 537	return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, sel);538}539 540static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)541{542	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);543	struct wm831x *wm831x = ldo->wm831x;544	int mask = 1 << rdev_get_id(rdev);545	int ret;546 547	/* Is the regulator on? */548	ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);549	if (ret < 0)550		return ret;551	if (ret & mask)552		return REGULATOR_STATUS_ON;553	else554		return REGULATOR_STATUS_OFF;555}556 557static const struct regulator_ops wm831x_alive_ldo_ops = {558	.list_voltage = regulator_list_voltage_linear,559	.map_voltage = regulator_map_voltage_linear,560	.get_voltage_sel = regulator_get_voltage_sel_regmap,561	.set_voltage_sel = regulator_set_voltage_sel_regmap,562	.set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,563	.get_status = wm831x_alive_ldo_get_status,564 565	.is_enabled = regulator_is_enabled_regmap,566	.enable = regulator_enable_regmap,567	.disable = regulator_disable_regmap,568};569 570static int wm831x_alive_ldo_probe(struct platform_device *pdev)571{572	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);573	struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);574	struct regulator_config config = { };575	int id;576	struct wm831x_ldo *ldo;577	struct resource *res;578	int ret;579 580	if (pdata && pdata->wm831x_num)581		id = (pdata->wm831x_num * 10) + 1;582	else583		id = 0;584	id = pdev->id - id;585 586 587	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);588 589	ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);590	if (!ldo)591		return -ENOMEM;592 593	ldo->wm831x = wm831x;594 595	res = platform_get_resource(pdev, IORESOURCE_REG, 0);596	if (res == NULL) {597		dev_err(&pdev->dev, "No REG resource\n");598		ret = -EINVAL;599		goto err;600	}601	ldo->base = res->start;602 603	snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);604	ldo->desc.name = ldo->name;605 606	snprintf(ldo->supply_name, sizeof(ldo->supply_name),607		 "LDO%dVDD", id + 1);608	ldo->desc.supply_name = ldo->supply_name;609 610	ldo->desc.id = id;611	ldo->desc.type = REGULATOR_VOLTAGE;612	ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1;613	ldo->desc.ops = &wm831x_alive_ldo_ops;614	ldo->desc.owner = THIS_MODULE;615	ldo->desc.vsel_reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;616	ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK;617	ldo->desc.enable_reg = WM831X_LDO_ENABLE;618	ldo->desc.enable_mask = 1 << id;619	ldo->desc.min_uV = 800000;620	ldo->desc.uV_step = 50000;621	ldo->desc.enable_time = 1000;622 623	config.dev = pdev->dev.parent;624	if (pdata)625		config.init_data = pdata->ldo[id];626	config.driver_data = ldo;627	config.regmap = wm831x->regmap;628 629	ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,630						 &config);631	if (IS_ERR(ldo->regulator)) {632		ret = PTR_ERR(ldo->regulator);633		dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",634			id + 1, ret);635		goto err;636	}637 638	platform_set_drvdata(pdev, ldo);639 640	return 0;641 642err:643	return ret;644}645 646static struct platform_driver wm831x_alive_ldo_driver = {647	.probe = wm831x_alive_ldo_probe,648	.driver		= {649		.name	= "wm831x-alive-ldo",650		.probe_type = PROBE_PREFER_ASYNCHRONOUS,651	},652};653 654static struct platform_driver * const drivers[] = {655	&wm831x_gp_ldo_driver,656	&wm831x_aldo_driver,657	&wm831x_alive_ldo_driver,658};659 660static int __init wm831x_ldo_init(void)661{662	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));663}664subsys_initcall(wm831x_ldo_init);665 666static void __exit wm831x_ldo_exit(void)667{668	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));669}670module_exit(wm831x_ldo_exit);671 672/* Module information */673MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");674MODULE_DESCRIPTION("WM831x LDO driver");675MODULE_LICENSE("GPL");676MODULE_ALIAS("platform:wm831x-ldo");677MODULE_ALIAS("platform:wm831x-aldo");678MODULE_ALIAS("platform:wm831x-aliveldo");679