Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6: (45 commits)
  regulator: missing index in PTR_ERR() in isl6271a_probe()
  regulator: Assign return value of mc13xxx_reg_rmw to ret
  regulator: Add initial per-regulator debugfs support
  regulator: Make regulator_has_full_constraints a bool
  regulator: Clean up logging a bit
  regulator: Optimise out noop voltage changes
  regulator: Add API to re-apply voltage to hardware
  regulator: Staticise non-exported functions in mc13892
  regulator: Only notify voltage changes when they succeed
  regulator: Provide a selector based set_voltage_sel() operation
  regulator: Factor out voltage set operation into a separate function
  regulator: Convert WM8994 to use get_voltage_sel()
  regulator: Convert WM835x to use get_voltage_sel()
  regulator: Allow modular build of mc13xxx-core
  regulator: support PMIC mc13892
  make mc13783 regulator code generic
  Change the register name definitions for mc13783
  mach-ux500: Updated and connected ab8500 regulator board configuration
  regulators: Removed macros for initialization of ab8500 regulators
  regulators: Added verbose debug messages to ab8500 regulators
  ...
This commit is contained in:
Linus Torvalds 2011-01-13 10:24:07 -08:00
commit 1896a1346a
45 changed files with 2970 additions and 843 deletions

View file

@ -254,10 +254,10 @@ static struct regulator_init_data cam_data = {
static struct mc13783_regulator_init_data pcm038_regulators[] = { static struct mc13783_regulator_init_data pcm038_regulators[] = {
{ {
.id = MC13783_REGU_VCAM, .id = MC13783_REG_VCAM,
.init_data = &cam_data, .init_data = &cam_data,
}, { }, {
.id = MC13783_REGU_VMMC1, .id = MC13783_REG_VMMC1,
.init_data = &sdhc1_data, .init_data = &sdhc1_data,
}, },
}; };

View file

@ -140,10 +140,10 @@ static struct regulator_init_data gpo_init = {
static struct mc13783_regulator_init_data mx31_3ds_regulators[] = { static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
{ {
.id = MC13783_REGU_PWGT1SPI, /* Power Gate for ARM core. */ .id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
.init_data = &pwgtx_init, .init_data = &pwgtx_init,
}, { }, {
.id = MC13783_REGU_PWGT2SPI, /* Power Gate for L2 Cache. */ .id = MC13783_REG_PWGT2SPI, /* Power Gate for L2 Cache. */
.init_data = &pwgtx_init, .init_data = &pwgtx_init,
}, { }, {

View file

@ -216,11 +216,11 @@ static struct regulator_init_data cam_vreg_data = {
static struct mc13783_regulator_init_data moboard_regulators[] = { static struct mc13783_regulator_init_data moboard_regulators[] = {
{ {
.id = MC13783_REGU_VMMC1, .id = MC13783_REG_VMMC1,
.init_data = &sdhc_vreg_data, .init_data = &sdhc_vreg_data,
}, },
{ {
.id = MC13783_REGU_VCAM, .id = MC13783_REG_VCAM,
.init_data = &cam_vreg_data, .init_data = &cam_vreg_data,
}, },
}; };

View file

@ -3,99 +3,94 @@
* *
* License Terms: GNU General Public License v2 * License Terms: GNU General Public License v2
* *
* Author: Sundar Iyer <sundar.iyer@stericsson.com> * Authors: Sundar Iyer <sundar.iyer@stericsson.com>
* Bengt Jonsson <bengt.g.jonsson@stericsson.com>
* *
* MOP500 board specific initialization for regulators * MOP500 board specific initialization for regulators
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
/* supplies to the display/camera */ /* AB8500 regulators */
static struct regulator_init_data ab8500_vaux1_regulator = { struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
.constraints = { /* supplies to the display/camera */
.name = "V-DISPLAY", [AB8500_LDO_AUX1] = {
.min_uV = 2500000, .constraints = {
.max_uV = 2900000, .name = "V-DISPLAY",
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE| .min_uV = 2500000,
REGULATOR_CHANGE_STATUS, .max_uV = 2900000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
},
},
/* supplies to the on-board eMMC */
[AB8500_LDO_AUX2] = {
.constraints = {
.name = "V-eMMC1",
.min_uV = 1100000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
},
},
/* supply for VAUX3, supplies to SDcard slots */
[AB8500_LDO_AUX3] = {
.constraints = {
.name = "V-MMC-SD",
.min_uV = 1100000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
},
},
/* supply for tvout, gpadc, TVOUT LDO */
[AB8500_LDO_TVOUT] = {
.constraints = {
.name = "V-TVOUT",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
/* supply for ab8500-vaudio, VAUDIO LDO */
[AB8500_LDO_AUDIO] = {
.constraints = {
.name = "V-AUD",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
/* supply for v-anamic1 VAMic1-LDO */
[AB8500_LDO_ANAMIC1] = {
.constraints = {
.name = "V-AMIC1",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
[AB8500_LDO_ANAMIC2] = {
.constraints = {
.name = "V-AMIC2",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
/* supply for v-dmic, VDMIC LDO */
[AB8500_LDO_DMIC] = {
.constraints = {
.name = "V-DMIC",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
/* supply for v-intcore12, VINTCORE12 LDO */
[AB8500_LDO_INTCORE] = {
.constraints = {
.name = "V-INTCORE",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
},
/* supply for U8500 CSI/DSI, VANA LDO */
[AB8500_LDO_ANA] = {
.constraints = {
.name = "V-CSI/DSI",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
}, },
}; };
/* supplies to the on-board eMMC */
static struct regulator_init_data ab8500_vaux2_regulator = {
.constraints = {
.name = "V-eMMC1",
.min_uV = 1100000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
REGULATOR_CHANGE_STATUS,
},
};
/* supply for VAUX3, supplies to SDcard slots */
static struct regulator_init_data ab8500_vaux3_regulator = {
.constraints = {
.name = "V-MMC-SD",
.min_uV = 1100000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
REGULATOR_CHANGE_STATUS,
},
};
/* supply for tvout, gpadc, TVOUT LDO */
static struct regulator_init_data ab8500_vtvout_init = {
.constraints = {
.name = "V-TVOUT",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
/* supply for ab8500-vaudio, VAUDIO LDO */
static struct regulator_init_data ab8500_vaudio_init = {
.constraints = {
.name = "V-AUD",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
/* supply for v-anamic1 VAMic1-LDO */
static struct regulator_init_data ab8500_vamic1_init = {
.constraints = {
.name = "V-AMIC1",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
static struct regulator_init_data ab8500_vamic2_init = {
.constraints = {
.name = "V-AMIC2",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
/* supply for v-dmic, VDMIC LDO */
static struct regulator_init_data ab8500_vdmic_init = {
.constraints = {
.name = "V-DMIC",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
/* supply for v-intcore12, VINTCORE12 LDO */
static struct regulator_init_data ab8500_vintcore_init = {
.constraints = {
.name = "V-INTCORE",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
/* supply for U8500 CSI/DSI, VANA LDO */
static struct regulator_init_data ab8500_vana_init = {
.constraints = {
.name = "V-CSI/DSI",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};

View file

@ -0,0 +1,19 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
*
* MOP500 board specific initialization for regulators
*/
#ifndef __BOARD_MOP500_REGULATORS_H
#define __BOARD_MOP500_REGULATORS_H
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
#endif

View file

@ -35,6 +35,7 @@
#include "devices-db8500.h" #include "devices-db8500.h"
#include "pins-db8500.h" #include "pins-db8500.h"
#include "board-mop500.h" #include "board-mop500.h"
#include "board-mop500-regulators.h"
static pin_cfg_t mop500_pins[] = { static pin_cfg_t mop500_pins[] = {
/* SSP0 */ /* SSP0 */
@ -80,6 +81,8 @@ static pin_cfg_t mop500_pins[] = {
static struct ab8500_platform_data ab8500_platdata = { static struct ab8500_platform_data ab8500_platdata = {
.irq_base = MOP500_AB8500_IRQ_BASE, .irq_base = MOP500_AB8500_IRQ_BASE,
.regulator = ab8500_regulators,
.num_regulator = ARRAY_SIZE(ab8500_regulators),
}; };
static struct resource ab8500_resources[] = { static struct resource ab8500_resources[] = {

View file

@ -249,7 +249,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
} }
static int pm8607_set_voltage(struct regulator_dev *rdev, static int pm8607_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
uint8_t val, mask; uint8_t val, mask;
@ -263,6 +263,7 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
ret = choose_voltage(rdev, min_uV, max_uV); ret = choose_voltage(rdev, min_uV, max_uV);
if (ret < 0) if (ret < 0)
return -EINVAL; return -EINVAL;
*selector = ret;
val = (uint8_t)(ret << info->vol_shift); val = (uint8_t)(ret << info->vol_shift);
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

View file

@ -186,13 +186,25 @@ config REGULATOR_PCAP
This driver provides support for the voltage regulators of the This driver provides support for the voltage regulators of the
PCAP2 PMIC. PCAP2 PMIC.
config REGULATOR_MC13XXX_CORE
tristate
config REGULATOR_MC13783 config REGULATOR_MC13783
tristate "Support regulators on Freescale MC13783 PMIC" tristate "Support regulators on Freescale MC13783 PMIC"
depends on MFD_MC13783 depends on MFD_MC13783
select REGULATOR_MC13XXX_CORE
help help
Say y here to support the regulators found on the Freescale MC13783 Say y here to support the regulators found on the Freescale MC13783
PMIC. PMIC.
config REGULATOR_MC13892
tristate "Support regulators on Freescale MC13892 PMIC"
depends on MFD_MC13XXX
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13892
PMIC.
config REGULATOR_AB3100 config REGULATOR_AB3100
tristate "ST-Ericsson AB3100 Regulator functions" tristate "ST-Ericsson AB3100 Regulator functions"
depends on AB3100_CORE depends on AB3100_CORE
@ -250,5 +262,15 @@ config REGULATOR_TPS6586X
help help
This driver supports TPS6586X voltage regulator chips. This driver supports TPS6586X voltage regulator chips.
config REGULATOR_TPS6524X
tristate "TI TPS6524X Power regulators"
depends on SPI
help
This driver supports TPS6524X voltage regulator chips. TPS6524X
provides three step-down converters and two general-purpose LDO
voltage regulators. This device is interfaced using a customized
serial interface currently supported on the sequencer serial
port controller.
endif endif

View file

@ -30,10 +30,13 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o

View file

@ -362,7 +362,8 @@ static int ab3100_get_best_voltage_index(struct regulator_dev *reg,
} }
static int ab3100_set_voltage_regulator(struct regulator_dev *reg, static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct ab3100_regulator *abreg = reg->reg_data; struct ab3100_regulator *abreg = reg->reg_data;
u8 regval; u8 regval;
@ -373,6 +374,8 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
if (bestindex < 0) if (bestindex < 0)
return bestindex; return bestindex;
*selector = bestindex;
err = abx500_get_register_interruptible(abreg->dev, 0, err = abx500_get_register_interruptible(abreg->dev, 0,
abreg->regreg, &regval); abreg->regreg, &regval);
if (err) { if (err) {

View file

@ -3,18 +3,13 @@
* *
* License Terms: GNU General Public License v2 * License Terms: GNU General Public License v2
* *
* Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
* Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
* *
* AB8500 peripheral regulators * AB8500 peripheral regulators
* *
* AB8500 supports the following regulators, * AB8500 supports the following regulators:
* LDOs - VAUDIO, VANAMIC2/2, VDIGMIC, VINTCORE12, VTVOUT, * VAUX1/2/3, VINTCORE, VTVOUT, VAUDIO, VAMIC1/2, VDMIC, VANA
* VAUX1/2/3, VANA
*
* for DB8500 cut 1.0 and previous versions of the silicon, all accesses
* to registers are through the DB8500 SPI. In cut 1.1 onwards, these
* accesses are through the DB8500 PRCMU I2C
*
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -28,38 +23,37 @@
/** /**
* struct ab8500_regulator_info - ab8500 regulator information * struct ab8500_regulator_info - ab8500 regulator information
* @dev: device pointer
* @desc: regulator description * @desc: regulator description
* @ab8500: ab8500 parent
* @regulator_dev: regulator device * @regulator_dev: regulator device
* @max_uV: maximum voltage (for variable voltage supplies) * @max_uV: maximum voltage (for variable voltage supplies)
* @min_uV: minimum voltage (for variable voltage supplies) * @min_uV: minimum voltage (for variable voltage supplies)
* @fixed_uV: typical voltage (for fixed voltage supplies) * @fixed_uV: typical voltage (for fixed voltage supplies)
* @update_bank: bank to control on/off * @update_bank: bank to control on/off
* @update_reg: register to control on/off * @update_reg: register to control on/off
* @mask: mask to enable/disable regulator * @update_mask: mask to enable/disable regulator
* @enable: bits to enable the regulator in normal(high power) mode * @update_val_enable: bits to enable the regulator in normal (high power) mode
* @voltage_bank: bank to control regulator voltage * @voltage_bank: bank to control regulator voltage
* @voltage_reg: register to control regulator voltage * @voltage_reg: register to control regulator voltage
* @voltage_mask: mask to control regulator voltage * @voltage_mask: mask to control regulator voltage
* @supported_voltages: supported voltage table * @voltages: supported voltage table
* @voltages_len: number of supported voltages for the regulator * @voltages_len: number of supported voltages for the regulator
*/ */
struct ab8500_regulator_info { struct ab8500_regulator_info {
struct device *dev; struct device *dev;
struct regulator_desc desc; struct regulator_desc desc;
struct ab8500 *ab8500;
struct regulator_dev *regulator; struct regulator_dev *regulator;
int max_uV; int max_uV;
int min_uV; int min_uV;
int fixed_uV; int fixed_uV;
u8 update_bank; u8 update_bank;
u8 update_reg; u8 update_reg;
u8 mask; u8 update_mask;
u8 enable; u8 update_val_enable;
u8 voltage_bank; u8 voltage_bank;
u8 voltage_reg; u8 voltage_reg;
u8 voltage_mask; u8 voltage_mask;
int const *supported_voltages; int const *voltages;
int voltages_len; int voltages_len;
}; };
@ -83,6 +77,17 @@ static const int ldo_vauxn_voltages[] = {
3300000, 3300000,
}; };
static const int ldo_vaux3_voltages[] = {
1200000,
1500000,
1800000,
2100000,
2500000,
2750000,
2790000,
2910000,
};
static const int ldo_vintcore_voltages[] = { static const int ldo_vintcore_voltages[] = {
1200000, 1200000,
1225000, 1225000,
@ -95,57 +100,80 @@ static const int ldo_vintcore_voltages[] = {
static int ab8500_regulator_enable(struct regulator_dev *rdev) static int ab8500_regulator_enable(struct regulator_dev *rdev)
{ {
int regulator_id, ret; int ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
ret = abx500_mask_and_set_register_interruptible(info->dev, ret = abx500_mask_and_set_register_interruptible(info->dev,
info->update_bank, info->update_reg, info->mask, info->enable); info->update_bank, info->update_reg,
info->update_mask, info->update_val_enable);
if (ret < 0) if (ret < 0)
dev_err(rdev_get_dev(rdev), dev_err(rdev_get_dev(rdev),
"couldn't set enable bits for regulator\n"); "couldn't set enable bits for regulator\n");
dev_vdbg(rdev_get_dev(rdev),
"%s-enable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
info->desc.name, info->update_bank, info->update_reg,
info->update_mask, info->update_val_enable);
return ret; return ret;
} }
static int ab8500_regulator_disable(struct regulator_dev *rdev) static int ab8500_regulator_disable(struct regulator_dev *rdev)
{ {
int regulator_id, ret; int ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
ret = abx500_mask_and_set_register_interruptible(info->dev, ret = abx500_mask_and_set_register_interruptible(info->dev,
info->update_bank, info->update_reg, info->mask, 0x0); info->update_bank, info->update_reg,
info->update_mask, 0x0);
if (ret < 0) if (ret < 0)
dev_err(rdev_get_dev(rdev), dev_err(rdev_get_dev(rdev),
"couldn't set disable bits for regulator\n"); "couldn't set disable bits for regulator\n");
dev_vdbg(rdev_get_dev(rdev),
"%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
info->desc.name, info->update_bank, info->update_reg,
info->update_mask, 0x0);
return ret; return ret;
} }
static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
{ {
int regulator_id, ret; int ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
u8 value; u8 regval;
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
ret = abx500_get_register_interruptible(info->dev, ret = abx500_get_register_interruptible(info->dev,
info->update_bank, info->update_reg, &value); info->update_bank, info->update_reg, &regval);
if (ret < 0) { if (ret < 0) {
dev_err(rdev_get_dev(rdev), dev_err(rdev_get_dev(rdev),
"couldn't read 0x%x register\n", info->update_reg); "couldn't read 0x%x register\n", info->update_reg);
return ret; return ret;
} }
if (value & info->mask) dev_vdbg(rdev_get_dev(rdev),
"%s-is_enabled (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
" 0x%x\n",
info->desc.name, info->update_bank, info->update_reg,
info->update_mask, regval);
if (regval & info->update_mask)
return true; return true;
else else
return false; return false;
@ -153,12 +181,12 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
{ {
int regulator_id;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
/* return the uV for the fixed regulators */ /* return the uV for the fixed regulators */
if (info->fixed_uV) if (info->fixed_uV)
@ -167,33 +195,40 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
if (selector >= info->voltages_len) if (selector >= info->voltages_len)
return -EINVAL; return -EINVAL;
return info->supported_voltages[selector]; return info->voltages[selector];
} }
static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) static int ab8500_regulator_get_voltage(struct regulator_dev *rdev)
{ {
int regulator_id, ret; int ret, val;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
u8 value; u8 regval;
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
ret = abx500_get_register_interruptible(info->dev, info->voltage_bank, ret = abx500_get_register_interruptible(info->dev,
info->voltage_reg, &value); info->voltage_bank, info->voltage_reg, &regval);
if (ret < 0) { if (ret < 0) {
dev_err(rdev_get_dev(rdev), dev_err(rdev_get_dev(rdev),
"couldn't read voltage reg for regulator\n"); "couldn't read voltage reg for regulator\n");
return ret; return ret;
} }
dev_vdbg(rdev_get_dev(rdev),
"%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
" 0x%x\n",
info->desc.name, info->voltage_bank, info->voltage_reg,
info->voltage_mask, regval);
/* vintcore has a different layout */ /* vintcore has a different layout */
value &= info->voltage_mask; val = regval & info->voltage_mask;
if (regulator_id == AB8500_LDO_INTCORE) if (info->desc.id == AB8500_LDO_INTCORE)
ret = info->supported_voltages[value >> 0x3]; ret = info->voltages[val >> 0x3];
else else
ret = info->supported_voltages[value]; ret = info->voltages[val];
return ret; return ret;
} }
@ -206,8 +241,8 @@ static int ab8500_get_best_voltage_index(struct regulator_dev *rdev,
/* check the supported voltage */ /* check the supported voltage */
for (i = 0; i < info->voltages_len; i++) { for (i = 0; i < info->voltages_len; i++) {
if ((info->supported_voltages[i] >= min_uV) && if ((info->voltages[i] >= min_uV) &&
(info->supported_voltages[i] <= max_uV)) (info->voltages[i] <= max_uV))
return i; return i;
} }
@ -215,14 +250,17 @@ static int ab8500_get_best_voltage_index(struct regulator_dev *rdev,
} }
static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
int regulator_id, ret; int ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
u8 regval;
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
/* get the appropriate voltages within the range */ /* get the appropriate voltages within the range */
ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV); ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV);
@ -232,14 +270,23 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
return ret; return ret;
} }
*selector = ret;
/* set the registers for the request */ /* set the registers for the request */
regval = (u8)ret;
ret = abx500_mask_and_set_register_interruptible(info->dev, ret = abx500_mask_and_set_register_interruptible(info->dev,
info->voltage_bank, info->voltage_reg, info->voltage_bank, info->voltage_reg,
info->voltage_mask, (u8)ret); info->voltage_mask, regval);
if (ret < 0) if (ret < 0)
dev_err(rdev_get_dev(rdev), dev_err(rdev_get_dev(rdev),
"couldn't set voltage reg for regulator\n"); "couldn't set voltage reg for regulator\n");
dev_vdbg(rdev_get_dev(rdev),
"%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
" 0x%x\n",
info->desc.name, info->voltage_bank, info->voltage_reg,
info->voltage_mask, regval);
return ret; return ret;
} }
@ -254,17 +301,17 @@ static struct regulator_ops ab8500_regulator_ops = {
static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
{ {
int regulator_id;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
regulator_id = rdev_get_id(rdev); if (info == NULL) {
if (regulator_id >= AB8500_NUM_REGULATORS) dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL; return -EINVAL;
}
return info->fixed_uV; return info->fixed_uV;
} }
static struct regulator_ops ab8500_ldo_fixed_ops = { static struct regulator_ops ab8500_regulator_fixed_ops = {
.enable = ab8500_regulator_enable, .enable = ab8500_regulator_enable,
.disable = ab8500_regulator_disable, .disable = ab8500_regulator_disable,
.is_enabled = ab8500_regulator_is_enabled, .is_enabled = ab8500_regulator_is_enabled,
@ -272,89 +319,198 @@ static struct regulator_ops ab8500_ldo_fixed_ops = {
.list_voltage = ab8500_list_voltage, .list_voltage = ab8500_list_voltage,
}; };
#define AB8500_LDO(_id, min, max, bank, reg, reg_mask, \ static struct ab8500_regulator_info
reg_enable, volt_bank, volt_reg, volt_mask, \ ab8500_regulator_info[AB8500_NUM_REGULATORS] = {
voltages, len_volts) \
{ \
.desc = { \
.name = "LDO-" #_id, \
.ops = &ab8500_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = AB8500_LDO_##_id, \
.owner = THIS_MODULE, \
}, \
.min_uV = (min) * 1000, \
.max_uV = (max) * 1000, \
.update_bank = bank, \
.update_reg = reg, \
.mask = reg_mask, \
.enable = reg_enable, \
.voltage_bank = volt_bank, \
.voltage_reg = volt_reg, \
.voltage_mask = volt_mask, \
.supported_voltages = voltages, \
.voltages_len = len_volts, \
.fixed_uV = 0, \
}
#define AB8500_FIXED_LDO(_id, fixed, bank, reg, \
reg_mask, reg_enable) \
{ \
.desc = { \
.name = "LDO-" #_id, \
.ops = &ab8500_ldo_fixed_ops, \
.type = REGULATOR_VOLTAGE, \
.id = AB8500_LDO_##_id, \
.owner = THIS_MODULE, \
}, \
.fixed_uV = fixed * 1000, \
.update_bank = bank, \
.update_reg = reg, \
.mask = reg_mask, \
.enable = reg_enable, \
}
static struct ab8500_regulator_info ab8500_regulator_info[] = {
/* /*
* Variable Voltage LDOs * Variable Voltage Regulators
* name, min uV, max uV, ctrl bank, ctrl reg, reg mask, enable mask, * name, min mV, max mV,
* volt ctrl bank, volt ctrl reg, volt ctrl mask, volt table, * update bank, reg, mask, enable val
* num supported volts * volt bank, reg, mask, table, table length
*/ */
AB8500_LDO(AUX1, 1100, 3300, 0x04, 0x09, 0x3, 0x1, 0x04, 0x1f, 0xf, [AB8500_LDO_AUX1] = {
ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), .desc = {
AB8500_LDO(AUX2, 1100, 3300, 0x04, 0x09, 0xc, 0x4, 0x04, 0x20, 0xf, .name = "LDO-AUX1",
ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), .ops = &ab8500_regulator_ops,
AB8500_LDO(AUX3, 1100, 3300, 0x04, 0x0a, 0x3, 0x1, 0x04, 0x21, 0xf, .type = REGULATOR_VOLTAGE,
ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), .id = AB8500_LDO_AUX1,
AB8500_LDO(INTCORE, 1100, 3300, 0x03, 0x80, 0x4, 0x4, 0x03, 0x80, 0x38, .owner = THIS_MODULE,
ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)), .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
},
.min_uV = 1100000,
.max_uV = 3300000,
.update_bank = 0x04,
.update_reg = 0x09,
.update_mask = 0x03,
.update_val_enable = 0x01,
.voltage_bank = 0x04,
.voltage_reg = 0x1f,
.voltage_mask = 0x0f,
.voltages = ldo_vauxn_voltages,
.voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
},
[AB8500_LDO_AUX2] = {
.desc = {
.name = "LDO-AUX2",
.ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUX2,
.owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
},
.min_uV = 1100000,
.max_uV = 3300000,
.update_bank = 0x04,
.update_reg = 0x09,
.update_mask = 0x0c,
.update_val_enable = 0x04,
.voltage_bank = 0x04,
.voltage_reg = 0x20,
.voltage_mask = 0x0f,
.voltages = ldo_vauxn_voltages,
.voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
},
[AB8500_LDO_AUX3] = {
.desc = {
.name = "LDO-AUX3",
.ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUX3,
.owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vaux3_voltages),
},
.min_uV = 1100000,
.max_uV = 3300000,
.update_bank = 0x04,
.update_reg = 0x0a,
.update_mask = 0x03,
.update_val_enable = 0x01,
.voltage_bank = 0x04,
.voltage_reg = 0x21,
.voltage_mask = 0x07,
.voltages = ldo_vaux3_voltages,
.voltages_len = ARRAY_SIZE(ldo_vaux3_voltages),
},
[AB8500_LDO_INTCORE] = {
.desc = {
.name = "LDO-INTCORE",
.ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_INTCORE,
.owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vintcore_voltages),
},
.min_uV = 1100000,
.max_uV = 3300000,
.update_bank = 0x03,
.update_reg = 0x80,
.update_mask = 0x44,
.update_val_enable = 0x04,
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
.voltages = ldo_vintcore_voltages,
.voltages_len = ARRAY_SIZE(ldo_vintcore_voltages),
},
/* /*
* Fixed Voltage LDOs * Fixed Voltage Regulators
* name, o/p uV, ctrl bank, ctrl reg, enable, disable * name, fixed mV,
* update bank, reg, mask, enable val
*/ */
AB8500_FIXED_LDO(TVOUT, 2000, 0x03, 0x80, 0x2, 0x2), [AB8500_LDO_TVOUT] = {
AB8500_FIXED_LDO(AUDIO, 2000, 0x03, 0x83, 0x2, 0x2), .desc = {
AB8500_FIXED_LDO(ANAMIC1, 2050, 0x03, 0x83, 0x4, 0x4), .name = "LDO-TVOUT",
AB8500_FIXED_LDO(ANAMIC2, 2050, 0x03, 0x83, 0x8, 0x8), .ops = &ab8500_regulator_fixed_ops,
AB8500_FIXED_LDO(DMIC, 1800, 0x03, 0x83, 0x10, 0x10), .type = REGULATOR_VOLTAGE,
AB8500_FIXED_LDO(ANA, 1200, 0x03, 0x83, 0xc, 0x4), .id = AB8500_LDO_TVOUT,
.owner = THIS_MODULE,
.n_voltages = 1,
},
.fixed_uV = 2000000,
.update_bank = 0x03,
.update_reg = 0x80,
.update_mask = 0x82,
.update_val_enable = 0x02,
},
[AB8500_LDO_AUDIO] = {
.desc = {
.name = "LDO-AUDIO",
.ops = &ab8500_regulator_fixed_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUDIO,
.owner = THIS_MODULE,
.n_voltages = 1,
},
.fixed_uV = 2000000,
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x02,
.update_val_enable = 0x02,
},
[AB8500_LDO_ANAMIC1] = {
.desc = {
.name = "LDO-ANAMIC1",
.ops = &ab8500_regulator_fixed_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_ANAMIC1,
.owner = THIS_MODULE,
.n_voltages = 1,
},
.fixed_uV = 2050000,
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x08,
.update_val_enable = 0x08,
},
[AB8500_LDO_ANAMIC2] = {
.desc = {
.name = "LDO-ANAMIC2",
.ops = &ab8500_regulator_fixed_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_ANAMIC2,
.owner = THIS_MODULE,
.n_voltages = 1,
},
.fixed_uV = 2050000,
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x10,
.update_val_enable = 0x10,
},
[AB8500_LDO_DMIC] = {
.desc = {
.name = "LDO-DMIC",
.ops = &ab8500_regulator_fixed_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_DMIC,
.owner = THIS_MODULE,
.n_voltages = 1,
},
.fixed_uV = 1800000,
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x04,
.update_val_enable = 0x04,
},
[AB8500_LDO_ANA] = {
.desc = {
.name = "LDO-ANA",
.ops = &ab8500_regulator_fixed_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_ANA,
.owner = THIS_MODULE,
.n_voltages = 1,
},
.fixed_uV = 1200000,
.update_bank = 0x04,
.update_reg = 0x06,
.update_mask = 0x0c,
.update_val_enable = 0x04,
},
}; };
static inline struct ab8500_regulator_info *find_regulator_info(int id)
{
struct ab8500_regulator_info *info;
int i;
for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
info = &ab8500_regulator_info[i];
if (info->desc.id == id)
return info;
}
return NULL;
}
static __devinit int ab8500_regulator_probe(struct platform_device *pdev) static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
{ {
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
@ -366,6 +522,16 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
pdata = dev_get_platdata(ab8500->dev); pdata = dev_get_platdata(ab8500->dev);
if (!pdata) {
dev_err(&pdev->dev, "null pdata\n");
return -EINVAL;
}
/* make sure the platform data has the correct size */
if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
dev_err(&pdev->dev, "platform configuration error\n");
return -EINVAL;
}
/* register all regulators */ /* register all regulators */
for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
@ -374,10 +540,22 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
/* assign per-regulator data */ /* assign per-regulator data */
info = &ab8500_regulator_info[i]; info = &ab8500_regulator_info[i];
info->dev = &pdev->dev; info->dev = &pdev->dev;
info->ab8500 = ab8500;
/* fix for hardware before ab8500v2.0 */
if (abx500_get_chip_id(info->dev) < 0x20) {
if (info->desc.id == AB8500_LDO_AUX3) {
info->desc.n_voltages =
ARRAY_SIZE(ldo_vauxn_voltages);
info->voltages = ldo_vauxn_voltages;
info->voltages_len =
ARRAY_SIZE(ldo_vauxn_voltages);
info->voltage_mask = 0xf;
}
}
/* register regulator with framework */
info->regulator = regulator_register(&info->desc, &pdev->dev, info->regulator = regulator_register(&info->desc, &pdev->dev,
pdata->regulator[i], info); &pdata->regulator[i], info);
if (IS_ERR(info->regulator)) { if (IS_ERR(info->regulator)) {
err = PTR_ERR(info->regulator); err = PTR_ERR(info->regulator);
dev_err(&pdev->dev, "failed to register regulator %s\n", dev_err(&pdev->dev, "failed to register regulator %s\n",
@ -389,6 +567,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
} }
return err; return err;
} }
dev_vdbg(rdev_get_dev(info->regulator),
"%s-probed\n", info->desc.name);
} }
return 0; return 0;
@ -401,6 +582,10 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
struct ab8500_regulator_info *info = NULL; struct ab8500_regulator_info *info = NULL;
info = &ab8500_regulator_info[i]; info = &ab8500_regulator_info[i];
dev_vdbg(rdev_get_dev(info->regulator),
"%s-remove\n", info->desc.name);
regulator_unregister(info->regulator); regulator_unregister(info->regulator);
} }

View file

@ -13,8 +13,11 @@
* *
*/ */
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
@ -25,16 +28,30 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#define CREATE_TRACE_POINTS
#include <trace/events/regulator.h>
#include "dummy.h" #include "dummy.h"
#define REGULATOR_VERSION "0.5" #define rdev_err(rdev, fmt, ...) \
pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
#define rdev_warn(rdev, fmt, ...) \
pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
#define rdev_info(rdev, fmt, ...) \
pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
#define rdev_dbg(rdev, fmt, ...) \
pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
static DEFINE_MUTEX(regulator_list_mutex); static DEFINE_MUTEX(regulator_list_mutex);
static LIST_HEAD(regulator_list); static LIST_HEAD(regulator_list);
static LIST_HEAD(regulator_map_list); static LIST_HEAD(regulator_map_list);
static int has_full_constraints; static bool has_full_constraints;
static bool board_wants_dummy_regulator; static bool board_wants_dummy_regulator;
#ifdef CONFIG_DEBUG_FS
static struct dentry *debugfs_root;
#endif
/* /*
* struct regulator_map * struct regulator_map
* *
@ -71,6 +88,8 @@ static int _regulator_get_current_limit(struct regulator_dev *rdev);
static unsigned int _regulator_get_mode(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
static void _notifier_call_chain(struct regulator_dev *rdev, static void _notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data); unsigned long event, void *data);
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV);
static const char *rdev_get_name(struct regulator_dev *rdev) static const char *rdev_get_name(struct regulator_dev *rdev)
{ {
@ -111,13 +130,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
BUG_ON(*min_uV > *max_uV); BUG_ON(*min_uV > *max_uV);
if (!rdev->constraints) { if (!rdev->constraints) {
printk(KERN_ERR "%s: no constraints for %s\n", __func__, rdev_err(rdev, "no constraints\n");
rdev_get_name(rdev));
return -ENODEV; return -ENODEV;
} }
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
printk(KERN_ERR "%s: operation not allowed for %s\n", rdev_err(rdev, "operation not allowed\n");
__func__, rdev_get_name(rdev));
return -EPERM; return -EPERM;
} }
@ -132,6 +149,27 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
return 0; return 0;
} }
/* Make sure we select a voltage that suits the needs of all
* regulator consumers
*/
static int regulator_check_consumers(struct regulator_dev *rdev,
int *min_uV, int *max_uV)
{
struct regulator *regulator;
list_for_each_entry(regulator, &rdev->consumer_list, list) {
if (*max_uV > regulator->max_uV)
*max_uV = regulator->max_uV;
if (*min_uV < regulator->min_uV)
*min_uV = regulator->min_uV;
}
if (*min_uV > *max_uV)
return -EINVAL;
return 0;
}
/* current constraint check */ /* current constraint check */
static int regulator_check_current_limit(struct regulator_dev *rdev, static int regulator_check_current_limit(struct regulator_dev *rdev,
int *min_uA, int *max_uA) int *min_uA, int *max_uA)
@ -139,13 +177,11 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
BUG_ON(*min_uA > *max_uA); BUG_ON(*min_uA > *max_uA);
if (!rdev->constraints) { if (!rdev->constraints) {
printk(KERN_ERR "%s: no constraints for %s\n", __func__, rdev_err(rdev, "no constraints\n");
rdev_get_name(rdev));
return -ENODEV; return -ENODEV;
} }
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
printk(KERN_ERR "%s: operation not allowed for %s\n", rdev_err(rdev, "operation not allowed\n");
__func__, rdev_get_name(rdev));
return -EPERM; return -EPERM;
} }
@ -174,18 +210,15 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)
} }
if (!rdev->constraints) { if (!rdev->constraints) {
printk(KERN_ERR "%s: no constraints for %s\n", __func__, rdev_err(rdev, "no constraints\n");
rdev_get_name(rdev));
return -ENODEV; return -ENODEV;
} }
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
printk(KERN_ERR "%s: operation not allowed for %s\n", rdev_err(rdev, "operation not allowed\n");
__func__, rdev_get_name(rdev));
return -EPERM; return -EPERM;
} }
if (!(rdev->constraints->valid_modes_mask & mode)) { if (!(rdev->constraints->valid_modes_mask & mode)) {
printk(KERN_ERR "%s: invalid mode %x for %s\n", rdev_err(rdev, "invalid mode %x\n", mode);
__func__, mode, rdev_get_name(rdev));
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
@ -195,13 +228,11 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)
static int regulator_check_drms(struct regulator_dev *rdev) static int regulator_check_drms(struct regulator_dev *rdev)
{ {
if (!rdev->constraints) { if (!rdev->constraints) {
printk(KERN_ERR "%s: no constraints for %s\n", __func__, rdev_err(rdev, "no constraints\n");
rdev_get_name(rdev));
return -ENODEV; return -ENODEV;
} }
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
printk(KERN_ERR "%s: operation not allowed for %s\n", rdev_err(rdev, "operation not allowed\n");
__func__, rdev_get_name(rdev));
return -EPERM; return -EPERM;
} }
return 0; return 0;
@ -553,18 +584,21 @@ static void drms_uA_update(struct regulator_dev *rdev)
err = regulator_check_drms(rdev); err = regulator_check_drms(rdev);
if (err < 0 || !rdev->desc->ops->get_optimum_mode || if (err < 0 || !rdev->desc->ops->get_optimum_mode ||
!rdev->desc->ops->get_voltage || !rdev->desc->ops->set_mode) (!rdev->desc->ops->get_voltage &&
!rdev->desc->ops->get_voltage_sel) ||
!rdev->desc->ops->set_mode)
return; return;
/* get output voltage */ /* get output voltage */
output_uV = rdev->desc->ops->get_voltage(rdev); output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) if (output_uV <= 0)
return; return;
/* get input voltage */ /* get input voltage */
if (rdev->supply && rdev->supply->desc->ops->get_voltage) input_uV = 0;
input_uV = rdev->supply->desc->ops->get_voltage(rdev->supply); if (rdev->supply)
else input_uV = _regulator_get_voltage(rdev);
if (input_uV <= 0)
input_uV = rdev->constraints->input_uV; input_uV = rdev->constraints->input_uV;
if (input_uV <= 0) if (input_uV <= 0)
return; return;
@ -598,20 +632,17 @@ static int suspend_set_state(struct regulator_dev *rdev,
*/ */
if (!rstate->enabled && !rstate->disabled) { if (!rstate->enabled && !rstate->disabled) {
if (can_set_state) if (can_set_state)
printk(KERN_WARNING "%s: No configuration for %s\n", rdev_warn(rdev, "No configuration\n");
__func__, rdev_get_name(rdev));
return 0; return 0;
} }
if (rstate->enabled && rstate->disabled) { if (rstate->enabled && rstate->disabled) {
printk(KERN_ERR "%s: invalid configuration for %s\n", rdev_err(rdev, "invalid configuration\n");
__func__, rdev_get_name(rdev));
return -EINVAL; return -EINVAL;
} }
if (!can_set_state) { if (!can_set_state) {
printk(KERN_ERR "%s: no way to set suspend state\n", rdev_err(rdev, "no way to set suspend state\n");
__func__);
return -EINVAL; return -EINVAL;
} }
@ -620,15 +651,14 @@ static int suspend_set_state(struct regulator_dev *rdev,
else else
ret = rdev->desc->ops->set_suspend_disable(rdev); ret = rdev->desc->ops->set_suspend_disable(rdev);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to enabled/disable\n", __func__); rdev_err(rdev, "failed to enabled/disable\n");
return ret; return ret;
} }
if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to set voltage\n", rdev_err(rdev, "failed to set voltage\n");
__func__);
return ret; return ret;
} }
} }
@ -636,7 +666,7 @@ static int suspend_set_state(struct regulator_dev *rdev,
if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to set mode\n", __func__); rdev_err(rdev, "failed to set mode\n");
return ret; return ret;
} }
} }
@ -714,29 +744,27 @@ static void print_constraints(struct regulator_dev *rdev)
if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
count += sprintf(buf + count, "standby"); count += sprintf(buf + count, "standby");
printk(KERN_INFO "regulator: %s: %s\n", rdev_get_name(rdev), buf); rdev_info(rdev, "%s\n", buf);
} }
static int machine_constraints_voltage(struct regulator_dev *rdev, static int machine_constraints_voltage(struct regulator_dev *rdev,
struct regulation_constraints *constraints) struct regulation_constraints *constraints)
{ {
struct regulator_ops *ops = rdev->desc->ops; struct regulator_ops *ops = rdev->desc->ops;
const char *name = rdev_get_name(rdev);
int ret; int ret;
/* do we need to apply the constraint voltage */ /* do we need to apply the constraint voltage */
if (rdev->constraints->apply_uV && if (rdev->constraints->apply_uV &&
rdev->constraints->min_uV == rdev->constraints->max_uV && rdev->constraints->min_uV == rdev->constraints->max_uV) {
ops->set_voltage) { ret = _regulator_do_set_voltage(rdev,
ret = ops->set_voltage(rdev, rdev->constraints->min_uV,
rdev->constraints->min_uV, rdev->constraints->max_uV); rdev->constraints->max_uV);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n", rdev_err(rdev, "failed to apply %duV constraint\n",
__func__, rdev->constraints->min_uV);
rdev->constraints->min_uV, name); rdev->constraints = NULL;
rdev->constraints = NULL; return ret;
return ret; }
}
} }
/* constrain machine-level voltage specs to fit /* constrain machine-level voltage specs to fit
@ -765,8 +793,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
/* else require explicit machine-level constraints */ /* else require explicit machine-level constraints */
if (cmin <= 0 || cmax <= 0 || cmax < cmin) { if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
pr_err("%s: %s '%s' voltage constraints\n", rdev_err(rdev, "invalid voltage constraints\n");
__func__, "invalid", name);
return -EINVAL; return -EINVAL;
} }
@ -787,22 +814,19 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
/* final: [min_uV..max_uV] valid iff constraints valid */ /* final: [min_uV..max_uV] valid iff constraints valid */
if (max_uV < min_uV) { if (max_uV < min_uV) {
pr_err("%s: %s '%s' voltage constraints\n", rdev_err(rdev, "unsupportable voltage constraints\n");
__func__, "unsupportable", name);
return -EINVAL; return -EINVAL;
} }
/* use regulator's subset of machine constraints */ /* use regulator's subset of machine constraints */
if (constraints->min_uV < min_uV) { if (constraints->min_uV < min_uV) {
pr_debug("%s: override '%s' %s, %d -> %d\n", rdev_dbg(rdev, "override min_uV, %d -> %d\n",
__func__, name, "min_uV", constraints->min_uV, min_uV);
constraints->min_uV, min_uV);
constraints->min_uV = min_uV; constraints->min_uV = min_uV;
} }
if (constraints->max_uV > max_uV) { if (constraints->max_uV > max_uV) {
pr_debug("%s: override '%s' %s, %d -> %d\n", rdev_dbg(rdev, "override max_uV, %d -> %d\n",
__func__, name, "max_uV", constraints->max_uV, max_uV);
constraints->max_uV, max_uV);
constraints->max_uV = max_uV; constraints->max_uV = max_uV;
} }
} }
@ -822,26 +846,25 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
* set_mode. * set_mode.
*/ */
static int set_machine_constraints(struct regulator_dev *rdev, static int set_machine_constraints(struct regulator_dev *rdev,
struct regulation_constraints *constraints) const struct regulation_constraints *constraints)
{ {
int ret = 0; int ret = 0;
const char *name;
struct regulator_ops *ops = rdev->desc->ops; struct regulator_ops *ops = rdev->desc->ops;
rdev->constraints = constraints; rdev->constraints = kmemdup(constraints, sizeof(*constraints),
GFP_KERNEL);
if (!rdev->constraints)
return -ENOMEM;
name = rdev_get_name(rdev); ret = machine_constraints_voltage(rdev, rdev->constraints);
ret = machine_constraints_voltage(rdev, constraints);
if (ret != 0) if (ret != 0)
goto out; goto out;
/* do we need to setup our suspend state */ /* do we need to setup our suspend state */
if (constraints->initial_state) { if (constraints->initial_state) {
ret = suspend_prepare(rdev, constraints->initial_state); ret = suspend_prepare(rdev, rdev->constraints->initial_state);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to set suspend state for %s\n", rdev_err(rdev, "failed to set suspend state\n");
__func__, name);
rdev->constraints = NULL; rdev->constraints = NULL;
goto out; goto out;
} }
@ -849,17 +872,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
if (constraints->initial_mode) { if (constraints->initial_mode) {
if (!ops->set_mode) { if (!ops->set_mode) {
printk(KERN_ERR "%s: no set_mode operation for %s\n", rdev_err(rdev, "no set_mode operation\n");
__func__, name);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
ret = ops->set_mode(rdev, constraints->initial_mode); ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR rdev_err(rdev, "failed to set initial mode: %d\n", ret);
"%s: failed to set initial mode for %s: %d\n",
__func__, name, ret);
goto out; goto out;
} }
} }
@ -867,11 +887,11 @@ static int set_machine_constraints(struct regulator_dev *rdev,
/* If the constraints say the regulator should be on at this point /* If the constraints say the regulator should be on at this point
* and we have control then make sure it is enabled. * and we have control then make sure it is enabled.
*/ */
if ((constraints->always_on || constraints->boot_on) && ops->enable) { if ((rdev->constraints->always_on || rdev->constraints->boot_on) &&
ops->enable) {
ret = ops->enable(rdev); ret = ops->enable(rdev);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to enable %s\n", rdev_err(rdev, "failed to enable\n");
__func__, name);
rdev->constraints = NULL; rdev->constraints = NULL;
goto out; goto out;
} }
@ -899,9 +919,8 @@ static int set_supply(struct regulator_dev *rdev,
err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
"supply"); "supply");
if (err) { if (err) {
printk(KERN_ERR rdev_err(rdev, "could not add device link %s err %d\n",
"%s: could not add device link %s err %d\n", supply_rdev->dev.kobj.name, err);
__func__, supply_rdev->dev.kobj.name, err);
goto out; goto out;
} }
rdev->supply = supply_rdev; rdev->supply = supply_rdev;
@ -957,10 +976,10 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
continue; continue;
dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n", dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n",
dev_name(&node->regulator->dev), dev_name(&node->regulator->dev),
node->regulator->desc->name, node->regulator->desc->name,
supply, supply,
dev_name(&rdev->dev), rdev_get_name(rdev)); dev_name(&rdev->dev), rdev_get_name(rdev));
return -EBUSY; return -EBUSY;
} }
@ -1031,8 +1050,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
regulator->dev_attr.show = device_requested_uA_show; regulator->dev_attr.show = device_requested_uA_show;
err = device_create_file(dev, &regulator->dev_attr); err = device_create_file(dev, &regulator->dev_attr);
if (err < 0) { if (err < 0) {
printk(KERN_WARNING "%s: could not add regulator_dev" rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
" load sysfs\n", __func__);
goto attr_name_err; goto attr_name_err;
} }
@ -1049,9 +1067,8 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
buf); buf);
if (err) { if (err) {
printk(KERN_WARNING rdev_warn(rdev, "could not add device link %s err %d\n",
"%s: could not add device link %s err %d\n", dev->kobj.name, err);
__func__, dev->kobj.name, err);
goto link_name_err; goto link_name_err;
} }
} }
@ -1088,7 +1105,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
int ret; int ret;
if (id == NULL) { if (id == NULL) {
printk(KERN_ERR "regulator: get() with no identifier\n"); pr_err("get() with no identifier\n");
return regulator; return regulator;
} }
@ -1122,8 +1139,8 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
* substitute in a dummy regulator so consumers can continue. * substitute in a dummy regulator so consumers can continue.
*/ */
if (!has_full_constraints) { if (!has_full_constraints) {
pr_warning("%s supply %s not found, using dummy regulator\n", pr_warn("%s supply %s not found, using dummy regulator\n",
devname, id); devname, id);
rdev = dummy_regulator_rdev; rdev = dummy_regulator_rdev;
goto found; goto found;
} }
@ -1274,8 +1291,7 @@ static int _regulator_enable(struct regulator_dev *rdev)
ret = _regulator_enable(rdev->supply); ret = _regulator_enable(rdev->supply);
mutex_unlock(&rdev->supply->mutex); mutex_unlock(&rdev->supply->mutex);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to enable %s: %d\n", rdev_err(rdev, "failed to enable: %d\n", ret);
__func__, rdev_get_name(rdev), ret);
return ret; return ret;
} }
} }
@ -1302,13 +1318,13 @@ static int _regulator_enable(struct regulator_dev *rdev)
if (ret >= 0) { if (ret >= 0) {
delay = ret; delay = ret;
} else { } else {
printk(KERN_WARNING rdev_warn(rdev, "enable_time() failed: %d\n",
"%s: enable_time() failed for %s: %d\n", ret);
__func__, rdev_get_name(rdev),
ret);
delay = 0; delay = 0;
} }
trace_regulator_enable(rdev_get_name(rdev));
/* Allow the regulator to ramp; it would be useful /* Allow the regulator to ramp; it would be useful
* to extend this for bulk operations so that the * to extend this for bulk operations so that the
* regulators can ramp together. */ * regulators can ramp together. */
@ -1316,6 +1332,8 @@ static int _regulator_enable(struct regulator_dev *rdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
trace_regulator_enable_delay(rdev_get_name(rdev));
if (delay >= 1000) { if (delay >= 1000) {
mdelay(delay / 1000); mdelay(delay / 1000);
udelay(delay % 1000); udelay(delay % 1000);
@ -1323,9 +1341,10 @@ static int _regulator_enable(struct regulator_dev *rdev)
udelay(delay); udelay(delay);
} }
trace_regulator_enable_complete(rdev_get_name(rdev));
} else if (ret < 0) { } else if (ret < 0) {
printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", rdev_err(rdev, "is_enabled() failed: %d\n", ret);
__func__, rdev_get_name(rdev), ret);
return ret; return ret;
} }
/* Fallthrough on positive return values - already enabled */ /* Fallthrough on positive return values - already enabled */
@ -1367,8 +1386,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
*supply_rdev_ptr = NULL; *supply_rdev_ptr = NULL;
if (WARN(rdev->use_count <= 0, if (WARN(rdev->use_count <= 0,
"unbalanced disables for %s\n", "unbalanced disables for %s\n", rdev_get_name(rdev)))
rdev_get_name(rdev)))
return -EIO; return -EIO;
/* are we the last user and permitted to disable ? */ /* are we the last user and permitted to disable ? */
@ -1378,13 +1396,16 @@ static int _regulator_disable(struct regulator_dev *rdev,
/* we are last user */ /* we are last user */
if (_regulator_can_change_status(rdev) && if (_regulator_can_change_status(rdev) &&
rdev->desc->ops->disable) { rdev->desc->ops->disable) {
trace_regulator_disable(rdev_get_name(rdev));
ret = rdev->desc->ops->disable(rdev); ret = rdev->desc->ops->disable(rdev);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to disable %s\n", rdev_err(rdev, "failed to disable\n");
__func__, rdev_get_name(rdev));
return ret; return ret;
} }
trace_regulator_disable_complete(rdev_get_name(rdev));
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
NULL); NULL);
} }
@ -1451,8 +1472,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
/* ah well, who wants to live forever... */ /* ah well, who wants to live forever... */
ret = rdev->desc->ops->disable(rdev); ret = rdev->desc->ops->disable(rdev);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to force disable %s\n", rdev_err(rdev, "failed to force disable\n");
__func__, rdev_get_name(rdev));
return ret; return ret;
} }
/* notify other consumers that power has been forced off */ /* notify other consumers that power has been forced off */
@ -1605,6 +1625,62 @@ int regulator_is_supported_voltage(struct regulator *regulator,
return 0; return 0;
} }
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int ret;
unsigned int selector;
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
if (rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector);
if (rdev->desc->ops->list_voltage)
selector = rdev->desc->ops->list_voltage(rdev,
selector);
else
selector = -1;
} else if (rdev->desc->ops->set_voltage_sel) {
int best_val = INT_MAX;
int i;
selector = 0;
/* Find the smallest voltage that falls within the specified
* range.
*/
for (i = 0; i < rdev->desc->n_voltages; i++) {
ret = rdev->desc->ops->list_voltage(rdev, i);
if (ret < 0)
continue;
if (ret < best_val && ret >= min_uV && ret <= max_uV) {
best_val = ret;
selector = i;
}
}
if (best_val != INT_MAX) {
ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
selector = best_val;
} else {
ret = -EINVAL;
}
} else {
ret = -EINVAL;
}
if (ret == 0)
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
NULL);
trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
return ret;
}
/** /**
* regulator_set_voltage - set regulator output voltage * regulator_set_voltage - set regulator output voltage
* @regulator: regulator source * @regulator: regulator source
@ -1626,12 +1702,20 @@ int regulator_is_supported_voltage(struct regulator *regulator,
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
{ {
struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *rdev = regulator->rdev;
int ret; int ret = 0;
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
* voltage for multiple frequencies, for example).
*/
if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
goto out;
/* sanity check */ /* sanity check */
if (!rdev->desc->ops->set_voltage) { if (!rdev->desc->ops->set_voltage &&
!rdev->desc->ops->set_voltage_sel) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@ -1642,18 +1726,76 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
goto out; goto out;
regulator->min_uV = min_uV; regulator->min_uV = min_uV;
regulator->max_uV = max_uV; regulator->max_uV = max_uV;
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV);
ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
if (ret < 0)
goto out;
ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
out: out:
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
mutex_unlock(&rdev->mutex); mutex_unlock(&rdev->mutex);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(regulator_set_voltage); EXPORT_SYMBOL_GPL(regulator_set_voltage);
/**
* regulator_sync_voltage - re-apply last regulator output voltage
* @regulator: regulator source
*
* Re-apply the last configured voltage. This is intended to be used
* where some external control source the consumer is cooperating with
* has caused the configured voltage to change.
*/
int regulator_sync_voltage(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
int ret, min_uV, max_uV;
mutex_lock(&rdev->mutex);
if (!rdev->desc->ops->set_voltage &&
!rdev->desc->ops->set_voltage_sel) {
ret = -EINVAL;
goto out;
}
/* This is only going to work if we've had a voltage configured. */
if (!regulator->min_uV && !regulator->max_uV) {
ret = -EINVAL;
goto out;
}
min_uV = regulator->min_uV;
max_uV = regulator->max_uV;
/* This should be a paranoia check... */
ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
if (ret < 0)
goto out;
ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
if (ret < 0)
goto out;
ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
out:
mutex_unlock(&rdev->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_sync_voltage);
static int _regulator_get_voltage(struct regulator_dev *rdev) static int _regulator_get_voltage(struct regulator_dev *rdev)
{ {
/* sanity check */ int sel;
if (rdev->desc->ops->get_voltage_sel) {
sel = rdev->desc->ops->get_voltage_sel(rdev);
if (sel < 0)
return sel;
return rdev->desc->ops->list_voltage(rdev, sel);
}
if (rdev->desc->ops->get_voltage) if (rdev->desc->ops->get_voltage)
return rdev->desc->ops->get_voltage(rdev); return rdev->desc->ops->get_voltage(rdev);
else else
@ -1880,21 +2022,20 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
goto out; goto out;
/* get output voltage */ /* get output voltage */
output_uV = rdev->desc->ops->get_voltage(rdev); output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) { if (output_uV <= 0) {
printk(KERN_ERR "%s: invalid output voltage found for %s\n", rdev_err(rdev, "invalid output voltage found\n");
__func__, rdev_get_name(rdev));
goto out; goto out;
} }
/* get input voltage */ /* get input voltage */
if (rdev->supply && rdev->supply->desc->ops->get_voltage) input_uV = 0;
input_uV = rdev->supply->desc->ops->get_voltage(rdev->supply); if (rdev->supply)
else input_uV = _regulator_get_voltage(rdev->supply);
if (input_uV <= 0)
input_uV = rdev->constraints->input_uV; input_uV = rdev->constraints->input_uV;
if (input_uV <= 0) { if (input_uV <= 0) {
printk(KERN_ERR "%s: invalid input voltage found for %s\n", rdev_err(rdev, "invalid input voltage found\n");
__func__, rdev_get_name(rdev));
goto out; goto out;
} }
@ -1907,16 +2048,14 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
total_uA_load); total_uA_load);
ret = regulator_check_mode(rdev, mode); ret = regulator_check_mode(rdev, mode);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to get optimum mode for %s @" rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
" %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev), total_uA_load, input_uV, output_uV);
total_uA_load, input_uV, output_uV);
goto out; goto out;
} }
ret = rdev->desc->ops->set_mode(rdev, mode); ret = rdev->desc->ops->set_mode(rdev, mode);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n", rdev_err(rdev, "failed to set optimum mode %x\n", mode);
__func__, mode, rdev_get_name(rdev));
goto out; goto out;
} }
ret = mode; ret = mode;
@ -2047,7 +2186,7 @@ int regulator_bulk_enable(int num_consumers,
return 0; return 0;
err: err:
printk(KERN_ERR "Failed to enable %s: %d\n", consumers[i].supply, ret); pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
for (--i; i >= 0; --i) for (--i; i >= 0; --i)
regulator_disable(consumers[i].consumer); regulator_disable(consumers[i].consumer);
@ -2082,8 +2221,7 @@ int regulator_bulk_disable(int num_consumers,
return 0; return 0;
err: err:
printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply, pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
ret);
for (--i; i >= 0; --i) for (--i; i >= 0; --i)
regulator_enable(consumers[i].consumer); regulator_enable(consumers[i].consumer);
@ -2166,7 +2304,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
int status = 0; int status = 0;
/* some attributes need specific methods to be displayed */ /* some attributes need specific methods to be displayed */
if (ops->get_voltage) { if (ops->get_voltage || ops->get_voltage_sel) {
status = device_create_file(dev, &dev_attr_microvolts); status = device_create_file(dev, &dev_attr_microvolts);
if (status < 0) if (status < 0)
return status; return status;
@ -2207,7 +2345,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
return status; return status;
/* constraints need specific supporting methods */ /* constraints need specific supporting methods */
if (ops->set_voltage) { if (ops->set_voltage || ops->set_voltage_sel) {
status = device_create_file(dev, &dev_attr_min_microvolts); status = device_create_file(dev, &dev_attr_min_microvolts);
if (status < 0) if (status < 0)
return status; return status;
@ -2271,6 +2409,23 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
return status; return status;
} }
static void rdev_init_debugfs(struct regulator_dev *rdev)
{
#ifdef CONFIG_DEBUG_FS
rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
if (IS_ERR(rdev->debugfs) || !rdev->debugfs) {
rdev_warn(rdev, "Failed to create debugfs directory\n");
rdev->debugfs = NULL;
return;
}
debugfs_create_u32("use_count", 0444, rdev->debugfs,
&rdev->use_count);
debugfs_create_u32("open_count", 0444, rdev->debugfs,
&rdev->open_count);
#endif
}
/** /**
* regulator_register - register regulator * regulator_register - register regulator
* @regulator_desc: regulator to register * @regulator_desc: regulator to register
@ -2282,7 +2437,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
* Returns 0 on success. * Returns 0 on success.
*/ */
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
struct device *dev, struct regulator_init_data *init_data, struct device *dev, const struct regulator_init_data *init_data,
void *driver_data) void *driver_data)
{ {
static atomic_t regulator_no = ATOMIC_INIT(0); static atomic_t regulator_no = ATOMIC_INIT(0);
@ -2302,6 +2457,22 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
if (!init_data) if (!init_data)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
/* Only one of each should be implemented */
WARN_ON(regulator_desc->ops->get_voltage &&
regulator_desc->ops->get_voltage_sel);
WARN_ON(regulator_desc->ops->set_voltage &&
regulator_desc->ops->set_voltage_sel);
/* If we're using selectors we must implement list_voltage. */
if (regulator_desc->ops->get_voltage_sel &&
!regulator_desc->ops->list_voltage) {
return ERR_PTR(-EINVAL);
}
if (regulator_desc->ops->set_voltage_sel &&
!regulator_desc->ops->list_voltage) {
return ERR_PTR(-EINVAL);
}
rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
if (rdev == NULL) if (rdev == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -2399,6 +2570,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
} }
list_add(&rdev->list, &regulator_list); list_add(&rdev->list, &regulator_list);
rdev_init_debugfs(rdev);
out: out:
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
return rdev; return rdev;
@ -2431,12 +2604,16 @@ void regulator_unregister(struct regulator_dev *rdev)
return; return;
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
#ifdef CONFIG_DEBUG_FS
debugfs_remove_recursive(rdev->debugfs);
#endif
WARN_ON(rdev->open_count); WARN_ON(rdev->open_count);
unset_regulator_supplies(rdev); unset_regulator_supplies(rdev);
list_del(&rdev->list); list_del(&rdev->list);
if (rdev->supply) if (rdev->supply)
sysfs_remove_link(&rdev->dev.kobj, "supply"); sysfs_remove_link(&rdev->dev.kobj, "supply");
device_unregister(&rdev->dev); device_unregister(&rdev->dev);
kfree(rdev->constraints);
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
} }
EXPORT_SYMBOL_GPL(regulator_unregister); EXPORT_SYMBOL_GPL(regulator_unregister);
@ -2465,8 +2642,7 @@ int regulator_suspend_prepare(suspend_state_t state)
mutex_unlock(&rdev->mutex); mutex_unlock(&rdev->mutex);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to prepare %s\n", rdev_err(rdev, "failed to prepare\n");
__func__, rdev_get_name(rdev));
goto out; goto out;
} }
} }
@ -2572,10 +2748,16 @@ static int __init regulator_init(void)
{ {
int ret; int ret;
printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
ret = class_register(&regulator_class); ret = class_register(&regulator_class);
#ifdef CONFIG_DEBUG_FS
debugfs_root = debugfs_create_dir("regulator", NULL);
if (IS_ERR(debugfs_root) || !debugfs_root) {
pr_warn("regulator: Failed to create debugfs directory\n");
debugfs_root = NULL;
}
#endif
regulator_dummy_init(); regulator_dummy_init();
return ret; return ret;
@ -2590,7 +2772,6 @@ static int __init regulator_init_complete(void)
struct regulator_ops *ops; struct regulator_ops *ops;
struct regulation_constraints *c; struct regulation_constraints *c;
int enabled, ret; int enabled, ret;
const char *name;
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
@ -2602,8 +2783,6 @@ static int __init regulator_init_complete(void)
ops = rdev->desc->ops; ops = rdev->desc->ops;
c = rdev->constraints; c = rdev->constraints;
name = rdev_get_name(rdev);
if (!ops->disable || (c && c->always_on)) if (!ops->disable || (c && c->always_on))
continue; continue;
@ -2624,13 +2803,10 @@ static int __init regulator_init_complete(void)
if (has_full_constraints) { if (has_full_constraints) {
/* We log since this may kill the system if it /* We log since this may kill the system if it
* goes wrong. */ * goes wrong. */
printk(KERN_INFO "%s: disabling %s\n", rdev_info(rdev, "disabling\n");
__func__, name);
ret = ops->disable(rdev); ret = ops->disable(rdev);
if (ret != 0) { if (ret != 0) {
printk(KERN_ERR rdev_err(rdev, "couldn't disable: %d\n", ret);
"%s: couldn't disable %s: %d\n",
__func__, name, ret);
} }
} else { } else {
/* The intention is that in future we will /* The intention is that in future we will
@ -2638,9 +2814,7 @@ static int __init regulator_init_complete(void)
* so warn even if we aren't going to do * so warn even if we aren't going to do
* anything here. * anything here.
*/ */
printk(KERN_WARNING rdev_warn(rdev, "incomplete constraints, leaving on\n");
"%s: incomplete constraints, leaving %s on\n",
__func__, name);
} }
unlock: unlock:

View file

@ -107,7 +107,7 @@ static inline int check_range(struct da903x_regulator_info *info,
/* DA9030/DA9034 common operations */ /* DA9030/DA9034 common operations */
static int da903x_set_ldo_voltage(struct regulator_dev *rdev, static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev); struct device *da9034_dev = to_da903x_dev(rdev);
@ -119,6 +119,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
} }
val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = val;
val <<= info->vol_shift; val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
@ -187,7 +188,8 @@ static int da903x_list_voltage(struct regulator_dev *rdev, unsigned selector)
/* DA9030 specific operations */ /* DA9030 specific operations */
static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da903x_dev = to_da903x_dev(rdev); struct device *da903x_dev = to_da903x_dev(rdev);
@ -200,6 +202,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
} }
val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = val;
val <<= info->vol_shift; val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */ val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
@ -214,7 +217,8 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
} }
static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da903x_dev = to_da903x_dev(rdev); struct device *da903x_dev = to_da903x_dev(rdev);
@ -234,6 +238,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
val = (min_uV - thresh + info->step_uV - 1) / info->step_uV; val = (min_uV - thresh + info->step_uV - 1) / info->step_uV;
} }
*selector = val;
val <<= info->vol_shift; val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
@ -263,7 +268,7 @@ static int da9030_get_ldo14_voltage(struct regulator_dev *rdev)
/* DA9034 specific operations */ /* DA9034 specific operations */
static int da9034_set_dvc_voltage(struct regulator_dev *rdev, static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev); struct device *da9034_dev = to_da903x_dev(rdev);
@ -276,6 +281,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
} }
val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = val;
val <<= info->vol_shift; val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
@ -289,7 +295,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
} }
static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
struct device *da9034_dev = to_da903x_dev(rdev); struct device *da9034_dev = to_da903x_dev(rdev);
@ -302,6 +308,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val); val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val);
*selector = val;
val <<= info->vol_shift; val <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

