Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

regulator: Add support for Richtek RT5739 voltage regulator

The RT5739 is a step-down switching voltage regulator that supports
output voltage ragne from 300mV to 1300mV with the wide input supply
voltage range from 2.5V to 5.5V.

Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
Link: https://lore.kernel.org/r/1676599618-24819-3-git-send-email-cy_huang@richtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

ChiYuan Huang and committed by
Mark Brown
4536f3b9 2e238605

+304
+13
drivers/regulator/Kconfig
··· 1120 1120 buck converters, 1 LDO, mute AC OFF depop function, with the general 1121 1121 I2C control interface. 1122 1122 1123 + config REGULATOR_RT5739 1124 + tristate "Rcihtek RT5739 Regulator" 1125 + depends on I2C 1126 + select REGMAP_I2C 1127 + help 1128 + This adds support for voltage regulator in Richtek RT5739. 1129 + It's a step-down switching voltage regulator. Using a proprietary 1130 + architecture with synchronous rectification, it is capable of 1131 + delivering 3.5A continuously at over 80% efficiency. 1132 + 1133 + This driver can also be built as a module. If so, the module 1134 + will be called rt5739. 1135 + 1123 1136 config REGULATOR_RT5759 1124 1137 tristate "Richtek RT5759 Regulator" 1125 1138 depends on I2C
+1
drivers/regulator/Makefile
··· 134 134 obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o 135 135 obj-$(CONFIG_REGULATOR_RT5120) += rt5120-regulator.o 136 136 obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o 137 + obj-$(CONFIG_REGULATOR_RT5739) += rt5739.o 137 138 obj-$(CONFIG_REGULATOR_RT5759) += rt5759-regulator.o 138 139 obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o 139 140 obj-$(CONFIG_REGULATOR_RT6190) += rt6190-regulator.o
+290
drivers/regulator/rt5739.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Device driver for RT5739 regulator 4 + * 5 + * Copyright (C) 2023 Richtek Technology Corp. 6 + * 7 + * Author: ChiYuan Huang <cy_huang@richtek.com> 8 + */ 9 + 10 + #include <linux/bits.h> 11 + #include <linux/gpio/consumer.h> 12 + #include <linux/i2c.h> 13 + #include <linux/kernel.h> 14 + #include <linux/mod_devicetable.h> 15 + #include <linux/property.h> 16 + #include <linux/regmap.h> 17 + #include <linux/regulator/driver.h> 18 + #include <linux/regulator/of_regulator.h> 19 + 20 + #define RT5739_AUTO_MODE 0 21 + #define RT5739_FPWM_MODE 1 22 + 23 + #define RT5739_REG_NSEL0 0x00 24 + #define RT5739_REG_NSEL1 0x01 25 + #define RT5739_REG_CNTL1 0x02 26 + #define RT5739_REG_ID1 0x03 27 + #define RT5739_REG_CNTL2 0x06 28 + #define RT5739_REG_CNTL4 0x08 29 + 30 + #define RT5739_VSEL_MASK GENMASK(7, 0) 31 + #define RT5739_MODEVSEL1_MASK BIT(1) 32 + #define RT5739_MODEVSEL0_MASK BIT(0) 33 + #define RT5739_VID_MASK GENMASK(7, 5) 34 + #define RT5739_ACTD_MASK BIT(7) 35 + #define RT5739_ENVSEL1_MASK BIT(1) 36 + #define RT5739_ENVSEL0_MASK BIT(0) 37 + 38 + #define RT5739_VOLT_MINUV 300000 39 + #define RT5739_VOLT_MAXUV 1300000 40 + #define RT5739_VOLT_STPUV 5000 41 + #define RT5739_N_VOLTS 201 42 + #define RT5739_I2CRDY_TIMEUS 1000 43 + 44 + static int rt5739_set_mode(struct regulator_dev *rdev, unsigned int mode) 45 + { 46 + const struct regulator_desc *desc = rdev->desc; 47 + struct regmap *regmap = rdev_get_regmap(rdev); 48 + unsigned int mask, val; 49 + 50 + if (desc->vsel_reg == RT5739_REG_NSEL0) 51 + mask = RT5739_MODEVSEL0_MASK; 52 + else 53 + mask = RT5739_MODEVSEL1_MASK; 54 + 55 + switch (mode) { 56 + case REGULATOR_MODE_FAST: 57 + val = mask; 58 + break; 59 + case REGULATOR_MODE_NORMAL: 60 + val = 0; 61 + break; 62 + default: 63 + return -EINVAL; 64 + } 65 + 66 + return regmap_update_bits(regmap, RT5739_REG_CNTL1, mask, val); 67 + } 68 + 69 + static unsigned int rt5739_get_mode(struct regulator_dev *rdev) 70 + { 71 + const struct regulator_desc *desc = rdev->desc; 72 + struct regmap *regmap = rdev_get_regmap(rdev); 73 + unsigned int mask, val; 74 + int ret; 75 + 76 + if (desc->vsel_reg == RT5739_REG_NSEL0) 77 + mask = RT5739_MODEVSEL0_MASK; 78 + else 79 + mask = RT5739_MODEVSEL1_MASK; 80 + 81 + ret = regmap_read(regmap, RT5739_REG_CNTL1, &val); 82 + if (ret) 83 + return REGULATOR_MODE_INVALID; 84 + 85 + if (val & mask) 86 + return REGULATOR_MODE_FAST; 87 + 88 + return REGULATOR_MODE_NORMAL; 89 + } 90 + 91 + static int rt5739_set_suspend_voltage(struct regulator_dev *rdev, int uV) 92 + { 93 + const struct regulator_desc *desc = rdev->desc; 94 + struct regmap *regmap = rdev_get_regmap(rdev); 95 + unsigned int reg, vsel; 96 + 97 + if (uV < RT5739_VOLT_MINUV || uV > RT5739_VOLT_MAXUV) 98 + return -EINVAL; 99 + 100 + if (desc->vsel_reg == RT5739_REG_NSEL0) 101 + reg = RT5739_REG_NSEL1; 102 + else 103 + reg = RT5739_REG_NSEL0; 104 + 105 + vsel = (uV - RT5739_VOLT_MINUV) / RT5739_VOLT_STPUV; 106 + return regmap_write(regmap, reg, vsel); 107 + } 108 + 109 + static int rt5739_set_suspend_enable(struct regulator_dev *rdev) 110 + { 111 + const struct regulator_desc *desc = rdev->desc; 112 + struct regmap *regmap = rdev_get_regmap(rdev); 113 + unsigned int mask; 114 + 115 + if (desc->vsel_reg == RT5739_REG_NSEL0) 116 + mask = RT5739_ENVSEL1_MASK; 117 + else 118 + mask = RT5739_ENVSEL0_MASK; 119 + 120 + return regmap_update_bits(regmap, desc->enable_reg, mask, mask); 121 + } 122 + 123 + static int rt5739_set_suspend_disable(struct regulator_dev *rdev) 124 + { 125 + const struct regulator_desc *desc = rdev->desc; 126 + struct regmap *regmap = rdev_get_regmap(rdev); 127 + unsigned int mask; 128 + 129 + if (desc->vsel_reg == RT5739_REG_NSEL0) 130 + mask = RT5739_ENVSEL1_MASK; 131 + else 132 + mask = RT5739_ENVSEL0_MASK; 133 + 134 + return regmap_update_bits(regmap, desc->enable_reg, mask, 0); 135 + } 136 + 137 + static int rt5739_set_suspend_mode(struct regulator_dev *rdev, 138 + unsigned int mode) 139 + { 140 + const struct regulator_desc *desc = rdev->desc; 141 + struct regmap *regmap = rdev_get_regmap(rdev); 142 + unsigned int mask, val; 143 + 144 + if (desc->vsel_reg == RT5739_REG_NSEL0) 145 + mask = RT5739_MODEVSEL1_MASK; 146 + else 147 + mask = RT5739_MODEVSEL0_MASK; 148 + 149 + switch (mode) { 150 + case REGULATOR_MODE_FAST: 151 + val = mask; 152 + break; 153 + case REGULATOR_MODE_NORMAL: 154 + val = 0; 155 + break; 156 + default: 157 + return -EINVAL; 158 + } 159 + 160 + return regmap_update_bits(regmap, RT5739_REG_CNTL1, mask, val); 161 + } 162 + 163 + static const struct regulator_ops rt5739_regulator_ops = { 164 + .list_voltage = regulator_list_voltage_linear, 165 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 166 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 167 + .enable = regulator_enable_regmap, 168 + .disable = regulator_disable_regmap, 169 + .is_enabled = regulator_is_enabled_regmap, 170 + .set_active_discharge = regulator_set_active_discharge_regmap, 171 + .set_mode = rt5739_set_mode, 172 + .get_mode = rt5739_get_mode, 173 + .set_suspend_voltage = rt5739_set_suspend_voltage, 174 + .set_suspend_enable = rt5739_set_suspend_enable, 175 + .set_suspend_disable = rt5739_set_suspend_disable, 176 + .set_suspend_mode = rt5739_set_suspend_mode, 177 + }; 178 + 179 + static unsigned int rt5739_of_map_mode(unsigned int mode) 180 + { 181 + switch (mode) { 182 + case RT5739_AUTO_MODE: 183 + return REGULATOR_MODE_NORMAL; 184 + case RT5739_FPWM_MODE: 185 + return REGULATOR_MODE_FAST; 186 + default: 187 + return REGULATOR_MODE_INVALID; 188 + } 189 + } 190 + 191 + static void rt5739_init_regulator_desc(struct regulator_desc *desc, 192 + bool vsel_active_high) 193 + { 194 + /* Fixed */ 195 + desc->name = "rt5739-regulator"; 196 + desc->owner = THIS_MODULE; 197 + desc->ops = &rt5739_regulator_ops; 198 + desc->n_voltages = RT5739_N_VOLTS; 199 + desc->min_uV = RT5739_VOLT_MINUV; 200 + desc->uV_step = RT5739_VOLT_STPUV; 201 + desc->vsel_mask = RT5739_VSEL_MASK; 202 + desc->enable_reg = RT5739_REG_CNTL2; 203 + desc->active_discharge_reg = RT5739_REG_CNTL1; 204 + desc->active_discharge_mask = RT5739_ACTD_MASK; 205 + desc->active_discharge_on = RT5739_ACTD_MASK; 206 + desc->of_map_mode = rt5739_of_map_mode; 207 + 208 + /* Assigned by vsel level */ 209 + if (vsel_active_high) { 210 + desc->vsel_reg = RT5739_REG_NSEL1; 211 + desc->enable_mask = RT5739_ENVSEL1_MASK; 212 + } else { 213 + desc->vsel_reg = RT5739_REG_NSEL0; 214 + desc->enable_mask = RT5739_ENVSEL0_MASK; 215 + } 216 + } 217 + 218 + static const struct regmap_config rt5739_regmap_config = { 219 + .name = "rt5739", 220 + .reg_bits = 8, 221 + .val_bits = 8, 222 + .max_register = RT5739_REG_CNTL4, 223 + }; 224 + 225 + static int rt5739_probe(struct i2c_client *i2c) 226 + { 227 + struct device *dev = &i2c->dev; 228 + struct regulator_desc *desc; 229 + struct regmap *regmap; 230 + struct gpio_desc *enable_gpio; 231 + struct regulator_config cfg = {}; 232 + struct regulator_dev *rdev; 233 + bool vsel_acth; 234 + unsigned int vid; 235 + int ret; 236 + 237 + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); 238 + if (!desc) 239 + return -ENOMEM; 240 + 241 + enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); 242 + if (IS_ERR(enable_gpio)) 243 + return dev_err_probe(dev, PTR_ERR(enable_gpio), "Failed to get 'enable' gpio\n"); 244 + else if (enable_gpio) 245 + usleep_range(RT5739_I2CRDY_TIMEUS, RT5739_I2CRDY_TIMEUS + 1000); 246 + 247 + regmap = devm_regmap_init_i2c(i2c, &rt5739_regmap_config); 248 + if (IS_ERR(regmap)) 249 + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); 250 + 251 + ret = regmap_read(regmap, RT5739_REG_ID1, &vid); 252 + if (ret) 253 + return dev_err_probe(dev, ret, "Failed to read VID\n"); 254 + 255 + /* RT5739: (VID & MASK) must be 0 */ 256 + if (vid & RT5739_VID_MASK) 257 + return dev_err_probe(dev, -ENODEV, "Incorrect VID (0x%02x)\n", vid); 258 + 259 + vsel_acth = device_property_read_bool(dev, "richtek,vsel-active-high"); 260 + 261 + rt5739_init_regulator_desc(desc, vsel_acth); 262 + 263 + cfg.dev = dev; 264 + cfg.of_node = dev_of_node(dev); 265 + cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc); 266 + rdev = devm_regulator_register(dev, desc, &cfg); 267 + if (IS_ERR(rdev)) 268 + return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n"); 269 + 270 + return 0; 271 + } 272 + 273 + static const struct of_device_id rt5739_device_table[] = { 274 + { .compatible = "richtek,rt5739" }, 275 + { /* sentinel */ } 276 + }; 277 + MODULE_DEVICE_TABLE(of, rt5739_device_table); 278 + 279 + static struct i2c_driver rt5739_driver = { 280 + .driver = { 281 + .name = "rt5739", 282 + .of_match_table = rt5739_device_table, 283 + }, 284 + .probe_new = rt5739_probe, 285 + }; 286 + module_i2c_driver(rt5739_driver); 287 + 288 + MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 289 + MODULE_DESCRIPTION("Richtek RT5739 regulator driver"); 290 + MODULE_LICENSE("GPL");