brintos

brintos / linux-shallow public Read only

0
0
Text · 12.8 KiB · a53ed52 Raw
518 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3#include <dt-bindings/regulator/richtek,rt5190a-regulator.h>4#include <linux/bits.h>5#include <linux/i2c.h>6#include <linux/interrupt.h>7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/of.h>10#include <linux/property.h>11#include <linux/regmap.h>12#include <linux/regulator/driver.h>13#include <linux/regulator/machine.h>14#include <linux/regulator/of_regulator.h>15 16#define RT5190A_REG_MANUFACTURE		0x0017#define RT5190A_REG_BUCK2VSEL		0x0418#define RT5190A_REG_BUCK3VSEL		0x0519#define RT5190A_REG_DCDCCNTL		0x0620#define RT5190A_REG_ENABLE		0x0721#define RT5190A_REG_DISCHARGE		0x0922#define RT5190A_REG_PROTMODE		0x0A23#define RT5190A_REG_MUTECNTL		0x0B24#define RT5190A_REG_PGSTAT		0x0F25#define RT5190A_REG_OVINT		0x1026#define RT5190A_REG_HOTDIEMASK		0x1727 28#define RT5190A_VSEL_MASK		GENMASK(6, 0)29#define RT5190A_RID_BITMASK(rid)	BIT(rid + 1)30#define RT5190A_BUCK1_DISCHG_MASK	GENMASK(1, 0)31#define RT5190A_BUCK1_DISCHG_ONVAL	0x0132#define RT5190A_OVERVOLT_MASK		GENMASK(7, 0)33#define RT5190A_UNDERVOLT_MASK		GENMASK(15, 8)34#define RT5190A_CH234OT_MASK		BIT(29)35#define RT5190A_CHIPOT_MASK		BIT(28)36 37#define RT5190A_BUCK23_MINUV		60000038#define RT5190A_BUCK23_MAXUV		140000039#define RT5190A_BUCK23_STEPUV		1000040#define RT5190A_BUCK23_STEPNUM		((1400000 - 600000) / 10000 + 1)41 42enum {43	RT5190A_IDX_BUCK1 = 0,44	RT5190A_IDX_BUCK2,45	RT5190A_IDX_BUCK3,46	RT5190A_IDX_BUCK4,47	RT5190A_IDX_LDO,48	RT5190A_MAX_IDX49};50 51struct rt5190a_priv {52	struct device *dev;53	struct regmap *regmap;54	struct regulator_desc rdesc[RT5190A_MAX_IDX];55	struct regulator_dev *rdev[RT5190A_MAX_IDX];56};57 58static int rt5190a_get_error_flags(struct regulator_dev *rdev,59				   unsigned int *flags)60{61	struct regmap *regmap = rdev_get_regmap(rdev);62	int rid = rdev_get_id(rdev);63	unsigned int pgood_stat;64	int ret;65 66	ret = regmap_read(regmap, RT5190A_REG_PGSTAT, &pgood_stat);67	if (ret)68		return ret;69 70	if (!(pgood_stat & RT5190A_RID_BITMASK(rid)))71		*flags = REGULATOR_ERROR_FAIL;72	else73		*flags = 0;74 75	return 0;76}77 78static int rt5190a_fixed_buck_set_mode(struct regulator_dev *rdev,79				       unsigned int mode)80{81	struct regmap *regmap = rdev_get_regmap(rdev);82	int rid = rdev_get_id(rdev);83	unsigned int mask = RT5190A_RID_BITMASK(rid), val;84 85	switch (mode) {86	case REGULATOR_MODE_FAST:87		val = mask;88		break;89	case REGULATOR_MODE_NORMAL:90		val = 0;91		break;92	default:93		return -EINVAL;94	}95 96	return regmap_update_bits(regmap, RT5190A_REG_DCDCCNTL, mask, val);97}98 99static unsigned int rt5190a_fixed_buck_get_mode(struct regulator_dev *rdev)100{101	struct regmap *regmap = rdev_get_regmap(rdev);102	int rid = rdev_get_id(rdev);103	unsigned int val;104	int ret;105 106	ret = regmap_read(regmap, RT5190A_REG_DCDCCNTL, &val);107	if (ret) {108		dev_err(&rdev->dev, "Failed to get mode [%d]\n", ret);109		return ret;110	}111 112	if (val & RT5190A_RID_BITMASK(rid))113		return REGULATOR_MODE_FAST;114 115	return REGULATOR_MODE_NORMAL;116}117 118static const struct regulator_ops rt5190a_ranged_buck_ops = {119	.enable	= regulator_enable_regmap,120	.disable = regulator_disable_regmap,121	.is_enabled = regulator_is_enabled_regmap,122	.set_voltage_sel = regulator_set_voltage_sel_regmap,123	.get_voltage_sel = regulator_get_voltage_sel_regmap,124	.list_voltage = regulator_list_voltage_linear,125	.set_active_discharge = regulator_set_active_discharge_regmap,126	.get_error_flags = rt5190a_get_error_flags,127};128 129static const struct regulator_ops rt5190a_fixed_buck_ops = {130	.enable	= regulator_enable_regmap,131	.disable = regulator_disable_regmap,132	.is_enabled = regulator_is_enabled_regmap,133	.set_active_discharge = regulator_set_active_discharge_regmap,134	.set_mode = rt5190a_fixed_buck_set_mode,135	.get_mode = rt5190a_fixed_buck_get_mode,136	.get_error_flags = rt5190a_get_error_flags,137};138 139static const struct regulator_ops rt5190a_fixed_ldo_ops = {140	.enable	= regulator_enable_regmap,141	.disable = regulator_disable_regmap,142	.is_enabled = regulator_is_enabled_regmap,143	.set_active_discharge = regulator_set_active_discharge_regmap,144	.get_error_flags = rt5190a_get_error_flags,145};146 147static irqreturn_t rt5190a_irq_handler(int irq, void *data)148{149	struct rt5190a_priv *priv = data;150	__le32 raws;151	unsigned int events, fields;152	static const struct {153		unsigned int bitmask;154		unsigned int report;155	} event_tbl[] = {156		{ RT5190A_OVERVOLT_MASK, REGULATOR_ERROR_REGULATION_OUT },157		{ RT5190A_UNDERVOLT_MASK, REGULATOR_ERROR_UNDER_VOLTAGE }158	};159	int i, j, ret;160 161	ret = regmap_raw_read(priv->regmap, RT5190A_REG_OVINT, &raws,162			      sizeof(raws));163	if (ret) {164		dev_err(priv->dev, "Failed to read events\n");165		return IRQ_NONE;166	}167 168	events = le32_to_cpu(raws);169 170	ret = regmap_raw_write(priv->regmap, RT5190A_REG_OVINT, &raws,171			       sizeof(raws));172	if (ret)173		dev_err(priv->dev, "Failed to write-clear events\n");174 175	/* Handle OV,UV events */176	for (i = 0; i < ARRAY_SIZE(event_tbl); i++) {177		fields = events & event_tbl[i].bitmask;178		fields >>= ffs(event_tbl[i].bitmask) - 1;179 180		for (j = 0; j < RT5190A_MAX_IDX; j++) {181			if (!(fields & RT5190A_RID_BITMASK(j)))182				continue;183 184			regulator_notifier_call_chain(priv->rdev[j],185						      event_tbl[i].report,186						      NULL);187		}188	}189 190	/* Handle CH234 OT event */191	if (events & RT5190A_CH234OT_MASK) {192		for (j = RT5190A_IDX_BUCK2; j < RT5190A_IDX_LDO; j++) {193			regulator_notifier_call_chain(priv->rdev[j],194						      REGULATOR_ERROR_OVER_TEMP,195						      NULL);196		}197	}198 199	/* Warning if CHIP OT occur */200	if (events & RT5190A_CHIPOT_MASK)201		dev_warn(priv->dev, "CHIP overheat\n");202 203	return IRQ_HANDLED;204}205 206static unsigned int rt5190a_of_map_mode(unsigned int mode)207{208	switch (mode) {209	case RT5190A_OPMODE_AUTO:210		return REGULATOR_MODE_NORMAL;211	case RT5190A_OPMODE_FPWM:212		return REGULATOR_MODE_FAST;213	default:214		return REGULATOR_MODE_INVALID;215	}216}217 218static int rt5190a_of_parse_cb(struct rt5190a_priv *priv, int rid,219			       struct of_regulator_match *match)220{221	struct regulator_desc *desc = priv->rdesc + rid;222	struct regulator_init_data *init_data = match->init_data;223	struct device_node *np = match->of_node;224	bool latchup_enable;225	unsigned int mask = RT5190A_RID_BITMASK(rid), val;226 227	if (!init_data)228		return 0;229 230	switch (rid) {231	case RT5190A_IDX_BUCK1:232	case RT5190A_IDX_BUCK4:233	case RT5190A_IDX_LDO:234		init_data->constraints.apply_uV = 0;235 236		if (init_data->constraints.min_uV ==237				init_data->constraints.max_uV)238			desc->fixed_uV = init_data->constraints.min_uV;239		else {240			dev_err(priv->dev,241				"Variable voltage for fixed regulator\n");242			return -EINVAL;243		}244		break;245	default:246		break;247	}248 249	latchup_enable = of_property_read_bool(np, "richtek,latchup-enable");250 251	/* latchup: 0, default hiccup: 1 */252	val = !latchup_enable ? mask : 0;253 254	return regmap_update_bits(priv->regmap, RT5190A_REG_PROTMODE, mask, val);255}256 257static void rt5190a_fillin_regulator_desc(struct regulator_desc *desc, int rid)258{259	static const char * const regu_name[] = { "buck1", "buck2",260						  "buck3", "buck4",261						  "ldo" };262	static const char * const supply[] = { NULL, "vin2", "vin3", "vin4",263					       "vinldo" };264 265	desc->name = regu_name[rid];266	desc->supply_name = supply[rid];267	desc->owner = THIS_MODULE;268	desc->type = REGULATOR_VOLTAGE;269	desc->id = rid;270	desc->enable_reg = RT5190A_REG_ENABLE;271	desc->enable_mask = RT5190A_RID_BITMASK(rid);272	desc->active_discharge_reg = RT5190A_REG_DISCHARGE;273	desc->active_discharge_mask = RT5190A_RID_BITMASK(rid);274	desc->active_discharge_on = RT5190A_RID_BITMASK(rid);275 276	switch (rid) {277	case RT5190A_IDX_BUCK1:278		desc->active_discharge_mask = RT5190A_BUCK1_DISCHG_MASK;279		desc->active_discharge_on = RT5190A_BUCK1_DISCHG_ONVAL;280		desc->n_voltages = 1;281		desc->ops = &rt5190a_fixed_buck_ops;282		desc->of_map_mode = rt5190a_of_map_mode;283		break;284	case RT5190A_IDX_BUCK2:285		desc->vsel_reg = RT5190A_REG_BUCK2VSEL;286		desc->vsel_mask = RT5190A_VSEL_MASK;287		desc->min_uV = RT5190A_BUCK23_MINUV;288		desc->uV_step = RT5190A_BUCK23_STEPUV;289		desc->n_voltages = RT5190A_BUCK23_STEPNUM;290		desc->ops = &rt5190a_ranged_buck_ops;291		break;292	case RT5190A_IDX_BUCK3:293		desc->vsel_reg = RT5190A_REG_BUCK3VSEL;294		desc->vsel_mask = RT5190A_VSEL_MASK;295		desc->min_uV = RT5190A_BUCK23_MINUV;296		desc->uV_step = RT5190A_BUCK23_STEPUV;297		desc->n_voltages = RT5190A_BUCK23_STEPNUM;298		desc->ops = &rt5190a_ranged_buck_ops;299		break;300	case RT5190A_IDX_BUCK4:301		desc->n_voltages = 1;302		desc->ops = &rt5190a_fixed_buck_ops;303		desc->of_map_mode = rt5190a_of_map_mode;304		break;305	case RT5190A_IDX_LDO:306		desc->n_voltages = 1;307		desc->ops = &rt5190a_fixed_ldo_ops;308		break;309	}310}311 312static struct of_regulator_match rt5190a_regulator_match[] = {313	{ .name = "buck1", },314	{ .name = "buck2", },315	{ .name = "buck3", },316	{ .name = "buck4", },317	{ .name = "ldo", }318};319 320static int rt5190a_parse_regulator_dt_data(struct rt5190a_priv *priv)321{322	struct device_node *regulator_np;323	struct regulator_desc *reg_desc;324	struct of_regulator_match *match;325	int i, ret;326 327	for (i = 0; i < RT5190A_MAX_IDX; i++) {328		reg_desc = priv->rdesc + i;329		match = rt5190a_regulator_match + i;330 331		rt5190a_fillin_regulator_desc(reg_desc, i);332 333		match->desc = reg_desc;334	}335 336	regulator_np = of_get_child_by_name(priv->dev->of_node, "regulators");337	if (!regulator_np) {338		dev_err(priv->dev, "Could not find 'regulators' node\n");339		return -ENODEV;340	}341 342	ret = of_regulator_match(priv->dev, regulator_np,343				 rt5190a_regulator_match,344				 ARRAY_SIZE(rt5190a_regulator_match));345 346	of_node_put(regulator_np);347 348	if (ret < 0) {349		dev_err(priv->dev,350			"Error parsing regulator init data: %d\n", ret);351		return ret;352	}353 354	for (i = 0; i < RT5190A_MAX_IDX; i++) {355		match = rt5190a_regulator_match + i;356 357		ret = rt5190a_of_parse_cb(priv, i, match);358		if (ret) {359			dev_err(priv->dev, "Failed in [%d] of_parse_cb\n", i);360			return ret;361		}362	}363 364	return 0;365}366 367static const struct reg_sequence rt5190a_init_patch[] = {368	{ 0x09, 0x3d, },369	{ 0x0a, 0x3e, },370	{ 0x0b, 0x01, },371	{ 0x10, 0xff, },372	{ 0x11, 0xff, },373	{ 0x12, 0xff, },374	{ 0x13, 0xff, },375	{ 0x14, 0, },376	{ 0x15, 0, },377	{ 0x16, 0x3e, },378	{ 0x17, 0, }379};380 381static int rt5190a_device_initialize(struct rt5190a_priv *priv)382{383	bool mute_enable;384	int ret;385 386	ret = regmap_register_patch(priv->regmap, rt5190a_init_patch,387				    ARRAY_SIZE(rt5190a_init_patch));388	if (ret) {389		dev_err(priv->dev, "Failed to do register patch\n");390		return ret;391	}392 393	mute_enable = device_property_read_bool(priv->dev,394						"richtek,mute-enable");395 396	if (mute_enable) {397		ret = regmap_write(priv->regmap, RT5190A_REG_MUTECNTL, 0x00);398		if (ret) {399			dev_err(priv->dev, "Failed to enable mute function\n");400			return ret;401		}402	}403 404	return 0;405}406 407static int rt5190a_device_check(struct rt5190a_priv *priv)408{409	u16 devid;410	int ret;411 412	ret = regmap_raw_read(priv->regmap, RT5190A_REG_MANUFACTURE, &devid,413			      sizeof(devid));414	if (ret)415		return ret;416 417	if (devid) {418		dev_err(priv->dev, "Incorrect device id 0x%04x\n", devid);419		return -ENODEV;420	}421 422	return 0;423}424 425static const struct regmap_config rt5190a_regmap_config = {426	.reg_bits = 8,427	.val_bits = 8,428	.max_register = RT5190A_REG_HOTDIEMASK,429};430 431static int rt5190a_probe(struct i2c_client *i2c)432{433	struct rt5190a_priv *priv;434	struct regulator_config cfg = {};435	int i, ret;436 437	priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);438	if (!priv)439		return -ENOMEM;440 441	priv->dev = &i2c->dev;442 443	priv->regmap = devm_regmap_init_i2c(i2c, &rt5190a_regmap_config);444	if (IS_ERR(priv->regmap)) {445		dev_err(&i2c->dev, "Failed to allocate regmap\n");446		return PTR_ERR(priv->regmap);447	}448 449	ret = rt5190a_device_check(priv);450	if (ret) {451		dev_err(&i2c->dev, "Failed to check device %d\n", ret);452		return ret;453	}454 455	ret = rt5190a_device_initialize(priv);456	if (ret) {457		dev_err(&i2c->dev, "Failed to initialize the device\n");458		return ret;459	}460 461	ret = rt5190a_parse_regulator_dt_data(priv);462	if (ret) {463		dev_err(&i2c->dev, "Failed to parse regulator dt\n");464		return ret;465	}466 467	cfg.dev = &i2c->dev;468	cfg.regmap = priv->regmap;469 470	for (i = 0; i < RT5190A_MAX_IDX; i++) {471		struct regulator_desc *desc = priv->rdesc + i;472		struct of_regulator_match *match = rt5190a_regulator_match + i;473 474		cfg.init_data = match->init_data;475		cfg.of_node = match->of_node;476 477		priv->rdev[i] = devm_regulator_register(&i2c->dev, desc, &cfg);478		if (IS_ERR(priv->rdev[i])) {479			dev_err(&i2c->dev, "Failed to register regulator %s\n",480				desc->name);481			return PTR_ERR(priv->rdev[i]);482		}483	}484 485	if (i2c->irq) {486		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,487						rt5190a_irq_handler,488						IRQF_ONESHOT,489						dev_name(&i2c->dev), priv);490		if (ret) {491			dev_err(&i2c->dev, "Failed to register interrupt\n");492			return ret;493		}494	}495 496	return 0;497}498 499static const struct of_device_id __maybe_unused rt5190a_device_table[] = {500	{ .compatible = "richtek,rt5190a", },501	{}502};503MODULE_DEVICE_TABLE(of, rt5190a_device_table);504 505static struct i2c_driver rt5190a_driver = {506	.driver = {507		.name = "rt5190a",508		.probe_type = PROBE_PREFER_ASYNCHRONOUS,509		.of_match_table = rt5190a_device_table,510	},511	.probe = rt5190a_probe,512};513module_i2c_driver(rt5190a_driver);514 515MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");516MODULE_DESCRIPTION("Richtek RT5190A Regulator Driver");517MODULE_LICENSE("GPL v2");518