View file

@ -58,7 +58,9 @@ out:
return data; return data;
} }
static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV) static int isl6271a_set_voltage(struct regulator_dev *dev,
int minuV, int maxuV,
unsigned *selector)
{ {
struct isl_pmic *pmic = rdev_get_drvdata(dev); struct isl_pmic *pmic = rdev_get_drvdata(dev);
int vsel, err, data; int vsel, err, data;
@ -78,6 +80,8 @@ static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV)
/* Convert the microvolts to data for the chip */ /* Convert the microvolts to data for the chip */
data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP; data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP;
*selector = data;
mutex_lock(&pmic->mtx); mutex_lock(&pmic->mtx);
err = i2c_smbus_write_byte(pmic->client, data); err = i2c_smbus_write_byte(pmic->client, data);
@ -169,7 +173,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
init_data, pmic); init_data, pmic);
if (IS_ERR(pmic->rdev[i])) { if (IS_ERR(pmic->rdev[i])) {
dev_err(&i2c->dev, "failed to register %s\n", id->name); dev_err(&i2c->dev, "failed to register %s\n", id->name);
err = PTR_ERR(pmic->rdev); err = PTR_ERR(pmic->rdev[i]);
goto error; goto error;
} }
} }

View file

@ -168,7 +168,8 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
} }
static int lp3971_ldo_set_voltage(struct regulator_dev *dev, static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned int *selector)
{ {
struct lp3971 *lp3971 = rdev_get_drvdata(dev); struct lp3971 *lp3971 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP3971_LDO1; int ldo = rdev_get_id(dev) - LP3971_LDO1;
@ -187,6 +188,8 @@ static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol) if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol)
return -EINVAL; return -EINVAL;
*selector = val;
return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo), return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
val << LDO_VOL_CONTR_SHIFT(ldo)); val << LDO_VOL_CONTR_SHIFT(ldo));
@ -256,7 +259,8 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
} }
static int lp3971_dcdc_set_voltage(struct regulator_dev *dev, static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned int *selector)
{ {
struct lp3971 *lp3971 = rdev_get_drvdata(dev); struct lp3971 *lp3971 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP3971_DCDC1; int buck = rdev_get_id(dev) - LP3971_DCDC1;
@ -277,6 +281,8 @@ static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol) if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol)
return -EINVAL; return -EINVAL;
*selector = val;
ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
BUCK_TARGET_VOL_MASK, val); BUCK_TARGET_VOL_MASK, val);
if (ret) if (ret)

