brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · c96fb02 Raw
217 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2023 Richtek Technology Corp.4 *5 * Author: ChiYuan Huang <cy_huang@richtek.com>6 */7 8#include <linux/i2c.h>9#include <linux/kernel.h>10#include <linux/mod_devicetable.h>11#include <linux/module.h>12#include <linux/property.h>13#include <linux/regmap.h>14#include <linux/regulator/driver.h>15#include <linux/regulator/of_regulator.h>16 17#define RT4803_AUTO_MODE	118#define RT4803_FPWM_MODE	219 20#define RT4803_REG_CONFIG	0x0121#define RT4803_REG_VSELL	0x0222#define RT4803_REG_VSELH	0x0323#define RT4803_REG_ILIM		0x0424#define RT4803_REG_STAT		0x0525 26#define RT4803_MODE_MASK	GENMASK(1, 0)27#define RT4803_VSEL_MASK	GENMASK(4, 0)28#define RT4803_ILIM_MASK	GENMASK(3, 0)29#define RT4803_TSD_MASK		BIT(7)30#define RT4803_HOTDIE_MASK	BIT(6)31#define RT4803_FAULT_MASK	BIT(1)32#define RT4803_PGOOD_MASK	BIT(0)33 34#define RT4803_VOUT_MINUV	285000035#define RT4803_VOUT_STEPUV	5000036#define RT4803_VOUT_NUM		3237 38static int rt4803_set_mode(struct regulator_dev *rdev, unsigned int mode)39{40	struct regmap *regmap = rdev_get_regmap(rdev);41	unsigned int modeval;42 43	switch (mode) {44	case REGULATOR_MODE_NORMAL:45		modeval = RT4803_AUTO_MODE;46		break;47	case REGULATOR_MODE_FAST:48		modeval = RT4803_FPWM_MODE;49		break;50	default:51		return -EINVAL;52	}53 54	modeval <<= ffs(RT4803_MODE_MASK) - 1;55 56	return regmap_update_bits(regmap, RT4803_REG_CONFIG, RT4803_MODE_MASK, modeval);57}58 59static unsigned int rt4803_get_mode(struct regulator_dev *rdev)60{61	struct regmap *regmap = rdev_get_regmap(rdev);62	unsigned int modeval;63	int ret;64 65	ret = regmap_read(regmap, RT4803_REG_CONFIG, &modeval);66	if (ret)67		return REGULATOR_MODE_INVALID;68 69	modeval >>= ffs(RT4803_MODE_MASK) - 1;70 71	switch (modeval) {72	case RT4803_AUTO_MODE:73		return REGULATOR_MODE_NORMAL;74	case RT4803_FPWM_MODE:75		return REGULATOR_MODE_FAST;76	default:77		return REGULATOR_MODE_INVALID;78	}79}80 81static int rt4803_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)82{83	struct regmap *regmap = rdev_get_regmap(rdev);84	unsigned int state, events = 0;85	int ret;86 87	ret = regmap_read(regmap, RT4803_REG_STAT, &state);88	if (ret)89		return ret;90 91	if (state & RT4803_PGOOD_MASK)92		goto out_error_flag;93 94	if (state & RT4803_FAULT_MASK)95		events |= REGULATOR_ERROR_FAIL;96 97	if (state & RT4803_HOTDIE_MASK)98		events |= REGULATOR_ERROR_OVER_TEMP_WARN;99 100	if (state & RT4803_TSD_MASK)101		events |= REGULATOR_ERROR_OVER_TEMP;102 103out_error_flag:104	*flags = events;105	return 0;106}107 108static int rt4803_set_suspend_voltage(struct regulator_dev *rdev, int uV)109{110	struct regmap *regmap = rdev_get_regmap(rdev);111	unsigned int reg, vsel;112 113	if (rdev->desc->vsel_reg == RT4803_REG_VSELL)114		reg = RT4803_REG_VSELH;115	else116		reg = RT4803_REG_VSELL;117 118	vsel = (uV - rdev->desc->min_uV) / rdev->desc->uV_step;119	vsel <<= ffs(RT4803_VSEL_MASK) - 1;120 121	return regmap_update_bits(regmap, reg, RT4803_VSEL_MASK, vsel);122}123 124static const struct regulator_ops rt4803_regulator_ops = {125	.list_voltage = regulator_list_voltage_linear,126	.set_voltage_sel = regulator_set_voltage_sel_regmap,127	.get_voltage_sel = regulator_get_voltage_sel_regmap,128	.set_mode = rt4803_set_mode,129	.get_mode = rt4803_get_mode,130	.get_error_flags = rt4803_get_error_flags,131	.set_suspend_voltage = rt4803_set_suspend_voltage,132};133 134static unsigned int rt4803_of_map_mode(unsigned int mode)135{136	switch (mode) {137	case RT4803_AUTO_MODE:138		return REGULATOR_MODE_NORMAL;139	case RT4803_FPWM_MODE:140		return REGULATOR_MODE_FAST;141	default:142		return REGULATOR_MODE_INVALID;143	}144}145 146static const struct regmap_config rt4803_regmap_config = {147	.reg_bits = 8,148	.val_bits = 8,149	.max_register = RT4803_REG_STAT,150};151 152static int rt4803_probe(struct i2c_client *i2c)153{154	struct device *dev = &i2c->dev;155	struct regmap *regmap;156	struct regulator_desc *desc;157	struct regulator_config cfg = {};158	struct regulator_dev *rdev;159	bool vsel_act_high;160	int ret;161 162	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);163	if (!desc)164		return -ENOMEM;165 166	regmap = devm_regmap_init_i2c(i2c, &rt4803_regmap_config);167	if (IS_ERR(regmap))168		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");169 170	/* Always configure the input current limit to max 5A at initial */171	ret = regmap_update_bits(regmap, RT4803_REG_ILIM, RT4803_ILIM_MASK, 0xff);172	if (ret)173		return dev_err_probe(dev, ret, "Failed to config ILIM to max\n");174 175	vsel_act_high = device_property_read_bool(dev, "richtek,vsel-active-high");176 177	desc->name = "rt4803-regulator";178	desc->type = REGULATOR_VOLTAGE;179	desc->owner = THIS_MODULE;180	desc->ops = &rt4803_regulator_ops;181	desc->min_uV = RT4803_VOUT_MINUV;182	desc->uV_step = RT4803_VOUT_STEPUV;183	desc->n_voltages = RT4803_VOUT_NUM;184	desc->vsel_mask = RT4803_VSEL_MASK;185	desc->of_map_mode = rt4803_of_map_mode;186	if (vsel_act_high)187		desc->vsel_reg = RT4803_REG_VSELH;188	else189		desc->vsel_reg = RT4803_REG_VSELL;190 191	cfg.dev = dev;192	cfg.of_node = dev_of_node(dev);193	cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc);194 195	rdev = devm_regulator_register(dev, desc, &cfg);196	return PTR_ERR_OR_ZERO(rdev);197}198 199static const struct of_device_id rt4803_device_match_table[] = {200	{ .compatible = "richtek,rt4803" },201	{}202};203MODULE_DEVICE_TABLE(of, rt4803_device_match_table);204 205static struct i2c_driver rt4803_driver = {206	.driver = {207		.name = "rt4803",208		.of_match_table = rt4803_device_match_table,209	},210	.probe = rt4803_probe,211};212module_i2c_driver(rt4803_driver);213 214MODULE_DESCRIPTION("Richtek RT4803 voltage regulator driver");215MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");216MODULE_LICENSE("GPL");217