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