View file

@ -292,7 +292,8 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev)
} }
static int lp3972_ldo_set_voltage(struct regulator_dev *dev, static int lp3972_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned int *selector)
{ {
struct lp3972 *lp3972 = rdev_get_drvdata(dev); struct lp3972 *lp3972 = rdev_get_drvdata(dev);
int ldo = rdev_get_id(dev) - LP3972_LDO1; int ldo = rdev_get_id(dev) - LP3972_LDO1;
@ -313,6 +314,8 @@ static int lp3972_ldo_set_voltage(struct regulator_dev *dev,
if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol) if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol)
return -EINVAL; return -EINVAL;
*selector = val;
shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo); shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo);
ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo), ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo),
LP3972_LDO_VOL_MASK(ldo) << shift, val << shift); LP3972_LDO_VOL_MASK(ldo) << shift, val << shift);
@ -416,7 +419,8 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev)
} }
static int lp3972_dcdc_set_voltage(struct regulator_dev *dev, static int lp3972_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned int *selector)
{ {
struct lp3972 *lp3972 = rdev_get_drvdata(dev); struct lp3972 *lp3972 = rdev_get_drvdata(dev);
int buck = rdev_get_id(dev) - LP3972_DCDC1; int buck = rdev_get_id(dev) - LP3972_DCDC1;
@ -438,6 +442,8 @@ static int lp3972_dcdc_set_voltage(struct regulator_dev *dev,
vol_map[val] > max_vol) vol_map[val] > max_vol)
return -EINVAL; return -EINVAL;
*selector = val;
ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck), ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck),
LP3972_BUCK_VOL_MASK, val); LP3972_BUCK_VOL_MASK, val);
if (ret) if (ret)

