2012-07-11 16:08:17 +04:00
/*
* s2mps11 . c
*
* Copyright ( c ) 2012 Samsung Electronics Co . , Ltd
* http : //www.samsung.com
*
* 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 .
*
*/
# include <linux/bug.h>
# include <linux/delay.h>
# include <linux/err.h>
# include <linux/gpio.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/regulator/driver.h>
# include <linux/regulator/machine.h>
# include <linux/mfd/samsung/core.h>
# include <linux/mfd/samsung/s2mps11.h>
struct s2mps11_info {
2012-07-13 06:12:40 +04:00
struct regulator_dev * rdev [ S2MPS11_REGULATOR_MAX ] ;
2012-07-11 16:08:17 +04:00
int ramp_delay2 ;
int ramp_delay34 ;
int ramp_delay5 ;
int ramp_delay16 ;
int ramp_delay7810 ;
int ramp_delay9 ;
bool buck6_ramp ;
bool buck2_ramp ;
bool buck3_ramp ;
bool buck4_ramp ;
} ;
static int get_ramp_delay ( int ramp_delay )
{
unsigned char cnt = 0 ;
ramp_delay / = 6 ;
while ( true ) {
ramp_delay = ramp_delay > > 1 ;
if ( ramp_delay = = 0 )
break ;
cnt + + ;
}
return cnt ;
}
static struct regulator_ops s2mps11_ldo_ops = {
. list_voltage = regulator_list_voltage_linear ,
. map_voltage = regulator_map_voltage_linear ,
. is_enabled = regulator_is_enabled_regmap ,
. enable = regulator_enable_regmap ,
. disable = regulator_disable_regmap ,
. get_voltage_sel = regulator_get_voltage_sel_regmap ,
. set_voltage_sel = regulator_set_voltage_sel_regmap ,
. set_voltage_time_sel = regulator_set_voltage_time_sel ,
} ;
static struct regulator_ops s2mps11_buck_ops = {
. list_voltage = regulator_list_voltage_linear ,
. map_voltage = regulator_map_voltage_linear ,
. is_enabled = regulator_is_enabled_regmap ,
. enable = regulator_enable_regmap ,
. disable = regulator_disable_regmap ,
. get_voltage_sel = regulator_get_voltage_sel_regmap ,
. set_voltage_sel = regulator_set_voltage_sel_regmap ,
. set_voltage_time_sel = regulator_set_voltage_time_sel ,
} ;
# define regulator_desc_ldo1(num) { \
. name = " LDO " # num , \
. id = S2MPS11_LDO # # num , \
. ops = & s2mps11_ldo_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_LDO_MIN , \
. uV_step = S2MPS11_LDO_STEP1 , \
. n_voltages = S2MPS11_LDO_N_VOLTAGES , \
. vsel_reg = S2MPS11_REG_L1CTRL + num - 1 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_LDO_VSEL_MASK , \
2012-07-11 16:08:17 +04:00
. enable_reg = S2MPS11_REG_L1CTRL + num - 1 , \
. enable_mask = S2MPS11_ENABLE_MASK \
}
# define regulator_desc_ldo2(num) { \
. name = " LDO " # num , \
. id = S2MPS11_LDO # # num , \
. ops = & s2mps11_ldo_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_LDO_MIN , \
. uV_step = S2MPS11_LDO_STEP2 , \
. n_voltages = S2MPS11_LDO_N_VOLTAGES , \
. vsel_reg = S2MPS11_REG_L1CTRL + num - 1 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_LDO_VSEL_MASK , \
2012-07-11 16:08:17 +04:00
. enable_reg = S2MPS11_REG_L1CTRL + num - 1 , \
. enable_mask = S2MPS11_ENABLE_MASK \
}
# define regulator_desc_buck1_4(num) { \
. name = " BUCK " # num , \
. id = S2MPS11_BUCK # # num , \
. ops = & s2mps11_buck_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_BUCK_MIN1 , \
. uV_step = S2MPS11_BUCK_STEP1 , \
. n_voltages = S2MPS11_BUCK_N_VOLTAGES , \
. vsel_reg = S2MPS11_REG_B1CTRL2 + ( num - 1 ) * 2 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_BUCK_VSEL_MASK , \
2012-07-11 16:08:17 +04:00
. enable_reg = S2MPS11_REG_B1CTRL1 + ( num - 1 ) * 2 , \
. enable_mask = S2MPS11_ENABLE_MASK \
}
# define regulator_desc_buck5 { \
. name = " BUCK5 " , \
. id = S2MPS11_BUCK5 , \
. ops = & s2mps11_buck_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_BUCK_MIN1 , \
. uV_step = S2MPS11_BUCK_STEP1 , \
. n_voltages = S2MPS11_BUCK_N_VOLTAGES , \
. vsel_reg = S2MPS11_REG_B5CTRL2 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_BUCK_VSEL_MASK , \
2012-07-11 16:08:17 +04:00
. enable_reg = S2MPS11_REG_B5CTRL1 , \
. enable_mask = S2MPS11_ENABLE_MASK \
}
# define regulator_desc_buck6_8(num) { \
. name = " BUCK " # num , \
. id = S2MPS11_BUCK # # num , \
. ops = & s2mps11_buck_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_BUCK_MIN1 , \
. uV_step = S2MPS11_BUCK_STEP1 , \
. n_voltages = S2MPS11_BUCK_N_VOLTAGES , \
. vsel_reg = S2MPS11_REG_B6CTRL2 + ( num - 6 ) * 2 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_BUCK_VSEL_MASK , \
2012-07-11 16:08:17 +04:00
. enable_reg = S2MPS11_REG_B6CTRL1 + ( num - 6 ) * 2 , \
. enable_mask = S2MPS11_ENABLE_MASK \
}
# define regulator_desc_buck9 { \
. name = " BUCK9 " , \
. id = S2MPS11_BUCK9 , \
. ops = & s2mps11_buck_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_BUCK_MIN3 , \
. uV_step = S2MPS11_BUCK_STEP3 , \
. n_voltages = S2MPS11_BUCK_N_VOLTAGES , \
. vsel_reg = S2MPS11_REG_B9CTRL2 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_BUCK_VSEL_MASK , \
2012-07-11 16:08:17 +04:00
. enable_reg = S2MPS11_REG_B9CTRL1 , \
. enable_mask = S2MPS11_ENABLE_MASK \
}
# define regulator_desc_buck10 { \
. name = " BUCK10 " , \
. id = S2MPS11_BUCK10 , \
. ops = & s2mps11_buck_ops , \
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
. min_uV = S2MPS11_BUCK_MIN2 , \
. uV_step = S2MPS11_BUCK_STEP2 , \
. n_voltages = S2MPS11_BUCK_N_VOLTAGES , \
2013-01-30 17:02:27 +04:00
. vsel_reg = S2MPS11_REG_B10CTRL2 , \
2012-07-12 05:35:50 +04:00
. vsel_mask = S2MPS11_BUCK_VSEL_MASK , \
2013-01-30 17:02:27 +04:00
. enable_reg = S2MPS11_REG_B10CTRL1 , \
2012-07-11 16:08:17 +04:00
. enable_mask = S2MPS11_ENABLE_MASK \
}
static struct regulator_desc regulators [ ] = {
regulator_desc_ldo2 ( 1 ) ,
regulator_desc_ldo1 ( 2 ) ,
regulator_desc_ldo1 ( 3 ) ,
regulator_desc_ldo1 ( 4 ) ,
regulator_desc_ldo1 ( 5 ) ,
regulator_desc_ldo2 ( 6 ) ,
regulator_desc_ldo1 ( 7 ) ,
regulator_desc_ldo1 ( 8 ) ,
regulator_desc_ldo1 ( 9 ) ,
regulator_desc_ldo1 ( 10 ) ,
regulator_desc_ldo2 ( 11 ) ,
regulator_desc_ldo1 ( 12 ) ,
regulator_desc_ldo1 ( 13 ) ,
regulator_desc_ldo1 ( 14 ) ,
regulator_desc_ldo1 ( 15 ) ,
regulator_desc_ldo1 ( 16 ) ,
regulator_desc_ldo1 ( 17 ) ,
regulator_desc_ldo1 ( 18 ) ,
regulator_desc_ldo1 ( 19 ) ,
regulator_desc_ldo1 ( 20 ) ,
regulator_desc_ldo1 ( 21 ) ,
regulator_desc_ldo2 ( 22 ) ,
regulator_desc_ldo2 ( 23 ) ,
regulator_desc_ldo1 ( 24 ) ,
regulator_desc_ldo1 ( 25 ) ,
regulator_desc_ldo1 ( 26 ) ,
regulator_desc_ldo2 ( 27 ) ,
regulator_desc_ldo1 ( 28 ) ,
regulator_desc_ldo1 ( 29 ) ,
regulator_desc_ldo1 ( 30 ) ,
regulator_desc_ldo1 ( 31 ) ,
regulator_desc_ldo1 ( 32 ) ,
regulator_desc_ldo1 ( 33 ) ,
regulator_desc_ldo1 ( 34 ) ,
regulator_desc_ldo1 ( 35 ) ,
regulator_desc_ldo1 ( 36 ) ,
regulator_desc_ldo1 ( 37 ) ,
regulator_desc_ldo1 ( 38 ) ,
regulator_desc_buck1_4 ( 1 ) ,
regulator_desc_buck1_4 ( 2 ) ,
regulator_desc_buck1_4 ( 3 ) ,
regulator_desc_buck1_4 ( 4 ) ,
regulator_desc_buck5 ,
regulator_desc_buck6_8 ( 6 ) ,
regulator_desc_buck6_8 ( 7 ) ,
regulator_desc_buck6_8 ( 8 ) ,
regulator_desc_buck9 ,
regulator_desc_buck10 ,
} ;
2012-11-19 22:22:22 +04:00
static int s2mps11_pmic_probe ( struct platform_device * pdev )
2012-07-11 16:08:17 +04:00
{
struct sec_pmic_dev * iodev = dev_get_drvdata ( pdev - > dev . parent ) ;
struct sec_platform_data * pdata = dev_get_platdata ( iodev - > dev ) ;
struct regulator_config config = { } ;
struct s2mps11_info * s2mps11 ;
2012-07-13 06:12:40 +04:00
int i , ret ;
2012-07-11 16:08:17 +04:00
unsigned char ramp_enable , ramp_reg = 0 ;
if ( ! pdata ) {
dev_err ( pdev - > dev . parent , " Platform data not supplied \n " ) ;
return - ENODEV ;
}
s2mps11 = devm_kzalloc ( & pdev - > dev , sizeof ( struct s2mps11_info ) ,
GFP_KERNEL ) ;
if ( ! s2mps11 )
return - ENOMEM ;
platform_set_drvdata ( pdev , s2mps11 ) ;
s2mps11 - > ramp_delay2 = pdata - > buck2_ramp_delay ;
s2mps11 - > ramp_delay34 = pdata - > buck34_ramp_delay ;
s2mps11 - > ramp_delay5 = pdata - > buck5_ramp_delay ;
s2mps11 - > ramp_delay16 = pdata - > buck16_ramp_delay ;
s2mps11 - > ramp_delay7810 = pdata - > buck7810_ramp_delay ;
s2mps11 - > ramp_delay9 = pdata - > buck9_ramp_delay ;
s2mps11 - > buck6_ramp = pdata - > buck6_ramp_enable ;
s2mps11 - > buck2_ramp = pdata - > buck2_ramp_enable ;
s2mps11 - > buck3_ramp = pdata - > buck3_ramp_enable ;
s2mps11 - > buck4_ramp = pdata - > buck4_ramp_enable ;
ramp_enable = ( s2mps11 - > buck2_ramp < < 3 ) | ( s2mps11 - > buck3_ramp < < 2 ) |
( s2mps11 - > buck4_ramp < < 1 ) | s2mps11 - > buck6_ramp ;
if ( ramp_enable ) {
if ( s2mps11 - > buck2_ramp )
2012-11-24 06:13:28 +04:00
ramp_reg | = get_ramp_delay ( s2mps11 - > ramp_delay2 ) < < 6 ;
2012-07-11 16:08:17 +04:00
if ( s2mps11 - > buck3_ramp | | s2mps11 - > buck4_ramp )
2012-11-24 06:13:28 +04:00
ramp_reg | = get_ramp_delay ( s2mps11 - > ramp_delay34 ) < < 4 ;
2012-07-12 05:39:10 +04:00
sec_reg_write ( iodev , S2MPS11_REG_RAMP , ramp_reg | ramp_enable ) ;
2012-07-11 16:08:17 +04:00
}
ramp_reg & = 0x00 ;
2012-11-24 06:13:28 +04:00
ramp_reg | = get_ramp_delay ( s2mps11 - > ramp_delay5 ) < < 6 ;
ramp_reg | = get_ramp_delay ( s2mps11 - > ramp_delay16 ) < < 4 ;
ramp_reg | = get_ramp_delay ( s2mps11 - > ramp_delay7810 ) < < 2 ;
2012-07-11 16:08:17 +04:00
ramp_reg | = get_ramp_delay ( s2mps11 - > ramp_delay9 ) ;
2012-07-12 05:39:10 +04:00
sec_reg_write ( iodev , S2MPS11_REG_RAMP_BUCK , ramp_reg ) ;
2012-07-11 16:08:17 +04:00
for ( i = 0 ; i < S2MPS11_REGULATOR_MAX ; i + + ) {
2012-07-12 05:37:37 +04:00
config . dev = & pdev - > dev ;
2012-07-11 16:08:17 +04:00
config . regmap = iodev - > regmap ;
config . init_data = pdata - > regulators [ i ] . initdata ;
config . driver_data = s2mps11 ;
2012-07-13 06:12:40 +04:00
s2mps11 - > rdev [ i ] = regulator_register ( & regulators [ i ] , & config ) ;
if ( IS_ERR ( s2mps11 - > rdev [ i ] ) ) {
ret = PTR_ERR ( s2mps11 - > rdev [ i ] ) ;
2012-07-12 05:37:37 +04:00
dev_err ( & pdev - > dev , " regulator init failed for %d \n " ,
i ) ;
2012-07-13 06:12:40 +04:00
s2mps11 - > rdev [ i ] = NULL ;
2012-07-11 16:08:17 +04:00
goto err ;
}
}
return 0 ;
err :
for ( i = 0 ; i < S2MPS11_REGULATOR_MAX ; i + + )
2012-07-13 06:12:40 +04:00
regulator_unregister ( s2mps11 - > rdev [ i ] ) ;
2012-07-11 16:08:17 +04:00
return ret ;
}
2012-11-19 22:26:10 +04:00
static int s2mps11_pmic_remove ( struct platform_device * pdev )
2012-07-11 16:08:17 +04:00
{
struct s2mps11_info * s2mps11 = platform_get_drvdata ( pdev ) ;
int i ;
for ( i = 0 ; i < S2MPS11_REGULATOR_MAX ; i + + )
2012-07-13 06:12:40 +04:00
regulator_unregister ( s2mps11 - > rdev [ i ] ) ;
2012-07-11 16:08:17 +04:00
return 0 ;
}
static const struct platform_device_id s2mps11_pmic_id [ ] = {
{ " s2mps11-pmic " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( platform , s2mps11_pmic_id ) ;
static struct platform_driver s2mps11_pmic_driver = {
. driver = {
. name = " s2mps11-pmic " ,
. owner = THIS_MODULE ,
} ,
. probe = s2mps11_pmic_probe ,
2012-11-19 22:20:42 +04:00
. remove = s2mps11_pmic_remove ,
2012-07-11 16:08:17 +04:00
. id_table = s2mps11_pmic_id ,
} ;
static int __init s2mps11_pmic_init ( void )
{
return platform_driver_register ( & s2mps11_pmic_driver ) ;
}
subsys_initcall ( s2mps11_pmic_init ) ;
static void __exit s2mps11_pmic_exit ( void )
{
platform_driver_unregister ( & s2mps11_pmic_driver ) ;
}
module_exit ( s2mps11_pmic_exit ) ;
/* Module information */
MODULE_AUTHOR ( " Sangbeom Kim <sbkim73@samsung.com> " ) ;
MODULE_DESCRIPTION ( " SAMSUNG S2MPS11 Regulator Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;