1*b497e1a1SWoodrow Douglass // SPDX-License-Identifier: GPL-2.0+ 2*b497e1a1SWoodrow Douglass 3*b497e1a1SWoodrow Douglass // documentation of this device is available at 4*b497e1a1SWoodrow Douglass // https://www.nxp.com/docs/en/data-sheet/PF5300.pdf 5*b497e1a1SWoodrow Douglass 6*b497e1a1SWoodrow Douglass #include <linux/delay.h> 7*b497e1a1SWoodrow Douglass #include <linux/err.h> 8*b497e1a1SWoodrow Douglass #include <linux/gpio/consumer.h> 9*b497e1a1SWoodrow Douglass #include <linux/i2c.h> 10*b497e1a1SWoodrow Douglass #include <linux/module.h> 11*b497e1a1SWoodrow Douglass #include <linux/regmap.h> 12*b497e1a1SWoodrow Douglass #include <linux/regulator/driver.h> 13*b497e1a1SWoodrow Douglass #include <linux/regulator/consumer.h> 14*b497e1a1SWoodrow Douglass #include <linux/regulator/machine.h> 15*b497e1a1SWoodrow Douglass #include <linux/regulator/of_regulator.h> 16*b497e1a1SWoodrow Douglass 17*b497e1a1SWoodrow Douglass /* registers */ 18*b497e1a1SWoodrow Douglass #define PF530X_DEVICEID 0x00 19*b497e1a1SWoodrow Douglass #define PF530X_REV 0x01 20*b497e1a1SWoodrow Douglass #define PF530X_EMREV 0x02 21*b497e1a1SWoodrow Douglass #define PF530X_PROGID 0x03 22*b497e1a1SWoodrow Douglass #define PF530X_CONFIG1 0x04 23*b497e1a1SWoodrow Douglass #define PF530X_INT_STATUS1 0x05 24*b497e1a1SWoodrow Douglass #define PF530X_INT_SENSE1 0x06 25*b497e1a1SWoodrow Douglass #define PF530X_INT_STATUS2 0x07 26*b497e1a1SWoodrow Douglass #define PF530X_INT_SENSE2 0x08 27*b497e1a1SWoodrow Douglass #define PF530X_BIST_STAT1 0x09 28*b497e1a1SWoodrow Douglass #define PF530X_BIST_CTRL 0x0a 29*b497e1a1SWoodrow Douglass #define PF530X_STATE 0x0b 30*b497e1a1SWoodrow Douglass #define PF530X_STATE_CTRL 0x0c 31*b497e1a1SWoodrow Douglass #define PF530X_SW1_VOLT 0x0d 32*b497e1a1SWoodrow Douglass #define PF530X_SW1_STBY_VOLT 0x0e 33*b497e1a1SWoodrow Douglass #define PF530X_SW1_CTRL1 0x0f 34*b497e1a1SWoodrow Douglass #define PF530X_SW1_CTRL2 0x10 35*b497e1a1SWoodrow Douglass #define PF530X_CLK_CTRL 0x11 36*b497e1a1SWoodrow Douglass #define PF530X_SEQ_CTRL1 0x12 37*b497e1a1SWoodrow Douglass #define PF530X_SEQ_CTRL2 0x13 38*b497e1a1SWoodrow Douglass #define PF530X_RANDOM_CHK 0x14 39*b497e1a1SWoodrow Douglass #define PF530X_RANDOM_GEN 0x15 40*b497e1a1SWoodrow Douglass #define PF530X_WD_CTRL1 0x16 41*b497e1a1SWoodrow Douglass #define PF530X_WD_SEED 0x17 42*b497e1a1SWoodrow Douglass #define PF530X_WD_ANSWER 0x18 43*b497e1a1SWoodrow Douglass #define PF530X_FLT_CNT1 0x19 44*b497e1a1SWoodrow Douglass #define PF530X_FLT_CNT2 0x1a 45*b497e1a1SWoodrow Douglass #define PF530X_OTP_MODE 0x2f 46*b497e1a1SWoodrow Douglass 47*b497e1a1SWoodrow Douglass enum pf530x_states { 48*b497e1a1SWoodrow Douglass PF530X_STATE_POF, 49*b497e1a1SWoodrow Douglass PF530X_STATE_FUSE_LOAD, 50*b497e1a1SWoodrow Douglass PF530X_STATE_LP_OFF, 51*b497e1a1SWoodrow Douglass PF530X_STATE_SELF_TEST, 52*b497e1a1SWoodrow Douglass PF530X_STATE_POWER_UP, 53*b497e1a1SWoodrow Douglass PF530X_STATE_INIT, 54*b497e1a1SWoodrow Douglass PF530X_STATE_IO_RELEASE, 55*b497e1a1SWoodrow Douglass PF530X_STATE_RUN, 56*b497e1a1SWoodrow Douglass PF530X_STATE_STANDBY, 57*b497e1a1SWoodrow Douglass PF530X_STATE_FAULT, 58*b497e1a1SWoodrow Douglass PF530X_STATE_FAILSAFE, 59*b497e1a1SWoodrow Douglass PF530X_STATE_POWER_DOWN, 60*b497e1a1SWoodrow Douglass PF530X_STATE_2MS_SELFTEST_RETRY, 61*b497e1a1SWoodrow Douglass PF530X_STATE_OFF_DLY, 62*b497e1a1SWoodrow Douglass }; 63*b497e1a1SWoodrow Douglass 64*b497e1a1SWoodrow Douglass #define PF530_FAM 0x50 65*b497e1a1SWoodrow Douglass enum pf530x_devid { 66*b497e1a1SWoodrow Douglass PF5300 = 0x3, 67*b497e1a1SWoodrow Douglass PF5301 = 0x4, 68*b497e1a1SWoodrow Douglass PF5302 = 0x5, 69*b497e1a1SWoodrow Douglass }; 70*b497e1a1SWoodrow Douglass 71*b497e1a1SWoodrow Douglass #define PF530x_FAM 0x50 72*b497e1a1SWoodrow Douglass #define PF530x_DEVICE_FAM_MASK GENMASK(7, 4) 73*b497e1a1SWoodrow Douglass #define PF530x_DEVICE_ID_MASK GENMASK(3, 0) 74*b497e1a1SWoodrow Douglass 75*b497e1a1SWoodrow Douglass #define PF530x_STATE_MASK GENMASK(3, 0) 76*b497e1a1SWoodrow Douglass #define PF530x_STATE_RUN 0x07 77*b497e1a1SWoodrow Douglass #define PF530x_STATE_STANDBY 0x08 78*b497e1a1SWoodrow Douglass #define PF530x_STATE_LP_OFF 0x02 79*b497e1a1SWoodrow Douglass 80*b497e1a1SWoodrow Douglass #define PF530X_OTP_STBY_MODE GENMASK(3, 2) 81*b497e1a1SWoodrow Douglass #define PF530X_OTP_RUN_MODE GENMASK(1, 0) 82*b497e1a1SWoodrow Douglass 83*b497e1a1SWoodrow Douglass #define PF530X_INT_STATUS_OV BIT(1) 84*b497e1a1SWoodrow Douglass #define PF530X_INT_STATUS_UV BIT(2) 85*b497e1a1SWoodrow Douglass #define PF530X_INT_STATUS_ILIM BIT(3) 86*b497e1a1SWoodrow Douglass 87*b497e1a1SWoodrow Douglass #define SW1_ILIM_S BIT(0) 88*b497e1a1SWoodrow Douglass #define VMON_UV_S BIT(1) 89*b497e1a1SWoodrow Douglass #define VMON_OV_S BIT(2) 90*b497e1a1SWoodrow Douglass #define VIN_OVLO_S BIT(3) 91*b497e1a1SWoodrow Douglass #define BG_ERR_S BIT(6) 92*b497e1a1SWoodrow Douglass 93*b497e1a1SWoodrow Douglass #define THERM_155_S BIT(3) 94*b497e1a1SWoodrow Douglass #define THERM_140_S BIT(2) 95*b497e1a1SWoodrow Douglass #define THERM_125_S BIT(1) 96*b497e1a1SWoodrow Douglass #define THERM_110_S BIT(0) 97*b497e1a1SWoodrow Douglass 98*b497e1a1SWoodrow Douglass struct pf530x_chip { 99*b497e1a1SWoodrow Douglass struct regmap *regmap; 100*b497e1a1SWoodrow Douglass struct device *dev; 101*b497e1a1SWoodrow Douglass }; 102*b497e1a1SWoodrow Douglass 103*b497e1a1SWoodrow Douglass static const struct regmap_config pf530x_regmap_config = { 104*b497e1a1SWoodrow Douglass .reg_bits = 8, 105*b497e1a1SWoodrow Douglass .val_bits = 8, 106*b497e1a1SWoodrow Douglass .max_register = PF530X_OTP_MODE, 107*b497e1a1SWoodrow Douglass .cache_type = REGCACHE_MAPLE, 108*b497e1a1SWoodrow Douglass }; 109*b497e1a1SWoodrow Douglass 110*b497e1a1SWoodrow Douglass static int pf530x_get_status(struct regulator_dev *rdev) 111*b497e1a1SWoodrow Douglass { 112*b497e1a1SWoodrow Douglass unsigned int state; 113*b497e1a1SWoodrow Douglass int ret; 114*b497e1a1SWoodrow Douglass 115*b497e1a1SWoodrow Douglass ret = regmap_read(rdev->regmap, PF530X_INT_SENSE1, &state); 116*b497e1a1SWoodrow Douglass if (ret != 0) 117*b497e1a1SWoodrow Douglass return ret; 118*b497e1a1SWoodrow Douglass 119*b497e1a1SWoodrow Douglass if ((state & (BG_ERR_S | SW1_ILIM_S | VMON_UV_S | VMON_OV_S | VIN_OVLO_S)) 120*b497e1a1SWoodrow Douglass != 0) 121*b497e1a1SWoodrow Douglass return REGULATOR_STATUS_ERROR; 122*b497e1a1SWoodrow Douglass 123*b497e1a1SWoodrow Douglass // no errors, check if what non-error state we're in 124*b497e1a1SWoodrow Douglass ret = regmap_read(rdev->regmap, PF530X_STATE, &state); 125*b497e1a1SWoodrow Douglass if (ret != 0) 126*b497e1a1SWoodrow Douglass return ret; 127*b497e1a1SWoodrow Douglass 128*b497e1a1SWoodrow Douglass state &= PF530x_STATE_MASK; 129*b497e1a1SWoodrow Douglass 130*b497e1a1SWoodrow Douglass switch (state) { 131*b497e1a1SWoodrow Douglass case PF530x_STATE_RUN: 132*b497e1a1SWoodrow Douglass ret = REGULATOR_STATUS_NORMAL; 133*b497e1a1SWoodrow Douglass break; 134*b497e1a1SWoodrow Douglass case PF530x_STATE_STANDBY: 135*b497e1a1SWoodrow Douglass ret = REGULATOR_STATUS_STANDBY; 136*b497e1a1SWoodrow Douglass break; 137*b497e1a1SWoodrow Douglass case PF530x_STATE_LP_OFF: 138*b497e1a1SWoodrow Douglass ret = REGULATOR_STATUS_OFF; 139*b497e1a1SWoodrow Douglass break; 140*b497e1a1SWoodrow Douglass default: 141*b497e1a1SWoodrow Douglass ret = REGULATOR_STATUS_ERROR; 142*b497e1a1SWoodrow Douglass break; 143*b497e1a1SWoodrow Douglass } 144*b497e1a1SWoodrow Douglass return ret; 145*b497e1a1SWoodrow Douglass } 146*b497e1a1SWoodrow Douglass 147*b497e1a1SWoodrow Douglass static int pf530x_get_error_flags(struct regulator_dev *rdev, unsigned int *flags) 148*b497e1a1SWoodrow Douglass { 149*b497e1a1SWoodrow Douglass unsigned int status; 150*b497e1a1SWoodrow Douglass int ret; 151*b497e1a1SWoodrow Douglass 152*b497e1a1SWoodrow Douglass ret = regmap_read(rdev->regmap, PF530X_INT_STATUS1, &status); 153*b497e1a1SWoodrow Douglass 154*b497e1a1SWoodrow Douglass if (ret != 0) 155*b497e1a1SWoodrow Douglass return ret; 156*b497e1a1SWoodrow Douglass 157*b497e1a1SWoodrow Douglass *flags = 0; 158*b497e1a1SWoodrow Douglass 159*b497e1a1SWoodrow Douglass if (status & PF530X_INT_STATUS_OV) 160*b497e1a1SWoodrow Douglass *flags |= REGULATOR_ERROR_OVER_VOLTAGE_WARN; 161*b497e1a1SWoodrow Douglass 162*b497e1a1SWoodrow Douglass if (status & PF530X_INT_STATUS_UV) 163*b497e1a1SWoodrow Douglass *flags |= REGULATOR_ERROR_UNDER_VOLTAGE; 164*b497e1a1SWoodrow Douglass 165*b497e1a1SWoodrow Douglass if (status & PF530X_INT_STATUS_ILIM) 166*b497e1a1SWoodrow Douglass *flags |= REGULATOR_ERROR_OVER_CURRENT; 167*b497e1a1SWoodrow Douglass 168*b497e1a1SWoodrow Douglass ret = regmap_read(rdev->regmap, PF530X_INT_SENSE2, &status); 169*b497e1a1SWoodrow Douglass 170*b497e1a1SWoodrow Douglass if (ret != 0) 171*b497e1a1SWoodrow Douglass return ret; 172*b497e1a1SWoodrow Douglass 173*b497e1a1SWoodrow Douglass if ((status & (THERM_155_S | 174*b497e1a1SWoodrow Douglass THERM_140_S | 175*b497e1a1SWoodrow Douglass THERM_125_S | 176*b497e1a1SWoodrow Douglass THERM_110_S)) != 0) 177*b497e1a1SWoodrow Douglass *flags |= REGULATOR_ERROR_OVER_TEMP_WARN; 178*b497e1a1SWoodrow Douglass 179*b497e1a1SWoodrow Douglass return 0; 180*b497e1a1SWoodrow Douglass } 181*b497e1a1SWoodrow Douglass 182*b497e1a1SWoodrow Douglass static const struct regulator_ops pf530x_regulator_ops = { 183*b497e1a1SWoodrow Douglass .enable = regulator_enable_regmap, 184*b497e1a1SWoodrow Douglass .disable = regulator_disable_regmap, 185*b497e1a1SWoodrow Douglass .is_enabled = regulator_is_enabled_regmap, 186*b497e1a1SWoodrow Douglass .map_voltage = regulator_map_voltage_linear_range, 187*b497e1a1SWoodrow Douglass .list_voltage = regulator_list_voltage_linear_range, 188*b497e1a1SWoodrow Douglass .set_voltage_sel = regulator_set_voltage_sel_regmap, 189*b497e1a1SWoodrow Douglass .get_voltage_sel = regulator_get_voltage_sel_regmap, 190*b497e1a1SWoodrow Douglass .get_status = pf530x_get_status, 191*b497e1a1SWoodrow Douglass .get_error_flags = pf530x_get_error_flags, 192*b497e1a1SWoodrow Douglass .set_bypass = regulator_set_bypass_regmap, 193*b497e1a1SWoodrow Douglass .get_bypass = regulator_get_bypass_regmap, 194*b497e1a1SWoodrow Douglass }; 195*b497e1a1SWoodrow Douglass 196*b497e1a1SWoodrow Douglass static const struct linear_range vrange = REGULATOR_LINEAR_RANGE(500000, 0, 140, 5000); 197*b497e1a1SWoodrow Douglass 198*b497e1a1SWoodrow Douglass static const struct regulator_desc pf530x_reg_desc = { 199*b497e1a1SWoodrow Douglass .name = "SW1", 200*b497e1a1SWoodrow Douglass .ops = &pf530x_regulator_ops, 201*b497e1a1SWoodrow Douglass .linear_ranges = &vrange, 202*b497e1a1SWoodrow Douglass .n_linear_ranges = 1, 203*b497e1a1SWoodrow Douglass .type = REGULATOR_VOLTAGE, 204*b497e1a1SWoodrow Douglass .id = 0, 205*b497e1a1SWoodrow Douglass .owner = THIS_MODULE, 206*b497e1a1SWoodrow Douglass .vsel_reg = PF530X_SW1_VOLT, 207*b497e1a1SWoodrow Douglass .vsel_mask = 0xFF, 208*b497e1a1SWoodrow Douglass .bypass_reg = PF530X_SW1_CTRL2, 209*b497e1a1SWoodrow Douglass .bypass_mask = 0x07, 210*b497e1a1SWoodrow Douglass .bypass_val_on = 0x07, 211*b497e1a1SWoodrow Douglass .bypass_val_off = 0x00, 212*b497e1a1SWoodrow Douglass .enable_reg = PF530X_SW1_CTRL1, 213*b497e1a1SWoodrow Douglass .enable_mask = GENMASK(5, 2), 214*b497e1a1SWoodrow Douglass .enable_val = GENMASK(5, 2), 215*b497e1a1SWoodrow Douglass .disable_val = 0, 216*b497e1a1SWoodrow Douglass }; 217*b497e1a1SWoodrow Douglass 218*b497e1a1SWoodrow Douglass static int pf530x_identify(struct pf530x_chip *chip) 219*b497e1a1SWoodrow Douglass { 220*b497e1a1SWoodrow Douglass unsigned int value; 221*b497e1a1SWoodrow Douglass u8 dev_fam, dev_id, full_layer_rev, metal_layer_rev, prog_idh, prog_idl, emrev; 222*b497e1a1SWoodrow Douglass const char *name = NULL; 223*b497e1a1SWoodrow Douglass int ret; 224*b497e1a1SWoodrow Douglass 225*b497e1a1SWoodrow Douglass ret = regmap_read(chip->regmap, PF530X_DEVICEID, &value); 226*b497e1a1SWoodrow Douglass if (ret) { 227*b497e1a1SWoodrow Douglass dev_err(chip->dev, "failed to read chip family\n"); 228*b497e1a1SWoodrow Douglass return ret; 229*b497e1a1SWoodrow Douglass } 230*b497e1a1SWoodrow Douglass 231*b497e1a1SWoodrow Douglass dev_fam = value & PF530x_DEVICE_FAM_MASK; 232*b497e1a1SWoodrow Douglass switch (dev_fam) { 233*b497e1a1SWoodrow Douglass case PF530x_FAM: 234*b497e1a1SWoodrow Douglass break; 235*b497e1a1SWoodrow Douglass default: 236*b497e1a1SWoodrow Douglass dev_err(chip->dev, 237*b497e1a1SWoodrow Douglass "Chip 0x%x is not from PF530X family\n", dev_fam); 238*b497e1a1SWoodrow Douglass return ret; 239*b497e1a1SWoodrow Douglass } 240*b497e1a1SWoodrow Douglass 241*b497e1a1SWoodrow Douglass dev_id = value & PF530x_DEVICE_ID_MASK; 242*b497e1a1SWoodrow Douglass switch (dev_id) { 243*b497e1a1SWoodrow Douglass case PF5300: 244*b497e1a1SWoodrow Douglass name = "PF5300"; 245*b497e1a1SWoodrow Douglass break; 246*b497e1a1SWoodrow Douglass case PF5301: 247*b497e1a1SWoodrow Douglass name = "PF5301"; 248*b497e1a1SWoodrow Douglass break; 249*b497e1a1SWoodrow Douglass case PF5302: 250*b497e1a1SWoodrow Douglass name = "PF5302"; 251*b497e1a1SWoodrow Douglass break; 252*b497e1a1SWoodrow Douglass default: 253*b497e1a1SWoodrow Douglass dev_err(chip->dev, "Unknown pf530x device id 0x%x\n", dev_id); 254*b497e1a1SWoodrow Douglass return -ENODEV; 255*b497e1a1SWoodrow Douglass } 256*b497e1a1SWoodrow Douglass 257*b497e1a1SWoodrow Douglass ret = regmap_read(chip->regmap, PF530X_REV, &value); 258*b497e1a1SWoodrow Douglass if (ret) { 259*b497e1a1SWoodrow Douglass dev_err(chip->dev, "failed to read chip rev\n"); 260*b497e1a1SWoodrow Douglass return ret; 261*b497e1a1SWoodrow Douglass } 262*b497e1a1SWoodrow Douglass 263*b497e1a1SWoodrow Douglass full_layer_rev = ((value & 0xF0) == 0) ? '0' : ((((value & 0xF0) >> 4) - 1) + 'A'); 264*b497e1a1SWoodrow Douglass metal_layer_rev = value & 0xF; 265*b497e1a1SWoodrow Douglass 266*b497e1a1SWoodrow Douglass ret = regmap_read(chip->regmap, PF530X_EMREV, &value); 267*b497e1a1SWoodrow Douglass if (ret) { 268*b497e1a1SWoodrow Douglass dev_err(chip->dev, "failed to read chip emrev register\n"); 269*b497e1a1SWoodrow Douglass return ret; 270*b497e1a1SWoodrow Douglass } 271*b497e1a1SWoodrow Douglass 272*b497e1a1SWoodrow Douglass prog_idh = (value >> 4) + 'A'; 273*b497e1a1SWoodrow Douglass // prog_idh skips 'O', per page 96 of the datasheet 274*b497e1a1SWoodrow Douglass if (prog_idh >= 'O') 275*b497e1a1SWoodrow Douglass prog_idh += 1; 276*b497e1a1SWoodrow Douglass 277*b497e1a1SWoodrow Douglass emrev = value & 0x7; 278*b497e1a1SWoodrow Douglass 279*b497e1a1SWoodrow Douglass ret = regmap_read(chip->regmap, PF530X_PROGID, &value); 280*b497e1a1SWoodrow Douglass if (ret) { 281*b497e1a1SWoodrow Douglass dev_err(chip->dev, "failed to read chip progid register\n"); 282*b497e1a1SWoodrow Douglass return ret; 283*b497e1a1SWoodrow Douglass } 284*b497e1a1SWoodrow Douglass 285*b497e1a1SWoodrow Douglass if (value >= 0x22) { 286*b497e1a1SWoodrow Douglass dev_err(chip->dev, "invalid value for progid register\n"); 287*b497e1a1SWoodrow Douglass return -ENODEV; 288*b497e1a1SWoodrow Douglass } else if (value < 10) { 289*b497e1a1SWoodrow Douglass prog_idl = value + '0'; 290*b497e1a1SWoodrow Douglass } else { 291*b497e1a1SWoodrow Douglass prog_idl = (value - 10) + 'A'; 292*b497e1a1SWoodrow Douglass // prog_idh skips 'O', per page 97 of the datasheet 293*b497e1a1SWoodrow Douglass if (prog_idl >= 'O') 294*b497e1a1SWoodrow Douglass prog_idl += 1; 295*b497e1a1SWoodrow Douglass } 296*b497e1a1SWoodrow Douglass 297*b497e1a1SWoodrow Douglass dev_info(chip->dev, "%s Regulator found (Rev %c%d ProgID %c%c EMREV %x).\n", 298*b497e1a1SWoodrow Douglass name, full_layer_rev, metal_layer_rev, prog_idh, prog_idl, emrev); 299*b497e1a1SWoodrow Douglass 300*b497e1a1SWoodrow Douglass return 0; 301*b497e1a1SWoodrow Douglass } 302*b497e1a1SWoodrow Douglass 303*b497e1a1SWoodrow Douglass static int pf530x_i2c_probe(struct i2c_client *client) 304*b497e1a1SWoodrow Douglass { 305*b497e1a1SWoodrow Douglass struct regulator_config config = { NULL, }; 306*b497e1a1SWoodrow Douglass struct pf530x_chip *chip; 307*b497e1a1SWoodrow Douglass int ret; 308*b497e1a1SWoodrow Douglass struct regulator_dev *rdev; 309*b497e1a1SWoodrow Douglass struct regulator_init_data *init_data; 310*b497e1a1SWoodrow Douglass 311*b497e1a1SWoodrow Douglass chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 312*b497e1a1SWoodrow Douglass if (!chip) 313*b497e1a1SWoodrow Douglass return -ENOMEM; 314*b497e1a1SWoodrow Douglass 315*b497e1a1SWoodrow Douglass i2c_set_clientdata(client, chip); 316*b497e1a1SWoodrow Douglass chip->dev = &client->dev; 317*b497e1a1SWoodrow Douglass 318*b497e1a1SWoodrow Douglass chip->regmap = devm_regmap_init_i2c(client, &pf530x_regmap_config); 319*b497e1a1SWoodrow Douglass if (IS_ERR(chip->regmap)) { 320*b497e1a1SWoodrow Douglass ret = PTR_ERR(chip->regmap); 321*b497e1a1SWoodrow Douglass dev_err(&client->dev, 322*b497e1a1SWoodrow Douglass "regmap allocation failed with err %d\n", ret); 323*b497e1a1SWoodrow Douglass return ret; 324*b497e1a1SWoodrow Douglass } 325*b497e1a1SWoodrow Douglass 326*b497e1a1SWoodrow Douglass ret = pf530x_identify(chip); 327*b497e1a1SWoodrow Douglass if (ret) 328*b497e1a1SWoodrow Douglass return ret; 329*b497e1a1SWoodrow Douglass 330*b497e1a1SWoodrow Douglass init_data = of_get_regulator_init_data(chip->dev, chip->dev->of_node, &pf530x_reg_desc); 331*b497e1a1SWoodrow Douglass if (!init_data) 332*b497e1a1SWoodrow Douglass return -ENODATA; 333*b497e1a1SWoodrow Douglass 334*b497e1a1SWoodrow Douglass config.dev = chip->dev; 335*b497e1a1SWoodrow Douglass config.of_node = chip->dev->of_node; 336*b497e1a1SWoodrow Douglass config.regmap = chip->regmap; 337*b497e1a1SWoodrow Douglass config.init_data = init_data; 338*b497e1a1SWoodrow Douglass 339*b497e1a1SWoodrow Douglass // the config parameter gets copied, it's ok to pass a pointer on the stack here 340*b497e1a1SWoodrow Douglass rdev = devm_regulator_register(&client->dev, &pf530x_reg_desc, &config); 341*b497e1a1SWoodrow Douglass if (IS_ERR(rdev)) { 342*b497e1a1SWoodrow Douglass dev_err(&client->dev, "failed to register %s regulator\n", pf530x_reg_desc.name); 343*b497e1a1SWoodrow Douglass return PTR_ERR(rdev); 344*b497e1a1SWoodrow Douglass } 345*b497e1a1SWoodrow Douglass 346*b497e1a1SWoodrow Douglass return 0; 347*b497e1a1SWoodrow Douglass } 348*b497e1a1SWoodrow Douglass 349*b497e1a1SWoodrow Douglass static const struct of_device_id pf530x_dt_ids[] = { 350*b497e1a1SWoodrow Douglass { .compatible = "nxp,pf5300",}, 351*b497e1a1SWoodrow Douglass { } 352*b497e1a1SWoodrow Douglass }; 353*b497e1a1SWoodrow Douglass MODULE_DEVICE_TABLE(of, pf530x_dt_ids); 354*b497e1a1SWoodrow Douglass 355*b497e1a1SWoodrow Douglass static const struct i2c_device_id pf530x_i2c_id[] = { 356*b497e1a1SWoodrow Douglass { "pf5300", 0 }, 357*b497e1a1SWoodrow Douglass { "pf5301", 0 }, 358*b497e1a1SWoodrow Douglass { "pf5302", 0 }, 359*b497e1a1SWoodrow Douglass {}, 360*b497e1a1SWoodrow Douglass }; 361*b497e1a1SWoodrow Douglass MODULE_DEVICE_TABLE(i2c, pf530x_i2c_id); 362*b497e1a1SWoodrow Douglass 363*b497e1a1SWoodrow Douglass static struct i2c_driver pf530x_regulator_driver = { 364*b497e1a1SWoodrow Douglass .id_table = pf530x_i2c_id, 365*b497e1a1SWoodrow Douglass .driver = { 366*b497e1a1SWoodrow Douglass .name = "pf530x", 367*b497e1a1SWoodrow Douglass .of_match_table = pf530x_dt_ids, 368*b497e1a1SWoodrow Douglass }, 369*b497e1a1SWoodrow Douglass .probe = pf530x_i2c_probe, 370*b497e1a1SWoodrow Douglass }; 371*b497e1a1SWoodrow Douglass module_i2c_driver(pf530x_regulator_driver); 372*b497e1a1SWoodrow Douglass 373*b497e1a1SWoodrow Douglass MODULE_AUTHOR("Woodrow Douglass <wdouglass@carnegierobotics.com>"); 374*b497e1a1SWoodrow Douglass MODULE_DESCRIPTION("Regulator Driver for NXP's PF5300/PF5301/PF5302 PMIC"); 375*b497e1a1SWoodrow Douglass MODULE_LICENSE("GPL"); 376