| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1 | /* | 
| Duy Truong | e833aca | 2013-02-12 13:35:08 -0800 | [diff] [blame] | 2 | * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3 | * | 
|  | 4 | * This program is free software; you can redistribute it and/or modify | 
|  | 5 | * it under the terms of the GNU General Public License version 2 and | 
|  | 6 | * only version 2 as published by the Free Software Foundation. | 
|  | 7 | * | 
|  | 8 | * This program is distributed in the hope that it will be useful, | 
|  | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 11 | * GNU General Public License for more details. | 
|  | 12 | */ | 
|  | 13 |  | 
|  | 14 | #define pr_fmt(fmt) "%s: " fmt, __func__ | 
|  | 15 |  | 
|  | 16 | #include <linux/module.h> | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 17 | #include <linux/delay.h> | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 18 | #include <linux/err.h> | 
|  | 19 | #include <linux/string.h> | 
|  | 20 | #include <linux/kernel.h> | 
|  | 21 | #include <linux/init.h> | 
|  | 22 | #include <linux/bitops.h> | 
|  | 23 | #include <linux/mfd/pm8xxx/core.h> | 
|  | 24 | #include <linux/mfd/pm8xxx/regulator.h> | 
|  | 25 |  | 
|  | 26 | /* Debug Flag Definitions */ | 
|  | 27 | enum { | 
|  | 28 | PM8XXX_VREG_DEBUG_REQUEST	= BIT(0), | 
|  | 29 | PM8XXX_VREG_DEBUG_DUPLICATE	= BIT(1), | 
|  | 30 | PM8XXX_VREG_DEBUG_INIT		= BIT(2), | 
|  | 31 | PM8XXX_VREG_DEBUG_WRITES	= BIT(3), /* SSBI writes */ | 
|  | 32 | }; | 
|  | 33 |  | 
|  | 34 | static int pm8xxx_vreg_debug_mask; | 
|  | 35 | module_param_named( | 
|  | 36 | debug_mask, pm8xxx_vreg_debug_mask, int, S_IRUSR | S_IWUSR | 
|  | 37 | ); | 
|  | 38 |  | 
|  | 39 | /* Common Masks */ | 
|  | 40 | #define REGULATOR_ENABLE_MASK		0x80 | 
|  | 41 | #define REGULATOR_ENABLE		0x80 | 
|  | 42 | #define REGULATOR_DISABLE		0x00 | 
|  | 43 |  | 
|  | 44 | #define REGULATOR_BANK_MASK		0xF0 | 
|  | 45 | #define REGULATOR_BANK_SEL(n)		((n) << 4) | 
|  | 46 | #define REGULATOR_BANK_WRITE		0x80 | 
|  | 47 |  | 
|  | 48 | #define LDO_TEST_BANKS			7 | 
|  | 49 | #define NLDO1200_TEST_BANKS		5 | 
|  | 50 | #define SMPS_TEST_BANKS			8 | 
|  | 51 |  | 
|  | 52 | /* | 
|  | 53 | * This voltage in uV is returned by get_voltage functions when there is no way | 
|  | 54 | * to determine the current voltage level.  It is needed because the regulator | 
|  | 55 | * framework treats a 0 uV voltage as an error. | 
|  | 56 | */ | 
|  | 57 | #define VOLTAGE_UNKNOWN			1 | 
|  | 58 |  | 
|  | 59 | /* LDO masks and values */ | 
|  | 60 |  | 
|  | 61 | /* CTRL register */ | 
|  | 62 | #define LDO_ENABLE_MASK			0x80 | 
|  | 63 | #define LDO_DISABLE			0x00 | 
|  | 64 | #define LDO_ENABLE			0x80 | 
|  | 65 | #define LDO_PULL_DOWN_ENABLE_MASK	0x40 | 
|  | 66 | #define LDO_PULL_DOWN_ENABLE		0x40 | 
|  | 67 |  | 
|  | 68 | #define LDO_CTRL_PM_MASK		0x20 | 
|  | 69 | #define LDO_CTRL_PM_HPM			0x00 | 
|  | 70 | #define LDO_CTRL_PM_LPM			0x20 | 
|  | 71 |  | 
|  | 72 | #define LDO_CTRL_VPROG_MASK		0x1F | 
|  | 73 |  | 
|  | 74 | /* TEST register bank 0 */ | 
|  | 75 | #define LDO_TEST_LPM_MASK		0x04 | 
|  | 76 | #define LDO_TEST_LPM_SEL_CTRL		0x00 | 
|  | 77 | #define LDO_TEST_LPM_SEL_TCXO		0x04 | 
|  | 78 |  | 
|  | 79 | /* TEST register bank 2 */ | 
|  | 80 | #define LDO_TEST_VPROG_UPDATE_MASK	0x08 | 
|  | 81 | #define LDO_TEST_RANGE_SEL_MASK		0x04 | 
|  | 82 | #define LDO_TEST_FINE_STEP_MASK		0x02 | 
|  | 83 | #define LDO_TEST_FINE_STEP_SHIFT	1 | 
|  | 84 |  | 
|  | 85 | /* TEST register bank 4 */ | 
|  | 86 | #define LDO_TEST_RANGE_EXT_MASK		0x01 | 
|  | 87 |  | 
|  | 88 | /* TEST register bank 5 */ | 
|  | 89 | #define LDO_TEST_PIN_CTRL_MASK		0x0F | 
|  | 90 | #define LDO_TEST_PIN_CTRL_EN3		0x08 | 
|  | 91 | #define LDO_TEST_PIN_CTRL_EN2		0x04 | 
|  | 92 | #define LDO_TEST_PIN_CTRL_EN1		0x02 | 
|  | 93 | #define LDO_TEST_PIN_CTRL_EN0		0x01 | 
|  | 94 |  | 
|  | 95 | /* TEST register bank 6 */ | 
|  | 96 | #define LDO_TEST_PIN_CTRL_LPM_MASK	0x0F | 
|  | 97 |  | 
|  | 98 | /* | 
|  | 99 | * If a given voltage could be output by two ranges, then the preferred one must | 
|  | 100 | * be determined by the range limits.  Specified voltage ranges should must | 
|  | 101 | * not overlap. | 
|  | 102 | * | 
|  | 103 | * Allowable voltage ranges: | 
|  | 104 | */ | 
|  | 105 | #define PLDO_LOW_UV_MIN			750000 | 
|  | 106 | #define PLDO_LOW_UV_MAX			1487500 | 
|  | 107 | #define PLDO_LOW_UV_FINE_STEP		12500 | 
|  | 108 |  | 
|  | 109 | #define PLDO_NORM_UV_MIN		1500000 | 
|  | 110 | #define PLDO_NORM_UV_MAX		3075000 | 
|  | 111 | #define PLDO_NORM_UV_FINE_STEP		25000 | 
|  | 112 |  | 
|  | 113 | #define PLDO_HIGH_UV_MIN		1750000 | 
|  | 114 | #define PLDO_HIGH_UV_SET_POINT_MIN	3100000 | 
|  | 115 | #define PLDO_HIGH_UV_MAX		4900000 | 
|  | 116 | #define PLDO_HIGH_UV_FINE_STEP		50000 | 
|  | 117 |  | 
|  | 118 | #define PLDO_LOW_SET_POINTS		((PLDO_LOW_UV_MAX - PLDO_LOW_UV_MIN) \ | 
|  | 119 | / PLDO_LOW_UV_FINE_STEP + 1) | 
|  | 120 | #define PLDO_NORM_SET_POINTS		((PLDO_NORM_UV_MAX - PLDO_NORM_UV_MIN) \ | 
|  | 121 | / PLDO_NORM_UV_FINE_STEP + 1) | 
|  | 122 | #define PLDO_HIGH_SET_POINTS		((PLDO_HIGH_UV_MAX \ | 
|  | 123 | - PLDO_HIGH_UV_SET_POINT_MIN) \ | 
|  | 124 | / PLDO_HIGH_UV_FINE_STEP + 1) | 
|  | 125 | #define PLDO_SET_POINTS			(PLDO_LOW_SET_POINTS \ | 
|  | 126 | + PLDO_NORM_SET_POINTS \ | 
|  | 127 | + PLDO_HIGH_SET_POINTS) | 
|  | 128 |  | 
|  | 129 | #define NLDO_UV_MIN			750000 | 
|  | 130 | #define NLDO_UV_MAX			1537500 | 
|  | 131 | #define NLDO_UV_FINE_STEP		12500 | 
|  | 132 |  | 
|  | 133 | #define NLDO_SET_POINTS			((NLDO_UV_MAX - NLDO_UV_MIN) \ | 
|  | 134 | / NLDO_UV_FINE_STEP + 1) | 
|  | 135 |  | 
|  | 136 | /* NLDO1200 masks and values */ | 
|  | 137 |  | 
|  | 138 | /* CTRL register */ | 
|  | 139 | #define NLDO1200_ENABLE_MASK		0x80 | 
|  | 140 | #define NLDO1200_DISABLE		0x00 | 
|  | 141 | #define NLDO1200_ENABLE			0x80 | 
|  | 142 |  | 
|  | 143 | /* Legacy mode */ | 
|  | 144 | #define NLDO1200_LEGACY_PM_MASK		0x20 | 
|  | 145 | #define NLDO1200_LEGACY_PM_HPM		0x00 | 
|  | 146 | #define NLDO1200_LEGACY_PM_LPM		0x20 | 
|  | 147 |  | 
|  | 148 | /* Advanced mode */ | 
|  | 149 | #define NLDO1200_CTRL_RANGE_MASK	0x40 | 
|  | 150 | #define NLDO1200_CTRL_RANGE_HIGH	0x00 | 
|  | 151 | #define NLDO1200_CTRL_RANGE_LOW		0x40 | 
|  | 152 | #define NLDO1200_CTRL_VPROG_MASK	0x3F | 
|  | 153 |  | 
|  | 154 | #define NLDO1200_LOW_UV_MIN		375000 | 
|  | 155 | #define NLDO1200_LOW_UV_MAX		743750 | 
|  | 156 | #define NLDO1200_LOW_UV_STEP		6250 | 
|  | 157 |  | 
|  | 158 | #define NLDO1200_HIGH_UV_MIN		750000 | 
|  | 159 | #define NLDO1200_HIGH_UV_MAX		1537500 | 
|  | 160 | #define NLDO1200_HIGH_UV_STEP		12500 | 
|  | 161 |  | 
|  | 162 | #define NLDO1200_LOW_SET_POINTS		((NLDO1200_LOW_UV_MAX \ | 
|  | 163 | - NLDO1200_LOW_UV_MIN) \ | 
|  | 164 | / NLDO1200_LOW_UV_STEP + 1) | 
|  | 165 | #define NLDO1200_HIGH_SET_POINTS	((NLDO1200_HIGH_UV_MAX \ | 
|  | 166 | - NLDO1200_HIGH_UV_MIN) \ | 
|  | 167 | / NLDO1200_HIGH_UV_STEP + 1) | 
|  | 168 | #define NLDO1200_SET_POINTS		(NLDO1200_LOW_SET_POINTS \ | 
|  | 169 | + NLDO1200_HIGH_SET_POINTS) | 
|  | 170 |  | 
|  | 171 | /* TEST register bank 0 */ | 
|  | 172 | #define NLDO1200_TEST_LPM_MASK		0x04 | 
|  | 173 | #define NLDO1200_TEST_LPM_SEL_CTRL	0x00 | 
|  | 174 | #define NLDO1200_TEST_LPM_SEL_TCXO	0x04 | 
|  | 175 |  | 
|  | 176 | /* TEST register bank 1 */ | 
|  | 177 | #define NLDO1200_PULL_DOWN_ENABLE_MASK	0x02 | 
|  | 178 | #define NLDO1200_PULL_DOWN_ENABLE	0x02 | 
|  | 179 |  | 
|  | 180 | /* TEST register bank 2 */ | 
|  | 181 | #define NLDO1200_ADVANCED_MODE_MASK	0x08 | 
|  | 182 | #define NLDO1200_ADVANCED_MODE		0x00 | 
|  | 183 | #define NLDO1200_LEGACY_MODE		0x08 | 
|  | 184 |  | 
|  | 185 | /* Advanced mode power mode control */ | 
|  | 186 | #define NLDO1200_ADVANCED_PM_MASK	0x02 | 
|  | 187 | #define NLDO1200_ADVANCED_PM_HPM	0x00 | 
|  | 188 | #define NLDO1200_ADVANCED_PM_LPM	0x02 | 
|  | 189 |  | 
|  | 190 | #define NLDO1200_IN_ADVANCED_MODE(vreg) \ | 
|  | 191 | ((vreg->test_reg[2] & NLDO1200_ADVANCED_MODE_MASK) \ | 
|  | 192 | == NLDO1200_ADVANCED_MODE) | 
|  | 193 |  | 
|  | 194 | /* SMPS masks and values */ | 
|  | 195 |  | 
|  | 196 | /* CTRL register */ | 
|  | 197 |  | 
|  | 198 | /* Legacy mode */ | 
|  | 199 | #define SMPS_LEGACY_ENABLE_MASK		0x80 | 
|  | 200 | #define SMPS_LEGACY_DISABLE		0x00 | 
|  | 201 | #define SMPS_LEGACY_ENABLE		0x80 | 
|  | 202 | #define SMPS_LEGACY_PULL_DOWN_ENABLE	0x40 | 
|  | 203 | #define SMPS_LEGACY_VREF_SEL_MASK	0x20 | 
|  | 204 | #define SMPS_LEGACY_VPROG_MASK		0x1F | 
|  | 205 |  | 
|  | 206 | /* Advanced mode */ | 
|  | 207 | #define SMPS_ADVANCED_BAND_MASK		0xC0 | 
|  | 208 | #define SMPS_ADVANCED_BAND_OFF		0x00 | 
|  | 209 | #define SMPS_ADVANCED_BAND_1		0x40 | 
|  | 210 | #define SMPS_ADVANCED_BAND_2		0x80 | 
|  | 211 | #define SMPS_ADVANCED_BAND_3		0xC0 | 
|  | 212 | #define SMPS_ADVANCED_VPROG_MASK	0x3F | 
|  | 213 |  | 
|  | 214 | /* Legacy mode voltage ranges */ | 
|  | 215 | #define SMPS_MODE3_UV_MIN		375000 | 
|  | 216 | #define SMPS_MODE3_UV_MAX		725000 | 
|  | 217 | #define SMPS_MODE3_UV_STEP		25000 | 
|  | 218 |  | 
|  | 219 | #define SMPS_MODE2_UV_MIN		750000 | 
|  | 220 | #define SMPS_MODE2_UV_MAX		1475000 | 
|  | 221 | #define SMPS_MODE2_UV_STEP		25000 | 
|  | 222 |  | 
|  | 223 | #define SMPS_MODE1_UV_MIN		1500000 | 
|  | 224 | #define SMPS_MODE1_UV_MAX		3050000 | 
|  | 225 | #define SMPS_MODE1_UV_STEP		50000 | 
|  | 226 |  | 
|  | 227 | #define SMPS_MODE3_SET_POINTS		((SMPS_MODE3_UV_MAX \ | 
|  | 228 | - SMPS_MODE3_UV_MIN) \ | 
|  | 229 | / SMPS_MODE3_UV_STEP + 1) | 
|  | 230 | #define SMPS_MODE2_SET_POINTS		((SMPS_MODE2_UV_MAX \ | 
|  | 231 | - SMPS_MODE2_UV_MIN) \ | 
|  | 232 | / SMPS_MODE2_UV_STEP + 1) | 
|  | 233 | #define SMPS_MODE1_SET_POINTS		((SMPS_MODE1_UV_MAX \ | 
|  | 234 | - SMPS_MODE1_UV_MIN) \ | 
|  | 235 | / SMPS_MODE1_UV_STEP + 1) | 
|  | 236 | #define SMPS_LEGACY_SET_POINTS		(SMPS_MODE3_SET_POINTS \ | 
|  | 237 | + SMPS_MODE2_SET_POINTS \ | 
|  | 238 | + SMPS_MODE1_SET_POINTS) | 
|  | 239 |  | 
|  | 240 | /* Advanced mode voltage ranges */ | 
|  | 241 | #define SMPS_BAND1_UV_MIN		375000 | 
|  | 242 | #define SMPS_BAND1_UV_MAX		737500 | 
|  | 243 | #define SMPS_BAND1_UV_STEP		12500 | 
|  | 244 |  | 
|  | 245 | #define SMPS_BAND2_UV_MIN		750000 | 
|  | 246 | #define SMPS_BAND2_UV_MAX		1487500 | 
|  | 247 | #define SMPS_BAND2_UV_STEP		12500 | 
|  | 248 |  | 
|  | 249 | #define SMPS_BAND3_UV_MIN		1500000 | 
|  | 250 | #define SMPS_BAND3_UV_MAX		3075000 | 
|  | 251 | #define SMPS_BAND3_UV_STEP		25000 | 
|  | 252 |  | 
|  | 253 | #define SMPS_BAND1_SET_POINTS		((SMPS_BAND1_UV_MAX \ | 
|  | 254 | - SMPS_BAND1_UV_MIN) \ | 
|  | 255 | / SMPS_BAND1_UV_STEP + 1) | 
|  | 256 | #define SMPS_BAND2_SET_POINTS		((SMPS_BAND2_UV_MAX \ | 
|  | 257 | - SMPS_BAND2_UV_MIN) \ | 
|  | 258 | / SMPS_BAND2_UV_STEP + 1) | 
|  | 259 | #define SMPS_BAND3_SET_POINTS		((SMPS_BAND3_UV_MAX \ | 
|  | 260 | - SMPS_BAND3_UV_MIN) \ | 
|  | 261 | / SMPS_BAND3_UV_STEP + 1) | 
|  | 262 | #define SMPS_ADVANCED_SET_POINTS	(SMPS_BAND1_SET_POINTS \ | 
|  | 263 | + SMPS_BAND2_SET_POINTS \ | 
|  | 264 | + SMPS_BAND3_SET_POINTS) | 
|  | 265 |  | 
|  | 266 | /* Test2 register bank 1 */ | 
|  | 267 | #define SMPS_LEGACY_VLOW_SEL_MASK	0x01 | 
|  | 268 |  | 
|  | 269 | /* Test2 register bank 6 */ | 
|  | 270 | #define SMPS_ADVANCED_PULL_DOWN_ENABLE	0x08 | 
|  | 271 |  | 
|  | 272 | /* Test2 register bank 7 */ | 
|  | 273 | #define SMPS_ADVANCED_MODE_MASK		0x02 | 
|  | 274 | #define SMPS_ADVANCED_MODE		0x02 | 
|  | 275 | #define SMPS_LEGACY_MODE		0x00 | 
|  | 276 |  | 
|  | 277 | #define SMPS_IN_ADVANCED_MODE(vreg) \ | 
|  | 278 | ((vreg->test_reg[7] & SMPS_ADVANCED_MODE_MASK) == SMPS_ADVANCED_MODE) | 
|  | 279 |  | 
|  | 280 | /* BUCK_SLEEP_CNTRL register */ | 
|  | 281 | #define SMPS_PIN_CTRL_MASK		0xF0 | 
|  | 282 | #define SMPS_PIN_CTRL_EN3		0x80 | 
|  | 283 | #define SMPS_PIN_CTRL_EN2		0x40 | 
|  | 284 | #define SMPS_PIN_CTRL_EN1		0x20 | 
|  | 285 | #define SMPS_PIN_CTRL_EN0		0x10 | 
|  | 286 |  | 
|  | 287 | #define SMPS_PIN_CTRL_LPM_MASK		0x0F | 
|  | 288 | #define SMPS_PIN_CTRL_LPM_EN3		0x08 | 
|  | 289 | #define SMPS_PIN_CTRL_LPM_EN2		0x04 | 
|  | 290 | #define SMPS_PIN_CTRL_LPM_EN1		0x02 | 
|  | 291 | #define SMPS_PIN_CTRL_LPM_EN0		0x01 | 
|  | 292 |  | 
|  | 293 | /* BUCK_CLOCK_CNTRL register */ | 
|  | 294 | #define SMPS_CLK_DIVIDE2		0x40 | 
|  | 295 |  | 
|  | 296 | #define SMPS_CLK_CTRL_MASK		0x30 | 
|  | 297 | #define SMPS_CLK_CTRL_FOLLOW_TCXO	0x00 | 
|  | 298 | #define SMPS_CLK_CTRL_PWM		0x10 | 
|  | 299 | #define SMPS_CLK_CTRL_PFM		0x20 | 
|  | 300 |  | 
|  | 301 | /* FTSMPS masks and values */ | 
|  | 302 |  | 
|  | 303 | /* CTRL register */ | 
|  | 304 | #define FTSMPS_VCTRL_BAND_MASK		0xC0 | 
|  | 305 | #define FTSMPS_VCTRL_BAND_OFF		0x00 | 
|  | 306 | #define FTSMPS_VCTRL_BAND_1		0x40 | 
|  | 307 | #define FTSMPS_VCTRL_BAND_2		0x80 | 
|  | 308 | #define FTSMPS_VCTRL_BAND_3		0xC0 | 
|  | 309 | #define FTSMPS_VCTRL_VPROG_MASK		0x3F | 
|  | 310 |  | 
|  | 311 | #define FTSMPS_BAND1_UV_MIN		350000 | 
|  | 312 | #define FTSMPS_BAND1_UV_MAX		650000 | 
|  | 313 | /* 3 LSB's of program voltage must be 0 in band 1. */ | 
|  | 314 | /* Logical step size */ | 
|  | 315 | #define FTSMPS_BAND1_UV_LOG_STEP	50000 | 
|  | 316 | /* Physical step size */ | 
|  | 317 | #define FTSMPS_BAND1_UV_PHYS_STEP	6250 | 
|  | 318 |  | 
|  | 319 | #define FTSMPS_BAND2_UV_MIN		700000 | 
|  | 320 | #define FTSMPS_BAND2_UV_MAX		1400000 | 
|  | 321 | #define FTSMPS_BAND2_UV_STEP		12500 | 
|  | 322 |  | 
|  | 323 | #define FTSMPS_BAND3_UV_MIN		1400000 | 
|  | 324 | #define FTSMPS_BAND3_UV_SET_POINT_MIN	1500000 | 
|  | 325 | #define FTSMPS_BAND3_UV_MAX		3300000 | 
|  | 326 | #define FTSMPS_BAND3_UV_STEP		50000 | 
|  | 327 |  | 
|  | 328 | #define FTSMPS_BAND1_SET_POINTS		((FTSMPS_BAND1_UV_MAX \ | 
|  | 329 | - FTSMPS_BAND1_UV_MIN) \ | 
|  | 330 | / FTSMPS_BAND1_UV_LOG_STEP + 1) | 
|  | 331 | #define FTSMPS_BAND2_SET_POINTS		((FTSMPS_BAND2_UV_MAX \ | 
|  | 332 | - FTSMPS_BAND2_UV_MIN) \ | 
|  | 333 | / FTSMPS_BAND2_UV_STEP + 1) | 
|  | 334 | #define FTSMPS_BAND3_SET_POINTS		((FTSMPS_BAND3_UV_MAX \ | 
|  | 335 | - FTSMPS_BAND3_UV_SET_POINT_MIN) \ | 
|  | 336 | / FTSMPS_BAND3_UV_STEP + 1) | 
|  | 337 | #define FTSMPS_SET_POINTS		(FTSMPS_BAND1_SET_POINTS \ | 
|  | 338 | + FTSMPS_BAND2_SET_POINTS \ | 
|  | 339 | + FTSMPS_BAND3_SET_POINTS) | 
|  | 340 |  | 
|  | 341 | /* FTS_CNFG1 register bank 0 */ | 
|  | 342 | #define FTSMPS_CNFG1_PM_MASK		0x0C | 
|  | 343 | #define FTSMPS_CNFG1_PM_PWM		0x00 | 
|  | 344 | #define FTSMPS_CNFG1_PM_PFM		0x08 | 
|  | 345 |  | 
|  | 346 | /* PWR_CNFG register */ | 
|  | 347 | #define FTSMPS_PULL_DOWN_ENABLE_MASK	0x40 | 
|  | 348 | #define FTSMPS_PULL_DOWN_ENABLE		0x40 | 
|  | 349 |  | 
|  | 350 | /* VS masks and values */ | 
|  | 351 |  | 
|  | 352 | /* CTRL register */ | 
|  | 353 | #define VS_ENABLE_MASK			0x80 | 
|  | 354 | #define VS_DISABLE			0x00 | 
|  | 355 | #define VS_ENABLE			0x80 | 
|  | 356 | #define VS_PULL_DOWN_ENABLE_MASK	0x40 | 
|  | 357 | #define VS_PULL_DOWN_DISABLE		0x40 | 
|  | 358 | #define VS_PULL_DOWN_ENABLE		0x00 | 
|  | 359 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 360 | #define VS_MODE_MASK			0x30 | 
|  | 361 | #define VS_MODE_NORMAL			0x10 | 
|  | 362 | #define VS_MODE_LPM			0x20 | 
|  | 363 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 364 | #define VS_PIN_CTRL_MASK		0x0F | 
|  | 365 | #define VS_PIN_CTRL_EN0			0x08 | 
|  | 366 | #define VS_PIN_CTRL_EN1			0x04 | 
|  | 367 | #define VS_PIN_CTRL_EN2			0x02 | 
|  | 368 | #define VS_PIN_CTRL_EN3			0x01 | 
|  | 369 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 370 | /* TEST register */ | 
|  | 371 | #define VS_OCP_MASK			0x10 | 
|  | 372 | #define VS_OCP_ENABLE			0x00 | 
|  | 373 | #define VS_OCP_DISABLE			0x10 | 
|  | 374 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 375 | /* VS300 masks and values */ | 
|  | 376 |  | 
|  | 377 | /* CTRL register */ | 
|  | 378 | #define VS300_CTRL_ENABLE_MASK		0xC0 | 
|  | 379 | #define VS300_CTRL_DISABLE		0x00 | 
|  | 380 | #define VS300_CTRL_ENABLE		0x40 | 
|  | 381 |  | 
|  | 382 | #define VS300_PULL_DOWN_ENABLE_MASK	0x20 | 
|  | 383 | #define VS300_PULL_DOWN_ENABLE		0x20 | 
|  | 384 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 385 | #define VS300_MODE_MASK			0x18 | 
|  | 386 | #define VS300_MODE_NORMAL		0x00 | 
|  | 387 | #define VS300_MODE_LPM			0x08 | 
|  | 388 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 389 | /* NCP masks and values */ | 
|  | 390 |  | 
|  | 391 | /* CTRL register */ | 
|  | 392 | #define NCP_ENABLE_MASK			0x80 | 
|  | 393 | #define NCP_DISABLE			0x00 | 
|  | 394 | #define NCP_ENABLE			0x80 | 
|  | 395 | #define NCP_VPROG_MASK			0x1F | 
|  | 396 |  | 
|  | 397 | #define NCP_UV_MIN			1500000 | 
|  | 398 | #define NCP_UV_MAX			3050000 | 
|  | 399 | #define NCP_UV_STEP			50000 | 
|  | 400 |  | 
|  | 401 | #define NCP_SET_POINTS			((NCP_UV_MAX - NCP_UV_MIN) \ | 
|  | 402 | / NCP_UV_STEP + 1) | 
|  | 403 |  | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 404 | /* Boost masks and values */ | 
|  | 405 | #define BOOST_ENABLE_MASK		0x80 | 
|  | 406 | #define BOOST_DISABLE			0x00 | 
|  | 407 | #define BOOST_ENABLE			0x80 | 
|  | 408 | #define BOOST_VPROG_MASK		0x1F | 
|  | 409 |  | 
|  | 410 | #define BOOST_UV_MIN			4000000 | 
|  | 411 | #define BOOST_UV_MAX			5550000 | 
|  | 412 | #define BOOST_UV_STEP			50000 | 
|  | 413 |  | 
|  | 414 | #define BOOST_SET_POINTS		((BOOST_UV_MAX - BOOST_UV_MIN) \ | 
|  | 415 | / BOOST_UV_STEP + 1) | 
|  | 416 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 417 | #define vreg_err(vreg, fmt, ...) \ | 
|  | 418 | pr_err("%s: " fmt, vreg->rdesc.name, ##__VA_ARGS__) | 
|  | 419 |  | 
|  | 420 | /* Determines which label to add to the print. */ | 
|  | 421 | enum pm8xxx_regulator_action { | 
|  | 422 | PM8XXX_REGULATOR_ACTION_INIT, | 
|  | 423 | PM8XXX_REGULATOR_ACTION_ENABLE, | 
|  | 424 | PM8XXX_REGULATOR_ACTION_DISABLE, | 
|  | 425 | PM8XXX_REGULATOR_ACTION_VOLTAGE, | 
|  | 426 | PM8XXX_REGULATOR_ACTION_MODE, | 
|  | 427 | PM8XXX_REGULATOR_ACTION_PIN_CTRL, | 
|  | 428 | }; | 
|  | 429 |  | 
|  | 430 | /* Debug state printing */ | 
|  | 431 | static void pm8xxx_vreg_show_state(struct regulator_dev *rdev, | 
|  | 432 | enum pm8xxx_regulator_action action); | 
|  | 433 |  | 
|  | 434 | /* | 
|  | 435 | * Perform a masked write to a PMIC register only if the new value differs | 
|  | 436 | * from the last value written to the register.  This removes redundant | 
|  | 437 | * register writing. | 
|  | 438 | * | 
|  | 439 | * No locking is required because registers are not shared between regulators. | 
|  | 440 | */ | 
|  | 441 | static int pm8xxx_vreg_masked_write(struct pm8xxx_vreg *vreg, u16 addr, u8 val, | 
|  | 442 | u8 mask, u8 *reg_save) | 
|  | 443 | { | 
|  | 444 | int rc = 0; | 
|  | 445 | u8 reg; | 
|  | 446 |  | 
|  | 447 | reg = (*reg_save & ~mask) | (val & mask); | 
|  | 448 | if (reg != *reg_save) { | 
|  | 449 | rc = pm8xxx_writeb(vreg->dev->parent, addr, reg); | 
|  | 450 |  | 
|  | 451 | if (rc) { | 
|  | 452 | pr_err("%s: pm8xxx_writeb failed; addr=0x%03X, rc=%d\n", | 
|  | 453 | vreg->rdesc.name, addr, rc); | 
|  | 454 | } else { | 
|  | 455 | *reg_save = reg; | 
|  | 456 | vreg->write_count++; | 
|  | 457 | if (pm8xxx_vreg_debug_mask & PM8XXX_VREG_DEBUG_WRITES) | 
|  | 458 | pr_info("%s: write(0x%03X)=0x%02X\n", | 
|  | 459 | vreg->rdesc.name, addr, reg); | 
|  | 460 | } | 
|  | 461 | } | 
|  | 462 |  | 
|  | 463 | return rc; | 
|  | 464 | } | 
|  | 465 |  | 
|  | 466 | /* | 
|  | 467 | * Perform a masked write to a PMIC register without checking the previously | 
|  | 468 | * written value.  This is needed for registers that must be rewritten even if | 
|  | 469 | * the value hasn't changed in order for changes in other registers to take | 
|  | 470 | * effect. | 
|  | 471 | */ | 
|  | 472 | static int pm8xxx_vreg_masked_write_forced(struct pm8xxx_vreg *vreg, u16 addr, | 
|  | 473 | u8 val, u8 mask, u8 *reg_save) | 
|  | 474 | { | 
|  | 475 | int rc = 0; | 
|  | 476 | u8 reg; | 
|  | 477 |  | 
|  | 478 | reg = (*reg_save & ~mask) | (val & mask); | 
|  | 479 | rc = pm8xxx_writeb(vreg->dev->parent, addr, reg); | 
|  | 480 |  | 
|  | 481 | if (rc) { | 
|  | 482 | pr_err("%s: pm8xxx_writeb failed; addr=0x%03X, rc=%d\n", | 
|  | 483 | vreg->rdesc.name, addr, rc); | 
|  | 484 | } else { | 
|  | 485 | *reg_save = reg; | 
|  | 486 | vreg->write_count++; | 
|  | 487 | if (pm8xxx_vreg_debug_mask & PM8XXX_VREG_DEBUG_WRITES) | 
|  | 488 | pr_info("%s: write(0x%03X)=0x%02X\n", vreg->rdesc.name, | 
|  | 489 | addr, reg); | 
|  | 490 | } | 
|  | 491 |  | 
|  | 492 | return rc; | 
|  | 493 | } | 
|  | 494 |  | 
|  | 495 | static int pm8xxx_vreg_is_pin_controlled(struct pm8xxx_vreg *vreg) | 
|  | 496 | { | 
|  | 497 | int ret = 0; | 
|  | 498 |  | 
|  | 499 | switch (vreg->type) { | 
|  | 500 | case PM8XXX_REGULATOR_TYPE_PLDO: | 
|  | 501 | case PM8XXX_REGULATOR_TYPE_NLDO: | 
|  | 502 | ret = ((vreg->test_reg[5] & LDO_TEST_PIN_CTRL_MASK) << 4) | 
|  | 503 | | (vreg->test_reg[6] & LDO_TEST_PIN_CTRL_LPM_MASK); | 
|  | 504 | break; | 
|  | 505 | case PM8XXX_REGULATOR_TYPE_SMPS: | 
|  | 506 | ret = vreg->sleep_ctrl_reg | 
|  | 507 | & (SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK); | 
|  | 508 | break; | 
|  | 509 | case PM8XXX_REGULATOR_TYPE_VS: | 
|  | 510 | ret = vreg->ctrl_reg & VS_PIN_CTRL_MASK; | 
|  | 511 | break; | 
|  | 512 | default: | 
|  | 513 | break; | 
|  | 514 | } | 
|  | 515 |  | 
|  | 516 | return ret; | 
|  | 517 | } | 
|  | 518 |  | 
|  | 519 | /* | 
|  | 520 | * Returns the logical pin control enable state because the pin control options | 
|  | 521 | * present in the hardware out of restart could be different from those desired | 
|  | 522 | * by the consumer. | 
|  | 523 | */ | 
|  | 524 | static int pm8xxx_vreg_pin_control_is_enabled(struct regulator_dev *rdev) | 
|  | 525 | { | 
|  | 526 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 527 | int enabled; | 
|  | 528 |  | 
|  | 529 | mutex_lock(&vreg->pc_lock); | 
|  | 530 | enabled = vreg->is_enabled_pc; | 
|  | 531 | mutex_unlock(&vreg->pc_lock); | 
|  | 532 |  | 
|  | 533 | return enabled; | 
|  | 534 | } | 
|  | 535 |  | 
|  | 536 | /* Returns the physical enable state of the regulator. */ | 
|  | 537 | static int _pm8xxx_vreg_is_enabled(struct pm8xxx_vreg *vreg) | 
|  | 538 | { | 
|  | 539 | int rc = 0; | 
|  | 540 |  | 
|  | 541 | /* | 
|  | 542 | * All regulator types except advanced mode SMPS, FTSMPS, and VS300 have | 
|  | 543 | * enable bit in bit 7 of the control register. | 
|  | 544 | */ | 
|  | 545 | switch (vreg->type) { | 
|  | 546 | case PM8XXX_REGULATOR_TYPE_FTSMPS: | 
|  | 547 | if ((vreg->ctrl_reg & FTSMPS_VCTRL_BAND_MASK) | 
|  | 548 | != FTSMPS_VCTRL_BAND_OFF) | 
|  | 549 | rc = 1; | 
|  | 550 | break; | 
|  | 551 | case PM8XXX_REGULATOR_TYPE_VS300: | 
|  | 552 | if ((vreg->ctrl_reg & VS300_CTRL_ENABLE_MASK) | 
|  | 553 | != VS300_CTRL_DISABLE) | 
|  | 554 | rc = 1; | 
|  | 555 | break; | 
|  | 556 | case PM8XXX_REGULATOR_TYPE_SMPS: | 
|  | 557 | if (SMPS_IN_ADVANCED_MODE(vreg)) { | 
|  | 558 | if ((vreg->ctrl_reg & SMPS_ADVANCED_BAND_MASK) | 
|  | 559 | != SMPS_ADVANCED_BAND_OFF) | 
|  | 560 | rc = 1; | 
|  | 561 | break; | 
|  | 562 | } | 
|  | 563 | /* Fall through for legacy mode SMPS. */ | 
|  | 564 | default: | 
|  | 565 | if ((vreg->ctrl_reg & REGULATOR_ENABLE_MASK) | 
|  | 566 | == REGULATOR_ENABLE) | 
|  | 567 | rc = 1; | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | return rc; | 
|  | 571 | } | 
|  | 572 |  | 
|  | 573 | /* | 
|  | 574 | * Returns the logical enable state of the regulator which may be different from | 
|  | 575 | * the physical enable state thanks to HPM/LPM pin control. | 
|  | 576 | */ | 
|  | 577 | static int pm8xxx_vreg_is_enabled(struct regulator_dev *rdev) | 
|  | 578 | { | 
|  | 579 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 580 | int enabled; | 
|  | 581 |  | 
|  | 582 | if (vreg->type == PM8XXX_REGULATOR_TYPE_PLDO | 
|  | 583 | || vreg->type == PM8XXX_REGULATOR_TYPE_NLDO | 
|  | 584 | || vreg->type == PM8XXX_REGULATOR_TYPE_SMPS | 
|  | 585 | || vreg->type == PM8XXX_REGULATOR_TYPE_VS) { | 
|  | 586 | /* Pin controllable */ | 
|  | 587 | mutex_lock(&vreg->pc_lock); | 
|  | 588 | enabled = vreg->is_enabled; | 
|  | 589 | mutex_unlock(&vreg->pc_lock); | 
|  | 590 | } else { | 
|  | 591 | /* Not pin controlable */ | 
|  | 592 | enabled = _pm8xxx_vreg_is_enabled(vreg); | 
|  | 593 | } | 
|  | 594 |  | 
|  | 595 | return enabled; | 
|  | 596 | } | 
|  | 597 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 598 | /* | 
|  | 599 | * Adds delay when increasing in voltage to account for the slew rate of | 
|  | 600 | * the regulator. | 
|  | 601 | */ | 
|  | 602 | static void pm8xxx_vreg_delay_for_slew(struct pm8xxx_vreg *vreg, int prev_uV, | 
|  | 603 | int new_uV) | 
|  | 604 | { | 
|  | 605 | int delay; | 
|  | 606 |  | 
|  | 607 | if (vreg->pdata.slew_rate == 0 || new_uV <= prev_uV || | 
|  | 608 | !_pm8xxx_vreg_is_enabled(vreg)) | 
|  | 609 | return; | 
|  | 610 |  | 
|  | 611 | delay = DIV_ROUND_UP(new_uV - prev_uV, vreg->pdata.slew_rate); | 
|  | 612 |  | 
|  | 613 | if (delay >= 1000) { | 
|  | 614 | mdelay(delay / 1000); | 
|  | 615 | udelay(delay % 1000); | 
|  | 616 | } else { | 
|  | 617 | udelay(delay); | 
|  | 618 | } | 
|  | 619 | } | 
|  | 620 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 621 | static int pm8xxx_pldo_get_voltage(struct regulator_dev *rdev) | 
|  | 622 | { | 
|  | 623 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 624 | int vmin, fine_step; | 
|  | 625 | u8 range_ext, range_sel, vprog, fine_step_reg; | 
|  | 626 |  | 
|  | 627 | mutex_lock(&vreg->pc_lock); | 
|  | 628 |  | 
|  | 629 | fine_step_reg = vreg->test_reg[2] & LDO_TEST_FINE_STEP_MASK; | 
|  | 630 | range_sel = vreg->test_reg[2] & LDO_TEST_RANGE_SEL_MASK; | 
|  | 631 | range_ext = vreg->test_reg[4] & LDO_TEST_RANGE_EXT_MASK; | 
|  | 632 | vprog = vreg->ctrl_reg & LDO_CTRL_VPROG_MASK; | 
|  | 633 |  | 
|  | 634 | mutex_unlock(&vreg->pc_lock); | 
|  | 635 |  | 
|  | 636 | vprog = (vprog << 1) | (fine_step_reg >> LDO_TEST_FINE_STEP_SHIFT); | 
|  | 637 |  | 
|  | 638 | if (range_sel) { | 
|  | 639 | /* low range mode */ | 
|  | 640 | fine_step = PLDO_LOW_UV_FINE_STEP; | 
|  | 641 | vmin = PLDO_LOW_UV_MIN; | 
|  | 642 | } else if (!range_ext) { | 
|  | 643 | /* normal mode */ | 
|  | 644 | fine_step = PLDO_NORM_UV_FINE_STEP; | 
|  | 645 | vmin = PLDO_NORM_UV_MIN; | 
|  | 646 | } else { | 
|  | 647 | /* high range mode */ | 
|  | 648 | fine_step = PLDO_HIGH_UV_FINE_STEP; | 
|  | 649 | vmin = PLDO_HIGH_UV_MIN; | 
|  | 650 | } | 
|  | 651 |  | 
|  | 652 | return fine_step * vprog + vmin; | 
|  | 653 | } | 
|  | 654 |  | 
|  | 655 | static int pm8xxx_pldo_list_voltage(struct regulator_dev *rdev, | 
|  | 656 | unsigned selector) | 
|  | 657 | { | 
|  | 658 | int uV; | 
|  | 659 |  | 
|  | 660 | if (selector >= PLDO_SET_POINTS) | 
|  | 661 | return 0; | 
|  | 662 |  | 
|  | 663 | if (selector < PLDO_LOW_SET_POINTS) | 
|  | 664 | uV = selector * PLDO_LOW_UV_FINE_STEP + PLDO_LOW_UV_MIN; | 
|  | 665 | else if (selector < (PLDO_LOW_SET_POINTS + PLDO_NORM_SET_POINTS)) | 
|  | 666 | uV = (selector - PLDO_LOW_SET_POINTS) * PLDO_NORM_UV_FINE_STEP | 
|  | 667 | + PLDO_NORM_UV_MIN; | 
|  | 668 | else | 
|  | 669 | uV = (selector - PLDO_LOW_SET_POINTS - PLDO_NORM_SET_POINTS) | 
|  | 670 | * PLDO_HIGH_UV_FINE_STEP | 
|  | 671 | + PLDO_HIGH_UV_SET_POINT_MIN; | 
|  | 672 |  | 
|  | 673 | return uV; | 
|  | 674 | } | 
|  | 675 |  | 
|  | 676 | static int pm8xxx_pldo_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 677 | int max_uV, unsigned *selector) | 
|  | 678 | { | 
|  | 679 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 680 | int rc = 0, uV = min_uV; | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 681 | int vmin, prev_uV; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 682 | unsigned vprog, fine_step; | 
|  | 683 | u8 range_ext, range_sel, fine_step_reg, prev_reg; | 
|  | 684 | bool reg_changed = false; | 
|  | 685 |  | 
|  | 686 | if (uV < PLDO_LOW_UV_MIN && max_uV >= PLDO_LOW_UV_MIN) | 
|  | 687 | uV = PLDO_LOW_UV_MIN; | 
|  | 688 |  | 
|  | 689 | if (uV < PLDO_LOW_UV_MIN || uV > PLDO_HIGH_UV_MAX) { | 
|  | 690 | vreg_err(vreg, | 
|  | 691 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 692 | min_uV, max_uV, PLDO_LOW_UV_MIN, PLDO_HIGH_UV_MAX); | 
|  | 693 | return -EINVAL; | 
|  | 694 | } | 
|  | 695 |  | 
|  | 696 | if (uV > PLDO_NORM_UV_MAX) { | 
|  | 697 | vmin = PLDO_HIGH_UV_MIN; | 
|  | 698 | fine_step = PLDO_HIGH_UV_FINE_STEP; | 
|  | 699 | range_ext = LDO_TEST_RANGE_EXT_MASK; | 
|  | 700 | range_sel = 0; | 
|  | 701 | } else if (uV > PLDO_LOW_UV_MAX) { | 
|  | 702 | vmin = PLDO_NORM_UV_MIN; | 
|  | 703 | fine_step = PLDO_NORM_UV_FINE_STEP; | 
|  | 704 | range_ext = 0; | 
|  | 705 | range_sel = 0; | 
|  | 706 | } else { | 
|  | 707 | vmin = PLDO_LOW_UV_MIN; | 
|  | 708 | fine_step = PLDO_LOW_UV_FINE_STEP; | 
|  | 709 | range_ext = 0; | 
|  | 710 | range_sel = LDO_TEST_RANGE_SEL_MASK; | 
|  | 711 | } | 
|  | 712 |  | 
|  | 713 | vprog = (uV - vmin + fine_step - 1) / fine_step; | 
|  | 714 | uV = vprog * fine_step + vmin; | 
|  | 715 | fine_step_reg = (vprog & 1) << LDO_TEST_FINE_STEP_SHIFT; | 
|  | 716 | vprog >>= 1; | 
|  | 717 |  | 
|  | 718 | if (uV > max_uV) { | 
|  | 719 | vreg_err(vreg, | 
|  | 720 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 721 | min_uV, max_uV); | 
|  | 722 | return -EINVAL; | 
|  | 723 | } | 
|  | 724 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 725 | prev_uV = pm8xxx_pldo_get_voltage(rdev); | 
|  | 726 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 727 | mutex_lock(&vreg->pc_lock); | 
|  | 728 |  | 
|  | 729 | /* Write fine step, range select and program voltage update. */ | 
|  | 730 | prev_reg = vreg->test_reg[2]; | 
|  | 731 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 732 | fine_step_reg | range_sel | REGULATOR_BANK_SEL(2) | 
|  | 733 | | REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK, | 
|  | 734 | LDO_TEST_FINE_STEP_MASK | LDO_TEST_RANGE_SEL_MASK | 
|  | 735 | | REGULATOR_BANK_MASK | LDO_TEST_VPROG_UPDATE_MASK, | 
|  | 736 | &vreg->test_reg[2]); | 
|  | 737 | if (rc) | 
|  | 738 | goto bail; | 
|  | 739 | if (prev_reg != vreg->test_reg[2]) | 
|  | 740 | reg_changed = true; | 
|  | 741 |  | 
|  | 742 | /* Write range extension. */ | 
|  | 743 | prev_reg = vreg->test_reg[4]; | 
|  | 744 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 745 | range_ext | REGULATOR_BANK_SEL(4) | 
|  | 746 | | REGULATOR_BANK_WRITE, | 
|  | 747 | LDO_TEST_RANGE_EXT_MASK | REGULATOR_BANK_MASK, | 
|  | 748 | &vreg->test_reg[4]); | 
|  | 749 | if (rc) | 
|  | 750 | goto bail; | 
|  | 751 | if (prev_reg != vreg->test_reg[4]) | 
|  | 752 | reg_changed = true; | 
|  | 753 |  | 
|  | 754 | /* Write new voltage. */ | 
|  | 755 | if (reg_changed) { | 
|  | 756 | /* | 
|  | 757 | * Force a CTRL register write even if the value hasn't changed. | 
|  | 758 | * This is neccessary because range select, range extension, and | 
|  | 759 | * fine step will not update until a value is written into the | 
|  | 760 | * control register. | 
|  | 761 | */ | 
|  | 762 | rc = pm8xxx_vreg_masked_write_forced(vreg, vreg->ctrl_addr, | 
|  | 763 | vprog, LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg); | 
|  | 764 | } else { | 
|  | 765 | /* Only write to control register if new value is different. */ | 
|  | 766 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, vprog, | 
|  | 767 | LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg); | 
|  | 768 | } | 
|  | 769 | bail: | 
|  | 770 | mutex_unlock(&vreg->pc_lock); | 
|  | 771 |  | 
|  | 772 | if (rc) | 
|  | 773 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 774 | else { | 
|  | 775 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, uV); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 776 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 777 | } | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 778 |  | 
|  | 779 | return rc; | 
|  | 780 | } | 
|  | 781 |  | 
|  | 782 | static int pm8xxx_nldo_get_voltage(struct regulator_dev *rdev) | 
|  | 783 | { | 
|  | 784 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 785 | u8 vprog, fine_step_reg; | 
|  | 786 |  | 
|  | 787 | mutex_lock(&vreg->pc_lock); | 
|  | 788 |  | 
|  | 789 | fine_step_reg = vreg->test_reg[2] & LDO_TEST_FINE_STEP_MASK; | 
|  | 790 | vprog = vreg->ctrl_reg & LDO_CTRL_VPROG_MASK; | 
|  | 791 |  | 
|  | 792 | mutex_unlock(&vreg->pc_lock); | 
|  | 793 |  | 
|  | 794 | vprog = (vprog << 1) | (fine_step_reg >> LDO_TEST_FINE_STEP_SHIFT); | 
|  | 795 |  | 
|  | 796 | return NLDO_UV_FINE_STEP * vprog + NLDO_UV_MIN; | 
|  | 797 | } | 
|  | 798 |  | 
|  | 799 | static int pm8xxx_nldo_list_voltage(struct regulator_dev *rdev, | 
|  | 800 | unsigned selector) | 
|  | 801 | { | 
|  | 802 | if (selector >= NLDO_SET_POINTS) | 
|  | 803 | return 0; | 
|  | 804 |  | 
|  | 805 | return selector * NLDO_UV_FINE_STEP + NLDO_UV_MIN; | 
|  | 806 | } | 
|  | 807 |  | 
|  | 808 | static int pm8xxx_nldo_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 809 | int max_uV, unsigned *selector) | 
|  | 810 | { | 
|  | 811 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 812 | unsigned vprog, fine_step_reg, prev_reg; | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 813 | int rc, prev_uV; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 814 | int uV = min_uV; | 
|  | 815 |  | 
|  | 816 | if (uV < NLDO_UV_MIN && max_uV >= NLDO_UV_MIN) | 
|  | 817 | uV = NLDO_UV_MIN; | 
|  | 818 |  | 
|  | 819 | if (uV < NLDO_UV_MIN || uV > NLDO_UV_MAX) { | 
|  | 820 | vreg_err(vreg, | 
|  | 821 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 822 | min_uV, max_uV, NLDO_UV_MIN, NLDO_UV_MAX); | 
|  | 823 | return -EINVAL; | 
|  | 824 | } | 
|  | 825 |  | 
|  | 826 | vprog = (uV - NLDO_UV_MIN + NLDO_UV_FINE_STEP - 1) / NLDO_UV_FINE_STEP; | 
|  | 827 | uV = vprog * NLDO_UV_FINE_STEP + NLDO_UV_MIN; | 
|  | 828 | fine_step_reg = (vprog & 1) << LDO_TEST_FINE_STEP_SHIFT; | 
|  | 829 | vprog >>= 1; | 
|  | 830 |  | 
|  | 831 | if (uV > max_uV) { | 
|  | 832 | vreg_err(vreg, | 
|  | 833 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 834 | min_uV, max_uV); | 
|  | 835 | return -EINVAL; | 
|  | 836 | } | 
|  | 837 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 838 | prev_uV = pm8xxx_nldo_get_voltage(rdev); | 
|  | 839 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 840 | mutex_lock(&vreg->pc_lock); | 
|  | 841 |  | 
|  | 842 | /* Write fine step. */ | 
|  | 843 | prev_reg = vreg->test_reg[2]; | 
|  | 844 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 845 | fine_step_reg | REGULATOR_BANK_SEL(2) | 
|  | 846 | | REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK, | 
|  | 847 | LDO_TEST_FINE_STEP_MASK | REGULATOR_BANK_MASK | 
|  | 848 | | LDO_TEST_VPROG_UPDATE_MASK, | 
|  | 849 | &vreg->test_reg[2]); | 
|  | 850 | if (rc) | 
|  | 851 | goto bail; | 
|  | 852 |  | 
|  | 853 | /* Write new voltage. */ | 
|  | 854 | if (prev_reg != vreg->test_reg[2]) { | 
|  | 855 | /* | 
|  | 856 | * Force a CTRL register write even if the value hasn't changed. | 
|  | 857 | * This is neccessary because fine step will not update until a | 
|  | 858 | * value is written into the control register. | 
|  | 859 | */ | 
|  | 860 | rc = pm8xxx_vreg_masked_write_forced(vreg, vreg->ctrl_addr, | 
|  | 861 | vprog, LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg); | 
|  | 862 | } else { | 
|  | 863 | /* Only write to control register if new value is different. */ | 
|  | 864 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, vprog, | 
|  | 865 | LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg); | 
|  | 866 | } | 
|  | 867 | bail: | 
|  | 868 | mutex_unlock(&vreg->pc_lock); | 
|  | 869 |  | 
|  | 870 | if (rc) | 
|  | 871 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 872 | else { | 
|  | 873 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, uV); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 874 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 875 | } | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 876 |  | 
|  | 877 | return rc; | 
|  | 878 | } | 
|  | 879 |  | 
|  | 880 | static int _pm8xxx_nldo1200_get_voltage(struct pm8xxx_vreg *vreg) | 
|  | 881 | { | 
|  | 882 | int uV = 0; | 
|  | 883 | int vprog; | 
|  | 884 |  | 
|  | 885 | if (!NLDO1200_IN_ADVANCED_MODE(vreg)) { | 
|  | 886 | pr_warn("%s: currently in legacy mode; voltage unknown.\n", | 
|  | 887 | vreg->rdesc.name); | 
|  | 888 | return vreg->save_uV; | 
|  | 889 | } | 
|  | 890 |  | 
|  | 891 | vprog = vreg->ctrl_reg & NLDO1200_CTRL_VPROG_MASK; | 
|  | 892 |  | 
|  | 893 | if ((vreg->ctrl_reg & NLDO1200_CTRL_RANGE_MASK) | 
|  | 894 | == NLDO1200_CTRL_RANGE_LOW) | 
|  | 895 | uV = vprog * NLDO1200_LOW_UV_STEP + NLDO1200_LOW_UV_MIN; | 
|  | 896 | else | 
|  | 897 | uV = vprog * NLDO1200_HIGH_UV_STEP + NLDO1200_HIGH_UV_MIN; | 
|  | 898 |  | 
|  | 899 | return uV; | 
|  | 900 | } | 
|  | 901 |  | 
|  | 902 | static int pm8xxx_nldo1200_get_voltage(struct regulator_dev *rdev) | 
|  | 903 | { | 
|  | 904 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 905 |  | 
|  | 906 | return _pm8xxx_nldo1200_get_voltage(vreg); | 
|  | 907 | } | 
|  | 908 |  | 
|  | 909 | static int pm8xxx_nldo1200_list_voltage(struct regulator_dev *rdev, | 
|  | 910 | unsigned selector) | 
|  | 911 | { | 
|  | 912 | int uV; | 
|  | 913 |  | 
|  | 914 | if (selector >= NLDO1200_SET_POINTS) | 
|  | 915 | return 0; | 
|  | 916 |  | 
|  | 917 | if (selector < NLDO1200_LOW_SET_POINTS) | 
|  | 918 | uV = selector * NLDO1200_LOW_UV_STEP + NLDO1200_LOW_UV_MIN; | 
|  | 919 | else | 
|  | 920 | uV = (selector - NLDO1200_LOW_SET_POINTS) | 
|  | 921 | * NLDO1200_HIGH_UV_STEP | 
|  | 922 | + NLDO1200_HIGH_UV_MIN; | 
|  | 923 |  | 
|  | 924 | return uV; | 
|  | 925 | } | 
|  | 926 |  | 
|  | 927 | static int _pm8xxx_nldo1200_set_voltage(struct pm8xxx_vreg *vreg, int min_uV, | 
|  | 928 | int max_uV) | 
|  | 929 | { | 
|  | 930 | u8 vprog, range; | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 931 | int rc, prev_uV; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 932 | int uV = min_uV; | 
|  | 933 |  | 
|  | 934 | if (uV < NLDO1200_LOW_UV_MIN && max_uV >= NLDO1200_LOW_UV_MIN) | 
|  | 935 | uV = NLDO1200_LOW_UV_MIN; | 
|  | 936 |  | 
|  | 937 | if (uV < NLDO1200_LOW_UV_MIN || uV > NLDO1200_HIGH_UV_MAX) { | 
|  | 938 | vreg_err(vreg, | 
|  | 939 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 940 | min_uV, max_uV, NLDO_UV_MIN, NLDO_UV_MAX); | 
|  | 941 | return -EINVAL; | 
|  | 942 | } | 
|  | 943 |  | 
|  | 944 | if (uV > NLDO1200_LOW_UV_MAX) { | 
|  | 945 | vprog = (uV - NLDO1200_HIGH_UV_MIN + NLDO1200_HIGH_UV_STEP - 1) | 
|  | 946 | / NLDO1200_HIGH_UV_STEP; | 
|  | 947 | uV = vprog * NLDO1200_HIGH_UV_STEP + NLDO1200_HIGH_UV_MIN; | 
|  | 948 | vprog &= NLDO1200_CTRL_VPROG_MASK; | 
|  | 949 | range = NLDO1200_CTRL_RANGE_HIGH; | 
|  | 950 | } else { | 
|  | 951 | vprog = (uV - NLDO1200_LOW_UV_MIN + NLDO1200_LOW_UV_STEP - 1) | 
|  | 952 | / NLDO1200_LOW_UV_STEP; | 
|  | 953 | uV = vprog * NLDO1200_LOW_UV_STEP + NLDO1200_LOW_UV_MIN; | 
|  | 954 | vprog &= NLDO1200_CTRL_VPROG_MASK; | 
|  | 955 | range = NLDO1200_CTRL_RANGE_LOW; | 
|  | 956 | } | 
|  | 957 |  | 
|  | 958 | if (uV > max_uV) { | 
|  | 959 | vreg_err(vreg, | 
|  | 960 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 961 | min_uV, max_uV); | 
|  | 962 | return -EINVAL; | 
|  | 963 | } | 
|  | 964 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 965 | prev_uV = _pm8xxx_nldo1200_get_voltage(vreg); | 
|  | 966 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 967 | /* Set to advanced mode */ | 
|  | 968 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 969 | NLDO1200_ADVANCED_MODE | REGULATOR_BANK_SEL(2) | 
|  | 970 | | REGULATOR_BANK_WRITE, NLDO1200_ADVANCED_MODE_MASK | 
|  | 971 | | REGULATOR_BANK_MASK, &vreg->test_reg[2]); | 
|  | 972 | if (rc) | 
|  | 973 | goto bail; | 
|  | 974 |  | 
|  | 975 | /* Set voltage and range selection. */ | 
|  | 976 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, vprog | range, | 
|  | 977 | NLDO1200_CTRL_VPROG_MASK | NLDO1200_CTRL_RANGE_MASK, | 
|  | 978 | &vreg->ctrl_reg); | 
|  | 979 | if (rc) | 
|  | 980 | goto bail; | 
|  | 981 |  | 
|  | 982 | vreg->save_uV = uV; | 
|  | 983 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 984 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, uV); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 985 | bail: | 
|  | 986 | if (rc) | 
|  | 987 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 988 |  | 
|  | 989 | return rc; | 
|  | 990 | } | 
|  | 991 |  | 
|  | 992 | static int pm8xxx_nldo1200_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 993 | int max_uV, unsigned *selector) | 
|  | 994 | { | 
|  | 995 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 996 | int rc; | 
|  | 997 |  | 
|  | 998 | rc = _pm8xxx_nldo1200_set_voltage(vreg, min_uV, max_uV); | 
|  | 999 |  | 
|  | 1000 | if (!rc) | 
|  | 1001 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
|  | 1002 |  | 
|  | 1003 | return rc; | 
|  | 1004 | } | 
|  | 1005 |  | 
|  | 1006 | static int pm8xxx_smps_get_voltage_advanced(struct pm8xxx_vreg *vreg) | 
|  | 1007 | { | 
|  | 1008 | u8 vprog, band; | 
|  | 1009 | int uV = 0; | 
|  | 1010 |  | 
|  | 1011 | vprog = vreg->ctrl_reg & SMPS_ADVANCED_VPROG_MASK; | 
|  | 1012 | band = vreg->ctrl_reg & SMPS_ADVANCED_BAND_MASK; | 
|  | 1013 |  | 
|  | 1014 | if (band == SMPS_ADVANCED_BAND_1) | 
|  | 1015 | uV = vprog * SMPS_BAND1_UV_STEP + SMPS_BAND1_UV_MIN; | 
|  | 1016 | else if (band == SMPS_ADVANCED_BAND_2) | 
|  | 1017 | uV = vprog * SMPS_BAND2_UV_STEP + SMPS_BAND2_UV_MIN; | 
|  | 1018 | else if (band == SMPS_ADVANCED_BAND_3) | 
|  | 1019 | uV = vprog * SMPS_BAND3_UV_STEP + SMPS_BAND3_UV_MIN; | 
|  | 1020 | else if (vreg->save_uV > 0) | 
|  | 1021 | uV = vreg->save_uV; | 
|  | 1022 | else | 
|  | 1023 | uV = VOLTAGE_UNKNOWN; | 
|  | 1024 |  | 
|  | 1025 | return uV; | 
|  | 1026 | } | 
|  | 1027 |  | 
|  | 1028 | static int pm8xxx_smps_get_voltage_legacy(struct pm8xxx_vreg *vreg) | 
|  | 1029 | { | 
|  | 1030 | u8 vlow, vref, vprog; | 
|  | 1031 | int uV; | 
|  | 1032 |  | 
|  | 1033 | vlow = vreg->test_reg[1] & SMPS_LEGACY_VLOW_SEL_MASK; | 
|  | 1034 | vref = vreg->ctrl_reg & SMPS_LEGACY_VREF_SEL_MASK; | 
|  | 1035 | vprog = vreg->ctrl_reg & SMPS_LEGACY_VPROG_MASK; | 
|  | 1036 |  | 
|  | 1037 | if (vlow && vref) { | 
|  | 1038 | /* mode 3 */ | 
|  | 1039 | uV = vprog * SMPS_MODE3_UV_STEP + SMPS_MODE3_UV_MIN; | 
|  | 1040 | } else if (vref) { | 
|  | 1041 | /* mode 2 */ | 
|  | 1042 | uV = vprog * SMPS_MODE2_UV_STEP + SMPS_MODE2_UV_MIN; | 
|  | 1043 | } else { | 
|  | 1044 | /* mode 1 */ | 
|  | 1045 | uV = vprog * SMPS_MODE1_UV_STEP + SMPS_MODE1_UV_MIN; | 
|  | 1046 | } | 
|  | 1047 |  | 
|  | 1048 | return uV; | 
|  | 1049 | } | 
|  | 1050 |  | 
|  | 1051 | static int _pm8xxx_smps_get_voltage(struct pm8xxx_vreg *vreg) | 
|  | 1052 | { | 
|  | 1053 | if (SMPS_IN_ADVANCED_MODE(vreg)) | 
|  | 1054 | return pm8xxx_smps_get_voltage_advanced(vreg); | 
|  | 1055 |  | 
|  | 1056 | return pm8xxx_smps_get_voltage_legacy(vreg); | 
|  | 1057 | } | 
|  | 1058 |  | 
|  | 1059 | static int pm8xxx_smps_list_voltage(struct regulator_dev *rdev, | 
|  | 1060 | unsigned selector) | 
|  | 1061 | { | 
|  | 1062 | int uV; | 
|  | 1063 |  | 
|  | 1064 | if (selector >= SMPS_ADVANCED_SET_POINTS) | 
|  | 1065 | return 0; | 
|  | 1066 |  | 
|  | 1067 | if (selector < SMPS_BAND1_SET_POINTS) | 
|  | 1068 | uV = selector * SMPS_BAND1_UV_STEP + SMPS_BAND1_UV_MIN; | 
|  | 1069 | else if (selector < (SMPS_BAND1_SET_POINTS + SMPS_BAND2_SET_POINTS)) | 
|  | 1070 | uV = (selector - SMPS_BAND1_SET_POINTS) * SMPS_BAND2_UV_STEP | 
|  | 1071 | + SMPS_BAND2_UV_MIN; | 
|  | 1072 | else | 
|  | 1073 | uV = (selector - SMPS_BAND1_SET_POINTS - SMPS_BAND2_SET_POINTS) | 
|  | 1074 | * SMPS_BAND3_UV_STEP | 
|  | 1075 | + SMPS_BAND3_UV_MIN; | 
|  | 1076 |  | 
|  | 1077 | return uV; | 
|  | 1078 | } | 
|  | 1079 |  | 
|  | 1080 | static int pm8xxx_smps_get_voltage(struct regulator_dev *rdev) | 
|  | 1081 | { | 
|  | 1082 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1083 | int uV; | 
|  | 1084 |  | 
|  | 1085 | mutex_lock(&vreg->pc_lock); | 
|  | 1086 | uV = _pm8xxx_smps_get_voltage(vreg); | 
|  | 1087 | mutex_unlock(&vreg->pc_lock); | 
|  | 1088 |  | 
|  | 1089 | return uV; | 
|  | 1090 | } | 
|  | 1091 |  | 
|  | 1092 | static int pm8xxx_smps_set_voltage_advanced(struct pm8xxx_vreg *vreg, | 
|  | 1093 | int min_uV, int max_uV, int force_on) | 
|  | 1094 | { | 
|  | 1095 | u8 vprog, band; | 
|  | 1096 | int rc; | 
|  | 1097 | int uV = min_uV; | 
|  | 1098 |  | 
|  | 1099 | if (uV < SMPS_BAND1_UV_MIN && max_uV >= SMPS_BAND1_UV_MIN) | 
|  | 1100 | uV = SMPS_BAND1_UV_MIN; | 
|  | 1101 |  | 
|  | 1102 | if (uV < SMPS_BAND1_UV_MIN || uV > SMPS_BAND3_UV_MAX) { | 
|  | 1103 | vreg_err(vreg, | 
|  | 1104 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 1105 | min_uV, max_uV, SMPS_BAND1_UV_MIN, SMPS_BAND3_UV_MAX); | 
|  | 1106 | return -EINVAL; | 
|  | 1107 | } | 
|  | 1108 |  | 
|  | 1109 | if (uV > SMPS_BAND2_UV_MAX) { | 
|  | 1110 | vprog = (uV - SMPS_BAND3_UV_MIN + SMPS_BAND3_UV_STEP - 1) | 
|  | 1111 | / SMPS_BAND3_UV_STEP; | 
|  | 1112 | band = SMPS_ADVANCED_BAND_3; | 
|  | 1113 | uV = SMPS_BAND3_UV_MIN + vprog * SMPS_BAND3_UV_STEP; | 
|  | 1114 | } else if (uV > SMPS_BAND1_UV_MAX) { | 
|  | 1115 | vprog = (uV - SMPS_BAND2_UV_MIN + SMPS_BAND2_UV_STEP - 1) | 
|  | 1116 | / SMPS_BAND2_UV_STEP; | 
|  | 1117 | band = SMPS_ADVANCED_BAND_2; | 
|  | 1118 | uV = SMPS_BAND2_UV_MIN + vprog * SMPS_BAND2_UV_STEP; | 
|  | 1119 | } else { | 
|  | 1120 | vprog = (uV - SMPS_BAND1_UV_MIN + SMPS_BAND1_UV_STEP - 1) | 
|  | 1121 | / SMPS_BAND1_UV_STEP; | 
|  | 1122 | band = SMPS_ADVANCED_BAND_1; | 
|  | 1123 | uV = SMPS_BAND1_UV_MIN + vprog * SMPS_BAND1_UV_STEP; | 
|  | 1124 | } | 
|  | 1125 |  | 
|  | 1126 | if (uV > max_uV) { | 
|  | 1127 | vreg_err(vreg, | 
|  | 1128 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 1129 | min_uV, max_uV); | 
|  | 1130 | return -EINVAL; | 
|  | 1131 | } | 
|  | 1132 |  | 
|  | 1133 | /* Do not set band if regulator currently disabled. */ | 
|  | 1134 | if (!_pm8xxx_vreg_is_enabled(vreg) && !force_on) | 
|  | 1135 | band = SMPS_ADVANCED_BAND_OFF; | 
|  | 1136 |  | 
|  | 1137 | /* Set advanced mode bit to 1. */ | 
|  | 1138 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, SMPS_ADVANCED_MODE | 
|  | 1139 | | REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7), | 
|  | 1140 | SMPS_ADVANCED_MODE_MASK | REGULATOR_BANK_MASK, | 
|  | 1141 | &vreg->test_reg[7]); | 
|  | 1142 | if (rc) | 
|  | 1143 | goto bail; | 
|  | 1144 |  | 
|  | 1145 | /* Set voltage and voltage band. */ | 
|  | 1146 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, band | vprog, | 
|  | 1147 | SMPS_ADVANCED_BAND_MASK | SMPS_ADVANCED_VPROG_MASK, | 
|  | 1148 | &vreg->ctrl_reg); | 
|  | 1149 | if (rc) | 
|  | 1150 | goto bail; | 
|  | 1151 |  | 
|  | 1152 | vreg->save_uV = uV; | 
|  | 1153 |  | 
|  | 1154 | bail: | 
|  | 1155 | if (rc) | 
|  | 1156 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1157 |  | 
|  | 1158 | return rc; | 
|  | 1159 | } | 
|  | 1160 |  | 
|  | 1161 | static int pm8xxx_smps_set_voltage_legacy(struct pm8xxx_vreg *vreg, int min_uV, | 
|  | 1162 | int max_uV) | 
|  | 1163 | { | 
|  | 1164 | u8 vlow, vref, vprog, pd, en; | 
|  | 1165 | int rc; | 
|  | 1166 | int uV = min_uV; | 
|  | 1167 |  | 
|  | 1168 | if (uV < SMPS_MODE3_UV_MIN && max_uV >= SMPS_MODE3_UV_MIN) | 
|  | 1169 | uV = SMPS_MODE3_UV_MIN; | 
|  | 1170 |  | 
|  | 1171 | if (uV < SMPS_MODE3_UV_MIN || uV > SMPS_MODE1_UV_MAX) { | 
|  | 1172 | vreg_err(vreg, | 
|  | 1173 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 1174 | min_uV, max_uV, SMPS_MODE3_UV_MIN, SMPS_MODE1_UV_MAX); | 
|  | 1175 | return -EINVAL; | 
|  | 1176 | } | 
|  | 1177 |  | 
|  | 1178 | if (uV > SMPS_MODE2_UV_MAX) { | 
|  | 1179 | vprog = (uV - SMPS_MODE1_UV_MIN + SMPS_MODE1_UV_STEP - 1) | 
|  | 1180 | / SMPS_MODE1_UV_STEP; | 
|  | 1181 | vref = 0; | 
|  | 1182 | vlow = 0; | 
|  | 1183 | uV = SMPS_MODE1_UV_MIN + vprog * SMPS_MODE1_UV_STEP; | 
|  | 1184 | } else if (uV > SMPS_MODE3_UV_MAX) { | 
|  | 1185 | vprog = (uV - SMPS_MODE2_UV_MIN + SMPS_MODE2_UV_STEP - 1) | 
|  | 1186 | / SMPS_MODE2_UV_STEP; | 
|  | 1187 | vref = SMPS_LEGACY_VREF_SEL_MASK; | 
|  | 1188 | vlow = 0; | 
|  | 1189 | uV = SMPS_MODE2_UV_MIN + vprog * SMPS_MODE2_UV_STEP; | 
|  | 1190 | } else { | 
|  | 1191 | vprog = (uV - SMPS_MODE3_UV_MIN + SMPS_MODE3_UV_STEP - 1) | 
|  | 1192 | / SMPS_MODE3_UV_STEP; | 
|  | 1193 | vref = SMPS_LEGACY_VREF_SEL_MASK; | 
|  | 1194 | vlow = SMPS_LEGACY_VLOW_SEL_MASK; | 
|  | 1195 | uV = SMPS_MODE3_UV_MIN + vprog * SMPS_MODE3_UV_STEP; | 
|  | 1196 | } | 
|  | 1197 |  | 
|  | 1198 | if (uV > max_uV) { | 
|  | 1199 | vreg_err(vreg, | 
|  | 1200 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 1201 | min_uV, max_uV); | 
|  | 1202 | return -EINVAL; | 
|  | 1203 | } | 
|  | 1204 |  | 
|  | 1205 | /* set vlow bit for ultra low voltage mode */ | 
|  | 1206 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1207 | vlow | REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(1), | 
|  | 1208 | REGULATOR_BANK_MASK | SMPS_LEGACY_VLOW_SEL_MASK, | 
|  | 1209 | &vreg->test_reg[1]); | 
|  | 1210 | if (rc) | 
|  | 1211 | goto bail; | 
|  | 1212 |  | 
|  | 1213 | /* Set advanced mode bit to 0. */ | 
|  | 1214 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, SMPS_LEGACY_MODE | 
|  | 1215 | | REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7), | 
|  | 1216 | SMPS_ADVANCED_MODE_MASK | REGULATOR_BANK_MASK, | 
|  | 1217 | &vreg->test_reg[7]); | 
|  | 1218 | if (rc) | 
|  | 1219 | goto bail; | 
|  | 1220 |  | 
|  | 1221 | en = (_pm8xxx_vreg_is_enabled(vreg) ? SMPS_LEGACY_ENABLE : 0); | 
|  | 1222 | pd = (vreg->pdata.pull_down_enable ? SMPS_LEGACY_PULL_DOWN_ENABLE : 0); | 
|  | 1223 |  | 
|  | 1224 | /* Set voltage (and the rest of the control register). */ | 
|  | 1225 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1226 | en | pd | vref | vprog, | 
|  | 1227 | SMPS_LEGACY_ENABLE_MASK | SMPS_LEGACY_PULL_DOWN_ENABLE | 
|  | 1228 | | SMPS_LEGACY_VREF_SEL_MASK | SMPS_LEGACY_VPROG_MASK, | 
|  | 1229 | &vreg->ctrl_reg); | 
|  | 1230 |  | 
|  | 1231 | vreg->save_uV = uV; | 
|  | 1232 |  | 
|  | 1233 | bail: | 
|  | 1234 | if (rc) | 
|  | 1235 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1236 |  | 
|  | 1237 | return rc; | 
|  | 1238 | } | 
|  | 1239 |  | 
|  | 1240 | static int pm8xxx_smps_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 1241 | int max_uV, unsigned *selector) | 
|  | 1242 | { | 
|  | 1243 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1244 | int rc = 0; | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1245 | int prev_uV, new_uV; | 
|  | 1246 |  | 
|  | 1247 | prev_uV = pm8xxx_smps_get_voltage(rdev); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1248 |  | 
|  | 1249 | mutex_lock(&vreg->pc_lock); | 
|  | 1250 |  | 
|  | 1251 | if (SMPS_IN_ADVANCED_MODE(vreg) || !pm8xxx_vreg_is_pin_controlled(vreg)) | 
|  | 1252 | rc = pm8xxx_smps_set_voltage_advanced(vreg, min_uV, max_uV, 0); | 
|  | 1253 | else | 
|  | 1254 | rc = pm8xxx_smps_set_voltage_legacy(vreg, min_uV, max_uV); | 
|  | 1255 |  | 
|  | 1256 | mutex_unlock(&vreg->pc_lock); | 
|  | 1257 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1258 | new_uV = pm8xxx_smps_get_voltage(rdev); | 
|  | 1259 |  | 
|  | 1260 | if (!rc) { | 
|  | 1261 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, new_uV); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1262 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1263 | } | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1264 |  | 
|  | 1265 | return rc; | 
|  | 1266 | } | 
|  | 1267 |  | 
|  | 1268 | static int _pm8xxx_ftsmps_get_voltage(struct pm8xxx_vreg *vreg) | 
|  | 1269 | { | 
|  | 1270 | u8 vprog, band; | 
|  | 1271 | int uV = 0; | 
|  | 1272 |  | 
|  | 1273 | if ((vreg->test_reg[0] & FTSMPS_CNFG1_PM_MASK) == FTSMPS_CNFG1_PM_PFM) { | 
|  | 1274 | vprog = vreg->pfm_ctrl_reg & FTSMPS_VCTRL_VPROG_MASK; | 
|  | 1275 | band = vreg->pfm_ctrl_reg & FTSMPS_VCTRL_BAND_MASK; | 
|  | 1276 | if (band == FTSMPS_VCTRL_BAND_OFF && vprog == 0) { | 
|  | 1277 | /* PWM_VCTRL overrides PFM_VCTRL */ | 
|  | 1278 | vprog = vreg->ctrl_reg & FTSMPS_VCTRL_VPROG_MASK; | 
|  | 1279 | band = vreg->ctrl_reg & FTSMPS_VCTRL_BAND_MASK; | 
|  | 1280 | } | 
|  | 1281 | } else { | 
|  | 1282 | vprog = vreg->ctrl_reg & FTSMPS_VCTRL_VPROG_MASK; | 
|  | 1283 | band = vreg->ctrl_reg & FTSMPS_VCTRL_BAND_MASK; | 
|  | 1284 | } | 
|  | 1285 |  | 
|  | 1286 | if (band == FTSMPS_VCTRL_BAND_1) | 
|  | 1287 | uV = vprog * FTSMPS_BAND1_UV_PHYS_STEP + FTSMPS_BAND1_UV_MIN; | 
|  | 1288 | else if (band == FTSMPS_VCTRL_BAND_2) | 
|  | 1289 | uV = vprog * FTSMPS_BAND2_UV_STEP + FTSMPS_BAND2_UV_MIN; | 
|  | 1290 | else if (band == FTSMPS_VCTRL_BAND_3) | 
|  | 1291 | uV = vprog * FTSMPS_BAND3_UV_STEP + FTSMPS_BAND3_UV_MIN; | 
|  | 1292 | else if (vreg->save_uV > 0) | 
|  | 1293 | uV = vreg->save_uV; | 
|  | 1294 | else | 
|  | 1295 | uV = VOLTAGE_UNKNOWN; | 
|  | 1296 |  | 
|  | 1297 | return uV; | 
|  | 1298 | } | 
|  | 1299 |  | 
|  | 1300 | static int pm8xxx_ftsmps_get_voltage(struct regulator_dev *rdev) | 
|  | 1301 | { | 
|  | 1302 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1303 |  | 
|  | 1304 | return _pm8xxx_ftsmps_get_voltage(vreg); | 
|  | 1305 | } | 
|  | 1306 |  | 
|  | 1307 | static int pm8xxx_ftsmps_list_voltage(struct regulator_dev *rdev, | 
|  | 1308 | unsigned selector) | 
|  | 1309 | { | 
|  | 1310 | int uV; | 
|  | 1311 |  | 
|  | 1312 | if (selector >= FTSMPS_SET_POINTS) | 
|  | 1313 | return 0; | 
|  | 1314 |  | 
|  | 1315 | if (selector < FTSMPS_BAND1_SET_POINTS) | 
|  | 1316 | uV = selector * FTSMPS_BAND1_UV_LOG_STEP + FTSMPS_BAND1_UV_MIN; | 
|  | 1317 | else if (selector < (FTSMPS_BAND1_SET_POINTS + FTSMPS_BAND2_SET_POINTS)) | 
|  | 1318 | uV = (selector - FTSMPS_BAND1_SET_POINTS) * FTSMPS_BAND2_UV_STEP | 
|  | 1319 | + FTSMPS_BAND2_UV_MIN; | 
|  | 1320 | else | 
|  | 1321 | uV = (selector - FTSMPS_BAND1_SET_POINTS | 
|  | 1322 | - FTSMPS_BAND2_SET_POINTS) | 
|  | 1323 | * FTSMPS_BAND3_UV_STEP | 
|  | 1324 | + FTSMPS_BAND3_UV_SET_POINT_MIN; | 
|  | 1325 |  | 
|  | 1326 | return uV; | 
|  | 1327 | } | 
|  | 1328 |  | 
|  | 1329 | static int _pm8xxx_ftsmps_set_voltage(struct pm8xxx_vreg *vreg, int min_uV, | 
|  | 1330 | int max_uV, int force_on) | 
|  | 1331 | { | 
|  | 1332 | int rc = 0; | 
|  | 1333 | u8 vprog, band; | 
|  | 1334 | int uV = min_uV; | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1335 | int prev_uV; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1336 |  | 
|  | 1337 | if (uV < FTSMPS_BAND1_UV_MIN && max_uV >= FTSMPS_BAND1_UV_MIN) | 
|  | 1338 | uV = FTSMPS_BAND1_UV_MIN; | 
|  | 1339 |  | 
|  | 1340 | if (uV < FTSMPS_BAND1_UV_MIN || uV > FTSMPS_BAND3_UV_MAX) { | 
|  | 1341 | vreg_err(vreg, | 
|  | 1342 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 1343 | min_uV, max_uV, FTSMPS_BAND1_UV_MIN, | 
|  | 1344 | FTSMPS_BAND3_UV_MAX); | 
|  | 1345 | return -EINVAL; | 
|  | 1346 | } | 
|  | 1347 |  | 
|  | 1348 | /* Round up for set points in the gaps between bands. */ | 
|  | 1349 | if (uV > FTSMPS_BAND1_UV_MAX && uV < FTSMPS_BAND2_UV_MIN) | 
|  | 1350 | uV = FTSMPS_BAND2_UV_MIN; | 
|  | 1351 | else if (uV > FTSMPS_BAND2_UV_MAX | 
|  | 1352 | && uV < FTSMPS_BAND3_UV_SET_POINT_MIN) | 
|  | 1353 | uV = FTSMPS_BAND3_UV_SET_POINT_MIN; | 
|  | 1354 |  | 
|  | 1355 | if (uV > FTSMPS_BAND2_UV_MAX) { | 
|  | 1356 | vprog = (uV - FTSMPS_BAND3_UV_MIN + FTSMPS_BAND3_UV_STEP - 1) | 
|  | 1357 | / FTSMPS_BAND3_UV_STEP; | 
|  | 1358 | band = FTSMPS_VCTRL_BAND_3; | 
|  | 1359 | uV = FTSMPS_BAND3_UV_MIN + vprog * FTSMPS_BAND3_UV_STEP; | 
|  | 1360 | } else if (uV > FTSMPS_BAND1_UV_MAX) { | 
|  | 1361 | vprog = (uV - FTSMPS_BAND2_UV_MIN + FTSMPS_BAND2_UV_STEP - 1) | 
|  | 1362 | / FTSMPS_BAND2_UV_STEP; | 
|  | 1363 | band = FTSMPS_VCTRL_BAND_2; | 
|  | 1364 | uV = FTSMPS_BAND2_UV_MIN + vprog * FTSMPS_BAND2_UV_STEP; | 
|  | 1365 | } else { | 
|  | 1366 | vprog = (uV - FTSMPS_BAND1_UV_MIN | 
|  | 1367 | + FTSMPS_BAND1_UV_LOG_STEP - 1) | 
|  | 1368 | / FTSMPS_BAND1_UV_LOG_STEP; | 
|  | 1369 | uV = FTSMPS_BAND1_UV_MIN + vprog * FTSMPS_BAND1_UV_LOG_STEP; | 
|  | 1370 | vprog *= FTSMPS_BAND1_UV_LOG_STEP / FTSMPS_BAND1_UV_PHYS_STEP; | 
|  | 1371 | band = FTSMPS_VCTRL_BAND_1; | 
|  | 1372 | } | 
|  | 1373 |  | 
|  | 1374 | if (uV > max_uV) { | 
|  | 1375 | vreg_err(vreg, | 
|  | 1376 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 1377 | min_uV, max_uV); | 
|  | 1378 | return -EINVAL; | 
|  | 1379 | } | 
|  | 1380 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1381 | prev_uV = _pm8xxx_ftsmps_get_voltage(vreg); | 
|  | 1382 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1383 | /* | 
|  | 1384 | * Do not set voltage if regulator is currently disabled because doing | 
|  | 1385 | * so will enable it. | 
|  | 1386 | */ | 
|  | 1387 | if (_pm8xxx_vreg_is_enabled(vreg) || force_on) { | 
|  | 1388 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1389 | band | vprog, | 
|  | 1390 | FTSMPS_VCTRL_BAND_MASK | FTSMPS_VCTRL_VPROG_MASK, | 
|  | 1391 | &vreg->ctrl_reg); | 
|  | 1392 | if (rc) | 
|  | 1393 | goto bail; | 
|  | 1394 |  | 
|  | 1395 | /* Program PFM_VCTRL as 0x00 so that PWM_VCTRL overrides it. */ | 
|  | 1396 | rc = pm8xxx_vreg_masked_write(vreg, vreg->pfm_ctrl_addr, 0x00, | 
|  | 1397 | FTSMPS_VCTRL_BAND_MASK | FTSMPS_VCTRL_VPROG_MASK, | 
|  | 1398 | &vreg->pfm_ctrl_reg); | 
|  | 1399 | if (rc) | 
|  | 1400 | goto bail; | 
|  | 1401 | } | 
|  | 1402 |  | 
|  | 1403 | vreg->save_uV = uV; | 
|  | 1404 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1405 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, uV); | 
|  | 1406 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1407 | bail: | 
|  | 1408 | if (rc) | 
|  | 1409 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1410 |  | 
|  | 1411 | return rc; | 
|  | 1412 | } | 
|  | 1413 |  | 
|  | 1414 | static int pm8xxx_ftsmps_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 1415 | int max_uV, unsigned *selector) | 
|  | 1416 | { | 
|  | 1417 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1418 | int rc; | 
|  | 1419 |  | 
|  | 1420 | rc = _pm8xxx_ftsmps_set_voltage(vreg, min_uV, max_uV, 0); | 
|  | 1421 |  | 
|  | 1422 | if (!rc) | 
|  | 1423 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
|  | 1424 |  | 
|  | 1425 | return rc; | 
|  | 1426 | } | 
|  | 1427 |  | 
|  | 1428 | static int pm8xxx_ncp_get_voltage(struct regulator_dev *rdev) | 
|  | 1429 | { | 
|  | 1430 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1431 | u8 vprog; | 
|  | 1432 |  | 
|  | 1433 | vprog = vreg->ctrl_reg & NCP_VPROG_MASK; | 
|  | 1434 |  | 
|  | 1435 | return NCP_UV_MIN + vprog * NCP_UV_STEP; | 
|  | 1436 | } | 
|  | 1437 |  | 
|  | 1438 | static int pm8xxx_ncp_list_voltage(struct regulator_dev *rdev, | 
|  | 1439 | unsigned selector) | 
|  | 1440 | { | 
|  | 1441 | if (selector >= NCP_SET_POINTS) | 
|  | 1442 | return 0; | 
|  | 1443 |  | 
|  | 1444 | return selector * NCP_UV_STEP + NCP_UV_MIN; | 
|  | 1445 | } | 
|  | 1446 |  | 
|  | 1447 | static int pm8xxx_ncp_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 1448 | int max_uV, unsigned *selector) | 
|  | 1449 | { | 
|  | 1450 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1451 | int rc, prev_uV; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1452 | int uV = min_uV; | 
|  | 1453 | u8 val; | 
|  | 1454 |  | 
|  | 1455 | if (uV < NCP_UV_MIN && max_uV >= NCP_UV_MIN) | 
|  | 1456 | uV = NCP_UV_MIN; | 
|  | 1457 |  | 
|  | 1458 | if (uV < NCP_UV_MIN || uV > NCP_UV_MAX) { | 
|  | 1459 | vreg_err(vreg, | 
|  | 1460 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 1461 | min_uV, max_uV, NCP_UV_MIN, NCP_UV_MAX); | 
|  | 1462 | return -EINVAL; | 
|  | 1463 | } | 
|  | 1464 |  | 
|  | 1465 | val = (uV - NCP_UV_MIN + NCP_UV_STEP - 1) / NCP_UV_STEP; | 
|  | 1466 | uV = val * NCP_UV_STEP + NCP_UV_MIN; | 
|  | 1467 |  | 
|  | 1468 | if (uV > max_uV) { | 
|  | 1469 | vreg_err(vreg, | 
|  | 1470 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 1471 | min_uV, max_uV); | 
|  | 1472 | return -EINVAL; | 
|  | 1473 | } | 
|  | 1474 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1475 | prev_uV = pm8xxx_ncp_get_voltage(rdev); | 
|  | 1476 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1477 | /* voltage setting */ | 
|  | 1478 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val, | 
|  | 1479 | NCP_VPROG_MASK, &vreg->ctrl_reg); | 
|  | 1480 | if (rc) | 
|  | 1481 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1482 | else { | 
|  | 1483 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, uV); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1484 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1485 | } | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1486 |  | 
|  | 1487 | return rc; | 
|  | 1488 | } | 
|  | 1489 |  | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 1490 | static int pm8xxx_boost_get_voltage(struct regulator_dev *rdev) | 
|  | 1491 | { | 
|  | 1492 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1493 | u8 vprog; | 
|  | 1494 |  | 
|  | 1495 | vprog = vreg->ctrl_reg & BOOST_VPROG_MASK; | 
|  | 1496 |  | 
|  | 1497 | return BOOST_UV_STEP * vprog + BOOST_UV_MIN; | 
|  | 1498 | } | 
|  | 1499 |  | 
|  | 1500 | static int pm8xxx_boost_list_voltage(struct regulator_dev *rdev, | 
|  | 1501 | unsigned selector) | 
|  | 1502 | { | 
|  | 1503 | if (selector >= BOOST_SET_POINTS) | 
|  | 1504 | return 0; | 
|  | 1505 |  | 
|  | 1506 | return selector * BOOST_UV_STEP + BOOST_UV_MIN; | 
|  | 1507 | } | 
|  | 1508 |  | 
|  | 1509 | static int pm8xxx_boost_set_voltage(struct regulator_dev *rdev, int min_uV, | 
|  | 1510 | int max_uV, unsigned *selector) | 
|  | 1511 | { | 
|  | 1512 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1513 | int rc, prev_uV; | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 1514 | int uV = min_uV; | 
|  | 1515 | u8 val; | 
|  | 1516 |  | 
|  | 1517 | if (uV < BOOST_UV_MIN && max_uV >= BOOST_UV_MIN) | 
|  | 1518 | uV = BOOST_UV_MIN; | 
|  | 1519 |  | 
|  | 1520 | if (uV < BOOST_UV_MIN || uV > BOOST_UV_MAX) { | 
|  | 1521 | vreg_err(vreg, | 
|  | 1522 | "request v=[%d, %d] is outside possible v=[%d, %d]\n", | 
|  | 1523 | min_uV, max_uV, BOOST_UV_MIN, BOOST_UV_MAX); | 
|  | 1524 | return -EINVAL; | 
|  | 1525 | } | 
|  | 1526 |  | 
|  | 1527 | val = (uV - BOOST_UV_MIN + BOOST_UV_STEP - 1) / BOOST_UV_STEP; | 
|  | 1528 | uV = val * BOOST_UV_STEP + BOOST_UV_MIN; | 
|  | 1529 |  | 
|  | 1530 | if (uV > max_uV) { | 
|  | 1531 | vreg_err(vreg, | 
|  | 1532 | "request v=[%d, %d] cannot be met by any set point\n", | 
|  | 1533 | min_uV, max_uV); | 
|  | 1534 | return -EINVAL; | 
|  | 1535 | } | 
|  | 1536 |  | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1537 | prev_uV = pm8xxx_boost_get_voltage(rdev); | 
|  | 1538 |  | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 1539 | /* voltage setting */ | 
|  | 1540 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val, | 
|  | 1541 | BOOST_VPROG_MASK, &vreg->ctrl_reg); | 
|  | 1542 | if (rc) | 
|  | 1543 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1544 | else { | 
|  | 1545 | pm8xxx_vreg_delay_for_slew(vreg, prev_uV, uV); | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 1546 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE); | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 1547 | } | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 1548 |  | 
|  | 1549 | return rc; | 
|  | 1550 | } | 
|  | 1551 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 1552 | static unsigned int pm8xxx_ldo_get_mode(struct regulator_dev *rdev) | 
|  | 1553 | { | 
|  | 1554 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1555 | unsigned int mode = 0; | 
|  | 1556 |  | 
|  | 1557 | mutex_lock(&vreg->pc_lock); | 
|  | 1558 | mode = vreg->mode; | 
|  | 1559 | mutex_unlock(&vreg->pc_lock); | 
|  | 1560 |  | 
|  | 1561 | return mode; | 
|  | 1562 | } | 
|  | 1563 |  | 
|  | 1564 | static int pm8xxx_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) | 
|  | 1565 | { | 
|  | 1566 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1567 | int rc = 0; | 
|  | 1568 |  | 
|  | 1569 | if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_IDLE) { | 
|  | 1570 | vreg_err(vreg, "invalid mode: %u\n", mode); | 
|  | 1571 | return -EINVAL; | 
|  | 1572 | } | 
|  | 1573 |  | 
|  | 1574 | mutex_lock(&vreg->pc_lock); | 
|  | 1575 |  | 
|  | 1576 | if (mode == REGULATOR_MODE_NORMAL | 
|  | 1577 | || (vreg->is_enabled_pc | 
|  | 1578 | && vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE)) { | 
|  | 1579 | /* HPM */ | 
|  | 1580 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1581 | LDO_CTRL_PM_HPM, LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 1582 | } else { | 
|  | 1583 | /* LPM */ | 
|  | 1584 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1585 | LDO_CTRL_PM_LPM, LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 1586 | if (rc) | 
|  | 1587 | goto bail; | 
|  | 1588 |  | 
|  | 1589 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1590 | LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE | 
|  | 1591 | | REGULATOR_BANK_SEL(0), | 
|  | 1592 | LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK, | 
|  | 1593 | &vreg->test_reg[0]); | 
|  | 1594 | } | 
|  | 1595 |  | 
|  | 1596 | bail: | 
|  | 1597 | if (!rc) | 
|  | 1598 | vreg->mode = mode; | 
|  | 1599 |  | 
|  | 1600 | mutex_unlock(&vreg->pc_lock); | 
|  | 1601 |  | 
|  | 1602 | if (rc) | 
|  | 1603 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1604 | else | 
|  | 1605 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_MODE); | 
|  | 1606 |  | 
|  | 1607 | return rc; | 
|  | 1608 | } | 
|  | 1609 |  | 
|  | 1610 | static unsigned int pm8xxx_nldo1200_get_mode(struct regulator_dev *rdev) | 
|  | 1611 | { | 
|  | 1612 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1613 | unsigned int mode = 0; | 
|  | 1614 |  | 
|  | 1615 | if (NLDO1200_IN_ADVANCED_MODE(vreg)) { | 
|  | 1616 | /* Advanced mode */ | 
|  | 1617 | if ((vreg->test_reg[2] & NLDO1200_ADVANCED_PM_MASK) | 
|  | 1618 | == NLDO1200_ADVANCED_PM_LPM) | 
|  | 1619 | mode = REGULATOR_MODE_IDLE; | 
|  | 1620 | else | 
|  | 1621 | mode = REGULATOR_MODE_NORMAL; | 
|  | 1622 | } else { | 
|  | 1623 | /* Legacy mode */ | 
|  | 1624 | if ((vreg->ctrl_reg & NLDO1200_LEGACY_PM_MASK) | 
|  | 1625 | == NLDO1200_LEGACY_PM_LPM) | 
|  | 1626 | mode = REGULATOR_MODE_IDLE; | 
|  | 1627 | else | 
|  | 1628 | mode = REGULATOR_MODE_NORMAL; | 
|  | 1629 | } | 
|  | 1630 |  | 
|  | 1631 | return mode; | 
|  | 1632 | } | 
|  | 1633 |  | 
|  | 1634 | static int pm8xxx_nldo1200_set_mode(struct regulator_dev *rdev, | 
|  | 1635 | unsigned int mode) | 
|  | 1636 | { | 
|  | 1637 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1638 | int rc = 0; | 
|  | 1639 |  | 
|  | 1640 | if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_IDLE) { | 
|  | 1641 | vreg_err(vreg, "invalid mode: %u\n", mode); | 
|  | 1642 | return -EINVAL; | 
|  | 1643 | } | 
|  | 1644 |  | 
|  | 1645 | /* | 
|  | 1646 | * Make sure that advanced mode is in use.  If it isn't, then set it | 
|  | 1647 | * and update the voltage accordingly. | 
|  | 1648 | */ | 
|  | 1649 | if (!NLDO1200_IN_ADVANCED_MODE(vreg)) { | 
|  | 1650 | rc = _pm8xxx_nldo1200_set_voltage(vreg, vreg->save_uV, | 
|  | 1651 | vreg->save_uV); | 
|  | 1652 | if (rc) | 
|  | 1653 | goto bail; | 
|  | 1654 | } | 
|  | 1655 |  | 
|  | 1656 | if (mode == REGULATOR_MODE_NORMAL) { | 
|  | 1657 | /* HPM */ | 
|  | 1658 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1659 | NLDO1200_ADVANCED_PM_HPM | REGULATOR_BANK_WRITE | 
|  | 1660 | | REGULATOR_BANK_SEL(2), NLDO1200_ADVANCED_PM_MASK | 
|  | 1661 | | REGULATOR_BANK_MASK, &vreg->test_reg[2]); | 
|  | 1662 | } else { | 
|  | 1663 | /* LPM */ | 
|  | 1664 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1665 | NLDO1200_ADVANCED_PM_LPM | REGULATOR_BANK_WRITE | 
|  | 1666 | | REGULATOR_BANK_SEL(2), NLDO1200_ADVANCED_PM_MASK | 
|  | 1667 | | REGULATOR_BANK_MASK, &vreg->test_reg[2]); | 
|  | 1668 | } | 
|  | 1669 |  | 
|  | 1670 | bail: | 
|  | 1671 | if (rc) | 
|  | 1672 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1673 | else | 
|  | 1674 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_MODE); | 
|  | 1675 |  | 
|  | 1676 | return rc; | 
|  | 1677 | } | 
|  | 1678 |  | 
|  | 1679 | static unsigned int pm8xxx_smps_get_mode(struct regulator_dev *rdev) | 
|  | 1680 | { | 
|  | 1681 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1682 | unsigned int mode = 0; | 
|  | 1683 |  | 
|  | 1684 | mutex_lock(&vreg->pc_lock); | 
|  | 1685 | mode = vreg->mode; | 
|  | 1686 | mutex_unlock(&vreg->pc_lock); | 
|  | 1687 |  | 
|  | 1688 | return mode; | 
|  | 1689 | } | 
|  | 1690 |  | 
|  | 1691 | static int pm8xxx_smps_set_mode(struct regulator_dev *rdev, unsigned int mode) | 
|  | 1692 | { | 
|  | 1693 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1694 | int rc = 0; | 
|  | 1695 |  | 
|  | 1696 | if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_IDLE) { | 
|  | 1697 | vreg_err(vreg, "invalid mode: %u\n", mode); | 
|  | 1698 | return -EINVAL; | 
|  | 1699 | } | 
|  | 1700 |  | 
|  | 1701 | mutex_lock(&vreg->pc_lock); | 
|  | 1702 |  | 
|  | 1703 | if (mode == REGULATOR_MODE_NORMAL | 
|  | 1704 | || (vreg->is_enabled_pc | 
|  | 1705 | && vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE)) { | 
|  | 1706 | /* HPM */ | 
|  | 1707 | rc = pm8xxx_vreg_masked_write(vreg, vreg->clk_ctrl_addr, | 
|  | 1708 | SMPS_CLK_CTRL_PWM, SMPS_CLK_CTRL_MASK, | 
|  | 1709 | &vreg->clk_ctrl_reg); | 
|  | 1710 | } else { | 
|  | 1711 | /* LPM */ | 
|  | 1712 | rc = pm8xxx_vreg_masked_write(vreg, vreg->clk_ctrl_addr, | 
|  | 1713 | SMPS_CLK_CTRL_PFM, SMPS_CLK_CTRL_MASK, | 
|  | 1714 | &vreg->clk_ctrl_reg); | 
|  | 1715 | } | 
|  | 1716 |  | 
|  | 1717 | if (!rc) | 
|  | 1718 | vreg->mode = mode; | 
|  | 1719 |  | 
|  | 1720 | mutex_unlock(&vreg->pc_lock); | 
|  | 1721 |  | 
|  | 1722 | if (rc) | 
|  | 1723 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1724 | else | 
|  | 1725 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_MODE); | 
|  | 1726 |  | 
|  | 1727 | return rc; | 
|  | 1728 | } | 
|  | 1729 |  | 
|  | 1730 | static unsigned int pm8xxx_ftsmps_get_mode(struct regulator_dev *rdev) | 
|  | 1731 | { | 
|  | 1732 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1733 | unsigned int mode = 0; | 
|  | 1734 |  | 
|  | 1735 | if ((vreg->test_reg[0] & FTSMPS_CNFG1_PM_MASK) == FTSMPS_CNFG1_PM_PFM) | 
|  | 1736 | mode = REGULATOR_MODE_IDLE; | 
|  | 1737 | else | 
|  | 1738 | mode = REGULATOR_MODE_NORMAL; | 
|  | 1739 |  | 
|  | 1740 | return mode; | 
|  | 1741 | } | 
|  | 1742 |  | 
|  | 1743 | static int pm8xxx_ftsmps_set_mode(struct regulator_dev *rdev, unsigned int mode) | 
|  | 1744 | { | 
|  | 1745 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1746 | int rc = 0; | 
|  | 1747 |  | 
|  | 1748 | if (mode == REGULATOR_MODE_NORMAL) { | 
|  | 1749 | /* HPM */ | 
|  | 1750 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1751 | FTSMPS_CNFG1_PM_PWM | REGULATOR_BANK_WRITE | 
|  | 1752 | | REGULATOR_BANK_SEL(0), FTSMPS_CNFG1_PM_MASK | 
|  | 1753 | | REGULATOR_BANK_MASK, &vreg->test_reg[0]); | 
|  | 1754 | } else if (mode == REGULATOR_MODE_IDLE) { | 
|  | 1755 | /* LPM */ | 
|  | 1756 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1757 | FTSMPS_CNFG1_PM_PFM | REGULATOR_BANK_WRITE | 
|  | 1758 | | REGULATOR_BANK_SEL(0), FTSMPS_CNFG1_PM_MASK | 
|  | 1759 | | REGULATOR_BANK_MASK, &vreg->test_reg[0]); | 
|  | 1760 | } else { | 
|  | 1761 | vreg_err(vreg, "invalid mode: %u\n", mode); | 
|  | 1762 | return -EINVAL; | 
|  | 1763 | } | 
|  | 1764 |  | 
|  | 1765 | if (rc) | 
|  | 1766 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1767 | else | 
|  | 1768 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_MODE); | 
|  | 1769 |  | 
|  | 1770 | return rc; | 
|  | 1771 | } | 
|  | 1772 |  | 
|  | 1773 | static unsigned int pm8xxx_vreg_get_optimum_mode(struct regulator_dev *rdev, | 
|  | 1774 | int input_uV, int output_uV, int load_uA) | 
|  | 1775 | { | 
|  | 1776 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1777 | unsigned int mode; | 
|  | 1778 |  | 
|  | 1779 | if (load_uA + vreg->pdata.system_uA >= vreg->hpm_min_load) | 
|  | 1780 | mode = REGULATOR_MODE_NORMAL; | 
|  | 1781 | else | 
|  | 1782 | mode = REGULATOR_MODE_IDLE; | 
|  | 1783 |  | 
|  | 1784 | return mode; | 
|  | 1785 | } | 
|  | 1786 |  | 
|  | 1787 | static int pm8xxx_ldo_enable(struct regulator_dev *rdev) | 
|  | 1788 | { | 
|  | 1789 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1790 | int rc, val; | 
|  | 1791 |  | 
|  | 1792 | mutex_lock(&vreg->pc_lock); | 
|  | 1793 |  | 
|  | 1794 | /* | 
|  | 1795 | * Choose HPM if previously set to HPM or if pin control is enabled in | 
|  | 1796 | * on/off mode. | 
|  | 1797 | */ | 
|  | 1798 | val = LDO_CTRL_PM_LPM; | 
|  | 1799 | if (vreg->mode == REGULATOR_MODE_NORMAL | 
|  | 1800 | || (vreg->is_enabled_pc | 
|  | 1801 | && vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE)) | 
|  | 1802 | val = LDO_CTRL_PM_HPM; | 
|  | 1803 |  | 
|  | 1804 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val | LDO_ENABLE, | 
|  | 1805 | LDO_ENABLE_MASK | LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 1806 |  | 
|  | 1807 | if (!rc) | 
|  | 1808 | vreg->is_enabled = true; | 
|  | 1809 |  | 
|  | 1810 | mutex_unlock(&vreg->pc_lock); | 
|  | 1811 |  | 
|  | 1812 | if (rc) | 
|  | 1813 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1814 | else | 
|  | 1815 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 1816 |  | 
|  | 1817 | return rc; | 
|  | 1818 | } | 
|  | 1819 |  | 
|  | 1820 | static int pm8xxx_ldo_disable(struct regulator_dev *rdev) | 
|  | 1821 | { | 
|  | 1822 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1823 | int rc; | 
|  | 1824 |  | 
|  | 1825 | mutex_lock(&vreg->pc_lock); | 
|  | 1826 |  | 
|  | 1827 | /* | 
|  | 1828 | * Only disable the regulator if it isn't still required for HPM/LPM | 
|  | 1829 | * pin control. | 
|  | 1830 | */ | 
|  | 1831 | if (!vreg->is_enabled_pc | 
|  | 1832 | || vreg->pdata.pin_fn != PM8XXX_VREG_PIN_FN_MODE) { | 
|  | 1833 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1834 | LDO_DISABLE, LDO_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 1835 | if (rc) | 
|  | 1836 | goto bail; | 
|  | 1837 | } | 
|  | 1838 |  | 
|  | 1839 | /* Change to LPM if HPM/LPM pin control is enabled. */ | 
|  | 1840 | if (vreg->is_enabled_pc | 
|  | 1841 | && vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_MODE) { | 
|  | 1842 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1843 | LDO_CTRL_PM_LPM, LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 1844 | if (rc) | 
|  | 1845 | goto bail; | 
|  | 1846 |  | 
|  | 1847 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 1848 | LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE | 
|  | 1849 | | REGULATOR_BANK_SEL(0), | 
|  | 1850 | LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK, | 
|  | 1851 | &vreg->test_reg[0]); | 
|  | 1852 | } | 
|  | 1853 |  | 
|  | 1854 | if (!rc) | 
|  | 1855 | vreg->is_enabled = false; | 
|  | 1856 | bail: | 
|  | 1857 | mutex_unlock(&vreg->pc_lock); | 
|  | 1858 |  | 
|  | 1859 | if (rc) | 
|  | 1860 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1861 | else | 
|  | 1862 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 1863 |  | 
|  | 1864 | return rc; | 
|  | 1865 | } | 
|  | 1866 |  | 
|  | 1867 | static int pm8xxx_nldo1200_enable(struct regulator_dev *rdev) | 
|  | 1868 | { | 
|  | 1869 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1870 | int rc; | 
|  | 1871 |  | 
|  | 1872 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, NLDO1200_ENABLE, | 
|  | 1873 | NLDO1200_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 1874 |  | 
|  | 1875 | if (rc) | 
|  | 1876 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1877 | else | 
|  | 1878 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 1879 |  | 
|  | 1880 | return rc; | 
|  | 1881 | } | 
|  | 1882 |  | 
|  | 1883 | static int pm8xxx_nldo1200_disable(struct regulator_dev *rdev) | 
|  | 1884 | { | 
|  | 1885 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1886 | int rc; | 
|  | 1887 |  | 
|  | 1888 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, NLDO1200_DISABLE, | 
|  | 1889 | NLDO1200_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 1890 |  | 
|  | 1891 | if (rc) | 
|  | 1892 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1893 | else | 
|  | 1894 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 1895 |  | 
|  | 1896 | return rc; | 
|  | 1897 | } | 
|  | 1898 |  | 
|  | 1899 | static int pm8xxx_smps_enable(struct regulator_dev *rdev) | 
|  | 1900 | { | 
|  | 1901 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1902 | int rc = 0; | 
|  | 1903 | int val; | 
|  | 1904 |  | 
|  | 1905 | mutex_lock(&vreg->pc_lock); | 
|  | 1906 |  | 
|  | 1907 | if (SMPS_IN_ADVANCED_MODE(vreg) | 
|  | 1908 | || !pm8xxx_vreg_is_pin_controlled(vreg)) { | 
|  | 1909 | /* Enable in advanced mode if not using pin control. */ | 
|  | 1910 | rc = pm8xxx_smps_set_voltage_advanced(vreg, vreg->save_uV, | 
|  | 1911 | vreg->save_uV, 1); | 
|  | 1912 | } else { | 
|  | 1913 | rc = pm8xxx_smps_set_voltage_legacy(vreg, vreg->save_uV, | 
|  | 1914 | vreg->save_uV); | 
|  | 1915 | if (rc) | 
|  | 1916 | goto bail; | 
|  | 1917 |  | 
|  | 1918 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1919 | SMPS_LEGACY_ENABLE, SMPS_LEGACY_ENABLE_MASK, | 
|  | 1920 | &vreg->ctrl_reg); | 
|  | 1921 | } | 
|  | 1922 |  | 
|  | 1923 | /* | 
|  | 1924 | * Choose HPM if previously set to HPM or if pin control is enabled in | 
|  | 1925 | * on/off mode. | 
|  | 1926 | */ | 
|  | 1927 | val = SMPS_CLK_CTRL_PFM; | 
|  | 1928 | if (vreg->mode == REGULATOR_MODE_NORMAL | 
|  | 1929 | || (vreg->is_enabled_pc | 
|  | 1930 | && vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE)) | 
|  | 1931 | val = SMPS_CLK_CTRL_PWM; | 
|  | 1932 |  | 
|  | 1933 | rc = pm8xxx_vreg_masked_write(vreg, vreg->clk_ctrl_addr, val, | 
|  | 1934 | SMPS_CLK_CTRL_MASK, &vreg->clk_ctrl_reg); | 
|  | 1935 |  | 
|  | 1936 | if (!rc) | 
|  | 1937 | vreg->is_enabled = true; | 
|  | 1938 | bail: | 
|  | 1939 | mutex_unlock(&vreg->pc_lock); | 
|  | 1940 |  | 
|  | 1941 | if (rc) | 
|  | 1942 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1943 | else | 
|  | 1944 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 1945 |  | 
|  | 1946 | return rc; | 
|  | 1947 | } | 
|  | 1948 |  | 
|  | 1949 | static int pm8xxx_smps_disable(struct regulator_dev *rdev) | 
|  | 1950 | { | 
|  | 1951 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 1952 | int rc; | 
|  | 1953 |  | 
|  | 1954 | mutex_lock(&vreg->pc_lock); | 
|  | 1955 |  | 
|  | 1956 | if (SMPS_IN_ADVANCED_MODE(vreg)) { | 
|  | 1957 | /* Change SMPS to legacy mode before disabling. */ | 
|  | 1958 | rc = pm8xxx_smps_set_voltage_legacy(vreg, vreg->save_uV, | 
|  | 1959 | vreg->save_uV); | 
|  | 1960 | if (rc) | 
|  | 1961 | goto bail; | 
|  | 1962 | } | 
|  | 1963 |  | 
|  | 1964 | /* | 
|  | 1965 | * Only disable the regulator if it isn't still required for HPM/LPM | 
|  | 1966 | * pin control. | 
|  | 1967 | */ | 
|  | 1968 | if (!vreg->is_enabled_pc | 
|  | 1969 | || vreg->pdata.pin_fn != PM8XXX_VREG_PIN_FN_MODE) { | 
|  | 1970 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 1971 | SMPS_LEGACY_DISABLE, SMPS_LEGACY_ENABLE_MASK, | 
|  | 1972 | &vreg->ctrl_reg); | 
|  | 1973 | if (rc) | 
|  | 1974 | goto bail; | 
|  | 1975 | } | 
|  | 1976 |  | 
|  | 1977 | /* Change to LPM if HPM/LPM pin control is enabled. */ | 
|  | 1978 | if (vreg->is_enabled_pc | 
|  | 1979 | && vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_MODE) | 
|  | 1980 | rc = pm8xxx_vreg_masked_write(vreg, vreg->clk_ctrl_addr, | 
|  | 1981 | SMPS_CLK_CTRL_PFM, SMPS_CLK_CTRL_MASK, | 
|  | 1982 | &vreg->clk_ctrl_reg); | 
|  | 1983 |  | 
|  | 1984 | if (!rc) | 
|  | 1985 | vreg->is_enabled = false; | 
|  | 1986 |  | 
|  | 1987 | bail: | 
|  | 1988 | mutex_unlock(&vreg->pc_lock); | 
|  | 1989 |  | 
|  | 1990 | if (rc) | 
|  | 1991 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 1992 | else | 
|  | 1993 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 1994 |  | 
|  | 1995 | return rc; | 
|  | 1996 | } | 
|  | 1997 |  | 
|  | 1998 | static int pm8xxx_ftsmps_enable(struct regulator_dev *rdev) | 
|  | 1999 | { | 
|  | 2000 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2001 | int rc; | 
|  | 2002 |  | 
|  | 2003 | rc = _pm8xxx_ftsmps_set_voltage(vreg, vreg->save_uV, vreg->save_uV, 1); | 
|  | 2004 |  | 
|  | 2005 | if (rc) | 
|  | 2006 | vreg_err(vreg, "set voltage failed, rc=%d\n", rc); | 
|  | 2007 | else | 
|  | 2008 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 2009 |  | 
|  | 2010 | return rc; | 
|  | 2011 | } | 
|  | 2012 |  | 
|  | 2013 | static int pm8xxx_ftsmps_disable(struct regulator_dev *rdev) | 
|  | 2014 | { | 
|  | 2015 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2016 | int rc; | 
|  | 2017 |  | 
|  | 2018 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2019 | FTSMPS_VCTRL_BAND_OFF, FTSMPS_VCTRL_BAND_MASK, &vreg->ctrl_reg); | 
|  | 2020 | if (rc) | 
|  | 2021 | goto bail; | 
|  | 2022 |  | 
|  | 2023 | rc = pm8xxx_vreg_masked_write(vreg, vreg->pfm_ctrl_addr, | 
|  | 2024 | FTSMPS_VCTRL_BAND_OFF, FTSMPS_VCTRL_BAND_MASK, | 
|  | 2025 | &vreg->pfm_ctrl_reg); | 
|  | 2026 | bail: | 
|  | 2027 | if (rc) | 
|  | 2028 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2029 | else | 
|  | 2030 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 2031 |  | 
|  | 2032 | return rc; | 
|  | 2033 | } | 
|  | 2034 |  | 
|  | 2035 | static int pm8xxx_vs_enable(struct regulator_dev *rdev) | 
|  | 2036 | { | 
|  | 2037 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2038 | int rc; | 
|  | 2039 |  | 
|  | 2040 | mutex_lock(&vreg->pc_lock); | 
|  | 2041 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 2042 | if (vreg->pdata.ocp_enable) { | 
|  | 2043 | /* Disable OCP. */ | 
|  | 2044 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2045 | VS_OCP_DISABLE, VS_OCP_MASK, &vreg->test_reg[0]); | 
|  | 2046 | if (rc) | 
|  | 2047 | goto done; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2048 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 2049 | /* Enable the switch while OCP is disabled. */ | 
|  | 2050 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2051 | VS_ENABLE | VS_MODE_NORMAL, | 
|  | 2052 | VS_ENABLE_MASK | VS_MODE_MASK, | 
|  | 2053 | &vreg->ctrl_reg); | 
|  | 2054 | if (rc) | 
|  | 2055 | goto done; | 
|  | 2056 |  | 
|  | 2057 | /* Wait for inrush current to subside, then enable OCP. */ | 
|  | 2058 | udelay(vreg->pdata.ocp_enable_time); | 
|  | 2059 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2060 | VS_OCP_ENABLE, VS_OCP_MASK, &vreg->test_reg[0]); | 
|  | 2061 | } else { | 
|  | 2062 | /* Enable the switch without touching OCP. */ | 
|  | 2063 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, VS_ENABLE, | 
|  | 2064 | VS_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2065 | } | 
|  | 2066 |  | 
|  | 2067 | done: | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2068 | if (!rc) | 
|  | 2069 | vreg->is_enabled = true; | 
|  | 2070 |  | 
|  | 2071 | mutex_unlock(&vreg->pc_lock); | 
|  | 2072 |  | 
|  | 2073 | if (rc) | 
|  | 2074 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2075 | else | 
|  | 2076 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 2077 |  | 
|  | 2078 | return rc; | 
|  | 2079 | } | 
|  | 2080 |  | 
|  | 2081 | static int pm8xxx_vs_disable(struct regulator_dev *rdev) | 
|  | 2082 | { | 
|  | 2083 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2084 | int rc; | 
|  | 2085 |  | 
|  | 2086 | mutex_lock(&vreg->pc_lock); | 
|  | 2087 |  | 
|  | 2088 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, VS_DISABLE, | 
|  | 2089 | VS_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2090 |  | 
|  | 2091 | if (!rc) | 
|  | 2092 | vreg->is_enabled = false; | 
|  | 2093 |  | 
|  | 2094 | mutex_unlock(&vreg->pc_lock); | 
|  | 2095 |  | 
|  | 2096 | if (rc) | 
|  | 2097 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2098 | else | 
|  | 2099 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 2100 |  | 
|  | 2101 | return rc; | 
|  | 2102 | } | 
|  | 2103 |  | 
|  | 2104 | static int pm8xxx_vs300_enable(struct regulator_dev *rdev) | 
|  | 2105 | { | 
|  | 2106 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2107 | int rc; | 
|  | 2108 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 2109 | if (vreg->pdata.ocp_enable) { | 
|  | 2110 | /* Disable OCP. */ | 
|  | 2111 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2112 | VS_OCP_DISABLE, VS_OCP_MASK, &vreg->test_reg[0]); | 
|  | 2113 | if (rc) | 
|  | 2114 | goto done; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2115 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 2116 | /* Enable the switch while OCP is disabled. */ | 
|  | 2117 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2118 | VS300_CTRL_ENABLE | VS300_MODE_NORMAL, | 
|  | 2119 | VS300_CTRL_ENABLE_MASK | VS300_MODE_MASK, | 
|  | 2120 | &vreg->ctrl_reg); | 
|  | 2121 | if (rc) | 
|  | 2122 | goto done; | 
|  | 2123 |  | 
|  | 2124 | /* Wait for inrush current to subside, then enable OCP. */ | 
|  | 2125 | udelay(vreg->pdata.ocp_enable_time); | 
|  | 2126 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2127 | VS_OCP_ENABLE, VS_OCP_MASK, &vreg->test_reg[0]); | 
|  | 2128 | } else { | 
|  | 2129 | /* Enable the regulator without touching OCP. */ | 
|  | 2130 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2131 | VS300_CTRL_ENABLE, VS300_CTRL_ENABLE_MASK, | 
|  | 2132 | &vreg->ctrl_reg); | 
|  | 2133 | } | 
|  | 2134 |  | 
|  | 2135 | done: | 
|  | 2136 | if (rc) { | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2137 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 2138 | } else { | 
|  | 2139 | vreg->is_enabled = true; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2140 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 2141 | } | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2142 |  | 
|  | 2143 | return rc; | 
|  | 2144 | } | 
|  | 2145 |  | 
|  | 2146 | static int pm8xxx_vs300_disable(struct regulator_dev *rdev) | 
|  | 2147 | { | 
|  | 2148 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2149 | int rc; | 
|  | 2150 |  | 
|  | 2151 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, VS300_CTRL_DISABLE, | 
|  | 2152 | VS300_CTRL_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2153 |  | 
|  | 2154 | if (rc) | 
|  | 2155 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2156 | else | 
|  | 2157 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 2158 |  | 
|  | 2159 | return rc; | 
|  | 2160 | } | 
|  | 2161 |  | 
|  | 2162 | static int pm8xxx_ncp_enable(struct regulator_dev *rdev) | 
|  | 2163 | { | 
|  | 2164 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2165 | int rc; | 
|  | 2166 |  | 
|  | 2167 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, NCP_ENABLE, | 
|  | 2168 | NCP_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2169 |  | 
|  | 2170 | if (rc) | 
|  | 2171 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2172 | else | 
|  | 2173 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 2174 |  | 
|  | 2175 | return rc; | 
|  | 2176 | } | 
|  | 2177 |  | 
|  | 2178 | static int pm8xxx_ncp_disable(struct regulator_dev *rdev) | 
|  | 2179 | { | 
|  | 2180 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2181 | int rc; | 
|  | 2182 |  | 
|  | 2183 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, NCP_DISABLE, | 
|  | 2184 | NCP_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2185 |  | 
|  | 2186 | if (rc) | 
|  | 2187 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2188 | else | 
|  | 2189 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 2190 |  | 
|  | 2191 | return rc; | 
|  | 2192 | } | 
|  | 2193 |  | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 2194 | static int pm8xxx_boost_enable(struct regulator_dev *rdev) | 
|  | 2195 | { | 
|  | 2196 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2197 | int rc; | 
|  | 2198 |  | 
|  | 2199 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, BOOST_ENABLE, | 
|  | 2200 | BOOST_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2201 |  | 
|  | 2202 | if (rc) | 
|  | 2203 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2204 | else | 
|  | 2205 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE); | 
|  | 2206 |  | 
|  | 2207 | return rc; | 
|  | 2208 | } | 
|  | 2209 |  | 
|  | 2210 | static int pm8xxx_boost_disable(struct regulator_dev *rdev) | 
|  | 2211 | { | 
|  | 2212 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2213 | int rc; | 
|  | 2214 |  | 
|  | 2215 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, BOOST_DISABLE, | 
|  | 2216 | BOOST_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2217 |  | 
|  | 2218 | if (rc) | 
|  | 2219 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2220 | else | 
|  | 2221 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE); | 
|  | 2222 |  | 
|  | 2223 | return rc; | 
|  | 2224 | } | 
|  | 2225 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2226 | static int pm8xxx_ldo_pin_control_enable(struct regulator_dev *rdev) | 
|  | 2227 | { | 
|  | 2228 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2229 | int rc = 0; | 
|  | 2230 | int bank; | 
|  | 2231 | u8 val = 0; | 
|  | 2232 | u8 mask; | 
|  | 2233 |  | 
|  | 2234 | mutex_lock(&vreg->pc_lock); | 
|  | 2235 |  | 
|  | 2236 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN0) | 
|  | 2237 | val |= LDO_TEST_PIN_CTRL_EN0; | 
|  | 2238 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN1) | 
|  | 2239 | val |= LDO_TEST_PIN_CTRL_EN1; | 
|  | 2240 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN2) | 
|  | 2241 | val |= LDO_TEST_PIN_CTRL_EN2; | 
|  | 2242 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN3) | 
|  | 2243 | val |= LDO_TEST_PIN_CTRL_EN3; | 
|  | 2244 |  | 
|  | 2245 | bank = (vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE ? 5 : 6); | 
|  | 2246 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2247 | val | REGULATOR_BANK_SEL(bank) | REGULATOR_BANK_WRITE, | 
|  | 2248 | LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK, | 
|  | 2249 | &vreg->test_reg[bank]); | 
|  | 2250 | if (rc) | 
|  | 2251 | goto bail; | 
|  | 2252 |  | 
|  | 2253 | /* Unset pin control bits in unused bank. */ | 
|  | 2254 | bank = (bank == 5 ? 6 : 5); | 
|  | 2255 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2256 | REGULATOR_BANK_SEL(bank) | REGULATOR_BANK_WRITE, | 
|  | 2257 | LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK, | 
|  | 2258 | &vreg->test_reg[bank]); | 
|  | 2259 | if (rc) | 
|  | 2260 | goto bail; | 
|  | 2261 |  | 
|  | 2262 | val = LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE | 
|  | 2263 | | REGULATOR_BANK_SEL(0); | 
|  | 2264 | mask = LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK; | 
|  | 2265 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, val, mask, | 
|  | 2266 | &vreg->test_reg[0]); | 
|  | 2267 | if (rc) | 
|  | 2268 | goto bail; | 
|  | 2269 |  | 
|  | 2270 | if (vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE) { | 
|  | 2271 | /* Pin control ON/OFF */ | 
|  | 2272 | val = LDO_CTRL_PM_HPM; | 
|  | 2273 | /* Leave physically enabled if already enabled. */ | 
|  | 2274 | val |= (vreg->is_enabled ? LDO_ENABLE : LDO_DISABLE); | 
|  | 2275 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val, | 
|  | 2276 | LDO_ENABLE_MASK | LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 2277 | if (rc) | 
|  | 2278 | goto bail; | 
|  | 2279 | } else { | 
|  | 2280 | /* Pin control LPM/HPM */ | 
|  | 2281 | val = LDO_ENABLE; | 
|  | 2282 | /* Leave in HPM if already enabled in HPM. */ | 
|  | 2283 | val |= (vreg->is_enabled && vreg->mode == REGULATOR_MODE_NORMAL | 
|  | 2284 | ?  LDO_CTRL_PM_HPM : LDO_CTRL_PM_LPM); | 
|  | 2285 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val, | 
|  | 2286 | LDO_ENABLE_MASK | LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 2287 | if (rc) | 
|  | 2288 | goto bail; | 
|  | 2289 | } | 
|  | 2290 |  | 
|  | 2291 | bail: | 
|  | 2292 | if (!rc) | 
|  | 2293 | vreg->is_enabled_pc = true; | 
|  | 2294 |  | 
|  | 2295 | mutex_unlock(&vreg->pc_lock); | 
|  | 2296 |  | 
|  | 2297 | if (rc) | 
|  | 2298 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2299 | else | 
|  | 2300 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_PIN_CTRL); | 
|  | 2301 |  | 
|  | 2302 | return rc; | 
|  | 2303 | } | 
|  | 2304 |  | 
|  | 2305 | static int pm8xxx_ldo_pin_control_disable(struct regulator_dev *rdev) | 
|  | 2306 | { | 
|  | 2307 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2308 | int rc; | 
|  | 2309 |  | 
|  | 2310 | mutex_lock(&vreg->pc_lock); | 
|  | 2311 |  | 
|  | 2312 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2313 | REGULATOR_BANK_SEL(5) | REGULATOR_BANK_WRITE, | 
|  | 2314 | LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK, | 
|  | 2315 | &vreg->test_reg[5]); | 
|  | 2316 | if (rc) | 
|  | 2317 | goto bail; | 
|  | 2318 |  | 
|  | 2319 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2320 | REGULATOR_BANK_SEL(6) | REGULATOR_BANK_WRITE, | 
|  | 2321 | LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK, | 
|  | 2322 | &vreg->test_reg[6]); | 
|  | 2323 |  | 
|  | 2324 | /* | 
|  | 2325 | * Physically disable the regulator if it was enabled in HPM/LPM pin | 
|  | 2326 | * control mode previously and it logically should not be enabled. | 
|  | 2327 | */ | 
|  | 2328 | if ((vreg->ctrl_reg & LDO_ENABLE_MASK) == LDO_ENABLE | 
|  | 2329 | && !vreg->is_enabled) { | 
|  | 2330 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2331 | LDO_DISABLE, LDO_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2332 | if (rc) | 
|  | 2333 | goto bail; | 
|  | 2334 | } | 
|  | 2335 |  | 
|  | 2336 | /* Change to LPM if LPM was enabled. */ | 
|  | 2337 | if (vreg->is_enabled && vreg->mode == REGULATOR_MODE_IDLE) { | 
|  | 2338 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2339 | LDO_CTRL_PM_LPM, LDO_CTRL_PM_MASK, &vreg->ctrl_reg); | 
|  | 2340 | if (rc) | 
|  | 2341 | goto bail; | 
|  | 2342 |  | 
|  | 2343 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2344 | LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE | 
|  | 2345 | | REGULATOR_BANK_SEL(0), | 
|  | 2346 | LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK, | 
|  | 2347 | &vreg->test_reg[0]); | 
|  | 2348 | if (rc) | 
|  | 2349 | goto bail; | 
|  | 2350 | } | 
|  | 2351 |  | 
|  | 2352 | bail: | 
|  | 2353 | if (!rc) | 
|  | 2354 | vreg->is_enabled_pc = false; | 
|  | 2355 |  | 
|  | 2356 | mutex_unlock(&vreg->pc_lock); | 
|  | 2357 |  | 
|  | 2358 | if (rc) | 
|  | 2359 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2360 | else | 
|  | 2361 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_PIN_CTRL); | 
|  | 2362 |  | 
|  | 2363 | return rc; | 
|  | 2364 | } | 
|  | 2365 |  | 
|  | 2366 | static int pm8xxx_smps_pin_control_enable(struct regulator_dev *rdev) | 
|  | 2367 | { | 
|  | 2368 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2369 | int rc = 0; | 
|  | 2370 | u8 val = 0; | 
|  | 2371 |  | 
|  | 2372 | mutex_lock(&vreg->pc_lock); | 
|  | 2373 |  | 
|  | 2374 | if (vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE) { | 
|  | 2375 | /* Pin control ON/OFF */ | 
|  | 2376 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN0) | 
|  | 2377 | val |= SMPS_PIN_CTRL_EN0; | 
|  | 2378 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN1) | 
|  | 2379 | val |= SMPS_PIN_CTRL_EN1; | 
|  | 2380 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN2) | 
|  | 2381 | val |= SMPS_PIN_CTRL_EN2; | 
|  | 2382 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN3) | 
|  | 2383 | val |= SMPS_PIN_CTRL_EN3; | 
|  | 2384 | } else { | 
|  | 2385 | /* Pin control LPM/HPM */ | 
|  | 2386 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN0) | 
|  | 2387 | val |= SMPS_PIN_CTRL_LPM_EN0; | 
|  | 2388 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN1) | 
|  | 2389 | val |= SMPS_PIN_CTRL_LPM_EN1; | 
|  | 2390 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN2) | 
|  | 2391 | val |= SMPS_PIN_CTRL_LPM_EN2; | 
|  | 2392 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN3) | 
|  | 2393 | val |= SMPS_PIN_CTRL_LPM_EN3; | 
|  | 2394 | } | 
|  | 2395 |  | 
|  | 2396 | rc = pm8xxx_smps_set_voltage_legacy(vreg, vreg->save_uV, vreg->save_uV); | 
|  | 2397 | if (rc) | 
|  | 2398 | goto bail; | 
|  | 2399 |  | 
|  | 2400 | rc = pm8xxx_vreg_masked_write(vreg, vreg->sleep_ctrl_addr, val, | 
|  | 2401 | SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK, | 
|  | 2402 | &vreg->sleep_ctrl_reg); | 
|  | 2403 | if (rc) | 
|  | 2404 | goto bail; | 
|  | 2405 |  | 
|  | 2406 | /* | 
|  | 2407 | * Physically enable the regulator if using HPM/LPM pin control mode or | 
|  | 2408 | * if the regulator should be logically left on. | 
|  | 2409 | */ | 
|  | 2410 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2411 | ((vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_MODE | 
|  | 2412 | || vreg->is_enabled) ? | 
|  | 2413 | SMPS_LEGACY_ENABLE : SMPS_LEGACY_DISABLE), | 
|  | 2414 | SMPS_LEGACY_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2415 | if (rc) | 
|  | 2416 | goto bail; | 
|  | 2417 |  | 
|  | 2418 | /* | 
|  | 2419 | * Set regulator to HPM if using on/off pin control or if the regulator | 
|  | 2420 | * is already enabled in HPM.  Otherwise, set it to LPM. | 
|  | 2421 | */ | 
|  | 2422 | rc = pm8xxx_vreg_masked_write(vreg, vreg->clk_ctrl_addr, | 
|  | 2423 | (vreg->pdata.pin_fn == PM8XXX_VREG_PIN_FN_ENABLE | 
|  | 2424 | || (vreg->is_enabled | 
|  | 2425 | && vreg->mode == REGULATOR_MODE_NORMAL) | 
|  | 2426 | ? SMPS_CLK_CTRL_PWM : SMPS_CLK_CTRL_PFM), | 
|  | 2427 | SMPS_CLK_CTRL_MASK, &vreg->clk_ctrl_reg); | 
|  | 2428 |  | 
|  | 2429 | bail: | 
|  | 2430 | if (!rc) | 
|  | 2431 | vreg->is_enabled_pc = true; | 
|  | 2432 |  | 
|  | 2433 | mutex_unlock(&vreg->pc_lock); | 
|  | 2434 |  | 
|  | 2435 | if (rc) | 
|  | 2436 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2437 | else | 
|  | 2438 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_PIN_CTRL); | 
|  | 2439 |  | 
|  | 2440 | return rc; | 
|  | 2441 | } | 
|  | 2442 |  | 
|  | 2443 | static int pm8xxx_smps_pin_control_disable(struct regulator_dev *rdev) | 
|  | 2444 | { | 
|  | 2445 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2446 | int rc; | 
|  | 2447 |  | 
|  | 2448 | mutex_lock(&vreg->pc_lock); | 
|  | 2449 |  | 
|  | 2450 | rc = pm8xxx_vreg_masked_write(vreg, vreg->sleep_ctrl_addr, 0, | 
|  | 2451 | SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK, | 
|  | 2452 | &vreg->sleep_ctrl_reg); | 
|  | 2453 | if (rc) | 
|  | 2454 | goto bail; | 
|  | 2455 |  | 
|  | 2456 | /* | 
|  | 2457 | * Physically disable the regulator if it was enabled in HPM/LPM pin | 
|  | 2458 | * control mode previously and it logically should not be enabled. | 
|  | 2459 | */ | 
|  | 2460 | if ((vreg->ctrl_reg & SMPS_LEGACY_ENABLE_MASK) == SMPS_LEGACY_ENABLE | 
|  | 2461 | && vreg->is_enabled == false) { | 
|  | 2462 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2463 | SMPS_LEGACY_DISABLE, SMPS_LEGACY_ENABLE_MASK, | 
|  | 2464 | &vreg->ctrl_reg); | 
|  | 2465 | if (rc) | 
|  | 2466 | goto bail; | 
|  | 2467 | } | 
|  | 2468 |  | 
|  | 2469 | /* Change to LPM if LPM was enabled. */ | 
|  | 2470 | if (vreg->is_enabled && vreg->mode == REGULATOR_MODE_IDLE) { | 
|  | 2471 | rc = pm8xxx_vreg_masked_write(vreg, vreg->clk_ctrl_addr, | 
|  | 2472 | SMPS_CLK_CTRL_PFM, SMPS_CLK_CTRL_MASK, | 
|  | 2473 | &vreg->clk_ctrl_reg); | 
|  | 2474 | if (rc) | 
|  | 2475 | goto bail; | 
|  | 2476 | } | 
|  | 2477 |  | 
|  | 2478 | rc = pm8xxx_smps_set_voltage_advanced(vreg, vreg->save_uV, | 
|  | 2479 | vreg->save_uV, 0); | 
|  | 2480 |  | 
|  | 2481 | bail: | 
|  | 2482 | if (!rc) | 
|  | 2483 | vreg->is_enabled_pc = false; | 
|  | 2484 |  | 
|  | 2485 | mutex_unlock(&vreg->pc_lock); | 
|  | 2486 |  | 
|  | 2487 | if (rc) | 
|  | 2488 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2489 | else | 
|  | 2490 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_PIN_CTRL); | 
|  | 2491 |  | 
|  | 2492 | return rc; | 
|  | 2493 | } | 
|  | 2494 |  | 
|  | 2495 | static int pm8xxx_vs_pin_control_enable(struct regulator_dev *rdev) | 
|  | 2496 | { | 
|  | 2497 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2498 | int rc; | 
|  | 2499 | u8 val = 0; | 
|  | 2500 |  | 
|  | 2501 | mutex_lock(&vreg->pc_lock); | 
|  | 2502 |  | 
|  | 2503 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN0) | 
|  | 2504 | val |= VS_PIN_CTRL_EN0; | 
|  | 2505 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN1) | 
|  | 2506 | val |= VS_PIN_CTRL_EN1; | 
|  | 2507 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN2) | 
|  | 2508 | val |= VS_PIN_CTRL_EN2; | 
|  | 2509 | if (vreg->pdata.pin_ctrl & PM8XXX_VREG_PIN_CTRL_EN3) | 
|  | 2510 | val |= VS_PIN_CTRL_EN3; | 
|  | 2511 |  | 
|  | 2512 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val, | 
|  | 2513 | VS_PIN_CTRL_MASK | VS_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2514 |  | 
|  | 2515 | if (!rc) | 
|  | 2516 | vreg->is_enabled_pc = true; | 
|  | 2517 |  | 
|  | 2518 | mutex_unlock(&vreg->pc_lock); | 
|  | 2519 |  | 
|  | 2520 | if (rc) | 
|  | 2521 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2522 | else | 
|  | 2523 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_PIN_CTRL); | 
|  | 2524 |  | 
|  | 2525 | return rc; | 
|  | 2526 | } | 
|  | 2527 |  | 
|  | 2528 | static int pm8xxx_vs_pin_control_disable(struct regulator_dev *rdev) | 
|  | 2529 | { | 
|  | 2530 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2531 | int rc; | 
|  | 2532 |  | 
|  | 2533 | mutex_lock(&vreg->pc_lock); | 
|  | 2534 |  | 
|  | 2535 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, 0, | 
|  | 2536 | VS_PIN_CTRL_MASK, &vreg->ctrl_reg); | 
|  | 2537 |  | 
|  | 2538 | if (!rc) | 
|  | 2539 | vreg->is_enabled_pc = false; | 
|  | 2540 |  | 
|  | 2541 | mutex_unlock(&vreg->pc_lock); | 
|  | 2542 |  | 
|  | 2543 | if (rc) | 
|  | 2544 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 2545 | else | 
|  | 2546 | pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_PIN_CTRL); | 
|  | 2547 |  | 
|  | 2548 | return rc; | 
|  | 2549 | } | 
|  | 2550 |  | 
|  | 2551 | static int pm8xxx_enable_time(struct regulator_dev *rdev) | 
|  | 2552 | { | 
|  | 2553 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2554 |  | 
|  | 2555 | return vreg->pdata.enable_time; | 
|  | 2556 | } | 
|  | 2557 |  | 
|  | 2558 | static const char const *pm8xxx_print_actions[] = { | 
|  | 2559 | [PM8XXX_REGULATOR_ACTION_INIT]		= "initial    ", | 
|  | 2560 | [PM8XXX_REGULATOR_ACTION_ENABLE]	= "enable     ", | 
|  | 2561 | [PM8XXX_REGULATOR_ACTION_DISABLE]	= "disable    ", | 
|  | 2562 | [PM8XXX_REGULATOR_ACTION_VOLTAGE]	= "set voltage", | 
|  | 2563 | [PM8XXX_REGULATOR_ACTION_MODE]		= "set mode   ", | 
|  | 2564 | [PM8XXX_REGULATOR_ACTION_PIN_CTRL]	= "pin control", | 
|  | 2565 | }; | 
|  | 2566 |  | 
|  | 2567 | static void pm8xxx_vreg_show_state(struct regulator_dev *rdev, | 
|  | 2568 | enum pm8xxx_regulator_action action) | 
|  | 2569 | { | 
|  | 2570 | struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev); | 
|  | 2571 | int uV, pc; | 
|  | 2572 | unsigned int mode; | 
|  | 2573 | const char *pc_en0 = "", *pc_en1 = "", *pc_en2 = "", *pc_en3 = ""; | 
|  | 2574 | const char *pc_total = ""; | 
|  | 2575 | const char *action_label = pm8xxx_print_actions[action]; | 
|  | 2576 | const char *enable_label; | 
|  | 2577 |  | 
|  | 2578 | mutex_lock(&vreg->pc_lock); | 
|  | 2579 |  | 
|  | 2580 | /* | 
|  | 2581 | * Do not print unless REQUEST is specified and SSBI writes have taken | 
|  | 2582 | * place, or DUPLICATE is specified. | 
|  | 2583 | */ | 
|  | 2584 | if (!((pm8xxx_vreg_debug_mask & PM8XXX_VREG_DEBUG_DUPLICATE) | 
|  | 2585 | || ((pm8xxx_vreg_debug_mask & PM8XXX_VREG_DEBUG_REQUEST) | 
|  | 2586 | && (vreg->write_count != vreg->prev_write_count)))) { | 
|  | 2587 | mutex_unlock(&vreg->pc_lock); | 
|  | 2588 | return; | 
|  | 2589 | } | 
|  | 2590 |  | 
|  | 2591 | vreg->prev_write_count = vreg->write_count; | 
|  | 2592 |  | 
|  | 2593 | pc = vreg->pdata.pin_ctrl; | 
|  | 2594 | if (vreg->is_enabled_pc) { | 
|  | 2595 | if (pc & PM8XXX_VREG_PIN_CTRL_EN0) | 
|  | 2596 | pc_en0 = " EN0"; | 
|  | 2597 | if (pc & PM8XXX_VREG_PIN_CTRL_EN1) | 
|  | 2598 | pc_en1 = " EN1"; | 
|  | 2599 | if (pc & PM8XXX_VREG_PIN_CTRL_EN2) | 
|  | 2600 | pc_en2 = " EN2"; | 
|  | 2601 | if (pc & PM8XXX_VREG_PIN_CTRL_EN3) | 
|  | 2602 | pc_en3 = " EN3"; | 
|  | 2603 | if (pc == PM8XXX_VREG_PIN_CTRL_NONE) | 
|  | 2604 | pc_total = " none"; | 
|  | 2605 | } else { | 
|  | 2606 | pc_total = " none"; | 
|  | 2607 | } | 
|  | 2608 |  | 
|  | 2609 | mutex_unlock(&vreg->pc_lock); | 
|  | 2610 |  | 
|  | 2611 | enable_label = pm8xxx_vreg_is_enabled(rdev) ? "on " : "off"; | 
|  | 2612 |  | 
|  | 2613 | switch (vreg->type) { | 
|  | 2614 | case PM8XXX_REGULATOR_TYPE_PLDO: | 
|  | 2615 | uV = pm8xxx_pldo_get_voltage(rdev); | 
|  | 2616 | mode = pm8xxx_ldo_get_mode(rdev); | 
|  | 2617 | pr_info("%s %-9s: %s, v=%7d uV, mode=%s, pc=%s%s%s%s%s\n", | 
|  | 2618 | action_label, vreg->rdesc.name, enable_label, uV, | 
|  | 2619 | (mode == REGULATOR_MODE_NORMAL ? "HPM" : "LPM"), | 
|  | 2620 | pc_en0, pc_en1, pc_en2, pc_en3, pc_total); | 
|  | 2621 | break; | 
|  | 2622 | case PM8XXX_REGULATOR_TYPE_NLDO: | 
|  | 2623 | uV = pm8xxx_nldo_get_voltage(rdev); | 
|  | 2624 | mode = pm8xxx_ldo_get_mode(rdev); | 
|  | 2625 | pr_info("%s %-9s: %s, v=%7d uV, mode=%s, pc=%s%s%s%s%s\n", | 
|  | 2626 | action_label, vreg->rdesc.name, enable_label, uV, | 
|  | 2627 | (mode == REGULATOR_MODE_NORMAL ? "HPM" : "LPM"), | 
|  | 2628 | pc_en0, pc_en1, pc_en2, pc_en3, pc_total); | 
|  | 2629 | break; | 
|  | 2630 | case PM8XXX_REGULATOR_TYPE_NLDO1200: | 
|  | 2631 | uV = pm8xxx_nldo1200_get_voltage(rdev); | 
|  | 2632 | mode = pm8xxx_nldo1200_get_mode(rdev); | 
|  | 2633 | pr_info("%s %-9s: %s, v=%7d uV, mode=%s\n", | 
|  | 2634 | action_label, vreg->rdesc.name, enable_label, uV, | 
|  | 2635 | (mode == REGULATOR_MODE_NORMAL ? "HPM" : "LPM")); | 
|  | 2636 | break; | 
|  | 2637 | case PM8XXX_REGULATOR_TYPE_SMPS: | 
|  | 2638 | uV = pm8xxx_smps_get_voltage(rdev); | 
|  | 2639 | mode = pm8xxx_smps_get_mode(rdev); | 
|  | 2640 | pr_info("%s %-9s: %s, v=%7d uV, mode=%s, pc=%s%s%s%s%s\n", | 
|  | 2641 | action_label, vreg->rdesc.name, enable_label, uV, | 
|  | 2642 | (mode == REGULATOR_MODE_NORMAL ? "HPM" : "LPM"), | 
|  | 2643 | pc_en0, pc_en1, pc_en2, pc_en3, pc_total); | 
|  | 2644 | break; | 
|  | 2645 | case PM8XXX_REGULATOR_TYPE_FTSMPS: | 
|  | 2646 | uV = pm8xxx_ftsmps_get_voltage(rdev); | 
|  | 2647 | mode = pm8xxx_ftsmps_get_mode(rdev); | 
|  | 2648 | pr_info("%s %-9s: %s, v=%7d uV, mode=%s\n", | 
|  | 2649 | action_label, vreg->rdesc.name, enable_label, uV, | 
|  | 2650 | (mode == REGULATOR_MODE_NORMAL ? "HPM" : "LPM")); | 
|  | 2651 | break; | 
|  | 2652 | case PM8XXX_REGULATOR_TYPE_VS: | 
|  | 2653 | pr_info("%s %-9s: %s, pc=%s%s%s%s%s\n", | 
|  | 2654 | action_label, vreg->rdesc.name, enable_label, | 
|  | 2655 | pc_en0, pc_en1, pc_en2, pc_en3, pc_total); | 
|  | 2656 | break; | 
|  | 2657 | case PM8XXX_REGULATOR_TYPE_VS300: | 
|  | 2658 | pr_info("%s %-9s: %s\n", | 
|  | 2659 | action_label, vreg->rdesc.name, enable_label); | 
|  | 2660 | break; | 
|  | 2661 | case PM8XXX_REGULATOR_TYPE_NCP: | 
|  | 2662 | uV = pm8xxx_ncp_get_voltage(rdev); | 
|  | 2663 | pr_info("%s %-9s: %s, v=%7d uV\n", | 
|  | 2664 | action_label, vreg->rdesc.name, enable_label, uV); | 
|  | 2665 | break; | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 2666 | case PM8XXX_REGULATOR_TYPE_BOOST: | 
|  | 2667 | uV = pm8xxx_boost_get_voltage(rdev); | 
|  | 2668 | pr_info("%s %-9s: %s, v=%7d uV\n", | 
|  | 2669 | action_label, vreg->rdesc.name, enable_label, uV); | 
|  | 2670 | break; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2671 | default: | 
|  | 2672 | break; | 
|  | 2673 | } | 
|  | 2674 | } | 
|  | 2675 |  | 
|  | 2676 | /* Real regulator operations. */ | 
|  | 2677 | static struct regulator_ops pm8xxx_pldo_ops = { | 
|  | 2678 | .enable			= pm8xxx_ldo_enable, | 
|  | 2679 | .disable		= pm8xxx_ldo_disable, | 
|  | 2680 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2681 | .set_voltage		= pm8xxx_pldo_set_voltage, | 
|  | 2682 | .get_voltage		= pm8xxx_pldo_get_voltage, | 
|  | 2683 | .list_voltage		= pm8xxx_pldo_list_voltage, | 
|  | 2684 | .set_mode		= pm8xxx_ldo_set_mode, | 
|  | 2685 | .get_mode		= pm8xxx_ldo_get_mode, | 
|  | 2686 | .get_optimum_mode	= pm8xxx_vreg_get_optimum_mode, | 
|  | 2687 | .enable_time		= pm8xxx_enable_time, | 
|  | 2688 | }; | 
|  | 2689 |  | 
|  | 2690 | static struct regulator_ops pm8xxx_nldo_ops = { | 
|  | 2691 | .enable			= pm8xxx_ldo_enable, | 
|  | 2692 | .disable		= pm8xxx_ldo_disable, | 
|  | 2693 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2694 | .set_voltage		= pm8xxx_nldo_set_voltage, | 
|  | 2695 | .get_voltage		= pm8xxx_nldo_get_voltage, | 
|  | 2696 | .list_voltage		= pm8xxx_nldo_list_voltage, | 
|  | 2697 | .set_mode		= pm8xxx_ldo_set_mode, | 
|  | 2698 | .get_mode		= pm8xxx_ldo_get_mode, | 
|  | 2699 | .get_optimum_mode	= pm8xxx_vreg_get_optimum_mode, | 
|  | 2700 | .enable_time		= pm8xxx_enable_time, | 
|  | 2701 | }; | 
|  | 2702 |  | 
|  | 2703 | static struct regulator_ops pm8xxx_nldo1200_ops = { | 
|  | 2704 | .enable			= pm8xxx_nldo1200_enable, | 
|  | 2705 | .disable		= pm8xxx_nldo1200_disable, | 
|  | 2706 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2707 | .set_voltage		= pm8xxx_nldo1200_set_voltage, | 
|  | 2708 | .get_voltage		= pm8xxx_nldo1200_get_voltage, | 
|  | 2709 | .list_voltage		= pm8xxx_nldo1200_list_voltage, | 
|  | 2710 | .set_mode		= pm8xxx_nldo1200_set_mode, | 
|  | 2711 | .get_mode		= pm8xxx_nldo1200_get_mode, | 
|  | 2712 | .get_optimum_mode	= pm8xxx_vreg_get_optimum_mode, | 
|  | 2713 | .enable_time		= pm8xxx_enable_time, | 
|  | 2714 | }; | 
|  | 2715 |  | 
|  | 2716 | static struct regulator_ops pm8xxx_smps_ops = { | 
|  | 2717 | .enable			= pm8xxx_smps_enable, | 
|  | 2718 | .disable		= pm8xxx_smps_disable, | 
|  | 2719 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2720 | .set_voltage		= pm8xxx_smps_set_voltage, | 
|  | 2721 | .get_voltage		= pm8xxx_smps_get_voltage, | 
|  | 2722 | .list_voltage		= pm8xxx_smps_list_voltage, | 
|  | 2723 | .set_mode		= pm8xxx_smps_set_mode, | 
|  | 2724 | .get_mode		= pm8xxx_smps_get_mode, | 
|  | 2725 | .get_optimum_mode	= pm8xxx_vreg_get_optimum_mode, | 
|  | 2726 | .enable_time		= pm8xxx_enable_time, | 
|  | 2727 | }; | 
|  | 2728 |  | 
|  | 2729 | static struct regulator_ops pm8xxx_ftsmps_ops = { | 
|  | 2730 | .enable			= pm8xxx_ftsmps_enable, | 
|  | 2731 | .disable		= pm8xxx_ftsmps_disable, | 
|  | 2732 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2733 | .set_voltage		= pm8xxx_ftsmps_set_voltage, | 
|  | 2734 | .get_voltage		= pm8xxx_ftsmps_get_voltage, | 
|  | 2735 | .list_voltage		= pm8xxx_ftsmps_list_voltage, | 
|  | 2736 | .set_mode		= pm8xxx_ftsmps_set_mode, | 
|  | 2737 | .get_mode		= pm8xxx_ftsmps_get_mode, | 
|  | 2738 | .get_optimum_mode	= pm8xxx_vreg_get_optimum_mode, | 
|  | 2739 | .enable_time		= pm8xxx_enable_time, | 
|  | 2740 | }; | 
|  | 2741 |  | 
|  | 2742 | static struct regulator_ops pm8xxx_vs_ops = { | 
|  | 2743 | .enable			= pm8xxx_vs_enable, | 
|  | 2744 | .disable		= pm8xxx_vs_disable, | 
|  | 2745 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2746 | .enable_time		= pm8xxx_enable_time, | 
|  | 2747 | }; | 
|  | 2748 |  | 
|  | 2749 | static struct regulator_ops pm8xxx_vs300_ops = { | 
|  | 2750 | .enable			= pm8xxx_vs300_enable, | 
|  | 2751 | .disable		= pm8xxx_vs300_disable, | 
|  | 2752 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2753 | .enable_time		= pm8xxx_enable_time, | 
|  | 2754 | }; | 
|  | 2755 |  | 
|  | 2756 | static struct regulator_ops pm8xxx_ncp_ops = { | 
|  | 2757 | .enable			= pm8xxx_ncp_enable, | 
|  | 2758 | .disable		= pm8xxx_ncp_disable, | 
|  | 2759 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2760 | .set_voltage		= pm8xxx_ncp_set_voltage, | 
|  | 2761 | .get_voltage		= pm8xxx_ncp_get_voltage, | 
|  | 2762 | .list_voltage		= pm8xxx_ncp_list_voltage, | 
|  | 2763 | .enable_time		= pm8xxx_enable_time, | 
|  | 2764 | }; | 
|  | 2765 |  | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 2766 | static struct regulator_ops pm8xxx_boost_ops = { | 
|  | 2767 | .enable			= pm8xxx_boost_enable, | 
|  | 2768 | .disable		= pm8xxx_boost_disable, | 
|  | 2769 | .is_enabled		= pm8xxx_vreg_is_enabled, | 
|  | 2770 | .set_voltage		= pm8xxx_boost_set_voltage, | 
|  | 2771 | .get_voltage		= pm8xxx_boost_get_voltage, | 
|  | 2772 | .list_voltage		= pm8xxx_boost_list_voltage, | 
|  | 2773 | .enable_time		= pm8xxx_enable_time, | 
|  | 2774 | }; | 
|  | 2775 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2776 | /* Pin control regulator operations. */ | 
|  | 2777 | static struct regulator_ops pm8xxx_ldo_pc_ops = { | 
|  | 2778 | .enable			= pm8xxx_ldo_pin_control_enable, | 
|  | 2779 | .disable		= pm8xxx_ldo_pin_control_disable, | 
|  | 2780 | .is_enabled		= pm8xxx_vreg_pin_control_is_enabled, | 
|  | 2781 | }; | 
|  | 2782 |  | 
|  | 2783 | static struct regulator_ops pm8xxx_smps_pc_ops = { | 
|  | 2784 | .enable			= pm8xxx_smps_pin_control_enable, | 
|  | 2785 | .disable		= pm8xxx_smps_pin_control_disable, | 
|  | 2786 | .is_enabled		= pm8xxx_vreg_pin_control_is_enabled, | 
|  | 2787 | }; | 
|  | 2788 |  | 
|  | 2789 | static struct regulator_ops pm8xxx_vs_pc_ops = { | 
|  | 2790 | .enable			= pm8xxx_vs_pin_control_enable, | 
|  | 2791 | .disable		= pm8xxx_vs_pin_control_disable, | 
|  | 2792 | .is_enabled		= pm8xxx_vreg_pin_control_is_enabled, | 
|  | 2793 | }; | 
|  | 2794 |  | 
|  | 2795 | static struct regulator_ops *pm8xxx_reg_ops[PM8XXX_REGULATOR_TYPE_MAX] = { | 
|  | 2796 | [PM8XXX_REGULATOR_TYPE_PLDO]		= &pm8xxx_pldo_ops, | 
|  | 2797 | [PM8XXX_REGULATOR_TYPE_NLDO]		= &pm8xxx_nldo_ops, | 
|  | 2798 | [PM8XXX_REGULATOR_TYPE_NLDO1200]	= &pm8xxx_nldo1200_ops, | 
|  | 2799 | [PM8XXX_REGULATOR_TYPE_SMPS]		= &pm8xxx_smps_ops, | 
|  | 2800 | [PM8XXX_REGULATOR_TYPE_FTSMPS]		= &pm8xxx_ftsmps_ops, | 
|  | 2801 | [PM8XXX_REGULATOR_TYPE_VS]		= &pm8xxx_vs_ops, | 
|  | 2802 | [PM8XXX_REGULATOR_TYPE_VS300]		= &pm8xxx_vs300_ops, | 
|  | 2803 | [PM8XXX_REGULATOR_TYPE_NCP]		= &pm8xxx_ncp_ops, | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 2804 | [PM8XXX_REGULATOR_TYPE_BOOST]		= &pm8xxx_boost_ops, | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2805 | }; | 
|  | 2806 |  | 
|  | 2807 | static struct regulator_ops *pm8xxx_reg_pc_ops[PM8XXX_REGULATOR_TYPE_MAX] = { | 
|  | 2808 | [PM8XXX_REGULATOR_TYPE_PLDO]		= &pm8xxx_ldo_pc_ops, | 
|  | 2809 | [PM8XXX_REGULATOR_TYPE_NLDO]		= &pm8xxx_ldo_pc_ops, | 
|  | 2810 | [PM8XXX_REGULATOR_TYPE_SMPS]		= &pm8xxx_smps_pc_ops, | 
|  | 2811 | [PM8XXX_REGULATOR_TYPE_VS]		= &pm8xxx_vs_pc_ops, | 
|  | 2812 | }; | 
|  | 2813 |  | 
|  | 2814 | static unsigned pm8xxx_n_voltages[PM8XXX_REGULATOR_TYPE_MAX] = { | 
|  | 2815 | [PM8XXX_REGULATOR_TYPE_PLDO]		= PLDO_SET_POINTS, | 
|  | 2816 | [PM8XXX_REGULATOR_TYPE_NLDO]		= NLDO_SET_POINTS, | 
|  | 2817 | [PM8XXX_REGULATOR_TYPE_NLDO1200]	= NLDO1200_SET_POINTS, | 
|  | 2818 | [PM8XXX_REGULATOR_TYPE_SMPS]		= SMPS_ADVANCED_SET_POINTS, | 
|  | 2819 | [PM8XXX_REGULATOR_TYPE_FTSMPS]		= FTSMPS_SET_POINTS, | 
|  | 2820 | [PM8XXX_REGULATOR_TYPE_VS]		= 0, | 
|  | 2821 | [PM8XXX_REGULATOR_TYPE_VS300]		= 0, | 
|  | 2822 | [PM8XXX_REGULATOR_TYPE_NCP]		= NCP_SET_POINTS, | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 2823 | [PM8XXX_REGULATOR_TYPE_BOOST]		= BOOST_SET_POINTS, | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 2824 | }; | 
|  | 2825 |  | 
|  | 2826 | static int pm8xxx_init_ldo(struct pm8xxx_vreg *vreg, bool is_real) | 
|  | 2827 | { | 
|  | 2828 | int rc = 0; | 
|  | 2829 | int i; | 
|  | 2830 | u8 bank; | 
|  | 2831 |  | 
|  | 2832 | /* Save the current control register state. */ | 
|  | 2833 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 2834 | if (rc) | 
|  | 2835 | goto bail; | 
|  | 2836 |  | 
|  | 2837 | /* Save the current test register state. */ | 
|  | 2838 | for (i = 0; i < LDO_TEST_BANKS; i++) { | 
|  | 2839 | bank = REGULATOR_BANK_SEL(i); | 
|  | 2840 | rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank); | 
|  | 2841 | if (rc) | 
|  | 2842 | goto bail; | 
|  | 2843 |  | 
|  | 2844 | rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr, | 
|  | 2845 | &vreg->test_reg[i]); | 
|  | 2846 | if (rc) | 
|  | 2847 | goto bail; | 
|  | 2848 | vreg->test_reg[i] |= REGULATOR_BANK_WRITE; | 
|  | 2849 | } | 
|  | 2850 |  | 
|  | 2851 | if (is_real) { | 
|  | 2852 | /* Set pull down enable based on platform data. */ | 
|  | 2853 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2854 | (vreg->pdata.pull_down_enable ? LDO_PULL_DOWN_ENABLE : 0), | 
|  | 2855 | LDO_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 2856 |  | 
|  | 2857 | vreg->is_enabled = !!_pm8xxx_vreg_is_enabled(vreg); | 
|  | 2858 |  | 
|  | 2859 | vreg->mode = ((vreg->ctrl_reg & LDO_CTRL_PM_MASK) | 
|  | 2860 | == LDO_CTRL_PM_LPM ? | 
|  | 2861 | REGULATOR_MODE_IDLE : REGULATOR_MODE_NORMAL); | 
|  | 2862 | } | 
|  | 2863 | bail: | 
|  | 2864 | if (rc) | 
|  | 2865 | vreg_err(vreg, "pm8xxx_readb/writeb failed, rc=%d\n", rc); | 
|  | 2866 |  | 
|  | 2867 | return rc; | 
|  | 2868 | } | 
|  | 2869 |  | 
|  | 2870 | static int pm8xxx_init_nldo1200(struct pm8xxx_vreg *vreg) | 
|  | 2871 | { | 
|  | 2872 | int rc = 0; | 
|  | 2873 | int i; | 
|  | 2874 | u8 bank; | 
|  | 2875 |  | 
|  | 2876 | /* Save the current control register state. */ | 
|  | 2877 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 2878 | if (rc) | 
|  | 2879 | goto bail; | 
|  | 2880 |  | 
|  | 2881 | /* Save the current test register state. */ | 
|  | 2882 | for (i = 0; i < LDO_TEST_BANKS; i++) { | 
|  | 2883 | bank = REGULATOR_BANK_SEL(i); | 
|  | 2884 | rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank); | 
|  | 2885 | if (rc) | 
|  | 2886 | goto bail; | 
|  | 2887 |  | 
|  | 2888 | rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr, | 
|  | 2889 | &vreg->test_reg[i]); | 
|  | 2890 | if (rc) | 
|  | 2891 | goto bail; | 
|  | 2892 | vreg->test_reg[i] |= REGULATOR_BANK_WRITE; | 
|  | 2893 | } | 
|  | 2894 |  | 
|  | 2895 | vreg->save_uV = _pm8xxx_nldo1200_get_voltage(vreg); | 
|  | 2896 |  | 
|  | 2897 | /* Set pull down enable based on platform data. */ | 
|  | 2898 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2899 | (vreg->pdata.pull_down_enable ? NLDO1200_PULL_DOWN_ENABLE : 0) | 
|  | 2900 | | REGULATOR_BANK_SEL(1) | REGULATOR_BANK_WRITE, | 
|  | 2901 | NLDO1200_PULL_DOWN_ENABLE_MASK | REGULATOR_BANK_MASK, | 
|  | 2902 | &vreg->test_reg[1]); | 
|  | 2903 |  | 
|  | 2904 | bail: | 
|  | 2905 | if (rc) | 
|  | 2906 | vreg_err(vreg, "pm8xxx_readb/writeb failed, rc=%d\n", rc); | 
|  | 2907 |  | 
|  | 2908 | return rc; | 
|  | 2909 | } | 
|  | 2910 |  | 
|  | 2911 | static int pm8xxx_init_smps(struct pm8xxx_vreg *vreg, bool is_real) | 
|  | 2912 | { | 
|  | 2913 | int rc = 0; | 
|  | 2914 | int i; | 
|  | 2915 | u8 bank; | 
|  | 2916 |  | 
|  | 2917 | /* Save the current control register state. */ | 
|  | 2918 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 2919 | if (rc) | 
|  | 2920 | goto bail; | 
|  | 2921 |  | 
|  | 2922 | /* Save the current test2 register state. */ | 
|  | 2923 | for (i = 0; i < SMPS_TEST_BANKS; i++) { | 
|  | 2924 | bank = REGULATOR_BANK_SEL(i); | 
|  | 2925 | rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank); | 
|  | 2926 | if (rc) | 
|  | 2927 | goto bail; | 
|  | 2928 |  | 
|  | 2929 | rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr, | 
|  | 2930 | &vreg->test_reg[i]); | 
|  | 2931 | if (rc) | 
|  | 2932 | goto bail; | 
|  | 2933 | vreg->test_reg[i] |= REGULATOR_BANK_WRITE; | 
|  | 2934 | } | 
|  | 2935 |  | 
|  | 2936 | /* Save the current clock control register state. */ | 
|  | 2937 | rc = pm8xxx_readb(vreg->dev->parent, vreg->clk_ctrl_addr, | 
|  | 2938 | &vreg->clk_ctrl_reg); | 
|  | 2939 | if (rc) | 
|  | 2940 | goto bail; | 
|  | 2941 |  | 
|  | 2942 | /* Save the current sleep control register state. */ | 
|  | 2943 | rc = pm8xxx_readb(vreg->dev->parent, vreg->sleep_ctrl_addr, | 
|  | 2944 | &vreg->sleep_ctrl_reg); | 
|  | 2945 | if (rc) | 
|  | 2946 | goto bail; | 
|  | 2947 |  | 
|  | 2948 | vreg->save_uV = _pm8xxx_smps_get_voltage(vreg); | 
|  | 2949 |  | 
|  | 2950 | if (is_real) { | 
|  | 2951 | /* Set advanced mode pull down enable based on platform data. */ | 
|  | 2952 | rc = pm8xxx_vreg_masked_write(vreg, vreg->test_addr, | 
|  | 2953 | (vreg->pdata.pull_down_enable | 
|  | 2954 | ? SMPS_ADVANCED_PULL_DOWN_ENABLE : 0) | 
|  | 2955 | | REGULATOR_BANK_SEL(6) | REGULATOR_BANK_WRITE, | 
|  | 2956 | REGULATOR_BANK_MASK | SMPS_ADVANCED_PULL_DOWN_ENABLE, | 
|  | 2957 | &vreg->test_reg[6]); | 
|  | 2958 | if (rc) | 
|  | 2959 | goto bail; | 
|  | 2960 |  | 
|  | 2961 | vreg->is_enabled = !!_pm8xxx_vreg_is_enabled(vreg); | 
|  | 2962 |  | 
|  | 2963 | vreg->mode = ((vreg->clk_ctrl_reg & SMPS_CLK_CTRL_MASK) | 
|  | 2964 | == SMPS_CLK_CTRL_PFM ? | 
|  | 2965 | REGULATOR_MODE_IDLE : REGULATOR_MODE_NORMAL); | 
|  | 2966 | } | 
|  | 2967 |  | 
|  | 2968 | if (!SMPS_IN_ADVANCED_MODE(vreg) && is_real) { | 
|  | 2969 | /* Set legacy mode pull down enable based on platform data. */ | 
|  | 2970 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 2971 | (vreg->pdata.pull_down_enable | 
|  | 2972 | ? SMPS_LEGACY_PULL_DOWN_ENABLE : 0), | 
|  | 2973 | SMPS_LEGACY_PULL_DOWN_ENABLE, &vreg->ctrl_reg); | 
|  | 2974 | if (rc) | 
|  | 2975 | goto bail; | 
|  | 2976 | } | 
|  | 2977 |  | 
|  | 2978 | bail: | 
|  | 2979 | if (rc) | 
|  | 2980 | vreg_err(vreg, "pm8xxx_readb/writeb failed, rc=%d\n", rc); | 
|  | 2981 |  | 
|  | 2982 | return rc; | 
|  | 2983 | } | 
|  | 2984 |  | 
|  | 2985 | static int pm8xxx_init_ftsmps(struct pm8xxx_vreg *vreg) | 
|  | 2986 | { | 
|  | 2987 | int rc, i; | 
|  | 2988 | u8 bank; | 
|  | 2989 |  | 
|  | 2990 | /* Save the current control register state. */ | 
|  | 2991 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 2992 | if (rc) | 
|  | 2993 | goto bail; | 
|  | 2994 |  | 
|  | 2995 | /* Store current regulator register values. */ | 
|  | 2996 | rc = pm8xxx_readb(vreg->dev->parent, vreg->pfm_ctrl_addr, | 
|  | 2997 | &vreg->pfm_ctrl_reg); | 
|  | 2998 | if (rc) | 
|  | 2999 | goto bail; | 
|  | 3000 |  | 
|  | 3001 | rc = pm8xxx_readb(vreg->dev->parent, vreg->pwr_cnfg_addr, | 
|  | 3002 | &vreg->pwr_cnfg_reg); | 
|  | 3003 | if (rc) | 
|  | 3004 | goto bail; | 
|  | 3005 |  | 
|  | 3006 | /* Save the current fts_cnfg1 register state (uses 'test' member). */ | 
|  | 3007 | for (i = 0; i < SMPS_TEST_BANKS; i++) { | 
|  | 3008 | bank = REGULATOR_BANK_SEL(i); | 
|  | 3009 | rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank); | 
|  | 3010 | if (rc) | 
|  | 3011 | goto bail; | 
|  | 3012 |  | 
|  | 3013 | rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr, | 
|  | 3014 | &vreg->test_reg[i]); | 
|  | 3015 | if (rc) | 
|  | 3016 | goto bail; | 
|  | 3017 | vreg->test_reg[i] |= REGULATOR_BANK_WRITE; | 
|  | 3018 | } | 
|  | 3019 |  | 
|  | 3020 | vreg->save_uV = _pm8xxx_ftsmps_get_voltage(vreg); | 
|  | 3021 |  | 
|  | 3022 | /* Set pull down enable based on platform data. */ | 
|  | 3023 | rc = pm8xxx_vreg_masked_write(vreg, vreg->pwr_cnfg_addr, | 
|  | 3024 | (vreg->pdata.pull_down_enable ? FTSMPS_PULL_DOWN_ENABLE : 0), | 
|  | 3025 | FTSMPS_PULL_DOWN_ENABLE_MASK, &vreg->pwr_cnfg_reg); | 
|  | 3026 |  | 
|  | 3027 | bail: | 
|  | 3028 | if (rc) | 
|  | 3029 | vreg_err(vreg, "pm8xxx_readb/writeb failed, rc=%d\n", rc); | 
|  | 3030 |  | 
|  | 3031 | return rc; | 
|  | 3032 | } | 
|  | 3033 |  | 
|  | 3034 | static int pm8xxx_init_vs(struct pm8xxx_vreg *vreg, bool is_real) | 
|  | 3035 | { | 
|  | 3036 | int rc = 0; | 
|  | 3037 |  | 
|  | 3038 | /* Save the current control register state. */ | 
|  | 3039 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 3040 | if (rc) { | 
|  | 3041 | vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc); | 
|  | 3042 | return rc; | 
|  | 3043 | } | 
|  | 3044 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 3045 | /* Save the current test register state. */ | 
|  | 3046 | rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr, | 
|  | 3047 | &vreg->test_reg[0]); | 
|  | 3048 | if (rc) { | 
|  | 3049 | vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc); | 
|  | 3050 | return rc; | 
|  | 3051 | } | 
|  | 3052 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3053 | if (is_real) { | 
|  | 3054 | /* Set pull down enable based on platform data. */ | 
|  | 3055 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 3056 | (vreg->pdata.pull_down_enable ? VS_PULL_DOWN_ENABLE | 
|  | 3057 | : VS_PULL_DOWN_DISABLE), | 
|  | 3058 | VS_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 3059 |  | 
|  | 3060 | if (rc) | 
|  | 3061 | vreg_err(vreg, | 
|  | 3062 | "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 3063 |  | 
|  | 3064 | vreg->is_enabled = !!_pm8xxx_vreg_is_enabled(vreg); | 
|  | 3065 | } | 
|  | 3066 |  | 
|  | 3067 | return rc; | 
|  | 3068 | } | 
|  | 3069 |  | 
|  | 3070 | static int pm8xxx_init_vs300(struct pm8xxx_vreg *vreg) | 
|  | 3071 | { | 
|  | 3072 | int rc; | 
|  | 3073 |  | 
|  | 3074 | /* Save the current control register state. */ | 
|  | 3075 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 3076 | if (rc) { | 
|  | 3077 | vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc); | 
|  | 3078 | return rc; | 
|  | 3079 | } | 
|  | 3080 |  | 
| David Collins | 0c19fa8 | 2012-01-30 11:23:38 -0800 | [diff] [blame] | 3081 | /* Save the current test register state. */ | 
|  | 3082 | rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr, | 
|  | 3083 | &vreg->test_reg[0]); | 
|  | 3084 | if (rc) { | 
|  | 3085 | vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc); | 
|  | 3086 | return rc; | 
|  | 3087 | } | 
|  | 3088 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3089 | /* Set pull down enable based on platform data. */ | 
|  | 3090 | rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, | 
|  | 3091 | (vreg->pdata.pull_down_enable ? VS300_PULL_DOWN_ENABLE : 0), | 
|  | 3092 | VS300_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg); | 
|  | 3093 |  | 
|  | 3094 | if (rc) | 
|  | 3095 | vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc); | 
|  | 3096 |  | 
|  | 3097 | return rc; | 
|  | 3098 | } | 
|  | 3099 |  | 
|  | 3100 | static int pm8xxx_init_ncp(struct pm8xxx_vreg *vreg) | 
|  | 3101 | { | 
|  | 3102 | int rc; | 
|  | 3103 |  | 
|  | 3104 | /* Save the current control register state. */ | 
|  | 3105 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 3106 | if (rc) { | 
|  | 3107 | vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc); | 
|  | 3108 | return rc; | 
|  | 3109 | } | 
|  | 3110 |  | 
|  | 3111 | return rc; | 
|  | 3112 | } | 
|  | 3113 |  | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 3114 | static int pm8xxx_init_boost(struct pm8xxx_vreg *vreg) | 
|  | 3115 | { | 
|  | 3116 | int rc; | 
|  | 3117 |  | 
|  | 3118 | /* Save the current control register state. */ | 
|  | 3119 | rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg); | 
|  | 3120 | if (rc) { | 
|  | 3121 | vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc); | 
|  | 3122 | return rc; | 
|  | 3123 | } | 
|  | 3124 |  | 
|  | 3125 | return rc; | 
|  | 3126 | } | 
|  | 3127 |  | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3128 | static int __devinit pm8xxx_vreg_probe(struct platform_device *pdev) | 
|  | 3129 | { | 
|  | 3130 | struct pm8xxx_regulator_core_platform_data *core_data; | 
|  | 3131 | const struct pm8xxx_regulator_platform_data *pdata; | 
|  | 3132 | enum pm8xxx_vreg_pin_function pin_fn; | 
|  | 3133 | struct regulator_desc *rdesc; | 
|  | 3134 | struct pm8xxx_vreg *vreg; | 
|  | 3135 | unsigned pin_ctrl; | 
|  | 3136 | int rc = 0; | 
|  | 3137 |  | 
|  | 3138 | if (pdev == NULL) { | 
|  | 3139 | pr_err("no platform device specified\n"); | 
|  | 3140 | return -EINVAL; | 
|  | 3141 | } | 
|  | 3142 |  | 
|  | 3143 | core_data = pdev->dev.platform_data; | 
|  | 3144 | if (core_data == NULL) { | 
|  | 3145 | pr_err("no core data specified\n"); | 
|  | 3146 | return -EINVAL; | 
|  | 3147 | } | 
|  | 3148 |  | 
|  | 3149 | pdata = core_data->pdata; | 
|  | 3150 | vreg = core_data->vreg; | 
|  | 3151 | if (pdata == NULL) { | 
|  | 3152 | pr_err("no pdata specified\n"); | 
|  | 3153 | return -EINVAL; | 
|  | 3154 | } else if (vreg == NULL) { | 
|  | 3155 | pr_err("no vreg specified\n"); | 
|  | 3156 | return -EINVAL; | 
|  | 3157 | } | 
|  | 3158 |  | 
|  | 3159 | if (vreg->rdesc.name == NULL) { | 
|  | 3160 | pr_err("regulator name missing\n"); | 
|  | 3161 | return -EINVAL; | 
| David Collins | 79952fe | 2012-03-09 16:11:22 -0800 | [diff] [blame] | 3162 | } else if (vreg->type < 0 || vreg->type >= PM8XXX_REGULATOR_TYPE_MAX) { | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3163 | pr_err("%s: regulator type=%d is invalid\n", vreg->rdesc.name, | 
|  | 3164 | vreg->type); | 
|  | 3165 | return -EINVAL; | 
|  | 3166 | } else if (core_data->is_pin_controlled | 
|  | 3167 | && pm8xxx_reg_pc_ops[vreg->type] == NULL) { | 
|  | 3168 | pr_err("%s: regulator type=%d does not support pin control\n", | 
|  | 3169 | vreg->rdesc.name, vreg->type); | 
|  | 3170 | return -EINVAL; | 
|  | 3171 | } else if (core_data->is_pin_controlled | 
|  | 3172 | && vreg->rdesc_pc.name == NULL) { | 
|  | 3173 | pr_err("%s: regulator pin control name missing\n", | 
|  | 3174 | vreg->rdesc.name); | 
|  | 3175 | return -EINVAL; | 
|  | 3176 | } | 
|  | 3177 |  | 
|  | 3178 | if (core_data->is_pin_controlled) | 
|  | 3179 | rdesc = &vreg->rdesc_pc; | 
|  | 3180 | else | 
|  | 3181 | rdesc = &vreg->rdesc; | 
|  | 3182 | if (!pdata) { | 
|  | 3183 | pr_err("%s requires platform data\n", vreg->rdesc.name); | 
|  | 3184 | return -EINVAL; | 
|  | 3185 | } | 
|  | 3186 |  | 
|  | 3187 | rdesc->id    = pdev->id; | 
|  | 3188 | rdesc->owner = THIS_MODULE; | 
|  | 3189 | rdesc->type  = REGULATOR_VOLTAGE; | 
|  | 3190 | if (core_data->is_pin_controlled) { | 
|  | 3191 | rdesc->ops = pm8xxx_reg_pc_ops[vreg->type]; | 
|  | 3192 | rdesc->n_voltages = 0; | 
|  | 3193 | } else { | 
|  | 3194 | rdesc->ops = pm8xxx_reg_ops[vreg->type]; | 
|  | 3195 | rdesc->n_voltages = pm8xxx_n_voltages[vreg->type]; | 
|  | 3196 | } | 
|  | 3197 |  | 
|  | 3198 | mutex_lock(&vreg->pc_lock); | 
|  | 3199 |  | 
|  | 3200 | if (!core_data->is_pin_controlled) { | 
|  | 3201 | /* Do not modify pin control and pin function values. */ | 
|  | 3202 | pin_ctrl = vreg->pdata.pin_ctrl; | 
|  | 3203 | pin_fn = vreg->pdata.pin_fn; | 
|  | 3204 | memcpy(&(vreg->pdata), pdata, | 
|  | 3205 | sizeof(struct pm8xxx_regulator_platform_data)); | 
|  | 3206 | vreg->pdata.pin_ctrl = pin_ctrl; | 
|  | 3207 | vreg->pdata.pin_fn = pin_fn; | 
| David Collins | d161f5a | 2012-05-25 14:44:45 -0700 | [diff] [blame] | 3208 | /* | 
|  | 3209 | * If slew_rate isn't specified but enable_time is, then set | 
|  | 3210 | * slew_rate = max_uV / enable_time. | 
|  | 3211 | */ | 
|  | 3212 | if (vreg->pdata.enable_time > 0 | 
|  | 3213 | && vreg->pdata.init_data.constraints.max_uV > 0 | 
|  | 3214 | && vreg->pdata.slew_rate <= 0) | 
|  | 3215 | vreg->pdata.slew_rate = | 
|  | 3216 | DIV_ROUND_UP(vreg->pdata.init_data.constraints.max_uV, | 
|  | 3217 | vreg->pdata.enable_time); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3218 | vreg->dev = &pdev->dev; | 
|  | 3219 | } else { | 
|  | 3220 | /* Pin control regulator */ | 
|  | 3221 | if ((pdata->pin_ctrl & PM8XXX_VREG_PIN_CTRL_ALL) | 
|  | 3222 | == PM8XXX_VREG_PIN_CTRL_NONE) { | 
|  | 3223 | pr_err("%s: no pin control input specified\n", | 
|  | 3224 | vreg->rdesc.name); | 
|  | 3225 | mutex_unlock(&vreg->pc_lock); | 
|  | 3226 | return -EINVAL; | 
|  | 3227 | } | 
|  | 3228 | vreg->pdata.pin_ctrl = pdata->pin_ctrl; | 
|  | 3229 | vreg->pdata.pin_fn = pdata->pin_fn; | 
|  | 3230 | vreg->dev_pc = &pdev->dev; | 
|  | 3231 | if (!vreg->dev) | 
|  | 3232 | vreg->dev = &pdev->dev; | 
|  | 3233 | } | 
|  | 3234 |  | 
|  | 3235 | /* Initialize register values. */ | 
|  | 3236 | switch (vreg->type) { | 
|  | 3237 | case PM8XXX_REGULATOR_TYPE_PLDO: | 
|  | 3238 | case PM8XXX_REGULATOR_TYPE_NLDO: | 
|  | 3239 | rc = pm8xxx_init_ldo(vreg, !core_data->is_pin_controlled); | 
|  | 3240 | break; | 
|  | 3241 | case PM8XXX_REGULATOR_TYPE_NLDO1200: | 
|  | 3242 | rc = pm8xxx_init_nldo1200(vreg); | 
|  | 3243 | break; | 
|  | 3244 | case PM8XXX_REGULATOR_TYPE_SMPS: | 
|  | 3245 | rc = pm8xxx_init_smps(vreg, !core_data->is_pin_controlled); | 
|  | 3246 | break; | 
|  | 3247 | case PM8XXX_REGULATOR_TYPE_FTSMPS: | 
|  | 3248 | rc = pm8xxx_init_ftsmps(vreg); | 
|  | 3249 | break; | 
|  | 3250 | case PM8XXX_REGULATOR_TYPE_VS: | 
|  | 3251 | rc = pm8xxx_init_vs(vreg, !core_data->is_pin_controlled); | 
|  | 3252 | break; | 
|  | 3253 | case PM8XXX_REGULATOR_TYPE_VS300: | 
|  | 3254 | rc = pm8xxx_init_vs300(vreg); | 
|  | 3255 | break; | 
|  | 3256 | case PM8XXX_REGULATOR_TYPE_NCP: | 
|  | 3257 | rc = pm8xxx_init_ncp(vreg); | 
|  | 3258 | break; | 
| David Collins | 525da18 | 2012-02-13 10:36:37 -0800 | [diff] [blame] | 3259 | case PM8XXX_REGULATOR_TYPE_BOOST: | 
|  | 3260 | rc = pm8xxx_init_boost(vreg); | 
|  | 3261 | break; | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3262 | default: | 
|  | 3263 | break; | 
|  | 3264 | } | 
|  | 3265 |  | 
|  | 3266 | mutex_unlock(&vreg->pc_lock); | 
|  | 3267 |  | 
|  | 3268 | if (rc) | 
|  | 3269 | goto bail; | 
|  | 3270 |  | 
|  | 3271 | if (!core_data->is_pin_controlled) { | 
|  | 3272 | vreg->rdev = regulator_register(rdesc, &pdev->dev, | 
| Rajendra Nayak | 11eafc6 | 2011-11-18 16:47:19 +0530 | [diff] [blame] | 3273 | &(pdata->init_data), vreg, NULL); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3274 | if (IS_ERR(vreg->rdev)) { | 
|  | 3275 | rc = PTR_ERR(vreg->rdev); | 
|  | 3276 | vreg->rdev = NULL; | 
|  | 3277 | pr_err("regulator_register failed: %s, rc=%d\n", | 
|  | 3278 | vreg->rdesc.name, rc); | 
|  | 3279 | } | 
|  | 3280 | } else { | 
|  | 3281 | vreg->rdev_pc = regulator_register(rdesc, &pdev->dev, | 
| Rajendra Nayak | 11eafc6 | 2011-11-18 16:47:19 +0530 | [diff] [blame] | 3282 | &(pdata->init_data), vreg, NULL); | 
| David Collins | 5c4a5ab | 2011-12-02 15:01:26 -0800 | [diff] [blame] | 3283 | if (IS_ERR(vreg->rdev_pc)) { | 
|  | 3284 | rc = PTR_ERR(vreg->rdev_pc); | 
|  | 3285 | vreg->rdev_pc = NULL; | 
|  | 3286 | pr_err("regulator_register failed: %s, rc=%d\n", | 
|  | 3287 | vreg->rdesc.name, rc); | 
|  | 3288 | } | 
|  | 3289 | } | 
|  | 3290 | if ((pm8xxx_vreg_debug_mask & PM8XXX_VREG_DEBUG_INIT) && !rc | 
|  | 3291 | && vreg->rdev) | 
|  | 3292 | pm8xxx_vreg_show_state(vreg->rdev, | 
|  | 3293 | PM8XXX_REGULATOR_ACTION_INIT); | 
|  | 3294 |  | 
|  | 3295 | platform_set_drvdata(pdev, core_data); | 
|  | 3296 |  | 
|  | 3297 | bail: | 
|  | 3298 | if (rc) | 
|  | 3299 | pr_err("error for %s, rc=%d\n", vreg->rdesc.name, rc); | 
|  | 3300 |  | 
|  | 3301 | return rc; | 
|  | 3302 | } | 
|  | 3303 |  | 
|  | 3304 | static int __devexit pm8xxx_vreg_remove(struct platform_device *pdev) | 
|  | 3305 | { | 
|  | 3306 | struct pm8xxx_regulator_core_platform_data *core_data; | 
|  | 3307 |  | 
|  | 3308 | core_data = platform_get_drvdata(pdev); | 
|  | 3309 | platform_set_drvdata(pdev, NULL); | 
|  | 3310 |  | 
|  | 3311 | if (core_data) { | 
|  | 3312 | if (core_data->is_pin_controlled) | 
|  | 3313 | regulator_unregister(core_data->vreg->rdev_pc); | 
|  | 3314 | else | 
|  | 3315 | regulator_unregister(core_data->vreg->rdev); | 
|  | 3316 | } | 
|  | 3317 |  | 
|  | 3318 | return 0; | 
|  | 3319 | } | 
|  | 3320 |  | 
|  | 3321 | static struct platform_driver pm8xxx_vreg_driver = { | 
|  | 3322 | .probe	= pm8xxx_vreg_probe, | 
|  | 3323 | .remove	= __devexit_p(pm8xxx_vreg_remove), | 
|  | 3324 | .driver	= { | 
|  | 3325 | .name	= PM8XXX_REGULATOR_DEV_NAME, | 
|  | 3326 | .owner	= THIS_MODULE, | 
|  | 3327 | }, | 
|  | 3328 | }; | 
|  | 3329 |  | 
|  | 3330 | static int __init pm8xxx_vreg_init(void) | 
|  | 3331 | { | 
|  | 3332 | return platform_driver_register(&pm8xxx_vreg_driver); | 
|  | 3333 | } | 
|  | 3334 | postcore_initcall(pm8xxx_vreg_init); | 
|  | 3335 |  | 
|  | 3336 | static void __exit pm8xxx_vreg_exit(void) | 
|  | 3337 | { | 
|  | 3338 | platform_driver_unregister(&pm8xxx_vreg_driver); | 
|  | 3339 | } | 
|  | 3340 | module_exit(pm8xxx_vreg_exit); | 
|  | 3341 |  | 
|  | 3342 | MODULE_LICENSE("GPL v2"); | 
|  | 3343 | MODULE_DESCRIPTION("PMIC PM8XXX regulator driver"); | 
|  | 3344 | MODULE_VERSION("1.0"); | 
|  | 3345 | MODULE_ALIAS("platform:" PM8XXX_REGULATOR_DEV_NAME); |