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:
commit
1896a1346a
45 changed files with 2970 additions and 843 deletions
|
@ -254,10 +254,10 @@ static struct regulator_init_data cam_data = {
|
|||
|
||||
static struct mc13783_regulator_init_data pcm038_regulators[] = {
|
||||
{
|
||||
.id = MC13783_REGU_VCAM,
|
||||
.id = MC13783_REG_VCAM,
|
||||
.init_data = &cam_data,
|
||||
}, {
|
||||
.id = MC13783_REGU_VMMC1,
|
||||
.id = MC13783_REG_VMMC1,
|
||||
.init_data = &sdhc1_data,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -140,10 +140,10 @@ static struct regulator_init_data gpo_init = {
|
|||
|
||||
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,
|
||||
}, {
|
||||
.id = MC13783_REGU_PWGT2SPI, /* Power Gate for L2 Cache. */
|
||||
.id = MC13783_REG_PWGT2SPI, /* Power Gate for L2 Cache. */
|
||||
.init_data = &pwgtx_init,
|
||||
}, {
|
||||
|
||||
|
|
|
@ -216,11 +216,11 @@ static struct regulator_init_data cam_vreg_data = {
|
|||
|
||||
static struct mc13783_regulator_init_data moboard_regulators[] = {
|
||||
{
|
||||
.id = MC13783_REGU_VMMC1,
|
||||
.id = MC13783_REG_VMMC1,
|
||||
.init_data = &sdhc_vreg_data,
|
||||
},
|
||||
{
|
||||
.id = MC13783_REGU_VCAM,
|
||||
.id = MC13783_REG_VCAM,
|
||||
.init_data = &cam_vreg_data,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,99 +3,94 @@
|
|||
*
|
||||
* 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
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/ab8500.h>
|
||||
|
||||
/* supplies to the display/camera */
|
||||
static struct regulator_init_data ab8500_vaux1_regulator = {
|
||||
.constraints = {
|
||||
.name = "V-DISPLAY",
|
||||
.min_uV = 2500000,
|
||||
.max_uV = 2900000,
|
||||
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
|
||||
REGULATOR_CHANGE_STATUS,
|
||||
/* AB8500 regulators */
|
||||
struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
/* supplies to the display/camera */
|
||||
[AB8500_LDO_AUX1] = {
|
||||
.constraints = {
|
||||
.name = "V-DISPLAY",
|
||||
.min_uV = 2500000,
|
||||
.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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
19
arch/arm/mach-ux500/board-mop500-regulators.h
Normal file
19
arch/arm/mach-ux500/board-mop500-regulators.h
Normal 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
|
|
@ -35,6 +35,7 @@
|
|||
#include "devices-db8500.h"
|
||||
#include "pins-db8500.h"
|
||||
#include "board-mop500.h"
|
||||
#include "board-mop500-regulators.h"
|
||||
|
||||
static pin_cfg_t mop500_pins[] = {
|
||||
/* SSP0 */
|
||||
|
@ -80,6 +81,8 @@ static pin_cfg_t mop500_pins[] = {
|
|||
|
||||
static struct ab8500_platform_data ab8500_platdata = {
|
||||
.irq_base = MOP500_AB8500_IRQ_BASE,
|
||||
.regulator = ab8500_regulators,
|
||||
.num_regulator = ARRAY_SIZE(ab8500_regulators),
|
||||
};
|
||||
|
||||
static struct resource ab8500_resources[] = {
|
||||
|
|
|
@ -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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
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);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
*selector = ret;
|
||||
val = (uint8_t)(ret << info->vol_shift);
|
||||
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
|
||||
|
||||
|
|
|
@ -186,13 +186,25 @@ config REGULATOR_PCAP
|
|||
This driver provides support for the voltage regulators of the
|
||||
PCAP2 PMIC.
|
||||
|
||||
config REGULATOR_MC13XXX_CORE
|
||||
tristate
|
||||
|
||||
config REGULATOR_MC13783
|
||||
tristate "Support regulators on Freescale MC13783 PMIC"
|
||||
depends on MFD_MC13783
|
||||
select REGULATOR_MC13XXX_CORE
|
||||
help
|
||||
Say y here to support the regulators found on the Freescale MC13783
|
||||
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
|
||||
tristate "ST-Ericsson AB3100 Regulator functions"
|
||||
depends on AB3100_CORE
|
||||
|
@ -250,5 +262,15 @@ config REGULATOR_TPS6586X
|
|||
help
|
||||
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
|
||||
|
||||
|
|
|
@ -30,10 +30,13 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
|||
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCAP) += pcap-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_TPS65023) += tps65023-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_ISL6271A) += isl6271a-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
|
||||
|
|
|
@ -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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
u8 regval;
|
||||
|
@ -373,6 +374,8 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
|
|||
if (bestindex < 0)
|
||||
return bestindex;
|
||||
|
||||
*selector = bestindex;
|
||||
|
||||
err = abx500_get_register_interruptible(abreg->dev, 0,
|
||||
abreg->regreg, ®val);
|
||||
if (err) {
|
||||
|
|
|
@ -3,18 +3,13 @@
|
|||
*
|
||||
* 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 supports the following regulators,
|
||||
* LDOs - VAUDIO, VANAMIC2/2, VDIGMIC, VINTCORE12, VTVOUT,
|
||||
* 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
|
||||
*
|
||||
* AB8500 supports the following regulators:
|
||||
* VAUX1/2/3, VINTCORE, VTVOUT, VAUDIO, VAMIC1/2, VDMIC, VANA
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -28,38 +23,37 @@
|
|||
|
||||
/**
|
||||
* struct ab8500_regulator_info - ab8500 regulator information
|
||||
* @dev: device pointer
|
||||
* @desc: regulator description
|
||||
* @ab8500: ab8500 parent
|
||||
* @regulator_dev: regulator device
|
||||
* @max_uV: maximum voltage (for variable voltage supplies)
|
||||
* @min_uV: minimum voltage (for variable voltage supplies)
|
||||
* @fixed_uV: typical voltage (for fixed voltage supplies)
|
||||
* @update_bank: bank to control on/off
|
||||
* @update_reg: register to control on/off
|
||||
* @mask: mask to enable/disable regulator
|
||||
* @enable: bits to enable the regulator in normal(high power) mode
|
||||
* @update_mask: mask to enable/disable regulator
|
||||
* @update_val_enable: bits to enable the regulator in normal (high power) mode
|
||||
* @voltage_bank: bank to control regulator voltage
|
||||
* @voltage_reg: register 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
|
||||
*/
|
||||
struct ab8500_regulator_info {
|
||||
struct device *dev;
|
||||
struct regulator_desc desc;
|
||||
struct ab8500 *ab8500;
|
||||
struct regulator_dev *regulator;
|
||||
int max_uV;
|
||||
int min_uV;
|
||||
int fixed_uV;
|
||||
u8 update_bank;
|
||||
u8 update_reg;
|
||||
u8 mask;
|
||||
u8 enable;
|
||||
u8 update_mask;
|
||||
u8 update_val_enable;
|
||||
u8 voltage_bank;
|
||||
u8 voltage_reg;
|
||||
u8 voltage_mask;
|
||||
int const *supported_voltages;
|
||||
int const *voltages;
|
||||
int voltages_len;
|
||||
};
|
||||
|
||||
|
@ -83,6 +77,17 @@ static const int ldo_vauxn_voltages[] = {
|
|||
3300000,
|
||||
};
|
||||
|
||||
static const int ldo_vaux3_voltages[] = {
|
||||
1200000,
|
||||
1500000,
|
||||
1800000,
|
||||
2100000,
|
||||
2500000,
|
||||
2750000,
|
||||
2790000,
|
||||
2910000,
|
||||
};
|
||||
|
||||
static const int ldo_vintcore_voltages[] = {
|
||||
1200000,
|
||||
1225000,
|
||||
|
@ -95,57 +100,80 @@ static const int ldo_vintcore_voltages[] = {
|
|||
|
||||
static int ab8500_regulator_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
int regulator_id, ret;
|
||||
int ret;
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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)
|
||||
dev_err(rdev_get_dev(rdev),
|
||||
"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;
|
||||
}
|
||||
|
||||
static int ab8500_regulator_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
int regulator_id, ret;
|
||||
int ret;
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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)
|
||||
dev_err(rdev_get_dev(rdev),
|
||||
"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;
|
||||
}
|
||||
|
||||
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);
|
||||
u8 value;
|
||||
u8 regval;
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = abx500_get_register_interruptible(info->dev,
|
||||
info->update_bank, info->update_reg, &value);
|
||||
info->update_bank, info->update_reg, ®val);
|
||||
if (ret < 0) {
|
||||
dev_err(rdev_get_dev(rdev),
|
||||
"couldn't read 0x%x register\n", info->update_reg);
|
||||
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;
|
||||
else
|
||||
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)
|
||||
{
|
||||
int regulator_id;
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* return the uV for the fixed regulators */
|
||||
if (info->fixed_uV)
|
||||
|
@ -167,33 +195,40 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
|
|||
if (selector >= info->voltages_len)
|
||||
return -EINVAL;
|
||||
|
||||
return info->supported_voltages[selector];
|
||||
return info->voltages[selector];
|
||||
}
|
||||
|
||||
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);
|
||||
u8 value;
|
||||
u8 regval;
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = abx500_get_register_interruptible(info->dev, info->voltage_bank,
|
||||
info->voltage_reg, &value);
|
||||
ret = abx500_get_register_interruptible(info->dev,
|
||||
info->voltage_bank, info->voltage_reg, ®val);
|
||||
if (ret < 0) {
|
||||
dev_err(rdev_get_dev(rdev),
|
||||
"couldn't read voltage reg for regulator\n");
|
||||
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 */
|
||||
value &= info->voltage_mask;
|
||||
if (regulator_id == AB8500_LDO_INTCORE)
|
||||
ret = info->supported_voltages[value >> 0x3];
|
||||
val = regval & info->voltage_mask;
|
||||
if (info->desc.id == AB8500_LDO_INTCORE)
|
||||
ret = info->voltages[val >> 0x3];
|
||||
else
|
||||
ret = info->supported_voltages[value];
|
||||
ret = info->voltages[val];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -206,8 +241,8 @@ static int ab8500_get_best_voltage_index(struct regulator_dev *rdev,
|
|||
|
||||
/* check the supported voltage */
|
||||
for (i = 0; i < info->voltages_len; i++) {
|
||||
if ((info->supported_voltages[i] >= min_uV) &&
|
||||
(info->supported_voltages[i] <= max_uV))
|
||||
if ((info->voltages[i] >= min_uV) &&
|
||||
(info->voltages[i] <= max_uV))
|
||||
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,
|
||||
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);
|
||||
u8 regval;
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get the appropriate voltages within the range */
|
||||
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;
|
||||
}
|
||||
|
||||
*selector = ret;
|
||||
|
||||
/* set the registers for the request */
|
||||
regval = (u8)ret;
|
||||
ret = abx500_mask_and_set_register_interruptible(info->dev,
|
||||
info->voltage_bank, info->voltage_reg,
|
||||
info->voltage_mask, (u8)ret);
|
||||
info->voltage_bank, info->voltage_reg,
|
||||
info->voltage_mask, regval);
|
||||
if (ret < 0)
|
||||
dev_err(rdev_get_dev(rdev),
|
||||
"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;
|
||||
}
|
||||
|
||||
|
@ -254,17 +301,17 @@ static struct regulator_ops ab8500_regulator_ops = {
|
|||
|
||||
static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
int regulator_id;
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= AB8500_NUM_REGULATORS)
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return info->fixed_uV;
|
||||
}
|
||||
|
||||
static struct regulator_ops ab8500_ldo_fixed_ops = {
|
||||
static struct regulator_ops ab8500_regulator_fixed_ops = {
|
||||
.enable = ab8500_regulator_enable,
|
||||
.disable = ab8500_regulator_disable,
|
||||
.is_enabled = ab8500_regulator_is_enabled,
|
||||
|
@ -272,89 +319,198 @@ static struct regulator_ops ab8500_ldo_fixed_ops = {
|
|||
.list_voltage = ab8500_list_voltage,
|
||||
};
|
||||
|
||||
#define AB8500_LDO(_id, min, max, bank, reg, reg_mask, \
|
||||
reg_enable, volt_bank, volt_reg, volt_mask, \
|
||||
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[] = {
|
||||
static struct ab8500_regulator_info
|
||||
ab8500_regulator_info[AB8500_NUM_REGULATORS] = {
|
||||
/*
|
||||
* Variable Voltage LDOs
|
||||
* name, min uV, max uV, ctrl bank, ctrl reg, reg mask, enable mask,
|
||||
* volt ctrl bank, volt ctrl reg, volt ctrl mask, volt table,
|
||||
* num supported volts
|
||||
* Variable Voltage Regulators
|
||||
* name, min mV, max mV,
|
||||
* update bank, reg, mask, enable val
|
||||
* volt bank, reg, mask, table, table length
|
||||
*/
|
||||
AB8500_LDO(AUX1, 1100, 3300, 0x04, 0x09, 0x3, 0x1, 0x04, 0x1f, 0xf,
|
||||
ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
|
||||
AB8500_LDO(AUX2, 1100, 3300, 0x04, 0x09, 0xc, 0x4, 0x04, 0x20, 0xf,
|
||||
ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
|
||||
AB8500_LDO(AUX3, 1100, 3300, 0x04, 0x0a, 0x3, 0x1, 0x04, 0x21, 0xf,
|
||||
ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
|
||||
AB8500_LDO(INTCORE, 1100, 3300, 0x03, 0x80, 0x4, 0x4, 0x03, 0x80, 0x38,
|
||||
ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)),
|
||||
[AB8500_LDO_AUX1] = {
|
||||
.desc = {
|
||||
.name = "LDO-AUX1",
|
||||
.ops = &ab8500_regulator_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.id = AB8500_LDO_AUX1,
|
||||
.owner = THIS_MODULE,
|
||||
.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
|
||||
* name, o/p uV, ctrl bank, ctrl reg, enable, disable
|
||||
* Fixed Voltage Regulators
|
||||
* name, fixed mV,
|
||||
* update bank, reg, mask, enable val
|
||||
*/
|
||||
AB8500_FIXED_LDO(TVOUT, 2000, 0x03, 0x80, 0x2, 0x2),
|
||||
AB8500_FIXED_LDO(AUDIO, 2000, 0x03, 0x83, 0x2, 0x2),
|
||||
AB8500_FIXED_LDO(ANAMIC1, 2050, 0x03, 0x83, 0x4, 0x4),
|
||||
AB8500_FIXED_LDO(ANAMIC2, 2050, 0x03, 0x83, 0x8, 0x8),
|
||||
AB8500_FIXED_LDO(DMIC, 1800, 0x03, 0x83, 0x10, 0x10),
|
||||
AB8500_FIXED_LDO(ANA, 1200, 0x03, 0x83, 0xc, 0x4),
|
||||
[AB8500_LDO_TVOUT] = {
|
||||
.desc = {
|
||||
.name = "LDO-TVOUT",
|
||||
.ops = &ab8500_regulator_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
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 */
|
||||
info = &ab8500_regulator_info[i];
|
||||
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,
|
||||
pdata->regulator[i], info);
|
||||
&pdata->regulator[i], info);
|
||||
if (IS_ERR(info->regulator)) {
|
||||
err = PTR_ERR(info->regulator);
|
||||
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;
|
||||
}
|
||||
|
||||
dev_vdbg(rdev_get_dev(info->regulator),
|
||||
"%s-probed\n", info->desc.name);
|
||||
}
|
||||
|
||||
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++) {
|
||||
struct ab8500_regulator_info *info = NULL;
|
||||
info = &ab8500_regulator_info[i];
|
||||
|
||||
dev_vdbg(rdev_get_dev(info->regulator),
|
||||
"%s-remove\n", info->desc.name);
|
||||
|
||||
regulator_unregister(info->regulator);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -25,16 +28,30 @@
|
|||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/regulator.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 LIST_HEAD(regulator_list);
|
||||
static LIST_HEAD(regulator_map_list);
|
||||
static int has_full_constraints;
|
||||
static bool has_full_constraints;
|
||||
static bool board_wants_dummy_regulator;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static struct dentry *debugfs_root;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 void _notifier_call_chain(struct regulator_dev *rdev,
|
||||
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)
|
||||
{
|
||||
|
@ -111,13 +130,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
|
|||
BUG_ON(*min_uV > *max_uV);
|
||||
|
||||
if (!rdev->constraints) {
|
||||
printk(KERN_ERR "%s: no constraints for %s\n", __func__,
|
||||
rdev_get_name(rdev));
|
||||
rdev_err(rdev, "no constraints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
|
||||
printk(KERN_ERR "%s: operation not allowed for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "operation not allowed\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
@ -132,6 +149,27 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
|
|||
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 */
|
||||
static int regulator_check_current_limit(struct regulator_dev *rdev,
|
||||
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);
|
||||
|
||||
if (!rdev->constraints) {
|
||||
printk(KERN_ERR "%s: no constraints for %s\n", __func__,
|
||||
rdev_get_name(rdev));
|
||||
rdev_err(rdev, "no constraints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
|
||||
printk(KERN_ERR "%s: operation not allowed for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "operation not allowed\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
@ -174,18 +210,15 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)
|
|||
}
|
||||
|
||||
if (!rdev->constraints) {
|
||||
printk(KERN_ERR "%s: no constraints for %s\n", __func__,
|
||||
rdev_get_name(rdev));
|
||||
rdev_err(rdev, "no constraints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
|
||||
printk(KERN_ERR "%s: operation not allowed for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "operation not allowed\n");
|
||||
return -EPERM;
|
||||
}
|
||||
if (!(rdev->constraints->valid_modes_mask & mode)) {
|
||||
printk(KERN_ERR "%s: invalid mode %x for %s\n",
|
||||
__func__, mode, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "invalid mode %x\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (!rdev->constraints) {
|
||||
printk(KERN_ERR "%s: no constraints for %s\n", __func__,
|
||||
rdev_get_name(rdev));
|
||||
rdev_err(rdev, "no constraints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
|
||||
printk(KERN_ERR "%s: operation not allowed for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "operation not allowed\n");
|
||||
return -EPERM;
|
||||
}
|
||||
return 0;
|
||||
|
@ -553,18 +584,21 @@ static void drms_uA_update(struct regulator_dev *rdev)
|
|||
|
||||
err = regulator_check_drms(rdev);
|
||||
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;
|
||||
|
||||
/* get output voltage */
|
||||
output_uV = rdev->desc->ops->get_voltage(rdev);
|
||||
output_uV = _regulator_get_voltage(rdev);
|
||||
if (output_uV <= 0)
|
||||
return;
|
||||
|
||||
/* get input voltage */
|
||||
if (rdev->supply && rdev->supply->desc->ops->get_voltage)
|
||||
input_uV = rdev->supply->desc->ops->get_voltage(rdev->supply);
|
||||
else
|
||||
input_uV = 0;
|
||||
if (rdev->supply)
|
||||
input_uV = _regulator_get_voltage(rdev);
|
||||
if (input_uV <= 0)
|
||||
input_uV = rdev->constraints->input_uV;
|
||||
if (input_uV <= 0)
|
||||
return;
|
||||
|
@ -598,20 +632,17 @@ static int suspend_set_state(struct regulator_dev *rdev,
|
|||
*/
|
||||
if (!rstate->enabled && !rstate->disabled) {
|
||||
if (can_set_state)
|
||||
printk(KERN_WARNING "%s: No configuration for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_warn(rdev, "No configuration\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rstate->enabled && rstate->disabled) {
|
||||
printk(KERN_ERR "%s: invalid configuration for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "invalid configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!can_set_state) {
|
||||
printk(KERN_ERR "%s: no way to set suspend state\n",
|
||||
__func__);
|
||||
rdev_err(rdev, "no way to set suspend state\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -620,15 +651,14 @@ static int suspend_set_state(struct regulator_dev *rdev,
|
|||
else
|
||||
ret = rdev->desc->ops->set_suspend_disable(rdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to enabled/disable\n", __func__);
|
||||
rdev_err(rdev, "failed to enabled/disable\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
|
||||
ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to set voltage\n",
|
||||
__func__);
|
||||
rdev_err(rdev, "failed to set voltage\n");
|
||||
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) {
|
||||
ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to set mode\n", __func__);
|
||||
rdev_err(rdev, "failed to set mode\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -714,29 +744,27 @@ static void print_constraints(struct regulator_dev *rdev)
|
|||
if (constraints->valid_modes_mask & REGULATOR_MODE_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,
|
||||
struct regulation_constraints *constraints)
|
||||
{
|
||||
struct regulator_ops *ops = rdev->desc->ops;
|
||||
const char *name = rdev_get_name(rdev);
|
||||
int ret;
|
||||
|
||||
/* do we need to apply the constraint voltage */
|
||||
if (rdev->constraints->apply_uV &&
|
||||
rdev->constraints->min_uV == rdev->constraints->max_uV &&
|
||||
ops->set_voltage) {
|
||||
ret = ops->set_voltage(rdev,
|
||||
rdev->constraints->min_uV, rdev->constraints->max_uV);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
|
||||
__func__,
|
||||
rdev->constraints->min_uV, name);
|
||||
rdev->constraints = NULL;
|
||||
return ret;
|
||||
}
|
||||
rdev->constraints->min_uV == rdev->constraints->max_uV) {
|
||||
ret = _regulator_do_set_voltage(rdev,
|
||||
rdev->constraints->min_uV,
|
||||
rdev->constraints->max_uV);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to apply %duV constraint\n",
|
||||
rdev->constraints->min_uV);
|
||||
rdev->constraints = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
|
||||
pr_err("%s: %s '%s' voltage constraints\n",
|
||||
__func__, "invalid", name);
|
||||
rdev_err(rdev, "invalid voltage constraints\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -787,22 +814,19 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
|
|||
|
||||
/* final: [min_uV..max_uV] valid iff constraints valid */
|
||||
if (max_uV < min_uV) {
|
||||
pr_err("%s: %s '%s' voltage constraints\n",
|
||||
__func__, "unsupportable", name);
|
||||
rdev_err(rdev, "unsupportable voltage constraints\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* use regulator's subset of machine constraints */
|
||||
if (constraints->min_uV < min_uV) {
|
||||
pr_debug("%s: override '%s' %s, %d -> %d\n",
|
||||
__func__, name, "min_uV",
|
||||
constraints->min_uV, min_uV);
|
||||
rdev_dbg(rdev, "override min_uV, %d -> %d\n",
|
||||
constraints->min_uV, min_uV);
|
||||
constraints->min_uV = min_uV;
|
||||
}
|
||||
if (constraints->max_uV > max_uV) {
|
||||
pr_debug("%s: override '%s' %s, %d -> %d\n",
|
||||
__func__, name, "max_uV",
|
||||
constraints->max_uV, max_uV);
|
||||
rdev_dbg(rdev, "override max_uV, %d -> %d\n",
|
||||
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.
|
||||
*/
|
||||
static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
struct regulation_constraints *constraints)
|
||||
const struct regulation_constraints *constraints)
|
||||
{
|
||||
int ret = 0;
|
||||
const char *name;
|
||||
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, constraints);
|
||||
ret = machine_constraints_voltage(rdev, rdev->constraints);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
/* do we need to setup our suspend state */
|
||||
if (constraints->initial_state) {
|
||||
ret = suspend_prepare(rdev, constraints->initial_state);
|
||||
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to set suspend state for %s\n",
|
||||
__func__, name);
|
||||
rdev_err(rdev, "failed to set suspend state\n");
|
||||
rdev->constraints = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -849,17 +872,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
|||
|
||||
if (constraints->initial_mode) {
|
||||
if (!ops->set_mode) {
|
||||
printk(KERN_ERR "%s: no set_mode operation for %s\n",
|
||||
__func__, name);
|
||||
rdev_err(rdev, "no set_mode operation\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ops->set_mode(rdev, constraints->initial_mode);
|
||||
ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR
|
||||
"%s: failed to set initial mode for %s: %d\n",
|
||||
__func__, name, ret);
|
||||
rdev_err(rdev, "failed to set initial mode: %d\n", ret);
|
||||
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
|
||||
* 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);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to enable %s\n",
|
||||
__func__, name);
|
||||
rdev_err(rdev, "failed to enable\n");
|
||||
rdev->constraints = NULL;
|
||||
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,
|
||||
"supply");
|
||||
if (err) {
|
||||
printk(KERN_ERR
|
||||
"%s: could not add device link %s err %d\n",
|
||||
__func__, supply_rdev->dev.kobj.name, err);
|
||||
rdev_err(rdev, "could not add device link %s err %d\n",
|
||||
supply_rdev->dev.kobj.name, err);
|
||||
goto out;
|
||||
}
|
||||
rdev->supply = supply_rdev;
|
||||
|
@ -957,10 +976,10 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
|
|||
continue;
|
||||
|
||||
dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n",
|
||||
dev_name(&node->regulator->dev),
|
||||
node->regulator->desc->name,
|
||||
supply,
|
||||
dev_name(&rdev->dev), rdev_get_name(rdev));
|
||||
dev_name(&node->regulator->dev),
|
||||
node->regulator->desc->name,
|
||||
supply,
|
||||
dev_name(&rdev->dev), rdev_get_name(rdev));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -1031,8 +1050,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
|||
regulator->dev_attr.show = device_requested_uA_show;
|
||||
err = device_create_file(dev, ®ulator->dev_attr);
|
||||
if (err < 0) {
|
||||
printk(KERN_WARNING "%s: could not add regulator_dev"
|
||||
" load sysfs\n", __func__);
|
||||
rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
|
||||
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,
|
||||
buf);
|
||||
if (err) {
|
||||
printk(KERN_WARNING
|
||||
"%s: could not add device link %s err %d\n",
|
||||
__func__, dev->kobj.name, err);
|
||||
rdev_warn(rdev, "could not add device link %s err %d\n",
|
||||
dev->kobj.name, err);
|
||||
goto link_name_err;
|
||||
}
|
||||
}
|
||||
|
@ -1088,7 +1105,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
|
|||
int ret;
|
||||
|
||||
if (id == NULL) {
|
||||
printk(KERN_ERR "regulator: get() with no identifier\n");
|
||||
pr_err("get() with no identifier\n");
|
||||
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.
|
||||
*/
|
||||
if (!has_full_constraints) {
|
||||
pr_warning("%s supply %s not found, using dummy regulator\n",
|
||||
devname, id);
|
||||
pr_warn("%s supply %s not found, using dummy regulator\n",
|
||||
devname, id);
|
||||
rdev = dummy_regulator_rdev;
|
||||
goto found;
|
||||
}
|
||||
|
@ -1274,8 +1291,7 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
|||
ret = _regulator_enable(rdev->supply);
|
||||
mutex_unlock(&rdev->supply->mutex);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to enable %s: %d\n",
|
||||
__func__, rdev_get_name(rdev), ret);
|
||||
rdev_err(rdev, "failed to enable: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -1302,13 +1318,13 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
|||
if (ret >= 0) {
|
||||
delay = ret;
|
||||
} else {
|
||||
printk(KERN_WARNING
|
||||
"%s: enable_time() failed for %s: %d\n",
|
||||
__func__, rdev_get_name(rdev),
|
||||
ret);
|
||||
rdev_warn(rdev, "enable_time() failed: %d\n",
|
||||
ret);
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
trace_regulator_enable(rdev_get_name(rdev));
|
||||
|
||||
/* Allow the regulator to ramp; it would be useful
|
||||
* to extend this for bulk operations so that the
|
||||
* regulators can ramp together. */
|
||||
|
@ -1316,6 +1332,8 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
trace_regulator_enable_delay(rdev_get_name(rdev));
|
||||
|
||||
if (delay >= 1000) {
|
||||
mdelay(delay / 1000);
|
||||
udelay(delay % 1000);
|
||||
|
@ -1323,9 +1341,10 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
|||
udelay(delay);
|
||||
}
|
||||
|
||||
trace_regulator_enable_complete(rdev_get_name(rdev));
|
||||
|
||||
} else if (ret < 0) {
|
||||
printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n",
|
||||
__func__, rdev_get_name(rdev), ret);
|
||||
rdev_err(rdev, "is_enabled() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Fallthrough on positive return values - already enabled */
|
||||
|
@ -1367,8 +1386,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
|
|||
*supply_rdev_ptr = NULL;
|
||||
|
||||
if (WARN(rdev->use_count <= 0,
|
||||
"unbalanced disables for %s\n",
|
||||
rdev_get_name(rdev)))
|
||||
"unbalanced disables for %s\n", rdev_get_name(rdev)))
|
||||
return -EIO;
|
||||
|
||||
/* 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 */
|
||||
if (_regulator_can_change_status(rdev) &&
|
||||
rdev->desc->ops->disable) {
|
||||
trace_regulator_disable(rdev_get_name(rdev));
|
||||
|
||||
ret = rdev->desc->ops->disable(rdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to disable %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "failed to disable\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
trace_regulator_disable_complete(rdev_get_name(rdev));
|
||||
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
|
||||
NULL);
|
||||
}
|
||||
|
@ -1451,8 +1472,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
|
|||
/* ah well, who wants to live forever... */
|
||||
ret = rdev->desc->ops->disable(rdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to force disable %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "failed to force disable\n");
|
||||
return ret;
|
||||
}
|
||||
/* notify other consumers that power has been forced off */
|
||||
|
@ -1605,6 +1625,62 @@ int regulator_is_supported_voltage(struct regulator *regulator,
|
|||
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: 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)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
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 */
|
||||
if (!rdev->desc->ops->set_voltage) {
|
||||
if (!rdev->desc->ops->set_voltage &&
|
||||
!rdev->desc->ops->set_voltage_sel) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1642,18 +1726,76 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
|
|||
goto out;
|
||||
regulator->min_uV = min_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:
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
|
||||
mutex_unlock(&rdev->mutex);
|
||||
return ret;
|
||||
}
|
||||
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)
|
||||
{
|
||||
/* 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)
|
||||
return rdev->desc->ops->get_voltage(rdev);
|
||||
else
|
||||
|
@ -1880,21 +2022,20 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
|
|||
goto out;
|
||||
|
||||
/* get output voltage */
|
||||
output_uV = rdev->desc->ops->get_voltage(rdev);
|
||||
output_uV = _regulator_get_voltage(rdev);
|
||||
if (output_uV <= 0) {
|
||||
printk(KERN_ERR "%s: invalid output voltage found for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "invalid output voltage found\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get input voltage */
|
||||
if (rdev->supply && rdev->supply->desc->ops->get_voltage)
|
||||
input_uV = rdev->supply->desc->ops->get_voltage(rdev->supply);
|
||||
else
|
||||
input_uV = 0;
|
||||
if (rdev->supply)
|
||||
input_uV = _regulator_get_voltage(rdev->supply);
|
||||
if (input_uV <= 0)
|
||||
input_uV = rdev->constraints->input_uV;
|
||||
if (input_uV <= 0) {
|
||||
printk(KERN_ERR "%s: invalid input voltage found for %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "invalid input voltage found\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1907,16 +2048,14 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
|
|||
total_uA_load);
|
||||
ret = regulator_check_mode(rdev, mode);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to get optimum mode for %s @"
|
||||
" %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev),
|
||||
total_uA_load, input_uV, output_uV);
|
||||
rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
|
||||
total_uA_load, input_uV, output_uV);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = rdev->desc->ops->set_mode(rdev, mode);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n",
|
||||
__func__, mode, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "failed to set optimum mode %x\n", mode);
|
||||
goto out;
|
||||
}
|
||||
ret = mode;
|
||||
|
@ -2047,7 +2186,7 @@ int regulator_bulk_enable(int num_consumers,
|
|||
return 0;
|
||||
|
||||
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)
|
||||
regulator_disable(consumers[i].consumer);
|
||||
|
||||
|
@ -2082,8 +2221,7 @@ int regulator_bulk_disable(int num_consumers,
|
|||
return 0;
|
||||
|
||||
err:
|
||||
printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply,
|
||||
ret);
|
||||
pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
|
||||
for (--i; i >= 0; --i)
|
||||
regulator_enable(consumers[i].consumer);
|
||||
|
||||
|
@ -2166,7 +2304,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
|||
int status = 0;
|
||||
|
||||
/* 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);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
@ -2207,7 +2345,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
|||
return status;
|
||||
|
||||
/* 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);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
@ -2271,6 +2409,23 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
|||
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_desc: regulator to register
|
||||
|
@ -2282,7 +2437,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
|||
* Returns 0 on success.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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);
|
||||
if (rdev == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -2399,6 +2570,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
|||
}
|
||||
|
||||
list_add(&rdev->list, ®ulator_list);
|
||||
|
||||
rdev_init_debugfs(rdev);
|
||||
out:
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
return rdev;
|
||||
|
@ -2431,12 +2604,16 @@ void regulator_unregister(struct regulator_dev *rdev)
|
|||
return;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
debugfs_remove_recursive(rdev->debugfs);
|
||||
#endif
|
||||
WARN_ON(rdev->open_count);
|
||||
unset_regulator_supplies(rdev);
|
||||
list_del(&rdev->list);
|
||||
if (rdev->supply)
|
||||
sysfs_remove_link(&rdev->dev.kobj, "supply");
|
||||
device_unregister(&rdev->dev);
|
||||
kfree(rdev->constraints);
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_unregister);
|
||||
|
@ -2465,8 +2642,7 @@ int regulator_suspend_prepare(suspend_state_t state)
|
|||
mutex_unlock(&rdev->mutex);
|
||||
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to prepare %s\n",
|
||||
__func__, rdev_get_name(rdev));
|
||||
rdev_err(rdev, "failed to prepare\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -2572,10 +2748,16 @@ static int __init regulator_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
|
||||
|
||||
ret = class_register(®ulator_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();
|
||||
|
||||
return ret;
|
||||
|
@ -2590,7 +2772,6 @@ static int __init regulator_init_complete(void)
|
|||
struct regulator_ops *ops;
|
||||
struct regulation_constraints *c;
|
||||
int enabled, ret;
|
||||
const char *name;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
|
||||
|
@ -2602,8 +2783,6 @@ static int __init regulator_init_complete(void)
|
|||
ops = rdev->desc->ops;
|
||||
c = rdev->constraints;
|
||||
|
||||
name = rdev_get_name(rdev);
|
||||
|
||||
if (!ops->disable || (c && c->always_on))
|
||||
continue;
|
||||
|
||||
|
@ -2624,13 +2803,10 @@ static int __init regulator_init_complete(void)
|
|||
if (has_full_constraints) {
|
||||
/* We log since this may kill the system if it
|
||||
* goes wrong. */
|
||||
printk(KERN_INFO "%s: disabling %s\n",
|
||||
__func__, name);
|
||||
rdev_info(rdev, "disabling\n");
|
||||
ret = ops->disable(rdev);
|
||||
if (ret != 0) {
|
||||
printk(KERN_ERR
|
||||
"%s: couldn't disable %s: %d\n",
|
||||
__func__, name, ret);
|
||||
rdev_err(rdev, "couldn't disable: %d\n", ret);
|
||||
}
|
||||
} else {
|
||||
/* 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
|
||||
* anything here.
|
||||
*/
|
||||
printk(KERN_WARNING
|
||||
"%s: incomplete constraints, leaving %s on\n",
|
||||
__func__, name);
|
||||
rdev_warn(rdev, "incomplete constraints, leaving on\n");
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
|
|
@ -107,7 +107,7 @@ static inline int check_range(struct da903x_regulator_info *info,
|
|||
|
||||
/* DA9030/DA9034 common operations */
|
||||
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 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;
|
||||
*selector = val;
|
||||
val <<= 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 */
|
||||
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 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;
|
||||
*selector = val;
|
||||
val <<= info->vol_shift;
|
||||
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
|
||||
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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct da903x_regulator_info *info = rdev_get_drvdata(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;
|
||||
}
|
||||
|
||||
*selector = val;
|
||||
val <<= 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 */
|
||||
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 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;
|
||||
*selector = val;
|
||||
val <<= 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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct da903x_regulator_info *info = rdev_get_drvdata(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 = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val);
|
||||
*selector = val;
|
||||
val <<= info->vol_shift;
|
||||
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
|
||||
|
||||
|
|
|
@ -58,7 +58,9 @@ out:
|
|||
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);
|
||||
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 */
|
||||
data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP;
|
||||
|
||||
*selector = data;
|
||||
|
||||
mutex_lock(&pmic->mtx);
|
||||
|
||||
err = i2c_smbus_write_byte(pmic->client, data);
|
||||
|
@ -169,7 +173,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
|
|||
init_data, pmic);
|
||||
if (IS_ERR(pmic->rdev[i])) {
|
||||
dev_err(&i2c->dev, "failed to register %s\n", id->name);
|
||||
err = PTR_ERR(pmic->rdev);
|
||||
err = PTR_ERR(pmic->rdev[i]);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,7 +168,8 @@ static int lp3971_ldo_get_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);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = val;
|
||||
|
||||
return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
|
||||
LDO_VOL_CONTR_MASK << 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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = val;
|
||||
|
||||
ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
|
||||
BUCK_TARGET_VOL_MASK, val);
|
||||
if (ret)
|
||||
|
|
|
@ -292,7 +292,8 @@ static int lp3972_ldo_get_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);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = val;
|
||||
|
||||
shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo);
|
||||
ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo),
|
||||
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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = val;
|
||||
|
||||
ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck),
|
||||
LP3972_BUCK_VOL_MASK, val);
|
||||
if (ret)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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 i2c_client *client = max1586->client;
|
||||
unsigned range_uV = max1586->max_uV - max1586->min_uV;
|
||||
unsigned selector;
|
||||
u8 v3_prog;
|
||||
|
||||
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)
|
||||
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;
|
||||
if (max1586_v3_calc_voltage(max1586, selector) > max_uV)
|
||||
if (max1586_v3_calc_voltage(max1586, *selector) > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -110,10 +110,10 @@ static int max1586_v6_calc_voltage(unsigned 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);
|
||||
unsigned selector;
|
||||
u8 v6_prog;
|
||||
|
||||
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;
|
||||
|
||||
if (min_uV < 1800000)
|
||||
selector = 0;
|
||||
*selector = 0;
|
||||
else if (min_uV < 2500000)
|
||||
selector = 1;
|
||||
*selector = 1;
|
||||
else if (min_uV < 3000000)
|
||||
selector = 2;
|
||||
*selector = 2;
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ static int max8649_get_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);
|
||||
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)
|
||||
/ MAX8649_DCDC_STEP;
|
||||
mask = MAX8649_VOL_MASK;
|
||||
*selector = data & mask;
|
||||
|
||||
return max8649_set_bits(info->i2c, info->vol_reg, mask, data);
|
||||
}
|
||||
|
|
|
@ -141,7 +141,8 @@ static int max8660_dcdc_get(struct regulator_dev *rdev)
|
|||
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);
|
||||
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))
|
||||
/ MAX8660_DCDC_STEP;
|
||||
*s = selector;
|
||||
|
||||
ret = max8660_dcdc_list(rdev, selector);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*s = selector;
|
||||
|
||||
ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);
|
||||
if (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;
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*s = selector;
|
||||
|
||||
if (rdev_get_id(rdev) == MAX8660_V6)
|
||||
return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);
|
||||
else
|
||||
|
|
|
@ -55,7 +55,7 @@ static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index)
|
|||
}
|
||||
|
||||
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);
|
||||
unsigned char data, mask;
|
||||
|
@ -66,6 +66,7 @@ static int max8925_set_voltage(struct regulator_dev *rdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
|
||||
*selector = data;
|
||||
data <<= info->vol_shift;
|
||||
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ static int max8952_get_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);
|
||||
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) {
|
||||
max8952->vid0 = (vid % 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_vid1, max8952->vid1);
|
||||
} else
|
||||
|
|
|
@ -304,7 +304,7 @@ static int max8998_get_voltage(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 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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = i;
|
||||
|
||||
ret = max8998_get_voltage_register(rdev, ®, &shift, &mask);
|
||||
if (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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = i;
|
||||
|
||||
ret = max8998_get_voltage_register(rdev, ®, &shift, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* 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 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
|
||||
*
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include "mc13xxx.h"
|
||||
|
||||
#define MC13783_REG_SWITCHERS5 29
|
||||
#define MC13783_REG_SWITCHERS5_SW3EN (1 << 20)
|
||||
|
@ -89,154 +91,106 @@
|
|||
#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 */
|
||||
static const int const mc13783_sw3_val[] = {
|
||||
static const int mc13783_sw3_val[] = {
|
||||
5000000, 5000000, 5000000, 5500000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vaudio_val[] = {
|
||||
static const int mc13783_vaudio_val[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_viohi_val[] = {
|
||||
static const int mc13783_viohi_val[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_violo_val[] = {
|
||||
static const int mc13783_violo_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vdig_val[] = {
|
||||
static const int mc13783_vdig_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vgen_val[] = {
|
||||
static const int mc13783_vgen_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
1100000, 2000000, 2775000, 2400000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfdig_val[] = {
|
||||
static const int mc13783_vrfdig_val[] = {
|
||||
1200000, 1500000, 1800000, 1875000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfref_val[] = {
|
||||
static const int mc13783_vrfref_val[] = {
|
||||
2475000, 2600000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfcp_val[] = {
|
||||
static const int mc13783_vrfcp_val[] = {
|
||||
2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vsim_val[] = {
|
||||
static const int mc13783_vsim_val[] = {
|
||||
1800000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vesim_val[] = {
|
||||
static const int mc13783_vesim_val[] = {
|
||||
1800000, 2900000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vcam_val[] = {
|
||||
static const int mc13783_vcam_val[] = {
|
||||
1500000, 1800000, 2500000, 2550000,
|
||||
2600000, 2750000, 2800000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfbg_val[] = {
|
||||
static const int mc13783_vrfbg_val[] = {
|
||||
1250000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vvib_val[] = {
|
||||
static const int mc13783_vvib_val[] = {
|
||||
1300000, 1800000, 2000000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vmmc_val[] = {
|
||||
static const int mc13783_vmmc_val[] = {
|
||||
1600000, 1800000, 2000000, 2600000,
|
||||
2700000, 2800000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrf_val[] = {
|
||||
static const int mc13783_vrf_val[] = {
|
||||
1500000, 1875000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_gpo_val[] = {
|
||||
static const int mc13783_gpo_val[] = {
|
||||
3100000,
|
||||
};
|
||||
|
||||
static const int const mc13783_pwgtdrv_val[] = {
|
||||
static const int mc13783_pwgtdrv_val[] = {
|
||||
5500000,
|
||||
};
|
||||
|
||||
static struct regulator_ops mc13783_regulator_ops;
|
||||
static struct regulator_ops mc13783_fixed_regulator_ops;
|
||||
static struct regulator_ops mc13783_gpo_regulator_ops;
|
||||
|
||||
#define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages) \
|
||||
[MC13783_ ## prefix ## _ ## _name] = { \
|
||||
.desc = { \
|
||||
.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_DEFINE(prefix, name, reg, vsel_reg, voltages) \
|
||||
MC13xxx_DEFINE(MC13783_REG_, name, reg, vsel_reg, voltages, \
|
||||
mc13xxx_regulator_ops)
|
||||
|
||||
#define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages) \
|
||||
[MC13783_ ## prefix ## _ ## _name] = { \
|
||||
.desc = { \
|
||||
.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_FIXED_DEFINE(prefix, name, reg, voltages) \
|
||||
MC13xxx_FIXED_DEFINE(MC13783_REG_, name, reg, voltages, \
|
||||
mc13xxx_fixed_regulator_ops)
|
||||
|
||||
#define MC13783_GPO_DEFINE(prefix, _name, _reg, _voltages) \
|
||||
[MC13783_ ## prefix ## _ ## _name] = { \
|
||||
.desc = { \
|
||||
.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_GPO_DEFINE(prefix, name, reg, voltages) \
|
||||
MC13xxx_GPO_DEFINE(MC13783_REG_, name, reg, voltages, \
|
||||
mc13783_gpo_regulator_ops)
|
||||
|
||||
#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) \
|
||||
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_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
|
||||
MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val),
|
||||
MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
|
||||
MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
|
||||
MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_violo_val),
|
||||
MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \
|
||||
|
@ -255,7 +209,7 @@ static struct mc13783_regulator mc13783_regulators[] = {
|
|||
mc13783_vesim_val),
|
||||
MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \
|
||||
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_vvib_val),
|
||||
MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \
|
||||
|
@ -266,215 +220,24 @@ static struct mc13783_regulator mc13783_regulators[] = {
|
|||
mc13783_vmmc_val),
|
||||
MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \
|
||||
mc13783_vmmc_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
|
||||
MC13783_GPO_DEFINE(REGU, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
|
||||
MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REG, GPO3, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REG, GPO4, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REG, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
|
||||
MC13783_GPO_DEFINE(REG, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
|
||||
};
|
||||
|
||||
struct mc13783_regulator_priv {
|
||||
struct mc13783 *mc13783;
|
||||
u32 powermisc_pwgt_state;
|
||||
struct regulator_dev *regulators[];
|
||||
};
|
||||
|
||||
static int mc13783_regulator_enable(struct regulator_dev *rdev)
|
||||
static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
|
||||
u32 val)
|
||||
{
|
||||
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,
|
||||
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;
|
||||
struct mc13xxx *mc13783 = priv->mc13xxx;
|
||||
int ret;
|
||||
u32 valread;
|
||||
|
||||
BUG_ON(val & ~mask);
|
||||
|
||||
ret = mc13783_reg_read(mc13783, MC13783_REG_POWERMISC, &valread);
|
||||
ret = mc13xxx_reg_read(mc13783, MC13783_REG_POWERMISC, &valread);
|
||||
if (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) |
|
||||
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)
|
||||
{
|
||||
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 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);
|
||||
|
||||
/* Power Gate enable value is 0 */
|
||||
if (id == MC13783_REGU_PWGT1SPI ||
|
||||
id == MC13783_REGU_PWGT2SPI)
|
||||
if (id == MC13783_REG_PWGT1SPI ||
|
||||
id == MC13783_REG_PWGT2SPI)
|
||||
en_val = 0;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit,
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
|
||||
en_val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 ret;
|
||||
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);
|
||||
|
||||
/* Power Gate disable value is 1 */
|
||||
if (id == MC13783_REGU_PWGT1SPI ||
|
||||
id == MC13783_REGU_PWGT2SPI)
|
||||
dis_val = mc13783_regulators[id].enable_bit;
|
||||
if (id == MC13783_REG_PWGT1SPI ||
|
||||
id == MC13783_REG_PWGT2SPI)
|
||||
dis_val = mc13xxx_regulators[id].enable_bit;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit,
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
|
||||
dis_val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
unsigned int val;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
|
||||
mc13xxx_unlock(priv->mc13xxx);
|
||||
|
||||
if (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) |
|
||||
(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 = {
|
||||
.enable = mc13783_gpo_regulator_enable,
|
||||
.disable = mc13783_gpo_regulator_disable,
|
||||
.is_enabled = mc13783_gpo_regulator_is_enabled,
|
||||
.list_voltage = mc13783_regulator_list_voltage,
|
||||
.set_voltage = mc13783_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13783_fixed_regulator_get_voltage,
|
||||
.list_voltage = mc13xxx_regulator_list_voltage,
|
||||
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
|
||||
};
|
||||
|
||||
static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mc13783_regulator_priv *priv;
|
||||
struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct mc13xxx_regulator_priv *priv;
|
||||
struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct mc13783_regulator_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct mc13783_regulator_init_data *init_data;
|
||||
|
@ -583,7 +349,8 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->mc13783 = mc13783;
|
||||
priv->mc13xxx_regulators = mc13783_regulators;
|
||||
priv->mc13xxx = mc13783;
|
||||
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
init_data = &pdata->regulators[i];
|
||||
|
@ -613,7 +380,7 @@ err:
|
|||
|
||||
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 =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
int i;
|
||||
|
|
635
drivers/regulator/mc13892-regulator.c
Normal file
635
drivers/regulator/mc13892-regulator.c
Normal 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");
|
241
drivers/regulator/mc13xxx-regulator-core.c
Normal file
241
drivers/regulator/mc13xxx-regulator-core.c
Normal 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
101
drivers/regulator/mc13xxx.h
Normal 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
|
|
@ -151,7 +151,8 @@ static struct pcap_regulator vreg_table[] = {
|
|||
};
|
||||
|
||||
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)];
|
||||
void *pcap = rdev_get_drvdata(rdev);
|
||||
|
@ -170,10 +171,12 @@ static int pcap_regulator_set_voltage(struct regulator_dev *rdev,
|
|||
i = 0;
|
||||
|
||||
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,
|
||||
(vreg->n_voltages - 1) << vreg->index,
|
||||
i << vreg->index);
|
||||
}
|
||||
|
||||
if (i == 0 && rdev_get_id(rdev) == V1)
|
||||
i = vreg->n_voltages - 1;
|
||||
|
|
|
@ -108,7 +108,8 @@ static unsigned int ldo_voltage_value(u8 bits)
|
|||
}
|
||||
|
||||
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;
|
||||
int regulator_id, millivolts;
|
||||
|
@ -147,6 +148,8 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
*selector = volt_bits;
|
||||
|
||||
return pcf50633_reg_write(pcf, regnr, volt_bits);
|
||||
}
|
||||
|
||||
|
|
|
@ -321,7 +321,8 @@ static int tps65023_dcdc_get_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);
|
||||
int dcdc = rdev_get_id(dev);
|
||||
|
@ -346,6 +347,8 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
|
|||
break;
|
||||
}
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
/* write to the register in case we found a match */
|
||||
if (vsel == tps->info[dcdc]->table_len)
|
||||
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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
|
||||
if (data < 0)
|
||||
return data;
|
||||
|
|
|
@ -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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct tps6507x_pmic *tps = rdev_get_drvdata(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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
data = tps6507x_pmic_reg_read(tps, reg);
|
||||
if (data < 0)
|
||||
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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct tps6507x_pmic *tps = rdev_get_drvdata(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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
data = tps6507x_pmic_reg_read(tps, reg);
|
||||
if (data < 0)
|
||||
return data;
|
||||
|
|
693
drivers/regulator/tps6524x-regulator.c
Normal file
693
drivers/regulator/tps6524x-regulator.c
Normal 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 = ∈
|
||||
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 = ®ulator_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");
|
|
@ -85,7 +85,8 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
|
|||
|
||||
static int __tps6586x_ldo_set_voltage(struct device *parent,
|
||||
struct tps6586x_regulator *ri,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
int val, uV;
|
||||
uint8_t mask;
|
||||
|
@ -100,6 +101,8 @@ static int __tps6586x_ldo_set_voltage(struct device *parent,
|
|||
/* use the first in-range value */
|
||||
if (min_uV <= uV && uV <= max_uV) {
|
||||
|
||||
*selector = val;
|
||||
|
||||
val <<= 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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct tps6586x_regulator *ri = rdev_get_drvdata(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)
|
||||
|
@ -140,13 +144,14 @@ static int tps6586x_ldo_get_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 device *parent = to_tps6586x_dev(rdev);
|
||||
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)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -329,7 +329,8 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
|
|||
}
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
||||
/* 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,
|
||||
VREG_VOLTAGE, vsel);
|
||||
}
|
||||
}
|
||||
|
||||
return -EDOM;
|
||||
|
@ -389,7 +392,8 @@ static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
|
|||
}
|
||||
|
||||
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);
|
||||
int vsel;
|
||||
|
@ -402,6 +406,7 @@ twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
|
|||
* mV = 1000mv + 100mv * (vsel - 1)
|
||||
*/
|
||||
vsel = (min_uV/1000 - 1000)/100 + 1;
|
||||
*selector = vsel;
|
||||
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel);
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
|
@ -314,6 +314,8 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
|
|||
if (vsel < 0)
|
||||
return vsel;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
/* If this value is already set then do a GPIO update if we can */
|
||||
if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (dcdc->dvs_gpio && dcdc->dvs_gpio_state)
|
||||
return wm831x_buckv_list_voltage(rdev, dcdc->dvs_vsel);
|
||||
return dcdc->dvs_vsel;
|
||||
else
|
||||
return wm831x_buckv_list_voltage(rdev, dcdc->on_vsel);
|
||||
return dcdc->on_vsel;
|
||||
}
|
||||
|
||||
/* 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 = {
|
||||
.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,
|
||||
.set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
|
||||
.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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, int *selector)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
|
@ -667,11 +673,12 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
|
|||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
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 *wm831x = dcdc->wm831x;
|
||||
|
@ -682,12 +689,12 @@ static int wm831x_buckp_get_voltage(struct regulator_dev *rdev)
|
|||
if (val < 0)
|
||||
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 = {
|
||||
.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,
|
||||
.set_suspend_voltage = wm831x_buckp_set_suspend_voltage,
|
||||
|
||||
|
|
|
@ -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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
|
@ -150,11 +155,12 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
|
|||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
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 *wm831x = ldo->wm831x;
|
||||
|
@ -167,7 +173,7 @@ static int wm831x_gp_ldo_get_voltage(struct regulator_dev *rdev)
|
|||
|
||||
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)
|
||||
|
@ -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 = {
|
||||
.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_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
|
||||
.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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
|
@ -450,11 +460,12 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
|
|||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
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 *wm831x = ldo->wm831x;
|
||||
|
@ -467,7 +478,7 @@ static int wm831x_aldo_get_voltage(struct regulator_dev *rdev)
|
|||
|
||||
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)
|
||||
|
@ -548,7 +559,7 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
|
|||
|
||||
static struct regulator_ops wm831x_aldo_ops = {
|
||||
.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_suspend_voltage = wm831x_aldo_set_suspend_voltage,
|
||||
.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,
|
||||
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 *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)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
|
@ -697,11 +713,12 @@ static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
|
|||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
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 *wm831x = ldo->wm831x;
|
||||
|
@ -714,7 +731,7 @@ static int wm831x_alive_ldo_get_voltage(struct regulator_dev *rdev)
|
|||
|
||||
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)
|
||||
|
@ -736,7 +753,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
|
|||
|
||||
static struct regulator_ops wm831x_alive_ldo_ops = {
|
||||
.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_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
|
||||
.get_status = wm831x_alive_ldo_get_status,
|
||||
|
|
|
@ -360,7 +360,7 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
|
|||
EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
*selector = mV;
|
||||
|
||||
/* all DCDCs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
|
||||
wm8350_reg_write(wm8350, volt_reg, val | mV);
|
||||
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);
|
||||
int volt_reg, dcdc = rdev_get_id(rdev);
|
||||
u16 val;
|
||||
|
||||
switch (dcdc) {
|
||||
case WM8350_DCDC_1:
|
||||
|
@ -429,8 +430,7 @@ static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
|
|||
}
|
||||
|
||||
/* all DCDCs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
|
||||
return wm8350_dcdc_val_to_mvolts(val) * 1000;
|
||||
return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
|
||||
}
|
||||
|
||||
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,
|
||||
int max_uV)
|
||||
int max_uV, unsigned *selector)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
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;
|
||||
}
|
||||
|
||||
*selector = mV;
|
||||
|
||||
/* all LDOs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
|
||||
wm8350_reg_write(wm8350, volt_reg, val | mV);
|
||||
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);
|
||||
int volt_reg, ldo = rdev_get_id(rdev);
|
||||
u16 val;
|
||||
|
||||
switch (ldo) {
|
||||
case WM8350_LDO_1:
|
||||
|
@ -827,8 +828,7 @@ static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
|
|||
}
|
||||
|
||||
/* all LDOs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
|
||||
return wm8350_ldo_val_to_mvolts(val) * 1000;
|
||||
return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.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,
|
||||
.enable = wm8350_dcdc_enable,
|
||||
.disable = wm8350_dcdc_disable,
|
||||
|
@ -1249,7 +1249,7 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
|
|||
|
||||
static struct regulator_ops wm8350_ldo_ops = {
|
||||
.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,
|
||||
.enable = wm8350_ldo_enable,
|
||||
.disable = wm8350_ldo_disable,
|
||||
|
|
|
@ -67,7 +67,7 @@ static int wm8400_ldo_get_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);
|
||||
u16 val;
|
||||
|
@ -93,6 +93,8 @@ static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
|
|||
val += 0xf;
|
||||
}
|
||||
|
||||
*selector = val;
|
||||
|
||||
return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
|
||||
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,
|
||||
int min_uV, int max_uV)
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct wm8400 *wm8400 = rdev_get_drvdata(dev);
|
||||
u16 val;
|
||||
|
@ -171,6 +173,8 @@ static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
|
|||
return -EINVAL;
|
||||
BUG_ON(850000 + (25000 * val) < min_uV);
|
||||
|
||||
*selector = val;
|
||||
|
||||
return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
|
||||
WM8400_DC1_VSEL_MASK, val);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
|
|||
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);
|
||||
int val;
|
||||
|
@ -95,13 +95,11 @@ static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev)
|
|||
if (val < 0)
|
||||
return val;
|
||||
|
||||
val = (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT;
|
||||
|
||||
return wm8994_ldo1_list_voltage(rdev, val);
|
||||
return (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT;
|
||||
}
|
||||
|
||||
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);
|
||||
int selector, v;
|
||||
|
@ -111,6 +109,7 @@ static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev,
|
|||
if (v < 0 || v > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
*s = selector;
|
||||
selector <<= WM8994_LDO1_VSEL_SHIFT;
|
||||
|
||||
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,
|
||||
|
||||
.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,
|
||||
};
|
||||
|
||||
|
@ -137,7 +136,7 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
|
|||
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);
|
||||
int val;
|
||||
|
@ -146,13 +145,11 @@ static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev)
|
|||
if (val < 0)
|
||||
return val;
|
||||
|
||||
val = (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT;
|
||||
|
||||
return wm8994_ldo2_list_voltage(rdev, val);
|
||||
return (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT;
|
||||
}
|
||||
|
||||
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);
|
||||
int selector, v;
|
||||
|
@ -162,6 +159,7 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
|
|||
if (v < 0 || v > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
*s = selector;
|
||||
selector <<= WM8994_LDO2_VSEL_SHIFT;
|
||||
|
||||
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,
|
||||
|
||||
.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,
|
||||
};
|
||||
|
||||
|
|
|
@ -99,8 +99,6 @@
|
|||
#define AB8500_NR_IRQS 104
|
||||
#define AB8500_NUM_IRQ_REGS 13
|
||||
|
||||
#define AB8500_NUM_REGULATORS 15
|
||||
|
||||
/**
|
||||
* struct ab8500 - ab8500 internal structure
|
||||
* @dev: parent device
|
||||
|
@ -145,7 +143,8 @@ struct regulator_init_data;
|
|||
struct ab8500_platform_data {
|
||||
int irq_base;
|
||||
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);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010 Yong Shen <yong.shen@linaro.org>
|
||||
* Copyright 2009-2010 Pengutronix
|
||||
* 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);
|
||||
|
||||
|
||||
#define MC13783_SW_SW1A 0
|
||||
#define MC13783_SW_SW1B 1
|
||||
#define MC13783_SW_SW2A 2
|
||||
#define MC13783_SW_SW2B 3
|
||||
#define MC13783_SW_SW3 4
|
||||
#define MC13783_SW_PLL 5
|
||||
#define MC13783_REGU_VAUDIO 6
|
||||
#define MC13783_REGU_VIOHI 7
|
||||
#define MC13783_REGU_VIOLO 8
|
||||
#define MC13783_REGU_VDIG 9
|
||||
#define MC13783_REGU_VGEN 10
|
||||
#define MC13783_REGU_VRFDIG 11
|
||||
#define MC13783_REGU_VRFREF 12
|
||||
#define MC13783_REGU_VRFCP 13
|
||||
#define MC13783_REGU_VSIM 14
|
||||
#define MC13783_REGU_VESIM 15
|
||||
#define MC13783_REGU_VCAM 16
|
||||
#define MC13783_REGU_VRFBG 17
|
||||
#define MC13783_REGU_VVIB 18
|
||||
#define MC13783_REGU_VRF1 19
|
||||
#define MC13783_REGU_VRF2 20
|
||||
#define MC13783_REGU_VMMC1 21
|
||||
#define MC13783_REGU_VMMC2 22
|
||||
#define MC13783_REGU_GPO1 23
|
||||
#define MC13783_REGU_GPO2 24
|
||||
#define MC13783_REGU_GPO3 25
|
||||
#define MC13783_REGU_GPO4 26
|
||||
#define MC13783_REGU_V1 27
|
||||
#define MC13783_REGU_V2 28
|
||||
#define MC13783_REGU_V3 29
|
||||
#define MC13783_REGU_V4 30
|
||||
#define MC13783_REGU_PWGT1SPI 31
|
||||
#define MC13783_REGU_PWGT2SPI 32
|
||||
#define MC13783_REG_SW1A 0
|
||||
#define MC13783_REG_SW1B 1
|
||||
#define MC13783_REG_SW2A 2
|
||||
#define MC13783_REG_SW2B 3
|
||||
#define MC13783_REG_SW3 4
|
||||
#define MC13783_REG_PLL 5
|
||||
#define MC13783_REG_VAUDIO 6
|
||||
#define MC13783_REG_VIOHI 7
|
||||
#define MC13783_REG_VIOLO 8
|
||||
#define MC13783_REG_VDIG 9
|
||||
#define MC13783_REG_VGEN 10
|
||||
#define MC13783_REG_VRFDIG 11
|
||||
#define MC13783_REG_VRFREF 12
|
||||
#define MC13783_REG_VRFCP 13
|
||||
#define MC13783_REG_VSIM 14
|
||||
#define MC13783_REG_VESIM 15
|
||||
#define MC13783_REG_VCAM 16
|
||||
#define MC13783_REG_VRFBG 17
|
||||
#define MC13783_REG_VVIB 18
|
||||
#define MC13783_REG_VRF1 19
|
||||
#define MC13783_REG_VRF2 20
|
||||
#define MC13783_REG_VMMC1 21
|
||||
#define MC13783_REG_VMMC2 22
|
||||
#define MC13783_REG_GPO1 23
|
||||
#define MC13783_REG_GPO2 24
|
||||
#define MC13783_REG_GPO3 25
|
||||
#define MC13783_REG_GPO4 26
|
||||
#define MC13783_REG_V1 27
|
||||
#define MC13783_REG_V2 28
|
||||
#define MC13783_REG_V3 29
|
||||
#define MC13783_REG_V4 30
|
||||
#define MC13783_REG_PWGT1SPI 31
|
||||
#define MC13783_REG_PWGT2SPI 32
|
||||
|
||||
#define MC13783_IRQ_ADCDONE MC13XXX_IRQ_ADCDONE
|
||||
#define MC13783_IRQ_ADCBISDONE MC13XXX_IRQ_ADCBISDONE
|
||||
|
|
39
include/linux/mfd/mc13892.h
Normal file
39
include/linux/mfd/mc13892.h
Normal 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
|
|
@ -11,15 +11,17 @@
|
|||
#define __LINUX_MFD_AB8500_REGULATOR_H
|
||||
|
||||
/* AB8500 regulators */
|
||||
#define AB8500_LDO_AUX1 0
|
||||
#define AB8500_LDO_AUX2 1
|
||||
#define AB8500_LDO_AUX3 2
|
||||
#define AB8500_LDO_INTCORE 3
|
||||
#define AB8500_LDO_TVOUT 4
|
||||
#define AB8500_LDO_AUDIO 5
|
||||
#define AB8500_LDO_ANAMIC1 6
|
||||
#define AB8500_LDO_ANAMIC2 7
|
||||
#define AB8500_LDO_DMIC 8
|
||||
#define AB8500_LDO_ANA 9
|
||||
|
||||
enum ab8500_regulator_id {
|
||||
AB8500_LDO_AUX1,
|
||||
AB8500_LDO_AUX2,
|
||||
AB8500_LDO_AUX3,
|
||||
AB8500_LDO_INTCORE,
|
||||
AB8500_LDO_TVOUT,
|
||||
AB8500_LDO_AUDIO,
|
||||
AB8500_LDO_ANAMIC1,
|
||||
AB8500_LDO_ANAMIC2,
|
||||
AB8500_LDO_DMIC,
|
||||
AB8500_LDO_ANA,
|
||||
AB8500_NUM_REGULATORS,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -154,6 +154,7 @@ int regulator_is_supported_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_sync_voltage(struct regulator *regulator);
|
||||
int regulator_set_current_limit(struct regulator *regulator,
|
||||
int min_uA, int max_uA);
|
||||
int regulator_get_current_limit(struct regulator *regulator);
|
||||
|
|
|
@ -42,7 +42,11 @@ enum regulator_status {
|
|||
*
|
||||
* @set_voltage: Set the voltage for the regulator within the range specified.
|
||||
* 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_sel: Return the currently configured voltage selector for the
|
||||
* regulator.
|
||||
* @list_voltage: Return one of the supported voltages, in microvolts; zero
|
||||
* if the selector indicates a voltage that is unusable on this system;
|
||||
* 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);
|
||||
|
||||
/* 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_sel) (struct regulator_dev *);
|
||||
|
||||
/* get/set regulator current */
|
||||
int (*set_current_limit) (struct regulator_dev *,
|
||||
|
@ -168,9 +175,9 @@ struct regulator_desc {
|
|||
*/
|
||||
struct regulator_dev {
|
||||
struct regulator_desc *desc;
|
||||
int use_count;
|
||||
int open_count;
|
||||
int exclusive;
|
||||
u32 use_count;
|
||||
u32 open_count;
|
||||
|
||||
/* lists we belong to */
|
||||
struct list_head list; /* list of all regulators */
|
||||
|
@ -188,10 +195,14 @@ struct regulator_dev {
|
|||
struct regulator_dev *supply; /* for tree */
|
||||
|
||||
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 device *dev, struct regulator_init_data *init_data,
|
||||
struct device *dev, const struct regulator_init_data *init_data,
|
||||
void *driver_data);
|
||||
void regulator_unregister(struct regulator_dev *rdev);
|
||||
|
||||
|
|
141
include/trace/events/regulator.h
Normal file
141
include/trace/events/regulator.h
Normal 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>
|
Loading…
Reference in a new issue