1*32a708baSChiYuan Huang // SPDX-License-Identifier: GPL-2.0+ 2*32a708baSChiYuan Huang // 3*32a708baSChiYuan Huang // Copyright (c) 2025 Richtek Technology Corp. 4*32a708baSChiYuan Huang // 5*32a708baSChiYuan Huang // Author: ChiYuan Huang <cy_huang@richtek.com> 6*32a708baSChiYuan Huang 7*32a708baSChiYuan Huang #include <linux/bitfield.h> 8*32a708baSChiYuan Huang #include <linux/bits.h> 9*32a708baSChiYuan Huang #include <linux/gpio/consumer.h> 10*32a708baSChiYuan Huang #include <linux/i2c.h> 11*32a708baSChiYuan Huang #include <linux/mod_devicetable.h> 12*32a708baSChiYuan Huang #include <linux/module.h> 13*32a708baSChiYuan Huang #include <linux/property.h> 14*32a708baSChiYuan Huang #include <linux/regmap.h> 15*32a708baSChiYuan Huang #include <linux/regulator/consumer.h> 16*32a708baSChiYuan Huang #include <linux/regulator/driver.h> 17*32a708baSChiYuan Huang #include <linux/regulator/of_regulator.h> 18*32a708baSChiYuan Huang 19*32a708baSChiYuan Huang #define RT8092_REG_MNTRPT 0x00 20*32a708baSChiYuan Huang #define RT8092_REG_VOUTH 0x10 21*32a708baSChiYuan Huang #define RT8092_REG_VOUTL 0x11 22*32a708baSChiYuan Huang #define RT8092_REG_PWMMODE 0x14 23*32a708baSChiYuan Huang #define RT8092_REG_EVENT 0x18 24*32a708baSChiYuan Huang #define RT8092_REG_VBANKH 0x1C 25*32a708baSChiYuan Huang #define RT8092_REG_VBANKL 0x1D 26*32a708baSChiYuan Huang #define RT8092_REG_VBOUND 0x1E 27*32a708baSChiYuan Huang 28*32a708baSChiYuan Huang #define RT8092_TSDEVT_MASK BIT(7) 29*32a708baSChiYuan Huang #define RT8092_PGEVT_MASK BIT(0) 30*32a708baSChiYuan Huang #define RT8092_VSEL_MASK GENMASK(6, 0) 31*32a708baSChiYuan Huang #define RT8092_VOUTEN_MASK BIT(7) 32*32a708baSChiYuan Huang #define RT8092_FPWML_MASK BIT(7) 33*32a708baSChiYuan Huang #define RT8092_FPWMH_MASK BIT(6) 34*32a708baSChiYuan Huang #define RT8092_OCPEVT_MASK BIT(7) 35*32a708baSChiYuan Huang #define RT8092_SCPEVT_MASK BIT(4) 36*32a708baSChiYuan Huang #define RT8092_VINUVEVT_MASK BIT(1) 37*32a708baSChiYuan Huang #define RT8092_VBANK_MASK GENMASK(1, 0) 38*32a708baSChiYuan Huang 39*32a708baSChiYuan Huang #define RT8092_MODE_AUTO 0 40*32a708baSChiYuan Huang #define RT8092_MODE_FPWM 1 41*32a708baSChiYuan Huang #define RT8092_VOUT_BASEUV 303125 42*32a708baSChiYuan Huang #define RT8092_VOUT_STEPUV 3125 43*32a708baSChiYuan Huang #define RT8092_VOUT_MINSEL 15 44*32a708baSChiYuan Huang #define RT8092_NUM_VOLTS 128 45*32a708baSChiYuan Huang #define RT8092_INITSS_US 400 46*32a708baSChiYuan Huang 47*32a708baSChiYuan Huang static int rt8092_get_vbank_index(struct regmap *regmap, bool vsel_high, unsigned int *vbank_idx) 48*32a708baSChiYuan Huang { 49*32a708baSChiYuan Huang unsigned int vbank_reg = vsel_high ? RT8092_REG_VBANKH : RT8092_REG_VBANKL; 50*32a708baSChiYuan Huang unsigned int index; 51*32a708baSChiYuan Huang int ret; 52*32a708baSChiYuan Huang 53*32a708baSChiYuan Huang ret = regmap_read(regmap, vbank_reg, &index); 54*32a708baSChiYuan Huang if (ret) 55*32a708baSChiYuan Huang return ret; 56*32a708baSChiYuan Huang 57*32a708baSChiYuan Huang *vbank_idx = FIELD_GET(RT8092_VBANK_MASK, index); 58*32a708baSChiYuan Huang return 0; 59*32a708baSChiYuan Huang } 60*32a708baSChiYuan Huang 61*32a708baSChiYuan Huang static int rt8092_set_operating_mode(struct regulator_dev *rdev, unsigned int mode) 62*32a708baSChiYuan Huang { 63*32a708baSChiYuan Huang const struct regulator_desc *desc = rdev->desc; 64*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 65*32a708baSChiYuan Huang unsigned int mode_mask, mode_val; 66*32a708baSChiYuan Huang 67*32a708baSChiYuan Huang mode_mask = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_FPWMH_MASK : RT8092_FPWML_MASK; 68*32a708baSChiYuan Huang 69*32a708baSChiYuan Huang switch (mode) { 70*32a708baSChiYuan Huang case REGULATOR_MODE_FAST: 71*32a708baSChiYuan Huang mode_val = mode_mask; 72*32a708baSChiYuan Huang break; 73*32a708baSChiYuan Huang case REGULATOR_MODE_NORMAL: 74*32a708baSChiYuan Huang mode_val = 0; 75*32a708baSChiYuan Huang break; 76*32a708baSChiYuan Huang default: 77*32a708baSChiYuan Huang return -EINVAL; 78*32a708baSChiYuan Huang } 79*32a708baSChiYuan Huang 80*32a708baSChiYuan Huang return regmap_update_bits(regmap, RT8092_REG_PWMMODE, mode_mask, mode_val); 81*32a708baSChiYuan Huang } 82*32a708baSChiYuan Huang 83*32a708baSChiYuan Huang static unsigned int rt8092_get_operating_mode(struct regulator_dev *rdev) 84*32a708baSChiYuan Huang { 85*32a708baSChiYuan Huang const struct regulator_desc *desc = rdev->desc; 86*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 87*32a708baSChiYuan Huang unsigned int mode_mask, mode_val; 88*32a708baSChiYuan Huang int ret; 89*32a708baSChiYuan Huang 90*32a708baSChiYuan Huang mode_mask = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_FPWMH_MASK : RT8092_FPWML_MASK; 91*32a708baSChiYuan Huang 92*32a708baSChiYuan Huang ret = regmap_read(regmap, RT8092_REG_PWMMODE, &mode_val); 93*32a708baSChiYuan Huang if (ret) 94*32a708baSChiYuan Huang return REGULATOR_MODE_INVALID; 95*32a708baSChiYuan Huang 96*32a708baSChiYuan Huang return mode_val & mode_mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; 97*32a708baSChiYuan Huang } 98*32a708baSChiYuan Huang 99*32a708baSChiYuan Huang static int rt8092_get_error_flags(struct regulator_dev *rdev, unsigned int *flags) 100*32a708baSChiYuan Huang { 101*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 102*32a708baSChiYuan Huang unsigned int mntrpt, evtrpt, events = 0; 103*32a708baSChiYuan Huang int ret; 104*32a708baSChiYuan Huang 105*32a708baSChiYuan Huang ret = regmap_read(regmap, RT8092_REG_MNTRPT, &mntrpt); 106*32a708baSChiYuan Huang if (ret) 107*32a708baSChiYuan Huang return ret; 108*32a708baSChiYuan Huang 109*32a708baSChiYuan Huang ret = regmap_read(regmap, RT8092_REG_EVENT, &evtrpt); 110*32a708baSChiYuan Huang if (ret) 111*32a708baSChiYuan Huang return ret; 112*32a708baSChiYuan Huang 113*32a708baSChiYuan Huang if (!(mntrpt & RT8092_PGEVT_MASK) || evtrpt & RT8092_VINUVEVT_MASK) 114*32a708baSChiYuan Huang events |= REGULATOR_ERROR_UNDER_VOLTAGE; 115*32a708baSChiYuan Huang 116*32a708baSChiYuan Huang if (mntrpt & RT8092_TSDEVT_MASK) 117*32a708baSChiYuan Huang events |= REGULATOR_ERROR_OVER_TEMP; 118*32a708baSChiYuan Huang 119*32a708baSChiYuan Huang if (evtrpt & RT8092_OCPEVT_MASK) 120*32a708baSChiYuan Huang events |= REGULATOR_ERROR_OVER_CURRENT; 121*32a708baSChiYuan Huang 122*32a708baSChiYuan Huang if (evtrpt & RT8092_SCPEVT_MASK) 123*32a708baSChiYuan Huang events |= REGULATOR_ERROR_FAIL; 124*32a708baSChiYuan Huang 125*32a708baSChiYuan Huang *flags = events; 126*32a708baSChiYuan Huang return 0; 127*32a708baSChiYuan Huang } 128*32a708baSChiYuan Huang 129*32a708baSChiYuan Huang 130*32a708baSChiYuan Huang static int rt8092_set_suspend_voltage(struct regulator_dev *rdev, int uV) 131*32a708baSChiYuan Huang { 132*32a708baSChiYuan Huang const struct regulator_desc *desc = rdev->desc; 133*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 134*32a708baSChiYuan Huang unsigned int vsel_reg, vsel_val, vbank_idx; 135*32a708baSChiYuan Huang bool vsel_high; 136*32a708baSChiYuan Huang int ret; 137*32a708baSChiYuan Huang 138*32a708baSChiYuan Huang vsel_reg = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_REG_VOUTL : RT8092_REG_VOUTH; 139*32a708baSChiYuan Huang vsel_high = desc->vsel_reg == RT8092_REG_VOUTH; 140*32a708baSChiYuan Huang 141*32a708baSChiYuan Huang ret = rt8092_get_vbank_index(regmap, vsel_high, &vbank_idx); 142*32a708baSChiYuan Huang if (ret) 143*32a708baSChiYuan Huang return ret; 144*32a708baSChiYuan Huang 145*32a708baSChiYuan Huang /* VOUT = (BASEUV + STEPUV * VSEL) * 2^vbank_idx */ 146*32a708baSChiYuan Huang uV >>= vbank_idx; 147*32a708baSChiYuan Huang if (uV < RT8092_VOUT_BASEUV) 148*32a708baSChiYuan Huang return -EINVAL; 149*32a708baSChiYuan Huang 150*32a708baSChiYuan Huang vsel_val = (uV - RT8092_VOUT_BASEUV) / RT8092_VOUT_STEPUV; 151*32a708baSChiYuan Huang if (vsel_val < RT8092_VOUT_MINSEL || vsel_val >= RT8092_NUM_VOLTS) 152*32a708baSChiYuan Huang return -EINVAL; 153*32a708baSChiYuan Huang 154*32a708baSChiYuan Huang return regmap_update_bits(regmap, vsel_reg, RT8092_VSEL_MASK, vsel_val); 155*32a708baSChiYuan Huang } 156*32a708baSChiYuan Huang 157*32a708baSChiYuan Huang static int rt8092_set_suspend_enable(struct regulator_dev *rdev) 158*32a708baSChiYuan Huang { 159*32a708baSChiYuan Huang const struct regulator_desc *desc = rdev->desc; 160*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 161*32a708baSChiYuan Huang unsigned int enable_reg; 162*32a708baSChiYuan Huang 163*32a708baSChiYuan Huang enable_reg = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_REG_VOUTL : RT8092_REG_VOUTH; 164*32a708baSChiYuan Huang return regmap_set_bits(regmap, enable_reg, RT8092_VOUTEN_MASK); 165*32a708baSChiYuan Huang } 166*32a708baSChiYuan Huang 167*32a708baSChiYuan Huang static int rt8092_set_suspend_disable(struct regulator_dev *rdev) 168*32a708baSChiYuan Huang { 169*32a708baSChiYuan Huang const struct regulator_desc *desc = rdev->desc; 170*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 171*32a708baSChiYuan Huang unsigned int enable_reg; 172*32a708baSChiYuan Huang 173*32a708baSChiYuan Huang enable_reg = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_REG_VOUTL : RT8092_REG_VOUTH; 174*32a708baSChiYuan Huang return regmap_clear_bits(regmap, enable_reg, RT8092_VOUTEN_MASK); 175*32a708baSChiYuan Huang } 176*32a708baSChiYuan Huang 177*32a708baSChiYuan Huang static int rt8092_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) 178*32a708baSChiYuan Huang { 179*32a708baSChiYuan Huang const struct regulator_desc *desc = rdev->desc; 180*32a708baSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 181*32a708baSChiYuan Huang unsigned int mode_mask, mode_val; 182*32a708baSChiYuan Huang 183*32a708baSChiYuan Huang mode_mask = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_FPWML_MASK : RT8092_FPWMH_MASK; 184*32a708baSChiYuan Huang 185*32a708baSChiYuan Huang switch (mode) { 186*32a708baSChiYuan Huang case REGULATOR_MODE_FAST: 187*32a708baSChiYuan Huang mode_val = mode_mask; 188*32a708baSChiYuan Huang break; 189*32a708baSChiYuan Huang case REGULATOR_MODE_NORMAL: 190*32a708baSChiYuan Huang mode_val = 0; 191*32a708baSChiYuan Huang break; 192*32a708baSChiYuan Huang default: 193*32a708baSChiYuan Huang return -EINVAL; 194*32a708baSChiYuan Huang } 195*32a708baSChiYuan Huang 196*32a708baSChiYuan Huang return regmap_update_bits(regmap, RT8092_REG_PWMMODE, mode_mask, mode_val); 197*32a708baSChiYuan Huang } 198*32a708baSChiYuan Huang 199*32a708baSChiYuan Huang static const struct regulator_ops rt8092_regulator_ops = { 200*32a708baSChiYuan Huang .list_voltage = regulator_list_voltage_linear, 201*32a708baSChiYuan Huang .get_voltage_sel = regulator_get_voltage_sel_regmap, 202*32a708baSChiYuan Huang .set_voltage_sel = regulator_set_voltage_sel_regmap, 203*32a708baSChiYuan Huang .enable = regulator_enable_regmap, 204*32a708baSChiYuan Huang .disable = regulator_disable_regmap, 205*32a708baSChiYuan Huang .is_enabled = regulator_is_enabled_regmap, 206*32a708baSChiYuan Huang .set_mode = rt8092_set_operating_mode, 207*32a708baSChiYuan Huang .get_mode = rt8092_get_operating_mode, 208*32a708baSChiYuan Huang .get_error_flags = rt8092_get_error_flags, 209*32a708baSChiYuan Huang .set_suspend_voltage = rt8092_set_suspend_voltage, 210*32a708baSChiYuan Huang .set_suspend_enable = rt8092_set_suspend_enable, 211*32a708baSChiYuan Huang .set_suspend_disable = rt8092_set_suspend_disable, 212*32a708baSChiYuan Huang .set_suspend_mode = rt8092_set_suspend_mode, 213*32a708baSChiYuan Huang }; 214*32a708baSChiYuan Huang 215*32a708baSChiYuan Huang static unsigned int rt8092_of_map_mode(unsigned int mode) 216*32a708baSChiYuan Huang { 217*32a708baSChiYuan Huang switch (mode) { 218*32a708baSChiYuan Huang case RT8092_MODE_AUTO: 219*32a708baSChiYuan Huang return REGULATOR_MODE_NORMAL; 220*32a708baSChiYuan Huang case RT8092_MODE_FPWM: 221*32a708baSChiYuan Huang return REGULATOR_MODE_FAST; 222*32a708baSChiYuan Huang default: 223*32a708baSChiYuan Huang return REGULATOR_MODE_INVALID; 224*32a708baSChiYuan Huang } 225*32a708baSChiYuan Huang } 226*32a708baSChiYuan Huang 227*32a708baSChiYuan Huang static const struct regmap_config rt8092_regmap_cfg = { 228*32a708baSChiYuan Huang .name = "rt8092", 229*32a708baSChiYuan Huang .reg_bits = 8, 230*32a708baSChiYuan Huang .val_bits = 8, 231*32a708baSChiYuan Huang .max_register = RT8092_REG_VBOUND, 232*32a708baSChiYuan Huang }; 233*32a708baSChiYuan Huang 234*32a708baSChiYuan Huang static int rt8092_probe(struct i2c_client *i2c) 235*32a708baSChiYuan Huang { 236*32a708baSChiYuan Huang unsigned int vbank_idx, min_uV, step_uV; 237*32a708baSChiYuan Huang struct regulator_config cfg = {}; 238*32a708baSChiYuan Huang struct device *dev = &i2c->dev; 239*32a708baSChiYuan Huang struct regulator_desc *desc; 240*32a708baSChiYuan Huang struct regulator_dev *rdev; 241*32a708baSChiYuan Huang struct gpio_desc *enable; 242*32a708baSChiYuan Huang struct regmap *regmap; 243*32a708baSChiYuan Huang bool vsel_high; 244*32a708baSChiYuan Huang int ret; 245*32a708baSChiYuan Huang 246*32a708baSChiYuan Huang desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); 247*32a708baSChiYuan Huang if (!desc) 248*32a708baSChiYuan Huang return -ENOMEM; 249*32a708baSChiYuan Huang 250*32a708baSChiYuan Huang enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); 251*32a708baSChiYuan Huang if (IS_ERR(enable)) 252*32a708baSChiYuan Huang return dev_err_probe(dev, PTR_ERR(enable), "Failed get 'enable' gpio\n"); 253*32a708baSChiYuan Huang 254*32a708baSChiYuan Huang regmap = devm_regmap_init_i2c(i2c, &rt8092_regmap_cfg); 255*32a708baSChiYuan Huang if (IS_ERR(regmap)) 256*32a708baSChiYuan Huang return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); 257*32a708baSChiYuan Huang 258*32a708baSChiYuan Huang vsel_high = device_property_read_bool(dev, "richtek,vsel-active-high"); 259*32a708baSChiYuan Huang 260*32a708baSChiYuan Huang ret = rt8092_get_vbank_index(regmap, vsel_high, &vbank_idx); 261*32a708baSChiYuan Huang if (ret) 262*32a708baSChiYuan Huang return dev_err_probe(dev, ret, "Failed to get VOUT bank index\n"); 263*32a708baSChiYuan Huang 264*32a708baSChiYuan Huang /* 265*32a708baSChiYuan Huang * step VOUT = STEP_UV * 2^vbank_idx 266*32a708baSChiYuan Huang * min VOUT = (BASEUV + STEPUV * VMIN_SEL) * 2^vbank_idx 267*32a708baSChiYuan Huang */ 268*32a708baSChiYuan Huang step_uV = RT8092_VOUT_STEPUV << vbank_idx; 269*32a708baSChiYuan Huang min_uV = (RT8092_VOUT_BASEUV + RT8092_VOUT_STEPUV * RT8092_VOUT_MINSEL) << vbank_idx; 270*32a708baSChiYuan Huang 271*32a708baSChiYuan Huang desc->name = "rt8092"; 272*32a708baSChiYuan Huang desc->owner = THIS_MODULE; 273*32a708baSChiYuan Huang desc->type = REGULATOR_VOLTAGE; 274*32a708baSChiYuan Huang desc->ops = &rt8092_regulator_ops; 275*32a708baSChiYuan Huang desc->n_voltages = RT8092_NUM_VOLTS; 276*32a708baSChiYuan Huang desc->min_uV = min_uV; 277*32a708baSChiYuan Huang desc->uV_step = step_uV; 278*32a708baSChiYuan Huang desc->linear_min_sel = RT8092_VOUT_MINSEL; 279*32a708baSChiYuan Huang desc->enable_reg = desc->vsel_reg = vsel_high ? RT8092_REG_VOUTH : RT8092_REG_VOUTL; 280*32a708baSChiYuan Huang desc->vsel_mask = RT8092_VSEL_MASK; 281*32a708baSChiYuan Huang desc->enable_mask = RT8092_VOUTEN_MASK; 282*32a708baSChiYuan Huang desc->enable_time = RT8092_INITSS_US; 283*32a708baSChiYuan Huang desc->of_map_mode = rt8092_of_map_mode; 284*32a708baSChiYuan Huang 285*32a708baSChiYuan Huang cfg.dev = dev; 286*32a708baSChiYuan Huang cfg.of_node = dev_of_node(dev); 287*32a708baSChiYuan Huang cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc); 288*32a708baSChiYuan Huang 289*32a708baSChiYuan Huang rdev = devm_regulator_register(dev, desc, &cfg); 290*32a708baSChiYuan Huang if (IS_ERR(rdev)) 291*32a708baSChiYuan Huang return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n"); 292*32a708baSChiYuan Huang 293*32a708baSChiYuan Huang return 0; 294*32a708baSChiYuan Huang } 295*32a708baSChiYuan Huang 296*32a708baSChiYuan Huang static const struct of_device_id rt8092_device_tables[] = { 297*32a708baSChiYuan Huang { .compatible = "richtek,rt8092" }, 298*32a708baSChiYuan Huang {} 299*32a708baSChiYuan Huang }; 300*32a708baSChiYuan Huang MODULE_DEVICE_TABLE(of, rt8092_device_tables); 301*32a708baSChiYuan Huang 302*32a708baSChiYuan Huang static struct i2c_driver rt8092_driver = { 303*32a708baSChiYuan Huang .driver = { 304*32a708baSChiYuan Huang .name = "rt8092", 305*32a708baSChiYuan Huang .of_match_table = rt8092_device_tables, 306*32a708baSChiYuan Huang }, 307*32a708baSChiYuan Huang .probe = rt8092_probe, 308*32a708baSChiYuan Huang }; 309*32a708baSChiYuan Huang module_i2c_driver(rt8092_driver); 310*32a708baSChiYuan Huang 311*32a708baSChiYuan Huang MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 312*32a708baSChiYuan Huang MODULE_DESCRIPTION("Richtek RT8092 Regulator Driver"); 313*32a708baSChiYuan Huang MODULE_LICENSE("GPL"); 314