Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3#include <linux/bitops.h>
  4#include <linux/kernel.h>
  5#include <linux/module.h>
  6#include <linux/of.h>
  7#include <linux/platform_device.h>
  8#include <linux/regmap.h>
  9#include <linux/regulator/consumer.h>
 10#include <linux/regulator/driver.h>
 11
 12enum {
 13	DSV_OUT_VLCM = 0,
 14	DSV_OUT_VPOS,
 15	DSV_OUT_VNEG,
 16	DSV_OUT_MAX
 17};
 18
 19#define RT4831_REG_DSVEN	0x09
 20#define RT4831_REG_VLCM		0x0c
 21#define RT4831_REG_VPOS		0x0d
 22#define RT4831_REG_VNEG		0x0e
 23#define RT4831_REG_FLAGS	0x0f
 24
 25#define RT4831_VOLT_MASK	GENMASK(5, 0)
 26#define RT4831_DSVMODE_SHIFT	5
 27#define RT4831_DSVMODE_MASK	GENMASK(7, 5)
 28#define RT4831_POSADEN_MASK	BIT(4)
 29#define RT4831_NEGADEN_MASK	BIT(3)
 30#define RT4831_POSEN_MASK	BIT(2)
 31#define RT4831_NEGEN_MASK	BIT(1)
 32
 33#define RT4831_OTP_MASK		BIT(6)
 34#define RT4831_LCMOVP_MASK	BIT(5)
 35#define RT4831_VPOSSCP_MASK	BIT(3)
 36#define RT4831_VNEGSCP_MASK	BIT(2)
 37
 38#define DSV_MODE_NORMAL		(0x4 << RT4831_DSVMODE_SHIFT)
 39#define DSV_MODE_BYPASS		(0x6 << RT4831_DSVMODE_SHIFT)
 40#define STEP_UV			50000
 41#define VLCM_MIN_UV		4000000
 42#define VLCM_MAX_UV		7150000
 43#define VLCM_N_VOLTAGES		((VLCM_MAX_UV - VLCM_MIN_UV) / STEP_UV + 1)
 44#define VPN_MIN_UV		4000000
 45#define VPN_MAX_UV		6500000
 46#define VPN_N_VOLTAGES		((VPN_MAX_UV - VPN_MIN_UV) / STEP_UV + 1)
 47
 48static int rt4831_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
 49{
 50	struct regmap *regmap = rdev_get_regmap(rdev);
 51	int rid = rdev_get_id(rdev);
 52	unsigned int val, events = 0;
 53	int ret;
 54
 55	ret = regmap_read(regmap, RT4831_REG_FLAGS, &val);
 56	if (ret)
 57		return ret;
 58
 59	if (val & RT4831_OTP_MASK)
 60		events |= REGULATOR_ERROR_OVER_TEMP;
 61
 62	if (rid == DSV_OUT_VLCM && (val & RT4831_LCMOVP_MASK))
 63		events |= REGULATOR_ERROR_OVER_CURRENT;
 64
 65	if (rid == DSV_OUT_VPOS && (val & RT4831_VPOSSCP_MASK))
 66		events |= REGULATOR_ERROR_OVER_CURRENT;
 67
 68	if (rid == DSV_OUT_VNEG && (val & RT4831_VNEGSCP_MASK))
 69		events |= REGULATOR_ERROR_OVER_CURRENT;
 70
 71	*flags = events;
 72	return 0;
 73}
 74
 75static const struct regulator_ops rt4831_dsvlcm_ops = {
 76	.list_voltage = regulator_list_voltage_linear,
 77	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 78	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 79	.set_bypass = regulator_set_bypass_regmap,
 80	.get_bypass = regulator_get_bypass_regmap,
 81	.get_error_flags = rt4831_get_error_flags,
 82};
 83
 84static const struct regulator_ops rt4831_dsvpn_ops = {
 85	.list_voltage = regulator_list_voltage_linear,
 86	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 87	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 88	.enable = regulator_enable_regmap,
 89	.disable = regulator_disable_regmap,
 90	.is_enabled = regulator_is_enabled_regmap,
 91	.set_active_discharge = regulator_set_active_discharge_regmap,
 92	.get_error_flags = rt4831_get_error_flags,
 93};
 94
 95static const struct regulator_desc rt4831_regulator_descs[] = {
 96	{
 97		.name = "DSVLCM",
 98		.ops = &rt4831_dsvlcm_ops,
 99		.of_match = of_match_ptr("DSVLCM"),
100		.regulators_node = of_match_ptr("regulators"),
101		.type = REGULATOR_VOLTAGE,
102		.id = DSV_OUT_VLCM,
103		.n_voltages = VLCM_N_VOLTAGES,
104		.min_uV = VLCM_MIN_UV,
105		.uV_step = STEP_UV,
106		.vsel_reg = RT4831_REG_VLCM,
107		.vsel_mask = RT4831_VOLT_MASK,
108		.bypass_reg = RT4831_REG_DSVEN,
109		.bypass_mask = RT4831_DSVMODE_MASK,
110		.bypass_val_on = DSV_MODE_BYPASS,
111		.bypass_val_off = DSV_MODE_NORMAL,
112		.owner = THIS_MODULE,
113	},
114	{
115		.name = "DSVP",
116		.ops = &rt4831_dsvpn_ops,
117		.of_match = of_match_ptr("DSVP"),
118		.regulators_node = of_match_ptr("regulators"),
119		.type = REGULATOR_VOLTAGE,
120		.id = DSV_OUT_VPOS,
121		.n_voltages = VPN_N_VOLTAGES,
122		.min_uV = VPN_MIN_UV,
123		.uV_step = STEP_UV,
124		.vsel_reg = RT4831_REG_VPOS,
125		.vsel_mask = RT4831_VOLT_MASK,
126		.enable_reg = RT4831_REG_DSVEN,
127		.enable_mask = RT4831_POSEN_MASK,
128		.active_discharge_reg = RT4831_REG_DSVEN,
129		.active_discharge_mask = RT4831_POSADEN_MASK,
130		.active_discharge_on = RT4831_POSADEN_MASK,
131		.owner = THIS_MODULE,
132	},
133	{
134		.name = "DSVN",
135		.ops = &rt4831_dsvpn_ops,
136		.of_match = of_match_ptr("DSVN"),
137		.regulators_node = of_match_ptr("regulators"),
138		.type = REGULATOR_VOLTAGE,
139		.id = DSV_OUT_VNEG,
140		.n_voltages = VPN_N_VOLTAGES,
141		.min_uV = VPN_MIN_UV,
142		.uV_step = STEP_UV,
143		.vsel_reg = RT4831_REG_VNEG,
144		.vsel_mask = RT4831_VOLT_MASK,
145		.enable_reg = RT4831_REG_DSVEN,
146		.enable_mask = RT4831_NEGEN_MASK,
147		.active_discharge_reg = RT4831_REG_DSVEN,
148		.active_discharge_mask = RT4831_NEGADEN_MASK,
149		.active_discharge_on = RT4831_NEGADEN_MASK,
150		.owner = THIS_MODULE,
151	}
152};
153
154static int rt4831_regulator_probe(struct platform_device *pdev)
155{
156	struct regmap *regmap;
157	struct regulator_dev *rdev;
158	struct regulator_config config = {};
159	int i, ret;
160
161	regmap = dev_get_regmap(pdev->dev.parent, NULL);
162	if (!regmap) {
163		dev_err(&pdev->dev, "Failed to init regmap\n");
164		return -ENODEV;
165	}
166
167	/* Configure DSV mode to normal by default */
168	ret = regmap_update_bits(regmap, RT4831_REG_DSVEN, RT4831_DSVMODE_MASK, DSV_MODE_NORMAL);
169	if (ret) {
170		dev_err(&pdev->dev, "Failed to configure dsv mode to normal\n");
171		return ret;
172	}
173
174	config.dev = pdev->dev.parent;
175	config.regmap = regmap;
176
177	for (i = 0; i < DSV_OUT_MAX; i++) {
178		rdev = devm_regulator_register(&pdev->dev, rt4831_regulator_descs + i, &config);
179		if (IS_ERR(rdev)) {
180			dev_err(&pdev->dev, "Failed to register %d regulator\n", i);
181			return PTR_ERR(rdev);
182		}
183	}
184
185	return 0;
186}
187
188static const struct platform_device_id rt4831_regulator_match[] = {
189	{ "rt4831-regulator", 0 },
190	{}
191};
192MODULE_DEVICE_TABLE(platform, rt4831_regulator_match);
193
194static struct platform_driver rt4831_regulator_driver = {
195	.driver = {
196		.name = "rt4831-regulator",
197		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
198	},
199	.id_table = rt4831_regulator_match,
200	.probe = rt4831_regulator_probe,
201};
202module_platform_driver(rt4831_regulator_driver);
203
204MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
205MODULE_DESCRIPTION("Richtek RT4831 DSV Regulators driver");
206MODULE_LICENSE("GPL v2");