brintos

brintos / linux-shallow public Read only

0
0
Text · 13.2 KiB · ede1709 Raw
530 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * max8660.c  --  Voltage regulation for the Maxim 8660/86614 *5 * based on max1586.c and wm8400-regulator.c6 *7 * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.8 *9 * Some info:10 *11 * Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8660-MAX8661.pdf12 *13 * This chip is a bit nasty because it is a write-only device. Thus, the driver14 * uses shadow registers to keep track of its values. The main problem appears15 * to be the initialization: When Linux boots up, we cannot know if the chip is16 * in the default state or not, so we would have to pass such information in17 * platform_data. As this adds a bit of complexity to the driver, this is left18 * out for now until it is really needed.19 *20 * [A|S|M]DTV1 registers are currently not used, but [A|S|M]DTV2.21 *22 * If the driver is feature complete, it might be worth to check if one set of23 * functions for V3-V7 is sufficient. For maximum flexibility during24 * development, they are separated for now.25 */26 27#include <linux/module.h>28#include <linux/err.h>29#include <linux/i2c.h>30#include <linux/platform_device.h>31#include <linux/regulator/driver.h>32#include <linux/slab.h>33#include <linux/regulator/max8660.h>34#include <linux/of.h>35#include <linux/of_device.h>36#include <linux/regulator/of_regulator.h>37 38#define MAX8660_DCDC_MIN_UV	 72500039#define MAX8660_DCDC_MAX_UV	180000040#define MAX8660_DCDC_STEP	  2500041#define MAX8660_DCDC_MAX_SEL	0x2b42 43#define MAX8660_LDO5_MIN_UV	170000044#define MAX8660_LDO5_MAX_UV	200000045#define MAX8660_LDO5_STEP	  2500046#define MAX8660_LDO5_MAX_SEL	0x0c47 48#define MAX8660_LDO67_MIN_UV	180000049#define MAX8660_LDO67_MAX_UV	330000050#define MAX8660_LDO67_STEP	 10000051#define MAX8660_LDO67_MAX_SEL	0x0f52 53enum {54	MAX8660_OVER1,55	MAX8660_OVER2,56	MAX8660_VCC1,57	MAX8660_ADTV1,58	MAX8660_ADTV2,59	MAX8660_SDTV1,60	MAX8660_SDTV2,61	MAX8660_MDTV1,62	MAX8660_MDTV2,63	MAX8660_L12VCR,64	MAX8660_FPWM,65	MAX8660_N_REGS,	/* not a real register */66};67 68struct max8660 {69	struct i2c_client *client;70	u8 shadow_regs[MAX8660_N_REGS];		/* as chip is write only */71};72 73static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val)74{75	static const u8 max8660_addresses[MAX8660_N_REGS] = {76	 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x8077	};78 79	int ret;80	u8 reg_val = (max8660->shadow_regs[reg] & mask) | val;81 82	dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n",83			max8660_addresses[reg], reg_val);84 85	ret = i2c_smbus_write_byte_data(max8660->client,86			max8660_addresses[reg], reg_val);87	if (ret == 0)88		max8660->shadow_regs[reg] = reg_val;89 90	return ret;91}92 93 94/*95 * DCDC functions96 */97 98static int max8660_dcdc_is_enabled(struct regulator_dev *rdev)99{100	struct max8660 *max8660 = rdev_get_drvdata(rdev);101	u8 val = max8660->shadow_regs[MAX8660_OVER1];102	u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;103 104	return !!(val & mask);105}106 107static int max8660_dcdc_enable(struct regulator_dev *rdev)108{109	struct max8660 *max8660 = rdev_get_drvdata(rdev);110	u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;111 112	return max8660_write(max8660, MAX8660_OVER1, 0xff, bit);113}114 115static int max8660_dcdc_disable(struct regulator_dev *rdev)116{117	struct max8660 *max8660 = rdev_get_drvdata(rdev);118	u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4;119 120	return max8660_write(max8660, MAX8660_OVER1, mask, 0);121}122 123static int max8660_dcdc_get_voltage_sel(struct regulator_dev *rdev)124{125	struct max8660 *max8660 = rdev_get_drvdata(rdev);126	u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;127	u8 selector = max8660->shadow_regs[reg];128 129	return selector;130}131 132static int max8660_dcdc_set_voltage_sel(struct regulator_dev *rdev,133					unsigned int selector)134{135	struct max8660 *max8660 = rdev_get_drvdata(rdev);136	u8 reg, bits;137	int ret;138 139	reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;140	ret = max8660_write(max8660, reg, 0, selector);141	if (ret)142		return ret;143 144	/* Select target voltage register and activate regulation */145	bits = (rdev_get_id(rdev) == MAX8660_V3) ? 0x03 : 0x30;146	return max8660_write(max8660, MAX8660_VCC1, 0xff, bits);147}148 149static struct regulator_ops max8660_dcdc_ops = {150	.is_enabled = max8660_dcdc_is_enabled,151	.list_voltage = regulator_list_voltage_linear,152	.map_voltage = regulator_map_voltage_linear,153	.set_voltage_sel = max8660_dcdc_set_voltage_sel,154	.get_voltage_sel = max8660_dcdc_get_voltage_sel,155};156 157 158/*159 * LDO5 functions160 */161 162static int max8660_ldo5_get_voltage_sel(struct regulator_dev *rdev)163{164	struct max8660 *max8660 = rdev_get_drvdata(rdev);165 166	u8 selector = max8660->shadow_regs[MAX8660_MDTV2];167	return selector;168}169 170static int max8660_ldo5_set_voltage_sel(struct regulator_dev *rdev,171					unsigned int selector)172{173	struct max8660 *max8660 = rdev_get_drvdata(rdev);174	int ret;175 176	ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);177	if (ret)178		return ret;179 180	/* Select target voltage register and activate regulation */181	return max8660_write(max8660, MAX8660_VCC1, 0xff, 0xc0);182}183 184static const struct regulator_ops max8660_ldo5_ops = {185	.list_voltage = regulator_list_voltage_linear,186	.map_voltage = regulator_map_voltage_linear,187	.set_voltage_sel = max8660_ldo5_set_voltage_sel,188	.get_voltage_sel = max8660_ldo5_get_voltage_sel,189};190 191 192/*193 * LDO67 functions194 */195 196static int max8660_ldo67_is_enabled(struct regulator_dev *rdev)197{198	struct max8660 *max8660 = rdev_get_drvdata(rdev);199	u8 val = max8660->shadow_regs[MAX8660_OVER2];200	u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;201 202	return !!(val & mask);203}204 205static int max8660_ldo67_enable(struct regulator_dev *rdev)206{207	struct max8660 *max8660 = rdev_get_drvdata(rdev);208	u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;209 210	return max8660_write(max8660, MAX8660_OVER2, 0xff, bit);211}212 213static int max8660_ldo67_disable(struct regulator_dev *rdev)214{215	struct max8660 *max8660 = rdev_get_drvdata(rdev);216	u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4;217 218	return max8660_write(max8660, MAX8660_OVER2, mask, 0);219}220 221static int max8660_ldo67_get_voltage_sel(struct regulator_dev *rdev)222{223	struct max8660 *max8660 = rdev_get_drvdata(rdev);224	u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4;225	u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf;226 227	return selector;228}229 230static int max8660_ldo67_set_voltage_sel(struct regulator_dev *rdev,231					 unsigned int selector)232{233	struct max8660 *max8660 = rdev_get_drvdata(rdev);234 235	if (rdev_get_id(rdev) == MAX8660_V6)236		return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);237	else238		return max8660_write(max8660, MAX8660_L12VCR, 0x0f,239				     selector << 4);240}241 242static const struct regulator_ops max8660_ldo67_ops = {243	.is_enabled = max8660_ldo67_is_enabled,244	.enable = max8660_ldo67_enable,245	.disable = max8660_ldo67_disable,246	.list_voltage = regulator_list_voltage_linear,247	.map_voltage = regulator_map_voltage_linear,248	.get_voltage_sel = max8660_ldo67_get_voltage_sel,249	.set_voltage_sel = max8660_ldo67_set_voltage_sel,250};251 252static const struct regulator_desc max8660_reg[] = {253	{254		.name = "V3(DCDC)",255		.id = MAX8660_V3,256		.ops = &max8660_dcdc_ops,257		.type = REGULATOR_VOLTAGE,258		.n_voltages = MAX8660_DCDC_MAX_SEL + 1,259		.owner = THIS_MODULE,260		.min_uV = MAX8660_DCDC_MIN_UV,261		.uV_step = MAX8660_DCDC_STEP,262	},263	{264		.name = "V4(DCDC)",265		.id = MAX8660_V4,266		.ops = &max8660_dcdc_ops,267		.type = REGULATOR_VOLTAGE,268		.n_voltages = MAX8660_DCDC_MAX_SEL + 1,269		.owner = THIS_MODULE,270		.min_uV = MAX8660_DCDC_MIN_UV,271		.uV_step = MAX8660_DCDC_STEP,272	},273	{274		.name = "V5(LDO)",275		.id = MAX8660_V5,276		.ops = &max8660_ldo5_ops,277		.type = REGULATOR_VOLTAGE,278		.n_voltages = MAX8660_LDO5_MAX_SEL + 1,279		.owner = THIS_MODULE,280		.min_uV = MAX8660_LDO5_MIN_UV,281		.uV_step = MAX8660_LDO5_STEP,282	},283	{284		.name = "V6(LDO)",285		.id = MAX8660_V6,286		.ops = &max8660_ldo67_ops,287		.type = REGULATOR_VOLTAGE,288		.n_voltages = MAX8660_LDO67_MAX_SEL + 1,289		.owner = THIS_MODULE,290		.min_uV = MAX8660_LDO67_MIN_UV,291		.uV_step = MAX8660_LDO67_STEP,292	},293	{294		.name = "V7(LDO)",295		.id = MAX8660_V7,296		.ops = &max8660_ldo67_ops,297		.type = REGULATOR_VOLTAGE,298		.n_voltages = MAX8660_LDO67_MAX_SEL + 1,299		.owner = THIS_MODULE,300		.min_uV = MAX8660_LDO67_MIN_UV,301		.uV_step = MAX8660_LDO67_STEP,302	},303};304 305enum {306	MAX8660 = 0,307	MAX8661 = 1,308};309 310#ifdef CONFIG_OF311static const struct of_device_id max8660_dt_ids[] = {312	{ .compatible = "maxim,max8660", .data = (void *) MAX8660 },313	{ .compatible = "maxim,max8661", .data = (void *) MAX8661 },314	{ }315};316MODULE_DEVICE_TABLE(of, max8660_dt_ids);317 318static int max8660_pdata_from_dt(struct device *dev,319				 struct device_node **of_node,320				 struct max8660_platform_data *pdata)321{322	int matched, i;323	struct device_node *np;324	struct max8660_subdev_data *sub;325	struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)] = { };326 327	np = of_get_child_by_name(dev->of_node, "regulators");328	if (!np) {329		dev_err(dev, "missing 'regulators' subnode in DT\n");330		return -EINVAL;331	}332 333	for (i = 0; i < ARRAY_SIZE(rmatch); i++)334		rmatch[i].name = max8660_reg[i].name;335 336	matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch));337	of_node_put(np);338	if (matched <= 0)339		return matched;340 341	pdata->subdevs = devm_kcalloc(dev,342				      matched,343				      sizeof(struct max8660_subdev_data),344				      GFP_KERNEL);345	if (!pdata->subdevs)346		return -ENOMEM;347 348	pdata->num_subdevs = matched;349	sub = pdata->subdevs;350 351	for (i = 0; i < matched; i++) {352		sub->id = i;353		sub->name = rmatch[i].name;354		sub->platform_data = rmatch[i].init_data;355		of_node[i] = rmatch[i].of_node;356		sub++;357	}358 359	return 0;360}361#else362static inline int max8660_pdata_from_dt(struct device *dev,363					struct device_node **of_node,364					struct max8660_platform_data *pdata)365{366	return 0;367}368#endif369 370static int max8660_probe(struct i2c_client *client)371{372	const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client);373	struct device *dev = &client->dev;374	struct max8660_platform_data pdata_of, *pdata = dev_get_platdata(dev);375	struct regulator_config config = { };376	struct max8660 *max8660;377	int boot_on, i, id, ret = -EINVAL;378	struct device_node *of_node[MAX8660_V_END];379	unsigned long type;380 381	if (dev->of_node && !pdata) {382		const struct of_device_id *id;383 384		id = of_match_device(of_match_ptr(max8660_dt_ids), dev);385		if (!id)386			return -ENODEV;387 388		ret = max8660_pdata_from_dt(dev, of_node, &pdata_of);389		if (ret < 0)390			return ret;391 392		pdata = &pdata_of;393		type = (unsigned long) id->data;394	} else {395		type = i2c_id->driver_data;396		memset(of_node, 0, sizeof(of_node));397	}398 399	if (pdata->num_subdevs > MAX8660_V_END) {400		dev_err(dev, "Too many regulators found!\n");401		return -EINVAL;402	}403 404	max8660 = devm_kzalloc(dev, sizeof(struct max8660), GFP_KERNEL);405	if (!max8660)406		return -ENOMEM;407 408	max8660->client = client;409 410	if (pdata->en34_is_high) {411		/* Simulate always on */412		max8660->shadow_regs[MAX8660_OVER1] = 5;413	} else {414		/* Otherwise devices can be toggled via software */415		max8660_dcdc_ops.enable = max8660_dcdc_enable;416		max8660_dcdc_ops.disable = max8660_dcdc_disable;417	}418 419	/*420	 * First, set up shadow registers to prevent glitches. As some421	 * registers are shared between regulators, everything must be properly422	 * set up for all regulators in advance.423	 */424	max8660->shadow_regs[MAX8660_ADTV1] =425		max8660->shadow_regs[MAX8660_ADTV2] =426		max8660->shadow_regs[MAX8660_SDTV1] =427		max8660->shadow_regs[MAX8660_SDTV2] = 0x1b;428	max8660->shadow_regs[MAX8660_MDTV1] =429		max8660->shadow_regs[MAX8660_MDTV2] = 0x04;430 431	for (i = 0; i < pdata->num_subdevs; i++) {432 433		if (!pdata->subdevs[i].platform_data)434			boot_on = false;435		else436			boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;437 438		switch (pdata->subdevs[i].id) {439		case MAX8660_V3:440			if (boot_on)441				max8660->shadow_regs[MAX8660_OVER1] |= 1;442			break;443 444		case MAX8660_V4:445			if (boot_on)446				max8660->shadow_regs[MAX8660_OVER1] |= 4;447			break;448 449		case MAX8660_V5:450			break;451 452		case MAX8660_V6:453			if (boot_on)454				max8660->shadow_regs[MAX8660_OVER2] |= 2;455			break;456 457		case MAX8660_V7:458			if (type == MAX8661) {459				dev_err(dev, "Regulator not on this chip!\n");460				return -EINVAL;461			}462 463			if (boot_on)464				max8660->shadow_regs[MAX8660_OVER2] |= 4;465			break;466 467		default:468			dev_err(dev, "invalid regulator %s\n",469				 pdata->subdevs[i].name);470			return ret;471		}472	}473 474	/* Finally register devices */475	for (i = 0; i < pdata->num_subdevs; i++) {476		struct regulator_dev *rdev;477 478		id = pdata->subdevs[i].id;479 480		config.dev = dev;481		config.init_data = pdata->subdevs[i].platform_data;482		config.of_node = of_node[i];483		config.driver_data = max8660;484 485		rdev = devm_regulator_register(&client->dev,486						  &max8660_reg[id], &config);487		if (IS_ERR(rdev)) {488			dev_err(&client->dev, "failed to register %s\n",489				max8660_reg[id].name);490			return PTR_ERR(rdev);491		}492	}493 494	i2c_set_clientdata(client, max8660);495	return 0;496}497 498static const struct i2c_device_id max8660_id[] = {499	{ .name = "max8660", .driver_data = MAX8660 },500	{ .name = "max8661", .driver_data = MAX8661 },501	{ }502};503MODULE_DEVICE_TABLE(i2c, max8660_id);504 505static struct i2c_driver max8660_driver = {506	.probe = max8660_probe,507	.driver		= {508		.name	= "max8660",509		.probe_type = PROBE_PREFER_ASYNCHRONOUS,510	},511	.id_table	= max8660_id,512};513 514static int __init max8660_init(void)515{516	return i2c_add_driver(&max8660_driver);517}518subsys_initcall(max8660_init);519 520static void __exit max8660_exit(void)521{522	i2c_del_driver(&max8660_driver);523}524module_exit(max8660_exit);525 526/* Module information */527MODULE_DESCRIPTION("MAXIM 8660/8661 voltage regulator driver");528MODULE_AUTHOR("Wolfram Sang");529MODULE_LICENSE("GPL v2");530