497 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2022 Richtek Technology Corp.4 *5 * Author: ChiYuan Huang <cy_huang@richtek.com>6 *7 */8 9#include <linux/bits.h>10#include <linux/delay.h>11#include <linux/gpio/consumer.h>12#include <linux/i2c.h>13#include <linux/interrupt.h>14#include <linux/kernel.h>15#include <linux/mod_devicetable.h>16#include <linux/module.h>17#include <linux/pm_runtime.h>18#include <linux/regmap.h>19#include <linux/regulator/consumer.h>20#include <linux/regulator/driver.h>21#include <linux/regulator/of_regulator.h>22 23#define RT6190_REG_VID 0x0024#define RT6190_REG_OUTV 0x0125#define RT6190_REG_OUTC 0x0326#define RT6190_REG_SET1 0x0D27#define RT6190_REG_SET2 0x0E28#define RT6190_REG_SET4 0x1029#define RT6190_REG_RATIO 0x1130#define RT6190_REG_OUT_VOLT_L 0x1231#define RT6190_REG_TEMP_H 0x1B32#define RT6190_REG_STAT1 0x1C33#define RT6190_REG_ALERT1 0x1E34#define RT6190_REG_ALERT2 0x1F35#define RT6190_REG_MASK2 0x2136#define RT6190_REG_OCPEN 0x2837#define RT6190_REG_SET5 0x2938#define RT6190_REG_VBUSC_ADC 0x3239#define RT6190_REG_BUSC_VOLT_L 0x3340#define RT6190_REG_BUSC_VOLT_H 0x3441#define RT6190_REG_STAT3 0x3742#define RT6190_REG_ALERT3 0x3843#define RT6190_REG_MASK3 0x3944 45#define RT6190_ENPWM_MASK BIT(7)46#define RT6190_ENDCHG_MASK BIT(4)47#define RT6190_ALERT_OTPEVT BIT(6)48#define RT6190_ALERT_UVPEVT BIT(5)49#define RT6190_ALERT_OVPEVT BIT(4)50#define RT6190_ENGCP_MASK BIT(1)51#define RT6190_FCCM_MASK BIT(7)52 53#define RICHTEK_VID 0x8254#define RT6190_OUT_MIN_UV 300000055#define RT6190_OUT_MAX_UV 3200000056#define RT6190_OUT_STEP_UV 2000057#define RT6190_OUT_N_VOLT (RT6190_OUT_MAX_UV / RT6190_OUT_STEP_UV + 1)58#define RT6190_OUTV_MINSEL 15059#define RT6190_OUT_MIN_UA 30600060#define RT6190_OUT_MAX_UA 1211400061#define RT6190_OUT_STEP_UA 2400062#define RT6190_OUTC_MINSEL 1963#define RT6190_EN_TIME_US 50064 65#define RT6190_PSM_MODE 066#define RT6190_FCCM_MODE 167 68struct rt6190_data {69 struct device *dev;70 struct regmap *regmap;71 struct gpio_desc *enable_gpio;72 unsigned int cached_alert_evt;73};74 75static int rt6190_out_set_voltage_sel(struct regulator_dev *rdev,76 unsigned int selector)77{78 struct regmap *regmap = rdev_get_regmap(rdev);79 __le16 le_sel = cpu_to_le16(selector);80 81 return regmap_raw_write(regmap, RT6190_REG_OUTV, &le_sel,82 sizeof(le_sel));83}84 85static int rt6190_out_get_voltage_sel(struct regulator_dev *rdev)86{87 struct regmap *regmap = rdev_get_regmap(rdev);88 __le16 le_sel;89 int ret;90 91 ret = regmap_raw_read(regmap, RT6190_REG_OUTV, &le_sel, sizeof(le_sel));92 93 return ret ?: le16_to_cpu(le_sel);94}95 96static int rt6190_out_enable(struct regulator_dev *rdev)97{98 struct rt6190_data *data = rdev_get_drvdata(rdev);99 struct regmap *regmap = rdev_get_regmap(rdev);100 u8 out_cfg[4];101 int ret;102 103 pm_runtime_get_sync(data->dev);104 105 /*106 * From off to on, vout config will restore to IC default.107 * Read vout configs before enable, and restore them after enable108 */109 ret = regmap_raw_read(regmap, RT6190_REG_OUTV, out_cfg,110 sizeof(out_cfg));111 if (ret)112 return ret;113 114 ret = regulator_enable_regmap(rdev);115 if (ret)116 return ret;117 118 ret = regmap_raw_write(regmap, RT6190_REG_OUTV, out_cfg,119 sizeof(out_cfg));120 if (ret)121 return ret;122 123 return regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK,124 RT6190_ENGCP_MASK);125}126 127static int rt6190_out_disable(struct regulator_dev *rdev)128{129 struct rt6190_data *data = rdev_get_drvdata(rdev);130 struct regmap *regmap = rdev_get_regmap(rdev);131 int ret;132 133 ret = regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, 0);134 if (ret)135 return ret;136 137 ret = regulator_disable_regmap(rdev);138 if (ret)139 return ret;140 141 /* cleared cached alert event */142 data->cached_alert_evt = 0;143 144 pm_runtime_put(data->dev);145 146 return 0;147}148 149static int rt6190_out_set_current_limit(struct regulator_dev *rdev, int min_uA,150 int max_uA)151{152 struct regmap *regmap = rdev_get_regmap(rdev);153 int csel, clim;154 __le16 le_csel;155 156 if (min_uA < RT6190_OUT_MIN_UA || max_uA > RT6190_OUT_MAX_UA)157 return -EINVAL;158 159 csel = DIV_ROUND_UP(min_uA - RT6190_OUT_MIN_UA, RT6190_OUT_STEP_UA);160 161 clim = RT6190_OUT_MIN_UA + RT6190_OUT_STEP_UA * csel;162 if (clim > max_uA)163 return -EINVAL;164 165 csel += RT6190_OUTC_MINSEL;166 le_csel = cpu_to_le16(csel);167 168 return regmap_raw_write(regmap, RT6190_REG_OUTC, &le_csel,169 sizeof(le_csel));170}171 172static int rt6190_out_get_current_limit(struct regulator_dev *rdev)173{174 struct regmap *regmap = rdev_get_regmap(rdev);175 __le16 le_csel;176 int csel, ret;177 178 ret = regmap_raw_read(regmap, RT6190_REG_OUTC, &le_csel,179 sizeof(le_csel));180 if (ret)181 return ret;182 183 csel = le16_to_cpu(le_csel);184 csel -= RT6190_OUTC_MINSEL;185 186 return RT6190_OUT_MIN_UA + RT6190_OUT_STEP_UA * csel;187}188 189static int rt6190_out_set_mode(struct regulator_dev *rdev, unsigned int mode)190{191 struct regmap *regmap = rdev_get_regmap(rdev);192 unsigned int val;193 194 switch (mode) {195 case REGULATOR_MODE_FAST:196 val = RT6190_FCCM_MASK;197 break;198 case REGULATOR_MODE_NORMAL:199 val = 0;200 break;201 default:202 return -EINVAL;203 }204 205 return regmap_update_bits(regmap, RT6190_REG_SET1, RT6190_FCCM_MASK,206 val);207}208 209static unsigned int rt6190_out_get_mode(struct regulator_dev *rdev)210{211 struct regmap *regmap = rdev_get_regmap(rdev);212 unsigned int config;213 int ret;214 215 ret = regmap_read(regmap, RT6190_REG_SET1, &config);216 if (ret)217 return REGULATOR_MODE_INVALID;218 219 if (config & RT6190_FCCM_MASK)220 return REGULATOR_MODE_FAST;221 222 return REGULATOR_MODE_NORMAL;223}224 225static int rt6190_out_get_error_flags(struct regulator_dev *rdev,226 unsigned int *flags)227{228 struct rt6190_data *data = rdev_get_drvdata(rdev);229 unsigned int state, rpt_flags = 0;230 int ret;231 232 ret = regmap_read(data->regmap, RT6190_REG_STAT1, &state);233 if (ret)234 return ret;235 236 state |= data->cached_alert_evt;237 238 if (state & RT6190_ALERT_OTPEVT)239 rpt_flags |= REGULATOR_ERROR_OVER_TEMP;240 241 if (state & RT6190_ALERT_UVPEVT)242 rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE;243 244 if (state & RT6190_ALERT_OVPEVT)245 rpt_flags |= REGULATOR_ERROR_REGULATION_OUT;246 247 *flags = rpt_flags;248 249 return 0;250}251 252static unsigned int rt6190_out_of_map_mode(unsigned int mode)253{254 switch (mode) {255 case RT6190_PSM_MODE:256 return REGULATOR_MODE_NORMAL;257 case RT6190_FCCM_MODE:258 return REGULATOR_MODE_FAST;259 default:260 return REGULATOR_MODE_INVALID;261 }262}263 264static const struct regulator_ops rt6190_regulator_ops = {265 .list_voltage = regulator_list_voltage_linear,266 .set_voltage_sel = rt6190_out_set_voltage_sel,267 .get_voltage_sel = rt6190_out_get_voltage_sel,268 .enable = rt6190_out_enable,269 .disable = rt6190_out_disable,270 .is_enabled = regulator_is_enabled_regmap,271 .set_current_limit = rt6190_out_set_current_limit,272 .get_current_limit = rt6190_out_get_current_limit,273 .set_active_discharge = regulator_set_active_discharge_regmap,274 .set_mode = rt6190_out_set_mode,275 .get_mode = rt6190_out_get_mode,276 .get_error_flags = rt6190_out_get_error_flags,277};278 279static const struct regulator_desc rt6190_regulator_desc = {280 .name = "rt6190-regulator",281 .type = REGULATOR_VOLTAGE,282 .owner = THIS_MODULE,283 .ops = &rt6190_regulator_ops,284 .min_uV = RT6190_OUT_MIN_UV,285 .uV_step = RT6190_OUT_STEP_UV,286 .n_voltages = RT6190_OUT_N_VOLT,287 .linear_min_sel = RT6190_OUTV_MINSEL,288 .enable_reg = RT6190_REG_SET2,289 .enable_mask = RT6190_ENPWM_MASK,290 .active_discharge_reg = RT6190_REG_SET2,291 .active_discharge_mask = RT6190_ENDCHG_MASK,292 .active_discharge_on = RT6190_ENDCHG_MASK,293 .of_map_mode = rt6190_out_of_map_mode,294};295 296static bool rt6190_is_volatile_reg(struct device *dev, unsigned int reg)297{298 switch (reg) {299 case RT6190_REG_OUT_VOLT_L ... RT6190_REG_ALERT2:300 case RT6190_REG_BUSC_VOLT_L ... RT6190_REG_BUSC_VOLT_H:301 case RT6190_REG_STAT3 ... RT6190_REG_ALERT3:302 return true;303 default:304 return false;305 }306}307 308static const struct regmap_config rt6190_regmap_config = {309 .name = "rt6190",310 .cache_type = REGCACHE_FLAT,311 .reg_bits = 8,312 .val_bits = 8,313 .max_register = RT6190_REG_MASK3,314 .num_reg_defaults_raw = RT6190_REG_MASK3 + 1,315 .volatile_reg = rt6190_is_volatile_reg,316};317 318static irqreturn_t rt6190_irq_handler(int irq, void *devid)319{320 struct regulator_dev *rdev = devid;321 struct rt6190_data *data = rdev_get_drvdata(rdev);322 unsigned int alert;323 int ret;324 325 ret = regmap_read(data->regmap, RT6190_REG_ALERT1, &alert);326 if (ret)327 return IRQ_NONE;328 329 /* Write clear alert events */330 ret = regmap_write(data->regmap, RT6190_REG_ALERT1, alert);331 if (ret)332 return IRQ_NONE;333 334 data->cached_alert_evt |= alert;335 336 if (alert & RT6190_ALERT_OTPEVT)337 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_TEMP, NULL);338 339 if (alert & RT6190_ALERT_UVPEVT)340 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL);341 342 if (alert & RT6190_ALERT_OVPEVT)343 regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, NULL);344 345 return IRQ_HANDLED;346}347 348static int rt6190_init_registers(struct regmap *regmap)349{350 int ret;351 352 /* Enable_ADC = 1 */353 ret = regmap_write(regmap, RT6190_REG_SET4, 0x82);354 if (ret)355 return ret;356 357 /* Config default VOUT ratio to be higher */358 ret = regmap_write(regmap, RT6190_REG_RATIO, 0x20);359 360 /* Mask unused alert */361 ret = regmap_write(regmap, RT6190_REG_MASK2, 0);362 if (ret)363 return ret;364 365 /* OCP config */366 ret = regmap_write(regmap, RT6190_REG_OCPEN, 0);367 if (ret)368 return ret;369 370 /* Enable VBUSC ADC */371 return regmap_write(regmap, RT6190_REG_VBUSC_ADC, 0x02);372}373 374static int rt6190_probe(struct i2c_client *i2c)375{376 struct device *dev = &i2c->dev;377 struct rt6190_data *data;378 struct gpio_desc *enable_gpio;379 struct regmap *regmap;380 struct regulator_dev *rdev;381 struct regulator_config cfg = {};382 unsigned int vid;383 int ret;384 385 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);386 if (!data)387 return -ENOMEM;388 389 enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);390 if (IS_ERR(enable_gpio))391 return dev_err_probe(dev, PTR_ERR(enable_gpio), "Failed to get 'enable' gpio\n");392 else if (enable_gpio)393 usleep_range(RT6190_EN_TIME_US, RT6190_EN_TIME_US * 2);394 395 regmap = devm_regmap_init_i2c(i2c, &rt6190_regmap_config);396 if (IS_ERR(regmap))397 return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");398 399 data->dev = dev;400 data->enable_gpio = enable_gpio;401 data->regmap = regmap;402 i2c_set_clientdata(i2c, data);403 404 ret = regmap_read(regmap, RT6190_REG_VID, &vid);405 if (ret)406 return dev_err_probe(dev, ret, "Failed to read VID\n");407 408 if (vid != RICHTEK_VID)409 return dev_err_probe(dev, -ENODEV, "Incorrect VID 0x%02x\n", vid);410 411 ret = rt6190_init_registers(regmap);412 if (ret)413 return dev_err_probe(dev, ret, "Failed to init registers\n");414 415 pm_runtime_set_active(dev);416 ret = devm_pm_runtime_enable(dev);417 if (ret)418 return dev_err_probe(dev, ret, "Failed to set pm_runtime enable\n");419 420 cfg.dev = dev;421 cfg.of_node = dev->of_node;422 cfg.driver_data = data;423 cfg.init_data = of_get_regulator_init_data(dev, dev->of_node,424 &rt6190_regulator_desc);425 426 rdev = devm_regulator_register(dev, &rt6190_regulator_desc, &cfg);427 if (IS_ERR(rdev))428 return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n");429 430 if (i2c->irq) {431 ret = devm_request_threaded_irq(dev, i2c->irq, NULL,432 rt6190_irq_handler,433 IRQF_ONESHOT, dev_name(dev),434 rdev);435 if (ret)436 return dev_err_probe(dev, ret, "Failed to register interrupt\n");437 }438 439 return 0;440}441 442static int rt6190_runtime_suspend(struct device *dev)443{444 struct rt6190_data *data = dev_get_drvdata(dev);445 struct regmap *regmap = data->regmap;446 447 if (!data->enable_gpio)448 return 0;449 450 regcache_cache_only(regmap, true);451 regcache_mark_dirty(regmap);452 453 gpiod_set_value(data->enable_gpio, 0);454 455 return 0;456}457 458static int rt6190_runtime_resume(struct device *dev)459{460 struct rt6190_data *data = dev_get_drvdata(dev);461 struct regmap *regmap = data->regmap;462 463 if (!data->enable_gpio)464 return 0;465 466 gpiod_set_value(data->enable_gpio, 1);467 usleep_range(RT6190_EN_TIME_US, RT6190_EN_TIME_US * 2);468 469 regcache_cache_only(regmap, false);470 return regcache_sync(regmap);471}472 473static const struct dev_pm_ops __maybe_unused rt6190_dev_pm = {474 RUNTIME_PM_OPS(rt6190_runtime_suspend, rt6190_runtime_resume, NULL)475};476 477static const struct of_device_id rt6190_of_dev_table[] = {478 { .compatible = "richtek,rt6190" },479 {}480};481MODULE_DEVICE_TABLE(of, rt6190_of_dev_table);482 483static struct i2c_driver rt6190_driver = {484 .driver = {485 .name = "rt6190",486 .probe_type = PROBE_PREFER_ASYNCHRONOUS,487 .of_match_table = rt6190_of_dev_table,488 .pm = pm_ptr(&rt6190_dev_pm),489 },490 .probe = rt6190_probe,491};492module_i2c_driver(rt6190_driver);493 494MODULE_DESCRIPTION("Richtek RT6190 regulator driver");495MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");496MODULE_LICENSE("GPL");497