Blame view
drivers/regulator/mc13892-regulator.c
20.1 KB
0f5683990
|
1 2 3 4 5 6 7 |
// SPDX-License-Identifier: GPL-2.0 // // Regulator Driver for Freescale MC13892 PMIC // // Copyright 2010 Yong Shen <yong.shen@linaro.org> // // Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org> |
5e428d5ce
|
8 9 10 11 12 13 14 15 16 |
#include <linux/mfd/mc13892.h> #include <linux/regulator/machine.h> #include <linux/regulator/driver.h> #include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/err.h> |
65602c32e
|
17 |
#include <linux/module.h> |
5e428d5ce
|
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
#include "mc13xxx.h" #define MC13892_REVISION 7 #define MC13892_POWERCTL0 13 #define MC13892_POWERCTL0_USEROFFSPI 3 #define MC13892_POWERCTL0_VCOINCELLVSEL 20 #define MC13892_POWERCTL0_VCOINCELLVSEL_M (7<<20) #define MC13892_POWERCTL0_VCOINCELLEN (1<<23) #define MC13892_SWITCHERS0_SWxHI (1<<23) #define MC13892_SWITCHERS0 24 #define MC13892_SWITCHERS0_SW1VSEL 0 #define MC13892_SWITCHERS0_SW1VSEL_M (0x1f<<0) #define MC13892_SWITCHERS0_SW1HI (1<<23) #define MC13892_SWITCHERS0_SW1EN 0 #define MC13892_SWITCHERS1 25 #define MC13892_SWITCHERS1_SW2VSEL 0 #define MC13892_SWITCHERS1_SW2VSEL_M (0x1f<<0) #define MC13892_SWITCHERS1_SW2HI (1<<23) #define MC13892_SWITCHERS1_SW2EN 0 #define MC13892_SWITCHERS2 26 #define MC13892_SWITCHERS2_SW3VSEL 0 #define MC13892_SWITCHERS2_SW3VSEL_M (0x1f<<0) #define MC13892_SWITCHERS2_SW3HI (1<<23) #define MC13892_SWITCHERS2_SW3EN 0 #define MC13892_SWITCHERS3 27 #define MC13892_SWITCHERS3_SW4VSEL 0 #define MC13892_SWITCHERS3_SW4VSEL_M (0x1f<<0) #define MC13892_SWITCHERS3_SW4HI (1<<23) #define MC13892_SWITCHERS3_SW4EN 0 #define MC13892_SWITCHERS4 28 #define MC13892_SWITCHERS4_SW1MODE 0 #define MC13892_SWITCHERS4_SW1MODE_AUTO (8<<0) #define MC13892_SWITCHERS4_SW1MODE_M (0xf<<0) #define MC13892_SWITCHERS4_SW2MODE 10 #define MC13892_SWITCHERS4_SW2MODE_AUTO (8<<10) #define MC13892_SWITCHERS4_SW2MODE_M (0xf<<10) #define MC13892_SWITCHERS5 29 #define MC13892_SWITCHERS5_SW3MODE 0 #define MC13892_SWITCHERS5_SW3MODE_AUTO (8<<0) #define MC13892_SWITCHERS5_SW3MODE_M (0xf<<0) #define MC13892_SWITCHERS5_SW4MODE 8 #define MC13892_SWITCHERS5_SW4MODE_AUTO (8<<8) #define MC13892_SWITCHERS5_SW4MODE_M (0xf<<8) #define MC13892_SWITCHERS5_SWBSTEN (1<<20) #define MC13892_REGULATORSETTING0 30 #define MC13892_REGULATORSETTING0_VGEN1VSEL 0 #define MC13892_REGULATORSETTING0_VDIGVSEL 4 #define MC13892_REGULATORSETTING0_VGEN2VSEL 6 #define MC13892_REGULATORSETTING0_VPLLVSEL 9 #define MC13892_REGULATORSETTING0_VUSB2VSEL 11 #define MC13892_REGULATORSETTING0_VGEN3VSEL 14 #define MC13892_REGULATORSETTING0_VCAMVSEL 16 #define MC13892_REGULATORSETTING0_VGEN1VSEL_M (3<<0) #define MC13892_REGULATORSETTING0_VDIGVSEL_M (3<<4) #define MC13892_REGULATORSETTING0_VGEN2VSEL_M (7<<6) #define MC13892_REGULATORSETTING0_VPLLVSEL_M (3<<9) #define MC13892_REGULATORSETTING0_VUSB2VSEL_M (3<<11) #define MC13892_REGULATORSETTING0_VGEN3VSEL_M (1<<14) #define MC13892_REGULATORSETTING0_VCAMVSEL_M (3<<16) #define MC13892_REGULATORSETTING1 31 #define MC13892_REGULATORSETTING1_VVIDEOVSEL 2 #define MC13892_REGULATORSETTING1_VAUDIOVSEL 4 #define MC13892_REGULATORSETTING1_VSDVSEL 6 #define MC13892_REGULATORSETTING1_VVIDEOVSEL_M (3<<2) #define MC13892_REGULATORSETTING1_VAUDIOVSEL_M (3<<4) #define MC13892_REGULATORSETTING1_VSDVSEL_M (7<<6) #define MC13892_REGULATORMODE0 32 #define MC13892_REGULATORMODE0_VGEN1EN (1<<0) #define MC13892_REGULATORMODE0_VGEN1STDBY (1<<1) #define MC13892_REGULATORMODE0_VGEN1MODE (1<<2) #define MC13892_REGULATORMODE0_VIOHIEN (1<<3) #define MC13892_REGULATORMODE0_VIOHISTDBY (1<<4) #define MC13892_REGULATORMODE0_VIOHIMODE (1<<5) #define MC13892_REGULATORMODE0_VDIGEN (1<<9) #define MC13892_REGULATORMODE0_VDIGSTDBY (1<<10) #define MC13892_REGULATORMODE0_VDIGMODE (1<<11) #define MC13892_REGULATORMODE0_VGEN2EN (1<<12) #define MC13892_REGULATORMODE0_VGEN2STDBY (1<<13) #define MC13892_REGULATORMODE0_VGEN2MODE (1<<14) #define MC13892_REGULATORMODE0_VPLLEN (1<<15) #define MC13892_REGULATORMODE0_VPLLSTDBY (1<<16) #define MC13892_REGULATORMODE0_VPLLMODE (1<<17) #define MC13892_REGULATORMODE0_VUSB2EN (1<<18) #define MC13892_REGULATORMODE0_VUSB2STDBY (1<<19) #define MC13892_REGULATORMODE0_VUSB2MODE (1<<20) #define MC13892_REGULATORMODE1 33 #define MC13892_REGULATORMODE1_VGEN3EN (1<<0) #define MC13892_REGULATORMODE1_VGEN3STDBY (1<<1) #define MC13892_REGULATORMODE1_VGEN3MODE (1<<2) #define MC13892_REGULATORMODE1_VCAMEN (1<<6) #define MC13892_REGULATORMODE1_VCAMSTDBY (1<<7) #define MC13892_REGULATORMODE1_VCAMMODE (1<<8) #define MC13892_REGULATORMODE1_VCAMCONFIGEN (1<<9) #define MC13892_REGULATORMODE1_VVIDEOEN (1<<12) #define MC13892_REGULATORMODE1_VVIDEOSTDBY (1<<13) #define MC13892_REGULATORMODE1_VVIDEOMODE (1<<14) #define MC13892_REGULATORMODE1_VAUDIOEN (1<<15) #define MC13892_REGULATORMODE1_VAUDIOSTDBY (1<<16) #define MC13892_REGULATORMODE1_VAUDIOMODE (1<<17) #define MC13892_REGULATORMODE1_VSDEN (1<<18) #define MC13892_REGULATORMODE1_VSDSTDBY (1<<19) #define MC13892_REGULATORMODE1_VSDMODE (1<<20) #define MC13892_POWERMISC 34 #define MC13892_POWERMISC_GPO1EN (1<<6) #define MC13892_POWERMISC_GPO2EN (1<<8) #define MC13892_POWERMISC_GPO3EN (1<<10) #define MC13892_POWERMISC_GPO4EN (1<<12) #define MC13892_POWERMISC_PWGT1SPIEN (1<<15) #define MC13892_POWERMISC_PWGT2SPIEN (1<<16) #define MC13892_POWERMISC_GPO4ADINEN (1<<21) #define MC13892_POWERMISC_PWGTSPI_M (3 << 15) #define MC13892_USB1 50 #define MC13892_USB1_VUSBEN (1<<3) |
34e74f39f
|
148 |
static const unsigned int mc13892_vcoincell[] = { |
5e428d5ce
|
149 150 151 |
2500000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, }; |
34e74f39f
|
152 |
static const unsigned int mc13892_sw1[] = { |
5e428d5ce
|
153 154 155 156 157 158 159 |
600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000 }; |
ccf3ed782
|
160 161 162 163 164 165 166 |
/* * Note: this table is used to derive SWxVSEL by index into * the array. Offset the values by the index of 1100000uV * to get the actual register value for that voltage selector * if the HI bit is to be set as well. */ #define MC13892_SWxHI_SEL_OFFSET 20 |
34e74f39f
|
167 |
static const unsigned int mc13892_sw[] = { |
5e428d5ce
|
168 169 170 171 172 173 174 175 176 177 |
600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000, 1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000 }; |
34e74f39f
|
178 |
static const unsigned int mc13892_swbst[] = { |
5e428d5ce
|
179 180 |
5000000, }; |
34e74f39f
|
181 |
static const unsigned int mc13892_viohi[] = { |
5e428d5ce
|
182 183 |
2775000, }; |
34e74f39f
|
184 |
static const unsigned int mc13892_vpll[] = { |
5e428d5ce
|
185 186 |
1050000, 1250000, 1650000, 1800000, }; |
34e74f39f
|
187 |
static const unsigned int mc13892_vdig[] = { |
5e428d5ce
|
188 189 |
1050000, 1250000, 1650000, 1800000, }; |
34e74f39f
|
190 |
static const unsigned int mc13892_vsd[] = { |
5e428d5ce
|
191 192 193 |
1800000, 2000000, 2600000, 2700000, 2800000, 2900000, 3000000, 3150000, }; |
34e74f39f
|
194 |
static const unsigned int mc13892_vusb2[] = { |
5e428d5ce
|
195 196 |
2400000, 2600000, 2700000, 2775000, }; |
34e74f39f
|
197 |
static const unsigned int mc13892_vvideo[] = { |
5e428d5ce
|
198 199 |
2700000, 2775000, 2500000, 2600000, }; |
34e74f39f
|
200 |
static const unsigned int mc13892_vaudio[] = { |
5e428d5ce
|
201 202 |
2300000, 2500000, 2775000, 3000000, }; |
34e74f39f
|
203 |
static const unsigned int mc13892_vcam[] = { |
5e428d5ce
|
204 205 |
2500000, 2600000, 2750000, 3000000, }; |
34e74f39f
|
206 |
static const unsigned int mc13892_vgen1[] = { |
5e428d5ce
|
207 208 |
1200000, 1500000, 2775000, 3150000, }; |
34e74f39f
|
209 |
static const unsigned int mc13892_vgen2[] = { |
5e428d5ce
|
210 211 212 |
1200000, 1500000, 1600000, 1800000, 2700000, 2800000, 3000000, 3150000, }; |
34e74f39f
|
213 |
static const unsigned int mc13892_vgen3[] = { |
5e428d5ce
|
214 215 |
1800000, 2900000, }; |
34e74f39f
|
216 |
static const unsigned int mc13892_vusb[] = { |
5e428d5ce
|
217 218 |
3300000, }; |
34e74f39f
|
219 |
static const unsigned int mc13892_gpo[] = { |
5e428d5ce
|
220 221 |
2750000, }; |
34e74f39f
|
222 |
static const unsigned int mc13892_pwgtdrv[] = { |
5e428d5ce
|
223 224 |
5000000, }; |
e5680c4de
|
225 226 |
static const struct regulator_ops mc13892_gpo_regulator_ops; static const struct regulator_ops mc13892_sw_regulator_ops; |
5e428d5ce
|
227 |
|
ec520911e
|
228 229 |
#define MC13892_FIXED_DEFINE(name, node, reg, voltages) \ MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages, \ |
5e428d5ce
|
230 |
mc13xxx_fixed_regulator_ops) |
ec520911e
|
231 232 |
#define MC13892_GPO_DEFINE(name, node, reg, voltages) \ MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages, \ |
5e428d5ce
|
233 |
mc13892_gpo_regulator_ops) |
ec520911e
|
234 235 |
#define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages) \ MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ |
5e428d5ce
|
236 |
mc13892_sw_regulator_ops) |
ec520911e
|
237 238 |
#define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages) \ MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ |
5e428d5ce
|
239 240 241 |
mc13xxx_regulator_ops) static struct mc13xxx_regulator mc13892_regulators[] = { |
ec520911e
|
242 243 244 245 246 247 248 249 |
MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell), MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1), MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw), MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw), MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw), MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst), MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi), MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0, |
5e428d5ce
|
250 |
mc13892_vpll), |
ec520911e
|
251 |
MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0, |
5e428d5ce
|
252 |
mc13892_vdig), |
ec520911e
|
253 |
MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1, |
5e428d5ce
|
254 |
mc13892_vsd), |
ec520911e
|
255 |
MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0, |
5e428d5ce
|
256 |
mc13892_vusb2), |
ec520911e
|
257 |
MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1, |
5e428d5ce
|
258 |
mc13892_vvideo), |
ec520911e
|
259 |
MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1, |
5e428d5ce
|
260 |
mc13892_vaudio), |
ec520911e
|
261 |
MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0, |
5e428d5ce
|
262 |
mc13892_vcam), |
ec520911e
|
263 |
MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0, |
5e428d5ce
|
264 |
mc13892_vgen1), |
ec520911e
|
265 |
MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0, |
5e428d5ce
|
266 |
mc13892_vgen2), |
ec520911e
|
267 |
MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0, |
5e428d5ce
|
268 |
mc13892_vgen3), |
ec520911e
|
269 270 271 272 273 274 275 |
MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb), MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo), MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo), MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo), MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo), MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv), MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv), |
5e428d5ce
|
276 |
}; |
27315cf61
|
277 278 |
static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, u32 val) |
5e428d5ce
|
279 280 281 282 283 284 |
{ struct mc13xxx *mc13892 = priv->mc13xxx; int ret; u32 valread; BUG_ON(val & ~mask); |
825d10591
|
285 |
mc13xxx_lock(priv->mc13xxx); |
5e428d5ce
|
286 287 |
ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread); if (ret) |
825d10591
|
288 |
goto out; |
5e428d5ce
|
289 290 291 292 293 294 295 296 297 298 299 |
/* Update the stored state for Power Gates. */ priv->powermisc_pwgt_state = (priv->powermisc_pwgt_state & ~mask) | val; priv->powermisc_pwgt_state &= MC13892_POWERMISC_PWGTSPI_M; /* Construct the new register value */ valread = (valread & ~mask) | val; /* Overwrite the PWGTxEN with the stored version */ valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) | priv->powermisc_pwgt_state; |
825d10591
|
300 301 302 303 |
ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); out: mc13xxx_unlock(priv->mc13xxx); return ret; |
5e428d5ce
|
304 305 306 307 308 309 |
} static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); |
5e428d5ce
|
310 311 312 313 314 315 316 317 318 319 320 321 |
u32 en_val = mc13892_regulators[id].enable_bit; u32 mask = mc13892_regulators[id].enable_bit; dev_dbg(rdev_get_dev(rdev), "%s id: %d ", __func__, id); /* Power Gate enable value is 0 */ if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) en_val = 0; if (id == MC13892_GPO4) mask |= MC13892_POWERMISC_GPO4ADINEN; |
825d10591
|
322 |
return mc13892_powermisc_rmw(priv, mask, en_val); |
5e428d5ce
|
323 324 325 326 327 328 |
} static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); |
5e428d5ce
|
329 330 331 332 333 334 335 336 |
u32 dis_val = 0; dev_dbg(rdev_get_dev(rdev), "%s id: %d ", __func__, id); /* Power Gate disable value is 1 */ if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) dis_val = mc13892_regulators[id].enable_bit; |
825d10591
|
337 |
return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, |
5e428d5ce
|
338 |
dis_val); |
5e428d5ce
|
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
} static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); unsigned int val; mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); mc13xxx_unlock(priv->mc13xxx); if (ret) return ret; /* Power Gates state is stored in powermisc_pwgt_state * where the meaning of bits is negated */ val = (val & ~MC13892_POWERMISC_PWGTSPI_M) | (priv->powermisc_pwgt_state ^ MC13892_POWERMISC_PWGTSPI_M); return (val & mc13892_regulators[id].enable_bit) != 0; } |
e5680c4de
|
361 |
static const struct regulator_ops mc13892_gpo_regulator_ops = { |
5e428d5ce
|
362 363 364 |
.enable = mc13892_gpo_regulator_enable, .disable = mc13892_gpo_regulator_disable, .is_enabled = mc13892_gpo_regulator_is_enabled, |
34e74f39f
|
365 |
.list_voltage = regulator_list_voltage_table, |
5e428d5ce
|
366 |
.set_voltage = mc13xxx_fixed_regulator_set_voltage, |
5e428d5ce
|
367 |
}; |
f1dcf9e4e
|
368 |
static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) |
5e428d5ce
|
369 370 371 |
{ struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); |
ccf3ed782
|
372 |
unsigned int val, selector; |
5e428d5ce
|
373 374 375 376 377 378 379 380 381 382 |
dev_dbg(rdev_get_dev(rdev), "%s id: %d ", __func__, id); mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].vsel_reg, &val); mc13xxx_unlock(priv->mc13xxx); if (ret) return ret; |
ccf3ed782
|
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
/* * Figure out if the HI bit is set inside the switcher mode register * since this means the selector value we return is at a different * offset into the selector table. * * According to the MC13892 documentation note 59 (Table 47) the SW1 * buck switcher does not support output range programming therefore * the HI bit must always remain 0. So do not do anything strange if * our register is MC13892_SWITCHERS0. */ selector = val & mc13892_regulators[id].vsel_mask; if ((mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) && (val & MC13892_SWITCHERS0_SWxHI)) { selector += MC13892_SWxHI_SEL_OFFSET; } |
5e428d5ce
|
400 |
|
ccf3ed782
|
401 402 403 |
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: 0x%08x selector: %d ", __func__, id, val, selector); |
5e428d5ce
|
404 |
|
ccf3ed782
|
405 |
return selector; |
5e428d5ce
|
406 |
} |
939b62d89
|
407 408 |
static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) |
5e428d5ce
|
409 410 |
{ struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); |
8db98440f
|
411 412 |
int volt, mask, id = rdev_get_id(rdev); u32 reg_value; |
5e428d5ce
|
413 |
int ret; |
8db98440f
|
414 415 |
volt = rdev->desc->volt_table[selector]; mask = mc13892_regulators[id].vsel_mask; |
ccf3ed782
|
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
reg_value = selector; /* * Don't mess with the HI bit or support HI voltage offsets for SW1. * * Since the get_voltage_sel callback has given a fudged value for * the selector offset, we need to back out that offset if HI is * to be set so we write the correct value to the register. * * The HI bit addition and selector offset handling COULD be more * complicated by shifting and masking off the voltage selector part * of the register then logical OR it back in, but since the selector * is at bits 4:0 there is very little point. This makes the whole * thing more readable and we do far less work. */ if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) { |
78040b630
|
433 |
mask |= MC13892_SWITCHERS0_SWxHI; |
ccf3ed782
|
434 435 436 |
if (volt > 1375000) { reg_value -= MC13892_SWxHI_SEL_OFFSET; reg_value |= MC13892_SWITCHERS0_SWxHI; |
78040b630
|
437 |
} else { |
ccf3ed782
|
438 |
reg_value &= ~MC13892_SWITCHERS0_SWxHI; |
ccf3ed782
|
439 |
} |
8db98440f
|
440 |
} |
5e428d5ce
|
441 |
|
8db98440f
|
442 |
mc13xxx_lock(priv->mc13xxx); |
c6a21f246
|
443 444 |
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, mask, reg_value); |
5e428d5ce
|
445 446 447 448 |
mc13xxx_unlock(priv->mc13xxx); return ret; } |
e5680c4de
|
449 |
static const struct regulator_ops mc13892_sw_regulator_ops = { |
34e74f39f
|
450 |
.list_voltage = regulator_list_voltage_table, |
3bdf59928
|
451 |
.map_voltage = regulator_map_voltage_ascend, |
939b62d89
|
452 |
.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, |
f1dcf9e4e
|
453 |
.get_voltage_sel = mc13892_sw_regulator_get_voltage_sel, |
5e428d5ce
|
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
}; static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode) { unsigned int en_val = 0; struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); if (mode == REGULATOR_MODE_FAST) en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN; mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val); mc13xxx_unlock(priv->mc13xxx); return ret; } |
27315cf61
|
472 |
static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) |
5e428d5ce
|
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
{ struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); unsigned int val; mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); mc13xxx_unlock(priv->mc13xxx); if (ret) return ret; if (val & MC13892_REGULATORMODE1_VCAMCONFIGEN) return REGULATOR_MODE_FAST; return REGULATOR_MODE_NORMAL; } |
39f5460d7
|
490 |
static struct regulator_ops mc13892_vcam_ops; |
5e428d5ce
|
491 |
|
a5023574d
|
492 |
static int mc13892_regulator_probe(struct platform_device *pdev) |
5e428d5ce
|
493 494 495 |
{ struct mc13xxx_regulator_priv *priv; struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); |
c8a03c96b
|
496 497 |
struct mc13xxx_regulator_platform_data *pdata = dev_get_platdata(&pdev->dev); |
93bcb23b3
|
498 |
struct mc13xxx_regulator_init_data *mc13xxx_data; |
a9d580104
|
499 |
struct regulator_config config = { }; |
5e428d5ce
|
500 |
int i, ret; |
eb0d8e7a1
|
501 |
int num_regulators = 0; |
5e428d5ce
|
502 |
u32 val; |
93bcb23b3
|
503 |
num_regulators = mc13xxx_get_num_regulators_dt(pdev); |
2c8a5dcaa
|
504 |
|
93bcb23b3
|
505 506 507 508 |
if (num_regulators <= 0 && pdata) num_regulators = pdata->num_regulators; if (num_regulators <= 0) return -EINVAL; |
0ed2dd03b
|
509 510 511 |
priv = devm_kzalloc(&pdev->dev, struct_size(priv, regulators, num_regulators), GFP_KERNEL); |
5e428d5ce
|
512 513 |
if (!priv) return -ENOMEM; |
93bcb23b3
|
514 |
priv->num_regulators = num_regulators; |
5e428d5ce
|
515 516 |
priv->mc13xxx_regulators = mc13892_regulators; priv->mc13xxx = mc13892; |
93bcb23b3
|
517 |
platform_set_drvdata(pdev, priv); |
5e428d5ce
|
518 519 520 521 |
mc13xxx_lock(mc13892); ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); if (ret) |
5777d9b34
|
522 |
goto err_unlock; |
5e428d5ce
|
523 |
|
ccf3ed782
|
524 |
/* enable switch auto mode (on 2.0A silicon only) */ |
5e428d5ce
|
525 526 527 528 529 530 531 |
if ((val & 0x0000FFFF) == 0x45d0) { ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4, MC13892_SWITCHERS4_SW1MODE_M | MC13892_SWITCHERS4_SW2MODE_M, MC13892_SWITCHERS4_SW1MODE_AUTO | MC13892_SWITCHERS4_SW2MODE_AUTO); if (ret) |
5777d9b34
|
532 |
goto err_unlock; |
5e428d5ce
|
533 |
|
923430cfe
|
534 |
ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5, |
5e428d5ce
|
535 536 537 538 539 |
MC13892_SWITCHERS5_SW3MODE_M | MC13892_SWITCHERS5_SW4MODE_M, MC13892_SWITCHERS5_SW3MODE_AUTO | MC13892_SWITCHERS5_SW4MODE_AUTO); if (ret) |
5777d9b34
|
540 |
goto err_unlock; |
5e428d5ce
|
541 542 |
} mc13xxx_unlock(mc13892); |
39f5460d7
|
543 544 545 546 547 548 |
/* update mc13892_vcam ops */ memcpy(&mc13892_vcam_ops, mc13892_regulators[MC13892_VCAM].desc.ops, sizeof(struct regulator_ops)); mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode, mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode, mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops; |
93bcb23b3
|
549 550 |
mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, |
eb0d8e7a1
|
551 |
ARRAY_SIZE(mc13892_regulators)); |
2c8a5dcaa
|
552 |
|
eb0d8e7a1
|
553 |
for (i = 0; i < priv->num_regulators; i++) { |
93bcb23b3
|
554 555 556 557 558 559 560 561 562 563 564 565 566 567 |
struct regulator_init_data *init_data; struct regulator_desc *desc; struct device_node *node = NULL; int id; if (mc13xxx_data) { id = mc13xxx_data[i].id; init_data = mc13xxx_data[i].init_data; node = mc13xxx_data[i].node; } else { id = pdata->regulators[i].id; init_data = pdata->regulators[i].init_data; } desc = &mc13892_regulators[id].desc; |
a9d580104
|
568 569 570 571 |
config.dev = &pdev->dev; config.init_data = init_data; config.driver_data = priv; config.of_node = node; |
5e428d5ce
|
572 |
|
8c0b4ab50
|
573 574 |
priv->regulators[i] = devm_regulator_register(&pdev->dev, desc, &config); |
5e428d5ce
|
575 576 577 578 |
if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s ", mc13892_regulators[i].desc.name); |
8c0b4ab50
|
579 |
return PTR_ERR(priv->regulators[i]); |
5e428d5ce
|
580 581 |
} } |
5e428d5ce
|
582 |
return 0; |
5e428d5ce
|
583 |
|
5777d9b34
|
584 |
err_unlock: |
5e428d5ce
|
585 |
mc13xxx_unlock(mc13892); |
5e428d5ce
|
586 587 |
return ret; } |
5e428d5ce
|
588 589 590 |
static struct platform_driver mc13892_regulator_driver = { .driver = { .name = "mc13892-regulator", |
5e428d5ce
|
591 |
}, |
5e428d5ce
|
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 |
.probe = mc13892_regulator_probe, }; static int __init mc13892_regulator_init(void) { return platform_driver_register(&mc13892_regulator_driver); } subsys_initcall(mc13892_regulator_init); static void __exit mc13892_regulator_exit(void) { platform_driver_unregister(&mc13892_regulator_driver); } module_exit(mc13892_regulator_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); MODULE_DESCRIPTION("Regulator Driver for Freescale MC13892 PMIC"); MODULE_ALIAS("platform:mc13892-regulator"); |