View file

@ -63,12 +63,12 @@ static int max1586_v3_calc_voltage(struct max1586_data *max1586,
return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL); return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL);
} }
static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV) static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned *selector)
{ {
struct max1586_data *max1586 = rdev_get_drvdata(rdev); struct max1586_data *max1586 = rdev_get_drvdata(rdev);
struct i2c_client *client = max1586->client; struct i2c_client *client = max1586->client;
unsigned range_uV = max1586->max_uV - max1586->min_uV; unsigned range_uV = max1586->max_uV - max1586->min_uV;
unsigned selector;
u8 v3_prog; u8 v3_prog;
if (min_uV > max1586->max_uV || max_uV < max1586->min_uV) if (min_uV > max1586->max_uV || max_uV < max1586->min_uV)
@ -76,15 +76,15 @@ static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV)
if (min_uV < max1586->min_uV) if (min_uV < max1586->min_uV)
min_uV = max1586->min_uV; min_uV = max1586->min_uV;
selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL + *selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL +
range_uV - 1) / range_uV; range_uV - 1) / range_uV;
if (max1586_v3_calc_voltage(max1586, selector) > max_uV) if (max1586_v3_calc_voltage(max1586, *selector) > max_uV)
return -EINVAL; return -EINVAL;
dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
max1586_v3_calc_voltage(max1586, selector) / 1000); max1586_v3_calc_voltage(max1586, *selector) / 1000);
v3_prog = I2C_V3_SELECT | (u8) selector; v3_prog = I2C_V3_SELECT | (u8) *selector;
return i2c_smbus_write_byte(client, v3_prog); return i2c_smbus_write_byte(client, v3_prog);
} }
@ -110,10 +110,10 @@ static int max1586_v6_calc_voltage(unsigned selector)
return voltages_uv[selector]; return voltages_uv[selector];
} }
static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *selector)
{ {
struct i2c_client *client = rdev_get_drvdata(rdev); struct i2c_client *client = rdev_get_drvdata(rdev);
unsigned selector;
u8 v6_prog; u8 v6_prog;
if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV) if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV)
@ -122,21 +122,21 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV)
return -EINVAL; return -EINVAL;
if (min_uV < 1800000) if (min_uV < 1800000)
selector = 0; *selector = 0;
else if (min_uV < 2500000) else if (min_uV < 2500000)
selector = 1; *selector = 1;
else if (min_uV < 3000000) else if (min_uV < 3000000)
selector = 2; *selector = 2;
else if (min_uV >= 3000000) else if (min_uV >= 3000000)
selector = 3; *selector = 3;
if (max1586_v6_calc_voltage(selector) > max_uV) if (max1586_v6_calc_voltage(*selector) > max_uV)
return -EINVAL; return -EINVAL;
dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
max1586_v6_calc_voltage(selector) / 1000); max1586_v6_calc_voltage(*selector) / 1000);
v6_prog = I2C_V6_SELECT | (u8) selector; v6_prog = I2C_V6_SELECT | (u8) *selector;
return i2c_smbus_write_byte(client, v6_prog); return i2c_smbus_write_byte(client, v6_prog);
} }

View file

@ -155,7 +155,7 @@ static int max8649_get_voltage(struct regulator_dev *rdev)
} }
static int max8649_set_voltage(struct regulator_dev *rdev, static int max8649_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct max8649_regulator_info *info = rdev_get_drvdata(rdev); struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
unsigned char data, mask; unsigned char data, mask;
@ -168,6 +168,7 @@ static int max8649_set_voltage(struct regulator_dev *rdev,
data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1) data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1)
/ MAX8649_DCDC_STEP; / MAX8649_DCDC_STEP;
mask = MAX8649_VOL_MASK; mask = MAX8649_VOL_MASK;
*selector = data & mask;
return max8649_set_bits(info->i2c, info->vol_reg, mask, data); return max8649_set_bits(info->i2c, info->vol_reg, mask, data);
} }

View file

@ -141,7 +141,8 @@ static int max8660_dcdc_get(struct regulator_dev *rdev)
return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
} }
static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV) static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *s)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 reg, selector, bits; u8 reg, selector, bits;
@ -154,6 +155,7 @@ static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV)
selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1)) selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1))
/ MAX8660_DCDC_STEP; / MAX8660_DCDC_STEP;
*s = selector;
ret = max8660_dcdc_list(rdev, selector); ret = max8660_dcdc_list(rdev, selector);
if (ret < 0 || ret > max_uV) if (ret < 0 || ret > max_uV)
@ -196,7 +198,8 @@ static int max8660_ldo5_get(struct regulator_dev *rdev)
return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
} }
static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV) static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *s)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 selector; u8 selector;
@ -213,6 +216,8 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV)
if (ret < 0 || ret > max_uV) if (ret < 0 || ret > max_uV)
return -EINVAL; return -EINVAL;
*s = selector;
ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector); ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);
if (ret) if (ret)
return ret; return ret;
@ -270,7 +275,8 @@ static int max8660_ldo67_get(struct regulator_dev *rdev)
return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
} }
static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV) static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV,
int max_uV, unsigned int *s)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 selector; u8 selector;
@ -288,6 +294,8 @@ static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV)
if (ret < 0 || ret > max_uV) if (ret < 0 || ret > max_uV)
return -EINVAL; return -EINVAL;
*s = selector;
if (rdev_get_id(rdev) == MAX8660_V6) if (rdev_get_id(rdev) == MAX8660_V6)
return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector); return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);
else else

View file

@ -55,7 +55,7 @@ static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index)
} }
static int max8925_set_voltage(struct regulator_dev *rdev, static int max8925_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned int *selector)
{ {
struct max8925_regulator_info *info = rdev_get_drvdata(rdev); struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
unsigned char data, mask; unsigned char data, mask;
@ -66,6 +66,7 @@ static int max8925_set_voltage(struct regulator_dev *rdev,
return -EINVAL; return -EINVAL;
} }
data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
*selector = data;
data <<= info->vol_shift; data <<= info->vol_shift;
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;

View file

@ -133,7 +133,7 @@ static int max8952_get_voltage(struct regulator_dev *rdev)
} }
static int max8952_set_voltage(struct regulator_dev *rdev, static int max8952_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct max8952_data *max8952 = rdev_get_drvdata(rdev); struct max8952_data *max8952 = rdev_get_drvdata(rdev);
s8 vid = -1, i; s8 vid = -1, i;
@ -156,6 +156,7 @@ static int max8952_set_voltage(struct regulator_dev *rdev,
if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) { if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) {
max8952->vid0 = (vid % 2 == 1); max8952->vid0 = (vid % 2 == 1);
max8952->vid1 = (((vid >> 1) % 2) == 1); max8952->vid1 = (((vid >> 1) % 2) == 1);
*selector = vid;
gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0);
gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1);
} else } else

View file

