| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * TI LP8788 MFD - ldo regulator driver | 
 | 3 |  * | 
 | 4 |  * Copyright 2012 Texas Instruments | 
 | 5 |  * | 
 | 6 |  * Author: Milo(Woogyom) Kim <milo.kim@ti.com> | 
 | 7 |  * | 
 | 8 |  * This program is free software; you can redistribute it and/or modify | 
 | 9 |  * it under the terms of the GNU General Public License version 2 as | 
 | 10 |  * published by the Free Software Foundation. | 
 | 11 |  * | 
 | 12 |  */ | 
 | 13 |  | 
 | 14 | #include <linux/module.h> | 
 | 15 | #include <linux/slab.h> | 
 | 16 | #include <linux/err.h> | 
 | 17 | #include <linux/platform_device.h> | 
 | 18 | #include <linux/regulator/driver.h> | 
 | 19 | #include <linux/gpio/consumer.h> | 
 | 20 | #include <linux/mfd/lp8788.h> | 
 | 21 |  | 
 | 22 | /* register address */ | 
 | 23 | #define LP8788_EN_LDO_A			0x0D	/* DLDO 1 ~ 8 */ | 
 | 24 | #define LP8788_EN_LDO_B			0x0E	/* DLDO 9 ~ 12, ALDO 1 ~ 4 */ | 
 | 25 | #define LP8788_EN_LDO_C			0x0F	/* ALDO 5 ~ 10 */ | 
 | 26 | #define LP8788_EN_SEL			0x10 | 
 | 27 | #define LP8788_DLDO1_VOUT		0x2E | 
 | 28 | #define LP8788_DLDO2_VOUT		0x2F | 
 | 29 | #define LP8788_DLDO3_VOUT		0x30 | 
 | 30 | #define LP8788_DLDO4_VOUT		0x31 | 
 | 31 | #define LP8788_DLDO5_VOUT		0x32 | 
 | 32 | #define LP8788_DLDO6_VOUT		0x33 | 
 | 33 | #define LP8788_DLDO7_VOUT		0x34 | 
 | 34 | #define LP8788_DLDO8_VOUT		0x35 | 
 | 35 | #define LP8788_DLDO9_VOUT		0x36 | 
 | 36 | #define LP8788_DLDO10_VOUT		0x37 | 
 | 37 | #define LP8788_DLDO11_VOUT		0x38 | 
 | 38 | #define LP8788_DLDO12_VOUT		0x39 | 
 | 39 | #define LP8788_ALDO1_VOUT		0x3A | 
 | 40 | #define LP8788_ALDO2_VOUT		0x3B | 
 | 41 | #define LP8788_ALDO3_VOUT		0x3C | 
 | 42 | #define LP8788_ALDO4_VOUT		0x3D | 
 | 43 | #define LP8788_ALDO5_VOUT		0x3E | 
 | 44 | #define LP8788_ALDO6_VOUT		0x3F | 
 | 45 | #define LP8788_ALDO7_VOUT		0x40 | 
 | 46 | #define LP8788_ALDO8_VOUT		0x41 | 
 | 47 | #define LP8788_ALDO9_VOUT		0x42 | 
 | 48 | #define LP8788_ALDO10_VOUT		0x43 | 
 | 49 | #define LP8788_DLDO1_TIMESTEP		0x44 | 
 | 50 |  | 
 | 51 | /* mask/shift bits */ | 
 | 52 | #define LP8788_EN_DLDO1_M		BIT(0)	/* Addr 0Dh ~ 0Fh */ | 
 | 53 | #define LP8788_EN_DLDO2_M		BIT(1) | 
 | 54 | #define LP8788_EN_DLDO3_M		BIT(2) | 
 | 55 | #define LP8788_EN_DLDO4_M		BIT(3) | 
 | 56 | #define LP8788_EN_DLDO5_M		BIT(4) | 
 | 57 | #define LP8788_EN_DLDO6_M		BIT(5) | 
 | 58 | #define LP8788_EN_DLDO7_M		BIT(6) | 
 | 59 | #define LP8788_EN_DLDO8_M		BIT(7) | 
 | 60 | #define LP8788_EN_DLDO9_M		BIT(0) | 
 | 61 | #define LP8788_EN_DLDO10_M		BIT(1) | 
 | 62 | #define LP8788_EN_DLDO11_M		BIT(2) | 
 | 63 | #define LP8788_EN_DLDO12_M		BIT(3) | 
 | 64 | #define LP8788_EN_ALDO1_M		BIT(4) | 
 | 65 | #define LP8788_EN_ALDO2_M		BIT(5) | 
 | 66 | #define LP8788_EN_ALDO3_M		BIT(6) | 
 | 67 | #define LP8788_EN_ALDO4_M		BIT(7) | 
 | 68 | #define LP8788_EN_ALDO5_M		BIT(0) | 
 | 69 | #define LP8788_EN_ALDO6_M		BIT(1) | 
 | 70 | #define LP8788_EN_ALDO7_M		BIT(2) | 
 | 71 | #define LP8788_EN_ALDO8_M		BIT(3) | 
 | 72 | #define LP8788_EN_ALDO9_M		BIT(4) | 
 | 73 | #define LP8788_EN_ALDO10_M		BIT(5) | 
 | 74 | #define LP8788_EN_SEL_DLDO911_M		BIT(0)	/* Addr 10h */ | 
 | 75 | #define LP8788_EN_SEL_DLDO7_M		BIT(1) | 
 | 76 | #define LP8788_EN_SEL_ALDO7_M		BIT(2) | 
 | 77 | #define LP8788_EN_SEL_ALDO5_M		BIT(3) | 
 | 78 | #define LP8788_EN_SEL_ALDO234_M		BIT(4) | 
 | 79 | #define LP8788_EN_SEL_ALDO1_M		BIT(5) | 
 | 80 | #define LP8788_VOUT_5BIT_M		0x1F	/* Addr 2Eh ~ 43h */ | 
 | 81 | #define LP8788_VOUT_4BIT_M		0x0F | 
 | 82 | #define LP8788_VOUT_3BIT_M		0x07 | 
 | 83 | #define LP8788_VOUT_1BIT_M		0x01 | 
 | 84 | #define LP8788_STARTUP_TIME_M		0xF8	/* Addr 44h ~ 59h */ | 
 | 85 | #define LP8788_STARTUP_TIME_S		3 | 
 | 86 |  | 
 | 87 | #define ENABLE_TIME_USEC		32 | 
 | 88 |  | 
 | 89 | enum lp8788_ldo_id { | 
 | 90 | 	DLDO1, | 
 | 91 | 	DLDO2, | 
 | 92 | 	DLDO3, | 
 | 93 | 	DLDO4, | 
 | 94 | 	DLDO5, | 
 | 95 | 	DLDO6, | 
 | 96 | 	DLDO7, | 
 | 97 | 	DLDO8, | 
 | 98 | 	DLDO9, | 
 | 99 | 	DLDO10, | 
 | 100 | 	DLDO11, | 
 | 101 | 	DLDO12, | 
 | 102 | 	ALDO1, | 
 | 103 | 	ALDO2, | 
 | 104 | 	ALDO3, | 
 | 105 | 	ALDO4, | 
 | 106 | 	ALDO5, | 
 | 107 | 	ALDO6, | 
 | 108 | 	ALDO7, | 
 | 109 | 	ALDO8, | 
 | 110 | 	ALDO9, | 
 | 111 | 	ALDO10, | 
 | 112 | }; | 
 | 113 |  | 
 | 114 | struct lp8788_ldo { | 
 | 115 | 	struct lp8788 *lp; | 
 | 116 | 	struct regulator_desc *desc; | 
 | 117 | 	struct regulator_dev *regulator; | 
 | 118 | 	struct gpio_desc *ena_gpiod; | 
 | 119 | }; | 
 | 120 |  | 
 | 121 | /* DLDO 1, 2, 3, 9 voltage table */ | 
 | 122 | static const int lp8788_dldo1239_vtbl[] = { | 
 | 123 | 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, | 
 | 124 | 	2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000, | 
 | 125 | 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, | 
 | 126 | 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, | 
 | 127 | }; | 
 | 128 |  | 
 | 129 | /* DLDO 4 voltage table */ | 
 | 130 | static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 }; | 
 | 131 |  | 
 | 132 | /* DLDO 5, 7, 8 and ALDO 6 voltage table */ | 
 | 133 | static const int lp8788_dldo578_aldo6_vtbl[] = { | 
 | 134 | 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, | 
 | 135 | 	2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000, | 
 | 136 | }; | 
 | 137 |  | 
 | 138 | /* DLDO 6 voltage table */ | 
 | 139 | static const int lp8788_dldo6_vtbl[] = { | 
 | 140 | 	3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000, | 
 | 141 | }; | 
 | 142 |  | 
 | 143 | /* DLDO 10, 11 voltage table */ | 
 | 144 | static const int lp8788_dldo1011_vtbl[] = { | 
 | 145 | 	1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, | 
 | 146 | 	1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, | 
 | 147 | }; | 
 | 148 |  | 
 | 149 | /* ALDO 1 voltage table */ | 
 | 150 | static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 }; | 
 | 151 |  | 
 | 152 | /* ALDO 7 voltage table */ | 
 | 153 | static const int lp8788_aldo7_vtbl[] = { | 
 | 154 | 	1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000, | 
 | 155 | }; | 
 | 156 |  | 
 | 157 | static int lp8788_ldo_enable_time(struct regulator_dev *rdev) | 
 | 158 | { | 
 | 159 | 	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); | 
 | 160 | 	enum lp8788_ldo_id id = rdev_get_id(rdev); | 
 | 161 | 	u8 val, addr = LP8788_DLDO1_TIMESTEP + id; | 
 | 162 |  | 
 | 163 | 	if (lp8788_read_byte(ldo->lp, addr, &val)) | 
 | 164 | 		return -EINVAL; | 
 | 165 |  | 
 | 166 | 	val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S; | 
 | 167 |  | 
 | 168 | 	return ENABLE_TIME_USEC * val; | 
 | 169 | } | 
 | 170 |  | 
 | 171 | static const struct regulator_ops lp8788_ldo_voltage_table_ops = { | 
 | 172 | 	.list_voltage = regulator_list_voltage_table, | 
 | 173 | 	.set_voltage_sel = regulator_set_voltage_sel_regmap, | 
 | 174 | 	.get_voltage_sel = regulator_get_voltage_sel_regmap, | 
 | 175 | 	.enable = regulator_enable_regmap, | 
 | 176 | 	.disable = regulator_disable_regmap, | 
 | 177 | 	.is_enabled = regulator_is_enabled_regmap, | 
 | 178 | 	.enable_time = lp8788_ldo_enable_time, | 
 | 179 | }; | 
 | 180 |  | 
 | 181 | static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = { | 
 | 182 | 	.list_voltage = regulator_list_voltage_linear, | 
 | 183 | 	.enable = regulator_enable_regmap, | 
 | 184 | 	.disable = regulator_disable_regmap, | 
 | 185 | 	.is_enabled = regulator_is_enabled_regmap, | 
 | 186 | 	.enable_time = lp8788_ldo_enable_time, | 
 | 187 | }; | 
 | 188 |  | 
 | 189 | static struct regulator_desc lp8788_dldo_desc[] = { | 
 | 190 | 	{ | 
 | 191 | 		.name = "dldo1", | 
 | 192 | 		.id = DLDO1, | 
 | 193 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 194 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), | 
 | 195 | 		.volt_table = lp8788_dldo1239_vtbl, | 
 | 196 | 		.type = REGULATOR_VOLTAGE, | 
 | 197 | 		.owner = THIS_MODULE, | 
 | 198 | 		.vsel_reg = LP8788_DLDO1_VOUT, | 
 | 199 | 		.vsel_mask = LP8788_VOUT_5BIT_M, | 
 | 200 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 201 | 		.enable_mask = LP8788_EN_DLDO1_M, | 
 | 202 | 	}, | 
 | 203 | 	{ | 
 | 204 | 		.name = "dldo2", | 
 | 205 | 		.id = DLDO2, | 
 | 206 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 207 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), | 
 | 208 | 		.volt_table = lp8788_dldo1239_vtbl, | 
 | 209 | 		.type = REGULATOR_VOLTAGE, | 
 | 210 | 		.owner = THIS_MODULE, | 
 | 211 | 		.vsel_reg = LP8788_DLDO2_VOUT, | 
 | 212 | 		.vsel_mask = LP8788_VOUT_5BIT_M, | 
 | 213 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 214 | 		.enable_mask = LP8788_EN_DLDO2_M, | 
 | 215 | 	}, | 
 | 216 | 	{ | 
 | 217 | 		.name = "dldo3", | 
 | 218 | 		.id = DLDO3, | 
 | 219 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 220 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), | 
 | 221 | 		.volt_table = lp8788_dldo1239_vtbl, | 
 | 222 | 		.type = REGULATOR_VOLTAGE, | 
 | 223 | 		.owner = THIS_MODULE, | 
 | 224 | 		.vsel_reg = LP8788_DLDO3_VOUT, | 
 | 225 | 		.vsel_mask = LP8788_VOUT_5BIT_M, | 
 | 226 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 227 | 		.enable_mask = LP8788_EN_DLDO3_M, | 
 | 228 | 	}, | 
 | 229 | 	{ | 
 | 230 | 		.name = "dldo4", | 
 | 231 | 		.id = DLDO4, | 
 | 232 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 233 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl), | 
 | 234 | 		.volt_table = lp8788_dldo4_vtbl, | 
 | 235 | 		.type = REGULATOR_VOLTAGE, | 
 | 236 | 		.owner = THIS_MODULE, | 
 | 237 | 		.vsel_reg = LP8788_DLDO4_VOUT, | 
 | 238 | 		.vsel_mask = LP8788_VOUT_1BIT_M, | 
 | 239 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 240 | 		.enable_mask = LP8788_EN_DLDO4_M, | 
 | 241 | 	}, | 
 | 242 | 	{ | 
 | 243 | 		.name = "dldo5", | 
 | 244 | 		.id = DLDO5, | 
 | 245 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 246 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), | 
 | 247 | 		.volt_table = lp8788_dldo578_aldo6_vtbl, | 
 | 248 | 		.type = REGULATOR_VOLTAGE, | 
 | 249 | 		.owner = THIS_MODULE, | 
 | 250 | 		.vsel_reg = LP8788_DLDO5_VOUT, | 
 | 251 | 		.vsel_mask = LP8788_VOUT_4BIT_M, | 
 | 252 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 253 | 		.enable_mask = LP8788_EN_DLDO5_M, | 
 | 254 | 	}, | 
 | 255 | 	{ | 
 | 256 | 		.name = "dldo6", | 
 | 257 | 		.id = DLDO6, | 
 | 258 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 259 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl), | 
 | 260 | 		.volt_table = lp8788_dldo6_vtbl, | 
 | 261 | 		.type = REGULATOR_VOLTAGE, | 
 | 262 | 		.owner = THIS_MODULE, | 
 | 263 | 		.vsel_reg = LP8788_DLDO6_VOUT, | 
 | 264 | 		.vsel_mask = LP8788_VOUT_3BIT_M, | 
 | 265 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 266 | 		.enable_mask = LP8788_EN_DLDO6_M, | 
 | 267 | 	}, | 
 | 268 | 	{ | 
 | 269 | 		.name = "dldo7", | 
 | 270 | 		.id = DLDO7, | 
 | 271 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 272 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), | 
 | 273 | 		.volt_table = lp8788_dldo578_aldo6_vtbl, | 
 | 274 | 		.type = REGULATOR_VOLTAGE, | 
 | 275 | 		.owner = THIS_MODULE, | 
 | 276 | 		.vsel_reg = LP8788_DLDO7_VOUT, | 
 | 277 | 		.vsel_mask = LP8788_VOUT_4BIT_M, | 
 | 278 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 279 | 		.enable_mask = LP8788_EN_DLDO7_M, | 
 | 280 | 	}, | 
 | 281 | 	{ | 
 | 282 | 		.name = "dldo8", | 
 | 283 | 		.id = DLDO8, | 
 | 284 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 285 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), | 
 | 286 | 		.volt_table = lp8788_dldo578_aldo6_vtbl, | 
 | 287 | 		.type = REGULATOR_VOLTAGE, | 
 | 288 | 		.owner = THIS_MODULE, | 
 | 289 | 		.vsel_reg = LP8788_DLDO8_VOUT, | 
 | 290 | 		.vsel_mask = LP8788_VOUT_4BIT_M, | 
 | 291 | 		.enable_reg = LP8788_EN_LDO_A, | 
 | 292 | 		.enable_mask = LP8788_EN_DLDO8_M, | 
 | 293 | 	}, | 
 | 294 | 	{ | 
 | 295 | 		.name = "dldo9", | 
 | 296 | 		.id = DLDO9, | 
 | 297 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 298 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), | 
 | 299 | 		.volt_table = lp8788_dldo1239_vtbl, | 
 | 300 | 		.type = REGULATOR_VOLTAGE, | 
 | 301 | 		.owner = THIS_MODULE, | 
 | 302 | 		.vsel_reg = LP8788_DLDO9_VOUT, | 
 | 303 | 		.vsel_mask = LP8788_VOUT_5BIT_M, | 
 | 304 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 305 | 		.enable_mask = LP8788_EN_DLDO9_M, | 
 | 306 | 	}, | 
 | 307 | 	{ | 
 | 308 | 		.name = "dldo10", | 
 | 309 | 		.id = DLDO10, | 
 | 310 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 311 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl), | 
 | 312 | 		.volt_table = lp8788_dldo1011_vtbl, | 
 | 313 | 		.type = REGULATOR_VOLTAGE, | 
 | 314 | 		.owner = THIS_MODULE, | 
 | 315 | 		.vsel_reg = LP8788_DLDO10_VOUT, | 
 | 316 | 		.vsel_mask = LP8788_VOUT_4BIT_M, | 
 | 317 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 318 | 		.enable_mask = LP8788_EN_DLDO10_M, | 
 | 319 | 	}, | 
 | 320 | 	{ | 
 | 321 | 		.name = "dldo11", | 
 | 322 | 		.id = DLDO11, | 
 | 323 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 324 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl), | 
 | 325 | 		.volt_table = lp8788_dldo1011_vtbl, | 
 | 326 | 		.type = REGULATOR_VOLTAGE, | 
 | 327 | 		.owner = THIS_MODULE, | 
 | 328 | 		.vsel_reg = LP8788_DLDO11_VOUT, | 
 | 329 | 		.vsel_mask = LP8788_VOUT_4BIT_M, | 
 | 330 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 331 | 		.enable_mask = LP8788_EN_DLDO11_M, | 
 | 332 | 	}, | 
 | 333 | 	{ | 
 | 334 | 		.name = "dldo12", | 
 | 335 | 		.id = DLDO12, | 
 | 336 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 337 | 		.n_voltages = 1, | 
 | 338 | 		.type = REGULATOR_VOLTAGE, | 
 | 339 | 		.owner = THIS_MODULE, | 
 | 340 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 341 | 		.enable_mask = LP8788_EN_DLDO12_M, | 
 | 342 | 		.min_uV = 2500000, | 
 | 343 | 	}, | 
 | 344 | }; | 
 | 345 |  | 
 | 346 | static struct regulator_desc lp8788_aldo_desc[] = { | 
 | 347 | 	{ | 
 | 348 | 		.name = "aldo1", | 
 | 349 | 		.id = ALDO1, | 
 | 350 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 351 | 		.n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl), | 
 | 352 | 		.volt_table = lp8788_aldo1_vtbl, | 
 | 353 | 		.type = REGULATOR_VOLTAGE, | 
 | 354 | 		.owner = THIS_MODULE, | 
 | 355 | 		.vsel_reg = LP8788_ALDO1_VOUT, | 
 | 356 | 		.vsel_mask = LP8788_VOUT_1BIT_M, | 
 | 357 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 358 | 		.enable_mask = LP8788_EN_ALDO1_M, | 
 | 359 | 	}, | 
 | 360 | 	{ | 
 | 361 | 		.name = "aldo2", | 
 | 362 | 		.id = ALDO2, | 
 | 363 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 364 | 		.n_voltages = 1, | 
 | 365 | 		.type = REGULATOR_VOLTAGE, | 
 | 366 | 		.owner = THIS_MODULE, | 
 | 367 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 368 | 		.enable_mask = LP8788_EN_ALDO2_M, | 
 | 369 | 		.min_uV = 2850000, | 
 | 370 | 	}, | 
 | 371 | 	{ | 
 | 372 | 		.name = "aldo3", | 
 | 373 | 		.id = ALDO3, | 
 | 374 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 375 | 		.n_voltages = 1, | 
 | 376 | 		.type = REGULATOR_VOLTAGE, | 
 | 377 | 		.owner = THIS_MODULE, | 
 | 378 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 379 | 		.enable_mask = LP8788_EN_ALDO3_M, | 
 | 380 | 		.min_uV = 2850000, | 
 | 381 | 	}, | 
 | 382 | 	{ | 
 | 383 | 		.name = "aldo4", | 
 | 384 | 		.id = ALDO4, | 
 | 385 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 386 | 		.n_voltages = 1, | 
 | 387 | 		.type = REGULATOR_VOLTAGE, | 
 | 388 | 		.owner = THIS_MODULE, | 
 | 389 | 		.enable_reg = LP8788_EN_LDO_B, | 
 | 390 | 		.enable_mask = LP8788_EN_ALDO4_M, | 
 | 391 | 		.min_uV = 2850000, | 
 | 392 | 	}, | 
 | 393 | 	{ | 
 | 394 | 		.name = "aldo5", | 
 | 395 | 		.id = ALDO5, | 
 | 396 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 397 | 		.n_voltages = 1, | 
 | 398 | 		.type = REGULATOR_VOLTAGE, | 
 | 399 | 		.owner = THIS_MODULE, | 
 | 400 | 		.enable_reg = LP8788_EN_LDO_C, | 
 | 401 | 		.enable_mask = LP8788_EN_ALDO5_M, | 
 | 402 | 		.min_uV = 2850000, | 
 | 403 | 	}, | 
 | 404 | 	{ | 
 | 405 | 		.name = "aldo6", | 
 | 406 | 		.id = ALDO6, | 
 | 407 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 408 | 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), | 
 | 409 | 		.volt_table = lp8788_dldo578_aldo6_vtbl, | 
 | 410 | 		.type = REGULATOR_VOLTAGE, | 
 | 411 | 		.owner = THIS_MODULE, | 
 | 412 | 		.vsel_reg = LP8788_ALDO6_VOUT, | 
 | 413 | 		.vsel_mask = LP8788_VOUT_4BIT_M, | 
 | 414 | 		.enable_reg = LP8788_EN_LDO_C, | 
 | 415 | 		.enable_mask = LP8788_EN_ALDO6_M, | 
 | 416 | 	}, | 
 | 417 | 	{ | 
 | 418 | 		.name = "aldo7", | 
 | 419 | 		.id = ALDO7, | 
 | 420 | 		.ops = &lp8788_ldo_voltage_table_ops, | 
 | 421 | 		.n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl), | 
 | 422 | 		.volt_table = lp8788_aldo7_vtbl, | 
 | 423 | 		.type = REGULATOR_VOLTAGE, | 
 | 424 | 		.owner = THIS_MODULE, | 
 | 425 | 		.vsel_reg = LP8788_ALDO7_VOUT, | 
 | 426 | 		.vsel_mask = LP8788_VOUT_3BIT_M, | 
 | 427 | 		.enable_reg = LP8788_EN_LDO_C, | 
 | 428 | 		.enable_mask = LP8788_EN_ALDO7_M, | 
 | 429 | 	}, | 
 | 430 | 	{ | 
 | 431 | 		.name = "aldo8", | 
 | 432 | 		.id = ALDO8, | 
 | 433 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 434 | 		.n_voltages = 1, | 
 | 435 | 		.type = REGULATOR_VOLTAGE, | 
 | 436 | 		.owner = THIS_MODULE, | 
 | 437 | 		.enable_reg = LP8788_EN_LDO_C, | 
 | 438 | 		.enable_mask = LP8788_EN_ALDO8_M, | 
 | 439 | 		.min_uV = 2500000, | 
 | 440 | 	}, | 
 | 441 | 	{ | 
 | 442 | 		.name = "aldo9", | 
 | 443 | 		.id = ALDO9, | 
 | 444 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 445 | 		.n_voltages = 1, | 
 | 446 | 		.type = REGULATOR_VOLTAGE, | 
 | 447 | 		.owner = THIS_MODULE, | 
 | 448 | 		.enable_reg = LP8788_EN_LDO_C, | 
 | 449 | 		.enable_mask = LP8788_EN_ALDO9_M, | 
 | 450 | 		.min_uV = 2500000, | 
 | 451 | 	}, | 
 | 452 | 	{ | 
 | 453 | 		.name = "aldo10", | 
 | 454 | 		.id = ALDO10, | 
 | 455 | 		.ops = &lp8788_ldo_voltage_fixed_ops, | 
 | 456 | 		.n_voltages = 1, | 
 | 457 | 		.type = REGULATOR_VOLTAGE, | 
 | 458 | 		.owner = THIS_MODULE, | 
 | 459 | 		.enable_reg = LP8788_EN_LDO_C, | 
 | 460 | 		.enable_mask = LP8788_EN_ALDO10_M, | 
 | 461 | 		.min_uV = 1100000, | 
 | 462 | 	}, | 
 | 463 | }; | 
 | 464 |  | 
 | 465 | static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, | 
 | 466 | 					struct lp8788_ldo *ldo, | 
 | 467 | 					enum lp8788_ldo_id id) | 
 | 468 | { | 
 | 469 | 	struct lp8788 *lp = ldo->lp; | 
 | 470 | 	enum lp8788_ext_ldo_en_id enable_id; | 
 | 471 | 	u8 en_mask[] = { | 
 | 472 | 		[EN_ALDO1]   = LP8788_EN_SEL_ALDO1_M, | 
 | 473 | 		[EN_ALDO234] = LP8788_EN_SEL_ALDO234_M, | 
 | 474 | 		[EN_ALDO5]   = LP8788_EN_SEL_ALDO5_M, | 
 | 475 | 		[EN_ALDO7]   = LP8788_EN_SEL_ALDO7_M, | 
 | 476 | 		[EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M, | 
 | 477 | 		[EN_DLDO911] = LP8788_EN_SEL_DLDO911_M, | 
 | 478 | 	}; | 
 | 479 |  | 
 | 480 | 	switch (id) { | 
 | 481 | 	case DLDO7: | 
 | 482 | 		enable_id = EN_DLDO7; | 
 | 483 | 		break; | 
 | 484 | 	case DLDO9: | 
 | 485 | 	case DLDO11: | 
 | 486 | 		enable_id = EN_DLDO911; | 
 | 487 | 		break; | 
 | 488 | 	case ALDO1: | 
 | 489 | 		enable_id = EN_ALDO1; | 
 | 490 | 		break; | 
 | 491 | 	case ALDO2 ... ALDO4: | 
 | 492 | 		enable_id = EN_ALDO234; | 
 | 493 | 		break; | 
 | 494 | 	case ALDO5: | 
 | 495 | 		enable_id = EN_ALDO5; | 
 | 496 | 		break; | 
 | 497 | 	case ALDO7: | 
 | 498 | 		enable_id = EN_ALDO7; | 
 | 499 | 		break; | 
 | 500 | 	default: | 
 | 501 | 		return 0; | 
 | 502 | 	} | 
 | 503 |  | 
 | 504 | 	/* FIXME: check default mode for GPIO here: high or low? */ | 
 | 505 | 	ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev, | 
 | 506 | 						       "enable", | 
 | 507 | 						       enable_id, | 
 | 508 | 						       GPIOD_OUT_HIGH); | 
 | 509 | 	if (IS_ERR(ldo->ena_gpiod)) | 
 | 510 | 		return PTR_ERR(ldo->ena_gpiod); | 
 | 511 |  | 
 | 512 | 	/* if no GPIO for ldo pin, then set default enable mode */ | 
 | 513 | 	if (!ldo->ena_gpiod) | 
 | 514 | 		goto set_default_ldo_enable_mode; | 
 | 515 |  | 
 | 516 | 	return 0; | 
 | 517 |  | 
 | 518 | set_default_ldo_enable_mode: | 
 | 519 | 	return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0); | 
 | 520 | } | 
 | 521 |  | 
 | 522 | static int lp8788_dldo_probe(struct platform_device *pdev) | 
 | 523 | { | 
 | 524 | 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); | 
 | 525 | 	int id = pdev->id; | 
 | 526 | 	struct lp8788_ldo *ldo; | 
 | 527 | 	struct regulator_config cfg = { }; | 
 | 528 | 	struct regulator_dev *rdev; | 
 | 529 | 	int ret; | 
 | 530 |  | 
 | 531 | 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); | 
 | 532 | 	if (!ldo) | 
 | 533 | 		return -ENOMEM; | 
 | 534 |  | 
 | 535 | 	ldo->lp = lp; | 
 | 536 | 	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id); | 
 | 537 | 	if (ret) | 
 | 538 | 		return ret; | 
 | 539 |  | 
 | 540 | 	if (ldo->ena_gpiod) | 
 | 541 | 		cfg.ena_gpiod = ldo->ena_gpiod; | 
 | 542 |  | 
 | 543 | 	cfg.dev = pdev->dev.parent; | 
 | 544 | 	cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL; | 
 | 545 | 	cfg.driver_data = ldo; | 
 | 546 | 	cfg.regmap = lp->regmap; | 
 | 547 |  | 
 | 548 | 	rdev = devm_regulator_register(&pdev->dev, &lp8788_dldo_desc[id], &cfg); | 
 | 549 | 	if (IS_ERR(rdev)) { | 
 | 550 | 		ret = PTR_ERR(rdev); | 
 | 551 | 		dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n", | 
 | 552 | 				id + 1, ret); | 
 | 553 | 		return ret; | 
 | 554 | 	} | 
 | 555 |  | 
 | 556 | 	ldo->regulator = rdev; | 
 | 557 | 	platform_set_drvdata(pdev, ldo); | 
 | 558 |  | 
 | 559 | 	return 0; | 
 | 560 | } | 
 | 561 |  | 
 | 562 | static struct platform_driver lp8788_dldo_driver = { | 
 | 563 | 	.probe = lp8788_dldo_probe, | 
 | 564 | 	.driver = { | 
 | 565 | 		.name = LP8788_DEV_DLDO, | 
 | 566 | 	}, | 
 | 567 | }; | 
 | 568 |  | 
 | 569 | static int lp8788_aldo_probe(struct platform_device *pdev) | 
 | 570 | { | 
 | 571 | 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); | 
 | 572 | 	int id = pdev->id; | 
 | 573 | 	struct lp8788_ldo *ldo; | 
 | 574 | 	struct regulator_config cfg = { }; | 
 | 575 | 	struct regulator_dev *rdev; | 
 | 576 | 	int ret; | 
 | 577 |  | 
 | 578 | 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); | 
 | 579 | 	if (!ldo) | 
 | 580 | 		return -ENOMEM; | 
 | 581 |  | 
 | 582 | 	ldo->lp = lp; | 
 | 583 | 	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id + ALDO1); | 
 | 584 | 	if (ret) | 
 | 585 | 		return ret; | 
 | 586 |  | 
 | 587 | 	if (ldo->ena_gpiod) | 
 | 588 | 		cfg.ena_gpiod = ldo->ena_gpiod; | 
 | 589 |  | 
 | 590 | 	cfg.dev = pdev->dev.parent; | 
 | 591 | 	cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL; | 
 | 592 | 	cfg.driver_data = ldo; | 
 | 593 | 	cfg.regmap = lp->regmap; | 
 | 594 |  | 
 | 595 | 	rdev = devm_regulator_register(&pdev->dev, &lp8788_aldo_desc[id], &cfg); | 
 | 596 | 	if (IS_ERR(rdev)) { | 
 | 597 | 		ret = PTR_ERR(rdev); | 
 | 598 | 		dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n", | 
 | 599 | 				id + 1, ret); | 
 | 600 | 		return ret; | 
 | 601 | 	} | 
 | 602 |  | 
 | 603 | 	ldo->regulator = rdev; | 
 | 604 | 	platform_set_drvdata(pdev, ldo); | 
 | 605 |  | 
 | 606 | 	return 0; | 
 | 607 | } | 
 | 608 |  | 
 | 609 | static struct platform_driver lp8788_aldo_driver = { | 
 | 610 | 	.probe = lp8788_aldo_probe, | 
 | 611 | 	.driver = { | 
 | 612 | 		.name = LP8788_DEV_ALDO, | 
 | 613 | 	}, | 
 | 614 | }; | 
 | 615 |  | 
 | 616 | static struct platform_driver * const drivers[] = { | 
 | 617 | 	&lp8788_dldo_driver, | 
 | 618 | 	&lp8788_aldo_driver, | 
 | 619 | }; | 
 | 620 |  | 
 | 621 | static int __init lp8788_ldo_init(void) | 
 | 622 | { | 
 | 623 | 	return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); | 
 | 624 | } | 
 | 625 | subsys_initcall(lp8788_ldo_init); | 
 | 626 |  | 
 | 627 | static void __exit lp8788_ldo_exit(void) | 
 | 628 | { | 
 | 629 | 	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); | 
 | 630 | } | 
 | 631 | module_exit(lp8788_ldo_exit); | 
 | 632 |  | 
 | 633 | MODULE_DESCRIPTION("TI LP8788 LDO Driver"); | 
 | 634 | MODULE_AUTHOR("Milo Kim"); | 
 | 635 | MODULE_LICENSE("GPL"); | 
 | 636 | MODULE_ALIAS("platform:lp8788-dldo"); | 
 | 637 | MODULE_ALIAS("platform:lp8788-aldo"); |