1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 Samsung Electronics 4 * Przemyslaw Marczak <p.marczak@samsung.com> 5 */ 6 7 #include <common.h> 8 #include <fdtdec.h> 9 #include <errno.h> 10 #include <dm.h> 11 #include <i2c.h> 12 #include <power/pmic.h> 13 #include <power/regulator.h> 14 #include <power/sandbox_pmic.h> 15 16 #define MODE(_id, _val, _name) [_id] = { \ 17 .id = _id, \ 18 .register_value = _val, \ 19 .name = _name, \ 20 } 21 22 #define RANGE(_min, _max, _step) { \ 23 .min = _min, \ 24 .max = _max, \ 25 .step = _step, \ 26 } 27 28 /* 29 * struct output_range - helper structure type to define the range of output 30 * operating values (current/voltage), limited by the PMIC IC design. 31 * 32 * @min - minimum value 33 * @max - maximum value 34 * @step - step value 35 */ 36 struct output_range { 37 int min; 38 int max; 39 int step; 40 }; 41 42 /* BUCK: 1,2 - voltage range */ 43 static struct output_range buck_voltage_range[] = { 44 RANGE(OUT_BUCK1_UV_MIN, OUT_BUCK1_UV_MAX, OUT_BUCK1_UV_STEP), 45 RANGE(OUT_BUCK2_UV_MIN, OUT_BUCK2_UV_MAX, OUT_BUCK2_UV_STEP), 46 }; 47 48 /* BUCK: 1 - current range */ 49 static struct output_range buck_current_range[] = { 50 RANGE(OUT_BUCK1_UA_MIN, OUT_BUCK1_UA_MAX, OUT_BUCK1_UA_STEP), 51 }; 52 53 /* BUCK operating modes */ 54 static struct dm_regulator_mode sandbox_buck_modes[] = { 55 MODE(BUCK_OM_OFF, OM2REG(BUCK_OM_OFF), "OFF"), 56 MODE(BUCK_OM_ON, OM2REG(BUCK_OM_ON), "ON"), 57 MODE(BUCK_OM_PWM, OM2REG(BUCK_OM_PWM), "PWM"), 58 }; 59 60 /* LDO: 1,2 - voltage range */ 61 static struct output_range ldo_voltage_range[] = { 62 RANGE(OUT_LDO1_UV_MIN, OUT_LDO1_UV_MAX, OUT_LDO1_UV_STEP), 63 RANGE(OUT_LDO2_UV_MIN, OUT_LDO2_UV_MAX, OUT_LDO2_UV_STEP), 64 }; 65 66 /* LDO: 1 - current range */ 67 static struct output_range ldo_current_range[] = { 68 RANGE(OUT_LDO1_UA_MIN, OUT_LDO1_UA_MAX, OUT_LDO1_UA_STEP), 69 }; 70 71 /* LDO operating modes */ 72 static struct dm_regulator_mode sandbox_ldo_modes[] = { 73 MODE(LDO_OM_OFF, OM2REG(LDO_OM_OFF), "OFF"), 74 MODE(LDO_OM_ON, OM2REG(LDO_OM_ON), "ON"), 75 MODE(LDO_OM_SLEEP, OM2REG(LDO_OM_SLEEP), "SLEEP"), 76 MODE(LDO_OM_STANDBY, OM2REG(LDO_OM_STANDBY), "STANDBY"), 77 }; 78 79 int out_get_value(struct udevice *dev, int output_count, int reg_type, 80 struct output_range *range) 81 { 82 uint8_t reg_val; 83 uint reg; 84 int ret; 85 86 if (dev->driver_data > output_count) { 87 pr_err("Unknown regulator number: %lu for PMIC %s!", 88 dev->driver_data, dev->name); 89 return -EINVAL; 90 } 91 92 reg = (dev->driver_data - 1) * OUT_REG_COUNT + reg_type; 93 ret = pmic_read(dev->parent, reg, ®_val, 1); 94 if (ret) { 95 pr_err("PMIC read failed: %d\n", ret); 96 return ret; 97 } 98 99 ret = REG2VAL(range[dev->driver_data - 1].min, 100 range[dev->driver_data - 1].step, 101 reg_val); 102 103 return ret; 104 } 105 106 static int out_set_value(struct udevice *dev, int output_count, int reg_type, 107 struct output_range *range, int value) 108 { 109 uint8_t reg_val; 110 uint reg; 111 int ret; 112 int max_value; 113 114 if (dev->driver_data > output_count) { 115 pr_err("Unknown regulator number: %lu for PMIC %s!", 116 dev->driver_data, dev->name); 117 return -EINVAL; 118 } 119 120 max_value = range[dev->driver_data - 1].max; 121 if (value > max_value) { 122 pr_err("Wrong value for %s: %lu. Max is: %d.", 123 dev->name, dev->driver_data, max_value); 124 return -EINVAL; 125 } 126 127 reg_val = VAL2REG(range[dev->driver_data - 1].min, 128 range[dev->driver_data - 1].step, 129 value); 130 131 reg = (dev->driver_data - 1) * OUT_REG_COUNT + reg_type; 132 ret = pmic_write(dev->parent, reg, ®_val, 1); 133 if (ret) { 134 pr_err("PMIC write failed: %d\n", ret); 135 return ret; 136 } 137 138 return 0; 139 } 140 141 static int out_get_mode(struct udevice *dev) 142 { 143 struct dm_regulator_uclass_platdata *uc_pdata; 144 uint8_t reg_val; 145 uint reg; 146 int ret; 147 int i; 148 149 uc_pdata = dev_get_uclass_platdata(dev); 150 151 reg = (dev->driver_data - 1) * OUT_REG_COUNT + OUT_REG_OM; 152 ret = pmic_read(dev->parent, reg, ®_val, 1); 153 if (ret) { 154 pr_err("PMIC read failed: %d\n", ret); 155 return ret; 156 } 157 158 for (i = 0; i < uc_pdata->mode_count; i++) { 159 if (reg_val == uc_pdata->mode[i].register_value) 160 return uc_pdata->mode[i].id; 161 } 162 163 pr_err("Unknown operation mode for %s!", dev->name); 164 return -EINVAL; 165 } 166 167 static int out_set_mode(struct udevice *dev, int mode) 168 { 169 struct dm_regulator_uclass_platdata *uc_pdata; 170 int reg_val = -1; 171 uint reg; 172 int ret; 173 int i; 174 175 uc_pdata = dev_get_uclass_platdata(dev); 176 177 if (mode >= uc_pdata->mode_count) 178 return -EINVAL; 179 180 for (i = 0; i < uc_pdata->mode_count; i++) { 181 if (mode == uc_pdata->mode[i].id) { 182 reg_val = uc_pdata->mode[i].register_value; 183 break; 184 } 185 } 186 187 if (reg_val == -1) { 188 pr_err("Unknown operation mode for %s!", dev->name); 189 return -EINVAL; 190 } 191 192 reg = (dev->driver_data - 1) * OUT_REG_COUNT + OUT_REG_OM; 193 ret = pmic_write(dev->parent, reg, (uint8_t *)®_val, 1); 194 if (ret) { 195 pr_err("PMIC write failed: %d\n", ret); 196 return ret; 197 } 198 199 return 0; 200 } 201 202 static int buck_get_voltage(struct udevice *dev) 203 { 204 return out_get_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UV, 205 buck_voltage_range); 206 } 207 208 static int buck_set_voltage(struct udevice *dev, int uV) 209 { 210 return out_set_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UV, 211 buck_voltage_range, uV); 212 } 213 214 static int buck_get_current(struct udevice *dev) 215 { 216 /* BUCK2 - unsupported */ 217 if (dev->driver_data == 2) 218 return -ENOSYS; 219 220 return out_get_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UA, 221 buck_current_range); 222 } 223 224 static int buck_set_current(struct udevice *dev, int uA) 225 { 226 /* BUCK2 - unsupported */ 227 if (dev->driver_data == 2) 228 return -ENOSYS; 229 230 return out_set_value(dev, SANDBOX_BUCK_COUNT, OUT_REG_UA, 231 buck_current_range, uA); 232 } 233 234 static int buck_get_enable(struct udevice *dev) 235 { 236 if (out_get_mode(dev) == BUCK_OM_OFF) 237 return false; 238 239 return true; 240 } 241 242 static int buck_set_enable(struct udevice *dev, bool enable) 243 { 244 return out_set_mode(dev, enable ? BUCK_OM_ON : BUCK_OM_OFF); 245 } 246 247 static int sandbox_buck_probe(struct udevice *dev) 248 { 249 struct dm_regulator_uclass_platdata *uc_pdata; 250 251 uc_pdata = dev_get_uclass_platdata(dev); 252 253 uc_pdata->type = REGULATOR_TYPE_BUCK; 254 uc_pdata->mode = sandbox_buck_modes; 255 uc_pdata->mode_count = ARRAY_SIZE(sandbox_buck_modes); 256 257 return 0; 258 } 259 260 static const struct dm_regulator_ops sandbox_buck_ops = { 261 .get_value = buck_get_voltage, 262 .set_value = buck_set_voltage, 263 .get_current = buck_get_current, 264 .set_current = buck_set_current, 265 .get_enable = buck_get_enable, 266 .set_enable = buck_set_enable, 267 .get_mode = out_get_mode, 268 .set_mode = out_set_mode, 269 }; 270 271 U_BOOT_DRIVER(sandbox_buck) = { 272 .name = SANDBOX_BUCK_DRIVER, 273 .id = UCLASS_REGULATOR, 274 .ops = &sandbox_buck_ops, 275 .probe = sandbox_buck_probe, 276 }; 277 278 static int ldo_get_voltage(struct udevice *dev) 279 { 280 return out_get_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UV, 281 ldo_voltage_range); 282 } 283 284 static int ldo_set_voltage(struct udevice *dev, int uV) 285 { 286 return out_set_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UV, 287 ldo_voltage_range, uV); 288 } 289 290 static int ldo_get_current(struct udevice *dev) 291 { 292 /* LDO2 - unsupported */ 293 if (dev->driver_data == 2) 294 return -ENOSYS; 295 296 return out_get_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UA, 297 ldo_current_range); 298 } 299 300 static int ldo_set_current(struct udevice *dev, int uA) 301 { 302 /* LDO2 - unsupported */ 303 if (dev->driver_data == 2) 304 return -ENOSYS; 305 306 return out_set_value(dev, SANDBOX_LDO_COUNT, OUT_REG_UA, 307 ldo_current_range, uA); 308 } 309 310 static int ldo_get_enable(struct udevice *dev) 311 { 312 if (out_get_mode(dev) == LDO_OM_OFF) 313 return false; 314 315 return true; 316 } 317 318 static int ldo_set_enable(struct udevice *dev, bool enable) 319 { 320 return out_set_mode(dev, enable ? LDO_OM_ON : LDO_OM_OFF); 321 } 322 323 static int sandbox_ldo_probe(struct udevice *dev) 324 { 325 struct dm_regulator_uclass_platdata *uc_pdata; 326 327 uc_pdata = dev_get_uclass_platdata(dev); 328 329 uc_pdata->type = REGULATOR_TYPE_LDO; 330 uc_pdata->mode = sandbox_ldo_modes; 331 uc_pdata->mode_count = ARRAY_SIZE(sandbox_ldo_modes); 332 333 return 0; 334 } 335 336 static const struct dm_regulator_ops sandbox_ldo_ops = { 337 .get_value = ldo_get_voltage, 338 .set_value = ldo_set_voltage, 339 .get_current = ldo_get_current, 340 .set_current = ldo_set_current, 341 .get_enable = ldo_get_enable, 342 .set_enable = ldo_set_enable, 343 .get_mode = out_get_mode, 344 .set_mode = out_set_mode, 345 }; 346 347 U_BOOT_DRIVER(sandbox_ldo) = { 348 .name = SANDBOX_LDO_DRIVER, 349 .id = UCLASS_REGULATOR, 350 .ops = &sandbox_ldo_ops, 351 .probe = sandbox_ldo_probe, 352 }; 353