@ -304,7 +304,7 @@ static int max8998_get_voltage(struct regulator_dev *rdev)
} }
static int max8998_set_voltage_ldo(struct regulator_dev *rdev, static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct max8998_data *max8998 = rdev_get_drvdata(rdev); struct max8998_data *max8998 = rdev_get_drvdata(rdev);
struct i2c_client *i2c = max8998->iodev->i2c; struct i2c_client *i2c = max8998->iodev->i2c;
@ -331,6 +331,8 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
if (desc->min + desc->step*i > max_vol) if (desc->min + desc->step*i > max_vol)
return -EINVAL; return -EINVAL;
*selector = i;
ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask); ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
if (ret) if (ret)
return ret; return ret;
@ -352,7 +354,7 @@ static inline void buck2_gpio_set(int gpio, int v)
} }
static int max8998_set_voltage_buck(struct regulator_dev *rdev, static int max8998_set_voltage_buck(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct max8998_data *max8998 = rdev_get_drvdata(rdev); struct max8998_data *max8998 = rdev_get_drvdata(rdev);
struct max8998_platform_data *pdata = struct max8998_platform_data *pdata =
@ -384,6 +386,8 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
if (desc->min + desc->step*i > max_vol) if (desc->min + desc->step*i > max_vol)
return -EINVAL; return -EINVAL;
*selector = i;
ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask); ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
if (ret) if (ret)
return ret; return ret;

View file

@ -1,6 +1,7 @@
/* /*
* Regulator Driver for Freescale MC13783 PMIC * Regulator Driver for Freescale MC13783 PMIC
* *
* Copyright 2010 Yong Shen <yong.shen@linaro.org>
* Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
* Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
* *
@ -17,6 +18,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include "mc13xxx.h"
#define MC13783_REG_SWITCHERS5 29 #define MC13783_REG_SWITCHERS5 29
#define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20)
@ -89,154 +91,106 @@
#define MC13783_REG_POWERMISC_PWGTSPI_M (3 << 15) #define MC13783_REG_POWERMISC_PWGTSPI_M (3 << 15)
struct mc13783_regulator {
struct regulator_desc desc;
int reg;
int enable_bit;
int vsel_reg;
int vsel_shift;
int vsel_mask;
int const *voltages;
};
/* Voltage Values */ /* Voltage Values */
static const int const mc13783_sw3_val[] = { static const int mc13783_sw3_val[] = {
5000000, 5000000, 5000000, 5500000, 5000000, 5000000, 5000000, 5500000,
}; };
static const int const mc13783_vaudio_val[] = { static const int mc13783_vaudio_val[] = {
2775000, 2775000,
}; };
static const int const mc13783_viohi_val[] = { static const int mc13783_viohi_val[] = {
2775000, 2775000,
}; };
static const int const mc13783_violo_val[] = { static const int mc13783_violo_val[] = {
1200000, 1300000, 1500000, 1800000, 1200000, 1300000, 1500000, 1800000,
}; };
static const int const mc13783_vdig_val[] = { static const int mc13783_vdig_val[] = {
1200000, 1300000, 1500000, 1800000, 1200000, 1300000, 1500000, 1800000,
}; };
static const int const mc13783_vgen_val[] = { static const int mc13783_vgen_val[] = {
1200000, 1300000, 1500000, 1800000, 1200000, 1300000, 1500000, 1800000,
1100000, 2000000, 2775000, 2400000, 1100000, 2000000, 2775000, 2400000,
}; };
static const int const mc13783_vrfdig_val[] = { static const int mc13783_vrfdig_val[] = {
1200000, 1500000, 1800000, 1875000, 1200000, 1500000, 1800000, 1875000,
}; };
static const int const mc13783_vrfref_val[] = { static const int mc13783_vrfref_val[] = {
2475000, 2600000, 2700000, 2775000, 2475000, 2600000, 2700000, 2775000,
}; };
static const int const mc13783_vrfcp_val[] = { static const int mc13783_vrfcp_val[] = {
2700000, 2775000, 2700000, 2775000,
}; };
static const int const mc13783_vsim_val[] = { static const int mc13783_vsim_val[] = {
1800000, 2900000, 3000000, 1800000, 2900000, 3000000,
}; };
static const int const mc13783_vesim_val[] = { static const int mc13783_vesim_val[] = {
1800000, 2900000, 1800000, 2900000,
}; };
static const int const mc13783_vcam_val[] = { static const int mc13783_vcam_val[] = {
1500000, 1800000, 2500000, 2550000, 1500000, 1800000, 2500000, 2550000,
2600000, 2750000, 2800000, 3000000, 2600000, 2750000, 2800000, 3000000,
}; };
static const int const mc13783_vrfbg_val[] = { static const int mc13783_vrfbg_val[] = {
1250000, 1250000,
}; };
static const int const mc13783_vvib_val[] = { static const int mc13783_vvib_val[] = {
1300000, 1800000, 2000000, 3000000, 1300000, 1800000, 2000000, 3000000,
}; };
static const int const mc13783_vmmc_val[] = { static const int mc13783_vmmc_val[] = {
1600000, 1800000, 2000000, 2600000, 1600000, 1800000, 2000000, 2600000,
2700000, 2800000, 2900000, 3000000, 2700000, 2800000, 2900000, 3000000,
}; };
static const int const mc13783_vrf_val[] = { static const int mc13783_vrf_val[] = {
1500000, 1875000, 2700000, 2775000, 1500000, 1875000, 2700000, 2775000,
}; };
static const int const mc13783_gpo_val[] = { static const int mc13783_gpo_val[] = {
3100000, 3100000,
}; };
static const int const mc13783_pwgtdrv_val[] = { static const int mc13783_pwgtdrv_val[] = {
5500000, 5500000,
}; };
static struct regulator_ops mc13783_regulator_ops;
static struct regulator_ops mc13783_fixed_regulator_ops;
static struct regulator_ops mc13783_gpo_regulator_ops; static struct regulator_ops mc13783_gpo_regulator_ops;
#define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages) \ #define MC13783_DEFINE(prefix, name, reg, vsel_reg, voltages) \
[MC13783_ ## prefix ## _ ## _name] = { \ MC13xxx_DEFINE(MC13783_REG_, name, reg, vsel_reg, voltages, \
.desc = { \ mc13xxx_regulator_ops)
.name = #prefix "_" #_name, \
.n_voltages = ARRAY_SIZE(_voltages), \
.ops = &mc13783_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MC13783_ ## prefix ## _ ## _name, \
.owner = THIS_MODULE, \
}, \
.reg = MC13783_REG_ ## _reg, \
.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
.vsel_reg = MC13783_REG_ ## _vsel_reg, \
.vsel_shift = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL,\
.vsel_mask = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL_M,\
.voltages = _voltages, \
}
#define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages) \ #define MC13783_FIXED_DEFINE(prefix, name, reg, voltages) \
[MC13783_ ## prefix ## _ ## _name] = { \ MC13xxx_FIXED_DEFINE(MC13783_REG_, name, reg, voltages, \
.desc = { \ mc13xxx_fixed_regulator_ops)
.name = #prefix "_" #_name, \
.n_voltages = ARRAY_SIZE(_voltages), \
.ops = &mc13783_fixed_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MC13783_ ## prefix ## _ ## _name, \
.owner = THIS_MODULE, \
}, \
.reg = MC13783_REG_ ## _reg, \
.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
.voltages = _voltages, \
}
#define MC13783_GPO_DEFINE(prefix, _name, _reg, _voltages) \ #define MC13783_GPO_DEFINE(prefix, name, reg, voltages) \
[MC13783_ ## prefix ## _ ## _name] = { \ MC13xxx_GPO_DEFINE(MC13783_REG_, name, reg, voltages, \
.desc = { \ mc13783_gpo_regulator_ops)
.name = #prefix "_" #_name, \
.n_voltages = ARRAY_SIZE(_voltages), \
.ops = &mc13783_gpo_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MC13783_ ## prefix ## _ ## _name, \
.owner = THIS_MODULE, \
}, \
.reg = MC13783_REG_ ## _reg, \
.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
.voltages = _voltages, \
}
#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \ #define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \
MC13783_DEFINE(SW, _name, _reg, _vsel_reg, _voltages) MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \ #define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \
MC13783_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages) MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
static struct mc13783_regulator mc13783_regulators[] = { static struct mc13xxx_regulator mc13783_regulators[] = {
MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
MC13783_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val), MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \ MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \
mc13783_violo_val), mc13783_violo_val),
MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \
@ -255,7 +209,7 @@ static struct mc13783_regulator mc13783_regulators[] = {
mc13783_vesim_val), mc13783_vesim_val),
MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \
mc13783_vcam_val), mc13783_vcam_val),
MC13783_FIXED_DEFINE(REGU, VRFBG, REGULATORMODE1, mc13783_vrfbg_val), MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \ MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \
mc13783_vvib_val), mc13783_vvib_val),
MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \ MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \
@ -266,215 +220,24 @@ static struct mc13783_regulator mc13783_regulators[] = {
mc13783_vmmc_val), mc13783_vmmc_val),
MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \ MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \
mc13783_vmmc_val), mc13783_vmmc_val),
MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC, mc13783_gpo_val), MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC, mc13783_gpo_val), MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC, mc13783_gpo_val), MC13783_GPO_DEFINE(REG, GPO3, POWERMISC, mc13783_gpo_val),
MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC, mc13783_gpo_val), MC13783_GPO_DEFINE(REG, GPO4, POWERMISC, mc13783_gpo_val),
MC13783_GPO_DEFINE(REGU, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val), MC13783_GPO_DEFINE(REG, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
MC13783_GPO_DEFINE(REGU, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val), MC13783_GPO_DEFINE(REG, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
}; };
struct mc13783_regulator_priv { static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
struct mc13783 *mc13783; u32 val)
u32 powermisc_pwgt_state;
struct regulator_dev *regulators[];
};
static int mc13783_regulator_enable(struct regulator_dev *rdev)
{ {
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx *mc13783 = priv->mc13xxx;
int id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13783_lock(priv->mc13783);
ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg,
mc13783_regulators[id].enable_bit,
mc13783_regulators[id].enable_bit);
mc13783_unlock(priv->mc13783);
return ret;
}
static int mc13783_regulator_disable(struct regulator_dev *rdev)
{
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13783_lock(priv->mc13783);
ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg,
mc13783_regulators[id].enable_bit, 0);
mc13783_unlock(priv->mc13783);
return ret;
}
static int mc13783_regulator_is_enabled(struct regulator_dev *rdev)
{
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val;
mc13783_lock(priv->mc13783);
ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
mc13783_unlock(priv->mc13783);
if (ret)
return ret;
return (val & mc13783_regulators[id].enable_bit) != 0;
}
static int mc13783_regulator_list_voltage(struct regulator_dev *rdev,
unsigned selector)
{
int id = rdev_get_id(rdev);
if (selector >= mc13783_regulators[id].desc.n_voltages)
return -EINVAL;
return mc13783_regulators[id].voltages[selector];
}
static int mc13783_get_best_voltage_index(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int reg_id = rdev_get_id(rdev);
int i;
int bestmatch;
int bestindex;
/*
* Locate the minimum voltage fitting the criteria on
* this regulator. The switchable voltages are not
* in strict falling order so we need to check them
* all for the best match.
*/
bestmatch = INT_MAX;
bestindex = -1;
for (i = 0; i < mc13783_regulators[reg_id].desc.n_voltages; i++) {
if (mc13783_regulators[reg_id].voltages[i] >= min_uV &&
mc13783_regulators[reg_id].voltages[i] < bestmatch) {
bestmatch = mc13783_regulators[reg_id].voltages[i];
bestindex = i;
}
}
if (bestindex < 0 || bestmatch > max_uV) {
dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n",
min_uV, max_uV);
return -EINVAL;
}
return bestindex;
}
static int mc13783_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
int value, id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
__func__, id, min_uV, max_uV);
/* Find the best index */
value = mc13783_get_best_voltage_index(rdev, min_uV, max_uV);
dev_dbg(rdev_get_dev(rdev), "%s best value: %d \n", __func__, value);
if (value < 0)
return value;
mc13783_lock(priv->mc13783);
ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].vsel_reg,
mc13783_regulators[id].vsel_mask,
value << mc13783_regulators[id].vsel_shift);
mc13783_unlock(priv->mc13783);
return ret;
}
static int mc13783_regulator_get_voltage(struct regulator_dev *rdev)
{
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13783_lock(priv->mc13783);
ret = mc13783_reg_read(priv->mc13783,
mc13783_regulators[id].vsel_reg, &val);
mc13783_unlock(priv->mc13783);
if (ret)
return ret;
val = (val & mc13783_regulators[id].vsel_mask)
>> mc13783_regulators[id].vsel_shift;
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
BUG_ON(val < 0 || val > mc13783_regulators[id].desc.n_voltages);
return mc13783_regulators[id].voltages[val];
}
static struct regulator_ops mc13783_regulator_ops = {
.enable = mc13783_regulator_enable,
.disable = mc13783_regulator_disable,
.is_enabled = mc13783_regulator_is_enabled,
.list_voltage = mc13783_regulator_list_voltage,
.set_voltage = mc13783_regulator_set_voltage,
.get_voltage = mc13783_regulator_get_voltage,
};
static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int id = rdev_get_id(rdev);
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
__func__, id, min_uV, max_uV);
if (min_uV >= mc13783_regulators[id].voltages[0] &&
max_uV <= mc13783_regulators[id].voltages[0])
return 0;
else
return -EINVAL;
}
static int mc13783_fixed_regulator_get_voltage(struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
return mc13783_regulators[id].voltages[0];
}
static struct regulator_ops mc13783_fixed_regulator_ops = {
.enable = mc13783_regulator_enable,
.disable = mc13783_regulator_disable,
.is_enabled = mc13783_regulator_is_enabled,
.list_voltage = mc13783_regulator_list_voltage,
.set_voltage = mc13783_fixed_regulator_set_voltage,
.get_voltage = mc13783_fixed_regulator_get_voltage,
};
static int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask,
u32 val)
{
struct mc13783 *mc13783 = priv->mc13783;
int ret; int ret;
u32 valread; u32 valread;
BUG_ON(val & ~mask); BUG_ON(val & ~mask);
ret = mc13783_reg_read(mc13783, MC13783_REG_POWERMISC, &valread); ret = mc13xxx_reg_read(mc13783, MC13783_REG_POWERMISC, &valread);
if (ret) if (ret)
return ret; return ret;
@ -489,34 +252,36 @@ static int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask,
valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) | valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
priv->powermisc_pwgt_state; priv->powermisc_pwgt_state;
return mc13783_reg_write(mc13783, MC13783_REG_POWERMISC, valread); return mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread);
} }
static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev)
{ {
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
int ret; int ret;
u32 en_val = mc13783_regulators[id].enable_bit; u32 en_val = mc13xxx_regulators[id].enable_bit;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
/* Power Gate enable value is 0 */ /* Power Gate enable value is 0 */
if (id == MC13783_REGU_PWGT1SPI || if (id == MC13783_REG_PWGT1SPI ||
id == MC13783_REGU_PWGT2SPI) id == MC13783_REG_PWGT2SPI)
en_val = 0; en_val = 0;
mc13783_lock(priv->mc13783); mc13xxx_lock(priv->mc13xxx);
ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit, ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
en_val); en_val);
mc13783_unlock(priv->mc13783); mc13xxx_unlock(priv->mc13xxx);
return ret; return ret;
} }
static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev)
{ {
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
int ret; int ret;
u32 dis_val = 0; u32 dis_val = 0;
@ -524,27 +289,28 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev)
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
/* Power Gate disable value is 1 */ /* Power Gate disable value is 1 */
if (id == MC13783_REGU_PWGT1SPI || if (id == MC13783_REG_PWGT1SPI ||
id == MC13783_REGU_PWGT2SPI) id == MC13783_REG_PWGT2SPI)
dis_val = mc13783_regulators[id].enable_bit; dis_val = mc13xxx_regulators[id].enable_bit;
mc13783_lock(priv->mc13783); mc13xxx_lock(priv->mc13xxx);
ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit, ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
dis_val); dis_val);
mc13783_unlock(priv->mc13783); mc13xxx_unlock(priv->mc13xxx);
return ret; return ret;
} }
static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
{ {
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int ret, id = rdev_get_id(rdev); int ret, id = rdev_get_id(rdev);
unsigned int val; unsigned int val;
mc13783_lock(priv->mc13783); mc13xxx_lock(priv->mc13xxx);
ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
mc13783_unlock(priv->mc13783); mc13xxx_unlock(priv->mc13xxx);
if (ret) if (ret)
return ret; return ret;
@ -554,22 +320,22 @@ static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) | val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
(priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M); (priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M);
return (val & mc13783_regulators[id].enable_bit) != 0; return (val & mc13xxx_regulators[id].enable_bit) != 0;
} }
static struct regulator_ops mc13783_gpo_regulator_ops = { static struct regulator_ops mc13783_gpo_regulator_ops = {
.enable = mc13783_gpo_regulator_enable, .enable = mc13783_gpo_regulator_enable,
.disable = mc13783_gpo_regulator_disable, .disable = mc13783_gpo_regulator_disable,
.is_enabled = mc13783_gpo_regulator_is_enabled, .is_enabled = mc13783_gpo_regulator_is_enabled,
.list_voltage = mc13783_regulator_list_voltage, .list_voltage = mc13xxx_regulator_list_voltage,
.set_voltage = mc13783_fixed_regulator_set_voltage, .set_voltage = mc13xxx_fixed_regulator_set_voltage,
.get_voltage = mc13783_fixed_regulator_get_voltage, .get_voltage = mc13xxx_fixed_regulator_get_voltage,
}; };
static int __devinit mc13783_regulator_probe(struct platform_device *pdev) static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
{ {
struct mc13783_regulator_priv *priv; struct mc13xxx_regulator_priv *priv;
struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent); struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
struct mc13783_regulator_platform_data *pdata = struct mc13783_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev); dev_get_platdata(&pdev->dev);
struct mc13783_regulator_init_data *init_data; struct mc13783_regulator_init_data *init_data;
@ -583,7 +349,8 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->mc13783 = mc13783; priv->mc13xxx_regulators = mc13783_regulators;
priv->mc13xxx = mc13783;
for (i = 0; i < pdata->num_regulators; i++) { for (i = 0; i < pdata->num_regulators; i++) {
init_data = &pdata->regulators[i]; init_data = &pdata->regulators[i];
@ -613,7 +380,7 @@ err:
static int __devexit mc13783_regulator_remove(struct platform_device *pdev) static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
{ {
struct mc13783_regulator_priv *priv = platform_get_drvdata(pdev); struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13783_regulator_platform_data *pdata = struct mc13783_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev); dev_get_platdata(&pdev->dev);
int i; int i;

View file

@ -0,0 +1,635 @@
/*
* Regulator Driver for Freescale MC13892 PMIC
*
* Copyright 2010 Yong Shen <yong.shen@linaro.org>
*
* Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/mfd/mc13892.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
#include "mc13xxx.h"
#define MC13892_REVISION 7
#define MC13892_POWERCTL0 13
#define MC13892_POWERCTL0_USEROFFSPI 3
#define MC13892_POWERCTL0_VCOINCELLVSEL 20
#define MC13892_POWERCTL0_VCOINCELLVSEL_M (7<<20)
#define MC13892_POWERCTL0_VCOINCELLEN (1<<23)
#define MC13892_SWITCHERS0_SWxHI (1<<23)
#define MC13892_SWITCHERS0 24
#define MC13892_SWITCHERS0_SW1VSEL 0
#define MC13892_SWITCHERS0_SW1VSEL_M (0x1f<<0)
#define MC13892_SWITCHERS0_SW1HI (1<<23)
#define MC13892_SWITCHERS0_SW1EN 0
#define MC13892_SWITCHERS1 25
#define MC13892_SWITCHERS1_SW2VSEL 0
#define MC13892_SWITCHERS1_SW2VSEL_M (0x1f<<0)
#define MC13892_SWITCHERS1_SW2HI (1<<23)
#define MC13892_SWITCHERS1_SW2EN 0
#define MC13892_SWITCHERS2 26
#define MC13892_SWITCHERS2_SW3VSEL 0
#define MC13892_SWITCHERS2_SW3VSEL_M (0x1f<<0)
#define MC13892_SWITCHERS2_SW3HI (1<<23)
#define MC13892_SWITCHERS2_SW3EN 0
#define MC13892_SWITCHERS3 27
#define MC13892_SWITCHERS3_SW4VSEL 0
#define MC13892_SWITCHERS3_SW4VSEL_M (0x1f<<0)
#define MC13892_SWITCHERS3_SW4HI (1<<23)
#define MC13892_SWITCHERS3_SW4EN 0
#define MC13892_SWITCHERS4 28
#define MC13892_SWITCHERS4_SW1MODE 0
#define MC13892_SWITCHERS4_SW1MODE_AUTO (8<<0)
#define MC13892_SWITCHERS4_SW1MODE_M (0xf<<0)
#define MC13892_SWITCHERS4_SW2MODE 10
#define MC13892_SWITCHERS4_SW2MODE_AUTO (8<<10)
#define MC13892_SWITCHERS4_SW2MODE_M (0xf<<10)
#define MC13892_SWITCHERS5 29
#define MC13892_SWITCHERS5_SW3MODE 0
#define MC13892_SWITCHERS5_SW3MODE_AUTO (8<<0)
#define MC13892_SWITCHERS5_SW3MODE_M (0xf<<0)
#define MC13892_SWITCHERS5_SW4MODE 8
#define MC13892_SWITCHERS5_SW4MODE_AUTO (8<<8)
#define MC13892_SWITCHERS5_SW4MODE_M (0xf<<8)
#define MC13892_SWITCHERS5_SWBSTEN (1<<20)
#define MC13892_REGULATORSETTING0 30
#define MC13892_REGULATORSETTING0_VGEN1VSEL 0
#define MC13892_REGULATORSETTING0_VDIGVSEL 4
#define MC13892_REGULATORSETTING0_VGEN2VSEL 6
#define MC13892_REGULATORSETTING0_VPLLVSEL 9
#define MC13892_REGULATORSETTING0_VUSB2VSEL 11
#define MC13892_REGULATORSETTING0_VGEN3VSEL 14
#define MC13892_REGULATORSETTING0_VCAMVSEL 16
#define MC13892_REGULATORSETTING0_VGEN1VSEL_M (3<<0)
#define MC13892_REGULATORSETTING0_VDIGVSEL_M (3<<4)
#define MC13892_REGULATORSETTING0_VGEN2VSEL_M (7<<6)
#define MC13892_REGULATORSETTING0_VPLLVSEL_M (3<<9)
#define MC13892_REGULATORSETTING0_VUSB2VSEL_M (3<<11)
#define MC13892_REGULATORSETTING0_VGEN3VSEL_M (1<<14)
#define MC13892_REGULATORSETTING0_VCAMVSEL_M (3<<16)
#define MC13892_REGULATORSETTING1 31
#define MC13892_REGULATORSETTING1_VVIDEOVSEL 2
#define MC13892_REGULATORSETTING1_VAUDIOVSEL 4
#define MC13892_REGULATORSETTING1_VSDVSEL 6
#define MC13892_REGULATORSETTING1_VVIDEOVSEL_M (3<<2)
#define MC13892_REGULATORSETTING1_VAUDIOVSEL_M (3<<4)
#define MC13892_REGULATORSETTING1_VSDVSEL_M (7<<6)
#define MC13892_REGULATORMODE0 32
#define MC13892_REGULATORMODE0_VGEN1EN (1<<0)
#define MC13892_REGULATORMODE0_VGEN1STDBY (1<<1)
#define MC13892_REGULATORMODE0_VGEN1MODE (1<<2)
#define MC13892_REGULATORMODE0_VIOHIEN (1<<3)
#define MC13892_REGULATORMODE0_VIOHISTDBY (1<<4)
#define MC13892_REGULATORMODE0_VIOHIMODE (1<<5)
#define MC13892_REGULATORMODE0_VDIGEN (1<<9)
#define MC13892_REGULATORMODE0_VDIGSTDBY (1<<10)
#define MC13892_REGULATORMODE0_VDIGMODE (1<<11)
#define MC13892_REGULATORMODE0_VGEN2EN (1<<12)
#define MC13892_REGULATORMODE0_VGEN2STDBY (1<<13)
#define MC13892_REGULATORMODE0_VGEN2MODE (1<<14)
#define MC13892_REGULATORMODE0_VPLLEN (1<<15)
#define MC13892_REGULATORMODE0_VPLLSTDBY (1<<16)
#define MC13892_REGULATORMODE0_VPLLMODE (1<<17)
#define MC13892_REGULATORMODE0_VUSB2EN (1<<18)
#define MC13892_REGULATORMODE0_VUSB2STDBY (1<<19)
#define MC13892_REGULATORMODE0_VUSB2MODE (1<<20)
#define MC13892_REGULATORMODE1 33
#define MC13892_REGULATORMODE1_VGEN3EN (1<<0)
#define MC13892_REGULATORMODE1_VGEN3STDBY (1<<1)
#define MC13892_REGULATORMODE1_VGEN3MODE (1<<2)
#define MC13892_REGULATORMODE1_VCAMEN (1<<6)
#define MC13892_REGULATORMODE1_VCAMSTDBY (1<<7)
#define MC13892_REGULATORMODE1_VCAMMODE (1<<8)
#define MC13892_REGULATORMODE1_VCAMCONFIGEN (1<<9)
#define MC13892_REGULATORMODE1_VVIDEOEN (1<<12)
#define MC13892_REGULATORMODE1_VVIDEOSTDBY (1<<13)
#define MC13892_REGULATORMODE1_VVIDEOMODE (1<<14)
#define MC13892_REGULATORMODE1_VAUDIOEN (1<<15)
#define MC13892_REGULATORMODE1_VAUDIOSTDBY (1<<16)
#define MC13892_REGULATORMODE1_VAUDIOMODE (1<<17)
#define MC13892_REGULATORMODE1_VSDEN (1<<18)
#define MC13892_REGULATORMODE1_VSDSTDBY (1<<19)
#define MC13892_REGULATORMODE1_VSDMODE (1<<20)
#define MC13892_POWERMISC 34
#define MC13892_POWERMISC_GPO1EN (1<<6)
#define MC13892_POWERMISC_GPO2EN (1<<8)
#define MC13892_POWERMISC_GPO3EN (1<<10)
#define MC13892_POWERMISC_GPO4EN (1<<12)
#define MC13892_POWERMISC_PWGT1SPIEN (1<<15)
#define MC13892_POWERMISC_PWGT2SPIEN (1<<16)
#define MC13892_POWERMISC_GPO4ADINEN (1<<21)
#define MC13892_POWERMISC_PWGTSPI_M (3 << 15)
#define MC13892_USB1 50
#define MC13892_USB1_VUSBEN (1<<3)
static const int mc13892_vcoincell[] = {
2500000, 2700000, 2800000, 2900000, 3000000, 3100000,
3200000, 3300000,
};
static const int mc13892_sw1[] = {
600000, 625000, 650000, 675000, 700000, 725000,
750000, 775000, 800000, 825000, 850000, 875000,
900000, 925000, 950000, 975000, 1000000, 1025000,
1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
1200000, 1225000, 1250000, 1275000, 1300000, 1325000,
1350000, 1375000
};
static const int mc13892_sw[] = {
600000, 625000, 650000, 675000, 700000, 725000,
750000, 775000, 800000, 825000, 850000, 875000,
900000, 925000, 950000, 975000, 1000000, 1025000,
1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
1200000, 1225000, 1250000, 1275000, 1300000, 1325000,
1350000, 1375000, 1400000, 1425000, 1450000, 1475000,
1500000, 1525000, 1550000, 1575000, 1600000, 1625000,
1650000, 1675000, 1700000, 1725000, 1750000, 1775000,
1800000, 1825000, 1850000, 1875000
};
static const int mc13892_swbst[] = {
5000000,
};
static const int mc13892_viohi[] = {
2775000,
};
static const int mc13892_vpll[] = {
1050000, 1250000, 1650000, 1800000,
};
static const int mc13892_vdig[] = {
1050000, 1250000, 1650000, 1800000,
};
static const int mc13892_vsd[] = {
1800000, 2000000, 2600000, 2700000,
2800000, 2900000, 3000000, 3150000,
};
static const int mc13892_vusb2[] = {
2400000, 2600000, 2700000, 2775000,
};
static const int mc13892_vvideo[] = {
2700000, 2775000, 2500000, 2600000,
};
static const int mc13892_vaudio[] = {
2300000, 2500000, 2775000, 3000000,
};
static const int mc13892_vcam[] = {
2500000, 2600000, 2750000, 3000000,
};
static const int mc13892_vgen1[] = {
1200000, 1500000, 2775000, 3150000,
};
static const int mc13892_vgen2[] = {
1200000, 1500000, 1600000, 1800000,
2700000, 2800000, 3000000, 3150000,
};
static const int mc13892_vgen3[] = {
1800000, 2900000,
};
static const int mc13892_vusb[] = {
3300000,
};
static const int mc13892_gpo[] = {
2750000,
};
static const int mc13892_pwgtdrv[] = {
5000000,
};
static struct regulator_ops mc13892_gpo_regulator_ops;
/* sw regulators need special care due to the "hi bit" */
static struct regulator_ops mc13892_sw_regulator_ops;
#define MC13892_FIXED_DEFINE(name, reg, voltages) \
MC13xxx_FIXED_DEFINE(MC13892_, name, reg, voltages, \
mc13xxx_fixed_regulator_ops)
#define MC13892_GPO_DEFINE(name, reg, voltages) \
MC13xxx_GPO_DEFINE(MC13892_, name, reg, voltages, \
mc13892_gpo_regulator_ops)
#define MC13892_SW_DEFINE(name, reg, vsel_reg, voltages) \
MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \
mc13892_sw_regulator_ops)
#define MC13892_DEFINE_REGU(name, reg, vsel_reg, voltages) \
MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \
mc13xxx_regulator_ops)
static struct mc13xxx_regulator mc13892_regulators[] = {
MC13892_DEFINE_REGU(VCOINCELL, POWERCTL0, POWERCTL0, mc13892_vcoincell),
MC13892_SW_DEFINE(SW1, SWITCHERS0, SWITCHERS0, mc13892_sw1),
MC13892_SW_DEFINE(SW2, SWITCHERS1, SWITCHERS1, mc13892_sw),
MC13892_SW_DEFINE(SW3, SWITCHERS2, SWITCHERS2, mc13892_sw),
MC13892_SW_DEFINE(SW4, SWITCHERS3, SWITCHERS3, mc13892_sw),
MC13892_FIXED_DEFINE(SWBST, SWITCHERS5, mc13892_swbst),
MC13892_FIXED_DEFINE(VIOHI, REGULATORMODE0, mc13892_viohi),
MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0, \
mc13892_vpll),
MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \
mc13892_vdig),
MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1, \
mc13892_vsd),
MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0, \
mc13892_vusb2),
MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1, \
mc13892_vvideo),
MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1, \
mc13892_vaudio),
MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \
mc13892_vcam),
MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0, \
mc13892_vgen1),
MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0, \
mc13892_vgen2),
MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0, \
mc13892_vgen3),
MC13892_FIXED_DEFINE(VUSB, USB1, mc13892_vusb),
MC13892_GPO_DEFINE(GPO1, POWERMISC, mc13892_gpo),
MC13892_GPO_DEFINE(GPO2, POWERMISC, mc13892_gpo),
MC13892_GPO_DEFINE(GPO3, POWERMISC, mc13892_gpo),
MC13892_GPO_DEFINE(GPO4, POWERMISC, mc13892_gpo),
MC13892_GPO_DEFINE(PWGT1SPI, POWERMISC, mc13892_pwgtdrv),
MC13892_GPO_DEFINE(PWGT2SPI, POWERMISC, mc13892_pwgtdrv),
};
static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
u32 val)
{
struct mc13xxx *mc13892 = priv->mc13xxx;
int ret;
u32 valread;
BUG_ON(val & ~mask);
ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread);
if (ret)
return ret;
/* Update the stored state for Power Gates. */
priv->powermisc_pwgt_state =
(priv->powermisc_pwgt_state & ~mask) | val;
priv->powermisc_pwgt_state &= MC13892_POWERMISC_PWGTSPI_M;
/* Construct the new register value */
valread = (valread & ~mask) | val;
/* Overwrite the PWGTxEN with the stored version */
valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) |
priv->powermisc_pwgt_state;
return mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread);
}
static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int ret;
u32 en_val = mc13892_regulators[id].enable_bit;
u32 mask = mc13892_regulators[id].enable_bit;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
/* Power Gate enable value is 0 */
if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI)
en_val = 0;
if (id == MC13892_GPO4)
mask |= MC13892_POWERMISC_GPO4ADINEN;
mc13xxx_lock(priv->mc13xxx);
ret = mc13892_powermisc_rmw(priv, mask, en_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int ret;
u32 dis_val = 0;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
/* Power Gate disable value is 1 */
if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI)
dis_val = mc13892_regulators[id].enable_bit;
mc13xxx_lock(priv->mc13xxx);
ret = mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit,
dis_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val;
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val);
mc13xxx_unlock(priv->mc13xxx);
if (ret)
return ret;
/* Power Gates state is stored in powermisc_pwgt_state
* where the meaning of bits is negated */
val = (val & ~MC13892_POWERMISC_PWGTSPI_M) |
(priv->powermisc_pwgt_state ^ MC13892_POWERMISC_PWGTSPI_M);
return (val & mc13892_regulators[id].enable_bit) != 0;
}
static struct regulator_ops mc13892_gpo_regulator_ops = {
.enable = mc13892_gpo_regulator_enable,
.disable = mc13892_gpo_regulator_disable,
.is_enabled = mc13892_gpo_regulator_is_enabled,
.list_voltage = mc13xxx_regulator_list_voltage,
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
};
static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val, hi;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
mc13892_regulators[id].vsel_reg, &val);
mc13xxx_unlock(priv->mc13xxx);
if (ret)
return ret;
hi = val & MC13892_SWITCHERS0_SWxHI;
val = (val & mc13892_regulators[id].vsel_mask)
>> mc13892_regulators[id].vsel_shift;
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
if (hi)
val = (25000 * val) + 1100000;
else
val = (25000 * val) + 600000;
return val;
}
static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int hi, value, val, mask, id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
__func__, id, min_uV, max_uV);
/* Find the best index */
value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV);
dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value);
if (value < 0)
return value;
value = mc13892_regulators[id].voltages[value];
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
mc13892_regulators[id].vsel_reg, &val);
if (ret)
goto err;
hi = val & MC13892_SWITCHERS0_SWxHI;
if (value > 1375)
hi = 1;
if (value < 1100)
hi = 0;
if (hi) {
value = (value - 1100000) / 25000;
value |= MC13892_SWITCHERS0_SWxHI;
} else
value = (value - 600000) / 25000;
mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI;
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg,
mask, value << mc13892_regulators[id].vsel_shift);
err:
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static struct regulator_ops mc13892_sw_regulator_ops = {
.is_enabled = mc13xxx_sw_regulator_is_enabled,
.list_voltage = mc13xxx_regulator_list_voltage,
.set_voltage = mc13892_sw_regulator_set_voltage,
.get_voltage = mc13892_sw_regulator_get_voltage,
};
static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
unsigned int en_val = 0;
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
if (mode == REGULATOR_MODE_FAST)
en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN;
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg,
MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val;
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val);
mc13xxx_unlock(priv->mc13xxx);
if (ret)
return ret;
if (val & MC13892_REGULATORMODE1_VCAMCONFIGEN)
return REGULATOR_MODE_FAST;
return REGULATOR_MODE_NORMAL;
}
static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct mc13xxx_regulator_init_data *init_data;
int i, ret;
u32 val;
priv = kzalloc(sizeof(*priv) +
pdata->num_regulators * sizeof(priv->regulators[0]),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->mc13xxx_regulators = mc13892_regulators;
priv->mc13xxx = mc13892;
mc13xxx_lock(mc13892);
ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
if (ret)
goto err_free;
/* enable switch auto mode */
if ((val & 0x0000FFFF) == 0x45d0) {
ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4,
MC13892_SWITCHERS4_SW1MODE_M |
MC13892_SWITCHERS4_SW2MODE_M,
MC13892_SWITCHERS4_SW1MODE_AUTO |
MC13892_SWITCHERS4_SW2MODE_AUTO);
if (ret)
goto err_free;
ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5,
MC13892_SWITCHERS5_SW3MODE_M |
MC13892_SWITCHERS5_SW4MODE_M,
MC13892_SWITCHERS5_SW3MODE_AUTO |
MC13892_SWITCHERS5_SW4MODE_AUTO);
if (ret)
goto err_free;
}
mc13xxx_unlock(mc13892);
mc13892_regulators[MC13892_VCAM].desc.ops->set_mode
= mc13892_vcam_set_mode;
mc13892_regulators[MC13892_VCAM].desc.ops->get_mode
= mc13892_vcam_get_mode;
for (i = 0; i < pdata->num_regulators; i++) {
init_data = &pdata->regulators[i];
priv->regulators[i] = regulator_register(
&mc13892_regulators[init_data->id].desc,
&pdev->dev, init_data->init_data, priv);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13892_regulators[i].desc.name);
ret = PTR_ERR(priv->regulators[i]);
goto err;
}
}
platform_set_drvdata(pdev, priv);
return 0;
err:
while (--i >= 0)
regulator_unregister(priv->regulators[i]);
err_free:
mc13xxx_unlock(mc13892);
kfree(priv);
return ret;
}
static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
int i;
platform_set_drvdata(pdev, NULL);
for (i = 0; i < pdata->num_regulators; i++)
regulator_unregister(priv->regulators[i]);
kfree(priv);
return 0;
}
static struct platform_driver mc13892_regulator_driver = {
.driver = {
.name = "mc13892-regulator",
.owner = THIS_MODULE,
},
.remove = __devexit_p(mc13892_regulator_remove),
.probe = mc13892_regulator_probe,
};
static int __init mc13892_regulator_init(void)
{
return platform_driver_register(&mc13892_regulator_driver);
}
subsys_initcall(mc13892_regulator_init);
static void __exit mc13892_regulator_exit(void)
{
platform_driver_unregister(&mc13892_regulator_driver);
}
module_exit(mc13892_regulator_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>");
MODULE_DESCRIPTION("Regulator Driver for Freescale MC13892 PMIC");
MODULE_ALIAS("platform:mc13892-regulator");

View file

@ -0,0 +1,241 @@
/*
* Regulator Driver for Freescale MC13xxx PMIC
*
* Copyright 2010 Yong Shen <yong.shen@linaro.org>
*
* Based on mc13783 regulator driver :
* Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
* Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Regs infos taken from mc13xxx drivers from freescale and mc13xxx.pdf file
* from freescale
*/
#include <linux/mfd/mc13xxx.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
#include "mc13xxx.h"
static int mc13xxx_regulator_enable(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
mc13xxx_regulators[id].enable_bit,
mc13xxx_regulators[id].enable_bit);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
mc13xxx_regulators[id].enable_bit, 0);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int ret, id = rdev_get_id(rdev);
unsigned int val;
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
mc13xxx_unlock(priv->mc13xxx);
if (ret)
return ret;
return (val & mc13xxx_regulators[id].enable_bit) != 0;
}
int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
unsigned selector)
{
int id = rdev_get_id(rdev);
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
if (selector >= mc13xxx_regulators[id].desc.n_voltages)
return -EINVAL;
return mc13xxx_regulators[id].voltages[selector];
}
EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage);
int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int reg_id = rdev_get_id(rdev);
int i;
int bestmatch;
int bestindex;
/*
* Locate the minimum voltage fitting the criteria on
* this regulator. The switchable voltages are not
* in strict falling order so we need to check them
* all for the best match.
*/
bestmatch = INT_MAX;
bestindex = -1;
for (i = 0; i < mc13xxx_regulators[reg_id].desc.n_voltages; i++) {
if (mc13xxx_regulators[reg_id].voltages[i] >= min_uV &&
mc13xxx_regulators[reg_id].voltages[i] < bestmatch) {
bestmatch = mc13xxx_regulators[reg_id].voltages[i];
bestindex = i;
}
}
if (bestindex < 0 || bestmatch > max_uV) {
dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n",
min_uV, max_uV);
return -EINVAL;
}
return bestindex;
}
EXPORT_SYMBOL_GPL(mc13xxx_get_best_voltage_index);
static int mc13xxx_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV, unsigned *selector)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int value, id = rdev_get_id(rdev);
int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
__func__, id, min_uV, max_uV);
/* Find the best index */
value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV);
dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value);
if (value < 0)
return value;
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
mc13xxx_regulators[id].vsel_mask,
value << mc13xxx_regulators[id].vsel_shift);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int ret, id = rdev_get_id(rdev);
unsigned int val;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
mc13xxx_regulators[id].vsel_reg, &val);
mc13xxx_unlock(priv->mc13xxx);
if (ret)
return ret;
val = (val & mc13xxx_regulators[id].vsel_mask)
>> mc13xxx_regulators[id].vsel_shift;
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
BUG_ON(val < 0 || val > mc13xxx_regulators[id].desc.n_voltages);
return mc13xxx_regulators[id].voltages[val];
}
struct regulator_ops mc13xxx_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
.list_voltage = mc13xxx_regulator_list_voltage,
.set_voltage = mc13xxx_regulator_set_voltage,
.get_voltage = mc13xxx_regulator_get_voltage,
};
EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV, unsigned *selector)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
__func__, id, min_uV, max_uV);
if (min_uV >= mc13xxx_regulators[id].voltages[0] &&
max_uV <= mc13xxx_regulators[id].voltages[0])
return 0;
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
return mc13xxx_regulators[id].voltages[0];
}
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage);
struct regulator_ops mc13xxx_fixed_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
.list_voltage = mc13xxx_regulator_list_voltage,
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
};
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev)
{
return 1;
}
EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>");
MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC");
MODULE_ALIAS("mc13xxx-regulator-core");

