1ffee1909SGyungoh Yoo /* 2ffee1909SGyungoh Yoo * max8907-regulator.c -- support regulators in max8907 3ffee1909SGyungoh Yoo * 4ffee1909SGyungoh Yoo * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com> 5ffee1909SGyungoh Yoo * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved. 6ffee1909SGyungoh Yoo * 7ffee1909SGyungoh Yoo * Portions based on drivers/regulator/tps65910-regulator.c, 8ffee1909SGyungoh Yoo * Copyright 2010 Texas Instruments Inc. 9ffee1909SGyungoh Yoo * Author: Graeme Gregory <gg@slimlogic.co.uk> 10ffee1909SGyungoh Yoo * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 11ffee1909SGyungoh Yoo * 12ffee1909SGyungoh Yoo * This program is free software; you can redistribute it and/or modify 13ffee1909SGyungoh Yoo * it under the terms of the GNU General Public License version 2 as 14ffee1909SGyungoh Yoo * published by the Free Software Foundation. 15ffee1909SGyungoh Yoo */ 16ffee1909SGyungoh Yoo 17ffee1909SGyungoh Yoo #include <linux/err.h> 18ffee1909SGyungoh Yoo #include <linux/init.h> 19ffee1909SGyungoh Yoo #include <linux/mfd/core.h> 20ffee1909SGyungoh Yoo #include <linux/mfd/max8907.h> 21ffee1909SGyungoh Yoo #include <linux/module.h> 22ffee1909SGyungoh Yoo #include <linux/of.h> 23ffee1909SGyungoh Yoo #include <linux/platform_device.h> 24ffee1909SGyungoh Yoo #include <linux/regulator/driver.h> 25ffee1909SGyungoh Yoo #include <linux/regulator/machine.h> 26ffee1909SGyungoh Yoo #include <linux/regulator/of_regulator.h> 27ffee1909SGyungoh Yoo #include <linux/regmap.h> 28ffee1909SGyungoh Yoo #include <linux/slab.h> 29ffee1909SGyungoh Yoo 30ffee1909SGyungoh Yoo #define MAX8907_II2RR_VERSION_MASK 0xF0 31ffee1909SGyungoh Yoo #define MAX8907_II2RR_VERSION_REV_A 0x00 32ffee1909SGyungoh Yoo #define MAX8907_II2RR_VERSION_REV_B 0x10 33ffee1909SGyungoh Yoo #define MAX8907_II2RR_VERSION_REV_C 0x30 34ffee1909SGyungoh Yoo 35ffee1909SGyungoh Yoo struct max8907_regulator { 36ffee1909SGyungoh Yoo struct regulator_desc desc[MAX8907_NUM_REGULATORS]; 37ffee1909SGyungoh Yoo struct regulator_dev *rdev[MAX8907_NUM_REGULATORS]; 38ffee1909SGyungoh Yoo }; 39ffee1909SGyungoh Yoo 40ffee1909SGyungoh Yoo #define REG_MBATT() \ 41ffee1909SGyungoh Yoo [MAX8907_MBATT] = { \ 42ffee1909SGyungoh Yoo .name = "MBATT", \ 43ffee1909SGyungoh Yoo .supply_name = "mbatt", \ 44ffee1909SGyungoh Yoo .id = MAX8907_MBATT, \ 45ffee1909SGyungoh Yoo .ops = &max8907_mbatt_ops, \ 46ffee1909SGyungoh Yoo .type = REGULATOR_VOLTAGE, \ 47ffee1909SGyungoh Yoo .owner = THIS_MODULE, \ 48ffee1909SGyungoh Yoo } 49ffee1909SGyungoh Yoo 50ffee1909SGyungoh Yoo #define REG_LDO(ids, supply, base, min, max, step) \ 51ffee1909SGyungoh Yoo [MAX8907_##ids] = { \ 52ffee1909SGyungoh Yoo .name = #ids, \ 53ffee1909SGyungoh Yoo .supply_name = supply, \ 54ffee1909SGyungoh Yoo .id = MAX8907_##ids, \ 55ffee1909SGyungoh Yoo .n_voltages = ((max) - (min)) / (step) + 1, \ 56ffee1909SGyungoh Yoo .ops = &max8907_ldo_ops, \ 57ffee1909SGyungoh Yoo .type = REGULATOR_VOLTAGE, \ 58ffee1909SGyungoh Yoo .owner = THIS_MODULE, \ 59ffee1909SGyungoh Yoo .min_uV = (min), \ 60ffee1909SGyungoh Yoo .uV_step = (step), \ 61ffee1909SGyungoh Yoo .vsel_reg = (base) + MAX8907_VOUT, \ 62ffee1909SGyungoh Yoo .vsel_mask = 0x3f, \ 63ffee1909SGyungoh Yoo .enable_reg = (base) + MAX8907_CTL, \ 64ffee1909SGyungoh Yoo .enable_mask = MAX8907_MASK_LDO_EN, \ 65ffee1909SGyungoh Yoo } 66ffee1909SGyungoh Yoo 67ffee1909SGyungoh Yoo #define REG_FIXED(ids, supply, voltage) \ 68ffee1909SGyungoh Yoo [MAX8907_##ids] = { \ 69ffee1909SGyungoh Yoo .name = #ids, \ 70ffee1909SGyungoh Yoo .supply_name = supply, \ 71ffee1909SGyungoh Yoo .id = MAX8907_##ids, \ 72ffee1909SGyungoh Yoo .n_voltages = 1, \ 73ffee1909SGyungoh Yoo .ops = &max8907_fixed_ops, \ 74ffee1909SGyungoh Yoo .type = REGULATOR_VOLTAGE, \ 75ffee1909SGyungoh Yoo .owner = THIS_MODULE, \ 76ffee1909SGyungoh Yoo .min_uV = (voltage), \ 77ffee1909SGyungoh Yoo } 78ffee1909SGyungoh Yoo 79ffee1909SGyungoh Yoo #define REG_OUT5V(ids, supply, base, voltage) \ 80ffee1909SGyungoh Yoo [MAX8907_##ids] = { \ 81ffee1909SGyungoh Yoo .name = #ids, \ 82ffee1909SGyungoh Yoo .supply_name = supply, \ 83ffee1909SGyungoh Yoo .id = MAX8907_##ids, \ 84ffee1909SGyungoh Yoo .n_voltages = 1, \ 85ffee1909SGyungoh Yoo .ops = &max8907_out5v_ops, \ 86ffee1909SGyungoh Yoo .type = REGULATOR_VOLTAGE, \ 87ffee1909SGyungoh Yoo .owner = THIS_MODULE, \ 88ffee1909SGyungoh Yoo .min_uV = (voltage), \ 89ffee1909SGyungoh Yoo .enable_reg = (base), \ 90ffee1909SGyungoh Yoo .enable_mask = MAX8907_MASK_OUT5V_EN, \ 91ffee1909SGyungoh Yoo } 92ffee1909SGyungoh Yoo 93ffee1909SGyungoh Yoo #define REG_BBAT(ids, supply, base, min, max, step) \ 94ffee1909SGyungoh Yoo [MAX8907_##ids] = { \ 95ffee1909SGyungoh Yoo .name = #ids, \ 96ffee1909SGyungoh Yoo .supply_name = supply, \ 97ffee1909SGyungoh Yoo .id = MAX8907_##ids, \ 98ffee1909SGyungoh Yoo .n_voltages = ((max) - (min)) / (step) + 1, \ 99ffee1909SGyungoh Yoo .ops = &max8907_bbat_ops, \ 100ffee1909SGyungoh Yoo .type = REGULATOR_VOLTAGE, \ 101ffee1909SGyungoh Yoo .owner = THIS_MODULE, \ 102ffee1909SGyungoh Yoo .min_uV = (min), \ 103ffee1909SGyungoh Yoo .uV_step = (step), \ 104ffee1909SGyungoh Yoo .vsel_reg = (base), \ 105ffee1909SGyungoh Yoo .vsel_mask = MAX8907_MASK_VBBATTCV, \ 106ffee1909SGyungoh Yoo } 107ffee1909SGyungoh Yoo 108ffee1909SGyungoh Yoo #define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \ 109ffee1909SGyungoh Yoo 750000, 3900000, 50000) 110ffee1909SGyungoh Yoo #define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \ 111ffee1909SGyungoh Yoo 650000, 2225000, 25000) 112ffee1909SGyungoh Yoo 113ffee1909SGyungoh Yoo static struct regulator_ops max8907_mbatt_ops = { 114ffee1909SGyungoh Yoo }; 115ffee1909SGyungoh Yoo 116ffee1909SGyungoh Yoo static struct regulator_ops max8907_ldo_ops = { 117ffee1909SGyungoh Yoo .list_voltage = regulator_list_voltage_linear, 118ffee1909SGyungoh Yoo .set_voltage_sel = regulator_set_voltage_sel_regmap, 119ffee1909SGyungoh Yoo .get_voltage_sel = regulator_get_voltage_sel_regmap, 120ffee1909SGyungoh Yoo .enable = regulator_enable_regmap, 121ffee1909SGyungoh Yoo .disable = regulator_disable_regmap, 122ffee1909SGyungoh Yoo .is_enabled = regulator_is_enabled_regmap, 123ffee1909SGyungoh Yoo }; 124ffee1909SGyungoh Yoo 125ffee1909SGyungoh Yoo static struct regulator_ops max8907_ldo_hwctl_ops = { 126ffee1909SGyungoh Yoo .list_voltage = regulator_list_voltage_linear, 127ffee1909SGyungoh Yoo .set_voltage_sel = regulator_set_voltage_sel_regmap, 128ffee1909SGyungoh Yoo .get_voltage_sel = regulator_get_voltage_sel_regmap, 129ffee1909SGyungoh Yoo }; 130ffee1909SGyungoh Yoo 131ffee1909SGyungoh Yoo static struct regulator_ops max8907_fixed_ops = { 132ffee1909SGyungoh Yoo .list_voltage = regulator_list_voltage_linear, 133ffee1909SGyungoh Yoo }; 134ffee1909SGyungoh Yoo 135ffee1909SGyungoh Yoo static struct regulator_ops max8907_out5v_ops = { 136ffee1909SGyungoh Yoo .list_voltage = regulator_list_voltage_linear, 137ffee1909SGyungoh Yoo .enable = regulator_enable_regmap, 138ffee1909SGyungoh Yoo .disable = regulator_disable_regmap, 139ffee1909SGyungoh Yoo .is_enabled = regulator_is_enabled_regmap, 140ffee1909SGyungoh Yoo }; 141ffee1909SGyungoh Yoo 142ffee1909SGyungoh Yoo static struct regulator_ops max8907_out5v_hwctl_ops = { 143ffee1909SGyungoh Yoo .list_voltage = regulator_list_voltage_linear, 144ffee1909SGyungoh Yoo }; 145ffee1909SGyungoh Yoo 146ffee1909SGyungoh Yoo static struct regulator_ops max8907_bbat_ops = { 147ffee1909SGyungoh Yoo .list_voltage = regulator_list_voltage_linear, 148ffee1909SGyungoh Yoo .set_voltage_sel = regulator_set_voltage_sel_regmap, 149ffee1909SGyungoh Yoo .get_voltage_sel = regulator_get_voltage_sel_regmap, 150ffee1909SGyungoh Yoo }; 151ffee1909SGyungoh Yoo 152ffee1909SGyungoh Yoo static struct regulator_desc max8907_regulators[] = { 153ffee1909SGyungoh Yoo REG_MBATT(), 154ffee1909SGyungoh Yoo REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000), 155ffee1909SGyungoh Yoo REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500), 156ffee1909SGyungoh Yoo REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000), 157ffee1909SGyungoh Yoo LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1), 158ffee1909SGyungoh Yoo LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2), 159ffee1909SGyungoh Yoo LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3), 160ffee1909SGyungoh Yoo LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4), 161ffee1909SGyungoh Yoo LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5), 162ffee1909SGyungoh Yoo LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6), 163ffee1909SGyungoh Yoo LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7), 164ffee1909SGyungoh Yoo LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8), 165ffee1909SGyungoh Yoo LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9), 166ffee1909SGyungoh Yoo LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10), 167ffee1909SGyungoh Yoo LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11), 168ffee1909SGyungoh Yoo LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12), 169ffee1909SGyungoh Yoo LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13), 170ffee1909SGyungoh Yoo LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14), 171ffee1909SGyungoh Yoo LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15), 172ffee1909SGyungoh Yoo LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16), 173ffee1909SGyungoh Yoo LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17), 174ffee1909SGyungoh Yoo LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18), 175ffee1909SGyungoh Yoo LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19), 176ffee1909SGyungoh Yoo LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20), 177ffee1909SGyungoh Yoo REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000), 178ffee1909SGyungoh Yoo REG_OUT5V(OUT33V, "mbatt", MAX8907_REG_OUT33VEN, 3300000), 179ffee1909SGyungoh Yoo REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG, 180ffee1909SGyungoh Yoo 2400000, 3000000, 200000), 181ffee1909SGyungoh Yoo REG_FIXED(SDBY, "MBATT", 1200000), 182ffee1909SGyungoh Yoo REG_FIXED(VRTC, "MBATT", 3300000), 183ffee1909SGyungoh Yoo }; 184ffee1909SGyungoh Yoo 185ffee1909SGyungoh Yoo #ifdef CONFIG_OF 186ffee1909SGyungoh Yoo 187ffee1909SGyungoh Yoo #define MATCH(_name, _id) \ 188ffee1909SGyungoh Yoo [MAX8907_##_id] = { \ 189ffee1909SGyungoh Yoo .name = #_name, \ 190ffee1909SGyungoh Yoo .driver_data = (void *)&max8907_regulators[MAX8907_##_id], \ 191ffee1909SGyungoh Yoo } 192ffee1909SGyungoh Yoo 193ffee1909SGyungoh Yoo static struct of_regulator_match max8907_matches[] = { 194ffee1909SGyungoh Yoo MATCH(mbatt, MBATT), 195ffee1909SGyungoh Yoo MATCH(sd1, SD1), 196ffee1909SGyungoh Yoo MATCH(sd2, SD2), 197ffee1909SGyungoh Yoo MATCH(sd3, SD3), 198ffee1909SGyungoh Yoo MATCH(ldo1, LDO1), 199ffee1909SGyungoh Yoo MATCH(ldo2, LDO2), 200ffee1909SGyungoh Yoo MATCH(ldo3, LDO3), 201ffee1909SGyungoh Yoo MATCH(ldo4, LDO4), 202ffee1909SGyungoh Yoo MATCH(ldo5, LDO5), 203ffee1909SGyungoh Yoo MATCH(ldo6, LDO6), 204ffee1909SGyungoh Yoo MATCH(ldo7, LDO7), 205ffee1909SGyungoh Yoo MATCH(ldo8, LDO8), 206ffee1909SGyungoh Yoo MATCH(ldo9, LDO9), 207ffee1909SGyungoh Yoo MATCH(ldo10, LDO10), 208ffee1909SGyungoh Yoo MATCH(ldo11, LDO11), 209ffee1909SGyungoh Yoo MATCH(ldo12, LDO12), 210ffee1909SGyungoh Yoo MATCH(ldo13, LDO13), 211ffee1909SGyungoh Yoo MATCH(ldo14, LDO14), 212ffee1909SGyungoh Yoo MATCH(ldo15, LDO15), 213ffee1909SGyungoh Yoo MATCH(ldo16, LDO16), 214ffee1909SGyungoh Yoo MATCH(ldo17, LDO17), 215ffee1909SGyungoh Yoo MATCH(ldo18, LDO18), 216ffee1909SGyungoh Yoo MATCH(ldo19, LDO19), 217ffee1909SGyungoh Yoo MATCH(ldo20, LDO20), 218ffee1909SGyungoh Yoo MATCH(out5v, OUT5V), 219ffee1909SGyungoh Yoo MATCH(out33v, OUT33V), 220ffee1909SGyungoh Yoo MATCH(bbat, BBAT), 221ffee1909SGyungoh Yoo MATCH(sdby, SDBY), 222ffee1909SGyungoh Yoo MATCH(vrtc, VRTC), 223ffee1909SGyungoh Yoo }; 224ffee1909SGyungoh Yoo 225ffee1909SGyungoh Yoo static int max8907_regulator_parse_dt(struct platform_device *pdev) 226ffee1909SGyungoh Yoo { 227ffee1909SGyungoh Yoo struct device_node *np = pdev->dev.parent->of_node; 228ffee1909SGyungoh Yoo struct device_node *regulators; 229ffee1909SGyungoh Yoo int ret; 230ffee1909SGyungoh Yoo 231ffee1909SGyungoh Yoo if (!pdev->dev.parent->of_node) 232ffee1909SGyungoh Yoo return 0; 233ffee1909SGyungoh Yoo 234ffee1909SGyungoh Yoo regulators = of_find_node_by_name(np, "regulators"); 235ffee1909SGyungoh Yoo if (!regulators) { 236ffee1909SGyungoh Yoo dev_err(&pdev->dev, "regulators node not found\n"); 237ffee1909SGyungoh Yoo return -EINVAL; 238ffee1909SGyungoh Yoo } 239ffee1909SGyungoh Yoo 240ffee1909SGyungoh Yoo ret = of_regulator_match(pdev->dev.parent, regulators, 241ffee1909SGyungoh Yoo max8907_matches, 242ffee1909SGyungoh Yoo ARRAY_SIZE(max8907_matches)); 243ffee1909SGyungoh Yoo if (ret < 0) { 244ffee1909SGyungoh Yoo dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", 245ffee1909SGyungoh Yoo ret); 246ffee1909SGyungoh Yoo return ret; 247ffee1909SGyungoh Yoo } 248ffee1909SGyungoh Yoo 249ffee1909SGyungoh Yoo return 0; 250ffee1909SGyungoh Yoo } 251ffee1909SGyungoh Yoo #else 252ffee1909SGyungoh Yoo static int max8907_regulator_parse_dt(struct platform_device *pdev) 253ffee1909SGyungoh Yoo { 254ffee1909SGyungoh Yoo return 0; 255ffee1909SGyungoh Yoo } 256ffee1909SGyungoh Yoo #endif 257ffee1909SGyungoh Yoo 258ffee1909SGyungoh Yoo static __devinit int max8907_regulator_probe(struct platform_device *pdev) 259ffee1909SGyungoh Yoo { 260ffee1909SGyungoh Yoo struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); 261ffee1909SGyungoh Yoo struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev); 262ffee1909SGyungoh Yoo int ret; 263ffee1909SGyungoh Yoo struct max8907_regulator *pmic; 264ffee1909SGyungoh Yoo unsigned int val; 265ffee1909SGyungoh Yoo int i; 266ffee1909SGyungoh Yoo struct regulator_config config = {}; 267ffee1909SGyungoh Yoo struct regulator_init_data *idata; 268ffee1909SGyungoh Yoo const char *mbatt_rail_name = NULL; 269ffee1909SGyungoh Yoo 270ffee1909SGyungoh Yoo ret = max8907_regulator_parse_dt(pdev); 271ffee1909SGyungoh Yoo if (ret) 272ffee1909SGyungoh Yoo return ret; 273ffee1909SGyungoh Yoo 274ffee1909SGyungoh Yoo pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 275ffee1909SGyungoh Yoo if (!pmic) { 276ffee1909SGyungoh Yoo dev_err(&pdev->dev, "Failed to alloc pmic\n"); 277ffee1909SGyungoh Yoo return -ENOMEM; 278ffee1909SGyungoh Yoo } 279ffee1909SGyungoh Yoo platform_set_drvdata(pdev, pmic); 280ffee1909SGyungoh Yoo 281ffee1909SGyungoh Yoo memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc)); 282ffee1909SGyungoh Yoo 283ffee1909SGyungoh Yoo /* Backwards compatibility with MAX8907B; SD1 uses different voltages */ 284ffee1909SGyungoh Yoo regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val); 285ffee1909SGyungoh Yoo if ((val & MAX8907_II2RR_VERSION_MASK) == 286ffee1909SGyungoh Yoo MAX8907_II2RR_VERSION_REV_B) { 287ffee1909SGyungoh Yoo pmic->desc[MAX8907_SD1].min_uV = 637500; 288ffee1909SGyungoh Yoo pmic->desc[MAX8907_SD1].uV_step = 12500; 289ffee1909SGyungoh Yoo pmic->desc[MAX8907_SD1].n_voltages = (1425000 - 637500) / 12500; 290ffee1909SGyungoh Yoo } 291ffee1909SGyungoh Yoo 292ffee1909SGyungoh Yoo for (i = 0; i < MAX8907_NUM_REGULATORS; i++) { 293ffee1909SGyungoh Yoo config.dev = pdev->dev.parent; 294ffee1909SGyungoh Yoo if (pdata) 295ffee1909SGyungoh Yoo idata = pdata->init_data[i]; 296ffee1909SGyungoh Yoo else 297ffee1909SGyungoh Yoo idata = max8907_matches[i].init_data; 298ffee1909SGyungoh Yoo config.init_data = idata; 299ffee1909SGyungoh Yoo config.driver_data = pmic; 300ffee1909SGyungoh Yoo config.regmap = max8907->regmap_gen; 301ffee1909SGyungoh Yoo config.of_node = max8907_matches[i].of_node; 302ffee1909SGyungoh Yoo 303ffee1909SGyungoh Yoo switch (pmic->desc[i].id) { 304ffee1909SGyungoh Yoo case MAX8907_MBATT: 305ffee1909SGyungoh Yoo mbatt_rail_name = idata->constraints.name; 306ffee1909SGyungoh Yoo break; 307ffee1909SGyungoh Yoo case MAX8907_BBAT: 308ffee1909SGyungoh Yoo case MAX8907_SDBY: 309ffee1909SGyungoh Yoo case MAX8907_VRTC: 310ffee1909SGyungoh Yoo idata->supply_regulator = mbatt_rail_name; 311ffee1909SGyungoh Yoo break; 312ffee1909SGyungoh Yoo } 313ffee1909SGyungoh Yoo 314ffee1909SGyungoh Yoo if (pmic->desc[i].ops == &max8907_ldo_ops) { 315ffee1909SGyungoh Yoo regmap_read(config.regmap, pmic->desc[i].enable_reg, 316ffee1909SGyungoh Yoo &val); 317ffee1909SGyungoh Yoo if ((val & MAX8907_MASK_LDO_SEQ) != 318ffee1909SGyungoh Yoo MAX8907_MASK_LDO_SEQ) 319ffee1909SGyungoh Yoo pmic->desc[i].ops = &max8907_ldo_hwctl_ops; 320ffee1909SGyungoh Yoo } else if (pmic->desc[i].ops == &max8907_out5v_ops) { 321ffee1909SGyungoh Yoo regmap_read(config.regmap, pmic->desc[i].enable_reg, 322ffee1909SGyungoh Yoo &val); 323ffee1909SGyungoh Yoo if ((val & (MAX8907_MASK_OUT5V_VINEN | 324ffee1909SGyungoh Yoo MAX8907_MASK_OUT5V_ENSRC)) != 325ffee1909SGyungoh Yoo MAX8907_MASK_OUT5V_ENSRC) 326ffee1909SGyungoh Yoo pmic->desc[i].ops = &max8907_out5v_hwctl_ops; 327ffee1909SGyungoh Yoo } 328ffee1909SGyungoh Yoo 329ffee1909SGyungoh Yoo pmic->rdev[i] = regulator_register(&pmic->desc[i], &config); 330ffee1909SGyungoh Yoo if (IS_ERR(pmic->rdev[i])) { 331ffee1909SGyungoh Yoo dev_err(&pdev->dev, 332ffee1909SGyungoh Yoo "failed to register %s regulator\n", 333ffee1909SGyungoh Yoo pmic->desc[i].name); 334ffee1909SGyungoh Yoo ret = PTR_ERR(pmic->rdev[i]); 335ffee1909SGyungoh Yoo goto err_unregister_regulator; 336ffee1909SGyungoh Yoo } 337ffee1909SGyungoh Yoo } 338ffee1909SGyungoh Yoo 339ffee1909SGyungoh Yoo return 0; 340ffee1909SGyungoh Yoo 341ffee1909SGyungoh Yoo err_unregister_regulator: 342ffee1909SGyungoh Yoo while (--i >= 0) 343ffee1909SGyungoh Yoo regulator_unregister(pmic->rdev[i]); 344ffee1909SGyungoh Yoo return ret; 345ffee1909SGyungoh Yoo } 346ffee1909SGyungoh Yoo 347ffee1909SGyungoh Yoo static __devexit int max8907_regulator_remove(struct platform_device *pdev) 348ffee1909SGyungoh Yoo { 349ffee1909SGyungoh Yoo struct max8907_regulator *pmic; 350ffee1909SGyungoh Yoo int i; 351ffee1909SGyungoh Yoo 352ffee1909SGyungoh Yoo for (i = 0; i < MAX8907_NUM_REGULATORS; i++) 353ffee1909SGyungoh Yoo regulator_unregister(pmic->rdev[i]); 354ffee1909SGyungoh Yoo 355ffee1909SGyungoh Yoo return 0; 356ffee1909SGyungoh Yoo } 357ffee1909SGyungoh Yoo 358ffee1909SGyungoh Yoo static struct platform_driver max8907_regulator_driver = { 359ffee1909SGyungoh Yoo .driver = { 360ffee1909SGyungoh Yoo .name = "max8907-regulator", 361ffee1909SGyungoh Yoo .owner = THIS_MODULE, 362ffee1909SGyungoh Yoo }, 363ffee1909SGyungoh Yoo .probe = max8907_regulator_probe, 364ffee1909SGyungoh Yoo .remove = __devexit_p(max8907_regulator_remove), 365ffee1909SGyungoh Yoo }; 366ffee1909SGyungoh Yoo 367ffee1909SGyungoh Yoo static int __init max8907_regulator_init(void) 368ffee1909SGyungoh Yoo { 369ffee1909SGyungoh Yoo return platform_driver_register(&max8907_regulator_driver); 370ffee1909SGyungoh Yoo } 371ffee1909SGyungoh Yoo 372ffee1909SGyungoh Yoo subsys_initcall(max8907_regulator_init); 373ffee1909SGyungoh Yoo 374ffee1909SGyungoh Yoo static void __exit max8907_reg_exit(void) 375ffee1909SGyungoh Yoo { 376ffee1909SGyungoh Yoo platform_driver_unregister(&max8907_regulator_driver); 377ffee1909SGyungoh Yoo } 378ffee1909SGyungoh Yoo 379ffee1909SGyungoh Yoo module_exit(max8907_reg_exit); 380ffee1909SGyungoh Yoo 381ffee1909SGyungoh Yoo MODULE_DESCRIPTION("MAX8907 regulator driver"); 382ffee1909SGyungoh Yoo MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>"); 383ffee1909SGyungoh Yoo MODULE_LICENSE("GPL v2"); 384