1 /* 2 * Copyright (C) 2015 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * Based on Rockchip's drivers/power/pmic/pmic_rk808.c: 6 * Copyright (C) 2012 rockchips 7 * zyw <zyw@rock-chips.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include <common.h> 13 #include <dm.h> 14 #include <errno.h> 15 #include <power/rk8xx_pmic.h> 16 #include <power/pmic.h> 17 #include <power/regulator.h> 18 19 #ifndef CONFIG_SPL_BUILD 20 #define ENABLE_DRIVER 21 #endif 22 23 /* Field Definitions */ 24 #define RK808_BUCK_VSEL_MASK 0x3f 25 #define RK808_BUCK4_VSEL_MASK 0xf 26 #define RK808_LDO_VSEL_MASK 0x1f 27 28 #define RK818_BUCK_VSEL_MASK 0x3f 29 #define RK818_BUCK4_VSEL_MASK 0x1f 30 #define RK818_LDO_VSEL_MASK 0x1f 31 #define RK818_LDO3_ON_VSEL_MASK 0xf 32 #define RK818_BOOST_ON_VSEL_MASK 0xe0 33 34 struct rk8xx_reg_info { 35 uint min_uv; 36 uint step_uv; 37 s8 vsel_reg; 38 u8 vsel_mask; 39 }; 40 41 static const struct rk8xx_reg_info rk808_buck[] = { 42 { 712500, 12500, REG_BUCK1_ON_VSEL, RK808_BUCK_VSEL_MASK, }, 43 { 712500, 12500, REG_BUCK2_ON_VSEL, RK808_BUCK_VSEL_MASK, }, 44 { 712500, 12500, -1, RK808_BUCK_VSEL_MASK, }, 45 { 1800000, 100000, REG_BUCK4_ON_VSEL, RK808_BUCK4_VSEL_MASK, }, 46 }; 47 48 static const struct rk8xx_reg_info rk808_ldo[] = { 49 { 1800000, 100000, REG_LDO1_ON_VSEL, RK808_LDO_VSEL_MASK, }, 50 { 1800000, 100000, REG_LDO2_ON_VSEL, RK808_LDO_VSEL_MASK, }, 51 { 800000, 100000, REG_LDO3_ON_VSEL, RK808_BUCK4_VSEL_MASK, }, 52 { 1800000, 100000, REG_LDO4_ON_VSEL, RK808_LDO_VSEL_MASK, }, 53 { 1800000, 100000, REG_LDO5_ON_VSEL, RK808_LDO_VSEL_MASK, }, 54 { 800000, 100000, REG_LDO6_ON_VSEL, RK808_LDO_VSEL_MASK, }, 55 { 800000, 100000, REG_LDO7_ON_VSEL, RK808_LDO_VSEL_MASK, }, 56 { 1800000, 100000, REG_LDO8_ON_VSEL, RK808_LDO_VSEL_MASK, }, 57 }; 58 59 static const struct rk8xx_reg_info rk818_buck[] = { 60 { 712500, 12500, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, }, 61 { 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, }, 62 { 712500, 12500, -1, RK818_BUCK_VSEL_MASK, }, 63 { 1800000, 100000, REG_BUCK4_ON_VSEL, RK818_BUCK4_VSEL_MASK, }, 64 }; 65 66 static const struct rk8xx_reg_info rk818_ldo[] = { 67 { 1800000, 100000, REG_LDO1_ON_VSEL, RK818_LDO_VSEL_MASK, }, 68 { 1800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, }, 69 { 800000, 100000, REG_LDO3_ON_VSEL, RK818_LDO3_ON_VSEL_MASK, }, 70 { 1800000, 100000, REG_LDO4_ON_VSEL, RK818_LDO_VSEL_MASK, }, 71 { 1800000, 100000, REG_LDO5_ON_VSEL, RK818_LDO_VSEL_MASK, }, 72 { 800000, 100000, REG_LDO6_ON_VSEL, RK818_LDO_VSEL_MASK, }, 73 { 800000, 100000, REG_LDO7_ON_VSEL, RK818_LDO_VSEL_MASK, }, 74 { 1800000, 100000, REG_LDO8_ON_VSEL, RK818_LDO_VSEL_MASK, }, 75 }; 76 77 static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, 78 int num) 79 { 80 struct rk8xx_priv *priv = dev_get_priv(pmic); 81 switch (priv->variant) { 82 case RK818_ID: 83 return &rk818_buck[num]; 84 default: 85 return &rk808_buck[num]; 86 } 87 } 88 89 static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, 90 int num) 91 { 92 struct rk8xx_priv *priv = dev_get_priv(pmic); 93 switch (priv->variant) { 94 case RK818_ID: 95 return &rk818_ldo[num - 1]; 96 default: 97 return &rk808_ldo[num - 1]; 98 } 99 } 100 101 static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) 102 { 103 const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck - 1); 104 int mask = info->vsel_mask; 105 int val; 106 107 if (info->vsel_reg == -1) 108 return -ENOSYS; 109 val = (uvolt - info->min_uv) / info->step_uv; 110 debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask, 111 val); 112 113 return pmic_clrsetbits(pmic, info->vsel_reg, mask, val); 114 } 115 116 static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) 117 { 118 uint mask; 119 int ret; 120 121 buck--; 122 mask = 1 << buck; 123 if (enable) { 124 ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX, 0, 3 << (buck * 2)); 125 if (ret) 126 return ret; 127 ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0); 128 if (ret) 129 return ret; 130 } 131 132 return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0); 133 } 134 135 #ifdef ENABLE_DRIVER 136 static int buck_get_value(struct udevice *dev) 137 { 138 int buck = dev->driver_data - 1; 139 const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck); 140 int mask = info->vsel_mask; 141 int ret, val; 142 143 if (info->vsel_reg == -1) 144 return -ENOSYS; 145 ret = pmic_reg_read(dev->parent, info->vsel_reg); 146 if (ret < 0) 147 return ret; 148 val = ret & mask; 149 150 return info->min_uv + val * info->step_uv; 151 } 152 153 static int buck_set_value(struct udevice *dev, int uvolt) 154 { 155 int buck = dev->driver_data; 156 157 return _buck_set_value(dev->parent, buck, uvolt); 158 } 159 160 static int buck_set_enable(struct udevice *dev, bool enable) 161 { 162 int buck = dev->driver_data; 163 164 return _buck_set_enable(dev->parent, buck, enable); 165 } 166 167 static bool buck_get_enable(struct udevice *dev) 168 { 169 int buck = dev->driver_data - 1; 170 int ret; 171 uint mask; 172 173 mask = 1 << buck; 174 175 ret = pmic_reg_read(dev->parent, REG_DCDC_EN); 176 if (ret < 0) 177 return ret; 178 179 return ret & mask ? true : false; 180 } 181 182 static int ldo_get_value(struct udevice *dev) 183 { 184 int ldo = dev->driver_data - 1; 185 const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo); 186 int mask = info->vsel_mask; 187 int ret, val; 188 189 if (info->vsel_reg == -1) 190 return -ENOSYS; 191 ret = pmic_reg_read(dev->parent, info->vsel_reg); 192 if (ret < 0) 193 return ret; 194 val = ret & mask; 195 196 return info->min_uv + val * info->step_uv; 197 } 198 199 static int ldo_set_value(struct udevice *dev, int uvolt) 200 { 201 int ldo = dev->driver_data - 1; 202 const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo); 203 int mask = info->vsel_mask; 204 int val; 205 206 if (info->vsel_reg == -1) 207 return -ENOSYS; 208 val = (uvolt - info->min_uv) / info->step_uv; 209 debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask, 210 val); 211 212 return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); 213 } 214 215 static int ldo_set_enable(struct udevice *dev, bool enable) 216 { 217 int ldo = dev->driver_data - 1; 218 uint mask; 219 220 mask = 1 << ldo; 221 222 return pmic_clrsetbits(dev->parent, REG_LDO_EN, mask, 223 enable ? mask : 0); 224 } 225 226 static bool ldo_get_enable(struct udevice *dev) 227 { 228 int ldo = dev->driver_data - 1; 229 int ret; 230 uint mask; 231 232 mask = 1 << ldo; 233 234 ret = pmic_reg_read(dev->parent, REG_LDO_EN); 235 if (ret < 0) 236 return ret; 237 238 return ret & mask ? true : false; 239 } 240 241 static int switch_set_enable(struct udevice *dev, bool enable) 242 { 243 int sw = dev->driver_data - 1; 244 uint mask; 245 246 mask = 1 << (sw + 5); 247 248 return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask, 249 enable ? mask : 0); 250 } 251 252 static bool switch_get_enable(struct udevice *dev) 253 { 254 int sw = dev->driver_data - 1; 255 int ret; 256 uint mask; 257 258 mask = 1 << (sw + 5); 259 260 ret = pmic_reg_read(dev->parent, REG_DCDC_EN); 261 if (ret < 0) 262 return ret; 263 264 return ret & mask ? true : false; 265 } 266 267 static int rk8xx_buck_probe(struct udevice *dev) 268 { 269 struct dm_regulator_uclass_platdata *uc_pdata; 270 271 uc_pdata = dev_get_uclass_platdata(dev); 272 273 uc_pdata->type = REGULATOR_TYPE_BUCK; 274 uc_pdata->mode_count = 0; 275 276 return 0; 277 } 278 279 static int rk8xx_ldo_probe(struct udevice *dev) 280 { 281 struct dm_regulator_uclass_platdata *uc_pdata; 282 283 uc_pdata = dev_get_uclass_platdata(dev); 284 285 uc_pdata->type = REGULATOR_TYPE_LDO; 286 uc_pdata->mode_count = 0; 287 288 return 0; 289 } 290 291 static int rk8xx_switch_probe(struct udevice *dev) 292 { 293 struct dm_regulator_uclass_platdata *uc_pdata; 294 295 uc_pdata = dev_get_uclass_platdata(dev); 296 297 uc_pdata->type = REGULATOR_TYPE_FIXED; 298 uc_pdata->mode_count = 0; 299 300 return 0; 301 } 302 303 static const struct dm_regulator_ops rk8xx_buck_ops = { 304 .get_value = buck_get_value, 305 .set_value = buck_set_value, 306 .get_enable = buck_get_enable, 307 .set_enable = buck_set_enable, 308 }; 309 310 static const struct dm_regulator_ops rk8xx_ldo_ops = { 311 .get_value = ldo_get_value, 312 .set_value = ldo_set_value, 313 .get_enable = ldo_get_enable, 314 .set_enable = ldo_set_enable, 315 }; 316 317 static const struct dm_regulator_ops rk8xx_switch_ops = { 318 .get_enable = switch_get_enable, 319 .set_enable = switch_set_enable, 320 }; 321 322 U_BOOT_DRIVER(rk8xx_buck) = { 323 .name = "rk8xx_buck", 324 .id = UCLASS_REGULATOR, 325 .ops = &rk8xx_buck_ops, 326 .probe = rk8xx_buck_probe, 327 }; 328 329 U_BOOT_DRIVER(rk8xx_ldo) = { 330 .name = "rk8xx_ldo", 331 .id = UCLASS_REGULATOR, 332 .ops = &rk8xx_ldo_ops, 333 .probe = rk8xx_ldo_probe, 334 }; 335 336 U_BOOT_DRIVER(rk8xx_switch) = { 337 .name = "rk8xx_switch", 338 .id = UCLASS_REGULATOR, 339 .ops = &rk8xx_switch_ops, 340 .probe = rk8xx_switch_probe, 341 }; 342 #endif 343 344 int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt) 345 { 346 int ret; 347 348 ret = _buck_set_value(pmic, buck, uvolt); 349 if (ret) 350 return ret; 351 352 return _buck_set_enable(pmic, buck, true); 353 } 354