101
drivers/regulator/mc13xxx.h Normal file
View file

@ -0,0 +1,101 @@
/*
* mc13xxx.h - regulators for the Freescale mc13xxx PMIC
*
* Copyright (C) 2010 Yong Shen <yong.shen@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __LINUX_REGULATOR_MC13XXX_H
#define __LINUX_REGULATOR_MC13XXX_H
#include <linux/regulator/driver.h>
struct mc13xxx_regulator {
struct regulator_desc desc;
int reg;
int enable_bit;
int vsel_reg;
int vsel_shift;
int vsel_mask;
int hi_bit;
int const *voltages;
};
struct mc13xxx_regulator_priv {
struct mc13xxx *mc13xxx;
u32 powermisc_pwgt_state;
struct mc13xxx_regulator *mc13xxx_regulators;
struct regulator_dev *regulators[];
};
extern int mc13xxx_sw_regulator(struct regulator_dev *rdev);
extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev);
extern int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev,
int min_uV, int max_uV);
extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
unsigned selector);
extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector);
extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev);
extern struct regulator_ops mc13xxx_regulator_ops;
extern struct regulator_ops mc13xxx_fixed_regulator_ops;
#define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
.name = #prefix "_" #_name, \
.n_voltages = ARRAY_SIZE(_voltages), \
.ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
.id = prefix ## _name, \
.owner = THIS_MODULE, \
}, \
.reg = prefix ## _reg, \
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
.vsel_reg = prefix ## _vsel_reg, \
.vsel_shift = prefix ## _vsel_reg ## _ ## _name ## VSEL,\
.vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\
.voltages = _voltages, \
}
#define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
.name = #prefix "_" #_name, \
.n_voltages = ARRAY_SIZE(_voltages), \
.ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
.id = prefix ## _name, \
.owner = THIS_MODULE, \
}, \
.reg = prefix ## _reg, \
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
.voltages = _voltages, \
}
#define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
.name = #prefix "_" #_name, \
.n_voltages = ARRAY_SIZE(_voltages), \
.ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
.id = prefix ## _name, \
.owner = THIS_MODULE, \
}, \
.reg = prefix ## _reg, \
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
.voltages = _voltages, \
}
#define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \
MC13xxx_DEFINE(SW, _name, _reg, _vsel_reg, _voltages, ops)
#define MC13xxx_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages, ops) \
MC13xxx_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages, ops)
#endif

View file

@ -151,7 +151,8 @@ static struct pcap_regulator vreg_table[] = {
}; };
static int pcap_regulator_set_voltage(struct regulator_dev *rdev, static int pcap_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
void *pcap = rdev_get_drvdata(rdev); void *pcap = rdev_get_drvdata(rdev);
@ -170,10 +171,12 @@ static int pcap_regulator_set_voltage(struct regulator_dev *rdev,
i = 0; i = 0;
uV = vreg->voltage_table[i] * 1000; uV = vreg->voltage_table[i] * 1000;
if (min_uV <= uV && uV <= max_uV) if (min_uV <= uV && uV <= max_uV) {
*selector = i;
return ezx_pcap_set_bits(pcap, vreg->reg, return ezx_pcap_set_bits(pcap, vreg->reg,
(vreg->n_voltages - 1) << vreg->index, (vreg->n_voltages - 1) << vreg->index,
i << vreg->index); i << vreg->index);
}
if (i == 0 && rdev_get_id(rdev) == V1) if (i == 0 && rdev_get_id(rdev) == V1)
i = vreg->n_voltages - 1; i = vreg->n_voltages - 1;

View file

@ -108,7 +108,8 @@ static unsigned int ldo_voltage_value(u8 bits)
} }
static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct pcf50633 *pcf; struct pcf50633 *pcf;
int regulator_id, millivolts; int regulator_id, millivolts;
@ -147,6 +148,8 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
return -EINVAL; return -EINVAL;
} }
*selector = volt_bits;
return pcf50633_reg_write(pcf, regnr, volt_bits); return pcf50633_reg_write(pcf, regnr, volt_bits);
} }

View file

@ -321,7 +321,8 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
} }
static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct tps_pmic *tps = rdev_get_drvdata(dev); struct tps_pmic *tps = rdev_get_drvdata(dev);
int dcdc = rdev_get_id(dev); int dcdc = rdev_get_id(dev);
@ -346,6 +347,8 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
break; break;
} }
*selector = vsel;
/* write to the register in case we found a match */ /* write to the register in case we found a match */
if (vsel == tps->info[dcdc]->table_len) if (vsel == tps->info[dcdc]->table_len)
return -EINVAL; return -EINVAL;
@ -371,7 +374,7 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
} }
static int tps65023_ldo_set_voltage(struct regulator_dev *dev, static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct tps_pmic *tps = rdev_get_drvdata(dev); struct tps_pmic *tps = rdev_get_drvdata(dev);
int data, vsel, ldo = rdev_get_id(dev); int data, vsel, ldo = rdev_get_id(dev);
@ -396,6 +399,8 @@ static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
if (vsel == tps->info[ldo]->table_len) if (vsel == tps->info[ldo]->table_len)
return -EINVAL; return -EINVAL;
*selector = vsel;
data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
if (data < 0) if (data < 0)
return data; return data;

View file

@ -369,7 +369,8 @@ static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev)
} }
static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
int data, vsel, dcdc = rdev_get_id(dev); int data, vsel, dcdc = rdev_get_id(dev);
@ -415,6 +416,8 @@ static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,
if (vsel == tps->info[dcdc]->table_len) if (vsel == tps->info[dcdc]->table_len)
return -EINVAL; return -EINVAL;
*selector = vsel;
data = tps6507x_pmic_reg_read(tps, reg); data = tps6507x_pmic_reg_read(tps, reg);
if (data < 0) if (data < 0)
return data; return data;
@ -450,7 +453,8 @@ static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev)
} }
static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev, static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
int data, vsel, ldo = rdev_get_id(dev); int data, vsel, ldo = rdev_get_id(dev);
@ -483,6 +487,8 @@ static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev,
if (vsel == tps->info[ldo]->table_len) if (vsel == tps->info[ldo]->table_len)
return -EINVAL; return -EINVAL;
*selector = vsel;
data = tps6507x_pmic_reg_read(tps, reg); data = tps6507x_pmic_reg_read(tps, reg);
if (data < 0) if (data < 0)
return data; return data;

View file

