137b918a0STim Harvey /* 237b918a0STim Harvey * Copyright (C) 2016 Gateworks Corporation, Inc. All Rights Reserved. 337b918a0STim Harvey * 437b918a0STim Harvey * This program is free software; you can redistribute it and/or modify 537b918a0STim Harvey * it under the terms of the GNU General Public License version 2 637b918a0STim Harvey * as published by the Free Software Foundation. 737b918a0STim Harvey * 837b918a0STim Harvey * This program is distributed in the hope that it will be useful, 937b918a0STim Harvey * but WITHOUT ANY WARRANTY; without even the implied warranty of 1037b918a0STim Harvey * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1137b918a0STim Harvey * GNU General Public License for more details. 1237b918a0STim Harvey * 1337b918a0STim Harvey */ 1437b918a0STim Harvey #include <linux/i2c.h> 1537b918a0STim Harvey #include <linux/init.h> 1637b918a0STim Harvey #include <linux/interrupt.h> 1737b918a0STim Harvey #include <linux/module.h> 1837b918a0STim Harvey #include <linux/kernel.h> 1937b918a0STim Harvey #include <linux/of.h> 2037b918a0STim Harvey #include <linux/regmap.h> 2137b918a0STim Harvey #include <linux/regulator/driver.h> 2237b918a0STim Harvey #include <linux/regulator/machine.h> 2337b918a0STim Harvey #include <linux/regulator/of_regulator.h> 2437b918a0STim Harvey 2537b918a0STim Harvey #define DRIVER_NAME "ltc3676" 2637b918a0STim Harvey 2737b918a0STim Harvey /* LTC3676 Registers */ 2837b918a0STim Harvey #define LTC3676_BUCK1 0x01 2937b918a0STim Harvey #define LTC3676_BUCK2 0x02 3037b918a0STim Harvey #define LTC3676_BUCK3 0x03 3137b918a0STim Harvey #define LTC3676_BUCK4 0x04 3237b918a0STim Harvey #define LTC3676_LDOA 0x05 3337b918a0STim Harvey #define LTC3676_LDOB 0x06 3437b918a0STim Harvey #define LTC3676_SQD1 0x07 3537b918a0STim Harvey #define LTC3676_SQD2 0x08 3637b918a0STim Harvey #define LTC3676_CNTRL 0x09 3737b918a0STim Harvey #define LTC3676_DVB1A 0x0A 3837b918a0STim Harvey #define LTC3676_DVB1B 0x0B 3937b918a0STim Harvey #define LTC3676_DVB2A 0x0C 4037b918a0STim Harvey #define LTC3676_DVB2B 0x0D 4137b918a0STim Harvey #define LTC3676_DVB3A 0x0E 4237b918a0STim Harvey #define LTC3676_DVB3B 0x0F 4337b918a0STim Harvey #define LTC3676_DVB4A 0x10 4437b918a0STim Harvey #define LTC3676_DVB4B 0x11 4537b918a0STim Harvey #define LTC3676_MSKIRQ 0x12 4637b918a0STim Harvey #define LTC3676_MSKPG 0x13 4737b918a0STim Harvey #define LTC3676_USER 0x14 4837b918a0STim Harvey #define LTC3676_IRQSTAT 0x15 4937b918a0STim Harvey #define LTC3676_PGSTATL 0x16 5037b918a0STim Harvey #define LTC3676_PGSTATRT 0x17 5137b918a0STim Harvey #define LTC3676_HRST 0x1E 5237b918a0STim Harvey #define LTC3676_CLIRQ 0x1F 5337b918a0STim Harvey 5437b918a0STim Harvey #define LTC3676_DVBxA_REF_SELECT BIT(5) 55*d2a66ddfSMarek Vasut #define LTC3676_DVBxB_PGOOD_MASK BIT(5) 5637b918a0STim Harvey 5737b918a0STim Harvey #define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3) 5837b918a0STim Harvey #define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4) 5937b918a0STim Harvey #define LTC3676_IRQSTAT_UNDERVOLT_FAULT BIT(5) 6037b918a0STim Harvey #define LTC3676_IRQSTAT_THERMAL_WARN BIT(6) 6137b918a0STim Harvey #define LTC3676_IRQSTAT_THERMAL_FAULT BIT(7) 6237b918a0STim Harvey 6337b918a0STim Harvey enum ltc3676_reg { 6437b918a0STim Harvey LTC3676_SW1, 6537b918a0STim Harvey LTC3676_SW2, 6637b918a0STim Harvey LTC3676_SW3, 6737b918a0STim Harvey LTC3676_SW4, 6837b918a0STim Harvey LTC3676_LDO1, 6937b918a0STim Harvey LTC3676_LDO2, 7037b918a0STim Harvey LTC3676_LDO3, 7137b918a0STim Harvey LTC3676_LDO4, 7237b918a0STim Harvey LTC3676_NUM_REGULATORS, 7337b918a0STim Harvey }; 7437b918a0STim Harvey 7537b918a0STim Harvey struct ltc3676 { 7637b918a0STim Harvey struct regmap *regmap; 7737b918a0STim Harvey struct device *dev; 7837b918a0STim Harvey struct regulator_desc regulator_descs[LTC3676_NUM_REGULATORS]; 7937b918a0STim Harvey struct regulator_dev *regulators[LTC3676_NUM_REGULATORS]; 8037b918a0STim Harvey }; 8137b918a0STim Harvey 8237b918a0STim Harvey static int ltc3676_set_suspend_voltage(struct regulator_dev *rdev, int uV) 8337b918a0STim Harvey { 8437b918a0STim Harvey struct ltc3676 *ltc3676 = rdev_get_drvdata(rdev); 8537b918a0STim Harvey struct device *dev = ltc3676->dev; 8637b918a0STim Harvey int dcdc = rdev_get_id(rdev); 8737b918a0STim Harvey int sel; 8837b918a0STim Harvey 8937b918a0STim Harvey dev_dbg(dev, "%s id=%d uV=%d\n", __func__, dcdc, uV); 9037b918a0STim Harvey sel = regulator_map_voltage_linear(rdev, uV, uV); 9137b918a0STim Harvey if (sel < 0) 9237b918a0STim Harvey return sel; 9337b918a0STim Harvey 9437b918a0STim Harvey /* DVBB register follows right after the corresponding DVBA register */ 9537b918a0STim Harvey return regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg + 1, 9637b918a0STim Harvey rdev->desc->vsel_mask, sel); 9737b918a0STim Harvey } 9837b918a0STim Harvey 9937b918a0STim Harvey static int ltc3676_set_suspend_mode(struct regulator_dev *rdev, 10037b918a0STim Harvey unsigned int mode) 10137b918a0STim Harvey { 10237b918a0STim Harvey struct ltc3676 *ltc3676= rdev_get_drvdata(rdev); 10337b918a0STim Harvey struct device *dev = ltc3676->dev; 10437b918a0STim Harvey int mask, val; 10537b918a0STim Harvey int dcdc = rdev_get_id(rdev); 10637b918a0STim Harvey 10737b918a0STim Harvey dev_dbg(dev, "%s id=%d mode=%d\n", __func__, dcdc, mode); 10837b918a0STim Harvey 10937b918a0STim Harvey mask = LTC3676_DVBxA_REF_SELECT; 11037b918a0STim Harvey switch (mode) { 11137b918a0STim Harvey case REGULATOR_MODE_STANDBY: 11237b918a0STim Harvey val = 0; /* select DVBxA */ 11337b918a0STim Harvey break; 11437b918a0STim Harvey case REGULATOR_MODE_NORMAL: 11537b918a0STim Harvey val = LTC3676_DVBxA_REF_SELECT; /* select DVBxB */ 11637b918a0STim Harvey break; 11737b918a0STim Harvey default: 11837b918a0STim Harvey dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", 11937b918a0STim Harvey rdev->desc->name, mode); 12037b918a0STim Harvey return -EINVAL; 12137b918a0STim Harvey } 12237b918a0STim Harvey 12337b918a0STim Harvey return regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg, 12437b918a0STim Harvey mask, val); 12537b918a0STim Harvey } 12637b918a0STim Harvey 127*d2a66ddfSMarek Vasut static int ltc3676_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) 128*d2a66ddfSMarek Vasut { 129*d2a66ddfSMarek Vasut struct ltc3676 *ltc3676 = rdev_get_drvdata(rdev); 130*d2a66ddfSMarek Vasut struct device *dev = ltc3676->dev; 131*d2a66ddfSMarek Vasut int ret, dcdc = rdev_get_id(rdev); 132*d2a66ddfSMarek Vasut 133*d2a66ddfSMarek Vasut dev_dbg(dev, "%s id=%d selector=%d\n", __func__, dcdc, selector); 134*d2a66ddfSMarek Vasut 135*d2a66ddfSMarek Vasut ret = regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg + 1, 136*d2a66ddfSMarek Vasut LTC3676_DVBxB_PGOOD_MASK, 137*d2a66ddfSMarek Vasut LTC3676_DVBxB_PGOOD_MASK); 138*d2a66ddfSMarek Vasut if (ret) 139*d2a66ddfSMarek Vasut return ret; 140*d2a66ddfSMarek Vasut 141*d2a66ddfSMarek Vasut return regulator_set_voltage_sel_regmap(rdev, selector); 142*d2a66ddfSMarek Vasut } 143*d2a66ddfSMarek Vasut 14437b918a0STim Harvey static inline unsigned int ltc3676_scale(unsigned int uV, u32 r1, u32 r2) 14537b918a0STim Harvey { 14637b918a0STim Harvey uint64_t tmp; 14737b918a0STim Harvey if (uV == 0) 14837b918a0STim Harvey return 0; 14937b918a0STim Harvey tmp = (uint64_t)uV * r1; 15037b918a0STim Harvey do_div(tmp, r2); 15137b918a0STim Harvey return uV + (unsigned int)tmp; 15237b918a0STim Harvey } 15337b918a0STim Harvey 15437b918a0STim Harvey static int ltc3676_of_parse_cb(struct device_node *np, 15537b918a0STim Harvey const struct regulator_desc *desc, 15637b918a0STim Harvey struct regulator_config *config) 15737b918a0STim Harvey { 15837b918a0STim Harvey struct ltc3676 *ltc3676 = config->driver_data; 15937b918a0STim Harvey struct regulator_desc *rdesc = <c3676->regulator_descs[desc->id]; 16037b918a0STim Harvey u32 r[2]; 16137b918a0STim Harvey int ret; 16237b918a0STim Harvey 16337b918a0STim Harvey /* LDO3 has a fixed output */ 16437b918a0STim Harvey if (desc->id == LTC3676_LDO3) 16537b918a0STim Harvey return 0; 16637b918a0STim Harvey 16737b918a0STim Harvey ret = of_property_read_u32_array(np, "lltc,fb-voltage-divider", r, 2); 16837b918a0STim Harvey if (ret) { 16937b918a0STim Harvey dev_err(ltc3676->dev, "Failed to parse voltage divider: %d\n", 17037b918a0STim Harvey ret); 17137b918a0STim Harvey return ret; 17237b918a0STim Harvey } 17337b918a0STim Harvey 17437b918a0STim Harvey rdesc->min_uV = ltc3676_scale(desc->min_uV, r[0], r[1]); 17537b918a0STim Harvey rdesc->uV_step = ltc3676_scale(desc->uV_step, r[0], r[1]); 17637b918a0STim Harvey rdesc->fixed_uV = ltc3676_scale(desc->fixed_uV, r[0], r[1]); 17737b918a0STim Harvey 17837b918a0STim Harvey return 0; 17937b918a0STim Harvey } 18037b918a0STim Harvey 18137b918a0STim Harvey /* SW1, SW2, SW3, SW4 linear 0.8V-3.3V with scalar via R1/R2 feeback res */ 182f9e93accSBhumika Goyal static const struct regulator_ops ltc3676_linear_regulator_ops = { 18337b918a0STim Harvey .enable = regulator_enable_regmap, 18437b918a0STim Harvey .disable = regulator_disable_regmap, 18537b918a0STim Harvey .is_enabled = regulator_is_enabled_regmap, 18637b918a0STim Harvey .list_voltage = regulator_list_voltage_linear, 187*d2a66ddfSMarek Vasut .set_voltage_sel = ltc3676_set_voltage_sel, 18837b918a0STim Harvey .get_voltage_sel = regulator_get_voltage_sel_regmap, 18937b918a0STim Harvey .set_suspend_voltage = ltc3676_set_suspend_voltage, 19037b918a0STim Harvey .set_suspend_mode = ltc3676_set_suspend_mode, 19137b918a0STim Harvey }; 19237b918a0STim Harvey 19337b918a0STim Harvey /* LDO1 always on fixed 0.8V-3.3V via scalar via R1/R2 feeback res */ 194f9e93accSBhumika Goyal static const struct regulator_ops ltc3676_fixed_standby_regulator_ops = { 19537b918a0STim Harvey }; 19637b918a0STim Harvey 19737b918a0STim Harvey /* LDO2, LDO3 fixed (LDO2 has external scalar via R1/R2 feedback res) */ 198f9e93accSBhumika Goyal static const struct regulator_ops ltc3676_fixed_regulator_ops = { 19937b918a0STim Harvey .enable = regulator_enable_regmap, 20037b918a0STim Harvey .disable = regulator_disable_regmap, 20137b918a0STim Harvey .is_enabled = regulator_is_enabled_regmap, 20237b918a0STim Harvey }; 20337b918a0STim Harvey 20437b918a0STim Harvey #define LTC3676_REG(_id, _name, _ops, en_reg, en_bit, dvba_reg, dvb_mask) \ 20537b918a0STim Harvey [LTC3676_ ## _id] = { \ 20637b918a0STim Harvey .name = #_name, \ 20737b918a0STim Harvey .of_match = of_match_ptr(#_name), \ 20837b918a0STim Harvey .regulators_node = of_match_ptr("regulators"), \ 20937b918a0STim Harvey .of_parse_cb = ltc3676_of_parse_cb, \ 21037b918a0STim Harvey .n_voltages = (dvb_mask) + 1, \ 21137b918a0STim Harvey .min_uV = (dvba_reg) ? 412500 : 0, \ 21237b918a0STim Harvey .uV_step = (dvba_reg) ? 12500 : 0, \ 21337b918a0STim Harvey .ramp_delay = (dvba_reg) ? 800 : 0, \ 21437b918a0STim Harvey .fixed_uV = (dvb_mask) ? 0 : 725000, \ 21537b918a0STim Harvey .ops = <c3676_ ## _ops ## _regulator_ops, \ 21637b918a0STim Harvey .type = REGULATOR_VOLTAGE, \ 21737b918a0STim Harvey .id = LTC3676_ ## _id, \ 21837b918a0STim Harvey .owner = THIS_MODULE, \ 21937b918a0STim Harvey .vsel_reg = (dvba_reg), \ 22037b918a0STim Harvey .vsel_mask = (dvb_mask), \ 22137b918a0STim Harvey .enable_reg = (en_reg), \ 22237b918a0STim Harvey .enable_mask = (1 << en_bit), \ 22337b918a0STim Harvey } 22437b918a0STim Harvey 22537b918a0STim Harvey #define LTC3676_LINEAR_REG(_id, _name, _en, _dvba) \ 22637b918a0STim Harvey LTC3676_REG(_id, _name, linear, \ 22737b918a0STim Harvey LTC3676_ ## _en, 7, \ 22837b918a0STim Harvey LTC3676_ ## _dvba, 0x1f) 22937b918a0STim Harvey 23037b918a0STim Harvey #define LTC3676_FIXED_REG(_id, _name, _en_reg, _en_bit) \ 23137b918a0STim Harvey LTC3676_REG(_id, _name, fixed, LTC3676_ ## _en_reg, _en_bit, 0, 0) 23237b918a0STim Harvey 23337b918a0STim Harvey static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = { 23437b918a0STim Harvey LTC3676_LINEAR_REG(SW1, sw1, BUCK1, DVB1A), 23537b918a0STim Harvey LTC3676_LINEAR_REG(SW2, sw2, BUCK2, DVB2A), 23637b918a0STim Harvey LTC3676_LINEAR_REG(SW3, sw3, BUCK3, DVB3A), 23737b918a0STim Harvey LTC3676_LINEAR_REG(SW4, sw4, BUCK4, DVB4A), 23837b918a0STim Harvey LTC3676_REG(LDO1, ldo1, fixed_standby, 0, 0, 0, 0), 23937b918a0STim Harvey LTC3676_FIXED_REG(LDO2, ldo2, LDOA, 2), 24037b918a0STim Harvey LTC3676_FIXED_REG(LDO3, ldo3, LDOA, 5), 24137b918a0STim Harvey LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2), 24237b918a0STim Harvey }; 24337b918a0STim Harvey 24437b918a0STim Harvey static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg) 24537b918a0STim Harvey { 24637b918a0STim Harvey switch (reg) { 24737b918a0STim Harvey case LTC3676_IRQSTAT: 24837b918a0STim Harvey case LTC3676_BUCK1: 24937b918a0STim Harvey case LTC3676_BUCK2: 25037b918a0STim Harvey case LTC3676_BUCK3: 25137b918a0STim Harvey case LTC3676_BUCK4: 25237b918a0STim Harvey case LTC3676_LDOA: 25337b918a0STim Harvey case LTC3676_LDOB: 25437b918a0STim Harvey case LTC3676_SQD1: 25537b918a0STim Harvey case LTC3676_SQD2: 25637b918a0STim Harvey case LTC3676_CNTRL: 25737b918a0STim Harvey case LTC3676_DVB1A: 25837b918a0STim Harvey case LTC3676_DVB1B: 25937b918a0STim Harvey case LTC3676_DVB2A: 26037b918a0STim Harvey case LTC3676_DVB2B: 26137b918a0STim Harvey case LTC3676_DVB3A: 26237b918a0STim Harvey case LTC3676_DVB3B: 26337b918a0STim Harvey case LTC3676_DVB4A: 26437b918a0STim Harvey case LTC3676_DVB4B: 26537b918a0STim Harvey case LTC3676_MSKIRQ: 26637b918a0STim Harvey case LTC3676_MSKPG: 26737b918a0STim Harvey case LTC3676_USER: 26837b918a0STim Harvey case LTC3676_HRST: 26937b918a0STim Harvey case LTC3676_CLIRQ: 27037b918a0STim Harvey return true; 27137b918a0STim Harvey } 27237b918a0STim Harvey return false; 27337b918a0STim Harvey } 27437b918a0STim Harvey 27537b918a0STim Harvey static bool ltc3676_readable_reg(struct device *dev, unsigned int reg) 27637b918a0STim Harvey { 27737b918a0STim Harvey switch (reg) { 27837b918a0STim Harvey case LTC3676_IRQSTAT: 27937b918a0STim Harvey case LTC3676_BUCK1: 28037b918a0STim Harvey case LTC3676_BUCK2: 28137b918a0STim Harvey case LTC3676_BUCK3: 28237b918a0STim Harvey case LTC3676_BUCK4: 28337b918a0STim Harvey case LTC3676_LDOA: 28437b918a0STim Harvey case LTC3676_LDOB: 28537b918a0STim Harvey case LTC3676_SQD1: 28637b918a0STim Harvey case LTC3676_SQD2: 28737b918a0STim Harvey case LTC3676_CNTRL: 28837b918a0STim Harvey case LTC3676_DVB1A: 28937b918a0STim Harvey case LTC3676_DVB1B: 29037b918a0STim Harvey case LTC3676_DVB2A: 29137b918a0STim Harvey case LTC3676_DVB2B: 29237b918a0STim Harvey case LTC3676_DVB3A: 29337b918a0STim Harvey case LTC3676_DVB3B: 29437b918a0STim Harvey case LTC3676_DVB4A: 29537b918a0STim Harvey case LTC3676_DVB4B: 29637b918a0STim Harvey case LTC3676_MSKIRQ: 29737b918a0STim Harvey case LTC3676_MSKPG: 29837b918a0STim Harvey case LTC3676_USER: 29937b918a0STim Harvey case LTC3676_HRST: 30037b918a0STim Harvey case LTC3676_CLIRQ: 30137b918a0STim Harvey return true; 30237b918a0STim Harvey } 30337b918a0STim Harvey return false; 30437b918a0STim Harvey } 30537b918a0STim Harvey 30637b918a0STim Harvey static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg) 30737b918a0STim Harvey { 30837b918a0STim Harvey switch (reg) { 30937b918a0STim Harvey case LTC3676_IRQSTAT: 31037b918a0STim Harvey case LTC3676_PGSTATL: 31137b918a0STim Harvey case LTC3676_PGSTATRT: 31237b918a0STim Harvey return true; 31337b918a0STim Harvey } 31437b918a0STim Harvey return false; 31537b918a0STim Harvey } 31637b918a0STim Harvey 31737b918a0STim Harvey static const struct regmap_config ltc3676_regmap_config = { 31837b918a0STim Harvey .reg_bits = 8, 31937b918a0STim Harvey .val_bits = 8, 32037b918a0STim Harvey .writeable_reg = ltc3676_writeable_reg, 32137b918a0STim Harvey .readable_reg = ltc3676_readable_reg, 32237b918a0STim Harvey .volatile_reg = ltc3676_volatile_reg, 32337b918a0STim Harvey .max_register = LTC3676_CLIRQ, 32437b918a0STim Harvey .use_single_rw = true, 32537b918a0STim Harvey .cache_type = REGCACHE_RBTREE, 32637b918a0STim Harvey }; 32737b918a0STim Harvey 32837b918a0STim Harvey static irqreturn_t ltc3676_isr(int irq, void *dev_id) 32937b918a0STim Harvey { 33037b918a0STim Harvey struct ltc3676 *ltc3676 = dev_id; 33137b918a0STim Harvey struct device *dev = ltc3676->dev; 33237b918a0STim Harvey unsigned int i, irqstat, event; 33337b918a0STim Harvey 33437b918a0STim Harvey regmap_read(ltc3676->regmap, LTC3676_IRQSTAT, &irqstat); 33537b918a0STim Harvey 33637b918a0STim Harvey dev_dbg(dev, "irq%d irqstat=0x%02x\n", irq, irqstat); 33737b918a0STim Harvey if (irqstat & LTC3676_IRQSTAT_THERMAL_WARN) { 33837b918a0STim Harvey dev_warn(dev, "Over-temperature Warning\n"); 33937b918a0STim Harvey event = REGULATOR_EVENT_OVER_TEMP; 34037b918a0STim Harvey for (i = 0; i < LTC3676_NUM_REGULATORS; i++) 34137b918a0STim Harvey regulator_notifier_call_chain(ltc3676->regulators[i], 34237b918a0STim Harvey event, NULL); 34337b918a0STim Harvey } 34437b918a0STim Harvey 34537b918a0STim Harvey if (irqstat & LTC3676_IRQSTAT_UNDERVOLT_WARN) { 34637b918a0STim Harvey dev_info(dev, "Undervoltage Warning\n"); 34737b918a0STim Harvey event = REGULATOR_EVENT_UNDER_VOLTAGE; 34837b918a0STim Harvey for (i = 0; i < LTC3676_NUM_REGULATORS; i++) 34937b918a0STim Harvey regulator_notifier_call_chain(ltc3676->regulators[i], 35037b918a0STim Harvey event, NULL); 35137b918a0STim Harvey } 35237b918a0STim Harvey 35337b918a0STim Harvey /* Clear warning condition */ 35437b918a0STim Harvey regmap_write(ltc3676->regmap, LTC3676_CLIRQ, 0); 35537b918a0STim Harvey 35637b918a0STim Harvey return IRQ_HANDLED; 35737b918a0STim Harvey } 35837b918a0STim Harvey 35937b918a0STim Harvey static int ltc3676_regulator_probe(struct i2c_client *client, 36037b918a0STim Harvey const struct i2c_device_id *id) 36137b918a0STim Harvey { 36237b918a0STim Harvey struct device *dev = &client->dev; 36337b918a0STim Harvey struct regulator_init_data *init_data = dev_get_platdata(dev); 36437b918a0STim Harvey struct regulator_desc *descs; 36537b918a0STim Harvey struct ltc3676 *ltc3676; 36637b918a0STim Harvey int i, ret; 36737b918a0STim Harvey 36837b918a0STim Harvey ltc3676 = devm_kzalloc(dev, sizeof(*ltc3676), GFP_KERNEL); 36937b918a0STim Harvey if (!ltc3676) 37037b918a0STim Harvey return -ENOMEM; 37137b918a0STim Harvey 37237b918a0STim Harvey i2c_set_clientdata(client, ltc3676); 37337b918a0STim Harvey ltc3676->dev = dev; 37437b918a0STim Harvey 37537b918a0STim Harvey descs = ltc3676->regulator_descs; 37637b918a0STim Harvey memcpy(descs, ltc3676_regulators, sizeof(ltc3676_regulators)); 37737b918a0STim Harvey descs[LTC3676_LDO3].fixed_uV = 1800000; /* LDO3 is fixed 1.8V */ 37837b918a0STim Harvey 37937b918a0STim Harvey ltc3676->regmap = devm_regmap_init_i2c(client, <c3676_regmap_config); 38037b918a0STim Harvey if (IS_ERR(ltc3676->regmap)) { 38137b918a0STim Harvey ret = PTR_ERR(ltc3676->regmap); 38237b918a0STim Harvey dev_err(dev, "failed to initialize regmap: %d\n", ret); 38337b918a0STim Harvey return ret; 38437b918a0STim Harvey } 38537b918a0STim Harvey 38637b918a0STim Harvey for (i = 0; i < LTC3676_NUM_REGULATORS; i++) { 38737b918a0STim Harvey struct regulator_desc *desc = <c3676->regulator_descs[i]; 38837b918a0STim Harvey struct regulator_config config = { }; 38937b918a0STim Harvey 39037b918a0STim Harvey if (init_data) 39137b918a0STim Harvey config.init_data = &init_data[i]; 39237b918a0STim Harvey 39337b918a0STim Harvey config.dev = dev; 39437b918a0STim Harvey config.driver_data = ltc3676; 39537b918a0STim Harvey 39637b918a0STim Harvey ltc3676->regulators[i] = devm_regulator_register(dev, desc, 39737b918a0STim Harvey &config); 39837b918a0STim Harvey if (IS_ERR(ltc3676->regulators[i])) { 39937b918a0STim Harvey ret = PTR_ERR(ltc3676->regulators[i]); 40037b918a0STim Harvey dev_err(dev, "failed to register regulator %s: %d\n", 40137b918a0STim Harvey desc->name, ret); 40237b918a0STim Harvey return ret; 40337b918a0STim Harvey } 40437b918a0STim Harvey } 40537b918a0STim Harvey 40637b918a0STim Harvey regmap_write(ltc3676->regmap, LTC3676_CLIRQ, 0); 40737b918a0STim Harvey if (client->irq) { 40837b918a0STim Harvey ret = devm_request_threaded_irq(dev, client->irq, NULL, 40937b918a0STim Harvey ltc3676_isr, 41037b918a0STim Harvey IRQF_TRIGGER_LOW | IRQF_ONESHOT, 41137b918a0STim Harvey client->name, ltc3676); 41237b918a0STim Harvey if (ret) { 41337b918a0STim Harvey dev_err(dev, "Failed to request IRQ: %d\n", ret); 41437b918a0STim Harvey return ret; 41537b918a0STim Harvey } 41637b918a0STim Harvey } 41737b918a0STim Harvey 41837b918a0STim Harvey return 0; 41937b918a0STim Harvey } 42037b918a0STim Harvey 42137b918a0STim Harvey static const struct i2c_device_id ltc3676_i2c_id[] = { 42237b918a0STim Harvey { "ltc3676" }, 42337b918a0STim Harvey { } 42437b918a0STim Harvey }; 42537b918a0STim Harvey MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id); 42637b918a0STim Harvey 427c3143415SJavier Martinez Canillas static const struct of_device_id ltc3676_of_match[] = { 428c3143415SJavier Martinez Canillas { .compatible = "lltc,ltc3676" }, 429c3143415SJavier Martinez Canillas { }, 430c3143415SJavier Martinez Canillas }; 431c3143415SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ltc3676_of_match); 432c3143415SJavier Martinez Canillas 43337b918a0STim Harvey static struct i2c_driver ltc3676_driver = { 43437b918a0STim Harvey .driver = { 43537b918a0STim Harvey .name = DRIVER_NAME, 436c3143415SJavier Martinez Canillas .of_match_table = of_match_ptr(ltc3676_of_match), 43737b918a0STim Harvey }, 43837b918a0STim Harvey .probe = ltc3676_regulator_probe, 43937b918a0STim Harvey .id_table = ltc3676_i2c_id, 44037b918a0STim Harvey }; 44137b918a0STim Harvey module_i2c_driver(ltc3676_driver); 44237b918a0STim Harvey 44337b918a0STim Harvey MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>"); 44437b918a0STim Harvey MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376"); 44537b918a0STim Harvey MODULE_LICENSE("GPL v2"); 446