1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2016 4 * Texas Instruments Incorporated, <www.ti.com> 5 * 6 * Keerthy <j-keerthy@ti.com> 7 */ 8 9#include <common.h> 10#include <fdtdec.h> 11#include <errno.h> 12#include <dm.h> 13#include <power/pmic.h> 14#include <power/regulator.h> 15#include <power/lp873x.h> 16 17static const char lp873x_buck_ctrl[LP873X_BUCK_NUM] = {0x2, 0x4}; 18static const char lp873x_buck_volt[LP873X_BUCK_NUM] = {0x6, 0x7}; 19static const char lp873x_ldo_ctrl[LP873X_LDO_NUM] = {0x8, 0x9}; 20static const char lp873x_ldo_volt[LP873X_LDO_NUM] = {0xA, 0xB}; 21 22static int lp873x_buck_enable(struct udevice *dev, int op, bool *enable) 23{ 24 int ret; 25 unsigned int adr; 26 struct dm_regulator_uclass_plat *uc_pdata; 27 28 uc_pdata = dev_get_uclass_plat(dev); 29 adr = uc_pdata->ctrl_reg; 30 31 ret = pmic_reg_read(dev->parent, adr); 32 if (ret < 0) 33 return ret; 34 35 if (op == PMIC_OP_GET) { 36 ret &= LP873X_BUCK_MODE_MASK; 37 38 if (ret) 39 *enable = true; 40 else 41 *enable = false; 42 43 return 0; 44 } else if (op == PMIC_OP_SET) { 45 if (*enable) 46 ret |= LP873X_BUCK_MODE_MASK; 47 else 48 ret &= ~(LP873X_BUCK_MODE_MASK); 49 ret = pmic_reg_write(dev->parent, adr, ret); 50 if (ret) 51 return ret; 52 } 53 54 return 0; 55} 56 57static int lp873x_buck_volt2hex(int uV) 58{ 59 if (uV > LP873X_BUCK_VOLT_MAX) 60 return -EINVAL; 61 else if (uV > 1400000) 62 return (uV - 1420000) / 20000 + 0x9E; 63 else if (uV > 730000) 64 return (uV - 735000) / 5000 + 0x18; 65 else if (uV >= 700000) 66 return (uV - 700000) / 10000 + 0x1; 67 else 68 return -EINVAL; 69} 70 71static int lp873x_buck_hex2volt(int hex) 72{ 73 if (hex > LP873X_BUCK_VOLT_MAX_HEX) 74 return -EINVAL; 75 else if (hex > 0x9D) 76 return 1400000 + (hex - 0x9D) * 20000; 77 else if (hex > 0x17) 78 return 730000 + (hex - 0x17) * 5000; 79 else if (hex >= 0x14) 80 return 700000 + (hex - 0x14) * 10000; 81 else 82 return -EINVAL; 83} 84 85static int lp873x_buck_val(struct udevice *dev, int op, int *uV) 86{ 87 unsigned int hex, adr; 88 int ret; 89 struct dm_regulator_uclass_plat *uc_pdata; 90 91 uc_pdata = dev_get_uclass_plat(dev); 92 93 if (op == PMIC_OP_GET) 94 *uV = 0; 95 96 adr = uc_pdata->volt_reg; 97 98 ret = pmic_reg_read(dev->parent, adr); 99 if (ret < 0) 100 return ret; 101 102 if (op == PMIC_OP_GET) { 103 ret &= LP873X_BUCK_VOLT_MASK; 104 ret = lp873x_buck_hex2volt(ret); 105 if (ret < 0) 106 return ret; 107 *uV = ret; 108 109 return 0; 110 } 111 112 hex = lp873x_buck_volt2hex(*uV); 113 if (hex < 0) 114 return hex; 115 116 ret &= 0x0; 117 ret |= hex; 118 119 ret = pmic_reg_write(dev->parent, adr, ret); 120 121 return ret; 122} 123 124static int lp873x_ldo_enable(struct udevice *dev, int op, bool *enable) 125{ 126 int ret; 127 unsigned int adr; 128 struct dm_regulator_uclass_plat *uc_pdata; 129 130 uc_pdata = dev_get_uclass_plat(dev); 131 adr = uc_pdata->ctrl_reg; 132 133 ret = pmic_reg_read(dev->parent, adr); 134 if (ret < 0) 135 return ret; 136 137 if (op == PMIC_OP_GET) { 138 ret &= LP873X_LDO_MODE_MASK; 139 140 if (ret) 141 *enable = true; 142 else 143 *enable = false; 144 145 return 0; 146 } else if (op == PMIC_OP_SET) { 147 if (*enable) 148 ret |= LP873X_LDO_MODE_MASK; 149 else 150 ret &= ~(LP873X_LDO_MODE_MASK); 151 152 ret = pmic_reg_write(dev->parent, adr, ret); 153 if (ret) 154 return ret; 155 } 156 157 return 0; 158} 159 160static int lp873x_ldo_volt2hex(int uV) 161{ 162 if (uV > LP873X_LDO_VOLT_MAX) 163 return -EINVAL; 164 165 return (uV - 800000) / 100000; 166} 167 168static int lp873x_ldo_hex2volt(int hex) 169{ 170 if (hex > LP873X_LDO_VOLT_MAX_HEX) 171 return -EINVAL; 172 173 if (!hex) 174 return 0; 175 176 return (hex * 100000) + 800000; 177} 178 179static int lp873x_ldo_val(struct udevice *dev, int op, int *uV) 180{ 181 unsigned int hex, adr; 182 int ret; 183 184 struct dm_regulator_uclass_plat *uc_pdata; 185 186 if (op == PMIC_OP_GET) 187 *uV = 0; 188 189 uc_pdata = dev_get_uclass_plat(dev); 190 191 adr = uc_pdata->volt_reg; 192 193 ret = pmic_reg_read(dev->parent, adr); 194 if (ret < 0) 195 return ret; 196 197 if (op == PMIC_OP_GET) { 198 ret &= LP873X_LDO_VOLT_MASK; 199 ret = lp873x_ldo_hex2volt(ret); 200 if (ret < 0) 201 return ret; 202 *uV = ret; 203 return 0; 204 } 205 206 hex = lp873x_ldo_volt2hex(*uV); 207 if (hex < 0) 208 return hex; 209 210 ret &= ~LP873X_LDO_VOLT_MASK; 211 ret |= hex; 212 if (*uV > 1650000) 213 ret |= 0x80; 214 ret = pmic_reg_write(dev->parent, adr, ret); 215 216 return ret; 217} 218 219static int lp873x_ldo_probe(struct udevice *dev) 220{ 221 struct dm_regulator_uclass_plat *uc_pdata; 222 223 uc_pdata = dev_get_uclass_plat(dev); 224 uc_pdata->type = REGULATOR_TYPE_LDO; 225 226 int idx = dev->driver_data; 227 if (idx >= LP873X_LDO_NUM) { 228 printf("Wrong ID for regulator\n"); 229 return -1; 230 } 231 232 uc_pdata->ctrl_reg = lp873x_ldo_ctrl[idx]; 233 uc_pdata->volt_reg = lp873x_ldo_volt[idx]; 234 235 return 0; 236} 237 238static int ldo_get_value(struct udevice *dev) 239{ 240 int uV; 241 int ret; 242 243 ret = lp873x_ldo_val(dev, PMIC_OP_GET, &uV); 244 if (ret) 245 return ret; 246 247 return uV; 248} 249 250static int ldo_set_value(struct udevice *dev, int uV) 251{ 252 return lp873x_ldo_val(dev, PMIC_OP_SET, &uV); 253} 254 255static int ldo_get_enable(struct udevice *dev) 256{ 257 bool enable = false; 258 int ret; 259 260 ret = lp873x_ldo_enable(dev, PMIC_OP_GET, &enable); 261 if (ret) 262 return ret; 263 264 return enable; 265} 266 267static int ldo_set_enable(struct udevice *dev, bool enable) 268{ 269 return lp873x_ldo_enable(dev, PMIC_OP_SET, &enable); 270} 271 272static int lp873x_buck_probe(struct udevice *dev) 273{ 274 struct dm_regulator_uclass_plat *uc_pdata; 275 int idx; 276 277 uc_pdata = dev_get_uclass_plat(dev); 278 uc_pdata->type = REGULATOR_TYPE_BUCK; 279 280 idx = dev->driver_data; 281 if (idx >= LP873X_BUCK_NUM) { 282 printf("Wrong ID for regulator\n"); 283 return -1; 284 } 285 286 uc_pdata->ctrl_reg = lp873x_buck_ctrl[idx]; 287 uc_pdata->volt_reg = lp873x_buck_volt[idx]; 288 289 return 0; 290} 291 292static int buck_get_value(struct udevice *dev) 293{ 294 int uV; 295 int ret; 296 297 ret = lp873x_buck_val(dev, PMIC_OP_GET, &uV); 298 if (ret) 299 return ret; 300 301 return uV; 302} 303 304static int buck_set_value(struct udevice *dev, int uV) 305{ 306 return lp873x_buck_val(dev, PMIC_OP_SET, &uV); 307} 308 309static int buck_get_enable(struct udevice *dev) 310{ 311 bool enable = false; 312 int ret; 313 314 315 ret = lp873x_buck_enable(dev, PMIC_OP_GET, &enable); 316 if (ret) 317 return ret; 318 319 return enable; 320} 321 322static int buck_set_enable(struct udevice *dev, bool enable) 323{ 324 return lp873x_buck_enable(dev, PMIC_OP_SET, &enable); 325} 326 327static const struct dm_regulator_ops lp873x_ldo_ops = { 328 .get_value = ldo_get_value, 329 .set_value = ldo_set_value, 330 .get_enable = ldo_get_enable, 331 .set_enable = ldo_set_enable, 332}; 333 334U_BOOT_DRIVER(lp873x_ldo) = { 335 .name = LP873X_LDO_DRIVER, 336 .id = UCLASS_REGULATOR, 337 .ops = &lp873x_ldo_ops, 338 .probe = lp873x_ldo_probe, 339}; 340 341static const struct dm_regulator_ops lp873x_buck_ops = { 342 .get_value = buck_get_value, 343 .set_value = buck_set_value, 344 .get_enable = buck_get_enable, 345 .set_enable = buck_set_enable, 346}; 347 348U_BOOT_DRIVER(lp873x_buck) = { 349 .name = LP873X_BUCK_DRIVER, 350 .id = UCLASS_REGULATOR, 351 .ops = &lp873x_buck_ops, 352 .probe = lp873x_buck_probe, 353}; 354