1*37b918a0STim Harvey /* 2*37b918a0STim Harvey * Copyright (C) 2016 Gateworks Corporation, Inc. All Rights Reserved. 3*37b918a0STim Harvey * 4*37b918a0STim Harvey * This program is free software; you can redistribute it and/or modify 5*37b918a0STim Harvey * it under the terms of the GNU General Public License version 2 6*37b918a0STim Harvey * as published by the Free Software Foundation. 7*37b918a0STim Harvey * 8*37b918a0STim Harvey * This program is distributed in the hope that it will be useful, 9*37b918a0STim Harvey * but WITHOUT ANY WARRANTY; without even the implied warranty of 10*37b918a0STim Harvey * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11*37b918a0STim Harvey * GNU General Public License for more details. 12*37b918a0STim Harvey * 13*37b918a0STim Harvey */ 14*37b918a0STim Harvey #include <linux/i2c.h> 15*37b918a0STim Harvey #include <linux/init.h> 16*37b918a0STim Harvey #include <linux/interrupt.h> 17*37b918a0STim Harvey #include <linux/module.h> 18*37b918a0STim Harvey #include <linux/kernel.h> 19*37b918a0STim Harvey #include <linux/of.h> 20*37b918a0STim Harvey #include <linux/regmap.h> 21*37b918a0STim Harvey #include <linux/regulator/driver.h> 22*37b918a0STim Harvey #include <linux/regulator/machine.h> 23*37b918a0STim Harvey #include <linux/regulator/of_regulator.h> 24*37b918a0STim Harvey 25*37b918a0STim Harvey #define DRIVER_NAME "ltc3676" 26*37b918a0STim Harvey 27*37b918a0STim Harvey /* LTC3676 Registers */ 28*37b918a0STim Harvey #define LTC3676_BUCK1 0x01 29*37b918a0STim Harvey #define LTC3676_BUCK2 0x02 30*37b918a0STim Harvey #define LTC3676_BUCK3 0x03 31*37b918a0STim Harvey #define LTC3676_BUCK4 0x04 32*37b918a0STim Harvey #define LTC3676_LDOA 0x05 33*37b918a0STim Harvey #define LTC3676_LDOB 0x06 34*37b918a0STim Harvey #define LTC3676_SQD1 0x07 35*37b918a0STim Harvey #define LTC3676_SQD2 0x08 36*37b918a0STim Harvey #define LTC3676_CNTRL 0x09 37*37b918a0STim Harvey #define LTC3676_DVB1A 0x0A 38*37b918a0STim Harvey #define LTC3676_DVB1B 0x0B 39*37b918a0STim Harvey #define LTC3676_DVB2A 0x0C 40*37b918a0STim Harvey #define LTC3676_DVB2B 0x0D 41*37b918a0STim Harvey #define LTC3676_DVB3A 0x0E 42*37b918a0STim Harvey #define LTC3676_DVB3B 0x0F 43*37b918a0STim Harvey #define LTC3676_DVB4A 0x10 44*37b918a0STim Harvey #define LTC3676_DVB4B 0x11 45*37b918a0STim Harvey #define LTC3676_MSKIRQ 0x12 46*37b918a0STim Harvey #define LTC3676_MSKPG 0x13 47*37b918a0STim Harvey #define LTC3676_USER 0x14 48*37b918a0STim Harvey #define LTC3676_IRQSTAT 0x15 49*37b918a0STim Harvey #define LTC3676_PGSTATL 0x16 50*37b918a0STim Harvey #define LTC3676_PGSTATRT 0x17 51*37b918a0STim Harvey #define LTC3676_HRST 0x1E 52*37b918a0STim Harvey #define LTC3676_CLIRQ 0x1F 53*37b918a0STim Harvey 54*37b918a0STim Harvey #define LTC3676_DVBxA_REF_SELECT BIT(5) 55*37b918a0STim Harvey 56*37b918a0STim Harvey #define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3) 57*37b918a0STim Harvey #define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4) 58*37b918a0STim Harvey #define LTC3676_IRQSTAT_UNDERVOLT_FAULT BIT(5) 59*37b918a0STim Harvey #define LTC3676_IRQSTAT_THERMAL_WARN BIT(6) 60*37b918a0STim Harvey #define LTC3676_IRQSTAT_THERMAL_FAULT BIT(7) 61*37b918a0STim Harvey 62*37b918a0STim Harvey enum ltc3676_reg { 63*37b918a0STim Harvey LTC3676_SW1, 64*37b918a0STim Harvey LTC3676_SW2, 65*37b918a0STim Harvey LTC3676_SW3, 66*37b918a0STim Harvey LTC3676_SW4, 67*37b918a0STim Harvey LTC3676_LDO1, 68*37b918a0STim Harvey LTC3676_LDO2, 69*37b918a0STim Harvey LTC3676_LDO3, 70*37b918a0STim Harvey LTC3676_LDO4, 71*37b918a0STim Harvey LTC3676_NUM_REGULATORS, 72*37b918a0STim Harvey }; 73*37b918a0STim Harvey 74*37b918a0STim Harvey struct ltc3676 { 75*37b918a0STim Harvey struct regmap *regmap; 76*37b918a0STim Harvey struct device *dev; 77*37b918a0STim Harvey struct regulator_desc regulator_descs[LTC3676_NUM_REGULATORS]; 78*37b918a0STim Harvey struct regulator_dev *regulators[LTC3676_NUM_REGULATORS]; 79*37b918a0STim Harvey }; 80*37b918a0STim Harvey 81*37b918a0STim Harvey static int ltc3676_set_suspend_voltage(struct regulator_dev *rdev, int uV) 82*37b918a0STim Harvey { 83*37b918a0STim Harvey struct ltc3676 *ltc3676 = rdev_get_drvdata(rdev); 84*37b918a0STim Harvey struct device *dev = ltc3676->dev; 85*37b918a0STim Harvey int dcdc = rdev_get_id(rdev); 86*37b918a0STim Harvey int sel; 87*37b918a0STim Harvey 88*37b918a0STim Harvey dev_dbg(dev, "%s id=%d uV=%d\n", __func__, dcdc, uV); 89*37b918a0STim Harvey sel = regulator_map_voltage_linear(rdev, uV, uV); 90*37b918a0STim Harvey if (sel < 0) 91*37b918a0STim Harvey return sel; 92*37b918a0STim Harvey 93*37b918a0STim Harvey /* DVBB register follows right after the corresponding DVBA register */ 94*37b918a0STim Harvey return regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg + 1, 95*37b918a0STim Harvey rdev->desc->vsel_mask, sel); 96*37b918a0STim Harvey } 97*37b918a0STim Harvey 98*37b918a0STim Harvey static int ltc3676_set_suspend_mode(struct regulator_dev *rdev, 99*37b918a0STim Harvey unsigned int mode) 100*37b918a0STim Harvey { 101*37b918a0STim Harvey struct ltc3676 *ltc3676= rdev_get_drvdata(rdev); 102*37b918a0STim Harvey struct device *dev = ltc3676->dev; 103*37b918a0STim Harvey int mask, val; 104*37b918a0STim Harvey int dcdc = rdev_get_id(rdev); 105*37b918a0STim Harvey 106*37b918a0STim Harvey dev_dbg(dev, "%s id=%d mode=%d\n", __func__, dcdc, mode); 107*37b918a0STim Harvey 108*37b918a0STim Harvey mask = LTC3676_DVBxA_REF_SELECT; 109*37b918a0STim Harvey switch (mode) { 110*37b918a0STim Harvey case REGULATOR_MODE_STANDBY: 111*37b918a0STim Harvey val = 0; /* select DVBxA */ 112*37b918a0STim Harvey break; 113*37b918a0STim Harvey case REGULATOR_MODE_NORMAL: 114*37b918a0STim Harvey val = LTC3676_DVBxA_REF_SELECT; /* select DVBxB */ 115*37b918a0STim Harvey break; 116*37b918a0STim Harvey default: 117*37b918a0STim Harvey dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", 118*37b918a0STim Harvey rdev->desc->name, mode); 119*37b918a0STim Harvey return -EINVAL; 120*37b918a0STim Harvey } 121*37b918a0STim Harvey 122*37b918a0STim Harvey return regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg, 123*37b918a0STim Harvey mask, val); 124*37b918a0STim Harvey } 125*37b918a0STim Harvey 126*37b918a0STim Harvey static inline unsigned int ltc3676_scale(unsigned int uV, u32 r1, u32 r2) 127*37b918a0STim Harvey { 128*37b918a0STim Harvey uint64_t tmp; 129*37b918a0STim Harvey if (uV == 0) 130*37b918a0STim Harvey return 0; 131*37b918a0STim Harvey tmp = (uint64_t)uV * r1; 132*37b918a0STim Harvey do_div(tmp, r2); 133*37b918a0STim Harvey return uV + (unsigned int)tmp; 134*37b918a0STim Harvey } 135*37b918a0STim Harvey 136*37b918a0STim Harvey static int ltc3676_of_parse_cb(struct device_node *np, 137*37b918a0STim Harvey const struct regulator_desc *desc, 138*37b918a0STim Harvey struct regulator_config *config) 139*37b918a0STim Harvey { 140*37b918a0STim Harvey struct ltc3676 *ltc3676 = config->driver_data; 141*37b918a0STim Harvey struct regulator_desc *rdesc = <c3676->regulator_descs[desc->id]; 142*37b918a0STim Harvey u32 r[2]; 143*37b918a0STim Harvey int ret; 144*37b918a0STim Harvey 145*37b918a0STim Harvey /* LDO3 has a fixed output */ 146*37b918a0STim Harvey if (desc->id == LTC3676_LDO3) 147*37b918a0STim Harvey return 0; 148*37b918a0STim Harvey 149*37b918a0STim Harvey ret = of_property_read_u32_array(np, "lltc,fb-voltage-divider", r, 2); 150*37b918a0STim Harvey if (ret) { 151*37b918a0STim Harvey dev_err(ltc3676->dev, "Failed to parse voltage divider: %d\n", 152*37b918a0STim Harvey ret); 153*37b918a0STim Harvey return ret; 154*37b918a0STim Harvey } 155*37b918a0STim Harvey 156*37b918a0STim Harvey rdesc->min_uV = ltc3676_scale(desc->min_uV, r[0], r[1]); 157*37b918a0STim Harvey rdesc->uV_step = ltc3676_scale(desc->uV_step, r[0], r[1]); 158*37b918a0STim Harvey rdesc->fixed_uV = ltc3676_scale(desc->fixed_uV, r[0], r[1]); 159*37b918a0STim Harvey 160*37b918a0STim Harvey return 0; 161*37b918a0STim Harvey } 162*37b918a0STim Harvey 163*37b918a0STim Harvey /* SW1, SW2, SW3, SW4 linear 0.8V-3.3V with scalar via R1/R2 feeback res */ 164*37b918a0STim Harvey static struct regulator_ops ltc3676_linear_regulator_ops = { 165*37b918a0STim Harvey .enable = regulator_enable_regmap, 166*37b918a0STim Harvey .disable = regulator_disable_regmap, 167*37b918a0STim Harvey .is_enabled = regulator_is_enabled_regmap, 168*37b918a0STim Harvey .list_voltage = regulator_list_voltage_linear, 169*37b918a0STim Harvey .set_voltage_sel = regulator_set_voltage_sel_regmap, 170*37b918a0STim Harvey .get_voltage_sel = regulator_get_voltage_sel_regmap, 171*37b918a0STim Harvey .set_suspend_voltage = ltc3676_set_suspend_voltage, 172*37b918a0STim Harvey .set_suspend_mode = ltc3676_set_suspend_mode, 173*37b918a0STim Harvey }; 174*37b918a0STim Harvey 175*37b918a0STim Harvey /* LDO1 always on fixed 0.8V-3.3V via scalar via R1/R2 feeback res */ 176*37b918a0STim Harvey static struct regulator_ops ltc3676_fixed_standby_regulator_ops = { 177*37b918a0STim Harvey }; 178*37b918a0STim Harvey 179*37b918a0STim Harvey /* LDO2, LDO3 fixed (LDO2 has external scalar via R1/R2 feedback res) */ 180*37b918a0STim Harvey static struct regulator_ops ltc3676_fixed_regulator_ops = { 181*37b918a0STim Harvey .enable = regulator_enable_regmap, 182*37b918a0STim Harvey .disable = regulator_disable_regmap, 183*37b918a0STim Harvey .is_enabled = regulator_is_enabled_regmap, 184*37b918a0STim Harvey }; 185*37b918a0STim Harvey 186*37b918a0STim Harvey #define LTC3676_REG(_id, _name, _ops, en_reg, en_bit, dvba_reg, dvb_mask) \ 187*37b918a0STim Harvey [LTC3676_ ## _id] = { \ 188*37b918a0STim Harvey .name = #_name, \ 189*37b918a0STim Harvey .of_match = of_match_ptr(#_name), \ 190*37b918a0STim Harvey .regulators_node = of_match_ptr("regulators"), \ 191*37b918a0STim Harvey .of_parse_cb = ltc3676_of_parse_cb, \ 192*37b918a0STim Harvey .n_voltages = (dvb_mask) + 1, \ 193*37b918a0STim Harvey .min_uV = (dvba_reg) ? 412500 : 0, \ 194*37b918a0STim Harvey .uV_step = (dvba_reg) ? 12500 : 0, \ 195*37b918a0STim Harvey .ramp_delay = (dvba_reg) ? 800 : 0, \ 196*37b918a0STim Harvey .fixed_uV = (dvb_mask) ? 0 : 725000, \ 197*37b918a0STim Harvey .ops = <c3676_ ## _ops ## _regulator_ops, \ 198*37b918a0STim Harvey .type = REGULATOR_VOLTAGE, \ 199*37b918a0STim Harvey .id = LTC3676_ ## _id, \ 200*37b918a0STim Harvey .owner = THIS_MODULE, \ 201*37b918a0STim Harvey .vsel_reg = (dvba_reg), \ 202*37b918a0STim Harvey .vsel_mask = (dvb_mask), \ 203*37b918a0STim Harvey .enable_reg = (en_reg), \ 204*37b918a0STim Harvey .enable_mask = (1 << en_bit), \ 205*37b918a0STim Harvey } 206*37b918a0STim Harvey 207*37b918a0STim Harvey #define LTC3676_LINEAR_REG(_id, _name, _en, _dvba) \ 208*37b918a0STim Harvey LTC3676_REG(_id, _name, linear, \ 209*37b918a0STim Harvey LTC3676_ ## _en, 7, \ 210*37b918a0STim Harvey LTC3676_ ## _dvba, 0x1f) 211*37b918a0STim Harvey 212*37b918a0STim Harvey #define LTC3676_FIXED_REG(_id, _name, _en_reg, _en_bit) \ 213*37b918a0STim Harvey LTC3676_REG(_id, _name, fixed, LTC3676_ ## _en_reg, _en_bit, 0, 0) 214*37b918a0STim Harvey 215*37b918a0STim Harvey static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = { 216*37b918a0STim Harvey LTC3676_LINEAR_REG(SW1, sw1, BUCK1, DVB1A), 217*37b918a0STim Harvey LTC3676_LINEAR_REG(SW2, sw2, BUCK2, DVB2A), 218*37b918a0STim Harvey LTC3676_LINEAR_REG(SW3, sw3, BUCK3, DVB3A), 219*37b918a0STim Harvey LTC3676_LINEAR_REG(SW4, sw4, BUCK4, DVB4A), 220*37b918a0STim Harvey LTC3676_REG(LDO1, ldo1, fixed_standby, 0, 0, 0, 0), 221*37b918a0STim Harvey LTC3676_FIXED_REG(LDO2, ldo2, LDOA, 2), 222*37b918a0STim Harvey LTC3676_FIXED_REG(LDO3, ldo3, LDOA, 5), 223*37b918a0STim Harvey LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2), 224*37b918a0STim Harvey }; 225*37b918a0STim Harvey 226*37b918a0STim Harvey static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg) 227*37b918a0STim Harvey { 228*37b918a0STim Harvey switch (reg) { 229*37b918a0STim Harvey case LTC3676_IRQSTAT: 230*37b918a0STim Harvey case LTC3676_BUCK1: 231*37b918a0STim Harvey case LTC3676_BUCK2: 232*37b918a0STim Harvey case LTC3676_BUCK3: 233*37b918a0STim Harvey case LTC3676_BUCK4: 234*37b918a0STim Harvey case LTC3676_LDOA: 235*37b918a0STim Harvey case LTC3676_LDOB: 236*37b918a0STim Harvey case LTC3676_SQD1: 237*37b918a0STim Harvey case LTC3676_SQD2: 238*37b918a0STim Harvey case LTC3676_CNTRL: 239*37b918a0STim Harvey case LTC3676_DVB1A: 240*37b918a0STim Harvey case LTC3676_DVB1B: 241*37b918a0STim Harvey case LTC3676_DVB2A: 242*37b918a0STim Harvey case LTC3676_DVB2B: 243*37b918a0STim Harvey case LTC3676_DVB3A: 244*37b918a0STim Harvey case LTC3676_DVB3B: 245*37b918a0STim Harvey case LTC3676_DVB4A: 246*37b918a0STim Harvey case LTC3676_DVB4B: 247*37b918a0STim Harvey case LTC3676_MSKIRQ: 248*37b918a0STim Harvey case LTC3676_MSKPG: 249*37b918a0STim Harvey case LTC3676_USER: 250*37b918a0STim Harvey case LTC3676_HRST: 251*37b918a0STim Harvey case LTC3676_CLIRQ: 252*37b918a0STim Harvey return true; 253*37b918a0STim Harvey } 254*37b918a0STim Harvey return false; 255*37b918a0STim Harvey } 256*37b918a0STim Harvey 257*37b918a0STim Harvey static bool ltc3676_readable_reg(struct device *dev, unsigned int reg) 258*37b918a0STim Harvey { 259*37b918a0STim Harvey switch (reg) { 260*37b918a0STim Harvey case LTC3676_IRQSTAT: 261*37b918a0STim Harvey case LTC3676_BUCK1: 262*37b918a0STim Harvey case LTC3676_BUCK2: 263*37b918a0STim Harvey case LTC3676_BUCK3: 264*37b918a0STim Harvey case LTC3676_BUCK4: 265*37b918a0STim Harvey case LTC3676_LDOA: 266*37b918a0STim Harvey case LTC3676_LDOB: 267*37b918a0STim Harvey case LTC3676_SQD1: 268*37b918a0STim Harvey case LTC3676_SQD2: 269*37b918a0STim Harvey case LTC3676_CNTRL: 270*37b918a0STim Harvey case LTC3676_DVB1A: 271*37b918a0STim Harvey case LTC3676_DVB1B: 272*37b918a0STim Harvey case LTC3676_DVB2A: 273*37b918a0STim Harvey case LTC3676_DVB2B: 274*37b918a0STim Harvey case LTC3676_DVB3A: 275*37b918a0STim Harvey case LTC3676_DVB3B: 276*37b918a0STim Harvey case LTC3676_DVB4A: 277*37b918a0STim Harvey case LTC3676_DVB4B: 278*37b918a0STim Harvey case LTC3676_MSKIRQ: 279*37b918a0STim Harvey case LTC3676_MSKPG: 280*37b918a0STim Harvey case LTC3676_USER: 281*37b918a0STim Harvey case LTC3676_HRST: 282*37b918a0STim Harvey case LTC3676_CLIRQ: 283*37b918a0STim Harvey return true; 284*37b918a0STim Harvey } 285*37b918a0STim Harvey return false; 286*37b918a0STim Harvey } 287*37b918a0STim Harvey 288*37b918a0STim Harvey static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg) 289*37b918a0STim Harvey { 290*37b918a0STim Harvey switch (reg) { 291*37b918a0STim Harvey case LTC3676_IRQSTAT: 292*37b918a0STim Harvey case LTC3676_PGSTATL: 293*37b918a0STim Harvey case LTC3676_PGSTATRT: 294*37b918a0STim Harvey return true; 295*37b918a0STim Harvey } 296*37b918a0STim Harvey return false; 297*37b918a0STim Harvey } 298*37b918a0STim Harvey 299*37b918a0STim Harvey static const struct regmap_config ltc3676_regmap_config = { 300*37b918a0STim Harvey .reg_bits = 8, 301*37b918a0STim Harvey .val_bits = 8, 302*37b918a0STim Harvey .writeable_reg = ltc3676_writeable_reg, 303*37b918a0STim Harvey .readable_reg = ltc3676_readable_reg, 304*37b918a0STim Harvey .volatile_reg = ltc3676_volatile_reg, 305*37b918a0STim Harvey .max_register = LTC3676_CLIRQ, 306*37b918a0STim Harvey .use_single_rw = true, 307*37b918a0STim Harvey .cache_type = REGCACHE_RBTREE, 308*37b918a0STim Harvey }; 309*37b918a0STim Harvey 310*37b918a0STim Harvey static irqreturn_t ltc3676_isr(int irq, void *dev_id) 311*37b918a0STim Harvey { 312*37b918a0STim Harvey struct ltc3676 *ltc3676 = dev_id; 313*37b918a0STim Harvey struct device *dev = ltc3676->dev; 314*37b918a0STim Harvey unsigned int i, irqstat, event; 315*37b918a0STim Harvey 316*37b918a0STim Harvey regmap_read(ltc3676->regmap, LTC3676_IRQSTAT, &irqstat); 317*37b918a0STim Harvey 318*37b918a0STim Harvey dev_dbg(dev, "irq%d irqstat=0x%02x\n", irq, irqstat); 319*37b918a0STim Harvey if (irqstat & LTC3676_IRQSTAT_THERMAL_WARN) { 320*37b918a0STim Harvey dev_warn(dev, "Over-temperature Warning\n"); 321*37b918a0STim Harvey event = REGULATOR_EVENT_OVER_TEMP; 322*37b918a0STim Harvey for (i = 0; i < LTC3676_NUM_REGULATORS; i++) 323*37b918a0STim Harvey regulator_notifier_call_chain(ltc3676->regulators[i], 324*37b918a0STim Harvey event, NULL); 325*37b918a0STim Harvey } 326*37b918a0STim Harvey 327*37b918a0STim Harvey if (irqstat & LTC3676_IRQSTAT_UNDERVOLT_WARN) { 328*37b918a0STim Harvey dev_info(dev, "Undervoltage Warning\n"); 329*37b918a0STim Harvey event = REGULATOR_EVENT_UNDER_VOLTAGE; 330*37b918a0STim Harvey for (i = 0; i < LTC3676_NUM_REGULATORS; i++) 331*37b918a0STim Harvey regulator_notifier_call_chain(ltc3676->regulators[i], 332*37b918a0STim Harvey event, NULL); 333*37b918a0STim Harvey } 334*37b918a0STim Harvey 335*37b918a0STim Harvey /* Clear warning condition */ 336*37b918a0STim Harvey regmap_write(ltc3676->regmap, LTC3676_CLIRQ, 0); 337*37b918a0STim Harvey 338*37b918a0STim Harvey return IRQ_HANDLED; 339*37b918a0STim Harvey } 340*37b918a0STim Harvey 341*37b918a0STim Harvey static int ltc3676_regulator_probe(struct i2c_client *client, 342*37b918a0STim Harvey const struct i2c_device_id *id) 343*37b918a0STim Harvey { 344*37b918a0STim Harvey struct device *dev = &client->dev; 345*37b918a0STim Harvey struct regulator_init_data *init_data = dev_get_platdata(dev); 346*37b918a0STim Harvey struct regulator_desc *descs; 347*37b918a0STim Harvey struct ltc3676 *ltc3676; 348*37b918a0STim Harvey int i, ret; 349*37b918a0STim Harvey 350*37b918a0STim Harvey ltc3676 = devm_kzalloc(dev, sizeof(*ltc3676), GFP_KERNEL); 351*37b918a0STim Harvey if (!ltc3676) 352*37b918a0STim Harvey return -ENOMEM; 353*37b918a0STim Harvey 354*37b918a0STim Harvey i2c_set_clientdata(client, ltc3676); 355*37b918a0STim Harvey ltc3676->dev = dev; 356*37b918a0STim Harvey 357*37b918a0STim Harvey descs = ltc3676->regulator_descs; 358*37b918a0STim Harvey memcpy(descs, ltc3676_regulators, sizeof(ltc3676_regulators)); 359*37b918a0STim Harvey descs[LTC3676_LDO3].fixed_uV = 1800000; /* LDO3 is fixed 1.8V */ 360*37b918a0STim Harvey 361*37b918a0STim Harvey ltc3676->regmap = devm_regmap_init_i2c(client, <c3676_regmap_config); 362*37b918a0STim Harvey if (IS_ERR(ltc3676->regmap)) { 363*37b918a0STim Harvey ret = PTR_ERR(ltc3676->regmap); 364*37b918a0STim Harvey dev_err(dev, "failed to initialize regmap: %d\n", ret); 365*37b918a0STim Harvey return ret; 366*37b918a0STim Harvey } 367*37b918a0STim Harvey 368*37b918a0STim Harvey for (i = 0; i < LTC3676_NUM_REGULATORS; i++) { 369*37b918a0STim Harvey struct regulator_desc *desc = <c3676->regulator_descs[i]; 370*37b918a0STim Harvey struct regulator_config config = { }; 371*37b918a0STim Harvey 372*37b918a0STim Harvey if (init_data) 373*37b918a0STim Harvey config.init_data = &init_data[i]; 374*37b918a0STim Harvey 375*37b918a0STim Harvey config.dev = dev; 376*37b918a0STim Harvey config.driver_data = ltc3676; 377*37b918a0STim Harvey 378*37b918a0STim Harvey ltc3676->regulators[i] = devm_regulator_register(dev, desc, 379*37b918a0STim Harvey &config); 380*37b918a0STim Harvey if (IS_ERR(ltc3676->regulators[i])) { 381*37b918a0STim Harvey ret = PTR_ERR(ltc3676->regulators[i]); 382*37b918a0STim Harvey dev_err(dev, "failed to register regulator %s: %d\n", 383*37b918a0STim Harvey desc->name, ret); 384*37b918a0STim Harvey return ret; 385*37b918a0STim Harvey } 386*37b918a0STim Harvey } 387*37b918a0STim Harvey 388*37b918a0STim Harvey regmap_write(ltc3676->regmap, LTC3676_CLIRQ, 0); 389*37b918a0STim Harvey if (client->irq) { 390*37b918a0STim Harvey ret = devm_request_threaded_irq(dev, client->irq, NULL, 391*37b918a0STim Harvey ltc3676_isr, 392*37b918a0STim Harvey IRQF_TRIGGER_LOW | IRQF_ONESHOT, 393*37b918a0STim Harvey client->name, ltc3676); 394*37b918a0STim Harvey if (ret) { 395*37b918a0STim Harvey dev_err(dev, "Failed to request IRQ: %d\n", ret); 396*37b918a0STim Harvey return ret; 397*37b918a0STim Harvey } 398*37b918a0STim Harvey } 399*37b918a0STim Harvey 400*37b918a0STim Harvey return 0; 401*37b918a0STim Harvey } 402*37b918a0STim Harvey 403*37b918a0STim Harvey static const struct i2c_device_id ltc3676_i2c_id[] = { 404*37b918a0STim Harvey { "ltc3676" }, 405*37b918a0STim Harvey { } 406*37b918a0STim Harvey }; 407*37b918a0STim Harvey MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id); 408*37b918a0STim Harvey 409*37b918a0STim Harvey static struct i2c_driver ltc3676_driver = { 410*37b918a0STim Harvey .driver = { 411*37b918a0STim Harvey .name = DRIVER_NAME, 412*37b918a0STim Harvey }, 413*37b918a0STim Harvey .probe = ltc3676_regulator_probe, 414*37b918a0STim Harvey .id_table = ltc3676_i2c_id, 415*37b918a0STim Harvey }; 416*37b918a0STim Harvey module_i2c_driver(ltc3676_driver); 417*37b918a0STim Harvey 418*37b918a0STim Harvey MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>"); 419*37b918a0STim Harvey MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376"); 420*37b918a0STim Harvey MODULE_LICENSE("GPL v2"); 421