1d1a82001SLee Jones /* 2d1a82001SLee Jones * Copyright (C) ST-Ericsson SA 2010 3d1a82001SLee Jones * 4d1a82001SLee Jones * License Terms: GNU General Public License v2 5d1a82001SLee Jones * 6d1a82001SLee Jones * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com> 7d1a82001SLee Jones * 8d1a82001SLee Jones * This file is based on drivers/regulator/ab8500.c 9d1a82001SLee Jones * 10d1a82001SLee Jones * AB8500 external regulators 11d1a82001SLee Jones * 12d1a82001SLee Jones * ab8500-ext supports the following regulators: 13d1a82001SLee Jones * - VextSupply3 14d1a82001SLee Jones */ 15d1a82001SLee Jones #include <linux/init.h> 16d1a82001SLee Jones #include <linux/kernel.h> 17d1a82001SLee Jones #include <linux/err.h> 18d1a82001SLee Jones #include <linux/module.h> 19d1a82001SLee Jones #include <linux/platform_device.h> 20d1a82001SLee Jones #include <linux/regulator/driver.h> 21d1a82001SLee Jones #include <linux/regulator/machine.h> 22d1a82001SLee Jones #include <linux/mfd/abx500.h> 23d1a82001SLee Jones #include <linux/mfd/abx500/ab8500.h> 24d1a82001SLee Jones #include <linux/regulator/ab8500.h> 25d1a82001SLee Jones 26d1a82001SLee Jones /** 27d1a82001SLee Jones * struct ab8500_ext_regulator_info - ab8500 regulator information 28d1a82001SLee Jones * @dev: device pointer 29d1a82001SLee Jones * @desc: regulator description 30d1a82001SLee Jones * @rdev: regulator device 3118bc2b39SBengt Jonsson * @cfg: regulator configuration (extension of regulator FW configuration) 32d1a82001SLee Jones * @update_bank: bank to control on/off 33d1a82001SLee Jones * @update_reg: register to control on/off 34d1a82001SLee Jones * @update_mask: mask to enable/disable and set mode of regulator 35d1a82001SLee Jones * @update_val: bits holding the regulator current mode 3618bc2b39SBengt Jonsson * @update_val_hp: bits to set EN pin active (LPn pin deactive) 37d1a82001SLee Jones * normally this means high power mode 3818bc2b39SBengt Jonsson * @update_val_lp: bits to set EN pin active and LPn pin active 39d1a82001SLee Jones * normally this means low power mode 4018bc2b39SBengt Jonsson * @update_val_hw: bits to set regulator pins in HW control 4118bc2b39SBengt Jonsson * SysClkReq pins and logic will choose mode 42d1a82001SLee Jones */ 43d1a82001SLee Jones struct ab8500_ext_regulator_info { 44d1a82001SLee Jones struct device *dev; 45d1a82001SLee Jones struct regulator_desc desc; 46d1a82001SLee Jones struct regulator_dev *rdev; 4718bc2b39SBengt Jonsson struct ab8500_ext_regulator_cfg *cfg; 48d1a82001SLee Jones u8 update_bank; 49d1a82001SLee Jones u8 update_reg; 50d1a82001SLee Jones u8 update_mask; 51d1a82001SLee Jones u8 update_val; 5218bc2b39SBengt Jonsson u8 update_val_hp; 5318bc2b39SBengt Jonsson u8 update_val_lp; 5418bc2b39SBengt Jonsson u8 update_val_hw; 55d1a82001SLee Jones }; 56d1a82001SLee Jones 5718bc2b39SBengt Jonsson static int enable(struct ab8500_ext_regulator_info *info, u8 *regval) 58d1a82001SLee Jones { 59d1a82001SLee Jones int ret; 60d1a82001SLee Jones 6118bc2b39SBengt Jonsson *regval = info->update_val; 6218bc2b39SBengt Jonsson 6318bc2b39SBengt Jonsson /* 6418bc2b39SBengt Jonsson * To satisfy both HW high power request and SW request, the regulator 6518bc2b39SBengt Jonsson * must be on in high power. 6618bc2b39SBengt Jonsson */ 6718bc2b39SBengt Jonsson if (info->cfg && info->cfg->hwreq) 6818bc2b39SBengt Jonsson *regval = info->update_val_hp; 69d1a82001SLee Jones 70d1a82001SLee Jones ret = abx500_mask_and_set_register_interruptible(info->dev, 71d1a82001SLee Jones info->update_bank, info->update_reg, 7218bc2b39SBengt Jonsson info->update_mask, *regval); 7337daa8aeSAxel Lin if (ret < 0) { 74d1a82001SLee Jones dev_err(rdev_get_dev(info->rdev), 75d1a82001SLee Jones "couldn't set enable bits for regulator\n"); 7637daa8aeSAxel Lin return ret; 7737daa8aeSAxel Lin } 78d1a82001SLee Jones 7918bc2b39SBengt Jonsson return ret; 8018bc2b39SBengt Jonsson } 8118bc2b39SBengt Jonsson 8218bc2b39SBengt Jonsson static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) 8318bc2b39SBengt Jonsson { 8418bc2b39SBengt Jonsson int ret; 8518bc2b39SBengt Jonsson struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); 8618bc2b39SBengt Jonsson u8 regval; 8718bc2b39SBengt Jonsson 8818bc2b39SBengt Jonsson if (info == NULL) { 8918bc2b39SBengt Jonsson dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); 9018bc2b39SBengt Jonsson return -EINVAL; 9118bc2b39SBengt Jonsson } 9218bc2b39SBengt Jonsson 9318bc2b39SBengt Jonsson ret = enable(info, ®val); 9418bc2b39SBengt Jonsson 95d1a82001SLee Jones dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):" 96d1a82001SLee Jones " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", 97d1a82001SLee Jones info->desc.name, info->update_bank, info->update_reg, 9818bc2b39SBengt Jonsson info->update_mask, regval); 9918bc2b39SBengt Jonsson 10018bc2b39SBengt Jonsson return ret; 10118bc2b39SBengt Jonsson } 10218bc2b39SBengt Jonsson 10318bc2b39SBengt Jonsson static int disable(struct ab8500_ext_regulator_info *info, u8 *regval) 10418bc2b39SBengt Jonsson { 10518bc2b39SBengt Jonsson int ret; 10618bc2b39SBengt Jonsson 10718bc2b39SBengt Jonsson *regval = 0x0; 10818bc2b39SBengt Jonsson 10918bc2b39SBengt Jonsson /* 11018bc2b39SBengt Jonsson * Set the regulator in HW request mode if configured 11118bc2b39SBengt Jonsson */ 11218bc2b39SBengt Jonsson if (info->cfg && info->cfg->hwreq) 11318bc2b39SBengt Jonsson *regval = info->update_val_hw; 11418bc2b39SBengt Jonsson 11518bc2b39SBengt Jonsson ret = abx500_mask_and_set_register_interruptible(info->dev, 11618bc2b39SBengt Jonsson info->update_bank, info->update_reg, 11718bc2b39SBengt Jonsson info->update_mask, *regval); 11837daa8aeSAxel Lin if (ret < 0) { 11918bc2b39SBengt Jonsson dev_err(rdev_get_dev(info->rdev), 12018bc2b39SBengt Jonsson "couldn't set disable bits for regulator\n"); 12137daa8aeSAxel Lin return ret; 12237daa8aeSAxel Lin } 12318bc2b39SBengt Jonsson 124d1a82001SLee Jones return ret; 125d1a82001SLee Jones } 126d1a82001SLee Jones 127d1a82001SLee Jones static int ab8500_ext_regulator_disable(struct regulator_dev *rdev) 128d1a82001SLee Jones { 129d1a82001SLee Jones int ret; 130d1a82001SLee Jones struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); 13118bc2b39SBengt Jonsson u8 regval; 132d1a82001SLee Jones 133d1a82001SLee Jones if (info == NULL) { 134d1a82001SLee Jones dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); 135d1a82001SLee Jones return -EINVAL; 136d1a82001SLee Jones } 137d1a82001SLee Jones 13818bc2b39SBengt Jonsson ret = disable(info, ®val); 139d1a82001SLee Jones 140d1a82001SLee Jones dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):" 141d1a82001SLee Jones " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", 142d1a82001SLee Jones info->desc.name, info->update_bank, info->update_reg, 14318bc2b39SBengt Jonsson info->update_mask, regval); 144d1a82001SLee Jones 145d1a82001SLee Jones return ret; 146d1a82001SLee Jones } 147d1a82001SLee Jones 148d1a82001SLee Jones static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev) 149d1a82001SLee Jones { 150d1a82001SLee Jones int ret; 151d1a82001SLee Jones struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); 152d1a82001SLee Jones u8 regval; 153d1a82001SLee Jones 154d1a82001SLee Jones if (info == NULL) { 155d1a82001SLee Jones dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); 156d1a82001SLee Jones return -EINVAL; 157d1a82001SLee Jones } 158d1a82001SLee Jones 159d1a82001SLee Jones ret = abx500_get_register_interruptible(info->dev, 160d1a82001SLee Jones info->update_bank, info->update_reg, ®val); 161d1a82001SLee Jones if (ret < 0) { 162d1a82001SLee Jones dev_err(rdev_get_dev(rdev), 163d1a82001SLee Jones "couldn't read 0x%x register\n", info->update_reg); 164d1a82001SLee Jones return ret; 165d1a82001SLee Jones } 166d1a82001SLee Jones 167d1a82001SLee Jones dev_dbg(rdev_get_dev(rdev), "%s-is_enabled (bank, reg, mask, value):" 168d1a82001SLee Jones " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", 169d1a82001SLee Jones info->desc.name, info->update_bank, info->update_reg, 170d1a82001SLee Jones info->update_mask, regval); 171d1a82001SLee Jones 17218bc2b39SBengt Jonsson if (((regval & info->update_mask) == info->update_val_lp) || 17318bc2b39SBengt Jonsson ((regval & info->update_mask) == info->update_val_hp)) 174*9ab51a0eSAxel Lin return 1; 175d1a82001SLee Jones else 176*9ab51a0eSAxel Lin return 0; 177d1a82001SLee Jones } 178d1a82001SLee Jones 179d1a82001SLee Jones static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, 180d1a82001SLee Jones unsigned int mode) 181d1a82001SLee Jones { 182d1a82001SLee Jones int ret = 0; 183d1a82001SLee Jones struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); 184d1a82001SLee Jones 185d1a82001SLee Jones if (info == NULL) { 186d1a82001SLee Jones dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); 187d1a82001SLee Jones return -EINVAL; 188d1a82001SLee Jones } 189d1a82001SLee Jones 190d1a82001SLee Jones switch (mode) { 191d1a82001SLee Jones case REGULATOR_MODE_NORMAL: 192d1a82001SLee Jones info->update_val = info->update_val_hp; 193d1a82001SLee Jones break; 194d1a82001SLee Jones case REGULATOR_MODE_IDLE: 195d1a82001SLee Jones info->update_val = info->update_val_lp; 196d1a82001SLee Jones break; 197d1a82001SLee Jones 198d1a82001SLee Jones default: 199d1a82001SLee Jones return -EINVAL; 200d1a82001SLee Jones } 201d1a82001SLee Jones 202*9ab51a0eSAxel Lin if (ab8500_ext_regulator_is_enabled(rdev)) { 203d1a82001SLee Jones u8 regval; 204d1a82001SLee Jones 205d1a82001SLee Jones ret = enable(info, ®val); 206d1a82001SLee Jones if (ret < 0) 207d1a82001SLee Jones dev_err(rdev_get_dev(rdev), 208d1a82001SLee Jones "Could not set regulator mode.\n"); 209d1a82001SLee Jones 210d1a82001SLee Jones dev_dbg(rdev_get_dev(rdev), 211d1a82001SLee Jones "%s-set_mode (bank, reg, mask, value): " 212d1a82001SLee Jones "0x%x, 0x%x, 0x%x, 0x%x\n", 213d1a82001SLee Jones info->desc.name, info->update_bank, info->update_reg, 214d1a82001SLee Jones info->update_mask, regval); 215d1a82001SLee Jones } 216d1a82001SLee Jones 217d1a82001SLee Jones return ret; 218d1a82001SLee Jones } 219d1a82001SLee Jones 220d1a82001SLee Jones static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev) 221d1a82001SLee Jones { 222d1a82001SLee Jones struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); 223d1a82001SLee Jones int ret; 224d1a82001SLee Jones 225d1a82001SLee Jones if (info == NULL) { 226d1a82001SLee Jones dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); 227d1a82001SLee Jones return -EINVAL; 228d1a82001SLee Jones } 229d1a82001SLee Jones 230d1a82001SLee Jones if (info->update_val == info->update_val_hp) 231d1a82001SLee Jones ret = REGULATOR_MODE_NORMAL; 232d1a82001SLee Jones else if (info->update_val == info->update_val_lp) 233d1a82001SLee Jones ret = REGULATOR_MODE_IDLE; 234d1a82001SLee Jones else 235d1a82001SLee Jones ret = -EINVAL; 236d1a82001SLee Jones 237d1a82001SLee Jones return ret; 238d1a82001SLee Jones } 239d1a82001SLee Jones 240d1a82001SLee Jones static int ab8500_ext_fixed_get_voltage(struct regulator_dev *rdev) 241d1a82001SLee Jones { 242d1a82001SLee Jones struct regulation_constraints *regu_constraints = rdev->constraints; 243d1a82001SLee Jones 244d1a82001SLee Jones if (regu_constraints == NULL) { 245d1a82001SLee Jones dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n"); 246d1a82001SLee Jones return -EINVAL; 247d1a82001SLee Jones } 248d1a82001SLee Jones if (regu_constraints->min_uV && regu_constraints->max_uV) { 249d1a82001SLee Jones if (regu_constraints->min_uV == regu_constraints->max_uV) 250d1a82001SLee Jones return regu_constraints->min_uV; 251d1a82001SLee Jones } 252d1a82001SLee Jones return -EINVAL; 253d1a82001SLee Jones } 254d1a82001SLee Jones 255d1a82001SLee Jones static int ab8500_ext_list_voltage(struct regulator_dev *rdev, 256d1a82001SLee Jones unsigned selector) 257d1a82001SLee Jones { 258d1a82001SLee Jones struct regulation_constraints *regu_constraints = rdev->constraints; 259d1a82001SLee Jones 260d1a82001SLee Jones if (regu_constraints == NULL) { 261d1a82001SLee Jones dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n"); 262d1a82001SLee Jones return -EINVAL; 263d1a82001SLee Jones } 264d1a82001SLee Jones /* return the uV for the fixed regulators */ 265d1a82001SLee Jones if (regu_constraints->min_uV && regu_constraints->max_uV) { 266d1a82001SLee Jones if (regu_constraints->min_uV == regu_constraints->max_uV) 267d1a82001SLee Jones return regu_constraints->min_uV; 268d1a82001SLee Jones } 269d1a82001SLee Jones return -EINVAL; 270d1a82001SLee Jones } 271d1a82001SLee Jones 272d1a82001SLee Jones static struct regulator_ops ab8500_ext_regulator_ops = { 273d1a82001SLee Jones .enable = ab8500_ext_regulator_enable, 274d1a82001SLee Jones .disable = ab8500_ext_regulator_disable, 275d1a82001SLee Jones .is_enabled = ab8500_ext_regulator_is_enabled, 276d1a82001SLee Jones .set_mode = ab8500_ext_regulator_set_mode, 277d1a82001SLee Jones .get_mode = ab8500_ext_regulator_get_mode, 278d1a82001SLee Jones .get_voltage = ab8500_ext_fixed_get_voltage, 279d1a82001SLee Jones .list_voltage = ab8500_ext_list_voltage, 280d1a82001SLee Jones }; 281d1a82001SLee Jones 282d1a82001SLee Jones static struct ab8500_ext_regulator_info 283d1a82001SLee Jones ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = { 284d1a82001SLee Jones [AB8500_EXT_SUPPLY1] = { 285d1a82001SLee Jones .desc = { 286d1a82001SLee Jones .name = "VEXTSUPPLY1", 287d1a82001SLee Jones .ops = &ab8500_ext_regulator_ops, 288d1a82001SLee Jones .type = REGULATOR_VOLTAGE, 289d1a82001SLee Jones .id = AB8500_EXT_SUPPLY1, 290d1a82001SLee Jones .owner = THIS_MODULE, 291d1a82001SLee Jones .n_voltages = 1, 292d1a82001SLee Jones }, 293d1a82001SLee Jones .update_bank = 0x04, 294d1a82001SLee Jones .update_reg = 0x08, 295d1a82001SLee Jones .update_mask = 0x03, 296d1a82001SLee Jones .update_val = 0x01, 297d1a82001SLee Jones .update_val_hp = 0x01, 298d1a82001SLee Jones .update_val_lp = 0x03, 299d1a82001SLee Jones .update_val_hw = 0x02, 300d1a82001SLee Jones }, 301d1a82001SLee Jones [AB8500_EXT_SUPPLY2] = { 302d1a82001SLee Jones .desc = { 303d1a82001SLee Jones .name = "VEXTSUPPLY2", 304d1a82001SLee Jones .ops = &ab8500_ext_regulator_ops, 305d1a82001SLee Jones .type = REGULATOR_VOLTAGE, 306d1a82001SLee Jones .id = AB8500_EXT_SUPPLY2, 307d1a82001SLee Jones .owner = THIS_MODULE, 308d1a82001SLee Jones .n_voltages = 1, 309d1a82001SLee Jones }, 310d1a82001SLee Jones .update_bank = 0x04, 311d1a82001SLee Jones .update_reg = 0x08, 312d1a82001SLee Jones .update_mask = 0x0c, 313d1a82001SLee Jones .update_val = 0x04, 314d1a82001SLee Jones .update_val_hp = 0x04, 315d1a82001SLee Jones .update_val_lp = 0x0c, 316d1a82001SLee Jones .update_val_hw = 0x08, 317d1a82001SLee Jones }, 318d1a82001SLee Jones [AB8500_EXT_SUPPLY3] = { 319d1a82001SLee Jones .desc = { 320d1a82001SLee Jones .name = "VEXTSUPPLY3", 321d1a82001SLee Jones .ops = &ab8500_ext_regulator_ops, 322d1a82001SLee Jones .type = REGULATOR_VOLTAGE, 323d1a82001SLee Jones .id = AB8500_EXT_SUPPLY3, 324d1a82001SLee Jones .owner = THIS_MODULE, 325d1a82001SLee Jones .n_voltages = 1, 326d1a82001SLee Jones }, 327d1a82001SLee Jones .update_bank = 0x04, 328d1a82001SLee Jones .update_reg = 0x08, 329d1a82001SLee Jones .update_mask = 0x30, 330d1a82001SLee Jones .update_val = 0x10, 33118bc2b39SBengt Jonsson .update_val_hp = 0x10, 33218bc2b39SBengt Jonsson .update_val_lp = 0x30, 33318bc2b39SBengt Jonsson .update_val_hw = 0x20, 334d1a82001SLee Jones }, 335d1a82001SLee Jones }; 336d1a82001SLee Jones 337d1a82001SLee Jones int ab8500_ext_regulator_init(struct platform_device *pdev) 338d1a82001SLee Jones { 339d1a82001SLee Jones struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); 340d1a82001SLee Jones struct ab8500_platform_data *ppdata; 341d1a82001SLee Jones struct ab8500_regulator_platform_data *pdata; 342d1a82001SLee Jones struct regulator_config config = { }; 343d1a82001SLee Jones int i, err; 344d1a82001SLee Jones 345d1a82001SLee Jones if (!ab8500) { 346d1a82001SLee Jones dev_err(&pdev->dev, "null mfd parent\n"); 347d1a82001SLee Jones return -EINVAL; 348d1a82001SLee Jones } 349d1a82001SLee Jones ppdata = dev_get_platdata(ab8500->dev); 350d1a82001SLee Jones if (!ppdata) { 351d1a82001SLee Jones dev_err(&pdev->dev, "null parent pdata\n"); 352d1a82001SLee Jones return -EINVAL; 353d1a82001SLee Jones } 354d1a82001SLee Jones 355d1a82001SLee Jones pdata = ppdata->regulator; 356d1a82001SLee Jones if (!pdata) { 357d1a82001SLee Jones dev_err(&pdev->dev, "null pdata\n"); 358d1a82001SLee Jones return -EINVAL; 359d1a82001SLee Jones } 360d1a82001SLee Jones 361d1a82001SLee Jones /* make sure the platform data has the correct size */ 362d1a82001SLee Jones if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) { 363d1a82001SLee Jones dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); 364d1a82001SLee Jones return -EINVAL; 365d1a82001SLee Jones } 366d1a82001SLee Jones 367d1a82001SLee Jones /* check for AB8500 2.x */ 368a6324709SBengt Jonsson if (is_ab8500_2p0_or_earlier(ab8500)) { 369d1a82001SLee Jones struct ab8500_ext_regulator_info *info; 370d1a82001SLee Jones 371d1a82001SLee Jones /* VextSupply3LPn is inverted on AB8500 2.x */ 372d1a82001SLee Jones info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3]; 373d1a82001SLee Jones info->update_val = 0x30; 37418bc2b39SBengt Jonsson info->update_val_hp = 0x30; 37518bc2b39SBengt Jonsson info->update_val_lp = 0x10; 376d1a82001SLee Jones } 377d1a82001SLee Jones 378d1a82001SLee Jones /* register all regulators */ 379d1a82001SLee Jones for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) { 380d1a82001SLee Jones struct ab8500_ext_regulator_info *info = NULL; 381d1a82001SLee Jones 382d1a82001SLee Jones /* assign per-regulator data */ 383d1a82001SLee Jones info = &ab8500_ext_regulator_info[i]; 384d1a82001SLee Jones info->dev = &pdev->dev; 38518bc2b39SBengt Jonsson info->cfg = (struct ab8500_ext_regulator_cfg *) 38618bc2b39SBengt Jonsson pdata->ext_regulator[i].driver_data; 387d1a82001SLee Jones 388d1a82001SLee Jones config.dev = &pdev->dev; 389d1a82001SLee Jones config.init_data = &pdata->ext_regulator[i]; 390d1a82001SLee Jones config.driver_data = info; 391d1a82001SLee Jones 392bd44e2cbSLee Jones if ((is_ab9540(ab8500) || is_ab8540(ab8500)) && 3930fe17e20SLee Jones ((info->desc.id == AB8500_EXT_SUPPLY1) || 3940fe17e20SLee Jones (info->desc.id == AB8500_EXT_SUPPLY2) || 3950fe17e20SLee Jones (info->desc.id == AB8500_EXT_SUPPLY3))) 3960fe17e20SLee Jones info->desc.ops = &ab8500_ext_regulator_ops; 3970fe17e20SLee Jones 398d1a82001SLee Jones /* register regulator with framework */ 399d1a82001SLee Jones info->rdev = regulator_register(&info->desc, &config); 400d1a82001SLee Jones 401d1a82001SLee Jones if (IS_ERR(info->rdev)) { 402d1a82001SLee Jones err = PTR_ERR(info->rdev); 403d1a82001SLee Jones dev_err(&pdev->dev, "failed to register regulator %s\n", 404d1a82001SLee Jones info->desc.name); 405d1a82001SLee Jones /* when we fail, un-register all earlier regulators */ 406d1a82001SLee Jones while (--i >= 0) { 407d1a82001SLee Jones info = &ab8500_ext_regulator_info[i]; 408d1a82001SLee Jones regulator_unregister(info->rdev); 409d1a82001SLee Jones } 410d1a82001SLee Jones return err; 411d1a82001SLee Jones } 412d1a82001SLee Jones 413d1a82001SLee Jones dev_dbg(rdev_get_dev(info->rdev), 414d1a82001SLee Jones "%s-probed\n", info->desc.name); 415d1a82001SLee Jones } 416d1a82001SLee Jones 417d1a82001SLee Jones return 0; 418d1a82001SLee Jones } 419d1a82001SLee Jones 420d1a82001SLee Jones int ab8500_ext_regulator_exit(struct platform_device *pdev) 421d1a82001SLee Jones { 422d1a82001SLee Jones int i; 423d1a82001SLee Jones 424d1a82001SLee Jones for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) { 425d1a82001SLee Jones struct ab8500_ext_regulator_info *info = NULL; 426d1a82001SLee Jones info = &ab8500_ext_regulator_info[i]; 427d1a82001SLee Jones 428d1a82001SLee Jones dev_vdbg(rdev_get_dev(info->rdev), 429d1a82001SLee Jones "%s-remove\n", info->desc.name); 430d1a82001SLee Jones 431d1a82001SLee Jones regulator_unregister(info->rdev); 432d1a82001SLee Jones } 433d1a82001SLee Jones 434d1a82001SLee Jones return 0; 435d1a82001SLee Jones } 436d1a82001SLee Jones 437d1a82001SLee Jones MODULE_LICENSE("GPL v2"); 438d1a82001SLee Jones MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>"); 439d1a82001SLee Jones MODULE_DESCRIPTION("AB8500 external regulator driver"); 440d1a82001SLee Jones MODULE_ALIAS("platform:ab8500-ext-regulator"); 441