2010-07-13 20:18:56 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* License Terms : GNU General Public License v2
*
2010-12-10 13:08:44 +03:00
* Authors : Sundar Iyer < sundar . iyer @ stericsson . com > for ST - Ericsson
* Bengt Jonsson < bengt . g . jonsson @ stericsson . com > for ST - Ericsson
2010-07-13 20:18:56 +04:00
*
* AB8500 peripheral regulators
*
2010-12-10 13:08:44 +03:00
* AB8500 supports the following regulators :
2011-03-10 16:43:31 +03:00
* VAUX1 / 2 / 3 , VINTCORE , VTVOUT , VUSB , VAUDIO , VAMIC1 / 2 , VDMIC , VANA
2010-07-13 20:18:56 +04:00
*/
# include <linux/init.h>
# include <linux/kernel.h>
2011-07-18 00:28:23 +04:00
# include <linux/module.h>
2010-07-13 20:18:56 +04:00
# include <linux/err.h>
# include <linux/platform_device.h>
2010-09-10 19:47:56 +04:00
# include <linux/mfd/abx500.h>
2011-12-02 17:16:33 +04:00
# include <linux/mfd/abx500/ab8500.h>
2012-05-17 17:45:16 +04:00
# include <linux/of.h>
# include <linux/regulator/of_regulator.h>
2010-07-13 20:18:56 +04:00
# include <linux/regulator/driver.h>
# include <linux/regulator/machine.h>
# include <linux/regulator/ab8500.h>
2012-05-17 17:45:16 +04:00
# include <linux/slab.h>
2010-07-13 20:18:56 +04:00
/**
* struct ab8500_regulator_info - ab8500 regulator information
2010-12-10 13:08:44 +03:00
* @ dev : device pointer
2010-07-13 20:18:56 +04:00
* @ desc : regulator description
* @ 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 )
2010-09-10 19:47:56 +04:00
* @ update_bank : bank to control on / off
2010-07-13 20:18:56 +04:00
* @ update_reg : register to control on / off
2010-12-10 13:08:44 +03:00
* @ update_mask : mask to enable / disable regulator
* @ update_val_enable : bits to enable the regulator in normal ( high power ) mode
2010-09-10 19:47:56 +04:00
* @ voltage_bank : bank to control regulator voltage
2010-07-13 20:18:56 +04:00
* @ voltage_reg : register to control regulator voltage
* @ voltage_mask : mask to control regulator voltage
2011-03-17 15:25:02 +03:00
* @ delay : startup / set voltage delay in us
2010-07-13 20:18:56 +04:00
*/
struct ab8500_regulator_info {
struct device * dev ;
struct regulator_desc desc ;
struct regulator_dev * regulator ;
int max_uV ;
int min_uV ;
int fixed_uV ;
2010-09-10 19:47:56 +04:00
u8 update_bank ;
u8 update_reg ;
2010-12-10 13:08:44 +03:00
u8 update_mask ;
u8 update_val_enable ;
2010-09-10 19:47:56 +04:00
u8 voltage_bank ;
u8 voltage_reg ;
u8 voltage_mask ;
2011-03-17 15:25:02 +03:00
unsigned int delay ;
2010-07-13 20:18:56 +04:00
} ;
/* voltage tables for the vauxn/vintcore supplies */
2012-05-20 06:33:35 +04:00
static const unsigned int ldo_vauxn_voltages [ ] = {
2010-07-13 20:18:56 +04:00
1100000 ,
1200000 ,
1300000 ,
1400000 ,
1500000 ,
1800000 ,
1850000 ,
1900000 ,
2500000 ,
2650000 ,
2700000 ,
2750000 ,
2800000 ,
2900000 ,
3000000 ,
3300000 ,
} ;
2012-05-20 06:33:35 +04:00
static const unsigned int ldo_vaux3_voltages [ ] = {
2010-12-10 13:08:43 +03:00
1200000 ,
1500000 ,
1800000 ,
2100000 ,
2500000 ,
2750000 ,
2790000 ,
2910000 ,
} ;
2012-05-20 06:33:35 +04:00
static const unsigned int ldo_vintcore_voltages [ ] = {
2010-07-13 20:18:56 +04:00
1200000 ,
1225000 ,
1250000 ,
1275000 ,
1300000 ,
1325000 ,
1350000 ,
} ;
static int ab8500_regulator_enable ( struct regulator_dev * rdev )
{
2010-12-10 13:08:45 +03:00
int ret ;
2010-07-13 20:18:56 +04:00
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
2010-12-10 13:08:45 +03:00
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
2010-07-13 20:18:56 +04:00
return - EINVAL ;
2010-12-10 13:08:45 +03:00
}
2010-07-13 20:18:56 +04:00
2010-09-10 19:47:56 +04:00
ret = abx500_mask_and_set_register_interruptible ( info - > dev ,
2010-12-10 13:08:44 +03:00
info - > update_bank , info - > update_reg ,
info - > update_mask , info - > update_val_enable ) ;
2010-07-13 20:18:56 +04:00
if ( ret < 0 )
dev_err ( rdev_get_dev ( rdev ) ,
" couldn't set enable bits for regulator \n " ) ;
2010-12-10 13:08:46 +03:00
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 ) ;
2010-07-13 20:18:56 +04:00
return ret ;
}
static int ab8500_regulator_disable ( struct regulator_dev * rdev )
{
2010-12-10 13:08:45 +03:00
int ret ;
2010-07-13 20:18:56 +04:00
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
2010-12-10 13:08:45 +03:00
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
2010-07-13 20:18:56 +04:00
return - EINVAL ;
2010-12-10 13:08:45 +03:00
}
2010-07-13 20:18:56 +04:00
2010-09-10 19:47:56 +04:00
ret = abx500_mask_and_set_register_interruptible ( info - > dev ,
2010-12-10 13:08:44 +03:00
info - > update_bank , info - > update_reg ,
info - > update_mask , 0x0 ) ;
2010-07-13 20:18:56 +04:00
if ( ret < 0 )
dev_err ( rdev_get_dev ( rdev ) ,
" couldn't set disable bits for regulator \n " ) ;
2010-12-10 13:08:46 +03:00
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 ) ;
2010-07-13 20:18:56 +04:00
return ret ;
}
static int ab8500_regulator_is_enabled ( struct regulator_dev * rdev )
{
2010-12-10 13:08:45 +03:00
int ret ;
2010-07-13 20:18:56 +04:00
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
2010-12-10 13:08:46 +03:00
u8 regval ;
2010-07-13 20:18:56 +04:00
2010-12-10 13:08:45 +03:00
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
2010-07-13 20:18:56 +04:00
return - EINVAL ;
2010-12-10 13:08:45 +03:00
}
2010-07-13 20:18:56 +04:00
2010-09-10 19:47:56 +04:00
ret = abx500_get_register_interruptible ( info - > dev ,
2010-12-10 13:08:46 +03:00
info - > update_bank , info - > update_reg , & regval ) ;
2010-07-13 20:18:56 +04:00
if ( ret < 0 ) {
dev_err ( rdev_get_dev ( rdev ) ,
" couldn't read 0x%x register \n " , info - > update_reg ) ;
return ret ;
}
2010-12-10 13:08:46 +03:00
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 )
2010-07-13 20:18:56 +04:00
return true ;
else
return false ;
}
2012-02-24 13:15:45 +04:00
static int ab8500_regulator_get_voltage_sel ( struct regulator_dev * rdev )
2010-07-13 20:18:56 +04:00
{
2010-12-10 13:08:46 +03:00
int ret , val ;
2010-07-13 20:18:56 +04:00
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
2010-12-10 13:08:46 +03:00
u8 regval ;
2010-07-13 20:18:56 +04:00
2010-12-10 13:08:45 +03:00
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
2010-07-13 20:18:56 +04:00
return - EINVAL ;
2010-12-10 13:08:45 +03:00
}
2010-07-13 20:18:56 +04:00
2010-12-10 13:08:46 +03:00
ret = abx500_get_register_interruptible ( info - > dev ,
info - > voltage_bank , info - > voltage_reg , & regval ) ;
2010-07-13 20:18:56 +04:00
if ( ret < 0 ) {
dev_err ( rdev_get_dev ( rdev ) ,
" couldn't read voltage reg for regulator \n " ) ;
return ret ;
}
2010-12-10 13:08:46 +03:00
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 ) ;
2010-07-13 20:18:56 +04:00
/* vintcore has a different layout */
2010-12-10 13:08:46 +03:00
val = regval & info - > voltage_mask ;
2010-12-10 13:08:45 +03:00
if ( info - > desc . id = = AB8500_LDO_INTCORE )
2012-02-24 13:15:45 +04:00
return val > > 0x3 ;
2010-07-13 20:18:56 +04:00
else
2012-02-24 13:15:45 +04:00
return val ;
2010-07-13 20:18:56 +04:00
}
2012-03-20 05:51:08 +04:00
static int ab8500_regulator_set_voltage_sel ( struct regulator_dev * rdev ,
unsigned selector )
2010-07-13 20:18:56 +04:00
{
2010-12-10 13:08:45 +03:00
int ret ;
2010-07-13 20:18:56 +04:00
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
2010-12-10 13:08:46 +03:00
u8 regval ;
2010-07-13 20:18:56 +04:00
2010-12-10 13:08:45 +03:00
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
2010-07-13 20:18:56 +04:00
return - EINVAL ;
2010-12-10 13:08:45 +03:00
}
2010-07-13 20:18:56 +04:00
/* set the registers for the request */
2012-03-20 05:51:08 +04:00
regval = ( u8 ) selector ;
2010-09-10 19:47:56 +04:00
ret = abx500_mask_and_set_register_interruptible ( info - > dev ,
2010-12-10 13:08:46 +03:00
info - > voltage_bank , info - > voltage_reg ,
info - > voltage_mask , regval ) ;
2010-07-13 20:18:56 +04:00
if ( ret < 0 )
dev_err ( rdev_get_dev ( rdev ) ,
" couldn't set voltage reg for regulator \n " ) ;
2010-12-10 13:08:46 +03:00
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 ) ;
2010-07-13 20:18:56 +04:00
return ret ;
}
2011-03-17 15:25:02 +03:00
static int ab8500_regulator_enable_time ( struct regulator_dev * rdev )
{
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
return info - > delay ;
}
static int ab8500_regulator_set_voltage_time_sel ( struct regulator_dev * rdev ,
unsigned int old_sel ,
unsigned int new_sel )
{
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
return info - > delay ;
}
2010-07-13 20:18:56 +04:00
static struct regulator_ops ab8500_regulator_ops = {
. enable = ab8500_regulator_enable ,
. disable = ab8500_regulator_disable ,
. is_enabled = ab8500_regulator_is_enabled ,
2012-02-24 13:15:45 +04:00
. get_voltage_sel = ab8500_regulator_get_voltage_sel ,
2012-03-20 05:51:08 +04:00
. set_voltage_sel = ab8500_regulator_set_voltage_sel ,
2012-05-20 06:33:35 +04:00
. list_voltage = regulator_list_voltage_table ,
2011-03-17 15:25:02 +03:00
. enable_time = ab8500_regulator_enable_time ,
. set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel ,
2010-07-13 20:18:56 +04:00
} ;
2012-05-20 06:33:35 +04:00
static int ab8500_fixed_list_voltage ( struct regulator_dev * rdev ,
unsigned selector )
{
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
return - EINVAL ;
}
return info - > fixed_uV ;
}
2010-07-13 20:18:56 +04:00
static int ab8500_fixed_get_voltage ( struct regulator_dev * rdev )
{
struct ab8500_regulator_info * info = rdev_get_drvdata ( rdev ) ;
2010-12-10 13:08:45 +03:00
if ( info = = NULL ) {
dev_err ( rdev_get_dev ( rdev ) , " regulator info null pointer \n " ) ;
2010-07-13 20:18:56 +04:00
return - EINVAL ;
2010-12-10 13:08:45 +03:00
}
2010-07-13 20:18:56 +04:00
return info - > fixed_uV ;
}
2010-12-10 13:08:47 +03:00
static struct regulator_ops ab8500_regulator_fixed_ops = {
2010-07-13 20:18:56 +04:00
. enable = ab8500_regulator_enable ,
. disable = ab8500_regulator_disable ,
. is_enabled = ab8500_regulator_is_enabled ,
. get_voltage = ab8500_fixed_get_voltage ,
2012-05-20 06:33:35 +04:00
. list_voltage = ab8500_fixed_list_voltage ,
2011-03-17 15:25:02 +03:00
. enable_time = ab8500_regulator_enable_time ,
. set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel ,
2010-07-13 20:18:56 +04:00
} ;
2010-12-10 13:08:47 +03:00
static struct ab8500_regulator_info
ab8500_regulator_info [ AB8500_NUM_REGULATORS ] = {
2010-07-13 20:18:56 +04:00
/*
2010-12-10 13:08:44 +03:00
* Variable Voltage Regulators
* name , min mV , max mV ,
* update bank , reg , mask , enable val
2012-05-20 06:33:35 +04:00
* volt bank , reg , mask
2010-07-13 20:18:56 +04:00
*/
2010-12-10 13:08:47 +03:00
[ 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 ) ,
2012-05-20 06:33:35 +04:00
. volt_table = ldo_vauxn_voltages ,
2010-12-10 13:08:47 +03:00
} ,
. 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 ,
} ,
[ 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 ) ,
2012-05-20 06:33:35 +04:00
. volt_table = ldo_vauxn_voltages ,
2010-12-10 13:08:47 +03:00
} ,
. 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 ,
} ,
[ 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 ) ,
2012-05-20 06:33:35 +04:00
. volt_table = ldo_vaux3_voltages ,
2010-12-10 13:08:47 +03:00
} ,
. 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 ,
} ,
[ 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 ) ,
2012-05-20 06:33:35 +04:00
. volt_table = ldo_vintcore_voltages ,
2010-12-10 13:08:47 +03:00
} ,
. 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 ,
} ,
2010-07-13 20:18:56 +04:00
/*
2010-12-10 13:08:44 +03:00
* Fixed Voltage Regulators
* name , fixed mV ,
* update bank , reg , mask , enable val
2010-07-13 20:18:56 +04:00
*/
2010-12-10 13:08:47 +03:00
[ 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 ,
} ,
2011-03-17 15:25:02 +03:00
. delay = 10000 ,
2010-12-10 13:08:47 +03:00
. fixed_uV = 2000000 ,
. update_bank = 0x03 ,
. update_reg = 0x80 ,
. update_mask = 0x82 ,
. update_val_enable = 0x02 ,
} ,
2011-03-10 16:43:31 +03:00
[ AB8500_LDO_USB ] = {
. desc = {
. name = " LDO-USB " ,
. ops = & ab8500_regulator_fixed_ops ,
. type = REGULATOR_VOLTAGE ,
. id = AB8500_LDO_USB ,
. owner = THIS_MODULE ,
. n_voltages = 1 ,
} ,
. fixed_uV = 3300000 ,
. update_bank = 0x03 ,
. update_reg = 0x82 ,
. update_mask = 0x03 ,
. update_val_enable = 0x01 ,
} ,
2010-12-10 13:08:47 +03:00
[ 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 ,
} ,
2010-07-13 20:18:56 +04:00
} ;
regulator: initialization for ab8500 regulators
The regulators on the AB8500 have a lot of custom
hardware control settings pertaining to 8 external
signals, settings which are board-specific and need
be provided from the platform at startup.
Initialization added for regulators Vana, VextSupply1,
VextSupply2, VextSupply3, Vaux1, Vaux2, Vaux3, VTVout,
Vintcore12, Vaudio, Vdmic, Vamic1, Vamic2, VrefDDR.
Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
Reviewed-by: Rickard Andersson <rickard.andersson@stericsson.com>
Reviewed-by: Jonas Aberg <jonas.aberg@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
2011-03-11 13:54:46 +03:00
struct ab8500_reg_init {
u8 bank ;
u8 addr ;
u8 mask ;
} ;
# define REG_INIT(_id, _bank, _addr, _mask) \
[ _id ] = { \
. bank = _bank , \
. addr = _addr , \
. mask = _mask , \
}
static struct ab8500_reg_init ab8500_reg_init [ ] = {
/*
* 0x30 , VanaRequestCtrl
* 0x0C , VpllRequestCtrl
* 0xc0 , VextSupply1RequestCtrl
*/
REG_INIT ( AB8500_REGUREQUESTCTRL2 , 0x03 , 0x04 , 0xfc ) ,
/*
* 0x03 , VextSupply2RequestCtrl
* 0x0c , VextSupply3RequestCtrl
* 0x30 , Vaux1RequestCtrl
* 0xc0 , Vaux2RequestCtrl
*/
REG_INIT ( AB8500_REGUREQUESTCTRL3 , 0x03 , 0x05 , 0xff ) ,
/*
* 0x03 , Vaux3RequestCtrl
* 0x04 , SwHPReq
*/
REG_INIT ( AB8500_REGUREQUESTCTRL4 , 0x03 , 0x06 , 0x07 ) ,
/*
* 0x08 , VanaSysClkReq1HPValid
* 0x20 , Vaux1SysClkReq1HPValid
* 0x40 , Vaux2SysClkReq1HPValid
* 0x80 , Vaux3SysClkReq1HPValid
*/
REG_INIT ( AB8500_REGUSYSCLKREQ1HPVALID1 , 0x03 , 0x07 , 0xe8 ) ,
/*
* 0x10 , VextSupply1SysClkReq1HPValid
* 0x20 , VextSupply2SysClkReq1HPValid
* 0x40 , VextSupply3SysClkReq1HPValid
*/
REG_INIT ( AB8500_REGUSYSCLKREQ1HPVALID2 , 0x03 , 0x08 , 0x70 ) ,
/*
* 0x08 , VanaHwHPReq1Valid
* 0x20 , Vaux1HwHPReq1Valid
* 0x40 , Vaux2HwHPReq1Valid
* 0x80 , Vaux3HwHPReq1Valid
*/
REG_INIT ( AB8500_REGUHWHPREQ1VALID1 , 0x03 , 0x09 , 0xe8 ) ,
/*
* 0x01 , VextSupply1HwHPReq1Valid
* 0x02 , VextSupply2HwHPReq1Valid
* 0x04 , VextSupply3HwHPReq1Valid
*/
REG_INIT ( AB8500_REGUHWHPREQ1VALID2 , 0x03 , 0x0a , 0x07 ) ,
/*
* 0x08 , VanaHwHPReq2Valid
* 0x20 , Vaux1HwHPReq2Valid
* 0x40 , Vaux2HwHPReq2Valid
* 0x80 , Vaux3HwHPReq2Valid
*/
REG_INIT ( AB8500_REGUHWHPREQ2VALID1 , 0x03 , 0x0b , 0xe8 ) ,
/*
* 0x01 , VextSupply1HwHPReq2Valid
* 0x02 , VextSupply2HwHPReq2Valid
* 0x04 , VextSupply3HwHPReq2Valid
*/
REG_INIT ( AB8500_REGUHWHPREQ2VALID2 , 0x03 , 0x0c , 0x07 ) ,
/*
* 0x20 , VanaSwHPReqValid
* 0x80 , Vaux1SwHPReqValid
*/
REG_INIT ( AB8500_REGUSWHPREQVALID1 , 0x03 , 0x0d , 0xa0 ) ,
/*
* 0x01 , Vaux2SwHPReqValid
* 0x02 , Vaux3SwHPReqValid
* 0x04 , VextSupply1SwHPReqValid
* 0x08 , VextSupply2SwHPReqValid
* 0x10 , VextSupply3SwHPReqValid
*/
REG_INIT ( AB8500_REGUSWHPREQVALID2 , 0x03 , 0x0e , 0x1f ) ,
/*
* 0x02 , SysClkReq2Valid1
* . . .
* 0x80 , SysClkReq8Valid1
*/
REG_INIT ( AB8500_REGUSYSCLKREQVALID1 , 0x03 , 0x0f , 0xfe ) ,
/*
* 0x02 , SysClkReq2Valid2
* . . .
* 0x80 , SysClkReq8Valid2
*/
REG_INIT ( AB8500_REGUSYSCLKREQVALID2 , 0x03 , 0x10 , 0xfe ) ,
/*
* 0x02 , VTVoutEna
* 0x04 , Vintcore12Ena
* 0x38 , Vintcore12Sel
* 0x40 , Vintcore12LP
* 0x80 , VTVoutLP
*/
REG_INIT ( AB8500_REGUMISC1 , 0x03 , 0x80 , 0xfe ) ,
/*
* 0x02 , VaudioEna
* 0x04 , VdmicEna
* 0x08 , Vamic1Ena
* 0x10 , Vamic2Ena
*/
REG_INIT ( AB8500_VAUDIOSUPPLY , 0x03 , 0x83 , 0x1e ) ,
/*
* 0x01 , Vamic1_dzout
* 0x02 , Vamic2_dzout
*/
REG_INIT ( AB8500_REGUCTRL1VAMIC , 0x03 , 0x84 , 0x03 ) ,
/*
* 0x0c , VanaRegu
* 0x03 , VpllRegu
*/
REG_INIT ( AB8500_VPLLVANAREGU , 0x04 , 0x06 , 0x0f ) ,
/*
* 0x01 , VrefDDREna
* 0x02 , VrefDDRSleepMode
*/
REG_INIT ( AB8500_VREFDDR , 0x04 , 0x07 , 0x03 ) ,
/*
* 0x03 , VextSupply1Regu
* 0x0c , VextSupply2Regu
* 0x30 , VextSupply3Regu
* 0x40 , ExtSupply2Bypass
* 0x80 , ExtSupply3Bypass
*/
REG_INIT ( AB8500_EXTSUPPLYREGU , 0x04 , 0x08 , 0xff ) ,
/*
* 0x03 , Vaux1Regu
* 0x0c , Vaux2Regu
*/
REG_INIT ( AB8500_VAUX12REGU , 0x04 , 0x09 , 0x0f ) ,
/*
* 0x03 , Vaux3Regu
*/
REG_INIT ( AB8500_VRF1VAUX3REGU , 0x04 , 0x0a , 0x03 ) ,
/*
* 0x3f , Vsmps1Sel1
*/
REG_INIT ( AB8500_VSMPS1SEL1 , 0x04 , 0x13 , 0x3f ) ,
/*
* 0x0f , Vaux1Sel
*/
REG_INIT ( AB8500_VAUX1SEL , 0x04 , 0x1f , 0x0f ) ,
/*
* 0x0f , Vaux2Sel
*/
REG_INIT ( AB8500_VAUX2SEL , 0x04 , 0x20 , 0x0f ) ,
/*
* 0x07 , Vaux3Sel
*/
REG_INIT ( AB8500_VRF1VAUX3SEL , 0x04 , 0x21 , 0x07 ) ,
/*
* 0x01 , VextSupply12LP
*/
REG_INIT ( AB8500_REGUCTRL2SPARE , 0x04 , 0x22 , 0x01 ) ,
/*
* 0x04 , Vaux1Disch
* 0x08 , Vaux2Disch
* 0x10 , Vaux3Disch
* 0x20 , Vintcore12Disch
* 0x40 , VTVoutDisch
* 0x80 , VaudioDisch
*/
REG_INIT ( AB8500_REGUCTRLDISCH , 0x04 , 0x43 , 0xfc ) ,
/*
* 0x02 , VanaDisch
* 0x04 , VdmicPullDownEna
* 0x10 , VdmicDisch
*/
REG_INIT ( AB8500_REGUCTRLDISCH2 , 0x04 , 0x44 , 0x16 ) ,
} ;
2012-05-17 17:45:14 +04:00
static __devinit int
ab8500_regulator_init_registers ( struct platform_device * pdev , int id , int value )
{
int err ;
if ( value & ~ ab8500_reg_init [ id ] . mask ) {
dev_err ( & pdev - > dev ,
" Configuration error: value outside mask. \n " ) ;
return - EINVAL ;
}
err = abx500_mask_and_set_register_interruptible (
& pdev - > dev ,
ab8500_reg_init [ id ] . bank ,
ab8500_reg_init [ id ] . addr ,
ab8500_reg_init [ id ] . mask ,
value ) ;
if ( err < 0 ) {
dev_err ( & pdev - > dev ,
" Failed to initialize 0x%02x, 0x%02x. \n " ,
ab8500_reg_init [ id ] . bank ,
ab8500_reg_init [ id ] . addr ) ;
return err ;
}
dev_vdbg ( & pdev - > dev ,
" init: 0x%02x, 0x%02x, 0x%02x, 0x%02x \n " ,
ab8500_reg_init [ id ] . bank ,
ab8500_reg_init [ id ] . addr ,
ab8500_reg_init [ id ] . mask ,
value ) ;
return 0 ;
}
static __devinit int ab8500_regulator_register ( struct platform_device * pdev ,
struct regulator_init_data * init_data ,
int id ,
struct device_node * np )
{
struct ab8500_regulator_info * info = NULL ;
struct regulator_config config = { } ;
int err ;
/* assign per-regulator data */
info = & ab8500_regulator_info [ id ] ;
info - > dev = & pdev - > dev ;
config . dev = & pdev - > dev ;
config . init_data = init_data ;
config . driver_data = info ;
config . of_node = np ;
/* 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 ) ;
2012-05-20 06:33:35 +04:00
info - > desc . volt_table = ldo_vauxn_voltages ;
2012-05-17 17:45:14 +04:00
info - > voltage_mask = 0xf ;
}
}
/* register regulator with framework */
info - > regulator = regulator_register ( & info - > desc , & config ) ;
if ( IS_ERR ( info - > regulator ) ) {
err = PTR_ERR ( info - > regulator ) ;
dev_err ( & pdev - > dev , " failed to register regulator %s \n " ,
info - > desc . name ) ;
/* when we fail, un-register all earlier regulators */
while ( - - id > = 0 ) {
info = & ab8500_regulator_info [ id ] ;
regulator_unregister ( info - > regulator ) ;
}
return err ;
}
return 0 ;
}
2012-05-17 17:45:16 +04:00
static struct of_regulator_match ab8500_regulator_matches [ ] = {
{ . name = " LDO-AUX1 " , . driver_data = ( void * ) AB8500_LDO_AUX1 , } ,
{ . name = " LDO-AUX2 " , . driver_data = ( void * ) AB8500_LDO_AUX2 , } ,
{ . name = " LDO-AUX3 " , . driver_data = ( void * ) AB8500_LDO_AUX3 , } ,
{ . name = " LDO-INTCORE " , . driver_data = ( void * ) AB8500_LDO_INTCORE , } ,
{ . name = " LDO-TVOUT " , . driver_data = ( void * ) AB8500_LDO_TVOUT , } ,
{ . name = " LDO-USB " , . driver_data = ( void * ) AB8500_LDO_USB , } ,
{ . name = " LDO-AUDIO " , . driver_data = ( void * ) AB8500_LDO_AUDIO , } ,
{ . name = " LDO-ANAMIC1 " , . driver_data = ( void * ) AB8500_LDO_ANAMIC1 , } ,
{ . name = " LDO-ANAMIC2 " , . driver_data = ( void * ) AB8500_LDO_ANAMIC2 , } ,
{ . name = " LDO-DMIC " , . driver_data = ( void * ) AB8500_LDO_DMIC , } ,
{ . name = " LDO-ANA " , . driver_data = ( void * ) AB8500_LDO_ANA , } ,
} ;
static __devinit int
ab8500_regulator_of_probe ( struct platform_device * pdev , struct device_node * np )
{
int err , i ;
for ( i = 0 ; i < ARRAY_SIZE ( ab8500_regulator_info ) ; i + + ) {
err = ab8500_regulator_register (
pdev , ab8500_regulator_matches [ i ] . init_data ,
i , ab8500_regulator_matches [ i ] . of_node ) ;
if ( err )
return err ;
}
return 0 ;
}
2010-07-13 20:18:56 +04:00
static __devinit int ab8500_regulator_probe ( struct platform_device * pdev )
{
struct ab8500 * ab8500 = dev_get_drvdata ( pdev - > dev . parent ) ;
2010-08-14 13:03:16 +04:00
struct ab8500_platform_data * pdata ;
2012-05-17 17:45:16 +04:00
struct device_node * np = pdev - > dev . of_node ;
2010-07-13 20:18:56 +04:00
int i , err ;
2012-05-17 17:45:16 +04:00
if ( np ) {
err = of_regulator_match ( & pdev - > dev , np ,
ab8500_regulator_matches ,
ARRAY_SIZE ( ab8500_regulator_matches ) ) ;
if ( err < 0 ) {
dev_err ( & pdev - > dev ,
" Error parsing regulator init data: %d \n " , err ) ;
return err ;
}
err = ab8500_regulator_of_probe ( pdev , np ) ;
return err ;
}
2010-07-13 20:18:56 +04:00
if ( ! ab8500 ) {
dev_err ( & pdev - > dev , " null mfd parent \n " ) ;
return - EINVAL ;
}
2010-08-14 13:03:16 +04:00
pdata = dev_get_platdata ( ab8500 - > dev ) ;
2010-12-10 13:08:45 +03:00
if ( ! pdata ) {
dev_err ( & pdev - > dev , " null pdata \n " ) ;
return - EINVAL ;
}
2010-07-13 20:18:56 +04:00
2010-12-10 13:08:40 +03:00
/* make sure the platform data has the correct size */
if ( pdata - > num_regulator ! = ARRAY_SIZE ( ab8500_regulator_info ) ) {
regulator: initialization for ab8500 regulators
The regulators on the AB8500 have a lot of custom
hardware control settings pertaining to 8 external
signals, settings which are board-specific and need
be provided from the platform at startup.
Initialization added for regulators Vana, VextSupply1,
VextSupply2, VextSupply3, Vaux1, Vaux2, Vaux3, VTVout,
Vintcore12, Vaudio, Vdmic, Vamic1, Vamic2, VrefDDR.
Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
Reviewed-by: Rickard Andersson <rickard.andersson@stericsson.com>
Reviewed-by: Jonas Aberg <jonas.aberg@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
2011-03-11 13:54:46 +03:00
dev_err ( & pdev - > dev , " Configuration error: size mismatch. \n " ) ;
2010-12-10 13:08:40 +03:00
return - EINVAL ;
}
regulator: initialization for ab8500 regulators
The regulators on the AB8500 have a lot of custom
hardware control settings pertaining to 8 external
signals, settings which are board-specific and need
be provided from the platform at startup.
Initialization added for regulators Vana, VextSupply1,
VextSupply2, VextSupply3, Vaux1, Vaux2, Vaux3, VTVout,
Vintcore12, Vaudio, Vdmic, Vamic1, Vamic2, VrefDDR.
Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
Reviewed-by: Rickard Andersson <rickard.andersson@stericsson.com>
Reviewed-by: Jonas Aberg <jonas.aberg@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
2011-03-11 13:54:46 +03:00
/* initialize registers */
for ( i = 0 ; i < pdata - > num_regulator_reg_init ; i + + ) {
2012-05-17 17:45:14 +04:00
int id , value ;
regulator: initialization for ab8500 regulators
The regulators on the AB8500 have a lot of custom
hardware control settings pertaining to 8 external
signals, settings which are board-specific and need
be provided from the platform at startup.
Initialization added for regulators Vana, VextSupply1,
VextSupply2, VextSupply3, Vaux1, Vaux2, Vaux3, VTVout,
Vintcore12, Vaudio, Vdmic, Vamic1, Vamic2, VrefDDR.
Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
Reviewed-by: Rickard Andersson <rickard.andersson@stericsson.com>
Reviewed-by: Jonas Aberg <jonas.aberg@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
2011-03-11 13:54:46 +03:00
id = pdata - > regulator_reg_init [ i ] . id ;
value = pdata - > regulator_reg_init [ i ] . value ;
/* check for configuration errors */
if ( id > = AB8500_NUM_REGULATOR_REGISTERS ) {
dev_err ( & pdev - > dev ,
" Configuration error: id outside range. \n " ) ;
return - EINVAL ;
}
2012-05-17 17:45:14 +04:00
err = ab8500_regulator_init_registers ( pdev , id , value ) ;
if ( err < 0 )
regulator: initialization for ab8500 regulators
The regulators on the AB8500 have a lot of custom
hardware control settings pertaining to 8 external
signals, settings which are board-specific and need
be provided from the platform at startup.
Initialization added for regulators Vana, VextSupply1,
VextSupply2, VextSupply3, Vaux1, Vaux2, Vaux3, VTVout,
Vintcore12, Vaudio, Vdmic, Vamic1, Vamic2, VrefDDR.
Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
Reviewed-by: Rickard Andersson <rickard.andersson@stericsson.com>
Reviewed-by: Jonas Aberg <jonas.aberg@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
2011-03-11 13:54:46 +03:00
return err ;
}
2010-07-13 20:18:56 +04:00
/* register all regulators */
for ( i = 0 ; i < ARRAY_SIZE ( ab8500_regulator_info ) ; i + + ) {
2012-05-17 17:45:14 +04:00
err = ab8500_regulator_register ( pdev , & pdata - > regulator [ i ] , i , NULL ) ;
if ( err < 0 )
2010-07-13 20:18:56 +04:00
return err ;
}
return 0 ;
}
static __devexit int ab8500_regulator_remove ( struct platform_device * pdev )
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( ab8500_regulator_info ) ; i + + ) {
struct ab8500_regulator_info * info = NULL ;
info = & ab8500_regulator_info [ i ] ;
2010-12-10 13:08:46 +03:00
dev_vdbg ( rdev_get_dev ( info - > regulator ) ,
" %s-remove \n " , info - > desc . name ) ;
2010-07-13 20:18:56 +04:00
regulator_unregister ( info - > regulator ) ;
}
return 0 ;
}
2012-05-17 17:45:16 +04:00
static const struct of_device_id ab8500_regulator_match [ ] = {
{ . compatible = " stericsson,ab8500-regulator " , } ,
{ }
} ;
2010-07-13 20:18:56 +04:00
static struct platform_driver ab8500_regulator_driver = {
. probe = ab8500_regulator_probe ,
. remove = __devexit_p ( ab8500_regulator_remove ) ,
. driver = {
. name = " ab8500-regulator " ,
. owner = THIS_MODULE ,
2012-05-17 17:45:16 +04:00
. of_match_table = ab8500_regulator_match ,
2010-07-13 20:18:56 +04:00
} ,
} ;
static int __init ab8500_regulator_init ( void )
{
int ret ;
ret = platform_driver_register ( & ab8500_regulator_driver ) ;
if ( ret ! = 0 )
pr_err ( " Failed to register ab8500 regulator: %d \n " , ret ) ;
return ret ;
}
subsys_initcall ( ab8500_regulator_init ) ;
static void __exit ab8500_regulator_exit ( void )
{
platform_driver_unregister ( & ab8500_regulator_driver ) ;
}
module_exit ( ab8500_regulator_exit ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( " Sundar Iyer <sundar.iyer@stericsson.com> " ) ;
MODULE_DESCRIPTION ( " Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC " ) ;
MODULE_ALIAS ( " platform:ab8500-regulator " ) ;