1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com> 4 */ 5 6#include <dm.h> 7#include <power/pmic.h> 8#include <power/regulator.h> 9#include <power/tps80031.h> 10 11static const char tps80031_smps_reg[][TPS80031_SMPS_NUM] = { 12 { 0x54, 0x5a, 0x66, 0x42, 0x48 }, 13 { 0x56, 0x5c, 0x68, 0x44, 0x4a }, 14 { BIT(3), BIT(4), BIT(6), BIT(0), BIT(1) }, 15}; 16 17static const char tps80031_ldo_reg[][TPS80031_LDO_NUM] = { 18 { 0x9e, 0x86, 0x8e, 0x8a, 0x9a, 0x92, 0xa6, 0x96, 0xa2 }, 19 { 0x9f, 0x87, 0x8f, 0x8b, 0x9b, 0x93, 0xa7, 0x97, 0xa3 }, 20}; 21 22static int tps80031_regulator_enable(struct udevice *dev, int op, bool *enable) 23{ 24 struct dm_regulator_uclass_plat *uc_pdata = 25 dev_get_uclass_plat(dev); 26 u32 adr = uc_pdata->ctrl_reg; 27 int val, ret; 28 29 val = pmic_reg_read(dev->parent, adr); 30 if (val < 0) 31 return val; 32 33 if (op == PMIC_OP_GET) { 34 if (val & REGULATOR_MODE_ON) 35 *enable = true; 36 else 37 *enable = false; 38 39 return 0; 40 } else if (op == PMIC_OP_SET) { 41 val &= ~REGULATOR_STATUS_MASK; 42 43 if (*enable) 44 val |= REGULATOR_MODE_ON; 45 46 ret = pmic_reg_write(dev->parent, adr, val); 47 if (ret) 48 return ret; 49 } 50 51 return 0; 52} 53 54static int tps80031_get_enable(struct udevice *dev) 55{ 56 bool enable = false; 57 int ret; 58 59 ret = tps80031_regulator_enable(dev, PMIC_OP_GET, &enable); 60 if (ret) 61 return ret; 62 63 return enable; 64} 65 66static int tps80031_set_enable(struct udevice *dev, bool enable) 67{ 68 return tps80031_regulator_enable(dev, PMIC_OP_SET, &enable); 69} 70 71/** 72 * tps80031_ldo_volt2hex() - convert voltage in uV into 73 * applicable to register hex value 74 * 75 * @uV: voltage in uV 76 * 77 * Return: voltage in hex on success, -ve on failure 78 */ 79static int tps80031_ldo_volt2hex(int uV) 80{ 81 if (uV > LDO_VOLT_MAX) 82 return -EINVAL; 83 84 if (uV < LDO_VOLT_MIN) 85 uV = LDO_VOLT_MIN; 86 87 return DIV_ROUND_UP(uV - LDO_VOLT_BASE, 102000); 88} 89 90/** 91 * tps80031_ldo_hex2volt() - convert register hex value into 92 * actual voltage in uV 93 * 94 * @hex: hex value of register 95 * 96 * Return: voltage in uV on success, -ve on failure 97 */ 98static int tps80031_ldo_hex2volt(int hex) 99{ 100 if (hex > LDO_VOLT_MAX_HEX) 101 return -EINVAL; 102 103 if (hex < LDO_VOLT_MIN_HEX) 104 hex = LDO_VOLT_MIN_HEX; 105 106 return LDO_VOLT_BASE + hex * 102000; 107} 108 109static int tps80031_ldo_val(struct udevice *dev, int op, int *uV) 110{ 111 struct dm_regulator_uclass_plat *uc_pdata = 112 dev_get_uclass_plat(dev); 113 u32 adr = uc_pdata->volt_reg; 114 int val, hex, ret; 115 116 val = pmic_reg_read(dev->parent, adr); 117 if (val < 0) 118 return val; 119 120 if (op == PMIC_OP_GET) { 121 *uV = 0; 122 123 ret = tps80031_ldo_hex2volt(val & LDO_VOLT_MASK); 124 if (ret < 0) 125 return ret; 126 127 *uV = ret; 128 return 0; 129 } 130 131 hex = tps80031_ldo_volt2hex(*uV); 132 if (hex < 0) 133 return hex; 134 135 val &= ~LDO_VOLT_MASK; 136 137 return pmic_reg_write(dev->parent, adr, val | hex); 138} 139 140static int tps80031_ldo_probe(struct udevice *dev) 141{ 142 struct dm_regulator_uclass_plat *uc_pdata = 143 dev_get_uclass_plat(dev); 144 145 uc_pdata->type = REGULATOR_TYPE_LDO; 146 147 /* check for ldoln and ldousb cases */ 148 if (!strcmp("ldoln", dev->name)) { 149 uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][7]; 150 uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][7]; 151 return 0; 152 } 153 154 if (!strcmp("ldousb", dev->name)) { 155 uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][8]; 156 uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][8]; 157 return 0; 158 } 159 160 if (dev->driver_data > 0) { 161 u8 idx = dev->driver_data - 1; 162 163 uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][idx]; 164 uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][idx]; 165 } 166 167 return 0; 168} 169 170static int ldo_get_value(struct udevice *dev) 171{ 172 int uV; 173 int ret; 174 175 ret = tps80031_ldo_val(dev, PMIC_OP_GET, &uV); 176 if (ret) 177 return ret; 178 179 return uV; 180} 181 182static int ldo_set_value(struct udevice *dev, int uV) 183{ 184 return tps80031_ldo_val(dev, PMIC_OP_SET, &uV); 185} 186 187static const struct dm_regulator_ops tps80031_ldo_ops = { 188 .get_value = ldo_get_value, 189 .set_value = ldo_set_value, 190 .get_enable = tps80031_get_enable, 191 .set_enable = tps80031_set_enable, 192}; 193 194U_BOOT_DRIVER(tps80031_ldo) = { 195 .name = TPS80031_LDO_DRIVER, 196 .id = UCLASS_REGULATOR, 197 .ops = &tps80031_ldo_ops, 198 .probe = tps80031_ldo_probe, 199}; 200 201struct tps80031_smps_priv { 202 int flags; 203}; 204 205/* DCDC voltages for the selector of 0x39 to 0x3F */ 206static int tps80031_dcdc_voltages[5] = { 207 1350000, 1500000, 1800000, 1900000, 2100000 208}; 209 210/** 211 * tps80031_smps_volt2hex() - convert voltage in uV into 212 * applicable to register hex value 213 * 214 * @base: base voltage in uV 215 * @uV: voltage in uV 216 * 217 * Return: voltage in hex on success, -ve on failure 218 */ 219static int tps80031_smps_volt2hex(u32 base, int uV) 220{ 221 int i; 222 223 if (uV < base) 224 return 1; 225 226 if (uV > SMPS_VOLT_LINEAR) { 227 for (i = 0; i < ARRAY_SIZE(tps80031_dcdc_voltages); i++) 228 if (uV <= tps80031_dcdc_voltages[i]) 229 break; 230 231 return SMPS_VOLT_NLINEAR_HEX + i; 232 } 233 234 return DIV_ROUND_UP(uV - base, 12500); 235} 236 237/** 238 * tps80031_smps_hex2volt() - convert register hex value into 239 * actual voltage in uV 240 * 241 * @base: base voltage in uV 242 * @hex: hex value of register 243 * 244 * Return: voltage in uV on success, -ve on failure 245 */ 246static int tps80031_smps_hex2volt(u32 base, int hex) 247{ 248 if (!hex) 249 return 0; 250 251 /* if reg value exceeds linear scale use table */ 252 if (hex > SMPS_VOLT_LINEAR_HEX) 253 return tps80031_dcdc_voltages[hex - SMPS_VOLT_LINEAR_HEX]; 254 else 255 return base + hex * 12500; 256} 257 258static int tps80031_smps_val(struct udevice *dev, int op, int *uV) 259{ 260 struct dm_regulator_uclass_plat *uc_pdata = 261 dev_get_uclass_plat(dev); 262 struct tps80031_smps_priv *priv = dev_get_priv(dev); 263 u32 adr = uc_pdata->volt_reg; 264 int base, val, hex, ret; 265 266 /* If offset flag was set then base voltage is higher */ 267 if (priv->flags & TPS80031_OFFSET_FLAG) 268 base = SMPS_VOLT_BASE_OFFSET; 269 else 270 base = SMPS_VOLT_BASE; 271 272 val = pmic_reg_read(dev->parent, adr); 273 if (val < 0) 274 return val; 275 276 if (op == PMIC_OP_GET) { 277 *uV = 0; 278 279 ret = tps80031_smps_hex2volt(base, val & SMPS_VOLT_MASK); 280 if (ret < 0) 281 return ret; 282 283 *uV = ret; 284 return 0; 285 } 286 287 hex = tps80031_smps_volt2hex(base, *uV); 288 if (hex < 0) 289 return hex; 290 291 val &= ~SMPS_VOLT_MASK; 292 293 return pmic_reg_write(dev->parent, adr, val | hex); 294} 295 296static int tps80031_smps_probe(struct udevice *dev) 297{ 298 struct dm_regulator_uclass_plat *uc_pdata = 299 dev_get_uclass_plat(dev); 300 struct tps80031_smps_priv *priv = dev_get_priv(dev); 301 int idx = dev->driver_data - 1; 302 int val; 303 304 uc_pdata->type = REGULATOR_TYPE_BUCK; 305 306 uc_pdata->ctrl_reg = tps80031_smps_reg[CTRL][idx]; 307 uc_pdata->volt_reg = tps80031_smps_reg[VOLT][idx]; 308 309 /* Determine if smps regulator uses higher voltage */ 310 val = pmic_reg_read(dev->parent, TPS80031_SMPS_OFFSET); 311 if (val & tps80031_smps_reg[OFFSET][idx]) 312 priv->flags |= TPS80031_OFFSET_FLAG; 313 314 return 0; 315} 316 317static int smps_get_value(struct udevice *dev) 318{ 319 int uV; 320 int ret; 321 322 ret = tps80031_smps_val(dev, PMIC_OP_GET, &uV); 323 if (ret) 324 return ret; 325 326 return uV; 327} 328 329static int smps_set_value(struct udevice *dev, int uV) 330{ 331 return tps80031_smps_val(dev, PMIC_OP_SET, &uV); 332} 333 334static const struct dm_regulator_ops tps80031_smps_ops = { 335 .get_value = smps_get_value, 336 .set_value = smps_set_value, 337 .get_enable = tps80031_get_enable, 338 .set_enable = tps80031_set_enable, 339}; 340 341U_BOOT_DRIVER(tps80031_smps) = { 342 .name = TPS80031_SMPS_DRIVER, 343 .id = UCLASS_REGULATOR, 344 .ops = &tps80031_smps_ops, 345 .probe = tps80031_smps_probe, 346 .priv_auto = sizeof(struct tps80031_smps_priv), 347}; 348