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 240f40cbcb9SAxel Lin ret = of_regulator_match(&pdev->dev, regulators, max8907_matches, 241ffee1909SGyungoh Yoo ARRAY_SIZE(max8907_matches)); 242ffee1909SGyungoh Yoo if (ret < 0) { 243ffee1909SGyungoh Yoo dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", 244ffee1909SGyungoh Yoo ret); 245ffee1909SGyungoh Yoo return ret; 246ffee1909SGyungoh Yoo } 247ffee1909SGyungoh Yoo 248ffee1909SGyungoh Yoo return 0; 249ffee1909SGyungoh Yoo } 250db551682SStephen Warren 251db551682SStephen Warren static inline struct regulator_init_data *match_init_data(int index) 252db551682SStephen Warren { 253db551682SStephen Warren return max8907_matches[index].init_data; 254db551682SStephen Warren } 255db551682SStephen Warren 256db551682SStephen Warren static inline struct device_node *match_of_node(int index) 257db551682SStephen Warren { 258db551682SStephen Warren return max8907_matches[index].of_node; 259db551682SStephen Warren } 260ffee1909SGyungoh Yoo #else 261ffee1909SGyungoh Yoo static int max8907_regulator_parse_dt(struct platform_device *pdev) 262ffee1909SGyungoh Yoo { 263ffee1909SGyungoh Yoo return 0; 264ffee1909SGyungoh Yoo } 265db551682SStephen Warren 266db551682SStephen Warren static inline struct regulator_init_data *match_init_data(int index) 267db551682SStephen Warren { 268db551682SStephen Warren return NULL; 269db551682SStephen Warren } 270db551682SStephen Warren 271db551682SStephen Warren static inline struct device_node *match_of_node(int index) 272db551682SStephen Warren { 273db551682SStephen Warren return NULL; 274db551682SStephen Warren } 275ffee1909SGyungoh Yoo #endif 276ffee1909SGyungoh Yoo 277a5023574SBill Pemberton static int max8907_regulator_probe(struct platform_device *pdev) 278ffee1909SGyungoh Yoo { 279ffee1909SGyungoh Yoo struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); 280ffee1909SGyungoh Yoo struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev); 281ffee1909SGyungoh Yoo int ret; 282ffee1909SGyungoh Yoo struct max8907_regulator *pmic; 283ffee1909SGyungoh Yoo unsigned int val; 284ffee1909SGyungoh Yoo int i; 285ffee1909SGyungoh Yoo struct regulator_config config = {}; 286ffee1909SGyungoh Yoo struct regulator_init_data *idata; 287ffee1909SGyungoh Yoo const char *mbatt_rail_name = NULL; 288ffee1909SGyungoh Yoo 289ffee1909SGyungoh Yoo ret = max8907_regulator_parse_dt(pdev); 290ffee1909SGyungoh Yoo if (ret) 291ffee1909SGyungoh Yoo return ret; 292ffee1909SGyungoh Yoo 293ffee1909SGyungoh Yoo pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 294ffee1909SGyungoh Yoo if (!pmic) { 295ffee1909SGyungoh Yoo dev_err(&pdev->dev, "Failed to alloc pmic\n"); 296ffee1909SGyungoh Yoo return -ENOMEM; 297ffee1909SGyungoh Yoo } 298ffee1909SGyungoh Yoo platform_set_drvdata(pdev, pmic); 299ffee1909SGyungoh Yoo 300ffee1909SGyungoh Yoo memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc)); 301ffee1909SGyungoh Yoo 302ffee1909SGyungoh Yoo /* Backwards compatibility with MAX8907B; SD1 uses different voltages */ 303ffee1909SGyungoh Yoo regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val); 304ffee1909SGyungoh Yoo if ((val & MAX8907_II2RR_VERSION_MASK) == 305ffee1909SGyungoh Yoo MAX8907_II2RR_VERSION_REV_B) { 306ffee1909SGyungoh Yoo pmic->desc[MAX8907_SD1].min_uV = 637500; 307ffee1909SGyungoh Yoo pmic->desc[MAX8907_SD1].uV_step = 12500; 3087305608bSAxel Lin pmic->desc[MAX8907_SD1].n_voltages = 3097305608bSAxel Lin (1425000 - 637500) / 12500 + 1; 310ffee1909SGyungoh Yoo } 311ffee1909SGyungoh Yoo 312ffee1909SGyungoh Yoo for (i = 0; i < MAX8907_NUM_REGULATORS; i++) { 313ffee1909SGyungoh Yoo config.dev = pdev->dev.parent; 314ffee1909SGyungoh Yoo if (pdata) 315ffee1909SGyungoh Yoo idata = pdata->init_data[i]; 316ffee1909SGyungoh Yoo else 317db551682SStephen Warren idata = match_init_data(i); 318ffee1909SGyungoh Yoo config.init_data = idata; 319ffee1909SGyungoh Yoo config.driver_data = pmic; 320ffee1909SGyungoh Yoo config.regmap = max8907->regmap_gen; 321db551682SStephen Warren config.of_node = match_of_node(i); 322ffee1909SGyungoh Yoo 323ffee1909SGyungoh Yoo switch (pmic->desc[i].id) { 324ffee1909SGyungoh Yoo case MAX8907_MBATT: 3255fc72f57SStephen Warren if (idata && idata->constraints.name) 326ffee1909SGyungoh Yoo mbatt_rail_name = idata->constraints.name; 3275fc72f57SStephen Warren else 3285fc72f57SStephen Warren mbatt_rail_name = pmic->desc[i].name; 329ffee1909SGyungoh Yoo break; 330ffee1909SGyungoh Yoo case MAX8907_BBAT: 331ffee1909SGyungoh Yoo case MAX8907_SDBY: 332ffee1909SGyungoh Yoo case MAX8907_VRTC: 333ffee1909SGyungoh Yoo idata->supply_regulator = mbatt_rail_name; 334ffee1909SGyungoh Yoo break; 335ffee1909SGyungoh Yoo } 336ffee1909SGyungoh Yoo 337ffee1909SGyungoh Yoo if (pmic->desc[i].ops == &max8907_ldo_ops) { 338ffee1909SGyungoh Yoo regmap_read(config.regmap, pmic->desc[i].enable_reg, 339ffee1909SGyungoh Yoo &val); 340ffee1909SGyungoh Yoo if ((val & MAX8907_MASK_LDO_SEQ) != 341ffee1909SGyungoh Yoo MAX8907_MASK_LDO_SEQ) 342ffee1909SGyungoh Yoo pmic->desc[i].ops = &max8907_ldo_hwctl_ops; 343ffee1909SGyungoh Yoo } else if (pmic->desc[i].ops == &max8907_out5v_ops) { 344ffee1909SGyungoh Yoo regmap_read(config.regmap, pmic->desc[i].enable_reg, 345ffee1909SGyungoh Yoo &val); 346ffee1909SGyungoh Yoo if ((val & (MAX8907_MASK_OUT5V_VINEN | 347ffee1909SGyungoh Yoo MAX8907_MASK_OUT5V_ENSRC)) != 348ffee1909SGyungoh Yoo MAX8907_MASK_OUT5V_ENSRC) 349ffee1909SGyungoh Yoo pmic->desc[i].ops = &max8907_out5v_hwctl_ops; 350ffee1909SGyungoh Yoo } 351ffee1909SGyungoh Yoo 352ffee1909SGyungoh Yoo pmic->rdev[i] = regulator_register(&pmic->desc[i], &config); 353ffee1909SGyungoh Yoo if (IS_ERR(pmic->rdev[i])) { 354ffee1909SGyungoh Yoo dev_err(&pdev->dev, 355ffee1909SGyungoh Yoo "failed to register %s regulator\n", 356ffee1909SGyungoh Yoo pmic->desc[i].name); 357ffee1909SGyungoh Yoo ret = PTR_ERR(pmic->rdev[i]); 358ffee1909SGyungoh Yoo goto err_unregister_regulator; 359ffee1909SGyungoh Yoo } 360ffee1909SGyungoh Yoo } 361ffee1909SGyungoh Yoo 362ffee1909SGyungoh Yoo return 0; 363ffee1909SGyungoh Yoo 364ffee1909SGyungoh Yoo err_unregister_regulator: 365ffee1909SGyungoh Yoo while (--i >= 0) 366ffee1909SGyungoh Yoo regulator_unregister(pmic->rdev[i]); 367ffee1909SGyungoh Yoo return ret; 368ffee1909SGyungoh Yoo } 369ffee1909SGyungoh Yoo 3708dc995f5SBill Pemberton static int max8907_regulator_remove(struct platform_device *pdev) 371ffee1909SGyungoh Yoo { 3720764ef59SAxel Lin struct max8907_regulator *pmic = platform_get_drvdata(pdev); 373ffee1909SGyungoh Yoo int i; 374ffee1909SGyungoh Yoo 375ffee1909SGyungoh Yoo for (i = 0; i < MAX8907_NUM_REGULATORS; i++) 376ffee1909SGyungoh Yoo regulator_unregister(pmic->rdev[i]); 377ffee1909SGyungoh Yoo 378ffee1909SGyungoh Yoo return 0; 379ffee1909SGyungoh Yoo } 380ffee1909SGyungoh Yoo 381ffee1909SGyungoh Yoo static struct platform_driver max8907_regulator_driver = { 382ffee1909SGyungoh Yoo .driver = { 383ffee1909SGyungoh Yoo .name = "max8907-regulator", 384ffee1909SGyungoh Yoo .owner = THIS_MODULE, 385ffee1909SGyungoh Yoo }, 386ffee1909SGyungoh Yoo .probe = max8907_regulator_probe, 3875eb9f2b9SBill Pemberton .remove = max8907_regulator_remove, 388ffee1909SGyungoh Yoo }; 389ffee1909SGyungoh Yoo 390ffee1909SGyungoh Yoo static int __init max8907_regulator_init(void) 391ffee1909SGyungoh Yoo { 392ffee1909SGyungoh Yoo return platform_driver_register(&max8907_regulator_driver); 393ffee1909SGyungoh Yoo } 394ffee1909SGyungoh Yoo 395ffee1909SGyungoh Yoo subsys_initcall(max8907_regulator_init); 396ffee1909SGyungoh Yoo 397ffee1909SGyungoh Yoo static void __exit max8907_reg_exit(void) 398ffee1909SGyungoh Yoo { 399ffee1909SGyungoh Yoo platform_driver_unregister(&max8907_regulator_driver); 400ffee1909SGyungoh Yoo } 401ffee1909SGyungoh Yoo 402ffee1909SGyungoh Yoo module_exit(max8907_reg_exit); 403ffee1909SGyungoh Yoo 404ffee1909SGyungoh Yoo MODULE_DESCRIPTION("MAX8907 regulator driver"); 405ffee1909SGyungoh Yoo MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>"); 406ffee1909SGyungoh Yoo MODULE_LICENSE("GPL v2"); 407d154f0a6SAxel Lin MODULE_ALIAS("platform:max8907-regulator"); 408