@ -0,0 +1,693 @@
/*
* Regulator driver for TPS6524x PMIC
*
* Copyright (C) 2010 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
* whether express or implied; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#define REG_LDO_SET 0x0
#define LDO_ILIM_MASK 1 /* 0 = 400-800, 1 = 900-1500 */
#define LDO_VSEL_MASK 0x0f
#define LDO2_ILIM_SHIFT 12
#define LDO2_VSEL_SHIFT 4
#define LDO1_ILIM_SHIFT 8
#define LDO1_VSEL_SHIFT 0
#define REG_BLOCK_EN 0x1
#define BLOCK_MASK 1
#define BLOCK_LDO1_SHIFT 0
#define BLOCK_LDO2_SHIFT 1
#define BLOCK_LCD_SHIFT 2
#define BLOCK_USB_SHIFT 3
#define REG_DCDC_SET 0x2
#define DCDC_VDCDC_MASK 0x1f
#define DCDC_VDCDC1_SHIFT 0
#define DCDC_VDCDC2_SHIFT 5
#define DCDC_VDCDC3_SHIFT 10
#define REG_DCDC_EN 0x3
#define DCDCDCDC_EN_MASK 0x1
#define DCDCDCDC1_EN_SHIFT 0
#define DCDCDCDC1_PG_MSK BIT(1)
#define DCDCDCDC2_EN_SHIFT 2
#define DCDCDCDC2_PG_MSK BIT(3)
#define DCDCDCDC3_EN_SHIFT 4
#define DCDCDCDC3_PG_MSK BIT(5)
#define REG_USB 0x4
#define USB_ILIM_SHIFT 0
#define USB_ILIM_MASK 0x3
#define USB_TSD_SHIFT 2
#define USB_TSD_MASK 0x3
#define USB_TWARN_SHIFT 4
#define USB_TWARN_MASK 0x3
#define USB_IWARN_SD BIT(6)
#define USB_FAST_LOOP BIT(7)
#define REG_ALARM 0x5
#define ALARM_LDO1 BIT(0)
#define ALARM_DCDC1 BIT(1)
#define ALARM_DCDC2 BIT(2)
#define ALARM_DCDC3 BIT(3)
#define ALARM_LDO2 BIT(4)
#define ALARM_USB_WARN BIT(5)
#define ALARM_USB_ALARM BIT(6)
#define ALARM_LCD BIT(9)
#define ALARM_TEMP_WARM BIT(10)
#define ALARM_TEMP_HOT BIT(11)
#define ALARM_NRST BIT(14)
#define ALARM_POWERUP BIT(15)
#define REG_INT_ENABLE 0x6
#define INT_LDO1 BIT(0)
#define INT_DCDC1 BIT(1)
#define INT_DCDC2 BIT(2)
#define INT_DCDC3 BIT(3)
#define INT_LDO2 BIT(4)
#define INT_USB_WARN BIT(5)
#define INT_USB_ALARM BIT(6)
#define INT_LCD BIT(9)
#define INT_TEMP_WARM BIT(10)
#define INT_TEMP_HOT BIT(11)
#define INT_GLOBAL_EN BIT(15)
#define REG_INT_STATUS 0x7
#define STATUS_LDO1 BIT(0)
#define STATUS_DCDC1 BIT(1)
#define STATUS_DCDC2 BIT(2)
#define STATUS_DCDC3 BIT(3)
#define STATUS_LDO2 BIT(4)
#define STATUS_USB_WARN BIT(5)
#define STATUS_USB_ALARM BIT(6)
#define STATUS_LCD BIT(9)
#define STATUS_TEMP_WARM BIT(10)
#define STATUS_TEMP_HOT BIT(11)
#define REG_SOFTWARE_RESET 0xb
#define REG_WRITE_ENABLE 0xd
#define REG_REV_ID 0xf
#define N_DCDC 3
#define N_LDO 2
#define N_SWITCH 2
#define N_REGULATORS (3 /* DCDC */ + \
2 /* LDO */ + \
2 /* switch */)
#define FIXED_ILIMSEL BIT(0)
#define FIXED_VOLTAGE BIT(1)
#define CMD_READ(reg) ((reg) << 6)
#define CMD_WRITE(reg) (BIT(5) | (reg) << 6)
#define STAT_CLK BIT(3)
#define STAT_WRITE BIT(2)
#define STAT_INVALID BIT(1)
#define STAT_WP BIT(0)
struct field {
int reg;
int shift;
int mask;
};
struct supply_info {
const char *name;
int n_voltages;
const int *voltages;
int fixed_voltage;
int n_ilimsels;
const int *ilimsels;
int fixed_ilimsel;
int flags;
struct field enable, voltage, ilimsel;
};
struct tps6524x {
struct device *dev;
struct spi_device *spi;
struct mutex lock;
struct regulator_desc desc[N_REGULATORS];
struct regulator_dev *rdev[N_REGULATORS];
};
static int __read_reg(struct tps6524x *hw, int reg)
{
int error = 0;
u16 cmd = CMD_READ(reg), in;
u8 status;
struct spi_message m;
struct spi_transfer t[3];
spi_message_init(&m);
memset(t, 0, sizeof(t));
t[0].tx_buf = &cmd;
t[0].len = 2;
t[0].bits_per_word = 12;
spi_message_add_tail(&t[0], &m);
t[1].rx_buf = &in;
t[1].len = 2;
t[1].bits_per_word = 16;
spi_message_add_tail(&t[1], &m);
t[2].rx_buf = &status;
t[2].len = 1;
t[2].bits_per_word = 4;
spi_message_add_tail(&t[2], &m);
error = spi_sync(hw->spi, &m);
if (error < 0)
return error;
dev_dbg(hw->dev, "read reg %d, data %x, status %x\n",
reg, in, status);
if (!(status & STAT_CLK) || (status & STAT_WRITE))
return -EIO;
if (status & STAT_INVALID)
return -EINVAL;
return in;
}
static int read_reg(struct tps6524x *hw, int reg)
{
int ret;
mutex_lock(&hw->lock);
ret = __read_reg(hw, reg);
mutex_unlock(&hw->lock);
return ret;
}
static int __write_reg(struct tps6524x *hw, int reg, int val)
{
int error = 0;
u16 cmd = CMD_WRITE(reg), out = val;
u8 status;
struct spi_message m;
struct spi_transfer t[3];
spi_message_init(&m);
memset(t, 0, sizeof(t));
t[0].tx_buf = &cmd;
t[0].len = 2;
t[0].bits_per_word = 12;
spi_message_add_tail(&t[0], &m);
t[1].tx_buf = &out;
t[1].len = 2;
t[1].bits_per_word = 16;
spi_message_add_tail(&t[1], &m);
t[2].rx_buf = &status;
t[2].len = 1;
t[2].bits_per_word = 4;
spi_message_add_tail(&t[2], &m);
error = spi_sync(hw->spi, &m);
if (error < 0)
return error;
dev_dbg(hw->dev, "wrote reg %d, data %x, status %x\n",
reg, out, status);
if (!(status & STAT_CLK) || !(status & STAT_WRITE))
return -EIO;
if (status & (STAT_INVALID | STAT_WP))
return -EINVAL;
return error;
}
static int __rmw_reg(struct tps6524x *hw, int reg, int mask, int val)
{
int ret;
ret = __read_reg(hw, reg);
if (ret < 0)
return ret;
ret &= ~mask;
ret |= val;
ret = __write_reg(hw, reg, ret);
return (ret < 0) ? ret : 0;
}
static int rmw_protect(struct tps6524x *hw, int reg, int mask, int val)
{
int ret;
mutex_lock(&hw->lock);
ret = __write_reg(hw, REG_WRITE_ENABLE, 1);
if (ret) {
dev_err(hw->dev, "failed to set write enable\n");
goto error;
}
ret = __rmw_reg(hw, reg, mask, val);
if (ret)
dev_err(hw->dev, "failed to rmw register %d\n", reg);
ret = __write_reg(hw, REG_WRITE_ENABLE, 0);
if (ret) {
dev_err(hw->dev, "failed to clear write enable\n");
goto error;
}
error:
mutex_unlock(&hw->lock);
return ret;
}
static int read_field(struct tps6524x *hw, const struct field *field)
{
int tmp;
tmp = read_reg(hw, field->reg);
if (tmp < 0)
return tmp;
return (tmp >> field->shift) & field->mask;
}
static int write_field(struct tps6524x *hw, const struct field *field,
int val)
{
if (val & ~field->mask)
return -EOVERFLOW;
return rmw_protect(hw, field->reg,
field->mask << field->shift,
val << field->shift);
}
static const int dcdc1_voltages[] = {
800000, 825000, 850000, 875000,
900000, 925000, 950000, 975000,
1000000, 1025000, 1050000, 1075000,
1100000, 1125000, 1150000, 1175000,
1200000, 1225000, 1250000, 1275000,
1300000, 1325000, 1350000, 1375000,
1400000, 1425000, 1450000, 1475000,
1500000, 1525000, 1550000, 1575000,
};
static const int dcdc2_voltages[] = {
1400000, 1450000, 1500000, 1550000,
1600000, 1650000, 1700000, 1750000,
1800000, 1850000, 1900000, 1950000,
2000000, 2050000, 2100000, 2150000,
2200000, 2250000, 2300000, 2350000,
2400000, 2450000, 2500000, 2550000,
2600000, 2650000, 2700000, 2750000,
2800000, 2850000, 2900000, 2950000,
};
static const int dcdc3_voltages[] = {
2400000, 2450000, 2500000, 2550000, 2600000,
2650000, 2700000, 2750000, 2800000, 2850000,
2900000, 2950000, 3000000, 3050000, 3100000,
3150000, 3200000, 3250000, 3300000, 3350000,
3400000, 3450000, 3500000, 3550000, 3600000,
};
static const int ldo1_voltages[] = {
4300000, 4350000, 4400000, 4450000,
4500000, 4550000, 4600000, 4650000,
4700000, 4750000, 4800000, 4850000,
4900000, 4950000, 5000000, 5050000,
};
static const int ldo2_voltages[] = {
1100000, 1150000, 1200000, 1250000,
1300000, 1700000, 1750000, 1800000,
1850000, 1900000, 3150000, 3200000,
3250000, 3300000, 3350000, 3400000,
};
static const int ldo_ilimsel[] = {
400000, 1500000
};
static const int usb_ilimsel[] = {
200000, 400000, 800000, 1000000
};
#define __MK_FIELD(_reg, _mask, _shift) \
{ .reg = (_reg), .mask = (_mask), .shift = (_shift), }
static const struct supply_info supply_info[N_REGULATORS] = {
{
.name = "DCDC1",
.flags = FIXED_ILIMSEL,
.n_voltages = ARRAY_SIZE(dcdc1_voltages),
.voltages = dcdc1_voltages,
.fixed_ilimsel = 2400000,
.enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
DCDCDCDC1_EN_SHIFT),
.voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
DCDC_VDCDC1_SHIFT),
},
{
.name = "DCDC2",
.flags = FIXED_ILIMSEL,
.n_voltages = ARRAY_SIZE(dcdc2_voltages),
.voltages = dcdc2_voltages,
.fixed_ilimsel = 1200000,
.enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
DCDCDCDC2_EN_SHIFT),
.voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
DCDC_VDCDC2_SHIFT),
},
{
.name = "DCDC3",
.flags = FIXED_ILIMSEL,
.n_voltages = ARRAY_SIZE(dcdc3_voltages),
.voltages = dcdc3_voltages,
.fixed_ilimsel = 1200000,
.enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
DCDCDCDC3_EN_SHIFT),
.voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
DCDC_VDCDC3_SHIFT),
},
{
.name = "LDO1",
.n_voltages = ARRAY_SIZE(ldo1_voltages),
.voltages = ldo1_voltages,
.n_ilimsels = ARRAY_SIZE(ldo_ilimsel),
.ilimsels = ldo_ilimsel,
.enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
BLOCK_LDO1_SHIFT),
.voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
LDO1_VSEL_SHIFT),
.ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
LDO1_ILIM_SHIFT),
},
{
.name = "LDO2",
.n_voltages = ARRAY_SIZE(ldo2_voltages),
.voltages = ldo2_voltages,
.n_ilimsels = ARRAY_SIZE(ldo_ilimsel),
.ilimsels = ldo_ilimsel,
.enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
BLOCK_LDO2_SHIFT),
.voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
LDO2_VSEL_SHIFT),
.ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
LDO2_ILIM_SHIFT),
},
{
.name = "USB",
.flags = FIXED_VOLTAGE,
.fixed_voltage = 5000000,
.n_ilimsels = ARRAY_SIZE(usb_ilimsel),
.ilimsels = usb_ilimsel,
.enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
BLOCK_USB_SHIFT),
.ilimsel = __MK_FIELD(REG_USB, USB_ILIM_MASK,
USB_ILIM_SHIFT),
},
{
.name = "LCD",
.flags = FIXED_VOLTAGE | FIXED_ILIMSEL,
.fixed_voltage = 5000000,
.fixed_ilimsel = 400000,
.enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
BLOCK_LCD_SHIFT),
},
};
static int list_voltage(struct regulator_dev *rdev, unsigned selector)
{
const struct supply_info *info;
struct tps6524x *hw;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
if (info->flags & FIXED_VOLTAGE)
return selector ? -EINVAL : info->fixed_voltage;
return ((selector < info->n_voltages) ?
info->voltages[selector] : -EINVAL);
}
static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned *selector)
{
const struct supply_info *info;
struct tps6524x *hw;
unsigned i;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
if (info->flags & FIXED_VOLTAGE)
return -EINVAL;
for (i = 0; i < info->n_voltages; i++)
if (min_uV <= info->voltages[i] &&
max_uV >= info->voltages[i])
break;
if (i >= info->n_voltages)
i = info->n_voltages - 1;
*selector = info->voltages[i];
return write_field(hw, &info->voltage, i);
}
static int get_voltage(struct regulator_dev *rdev)
{
const struct supply_info *info;
struct tps6524x *hw;
int ret;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
if (info->flags & FIXED_VOLTAGE)
return info->fixed_voltage;
ret = read_field(hw, &info->voltage);
if (ret < 0)
return ret;
if (WARN_ON(ret >= info->n_voltages))
return -EIO;
return info->voltages[ret];
}
static int set_current_limit(struct regulator_dev *rdev, int min_uA,
int max_uA)
{
const struct supply_info *info;
struct tps6524x *hw;
int i;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
if (info->flags & FIXED_ILIMSEL)
return -EINVAL;
for (i = 0; i < info->n_ilimsels; i++)
if (min_uA <= info->ilimsels[i] &&
max_uA >= info->ilimsels[i])
break;
if (i >= info->n_ilimsels)
return -EINVAL;
return write_field(hw, &info->ilimsel, i);
}
static int get_current_limit(struct regulator_dev *rdev)
{
const struct supply_info *info;
struct tps6524x *hw;
int ret;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
if (info->flags & FIXED_ILIMSEL)
return info->fixed_ilimsel;
ret = read_field(hw, &info->ilimsel);
if (ret < 0)
return ret;
if (WARN_ON(ret >= info->n_ilimsels))
return -EIO;
return info->ilimsels[ret];
}
static int enable_supply(struct regulator_dev *rdev)
{
const struct supply_info *info;
struct tps6524x *hw;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
return write_field(hw, &info->enable, 1);
}
static int disable_supply(struct regulator_dev *rdev)
{
const struct supply_info *info;
struct tps6524x *hw;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
return write_field(hw, &info->enable, 0);
}
static int is_supply_enabled(struct regulator_dev *rdev)
{
const struct supply_info *info;
struct tps6524x *hw;
hw = rdev_get_drvdata(rdev);
info = &supply_info[rdev_get_id(rdev)];
return read_field(hw, &info->enable);
}
static struct regulator_ops regulator_ops = {
.is_enabled = is_supply_enabled,
.enable = enable_supply,
.disable = disable_supply,
.get_voltage = get_voltage,
.set_voltage = set_voltage,
.list_voltage = list_voltage,
.set_current_limit = set_current_limit,
.get_current_limit = get_current_limit,
};
static int __devexit pmic_remove(struct spi_device *spi)
{
struct tps6524x *hw = spi_get_drvdata(spi);
int i;
if (!hw)
return 0;
for (i = 0; i < N_REGULATORS; i++) {
if (hw->rdev[i])
regulator_unregister(hw->rdev[i]);
hw->rdev[i] = NULL;
}
spi_set_drvdata(spi, NULL);
kfree(hw);
return 0;
}
static int __devinit pmic_probe(struct spi_device *spi)
{
struct tps6524x *hw;
struct device *dev = &spi->dev;
const struct supply_info *info = supply_info;
struct regulator_init_data *init_data;
int ret = 0, i;
init_data = dev->platform_data;
if (!init_data) {
dev_err(dev, "could not find regulator platform data\n");
return -EINVAL;
}
hw = kzalloc(sizeof(struct tps6524x), GFP_KERNEL);
if (!hw) {
dev_err(dev, "cannot allocate regulator private data\n");
return -ENOMEM;
}
spi_set_drvdata(spi, hw);
memset(hw, 0, sizeof(struct tps6524x));
hw->dev = dev;
hw->spi = spi_dev_get(spi);
mutex_init(&hw->lock);
for (i = 0; i < N_REGULATORS; i++, info++, init_data++) {
hw->desc[i].name = info->name;
hw->desc[i].id = i;
hw->desc[i].n_voltages = info->n_voltages;
hw->desc[i].ops = &regulator_ops;
hw->desc[i].type = REGULATOR_VOLTAGE;
hw->desc[i].owner = THIS_MODULE;
if (info->flags & FIXED_VOLTAGE)
hw->desc[i].n_voltages = 1;
hw->rdev[i] = regulator_register(&hw->desc[i], dev,
init_data, hw);
if (IS_ERR(hw->rdev[i])) {
ret = PTR_ERR(hw->rdev[i]);
hw->rdev[i] = NULL;
goto fail;
}
}
return 0;
fail:
pmic_remove(spi);
return ret;
}
static struct spi_driver pmic_driver = {
.probe = pmic_probe,
.remove = __devexit_p(pmic_remove),
.driver = {
.name = "tps6524x",
.owner = THIS_MODULE,
},
};
static int __init pmic_driver_init(void)
{
return spi_register_driver(&pmic_driver);
}
module_init(pmic_driver_init);
static void __exit pmic_driver_exit(void)
{
spi_unregister_driver(&pmic_driver);
}
module_exit(pmic_driver_exit);
MODULE_DESCRIPTION("TPS6524X PMIC Driver");
MODULE_AUTHOR("Cyril Chemparathy");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:tps6524x");

View file

@ -85,7 +85,8 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
static int __tps6586x_ldo_set_voltage(struct device *parent, static int __tps6586x_ldo_set_voltage(struct device *parent,
struct tps6586x_regulator *ri, struct tps6586x_regulator *ri,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
int val, uV; int val, uV;
uint8_t mask; uint8_t mask;
@ -100,6 +101,8 @@ static int __tps6586x_ldo_set_voltage(struct device *parent,
/* use the first in-range value */ /* use the first in-range value */
if (min_uV <= uV && uV <= max_uV) { if (min_uV <= uV && uV <= max_uV) {
*selector = val;
val <<= ri->volt_shift; val <<= ri->volt_shift;
mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
@ -111,12 +114,13 @@ static int __tps6586x_ldo_set_voltage(struct device *parent,
} }
static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev); struct device *parent = to_tps6586x_dev(rdev);
return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV,
selector);
} }
static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev)
@ -140,13 +144,14 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev)
} }
static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev); struct device *parent = to_tps6586x_dev(rdev);
int ret; int ret;
ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV,
selector);
if (ret) if (ret)
return ret; return ret;

View file

@ -329,7 +329,8 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
} }
static int static int
twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned *selector)
{ {
struct twlreg_info *info = rdev_get_drvdata(rdev); struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel; int vsel;
@ -345,9 +346,11 @@ twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
/* REVISIT for VAUX2, first match may not be best/lowest */ /* REVISIT for VAUX2, first match may not be best/lowest */
/* use the first in-range value */ /* use the first in-range value */
if (min_uV <= uV && uV <= max_uV) if (min_uV <= uV && uV <= max_uV) {
*selector = vsel;
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, return twlreg_write(info, TWL_MODULE_PM_RECEIVER,
VREG_VOLTAGE, vsel); VREG_VOLTAGE, vsel);
}
} }
return -EDOM; return -EDOM;
@ -389,7 +392,8 @@ static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
} }
static int static int
twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned *selector)
{ {
struct twlreg_info *info = rdev_get_drvdata(rdev); struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel; int vsel;
@ -402,6 +406,7 @@ twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
* mV = 1000mv + 100mv * (vsel - 1) * mV = 1000mv + 100mv * (vsel - 1)
*/ */
vsel = (min_uV/1000 - 1000)/100 + 1; vsel = (min_uV/1000 - 1000)/100 + 1;
*selector = vsel;
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel);
} }

View file

