1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 Google, Inc 4 */ 5 6 #include <common.h> 7 #include <fdtdec.h> 8 #include <errno.h> 9 #include <dm.h> 10 #include <i2c.h> 11 #include <power/pmic.h> 12 #include <power/regulator.h> 13 #include <power/s5m8767.h> 14 15 static const struct sec_voltage_desc buck_v1 = { 16 .max = 2225000, 17 .min = 650000, 18 .step = 6250, 19 }; 20 21 static const struct sec_voltage_desc buck_v2 = { 22 .max = 1600000, 23 .min = 600000, 24 .step = 6250, 25 }; 26 27 static const struct sec_voltage_desc buck_v3 = { 28 .max = 3000000, 29 .min = 750000, 30 .step = 12500, 31 }; 32 33 static const struct sec_voltage_desc ldo_v1 = { 34 .max = 3950000, 35 .min = 800000, 36 .step = 50000, 37 }; 38 39 static const struct sec_voltage_desc ldo_v2 = { 40 .max = 2375000, 41 .min = 800000, 42 .step = 25000, 43 }; 44 45 static const struct s5m8767_para buck_param[] = { 46 /* 47 * | voltage ----| | enable -| voltage 48 * regnum addr bpos mask addr on desc 49 */ 50 {S5M8767_BUCK1, 0x33, 0x0, 0xff, 0x32, 0x3, &buck_v1}, 51 {S5M8767_BUCK2, 0x35, 0x0, 0xff, 0x34, 0x1, &buck_v2}, 52 {S5M8767_BUCK3, 0x3e, 0x0, 0xff, 0x3d, 0x1, &buck_v2}, 53 {S5M8767_BUCK4, 0x47, 0x0, 0xff, 0x46, 0x1, &buck_v2}, 54 {S5M8767_BUCK5, 0x50, 0x0, 0xff, 0x4f, 0x3, &buck_v1}, 55 {S5M8767_BUCK6, 0x55, 0x0, 0xff, 0x54, 0x3, &buck_v1}, 56 {S5M8767_BUCK7, 0x57, 0x0, 0xff, 0x56, 0x3, &buck_v3}, 57 {S5M8767_BUCK8, 0x59, 0x0, 0xff, 0x58, 0x3, &buck_v3}, 58 {S5M8767_BUCK9, 0x5b, 0x0, 0xff, 0x5a, 0x3, &buck_v3}, 59 }; 60 61 static const struct s5m8767_para ldo_param[] = { 62 {S5M8767_LDO1, 0x5c, 0x0, 0x3f, 0x5c, 0x3, &ldo_v2}, 63 {S5M8767_LDO2, 0x5d, 0x0, 0x3f, 0x5d, 0x1, &ldo_v2}, 64 {S5M8767_LDO3, 0x61, 0x0, 0x3f, 0x61, 0x3, &ldo_v1}, 65 {S5M8767_LDO4, 0x62, 0x0, 0x3f, 0x62, 0x3, &ldo_v1}, 66 {S5M8767_LDO5, 0x63, 0x0, 0x3f, 0x63, 0x3, &ldo_v1}, 67 {S5M8767_LDO6, 0x64, 0x0, 0x3f, 0x64, 0x1, &ldo_v2}, 68 {S5M8767_LDO7, 0x65, 0x0, 0x3f, 0x65, 0x1, &ldo_v2}, 69 {S5M8767_LDO8, 0x66, 0x0, 0x3f, 0x66, 0x1, &ldo_v2}, 70 {S5M8767_LDO9, 0x67, 0x0, 0x3f, 0x67, 0x3, &ldo_v1}, 71 {S5M8767_LDO10, 0x68, 0x0, 0x3f, 0x68, 0x1, &ldo_v1}, 72 {S5M8767_LDO11, 0x69, 0x0, 0x3f, 0x69, 0x1, &ldo_v1}, 73 {S5M8767_LDO12, 0x6a, 0x0, 0x3f, 0x6a, 0x1, &ldo_v1}, 74 {S5M8767_LDO13, 0x6b, 0x0, 0x3f, 0x6b, 0x3, &ldo_v1}, 75 {S5M8767_LDO14, 0x6c, 0x0, 0x3f, 0x6c, 0x1, &ldo_v1}, 76 {S5M8767_LDO15, 0x6d, 0x0, 0x3f, 0x6d, 0x1, &ldo_v2}, 77 {S5M8767_LDO16, 0x6e, 0x0, 0x3f, 0x6e, 0x1, &ldo_v1}, 78 {S5M8767_LDO17, 0x6f, 0x0, 0x3f, 0x6f, 0x3, &ldo_v1}, 79 {S5M8767_LDO18, 0x70, 0x0, 0x3f, 0x70, 0x3, &ldo_v1}, 80 {S5M8767_LDO19, 0x71, 0x0, 0x3f, 0x71, 0x3, &ldo_v1}, 81 {S5M8767_LDO20, 0x72, 0x0, 0x3f, 0x72, 0x3, &ldo_v1}, 82 {S5M8767_LDO21, 0x73, 0x0, 0x3f, 0x73, 0x3, &ldo_v1}, 83 {S5M8767_LDO22, 0x74, 0x0, 0x3f, 0x74, 0x3, &ldo_v1}, 84 {S5M8767_LDO23, 0x75, 0x0, 0x3f, 0x75, 0x3, &ldo_v1}, 85 {S5M8767_LDO24, 0x76, 0x0, 0x3f, 0x76, 0x3, &ldo_v1}, 86 {S5M8767_LDO25, 0x77, 0x0, 0x3f, 0x77, 0x3, &ldo_v1}, 87 {S5M8767_LDO26, 0x78, 0x0, 0x3f, 0x78, 0x3, &ldo_v1}, 88 {S5M8767_LDO27, 0x79, 0x0, 0x3f, 0x79, 0x3, &ldo_v1}, 89 {S5M8767_LDO28, 0x7a, 0x0, 0x3f, 0x7a, 0x3, &ldo_v1}, 90 }; 91 92 enum { 93 ENABLE_SHIFT = 6, 94 ENABLE_MASK = 3, 95 }; 96 97 static int reg_get_value(struct udevice *dev, const struct s5m8767_para *param) 98 { 99 const struct sec_voltage_desc *desc; 100 int ret, uv, val; 101 102 ret = pmic_reg_read(dev->parent, param->vol_addr); 103 if (ret < 0) 104 return ret; 105 106 desc = param->vol; 107 val = (ret >> param->vol_bitpos) & param->vol_bitmask; 108 uv = desc->min + val * desc->step; 109 110 return uv; 111 } 112 113 static int reg_set_value(struct udevice *dev, const struct s5m8767_para *param, 114 int uv) 115 { 116 const struct sec_voltage_desc *desc; 117 int ret, val; 118 119 desc = param->vol; 120 if (uv < desc->min || uv > desc->max) 121 return -EINVAL; 122 val = (uv - desc->min) / desc->step; 123 val = (val & param->vol_bitmask) << param->vol_bitpos; 124 ret = pmic_clrsetbits(dev->parent, param->vol_addr, 125 param->vol_bitmask << param->vol_bitpos, 126 val); 127 128 return ret; 129 } 130 131 static int s5m8767_ldo_probe(struct udevice *dev) 132 { 133 struct dm_regulator_uclass_platdata *uc_pdata; 134 135 uc_pdata = dev_get_uclass_platdata(dev); 136 137 uc_pdata->type = REGULATOR_TYPE_LDO; 138 uc_pdata->mode_count = 0; 139 140 return 0; 141 } 142 static int ldo_get_value(struct udevice *dev) 143 { 144 int ldo = dev->driver_data; 145 146 return reg_get_value(dev, &ldo_param[ldo]); 147 } 148 149 static int ldo_set_value(struct udevice *dev, int uv) 150 { 151 int ldo = dev->driver_data; 152 153 return reg_set_value(dev, &ldo_param[ldo], uv); 154 } 155 156 static int reg_get_enable(struct udevice *dev, const struct s5m8767_para *param) 157 { 158 bool enable; 159 int ret; 160 161 ret = pmic_reg_read(dev->parent, param->reg_enaddr); 162 if (ret < 0) 163 return ret; 164 165 enable = (ret >> ENABLE_SHIFT) & ENABLE_MASK; 166 167 return enable; 168 } 169 170 static int reg_set_enable(struct udevice *dev, const struct s5m8767_para *param, 171 bool enable) 172 { 173 int ret; 174 175 ret = pmic_reg_read(dev->parent, param->reg_enaddr); 176 if (ret < 0) 177 return ret; 178 179 ret = pmic_clrsetbits(dev->parent, param->reg_enaddr, 180 ENABLE_MASK << ENABLE_SHIFT, 181 enable ? param->reg_enbiton << ENABLE_SHIFT : 0); 182 183 return ret; 184 } 185 186 static int ldo_get_enable(struct udevice *dev) 187 { 188 int ldo = dev->driver_data; 189 190 return reg_get_enable(dev, &ldo_param[ldo]); 191 } 192 193 static int ldo_set_enable(struct udevice *dev, bool enable) 194 { 195 int ldo = dev->driver_data; 196 197 return reg_set_enable(dev, &ldo_param[ldo], enable); 198 } 199 200 static int s5m8767_buck_probe(struct udevice *dev) 201 { 202 struct dm_regulator_uclass_platdata *uc_pdata; 203 204 uc_pdata = dev_get_uclass_platdata(dev); 205 206 uc_pdata->type = REGULATOR_TYPE_BUCK; 207 uc_pdata->mode_count = 0; 208 209 return 0; 210 } 211 212 static int buck_get_value(struct udevice *dev) 213 { 214 int buck = dev->driver_data; 215 216 return reg_get_value(dev, &buck_param[buck]); 217 } 218 219 static int buck_set_value(struct udevice *dev, int uv) 220 { 221 int buck = dev->driver_data; 222 223 return reg_set_value(dev, &buck_param[buck], uv); 224 } 225 226 static int buck_get_enable(struct udevice *dev) 227 { 228 int buck = dev->driver_data; 229 230 return reg_get_enable(dev, &buck_param[buck]); 231 } 232 233 static int buck_set_enable(struct udevice *dev, bool enable) 234 { 235 int buck = dev->driver_data; 236 237 return reg_set_enable(dev, &buck_param[buck], enable); 238 } 239 240 static const struct dm_regulator_ops s5m8767_ldo_ops = { 241 .get_value = ldo_get_value, 242 .set_value = ldo_set_value, 243 .get_enable = ldo_get_enable, 244 .set_enable = ldo_set_enable, 245 }; 246 247 U_BOOT_DRIVER(s5m8767_ldo) = { 248 .name = S5M8767_LDO_DRIVER, 249 .id = UCLASS_REGULATOR, 250 .ops = &s5m8767_ldo_ops, 251 .probe = s5m8767_ldo_probe, 252 }; 253 254 static const struct dm_regulator_ops s5m8767_buck_ops = { 255 .get_value = buck_get_value, 256 .set_value = buck_set_value, 257 .get_enable = buck_get_enable, 258 .set_enable = buck_set_enable, 259 }; 260 261 U_BOOT_DRIVER(s5m8767_buck) = { 262 .name = S5M8767_BUCK_DRIVER, 263 .id = UCLASS_REGULATOR, 264 .ops = &s5m8767_buck_ops, 265 .probe = s5m8767_buck_probe, 266 }; 267