1*760423dfSChiYuan Huang // SPDX-License-Identifier: GPL-2.0+ 2*760423dfSChiYuan Huang 3*760423dfSChiYuan Huang #include <dt-bindings/regulator/richtek,rt5190a-regulator.h> 4*760423dfSChiYuan Huang #include <linux/bits.h> 5*760423dfSChiYuan Huang #include <linux/i2c.h> 6*760423dfSChiYuan Huang #include <linux/interrupt.h> 7*760423dfSChiYuan Huang #include <linux/kernel.h> 8*760423dfSChiYuan Huang #include <linux/module.h> 9*760423dfSChiYuan Huang #include <linux/of.h> 10*760423dfSChiYuan Huang #include <linux/property.h> 11*760423dfSChiYuan Huang #include <linux/regmap.h> 12*760423dfSChiYuan Huang #include <linux/regulator/driver.h> 13*760423dfSChiYuan Huang #include <linux/regulator/machine.h> 14*760423dfSChiYuan Huang #include <linux/regulator/of_regulator.h> 15*760423dfSChiYuan Huang 16*760423dfSChiYuan Huang #define RT5190A_REG_MANUFACTURE 0x00 17*760423dfSChiYuan Huang #define RT5190A_REG_BUCK2VSEL 0x04 18*760423dfSChiYuan Huang #define RT5190A_REG_BUCK3VSEL 0x05 19*760423dfSChiYuan Huang #define RT5190A_REG_DCDCCNTL 0x06 20*760423dfSChiYuan Huang #define RT5190A_REG_ENABLE 0x07 21*760423dfSChiYuan Huang #define RT5190A_REG_DISCHARGE 0x09 22*760423dfSChiYuan Huang #define RT5190A_REG_PROTMODE 0x0A 23*760423dfSChiYuan Huang #define RT5190A_REG_MUTECNTL 0x0B 24*760423dfSChiYuan Huang #define RT5190A_REG_PGSTAT 0x0F 25*760423dfSChiYuan Huang #define RT5190A_REG_OVINT 0x10 26*760423dfSChiYuan Huang #define RT5190A_REG_HOTDIEMASK 0x17 27*760423dfSChiYuan Huang 28*760423dfSChiYuan Huang #define RT5190A_VSEL_MASK GENMASK(6, 0) 29*760423dfSChiYuan Huang #define RT5190A_RID_BITMASK(rid) BIT(rid + 1) 30*760423dfSChiYuan Huang #define RT5190A_BUCK1_DISCHG_MASK GENMASK(1, 0) 31*760423dfSChiYuan Huang #define RT5190A_BUCK1_DISCHG_ONVAL 0x01 32*760423dfSChiYuan Huang #define RT5190A_OVERVOLT_MASK GENMASK(7, 0) 33*760423dfSChiYuan Huang #define RT5190A_UNDERVOLT_MASK GENMASK(15, 8) 34*760423dfSChiYuan Huang #define RT5190A_CH234OT_MASK BIT(29) 35*760423dfSChiYuan Huang #define RT5190A_CHIPOT_MASK BIT(28) 36*760423dfSChiYuan Huang 37*760423dfSChiYuan Huang #define RT5190A_BUCK23_MINUV 600000 38*760423dfSChiYuan Huang #define RT5190A_BUCK23_MAXUV 1400000 39*760423dfSChiYuan Huang #define RT5190A_BUCK23_STEPUV 10000 40*760423dfSChiYuan Huang #define RT5190A_BUCK23_STEPNUM ((1400000 - 600000) / 10000 + 1) 41*760423dfSChiYuan Huang 42*760423dfSChiYuan Huang enum { 43*760423dfSChiYuan Huang RT5190A_IDX_BUCK1 = 0, 44*760423dfSChiYuan Huang RT5190A_IDX_BUCK2, 45*760423dfSChiYuan Huang RT5190A_IDX_BUCK3, 46*760423dfSChiYuan Huang RT5190A_IDX_BUCK4, 47*760423dfSChiYuan Huang RT5190A_IDX_LDO, 48*760423dfSChiYuan Huang RT5190A_MAX_IDX 49*760423dfSChiYuan Huang }; 50*760423dfSChiYuan Huang 51*760423dfSChiYuan Huang struct rt5190a_priv { 52*760423dfSChiYuan Huang struct device *dev; 53*760423dfSChiYuan Huang struct regmap *regmap; 54*760423dfSChiYuan Huang struct regulator_desc rdesc[RT5190A_MAX_IDX]; 55*760423dfSChiYuan Huang struct regulator_dev *rdev[RT5190A_MAX_IDX]; 56*760423dfSChiYuan Huang }; 57*760423dfSChiYuan Huang 58*760423dfSChiYuan Huang static int rt5190a_get_error_flags(struct regulator_dev *rdev, 59*760423dfSChiYuan Huang unsigned int *flags) 60*760423dfSChiYuan Huang { 61*760423dfSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 62*760423dfSChiYuan Huang int rid = rdev_get_id(rdev); 63*760423dfSChiYuan Huang unsigned int pgood_stat; 64*760423dfSChiYuan Huang int ret; 65*760423dfSChiYuan Huang 66*760423dfSChiYuan Huang ret = regmap_read(regmap, RT5190A_REG_PGSTAT, &pgood_stat); 67*760423dfSChiYuan Huang if (ret) 68*760423dfSChiYuan Huang return ret; 69*760423dfSChiYuan Huang 70*760423dfSChiYuan Huang if (!(pgood_stat & RT5190A_RID_BITMASK(rid))) 71*760423dfSChiYuan Huang *flags = REGULATOR_ERROR_FAIL; 72*760423dfSChiYuan Huang else 73*760423dfSChiYuan Huang *flags = 0; 74*760423dfSChiYuan Huang 75*760423dfSChiYuan Huang return 0; 76*760423dfSChiYuan Huang } 77*760423dfSChiYuan Huang 78*760423dfSChiYuan Huang static int rt5190a_fixed_buck_set_mode(struct regulator_dev *rdev, 79*760423dfSChiYuan Huang unsigned int mode) 80*760423dfSChiYuan Huang { 81*760423dfSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 82*760423dfSChiYuan Huang int rid = rdev_get_id(rdev); 83*760423dfSChiYuan Huang unsigned int mask = RT5190A_RID_BITMASK(rid), val; 84*760423dfSChiYuan Huang 85*760423dfSChiYuan Huang switch (mode) { 86*760423dfSChiYuan Huang case REGULATOR_MODE_FAST: 87*760423dfSChiYuan Huang val = mask; 88*760423dfSChiYuan Huang break; 89*760423dfSChiYuan Huang case REGULATOR_MODE_NORMAL: 90*760423dfSChiYuan Huang val = 0; 91*760423dfSChiYuan Huang break; 92*760423dfSChiYuan Huang default: 93*760423dfSChiYuan Huang return -EINVAL; 94*760423dfSChiYuan Huang } 95*760423dfSChiYuan Huang 96*760423dfSChiYuan Huang return regmap_update_bits(regmap, RT5190A_REG_DCDCCNTL, mask, val); 97*760423dfSChiYuan Huang } 98*760423dfSChiYuan Huang 99*760423dfSChiYuan Huang static unsigned int rt5190a_fixed_buck_get_mode(struct regulator_dev *rdev) 100*760423dfSChiYuan Huang { 101*760423dfSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 102*760423dfSChiYuan Huang int rid = rdev_get_id(rdev); 103*760423dfSChiYuan Huang unsigned int val; 104*760423dfSChiYuan Huang int ret; 105*760423dfSChiYuan Huang 106*760423dfSChiYuan Huang ret = regmap_read(regmap, RT5190A_REG_DCDCCNTL, &val); 107*760423dfSChiYuan Huang if (ret) { 108*760423dfSChiYuan Huang dev_err(&rdev->dev, "Failed to get mode [%d]\n", ret); 109*760423dfSChiYuan Huang return ret; 110*760423dfSChiYuan Huang } 111*760423dfSChiYuan Huang 112*760423dfSChiYuan Huang if (val & RT5190A_RID_BITMASK(rid)) 113*760423dfSChiYuan Huang return REGULATOR_MODE_FAST; 114*760423dfSChiYuan Huang 115*760423dfSChiYuan Huang return REGULATOR_MODE_NORMAL; 116*760423dfSChiYuan Huang } 117*760423dfSChiYuan Huang 118*760423dfSChiYuan Huang static const struct regulator_ops rt5190a_ranged_buck_ops = { 119*760423dfSChiYuan Huang .enable = regulator_enable_regmap, 120*760423dfSChiYuan Huang .disable = regulator_disable_regmap, 121*760423dfSChiYuan Huang .is_enabled = regulator_is_enabled_regmap, 122*760423dfSChiYuan Huang .set_voltage_sel = regulator_set_voltage_sel_regmap, 123*760423dfSChiYuan Huang .get_voltage_sel = regulator_get_voltage_sel_regmap, 124*760423dfSChiYuan Huang .list_voltage = regulator_list_voltage_linear, 125*760423dfSChiYuan Huang .set_active_discharge = regulator_set_active_discharge_regmap, 126*760423dfSChiYuan Huang .get_error_flags = rt5190a_get_error_flags, 127*760423dfSChiYuan Huang }; 128*760423dfSChiYuan Huang 129*760423dfSChiYuan Huang static const struct regulator_ops rt5190a_fixed_buck_ops = { 130*760423dfSChiYuan Huang .enable = regulator_enable_regmap, 131*760423dfSChiYuan Huang .disable = regulator_disable_regmap, 132*760423dfSChiYuan Huang .is_enabled = regulator_is_enabled_regmap, 133*760423dfSChiYuan Huang .set_active_discharge = regulator_set_active_discharge_regmap, 134*760423dfSChiYuan Huang .set_mode = rt5190a_fixed_buck_set_mode, 135*760423dfSChiYuan Huang .get_mode = rt5190a_fixed_buck_get_mode, 136*760423dfSChiYuan Huang .get_error_flags = rt5190a_get_error_flags, 137*760423dfSChiYuan Huang }; 138*760423dfSChiYuan Huang 139*760423dfSChiYuan Huang static const struct regulator_ops rt5190a_fixed_ldo_ops = { 140*760423dfSChiYuan Huang .enable = regulator_enable_regmap, 141*760423dfSChiYuan Huang .disable = regulator_disable_regmap, 142*760423dfSChiYuan Huang .is_enabled = regulator_is_enabled_regmap, 143*760423dfSChiYuan Huang .set_active_discharge = regulator_set_active_discharge_regmap, 144*760423dfSChiYuan Huang .get_error_flags = rt5190a_get_error_flags, 145*760423dfSChiYuan Huang }; 146*760423dfSChiYuan Huang 147*760423dfSChiYuan Huang static irqreturn_t rt5190a_irq_handler(int irq, void *data) 148*760423dfSChiYuan Huang { 149*760423dfSChiYuan Huang struct rt5190a_priv *priv = data; 150*760423dfSChiYuan Huang __le32 raws; 151*760423dfSChiYuan Huang unsigned int events, fields; 152*760423dfSChiYuan Huang static const struct { 153*760423dfSChiYuan Huang unsigned int bitmask; 154*760423dfSChiYuan Huang unsigned int report; 155*760423dfSChiYuan Huang } event_tbl[] = { 156*760423dfSChiYuan Huang { RT5190A_OVERVOLT_MASK, REGULATOR_ERROR_REGULATION_OUT }, 157*760423dfSChiYuan Huang { RT5190A_UNDERVOLT_MASK, REGULATOR_ERROR_UNDER_VOLTAGE } 158*760423dfSChiYuan Huang }; 159*760423dfSChiYuan Huang int i, j, ret; 160*760423dfSChiYuan Huang 161*760423dfSChiYuan Huang ret = regmap_raw_read(priv->regmap, RT5190A_REG_OVINT, &raws, 162*760423dfSChiYuan Huang sizeof(raws)); 163*760423dfSChiYuan Huang if (ret) { 164*760423dfSChiYuan Huang dev_err(priv->dev, "Failed to read events\n"); 165*760423dfSChiYuan Huang return IRQ_NONE; 166*760423dfSChiYuan Huang } 167*760423dfSChiYuan Huang 168*760423dfSChiYuan Huang events = le32_to_cpu(raws); 169*760423dfSChiYuan Huang 170*760423dfSChiYuan Huang ret = regmap_raw_write(priv->regmap, RT5190A_REG_OVINT, &raws, 171*760423dfSChiYuan Huang sizeof(raws)); 172*760423dfSChiYuan Huang if (ret) 173*760423dfSChiYuan Huang dev_err(priv->dev, "Failed to write-clear events\n"); 174*760423dfSChiYuan Huang 175*760423dfSChiYuan Huang /* Handle OV,UV events */ 176*760423dfSChiYuan Huang for (i = 0; i < ARRAY_SIZE(event_tbl); i++) { 177*760423dfSChiYuan Huang fields = events & event_tbl[i].bitmask; 178*760423dfSChiYuan Huang fields >>= ffs(event_tbl[i].bitmask) - 1; 179*760423dfSChiYuan Huang 180*760423dfSChiYuan Huang for (j = 0; j < RT5190A_MAX_IDX; j++) { 181*760423dfSChiYuan Huang if (!(fields & RT5190A_RID_BITMASK(j))) 182*760423dfSChiYuan Huang continue; 183*760423dfSChiYuan Huang 184*760423dfSChiYuan Huang regulator_notifier_call_chain(priv->rdev[j], 185*760423dfSChiYuan Huang event_tbl[i].report, 186*760423dfSChiYuan Huang NULL); 187*760423dfSChiYuan Huang } 188*760423dfSChiYuan Huang } 189*760423dfSChiYuan Huang 190*760423dfSChiYuan Huang /* Handle CH234 OT event */ 191*760423dfSChiYuan Huang if (events & RT5190A_CH234OT_MASK) { 192*760423dfSChiYuan Huang for (j = RT5190A_IDX_BUCK2; j < RT5190A_IDX_LDO; j++) { 193*760423dfSChiYuan Huang regulator_notifier_call_chain(priv->rdev[j], 194*760423dfSChiYuan Huang REGULATOR_ERROR_OVER_TEMP, 195*760423dfSChiYuan Huang NULL); 196*760423dfSChiYuan Huang } 197*760423dfSChiYuan Huang } 198*760423dfSChiYuan Huang 199*760423dfSChiYuan Huang /* Warning if CHIP OT occur */ 200*760423dfSChiYuan Huang if (events & RT5190A_CHIPOT_MASK) 201*760423dfSChiYuan Huang dev_warn(priv->dev, "CHIP overheat\n"); 202*760423dfSChiYuan Huang 203*760423dfSChiYuan Huang return IRQ_HANDLED; 204*760423dfSChiYuan Huang } 205*760423dfSChiYuan Huang 206*760423dfSChiYuan Huang static unsigned int rt5190a_of_map_mode(unsigned int mode) 207*760423dfSChiYuan Huang { 208*760423dfSChiYuan Huang switch (mode) { 209*760423dfSChiYuan Huang case RT5190A_OPMODE_AUTO: 210*760423dfSChiYuan Huang return REGULATOR_MODE_NORMAL; 211*760423dfSChiYuan Huang case RT5190A_OPMODE_FPWM: 212*760423dfSChiYuan Huang return REGULATOR_MODE_FAST; 213*760423dfSChiYuan Huang default: 214*760423dfSChiYuan Huang return REGULATOR_MODE_INVALID; 215*760423dfSChiYuan Huang } 216*760423dfSChiYuan Huang } 217*760423dfSChiYuan Huang 218*760423dfSChiYuan Huang static int rt5190a_of_parse_cb(struct rt5190a_priv *priv, int rid, 219*760423dfSChiYuan Huang struct of_regulator_match *match) 220*760423dfSChiYuan Huang { 221*760423dfSChiYuan Huang struct regulator_desc *desc = priv->rdesc + rid; 222*760423dfSChiYuan Huang struct regulator_init_data *init_data = match->init_data; 223*760423dfSChiYuan Huang struct device_node *np = match->of_node; 224*760423dfSChiYuan Huang bool latchup_enable; 225*760423dfSChiYuan Huang unsigned int mask = RT5190A_RID_BITMASK(rid), val; 226*760423dfSChiYuan Huang 227*760423dfSChiYuan Huang switch (rid) { 228*760423dfSChiYuan Huang case RT5190A_IDX_BUCK1: 229*760423dfSChiYuan Huang case RT5190A_IDX_BUCK4: 230*760423dfSChiYuan Huang case RT5190A_IDX_LDO: 231*760423dfSChiYuan Huang init_data->constraints.apply_uV = 0; 232*760423dfSChiYuan Huang 233*760423dfSChiYuan Huang if (init_data->constraints.min_uV == 234*760423dfSChiYuan Huang init_data->constraints.max_uV) 235*760423dfSChiYuan Huang desc->fixed_uV = init_data->constraints.min_uV; 236*760423dfSChiYuan Huang else { 237*760423dfSChiYuan Huang dev_err(priv->dev, 238*760423dfSChiYuan Huang "Variable voltage for fixed regulator\n"); 239*760423dfSChiYuan Huang return -EINVAL; 240*760423dfSChiYuan Huang } 241*760423dfSChiYuan Huang break; 242*760423dfSChiYuan Huang default: 243*760423dfSChiYuan Huang break; 244*760423dfSChiYuan Huang } 245*760423dfSChiYuan Huang 246*760423dfSChiYuan Huang latchup_enable = of_property_read_bool(np, "richtek,latchup-enable"); 247*760423dfSChiYuan Huang 248*760423dfSChiYuan Huang /* latchup: 0, default hiccup: 1 */ 249*760423dfSChiYuan Huang val = !latchup_enable ? mask : 0; 250*760423dfSChiYuan Huang 251*760423dfSChiYuan Huang return regmap_update_bits(priv->regmap, RT5190A_REG_PROTMODE, mask, val); 252*760423dfSChiYuan Huang } 253*760423dfSChiYuan Huang 254*760423dfSChiYuan Huang static void rt5190a_fillin_regulator_desc(struct regulator_desc *desc, int rid) 255*760423dfSChiYuan Huang { 256*760423dfSChiYuan Huang static const char * const regu_name[] = { "buck1", "buck2", 257*760423dfSChiYuan Huang "buck3", "buck4", 258*760423dfSChiYuan Huang "ldo" }; 259*760423dfSChiYuan Huang static const char * const supply[] = { NULL, "vin2", "vin3", "vin4", 260*760423dfSChiYuan Huang "vinldo" }; 261*760423dfSChiYuan Huang 262*760423dfSChiYuan Huang desc->name = regu_name[rid]; 263*760423dfSChiYuan Huang desc->supply_name = supply[rid]; 264*760423dfSChiYuan Huang desc->owner = THIS_MODULE; 265*760423dfSChiYuan Huang desc->type = REGULATOR_VOLTAGE; 266*760423dfSChiYuan Huang desc->id = rid; 267*760423dfSChiYuan Huang desc->enable_reg = RT5190A_REG_ENABLE; 268*760423dfSChiYuan Huang desc->enable_mask = RT5190A_RID_BITMASK(rid); 269*760423dfSChiYuan Huang desc->active_discharge_reg = RT5190A_REG_DISCHARGE; 270*760423dfSChiYuan Huang desc->active_discharge_mask = RT5190A_RID_BITMASK(rid); 271*760423dfSChiYuan Huang desc->active_discharge_on = RT5190A_RID_BITMASK(rid); 272*760423dfSChiYuan Huang 273*760423dfSChiYuan Huang switch (rid) { 274*760423dfSChiYuan Huang case RT5190A_IDX_BUCK1: 275*760423dfSChiYuan Huang desc->active_discharge_mask = RT5190A_BUCK1_DISCHG_MASK; 276*760423dfSChiYuan Huang desc->active_discharge_on = RT5190A_BUCK1_DISCHG_ONVAL; 277*760423dfSChiYuan Huang desc->n_voltages = 1; 278*760423dfSChiYuan Huang desc->ops = &rt5190a_fixed_buck_ops; 279*760423dfSChiYuan Huang desc->of_map_mode = rt5190a_of_map_mode; 280*760423dfSChiYuan Huang break; 281*760423dfSChiYuan Huang case RT5190A_IDX_BUCK2: 282*760423dfSChiYuan Huang desc->vsel_reg = RT5190A_REG_BUCK2VSEL; 283*760423dfSChiYuan Huang desc->vsel_mask = RT5190A_VSEL_MASK; 284*760423dfSChiYuan Huang desc->min_uV = RT5190A_BUCK23_MINUV; 285*760423dfSChiYuan Huang desc->uV_step = RT5190A_BUCK23_STEPUV; 286*760423dfSChiYuan Huang desc->n_voltages = RT5190A_BUCK23_STEPNUM; 287*760423dfSChiYuan Huang desc->ops = &rt5190a_ranged_buck_ops; 288*760423dfSChiYuan Huang break; 289*760423dfSChiYuan Huang case RT5190A_IDX_BUCK3: 290*760423dfSChiYuan Huang desc->vsel_reg = RT5190A_REG_BUCK3VSEL; 291*760423dfSChiYuan Huang desc->vsel_mask = RT5190A_VSEL_MASK; 292*760423dfSChiYuan Huang desc->min_uV = RT5190A_BUCK23_MINUV; 293*760423dfSChiYuan Huang desc->uV_step = RT5190A_BUCK23_STEPUV; 294*760423dfSChiYuan Huang desc->n_voltages = RT5190A_BUCK23_STEPNUM; 295*760423dfSChiYuan Huang desc->ops = &rt5190a_ranged_buck_ops; 296*760423dfSChiYuan Huang break; 297*760423dfSChiYuan Huang case RT5190A_IDX_BUCK4: 298*760423dfSChiYuan Huang desc->n_voltages = 1; 299*760423dfSChiYuan Huang desc->ops = &rt5190a_fixed_buck_ops; 300*760423dfSChiYuan Huang desc->of_map_mode = rt5190a_of_map_mode; 301*760423dfSChiYuan Huang break; 302*760423dfSChiYuan Huang case RT5190A_IDX_LDO: 303*760423dfSChiYuan Huang desc->n_voltages = 1; 304*760423dfSChiYuan Huang desc->ops = &rt5190a_fixed_ldo_ops; 305*760423dfSChiYuan Huang break; 306*760423dfSChiYuan Huang } 307*760423dfSChiYuan Huang } 308*760423dfSChiYuan Huang 309*760423dfSChiYuan Huang static struct of_regulator_match rt5190a_regulator_match[] = { 310*760423dfSChiYuan Huang { .name = "buck1", }, 311*760423dfSChiYuan Huang { .name = "buck2", }, 312*760423dfSChiYuan Huang { .name = "buck3", }, 313*760423dfSChiYuan Huang { .name = "buck4", }, 314*760423dfSChiYuan Huang { .name = "ldo", } 315*760423dfSChiYuan Huang }; 316*760423dfSChiYuan Huang 317*760423dfSChiYuan Huang static int rt5190a_parse_regulator_dt_data(struct rt5190a_priv *priv) 318*760423dfSChiYuan Huang { 319*760423dfSChiYuan Huang struct device_node *regulator_np; 320*760423dfSChiYuan Huang struct regulator_desc *reg_desc; 321*760423dfSChiYuan Huang struct of_regulator_match *match; 322*760423dfSChiYuan Huang int i, ret; 323*760423dfSChiYuan Huang 324*760423dfSChiYuan Huang for (i = 0; i < RT5190A_MAX_IDX; i++) { 325*760423dfSChiYuan Huang reg_desc = priv->rdesc + i; 326*760423dfSChiYuan Huang match = rt5190a_regulator_match + i; 327*760423dfSChiYuan Huang 328*760423dfSChiYuan Huang rt5190a_fillin_regulator_desc(reg_desc, i); 329*760423dfSChiYuan Huang 330*760423dfSChiYuan Huang match->desc = reg_desc; 331*760423dfSChiYuan Huang } 332*760423dfSChiYuan Huang 333*760423dfSChiYuan Huang regulator_np = of_get_child_by_name(priv->dev->of_node, "regulators"); 334*760423dfSChiYuan Huang if (!regulator_np) { 335*760423dfSChiYuan Huang dev_err(priv->dev, "Could not find 'regulators' node\n"); 336*760423dfSChiYuan Huang return -ENODEV; 337*760423dfSChiYuan Huang } 338*760423dfSChiYuan Huang 339*760423dfSChiYuan Huang ret = of_regulator_match(priv->dev, regulator_np, 340*760423dfSChiYuan Huang rt5190a_regulator_match, 341*760423dfSChiYuan Huang ARRAY_SIZE(rt5190a_regulator_match)); 342*760423dfSChiYuan Huang 343*760423dfSChiYuan Huang of_node_put(regulator_np); 344*760423dfSChiYuan Huang 345*760423dfSChiYuan Huang if (ret < 0) { 346*760423dfSChiYuan Huang dev_err(priv->dev, 347*760423dfSChiYuan Huang "Error parsing regulator init data: %d\n", ret); 348*760423dfSChiYuan Huang return ret; 349*760423dfSChiYuan Huang } 350*760423dfSChiYuan Huang 351*760423dfSChiYuan Huang for (i = 0; i < RT5190A_MAX_IDX; i++) { 352*760423dfSChiYuan Huang match = rt5190a_regulator_match + i; 353*760423dfSChiYuan Huang 354*760423dfSChiYuan Huang ret = rt5190a_of_parse_cb(priv, i, match); 355*760423dfSChiYuan Huang if (ret) { 356*760423dfSChiYuan Huang dev_err(priv->dev, "Failed in [%d] of_parse_cb\n", i); 357*760423dfSChiYuan Huang return ret; 358*760423dfSChiYuan Huang } 359*760423dfSChiYuan Huang } 360*760423dfSChiYuan Huang 361*760423dfSChiYuan Huang return 0; 362*760423dfSChiYuan Huang } 363*760423dfSChiYuan Huang 364*760423dfSChiYuan Huang static const struct reg_sequence rt5190a_init_patch[] = { 365*760423dfSChiYuan Huang { 0x09, 0x3d, }, 366*760423dfSChiYuan Huang { 0x0a, 0x3e, }, 367*760423dfSChiYuan Huang { 0x0b, 0x01, }, 368*760423dfSChiYuan Huang { 0x10, 0xff, }, 369*760423dfSChiYuan Huang { 0x11, 0xff, }, 370*760423dfSChiYuan Huang { 0x12, 0xff, }, 371*760423dfSChiYuan Huang { 0x13, 0xff, }, 372*760423dfSChiYuan Huang { 0x14, 0, }, 373*760423dfSChiYuan Huang { 0x15, 0, }, 374*760423dfSChiYuan Huang { 0x16, 0x3e, }, 375*760423dfSChiYuan Huang { 0x17, 0, } 376*760423dfSChiYuan Huang }; 377*760423dfSChiYuan Huang 378*760423dfSChiYuan Huang static int rt5190a_device_initialize(struct rt5190a_priv *priv) 379*760423dfSChiYuan Huang { 380*760423dfSChiYuan Huang bool mute_enable; 381*760423dfSChiYuan Huang int ret; 382*760423dfSChiYuan Huang 383*760423dfSChiYuan Huang ret = regmap_register_patch(priv->regmap, rt5190a_init_patch, 384*760423dfSChiYuan Huang ARRAY_SIZE(rt5190a_init_patch)); 385*760423dfSChiYuan Huang if (ret) { 386*760423dfSChiYuan Huang dev_err(priv->dev, "Failed to do register patch\n"); 387*760423dfSChiYuan Huang return ret; 388*760423dfSChiYuan Huang } 389*760423dfSChiYuan Huang 390*760423dfSChiYuan Huang mute_enable = device_property_read_bool(priv->dev, 391*760423dfSChiYuan Huang "richtek,mute-enable"); 392*760423dfSChiYuan Huang 393*760423dfSChiYuan Huang if (mute_enable) { 394*760423dfSChiYuan Huang ret = regmap_write(priv->regmap, RT5190A_REG_MUTECNTL, 0x00); 395*760423dfSChiYuan Huang if (ret) { 396*760423dfSChiYuan Huang dev_err(priv->dev, "Failed to enable mute function\n"); 397*760423dfSChiYuan Huang return ret; 398*760423dfSChiYuan Huang } 399*760423dfSChiYuan Huang } 400*760423dfSChiYuan Huang 401*760423dfSChiYuan Huang return 0; 402*760423dfSChiYuan Huang } 403*760423dfSChiYuan Huang 404*760423dfSChiYuan Huang static int rt5190a_device_check(struct rt5190a_priv *priv) 405*760423dfSChiYuan Huang { 406*760423dfSChiYuan Huang u16 devid; 407*760423dfSChiYuan Huang int ret; 408*760423dfSChiYuan Huang 409*760423dfSChiYuan Huang ret = regmap_raw_read(priv->regmap, RT5190A_REG_MANUFACTURE, &devid, 410*760423dfSChiYuan Huang sizeof(devid)); 411*760423dfSChiYuan Huang if (ret) 412*760423dfSChiYuan Huang return ret; 413*760423dfSChiYuan Huang 414*760423dfSChiYuan Huang if (devid) { 415*760423dfSChiYuan Huang dev_err(priv->dev, "Incorrect device id 0x%04x\n", devid); 416*760423dfSChiYuan Huang return -ENODEV; 417*760423dfSChiYuan Huang } 418*760423dfSChiYuan Huang 419*760423dfSChiYuan Huang return 0; 420*760423dfSChiYuan Huang } 421*760423dfSChiYuan Huang 422*760423dfSChiYuan Huang static const struct regmap_config rt5190a_regmap_config = { 423*760423dfSChiYuan Huang .reg_bits = 8, 424*760423dfSChiYuan Huang .val_bits = 8, 425*760423dfSChiYuan Huang .max_register = RT5190A_REG_HOTDIEMASK, 426*760423dfSChiYuan Huang }; 427*760423dfSChiYuan Huang 428*760423dfSChiYuan Huang static int rt5190a_probe(struct i2c_client *i2c) 429*760423dfSChiYuan Huang { 430*760423dfSChiYuan Huang struct rt5190a_priv *priv; 431*760423dfSChiYuan Huang struct regulator_config cfg = {}; 432*760423dfSChiYuan Huang int i, ret; 433*760423dfSChiYuan Huang 434*760423dfSChiYuan Huang priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); 435*760423dfSChiYuan Huang if (!priv) 436*760423dfSChiYuan Huang return -ENOMEM; 437*760423dfSChiYuan Huang 438*760423dfSChiYuan Huang priv->dev = &i2c->dev; 439*760423dfSChiYuan Huang 440*760423dfSChiYuan Huang priv->regmap = devm_regmap_init_i2c(i2c, &rt5190a_regmap_config); 441*760423dfSChiYuan Huang if (IS_ERR(priv->regmap)) { 442*760423dfSChiYuan Huang dev_err(&i2c->dev, "Failed to allocate regmap\n"); 443*760423dfSChiYuan Huang return PTR_ERR(priv->regmap); 444*760423dfSChiYuan Huang } 445*760423dfSChiYuan Huang 446*760423dfSChiYuan Huang ret = rt5190a_device_check(priv); 447*760423dfSChiYuan Huang if (ret) { 448*760423dfSChiYuan Huang dev_err(&i2c->dev, "Failed to check device %d\n", ret); 449*760423dfSChiYuan Huang return ret; 450*760423dfSChiYuan Huang } 451*760423dfSChiYuan Huang 452*760423dfSChiYuan Huang ret = rt5190a_device_initialize(priv); 453*760423dfSChiYuan Huang if (ret) { 454*760423dfSChiYuan Huang dev_err(&i2c->dev, "Failed to initialize the device\n"); 455*760423dfSChiYuan Huang return ret; 456*760423dfSChiYuan Huang } 457*760423dfSChiYuan Huang 458*760423dfSChiYuan Huang ret = rt5190a_parse_regulator_dt_data(priv); 459*760423dfSChiYuan Huang if (ret) { 460*760423dfSChiYuan Huang dev_err(&i2c->dev, "Failed to parse regulator dt\n"); 461*760423dfSChiYuan Huang return ret; 462*760423dfSChiYuan Huang } 463*760423dfSChiYuan Huang 464*760423dfSChiYuan Huang cfg.dev = &i2c->dev; 465*760423dfSChiYuan Huang cfg.regmap = priv->regmap; 466*760423dfSChiYuan Huang 467*760423dfSChiYuan Huang for (i = 0; i < RT5190A_MAX_IDX; i++) { 468*760423dfSChiYuan Huang struct regulator_desc *desc = priv->rdesc + i; 469*760423dfSChiYuan Huang struct of_regulator_match *match = rt5190a_regulator_match + i; 470*760423dfSChiYuan Huang 471*760423dfSChiYuan Huang cfg.init_data = match->init_data; 472*760423dfSChiYuan Huang cfg.of_node = match->of_node; 473*760423dfSChiYuan Huang 474*760423dfSChiYuan Huang priv->rdev[i] = devm_regulator_register(&i2c->dev, desc, &cfg); 475*760423dfSChiYuan Huang if (IS_ERR(priv->rdev[i])) { 476*760423dfSChiYuan Huang dev_err(&i2c->dev, "Failed to register regulator %s\n", 477*760423dfSChiYuan Huang desc->name); 478*760423dfSChiYuan Huang return PTR_ERR(priv->rdev[i]); 479*760423dfSChiYuan Huang } 480*760423dfSChiYuan Huang } 481*760423dfSChiYuan Huang 482*760423dfSChiYuan Huang if (i2c->irq) { 483*760423dfSChiYuan Huang ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, 484*760423dfSChiYuan Huang rt5190a_irq_handler, 485*760423dfSChiYuan Huang IRQF_ONESHOT, 486*760423dfSChiYuan Huang dev_name(&i2c->dev), priv); 487*760423dfSChiYuan Huang if (ret) { 488*760423dfSChiYuan Huang dev_err(&i2c->dev, "Failed to register interrupt\n"); 489*760423dfSChiYuan Huang return ret; 490*760423dfSChiYuan Huang } 491*760423dfSChiYuan Huang } 492*760423dfSChiYuan Huang 493*760423dfSChiYuan Huang return 0; 494*760423dfSChiYuan Huang } 495*760423dfSChiYuan Huang 496*760423dfSChiYuan Huang static const struct of_device_id __maybe_unused rt5190a_device_table[] = { 497*760423dfSChiYuan Huang { .compatible = "richtek,rt5190a", }, 498*760423dfSChiYuan Huang {} 499*760423dfSChiYuan Huang }; 500*760423dfSChiYuan Huang MODULE_DEVICE_TABLE(of, rt5190a_device_table); 501*760423dfSChiYuan Huang 502*760423dfSChiYuan Huang static struct i2c_driver rt5190a_driver = { 503*760423dfSChiYuan Huang .driver = { 504*760423dfSChiYuan Huang .name = "rt5190a", 505*760423dfSChiYuan Huang .of_match_table = rt5190a_device_table, 506*760423dfSChiYuan Huang }, 507*760423dfSChiYuan Huang .probe_new = rt5190a_probe, 508*760423dfSChiYuan Huang }; 509*760423dfSChiYuan Huang module_i2c_driver(rt5190a_driver); 510*760423dfSChiYuan Huang 511*760423dfSChiYuan Huang MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 512*760423dfSChiYuan Huang MODULE_DESCRIPTION("Richtek RT5190A Regulator Driver"); 513*760423dfSChiYuan Huang MODULE_LICENSE("GPL v2"); 514