@ -302,7 +302,7 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
} }
static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
struct wm831x *wm831x = dcdc->wm831x; struct wm831x *wm831x = dcdc->wm831x;
@ -314,6 +314,8 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
if (vsel < 0) if (vsel < 0)
return vsel; return vsel;
*selector = vsel;
/* If this value is already set then do a GPIO update if we can */ /* If this value is already set then do a GPIO update if we can */
if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
return wm831x_buckv_set_dvs(rdev, 0); return wm831x_buckv_set_dvs(rdev, 0);
@ -375,14 +377,14 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel); return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel);
} }
static int wm831x_buckv_get_voltage(struct regulator_dev *rdev) static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
if (dcdc->dvs_gpio && dcdc->dvs_gpio_state) if (dcdc->dvs_gpio && dcdc->dvs_gpio_state)
return wm831x_buckv_list_voltage(rdev, dcdc->dvs_vsel); return dcdc->dvs_vsel;
else else
return wm831x_buckv_list_voltage(rdev, dcdc->on_vsel); return dcdc->on_vsel;
} }
/* Current limit options */ /* Current limit options */
@ -424,7 +426,7 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
static struct regulator_ops wm831x_buckv_ops = { static struct regulator_ops wm831x_buckv_ops = {
.set_voltage = wm831x_buckv_set_voltage, .set_voltage = wm831x_buckv_set_voltage,
.get_voltage = wm831x_buckv_get_voltage, .get_voltage_sel = wm831x_buckv_get_voltage_sel,
.list_voltage = wm831x_buckv_list_voltage, .list_voltage = wm831x_buckv_list_voltage,
.set_suspend_voltage = wm831x_buckv_set_suspend_voltage, .set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
.set_current_limit = wm831x_buckv_set_current_limit, .set_current_limit = wm831x_buckv_set_current_limit,
@ -636,7 +638,7 @@ static int wm831x_buckp_list_voltage(struct regulator_dev *rdev,
} }
static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg,
int min_uV, int max_uV) int min_uV, int max_uV, int *selector)
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
struct wm831x *wm831x = dcdc->wm831x; struct wm831x *wm831x = dcdc->wm831x;
@ -650,16 +652,20 @@ static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg,
if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV) if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV)
return -EINVAL; return -EINVAL;
*selector = vsel;
return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel); return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel);
} }
static int wm831x_buckp_set_voltage(struct regulator_dev *rdev, static int wm831x_buckp_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV); return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV,
selector);
} }
static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
@ -667,11 +673,12 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
unsigned selector;
return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV); return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector);
} }
static int wm831x_buckp_get_voltage(struct regulator_dev *rdev) static int wm831x_buckp_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
struct wm831x *wm831x = dcdc->wm831x; struct wm831x *wm831x = dcdc->wm831x;
@ -682,12 +689,12 @@ static int wm831x_buckp_get_voltage(struct regulator_dev *rdev)
if (val < 0) if (val < 0)
return val; return val;
return wm831x_buckp_list_voltage(rdev, val & WM831X_DC3_ON_VSEL_MASK); return val & WM831X_DC3_ON_VSEL_MASK;
} }
static struct regulator_ops wm831x_buckp_ops = { static struct regulator_ops wm831x_buckp_ops = {
.set_voltage = wm831x_buckp_set_voltage, .set_voltage = wm831x_buckp_set_voltage,
.get_voltage = wm831x_buckp_get_voltage, .get_voltage_sel = wm831x_buckp_get_voltage_sel,
.list_voltage = wm831x_buckp_list_voltage, .list_voltage = wm831x_buckp_list_voltage,
.set_suspend_voltage = wm831x_buckp_set_suspend_voltage, .set_suspend_voltage = wm831x_buckp_set_suspend_voltage,

View file

@ -113,7 +113,8 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
} }
static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
@ -133,16 +134,20 @@ static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
if (ret < min_uV || ret > max_uV) if (ret < min_uV || ret > max_uV)
return -EINVAL; return -EINVAL;
*selector = vsel;
return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel); return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel);
} }
static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev, static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
int reg = ldo->base + WM831X_LDO_ON_CONTROL; int reg = ldo->base + WM831X_LDO_ON_CONTROL;
return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV); return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
selector);
} }
static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
@ -150,11 +155,12 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
unsigned int selector;
return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV); return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
} }
static int wm831x_gp_ldo_get_voltage(struct regulator_dev *rdev) static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
@ -167,7 +173,7 @@ static int wm831x_gp_ldo_get_voltage(struct regulator_dev *rdev)
ret &= WM831X_LDO1_ON_VSEL_MASK; ret &= WM831X_LDO1_ON_VSEL_MASK;
return wm831x_gp_ldo_list_voltage(rdev, ret); return ret;
} }
static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev) static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)
@ -287,7 +293,7 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
static struct regulator_ops wm831x_gp_ldo_ops = { static struct regulator_ops wm831x_gp_ldo_ops = {
.list_voltage = wm831x_gp_ldo_list_voltage, .list_voltage = wm831x_gp_ldo_list_voltage,
.get_voltage = wm831x_gp_ldo_get_voltage, .get_voltage_sel = wm831x_gp_ldo_get_voltage_sel,
.set_voltage = wm831x_gp_ldo_set_voltage, .set_voltage = wm831x_gp_ldo_set_voltage,
.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
.get_mode = wm831x_gp_ldo_get_mode, .get_mode = wm831x_gp_ldo_get_mode,
@ -413,7 +419,8 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
} }
static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg, static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
@ -433,16 +440,19 @@ static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
if (ret < min_uV || ret > max_uV) if (ret < min_uV || ret > max_uV)
return -EINVAL; return -EINVAL;
*selector = vsel;
return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel); return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel);
} }
static int wm831x_aldo_set_voltage(struct regulator_dev *rdev, static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
int reg = ldo->base + WM831X_LDO_ON_CONTROL; int reg = ldo->base + WM831X_LDO_ON_CONTROL;
return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV); return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
selector);
} }
static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
@ -450,11 +460,12 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
unsigned int selector;
return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV); return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector);
} }
static int wm831x_aldo_get_voltage(struct regulator_dev *rdev) static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
@ -467,7 +478,7 @@ static int wm831x_aldo_get_voltage(struct regulator_dev *rdev)
ret &= WM831X_LDO7_ON_VSEL_MASK; ret &= WM831X_LDO7_ON_VSEL_MASK;
return wm831x_aldo_list_voltage(rdev, ret); return ret;
} }
static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
@ -548,7 +559,7 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
static struct regulator_ops wm831x_aldo_ops = { static struct regulator_ops wm831x_aldo_ops = {
.list_voltage = wm831x_aldo_list_voltage, .list_voltage = wm831x_aldo_list_voltage,
.get_voltage = wm831x_aldo_get_voltage, .get_voltage_sel = wm831x_aldo_get_voltage_sel,
.set_voltage = wm831x_aldo_set_voltage, .set_voltage = wm831x_aldo_set_voltage,
.set_suspend_voltage = wm831x_aldo_set_suspend_voltage, .set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
.get_mode = wm831x_aldo_get_mode, .get_mode = wm831x_aldo_get_mode,
@ -666,7 +677,8 @@ static int wm831x_alive_ldo_list_voltage(struct regulator_dev *rdev,
static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
int reg, int reg,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
@ -680,16 +692,20 @@ static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
if (ret < min_uV || ret > max_uV) if (ret < min_uV || ret > max_uV)
return -EINVAL; return -EINVAL;
*selector = vsel;
return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel); return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel);
} }
static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev, static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV,
unsigned *selector)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV); return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
selector);
} }
static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
@ -697,11 +713,12 @@ static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL; int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
unsigned selector;
return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV); return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
} }
static int wm831x_alive_ldo_get_voltage(struct regulator_dev *rdev) static int wm831x_alive_ldo_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
@ -714,7 +731,7 @@ static int wm831x_alive_ldo_get_voltage(struct regulator_dev *rdev)
ret &= WM831X_LDO11_ON_VSEL_MASK; ret &= WM831X_LDO11_ON_VSEL_MASK;
return wm831x_alive_ldo_list_voltage(rdev, ret); return ret;
} }
static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
@ -736,7 +753,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
static struct regulator_ops wm831x_alive_ldo_ops = { static struct regulator_ops wm831x_alive_ldo_ops = {
.list_voltage = wm831x_alive_ldo_list_voltage, .list_voltage = wm831x_alive_ldo_list_voltage,
.get_voltage = wm831x_alive_ldo_get_voltage, .get_voltage_sel = wm831x_alive_ldo_get_voltage_sel,
.set_voltage = wm831x_alive_ldo_set_voltage, .set_voltage = wm831x_alive_ldo_set_voltage,
.set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
.get_status = wm831x_alive_ldo_get_status, .get_status = wm831x_alive_ldo_get_status,

View file

@ -360,7 +360,7 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
EXPORT_SYMBOL_GPL(wm8350_isink_set_flash); EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV) int max_uV, unsigned *selector)
{ {
struct wm8350 *wm8350 = rdev_get_drvdata(rdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
int volt_reg, dcdc = rdev_get_id(rdev), mV, int volt_reg, dcdc = rdev_get_id(rdev), mV,
@ -397,17 +397,18 @@ static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
return -EINVAL; return -EINVAL;
} }
*selector = mV;
/* all DCDCs have same mV bits */ /* all DCDCs have same mV bits */
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
wm8350_reg_write(wm8350, volt_reg, val | mV); wm8350_reg_write(wm8350, volt_reg, val | mV);
return 0; return 0;
} }
static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev) static int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm8350 *wm8350 = rdev_get_drvdata(rdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
int volt_reg, dcdc = rdev_get_id(rdev); int volt_reg, dcdc = rdev_get_id(rdev);
u16 val;
switch (dcdc) { switch (dcdc) {
case WM8350_DCDC_1: case WM8350_DCDC_1:
@ -429,8 +430,7 @@ static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
} }
/* all DCDCs have same mV bits */ /* all DCDCs have same mV bits */
val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK; return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
return wm8350_dcdc_val_to_mvolts(val) * 1000;
} }
static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev, static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
@ -754,7 +754,7 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
} }
static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV) int max_uV, unsigned *selector)
{ {
struct wm8350 *wm8350 = rdev_get_drvdata(rdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000, int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
@ -797,17 +797,18 @@ static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
return -EINVAL; return -EINVAL;
} }
*selector = mV;
/* all LDOs have same mV bits */ /* all LDOs have same mV bits */
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
wm8350_reg_write(wm8350, volt_reg, val | mV); wm8350_reg_write(wm8350, volt_reg, val | mV);
return 0; return 0;
} }
static int wm8350_ldo_get_voltage(struct regulator_dev *rdev) static int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm8350 *wm8350 = rdev_get_drvdata(rdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
int volt_reg, ldo = rdev_get_id(rdev); int volt_reg, ldo = rdev_get_id(rdev);
u16 val;
switch (ldo) { switch (ldo) {
case WM8350_LDO_1: case WM8350_LDO_1:
@ -827,8 +828,7 @@ static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
} }
/* all LDOs have same mV bits */ /* all LDOs have same mV bits */
val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK; return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
return wm8350_ldo_val_to_mvolts(val) * 1000;
} }
static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
@ -1225,7 +1225,7 @@ static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
static struct regulator_ops wm8350_dcdc_ops = { static struct regulator_ops wm8350_dcdc_ops = {
.set_voltage = wm8350_dcdc_set_voltage, .set_voltage = wm8350_dcdc_set_voltage,
.get_voltage = wm8350_dcdc_get_voltage, .get_voltage_sel = wm8350_dcdc_get_voltage_sel,
.list_voltage = wm8350_dcdc_list_voltage, .list_voltage = wm8350_dcdc_list_voltage,
.enable = wm8350_dcdc_enable, .enable = wm8350_dcdc_enable,
.disable = wm8350_dcdc_disable, .disable = wm8350_dcdc_disable,
@ -1249,7 +1249,7 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
static struct regulator_ops wm8350_ldo_ops = { static struct regulator_ops wm8350_ldo_ops = {
.set_voltage = wm8350_ldo_set_voltage, .set_voltage = wm8350_ldo_set_voltage,
.get_voltage = wm8350_ldo_get_voltage, .get_voltage_sel = wm8350_ldo_get_voltage_sel,
.list_voltage = wm8350_ldo_list_voltage, .list_voltage = wm8350_ldo_list_voltage,
.enable = wm8350_ldo_enable, .enable = wm8350_ldo_enable,
.disable = wm8350_ldo_disable, .disable = wm8350_ldo_disable,

View file

@ -67,7 +67,7 @@ static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
} }
static int wm8400_ldo_set_voltage(struct regulator_dev *dev, static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct wm8400 *wm8400 = rdev_get_drvdata(dev); struct wm8400 *wm8400 = rdev_get_drvdata(dev);
u16 val; u16 val;
@ -93,6 +93,8 @@ static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
val += 0xf; val += 0xf;
} }
*selector = val;
return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
WM8400_LDO1_VSEL_MASK, val); WM8400_LDO1_VSEL_MASK, val);
} }
@ -156,7 +158,7 @@ static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
} }
static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *selector)
{ {
struct wm8400 *wm8400 = rdev_get_drvdata(dev); struct wm8400 *wm8400 = rdev_get_drvdata(dev);
u16 val; u16 val;
@ -171,6 +173,8 @@ static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
return -EINVAL; return -EINVAL;
BUG_ON(850000 + (25000 * val) < min_uV); BUG_ON(850000 + (25000 * val) < min_uV);
*selector = val;
return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
WM8400_DC1_VSEL_MASK, val); WM8400_DC1_VSEL_MASK, val);
} }

View file

@ -86,7 +86,7 @@ static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
return (selector * 100000) + 2400000; return (selector * 100000) + 2400000;
} }
static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev) static int wm8994_ldo1_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
int val; int val;
@ -95,13 +95,11 @@ static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev)
if (val < 0) if (val < 0)
return val; return val;
val = (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT; return (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT;
return wm8994_ldo1_list_voltage(rdev, val);
} }
static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev, static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *s)
{ {
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
int selector, v; int selector, v;
@ -111,6 +109,7 @@ static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev,
if (v < 0 || v > max_uV) if (v < 0 || v > max_uV)
return -EINVAL; return -EINVAL;
*s = selector;
selector <<= WM8994_LDO1_VSEL_SHIFT; selector <<= WM8994_LDO1_VSEL_SHIFT;
return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1, return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1,
@ -124,7 +123,7 @@ static struct regulator_ops wm8994_ldo1_ops = {
.enable_time = wm8994_ldo_enable_time, .enable_time = wm8994_ldo_enable_time,
.list_voltage = wm8994_ldo1_list_voltage, .list_voltage = wm8994_ldo1_list_voltage,
.get_voltage = wm8994_ldo1_get_voltage, .get_voltage_sel = wm8994_ldo1_get_voltage_sel,
.set_voltage = wm8994_ldo1_set_voltage, .set_voltage = wm8994_ldo1_set_voltage,
}; };
@ -137,7 +136,7 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
return (selector * 100000) + 900000; return (selector * 100000) + 900000;
} }
static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev) static int wm8994_ldo2_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
int val; int val;
@ -146,13 +145,11 @@ static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev)
if (val < 0) if (val < 0)
return val; return val;
val = (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT; return (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT;
return wm8994_ldo2_list_voltage(rdev, val);
} }
static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev, static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV, unsigned *s)
{ {
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
int selector, v; int selector, v;
@ -162,6 +159,7 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
if (v < 0 || v > max_uV) if (v < 0 || v > max_uV)
return -EINVAL; return -EINVAL;
*s = selector;
selector <<= WM8994_LDO2_VSEL_SHIFT; selector <<= WM8994_LDO2_VSEL_SHIFT;
return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2, return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2,
@ -175,7 +173,7 @@ static struct regulator_ops wm8994_ldo2_ops = {
.enable_time = wm8994_ldo_enable_time, .enable_time = wm8994_ldo_enable_time,
.list_voltage = wm8994_ldo2_list_voltage, .list_voltage = wm8994_ldo2_list_voltage,
.get_voltage = wm8994_ldo2_get_voltage, .get_voltage_sel = wm8994_ldo2_get_voltage_sel,
.set_voltage = wm8994_ldo2_set_voltage, .set_voltage = wm8994_ldo2_set_voltage,
}; };

View file

@ -99,8 +99,6 @@
#define AB8500_NR_IRQS 104 #define AB8500_NR_IRQS 104
#define AB8500_NUM_IRQ_REGS 13 #define AB8500_NUM_IRQ_REGS 13
#define AB8500_NUM_REGULATORS 15
/** /**
* struct ab8500 - ab8500 internal structure * struct ab8500 - ab8500 internal structure
* @dev: parent device * @dev: parent device
@ -145,7 +143,8 @@ struct regulator_init_data;
struct ab8500_platform_data { struct ab8500_platform_data {
int irq_base; int irq_base;
void (*init) (struct ab8500 *); void (*init) (struct ab8500 *);
struct regulator_init_data *regulator[AB8500_NUM_REGULATORS]; int num_regulator;
struct regulator_init_data *regulator;
}; };
extern int __devinit ab8500_init(struct ab8500 *ab8500); extern int __devinit ab8500_init(struct ab8500 *ab8500);

View file

@ -1,4 +1,5 @@
/* /*
* Copyright 2010 Yong Shen <yong.shen@linaro.org>
* Copyright 2009-2010 Pengutronix * Copyright 2009-2010 Pengutronix
* Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
* *
@ -122,39 +123,39 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
unsigned int channel, unsigned int *sample); unsigned int channel, unsigned int *sample);
#define MC13783_SW_SW1A 0 #define MC13783_REG_SW1A 0
#define MC13783_SW_SW1B 1 #define MC13783_REG_SW1B 1
#define MC13783_SW_SW2A 2 #define MC13783_REG_SW2A 2
#define MC13783_SW_SW2B 3 #define MC13783_REG_SW2B 3
#define MC13783_SW_SW3 4 #define MC13783_REG_SW3 4
#define MC13783_SW_PLL 5 #define MC13783_REG_PLL 5
#define MC13783_REGU_VAUDIO 6 #define MC13783_REG_VAUDIO 6
#define MC13783_REGU_VIOHI 7 #define MC13783_REG_VIOHI 7
#define MC13783_REGU_VIOLO 8 #define MC13783_REG_VIOLO 8
#define MC13783_REGU_VDIG 9 #define MC13783_REG_VDIG 9
#define MC13783_REGU_VGEN 10 #define MC13783_REG_VGEN 10
#define MC13783_REGU_VRFDIG 11 #define MC13783_REG_VRFDIG 11
#define MC13783_REGU_VRFREF 12 #define MC13783_REG_VRFREF 12
#define MC13783_REGU_VRFCP 13 #define MC13783_REG_VRFCP 13
#define MC13783_REGU_VSIM 14 #define MC13783_REG_VSIM 14
#define MC13783_REGU_VESIM 15 #define MC13783_REG_VESIM 15
#define MC13783_REGU_VCAM 16 #define MC13783_REG_VCAM 16
#define MC13783_REGU_VRFBG 17 #define MC13783_REG_VRFBG 17
#define MC13783_REGU_VVIB 18 #define MC13783_REG_VVIB 18
#define MC13783_REGU_VRF1 19 #define MC13783_REG_VRF1 19
#define MC13783_REGU_VRF2 20 #define MC13783_REG_VRF2 20
#define MC13783_REGU_VMMC1 21 #define MC13783_REG_VMMC1 21
#define MC13783_REGU_VMMC2 22 #define MC13783_REG_VMMC2 22
#define MC13783_REGU_GPO1 23 #define MC13783_REG_GPO1 23
#define MC13783_REGU_GPO2 24 #define MC13783_REG_GPO2 24
#define MC13783_REGU_GPO3 25 #define MC13783_REG_GPO3 25
#define MC13783_REGU_GPO4 26 #define MC13783_REG_GPO4 26
#define MC13783_REGU_V1 27 #define MC13783_REG_V1 27
#define MC13783_REGU_V2 28 #define MC13783_REG_V2 28
#define MC13783_REGU_V3 29 #define MC13783_REG_V3 29
#define MC13783_REGU_V4 30 #define MC13783_REG_V4 30
#define MC13783_REGU_PWGT1SPI 31 #define MC13783_REG_PWGT1SPI 31
#define MC13783_REGU_PWGT2SPI 32 #define MC13783_REG_PWGT2SPI 32
#define MC13783_IRQ_ADCDONE MC13XXX_IRQ_ADCDONE #define MC13783_IRQ_ADCDONE MC13XXX_IRQ_ADCDONE
#define MC13783_IRQ_ADCBISDONE MC13XXX_IRQ_ADCBISDONE #define MC13783_IRQ_ADCBISDONE MC13XXX_IRQ_ADCBISDONE

View file

@ -0,0 +1,39 @@
/*
* Copyright 2010 Yong Shen <yong.shen@linaro.org>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
#ifndef __LINUX_MFD_MC13892_H
#define __LINUX_MFD_MC13892_H
#include <linux/mfd/mc13xxx.h>
#define MC13892_SW1 0
#define MC13892_SW2 1
#define MC13892_SW3 2
#define MC13892_SW4 3
#define MC13892_SWBST 4
#define MC13892_VIOHI 5
#define MC13892_VPLL 6
#define MC13892_VDIG 7
#define MC13892_VSD 8
#define MC13892_VUSB2 9
#define MC13892_VVIDEO 10
#define MC13892_VAUDIO 11
#define MC13892_VCAM 12
#define MC13892_VGEN1 13
#define MC13892_VGEN2 14
#define MC13892_VGEN3 15
#define MC13892_VUSB 16
#define MC13892_GPO1 17
#define MC13892_GPO2 18
#define MC13892_GPO3 19
#define MC13892_GPO4 20
#define MC13892_PWGT1SPI 21
#define MC13892_PWGT2SPI 22
#define MC13892_VCOINCELL 23
#endif

View file

@ -11,15 +11,17 @@
#define __LINUX_MFD_AB8500_REGULATOR_H #define __LINUX_MFD_AB8500_REGULATOR_H
/* AB8500 regulators */ /* AB8500 regulators */
#define AB8500_LDO_AUX1 0 enum ab8500_regulator_id {
#define AB8500_LDO_AUX2 1 AB8500_LDO_AUX1,
#define AB8500_LDO_AUX3 2 AB8500_LDO_AUX2,
#define AB8500_LDO_INTCORE 3 AB8500_LDO_AUX3,
#define AB8500_LDO_TVOUT 4 AB8500_LDO_INTCORE,
#define AB8500_LDO_AUDIO 5 AB8500_LDO_TVOUT,
#define AB8500_LDO_ANAMIC1 6 AB8500_LDO_AUDIO,
#define AB8500_LDO_ANAMIC2 7 AB8500_LDO_ANAMIC1,
#define AB8500_LDO_DMIC 8 AB8500_LDO_ANAMIC2,
#define AB8500_LDO_ANA 9 AB8500_LDO_DMIC,
AB8500_LDO_ANA,
AB8500_NUM_REGULATORS,
};
#endif #endif

View file

@ -154,6 +154,7 @@ int regulator_is_supported_voltage(struct regulator *regulator,
int min_uV, int max_uV); int min_uV, int max_uV);
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV); int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
int regulator_get_voltage(struct regulator *regulator); int regulator_get_voltage(struct regulator *regulator);
int regulator_sync_voltage(struct regulator *regulator);
int regulator_set_current_limit(struct regulator *regulator, int regulator_set_current_limit(struct regulator *regulator,
int min_uA, int max_uA); int min_uA, int max_uA);
int regulator_get_current_limit(struct regulator *regulator); int regulator_get_current_limit(struct regulator *regulator);

View file

@ -42,7 +42,11 @@ enum regulator_status {
* *
* @set_voltage: Set the voltage for the regulator within the range specified. * @set_voltage: Set the voltage for the regulator within the range specified.
* The driver should select the voltage closest to min_uV. * The driver should select the voltage closest to min_uV.
* @set_voltage_sel: Set the voltage for the regulator using the specified
* selector.
* @get_voltage: Return the currently configured voltage for the regulator. * @get_voltage: Return the currently configured voltage for the regulator.
* @get_voltage_sel: Return the currently configured voltage selector for the
* regulator.
* @list_voltage: Return one of the supported voltages, in microvolts; zero * @list_voltage: Return one of the supported voltages, in microvolts; zero
* if the selector indicates a voltage that is unusable on this system; * if the selector indicates a voltage that is unusable on this system;
* or negative errno. Selectors range from zero to one less than * or negative errno. Selectors range from zero to one less than
@ -79,8 +83,11 @@ struct regulator_ops {
int (*list_voltage) (struct regulator_dev *, unsigned selector); int (*list_voltage) (struct regulator_dev *, unsigned selector);
/* get/set regulator voltage */ /* get/set regulator voltage */
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV); int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,
unsigned *selector);
int (*set_voltage_sel) (struct regulator_dev *, unsigned selector);
int (*get_voltage) (struct regulator_dev *); int (*get_voltage) (struct regulator_dev *);
int (*get_voltage_sel) (struct regulator_dev *);
/* get/set regulator current */ /* get/set regulator current */
int (*set_current_limit) (struct regulator_dev *, int (*set_current_limit) (struct regulator_dev *,
@ -168,9 +175,9 @@ struct regulator_desc {
*/ */
struct regulator_dev { struct regulator_dev {
struct regulator_desc *desc; struct regulator_desc *desc;
int use_count;
int open_count;
int exclusive; int exclusive;
u32 use_count;
u32 open_count;
/* lists we belong to */ /* lists we belong to */
struct list_head list; /* list of all regulators */ struct list_head list; /* list of all regulators */
@ -188,10 +195,14 @@ struct regulator_dev {
struct regulator_dev *supply; /* for tree */ struct regulator_dev *supply; /* for tree */
void *reg_data; /* regulator_dev data */ void *reg_data; /* regulator_dev data */
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
}; };
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
struct device *dev, struct regulator_init_data *init_data, struct device *dev, const struct regulator_init_data *init_data,
void *driver_data); void *driver_data);
void regulator_unregister(struct regulator_dev *rdev); void regulator_unregister(struct regulator_dev *rdev);

View file

@ -0,0 +1,141 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM regulator
#if !defined(_TRACE_REGULATOR_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_REGULATOR_H
#include <linux/ktime.h>
#include <linux/tracepoint.h>
/*
* Events which just log themselves and the regulator name for enable/disable
* type tracking.
*/
DECLARE_EVENT_CLASS(regulator_basic,
TP_PROTO(const char *name),
TP_ARGS(name),
TP_STRUCT__entry(
__string( name, name )
),
TP_fast_assign(
__assign_str(name, name);
),
TP_printk("name=%s", __get_str(name))
);
DEFINE_EVENT(regulator_basic, regulator_enable,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_enable_delay,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_enable_complete,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_disable,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_disable_complete,
TP_PROTO(const char *name),
TP_ARGS(name)
);
/*
* Events that take a range of numerical values, mostly for voltages
* and so on.
*/
DECLARE_EVENT_CLASS(regulator_range,
TP_PROTO(const char *name, int min, int max),
TP_ARGS(name, min, max),
TP_STRUCT__entry(
__string( name, name )
__field( int, min )
__field( int, max )
),
TP_fast_assign(
__assign_str(name, name);
__entry->min = min;
__entry->max = max;
),
TP_printk("name=%s (%d-%d)", __get_str(name),
(int)__entry->min, (int)__entry->max)
);
DEFINE_EVENT(regulator_range, regulator_set_voltage,
TP_PROTO(const char *name, int min, int max),
TP_ARGS(name, min, max)
);
/*
* Events that take a single value, mostly for readback and refcounts.
*/
DECLARE_EVENT_CLASS(regulator_value,
TP_PROTO(const char *name, unsigned int val),
TP_ARGS(name, val),
TP_STRUCT__entry(
__string( name, name )
__field( unsigned int, val )
),
TP_fast_assign(
__assign_str(name, name);
__entry->val = val;
),
TP_printk("name=%s, val=%u", __get_str(name),
(int)__entry->val)
);
DEFINE_EVENT(regulator_value, regulator_set_voltage_complete,
TP_PROTO(const char *name, unsigned int value),
TP_ARGS(name, value)
);
#endif /* _TRACE_POWER_H */
/* This part must be outside protection */
#include <trace/define_trace.h>