1 /* 2 * TI LM363X Regulator Driver 3 * 4 * Copyright 2015 Texas Instruments 5 * 6 * Author: Milo Kim <milo.kim@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/err.h> 14 #include <linux/kernel.h> 15 #include <linux/mfd/ti-lmu.h> 16 #include <linux/mfd/ti-lmu-register.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/gpio/consumer.h> 20 #include <linux/platform_device.h> 21 #include <linux/regulator/driver.h> 22 #include <linux/regulator/of_regulator.h> 23 #include <linux/slab.h> 24 25 /* LM3631 */ 26 #define LM3631_BOOST_VSEL_MAX 0x25 27 #define LM3631_LDO_VSEL_MAX 0x28 28 #define LM3631_CONT_VSEL_MAX 0x03 29 #define LM3631_VBOOST_MIN 4500000 30 #define LM3631_VCONT_MIN 1800000 31 #define LM3631_VLDO_MIN 4000000 32 #define ENABLE_TIME_USEC 1000 33 34 /* LM3632 */ 35 #define LM3632_BOOST_VSEL_MAX 0x26 36 #define LM3632_LDO_VSEL_MAX 0x29 37 #define LM3632_VBOOST_MIN 4500000 38 #define LM3632_VLDO_MIN 4000000 39 40 /* Common */ 41 #define LM363X_STEP_50mV 50000 42 #define LM363X_STEP_500mV 500000 43 44 static const int ldo_cont_enable_time[] = { 45 0, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 46 }; 47 48 static int lm363x_regulator_enable_time(struct regulator_dev *rdev) 49 { 50 enum lm363x_regulator_id id = rdev_get_id(rdev); 51 unsigned int val, addr, mask; 52 53 switch (id) { 54 case LM3631_LDO_CONT: 55 addr = LM3631_REG_ENTIME_VCONT; 56 mask = LM3631_ENTIME_CONT_MASK; 57 break; 58 case LM3631_LDO_OREF: 59 addr = LM3631_REG_ENTIME_VOREF; 60 mask = LM3631_ENTIME_MASK; 61 break; 62 case LM3631_LDO_POS: 63 addr = LM3631_REG_ENTIME_VPOS; 64 mask = LM3631_ENTIME_MASK; 65 break; 66 case LM3631_LDO_NEG: 67 addr = LM3631_REG_ENTIME_VNEG; 68 mask = LM3631_ENTIME_MASK; 69 break; 70 default: 71 return 0; 72 } 73 74 if (regmap_read(rdev->regmap, addr, &val)) 75 return -EINVAL; 76 77 val = (val & mask) >> LM3631_ENTIME_SHIFT; 78 79 if (id == LM3631_LDO_CONT) 80 return ldo_cont_enable_time[val]; 81 else 82 return ENABLE_TIME_USEC * val; 83 } 84 85 static const struct regulator_ops lm363x_boost_voltage_table_ops = { 86 .list_voltage = regulator_list_voltage_linear, 87 .set_voltage_sel = regulator_set_voltage_sel_regmap, 88 .get_voltage_sel = regulator_get_voltage_sel_regmap, 89 }; 90 91 static const struct regulator_ops lm363x_regulator_voltage_table_ops = { 92 .list_voltage = regulator_list_voltage_linear, 93 .set_voltage_sel = regulator_set_voltage_sel_regmap, 94 .get_voltage_sel = regulator_get_voltage_sel_regmap, 95 .enable = regulator_enable_regmap, 96 .disable = regulator_disable_regmap, 97 .is_enabled = regulator_is_enabled_regmap, 98 .enable_time = lm363x_regulator_enable_time, 99 }; 100 101 static const struct regulator_desc lm363x_regulator_desc[] = { 102 /* LM3631 */ 103 { 104 .name = "vboost", 105 .of_match = "vboost", 106 .id = LM3631_BOOST, 107 .ops = &lm363x_boost_voltage_table_ops, 108 .n_voltages = LM3631_BOOST_VSEL_MAX + 1, 109 .min_uV = LM3631_VBOOST_MIN, 110 .uV_step = LM363X_STEP_50mV, 111 .type = REGULATOR_VOLTAGE, 112 .owner = THIS_MODULE, 113 .vsel_reg = LM3631_REG_VOUT_BOOST, 114 .vsel_mask = LM3631_VOUT_MASK, 115 }, 116 { 117 .name = "ldo_cont", 118 .of_match = "vcont", 119 .id = LM3631_LDO_CONT, 120 .ops = &lm363x_regulator_voltage_table_ops, 121 .n_voltages = LM3631_CONT_VSEL_MAX + 1, 122 .min_uV = LM3631_VCONT_MIN, 123 .uV_step = LM363X_STEP_500mV, 124 .type = REGULATOR_VOLTAGE, 125 .owner = THIS_MODULE, 126 .vsel_reg = LM3631_REG_VOUT_CONT, 127 .vsel_mask = LM3631_VOUT_CONT_MASK, 128 .enable_reg = LM3631_REG_LDO_CTRL2, 129 .enable_mask = LM3631_EN_CONT_MASK, 130 }, 131 { 132 .name = "ldo_oref", 133 .of_match = "voref", 134 .id = LM3631_LDO_OREF, 135 .ops = &lm363x_regulator_voltage_table_ops, 136 .n_voltages = LM3631_LDO_VSEL_MAX + 1, 137 .min_uV = LM3631_VLDO_MIN, 138 .uV_step = LM363X_STEP_50mV, 139 .type = REGULATOR_VOLTAGE, 140 .owner = THIS_MODULE, 141 .vsel_reg = LM3631_REG_VOUT_OREF, 142 .vsel_mask = LM3631_VOUT_MASK, 143 .enable_reg = LM3631_REG_LDO_CTRL1, 144 .enable_mask = LM3631_EN_OREF_MASK, 145 }, 146 { 147 .name = "ldo_vpos", 148 .of_match = "vpos", 149 .id = LM3631_LDO_POS, 150 .ops = &lm363x_regulator_voltage_table_ops, 151 .n_voltages = LM3631_LDO_VSEL_MAX + 1, 152 .min_uV = LM3631_VLDO_MIN, 153 .uV_step = LM363X_STEP_50mV, 154 .type = REGULATOR_VOLTAGE, 155 .owner = THIS_MODULE, 156 .vsel_reg = LM3631_REG_VOUT_POS, 157 .vsel_mask = LM3631_VOUT_MASK, 158 .enable_reg = LM3631_REG_LDO_CTRL1, 159 .enable_mask = LM3631_EN_VPOS_MASK, 160 }, 161 { 162 .name = "ldo_vneg", 163 .of_match = "vneg", 164 .id = LM3631_LDO_NEG, 165 .ops = &lm363x_regulator_voltage_table_ops, 166 .n_voltages = LM3631_LDO_VSEL_MAX + 1, 167 .min_uV = LM3631_VLDO_MIN, 168 .uV_step = LM363X_STEP_50mV, 169 .type = REGULATOR_VOLTAGE, 170 .owner = THIS_MODULE, 171 .vsel_reg = LM3631_REG_VOUT_NEG, 172 .vsel_mask = LM3631_VOUT_MASK, 173 .enable_reg = LM3631_REG_LDO_CTRL1, 174 .enable_mask = LM3631_EN_VNEG_MASK, 175 }, 176 /* LM3632 */ 177 { 178 .name = "vboost", 179 .of_match = "vboost", 180 .id = LM3632_BOOST, 181 .ops = &lm363x_boost_voltage_table_ops, 182 .n_voltages = LM3632_BOOST_VSEL_MAX + 1, 183 .min_uV = LM3632_VBOOST_MIN, 184 .uV_step = LM363X_STEP_50mV, 185 .type = REGULATOR_VOLTAGE, 186 .owner = THIS_MODULE, 187 .vsel_reg = LM3632_REG_VOUT_BOOST, 188 .vsel_mask = LM3632_VOUT_MASK, 189 }, 190 { 191 .name = "ldo_vpos", 192 .of_match = "vpos", 193 .id = LM3632_LDO_POS, 194 .ops = &lm363x_regulator_voltage_table_ops, 195 .n_voltages = LM3632_LDO_VSEL_MAX + 1, 196 .min_uV = LM3632_VLDO_MIN, 197 .uV_step = LM363X_STEP_50mV, 198 .type = REGULATOR_VOLTAGE, 199 .owner = THIS_MODULE, 200 .vsel_reg = LM3632_REG_VOUT_POS, 201 .vsel_mask = LM3632_VOUT_MASK, 202 .enable_reg = LM3632_REG_BIAS_CONFIG, 203 .enable_mask = LM3632_EN_VPOS_MASK, 204 }, 205 { 206 .name = "ldo_vneg", 207 .of_match = "vneg", 208 .id = LM3632_LDO_NEG, 209 .ops = &lm363x_regulator_voltage_table_ops, 210 .n_voltages = LM3632_LDO_VSEL_MAX + 1, 211 .min_uV = LM3632_VLDO_MIN, 212 .uV_step = LM363X_STEP_50mV, 213 .type = REGULATOR_VOLTAGE, 214 .owner = THIS_MODULE, 215 .vsel_reg = LM3632_REG_VOUT_NEG, 216 .vsel_mask = LM3632_VOUT_MASK, 217 .enable_reg = LM3632_REG_BIAS_CONFIG, 218 .enable_mask = LM3632_EN_VNEG_MASK, 219 }, 220 }; 221 222 static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id) 223 { 224 /* 225 * Check LCM_EN1/2_GPIO is configured. 226 * Those pins are used for enabling VPOS/VNEG LDOs. 227 * Do not use devm* here: the regulator core takes over the 228 * lifecycle management of the GPIO descriptor. 229 */ 230 switch (id) { 231 case LM3632_LDO_POS: 232 return gpiod_get_index_optional(dev, "enable", 0, 233 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); 234 case LM3632_LDO_NEG: 235 return gpiod_get_index_optional(dev, "enable", 1, 236 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); 237 default: 238 return NULL; 239 } 240 } 241 242 static int lm363x_regulator_probe(struct platform_device *pdev) 243 { 244 struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent); 245 struct regmap *regmap = lmu->regmap; 246 struct regulator_config cfg = { }; 247 struct regulator_dev *rdev; 248 struct device *dev = &pdev->dev; 249 int id = pdev->id; 250 struct gpio_desc *gpiod; 251 int ret; 252 253 cfg.dev = dev; 254 cfg.regmap = regmap; 255 256 /* 257 * LM3632 LDOs can be controlled by external pin. 258 * Register update is required if the pin is used. 259 */ 260 gpiod = lm363x_regulator_of_get_enable_gpio(dev, id); 261 if (IS_ERR(gpiod)) 262 return PTR_ERR(gpiod); 263 264 if (gpiod) { 265 cfg.ena_gpiod = gpiod; 266 267 ret = regmap_update_bits(regmap, LM3632_REG_BIAS_CONFIG, 268 LM3632_EXT_EN_MASK, 269 LM3632_EXT_EN_MASK); 270 if (ret) { 271 gpiod_put(gpiod); 272 dev_err(dev, "External pin err: %d\n", ret); 273 return ret; 274 } 275 } 276 277 rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg); 278 if (IS_ERR(rdev)) { 279 ret = PTR_ERR(rdev); 280 dev_err(dev, "[%d] regulator register err: %d\n", id, ret); 281 return ret; 282 } 283 284 return 0; 285 } 286 287 static struct platform_driver lm363x_regulator_driver = { 288 .probe = lm363x_regulator_probe, 289 .driver = { 290 .name = "lm363x-regulator", 291 }, 292 }; 293 294 module_platform_driver(lm363x_regulator_driver); 295 296 MODULE_DESCRIPTION("TI LM363X Regulator Driver"); 297 MODULE_AUTHOR("Milo Kim"); 298 MODULE_LICENSE("GPL v2"); 299 MODULE_ALIAS("platform:lm363x-regulator"); 300