2019-05-28 20:10:04 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-03-22 17:04:09 +04:00
/*
* Regulator driver for tps65090 power management chip .
*
* Copyright ( c ) 2012 , NVIDIA CORPORATION . All rights reserved .
*/
# include <linux/module.h>
2014-04-23 19:56:05 +04:00
# include <linux/delay.h>
2012-03-22 17:04:09 +04:00
# include <linux/init.h>
2018-05-14 11:06:33 +03:00
# include <linux/of.h>
# include <linux/gpio/consumer.h>
2012-03-22 17:04:09 +04:00
# include <linux/slab.h>
# include <linux/err.h>
# include <linux/platform_device.h>
# include <linux/regulator/driver.h>
# include <linux/regulator/machine.h>
2013-01-29 13:05:16 +04:00
# include <linux/regulator/of_regulator.h>
2012-03-22 17:04:09 +04:00
# include <linux/mfd/tps65090.h>
2014-04-23 19:56:05 +04:00
# define MAX_CTRL_READ_TRIES 5
# define MAX_FET_ENABLE_TRIES 1000
# define CTRL_EN_BIT 0 /* Regulator enable bit, active high */
2014-04-17 03:12:28 +04:00
# define CTRL_WT_BIT 2 /* Regulator wait time 0 bit */
2014-04-23 19:56:05 +04:00
# define CTRL_PG_BIT 4 /* Regulator power good bit, 1=good */
# define CTRL_TO_BIT 7 /* Regulator timeout bit, 1=wait */
2014-04-17 03:12:28 +04:00
# define MAX_OVERCURRENT_WAIT 3 /* Overcurrent wait must be <= this */
/**
* struct tps65090_regulator - Per - regulator data for a tps65090 regulator
*
* @ dev : Pointer to our device .
* @ desc : The struct regulator_desc for the regulator .
* @ rdev : The struct regulator_dev for the regulator .
* @ overcurrent_wait_valid : True if overcurrent_wait is valid .
* @ overcurrent_wait : For FETs , the value to put in the WTFET bitfield .
*/
2012-03-22 17:04:09 +04:00
struct tps65090_regulator {
struct device * dev ;
2012-10-09 13:48:59 +04:00
struct regulator_desc * desc ;
struct regulator_dev * rdev ;
2014-04-17 03:12:28 +04:00
bool overcurrent_wait_valid ;
int overcurrent_wait ;
2012-03-22 17:04:09 +04:00
} ;
2020-08-30 01:11:01 +03:00
static const struct regulator_ops tps65090_ext_control_ops = {
2012-10-09 13:49:02 +04:00
} ;
2014-04-17 03:12:28 +04:00
/**
* tps65090_reg_set_overcurrent_wait - Setup overcurrent wait
*
* This will set the overcurrent wait time based on what ' s in the regulator
* info .
*
* @ ri : Overall regulator data
* @ rdev : Regulator device
*
* Return : 0 if no error , non - zero if there was an error writing the register .
*/
static int tps65090_reg_set_overcurrent_wait ( struct tps65090_regulator * ri ,
struct regulator_dev * rdev )
{
int ret ;
ret = regmap_update_bits ( rdev - > regmap , rdev - > desc - > enable_reg ,
MAX_OVERCURRENT_WAIT < < CTRL_WT_BIT ,
ri - > overcurrent_wait < < CTRL_WT_BIT ) ;
if ( ret ) {
dev_err ( & rdev - > dev , " Error updating overcurrent wait %#x \n " ,
rdev - > desc - > enable_reg ) ;
}
return ret ;
}
2014-04-23 19:56:05 +04:00
/**
* tps65090_try_enable_fet - Try to enable a FET
*
* @ rdev : Regulator device
*
* Return : 0 if ok , - ENOTRECOVERABLE if the FET power good bit did not get
* set , or some other - ve value if another error occurred ( e . g . i2c error )
*/
static int tps65090_try_enable_fet ( struct regulator_dev * rdev )
{
unsigned int control ;
int ret , i ;
ret = regmap_update_bits ( rdev - > regmap , rdev - > desc - > enable_reg ,
rdev - > desc - > enable_mask ,
rdev - > desc - > enable_mask ) ;
if ( ret < 0 ) {
dev_err ( & rdev - > dev , " Error in updating reg %#x \n " ,
rdev - > desc - > enable_reg ) ;
return ret ;
}
for ( i = 0 ; i < MAX_CTRL_READ_TRIES ; i + + ) {
ret = regmap_read ( rdev - > regmap , rdev - > desc - > enable_reg ,
& control ) ;
if ( ret < 0 )
return ret ;
if ( ! ( control & BIT ( CTRL_TO_BIT ) ) )
break ;
usleep_range ( 1000 , 1500 ) ;
}
if ( ! ( control & BIT ( CTRL_PG_BIT ) ) )
return - ENOTRECOVERABLE ;
return 0 ;
}
/**
* tps65090_fet_enable - Enable a FET , trying a few times if it fails
*
* Some versions of the tps65090 have issues when turning on the FETs .
* This function goes through several steps to ensure the best chance of the
* FET going on . Specifically :
* - We ' ll make sure that we bump the " overcurrent wait " to the maximum , which
* increases the chances that we ' ll turn on properly .
* - We ' ll retry turning the FET on multiple times ( turning off in between ) .
*
* @ rdev : Regulator device
*
* Return : 0 if ok , non - zero if it fails .
*/
static int tps65090_fet_enable ( struct regulator_dev * rdev )
{
int ret , tries ;
/*
* Try enabling multiple times until we succeed since sometimes the
* first try times out .
*/
tries = 0 ;
while ( true ) {
ret = tps65090_try_enable_fet ( rdev ) ;
if ( ! ret )
break ;
if ( ret ! = - ENOTRECOVERABLE | | tries = = MAX_FET_ENABLE_TRIES )
goto err ;
/* Try turning the FET off (and then on again) */
ret = regmap_update_bits ( rdev - > regmap , rdev - > desc - > enable_reg ,
rdev - > desc - > enable_mask , 0 ) ;
if ( ret )
goto err ;
tries + + ;
}
if ( tries )
dev_warn ( & rdev - > dev , " reg %#x enable ok after %d tries \n " ,
rdev - > desc - > enable_reg , tries ) ;
return 0 ;
err :
dev_warn ( & rdev - > dev , " reg %#x enable failed \n " , rdev - > desc - > enable_reg ) ;
WARN_ON ( 1 ) ;
return ret ;
}
2020-08-30 01:11:01 +03:00
static const struct regulator_ops tps65090_reg_control_ops = {
2012-10-09 13:49:02 +04:00
. enable = regulator_enable_regmap ,
. disable = regulator_disable_regmap ,
. is_enabled = regulator_is_enabled_regmap ,
2012-03-22 17:04:09 +04:00
} ;
2020-08-30 01:11:01 +03:00
static const struct regulator_ops tps65090_fet_control_ops = {
2014-04-23 19:56:05 +04:00
. enable = tps65090_fet_enable ,
. disable = regulator_disable_regmap ,
. is_enabled = regulator_is_enabled_regmap ,
} ;
2020-08-30 01:11:01 +03:00
static const struct regulator_ops tps65090_ldo_ops = {
2012-10-09 13:49:01 +04:00
} ;
2014-07-31 16:31:05 +04:00
# define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \
2012-03-22 17:04:09 +04:00
{ \
2012-10-09 13:48:59 +04:00
. name = " TPS65090_RAILS " # _id , \
. supply_name = _sname , \
2012-10-09 13:49:00 +04:00
. id = TPS65090_REGULATOR_ # # _id , \
2014-07-31 16:31:05 +04:00
. n_voltages = _nvolt , \
2012-10-09 13:48:59 +04:00
. ops = & _ops , \
2014-07-31 16:31:05 +04:00
. fixed_uV = _volt , \
2012-10-09 13:48:59 +04:00
. enable_reg = _en_reg , \
2014-04-23 19:56:05 +04:00
. enable_val = _en_bits , \
. enable_mask = _en_bits , \
2012-10-09 13:48:59 +04:00
. type = REGULATOR_VOLTAGE , \
. owner = THIS_MODULE , \
2012-03-22 17:04:09 +04:00
}
2014-07-31 16:31:05 +04:00
# define tps65090_REG_FIXEDV(_id, _sname, en_reg, _en_bits, _volt, _ops) \
tps65090_REG_DESC ( _id , _sname , en_reg , _en_bits , 1 , _volt , _ops )
# define tps65090_REG_SWITCH(_id, _sname, en_reg, _en_bits, _ops) \
tps65090_REG_DESC ( _id , _sname , en_reg , _en_bits , 0 , 0 , _ops )
2012-10-09 13:48:59 +04:00
static struct regulator_desc tps65090_regulator_desc [ ] = {
2014-07-31 16:31:05 +04:00
tps65090_REG_FIXEDV ( DCDC1 , " vsys1 " , 0x0C , BIT ( CTRL_EN_BIT ) , 5000000 ,
tps65090_reg_control_ops ) ,
tps65090_REG_FIXEDV ( DCDC2 , " vsys2 " , 0x0D , BIT ( CTRL_EN_BIT ) , 3300000 ,
tps65090_reg_control_ops ) ,
tps65090_REG_SWITCH ( DCDC3 , " vsys3 " , 0x0E , BIT ( CTRL_EN_BIT ) ,
tps65090_reg_control_ops ) ,
tps65090_REG_SWITCH ( FET1 , " infet1 " , 0x0F ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_SWITCH ( FET2 , " infet2 " , 0x10 ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_SWITCH ( FET3 , " infet3 " , 0x11 ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_SWITCH ( FET4 , " infet4 " , 0x12 ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_SWITCH ( FET5 , " infet5 " , 0x13 ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_SWITCH ( FET6 , " infet6 " , 0x14 ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_SWITCH ( FET7 , " infet7 " , 0x15 ,
BIT ( CTRL_EN_BIT ) | BIT ( CTRL_PG_BIT ) ,
tps65090_fet_control_ops ) ,
tps65090_REG_FIXEDV ( LDO1 , " vsys-l1 " , 0 , 0 , 5000000 ,
tps65090_ldo_ops ) ,
tps65090_REG_FIXEDV ( LDO2 , " vsys-l2 " , 0 , 0 , 3300000 ,
tps65090_ldo_ops ) ,
2012-03-22 17:04:09 +04:00
} ;
2012-10-09 13:48:59 +04:00
static inline bool is_dcdc ( int id )
2012-03-22 17:04:09 +04:00
{
2012-10-09 13:48:59 +04:00
switch ( id ) {
2012-10-09 13:49:00 +04:00
case TPS65090_REGULATOR_DCDC1 :
case TPS65090_REGULATOR_DCDC2 :
case TPS65090_REGULATOR_DCDC3 :
2012-10-09 13:48:59 +04:00
return true ;
default :
return false ;
}
}
2012-03-22 17:04:09 +04:00
2012-11-19 22:22:22 +04:00
static int tps65090_config_ext_control (
2012-10-09 13:48:59 +04:00
struct tps65090_regulator * ri , bool enable )
{
int ret ;
struct device * parent = ri - > dev - > parent ;
unsigned int reg_en_reg = ri - > desc - > enable_reg ;
if ( enable )
ret = tps65090_set_bits ( parent , reg_en_reg , 1 ) ;
else
ret = tps65090_clr_bits ( parent , reg_en_reg , 1 ) ;
if ( ret < 0 )
dev_err ( ri - > dev , " Error in updating reg 0x%x \n " , reg_en_reg ) ;
return ret ;
}
2012-11-19 22:22:22 +04:00
static int tps65090_regulator_disable_ext_control (
2012-10-09 13:48:59 +04:00
struct tps65090_regulator * ri ,
struct tps65090_regulator_plat_data * tps_pdata )
{
int ret = 0 ;
struct device * parent = ri - > dev - > parent ;
unsigned int reg_en_reg = ri - > desc - > enable_reg ;
/*
* First enable output for internal control if require .
* And then disable external control .
*/
if ( tps_pdata - > reg_init_data - > constraints . always_on | |
tps_pdata - > reg_init_data - > constraints . boot_on ) {
ret = tps65090_set_bits ( parent , reg_en_reg , 0 ) ;
if ( ret < 0 ) {
dev_err ( ri - > dev , " Error in set reg 0x%x \n " , reg_en_reg ) ;
return ret ;
}
2012-03-22 17:04:09 +04:00
}
2012-10-09 13:48:59 +04:00
return tps65090_config_ext_control ( ri , false ) ;
2012-03-22 17:04:09 +04:00
}
2013-01-29 13:05:16 +04:00
# ifdef CONFIG_OF
static struct of_regulator_match tps65090_matches [ ] = {
{ . name = " dcdc1 " , } ,
{ . name = " dcdc2 " , } ,
{ . name = " dcdc3 " , } ,
{ . name = " fet1 " , } ,
{ . name = " fet2 " , } ,
{ . name = " fet3 " , } ,
{ . name = " fet4 " , } ,
{ . name = " fet5 " , } ,
{ . name = " fet6 " , } ,
{ . name = " fet7 " , } ,
{ . name = " ldo1 " , } ,
{ . name = " ldo2 " , } ,
} ;
static struct tps65090_platform_data * tps65090_parse_dt_reg_data (
struct platform_device * pdev ,
struct of_regulator_match * * tps65090_reg_matches )
{
struct tps65090_platform_data * tps65090_pdata ;
struct device_node * np = pdev - > dev . parent - > of_node ;
struct device_node * regulators ;
int idx = 0 , ret ;
struct tps65090_regulator_plat_data * reg_pdata ;
tps65090_pdata = devm_kzalloc ( & pdev - > dev , sizeof ( * tps65090_pdata ) ,
GFP_KERNEL ) ;
2014-02-20 12:53:15 +04:00
if ( ! tps65090_pdata )
2013-01-29 13:05:16 +04:00
return ERR_PTR ( - ENOMEM ) ;
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
reg_pdata = devm_kcalloc ( & pdev - > dev ,
TPS65090_REGULATOR_MAX , sizeof ( * reg_pdata ) ,
GFP_KERNEL ) ;
2014-02-20 12:53:15 +04:00
if ( ! reg_pdata )
2013-01-29 13:05:16 +04:00
return ERR_PTR ( - ENOMEM ) ;
2013-10-08 18:01:02 +04:00
regulators = of_get_child_by_name ( np , " regulators " ) ;
2013-01-29 13:05:16 +04:00
if ( ! regulators ) {
dev_err ( & pdev - > dev , " regulator node not found \n " ) ;
return ERR_PTR ( - ENODEV ) ;
}
2013-01-30 16:28:20 +04:00
ret = of_regulator_match ( & pdev - > dev , regulators , tps65090_matches ,
2013-01-29 13:05:16 +04:00
ARRAY_SIZE ( tps65090_matches ) ) ;
2014-02-17 13:03:37 +04:00
of_node_put ( regulators ) ;
2013-01-29 13:05:16 +04:00
if ( ret < 0 ) {
dev_err ( & pdev - > dev ,
" Error parsing regulator init data: %d \n " , ret ) ;
return ERR_PTR ( ret ) ;
}
* tps65090_reg_matches = tps65090_matches ;
for ( idx = 0 ; idx < ARRAY_SIZE ( tps65090_matches ) ; idx + + ) {
struct regulator_init_data * ri_data ;
struct tps65090_regulator_plat_data * rpdata ;
2019-10-05 02:10:13 +03:00
struct device_node * np ;
2013-01-29 13:05:16 +04:00
rpdata = & reg_pdata [ idx ] ;
ri_data = tps65090_matches [ idx ] . init_data ;
2019-10-05 02:10:13 +03:00
if ( ! ri_data )
continue ;
np = tps65090_matches [ idx ] . of_node ;
if ( ! np )
2013-01-29 13:05:16 +04:00
continue ;
rpdata - > reg_init_data = ri_data ;
2019-10-05 02:10:13 +03:00
rpdata - > enable_ext_control = of_property_read_bool ( np ,
" ti,enable-ext-control " ) ;
2018-05-14 11:06:33 +03:00
if ( rpdata - > enable_ext_control ) {
enum gpiod_flags gflags ;
if ( ri_data - > constraints . always_on | |
ri_data - > constraints . boot_on )
gflags = GPIOD_OUT_HIGH ;
else
gflags = GPIOD_OUT_LOW ;
2018-10-15 12:02:40 +03:00
gflags | = GPIOD_FLAGS_BIT_NONEXCLUSIVE ;
2018-05-14 11:06:33 +03:00
2019-10-05 02:10:13 +03:00
rpdata - > gpiod = devm_fwnode_gpiod_get (
& pdev - > dev ,
of_fwnode_handle ( np ) ,
" dcdc-ext-control " ,
gflags ,
" tps65090 " ) ;
2019-06-21 00:37:08 +03:00
if ( PTR_ERR ( rpdata - > gpiod ) = = - ENOENT ) {
2018-05-14 11:06:33 +03:00
dev_err ( & pdev - > dev ,
" could not find DCDC external control GPIO \n " ) ;
2019-06-21 00:37:08 +03:00
rpdata - > gpiod = NULL ;
} else if ( IS_ERR ( rpdata - > gpiod ) )
return ERR_CAST ( rpdata - > gpiod ) ;
2018-05-14 11:06:33 +03:00
}
2013-01-29 13:05:16 +04:00
2019-10-05 02:10:13 +03:00
if ( of_property_read_u32 ( np , " ti,overcurrent-wait " ,
2014-04-17 03:12:28 +04:00
& rpdata - > overcurrent_wait ) = = 0 )
rpdata - > overcurrent_wait_valid = true ;
2013-01-29 13:05:16 +04:00
tps65090_pdata - > reg_pdata [ idx ] = rpdata ;
}
return tps65090_pdata ;
}
# else
static inline struct tps65090_platform_data * tps65090_parse_dt_reg_data (
struct platform_device * pdev ,
struct of_regulator_match * * tps65090_reg_matches )
{
* tps65090_reg_matches = NULL ;
return NULL ;
}
# endif
2012-11-19 22:22:22 +04:00
static int tps65090_regulator_probe ( struct platform_device * pdev )
2012-03-22 17:04:09 +04:00
{
2012-04-17 13:08:56 +04:00
struct tps65090 * tps65090_mfd = dev_get_drvdata ( pdev - > dev . parent ) ;
2012-03-22 17:04:09 +04:00
struct tps65090_regulator * ri = NULL ;
2012-04-04 03:50:22 +04:00
struct regulator_config config = { } ;
2012-03-22 17:04:09 +04:00
struct regulator_dev * rdev ;
2012-10-09 13:48:59 +04:00
struct tps65090_regulator_plat_data * tps_pdata ;
struct tps65090_regulator * pmic ;
struct tps65090_platform_data * tps65090_pdata ;
2013-01-29 13:05:16 +04:00
struct of_regulator_match * tps65090_reg_matches = NULL ;
2012-10-09 13:48:59 +04:00
int num ;
int ret ;
2012-03-22 17:04:09 +04:00
2012-10-09 13:48:59 +04:00
dev_dbg ( & pdev - > dev , " Probing regulator \n " ) ;
2012-03-22 17:04:09 +04:00
2012-10-09 13:48:59 +04:00
tps65090_pdata = dev_get_platdata ( pdev - > dev . parent ) ;
2013-01-29 13:05:16 +04:00
if ( ! tps65090_pdata & & tps65090_mfd - > dev - > of_node )
tps65090_pdata = tps65090_parse_dt_reg_data ( pdev ,
& tps65090_reg_matches ) ;
if ( IS_ERR_OR_NULL ( tps65090_pdata ) ) {
2012-10-09 13:48:59 +04:00
dev_err ( & pdev - > dev , " Platform data missing \n " ) ;
2013-01-29 13:05:16 +04:00
return tps65090_pdata ? PTR_ERR ( tps65090_pdata ) : - EINVAL ;
2012-03-22 17:04:09 +04:00
}
2012-10-09 13:48:59 +04:00
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
pmic = devm_kcalloc ( & pdev - > dev ,
TPS65090_REGULATOR_MAX , sizeof ( * pmic ) ,
GFP_KERNEL ) ;
2014-02-20 12:53:15 +04:00
if ( ! pmic )
2012-10-09 13:48:59 +04:00
return - ENOMEM ;
2012-10-09 13:49:00 +04:00
for ( num = 0 ; num < TPS65090_REGULATOR_MAX ; num + + ) {
2012-10-09 13:48:59 +04:00
tps_pdata = tps65090_pdata - > reg_pdata [ num ] ;
ri = & pmic [ num ] ;
ri - > dev = & pdev - > dev ;
ri - > desc = & tps65090_regulator_desc [ num ] ;
2014-05-01 22:50:16 +04:00
if ( tps_pdata ) {
ri - > overcurrent_wait_valid =
tps_pdata - > overcurrent_wait_valid ;
ri - > overcurrent_wait = tps_pdata - > overcurrent_wait ;
}
2012-10-09 13:48:59 +04:00
/*
* TPS5090 DCDC support the control from external digital input .
2012-10-09 13:49:02 +04:00
* Configure it as per platform data .
2012-10-09 13:48:59 +04:00
*/
if ( tps_pdata & & is_dcdc ( num ) & & tps_pdata - > reg_init_data ) {
2012-10-09 13:49:02 +04:00
if ( tps_pdata - > enable_ext_control ) {
2018-05-14 11:06:33 +03:00
config . ena_gpiod = tps_pdata - > gpiod ;
2012-10-09 13:49:02 +04:00
ri - > desc - > ops = & tps65090_ext_control_ops ;
} else {
ret = tps65090_regulator_disable_ext_control (
2012-10-09 13:48:59 +04:00
ri , tps_pdata ) ;
2012-10-09 13:49:02 +04:00
if ( ret < 0 ) {
dev_err ( & pdev - > dev ,
2012-10-09 13:48:59 +04:00
" failed disable ext control \n " ) ;
2013-09-04 15:47:48 +04:00
return ret ;
2012-10-09 13:49:02 +04:00
}
2012-10-09 13:48:59 +04:00
}
}
2012-10-09 13:49:02 +04:00
2013-01-29 13:05:16 +04:00
config . dev = pdev - > dev . parent ;
2012-10-09 13:48:59 +04:00
config . driver_data = ri ;
config . regmap = tps65090_mfd - > rmap ;
if ( tps_pdata )
config . init_data = tps_pdata - > reg_init_data ;
else
config . init_data = NULL ;
2013-01-29 13:05:16 +04:00
if ( tps65090_reg_matches )
config . of_node = tps65090_reg_matches [ num ] . of_node ;
else
config . of_node = NULL ;
2012-10-09 13:48:59 +04:00
2018-12-06 15:43:50 +03:00
/*
* Hand the GPIO descriptor management over to the regulator
* core , remove it from devres management .
*/
if ( config . ena_gpiod )
devm_gpiod_unhinge ( & pdev - > dev , config . ena_gpiod ) ;
2013-09-04 15:47:48 +04:00
rdev = devm_regulator_register ( & pdev - > dev , ri - > desc , & config ) ;
2012-10-09 13:48:59 +04:00
if ( IS_ERR ( rdev ) ) {
dev_err ( & pdev - > dev , " failed to register regulator %s \n " ,
ri - > desc - > name ) ;
2013-09-04 15:47:48 +04:00
return PTR_ERR ( rdev ) ;
2012-10-09 13:48:59 +04:00
}
ri - > rdev = rdev ;
2012-10-09 13:49:02 +04:00
2014-04-17 03:12:28 +04:00
if ( ri - > overcurrent_wait_valid ) {
ret = tps65090_reg_set_overcurrent_wait ( ri , rdev ) ;
if ( ret < 0 )
return ret ;
}
2012-10-09 13:49:02 +04:00
/* Enable external control if it is require */
if ( tps_pdata & & is_dcdc ( num ) & & tps_pdata - > reg_init_data & &
tps_pdata - > enable_ext_control ) {
ret = tps65090_config_ext_control ( ri , true ) ;
2013-09-04 15:47:48 +04:00
if ( ret < 0 )
return ret ;
2012-10-09 13:49:02 +04:00
}
2012-03-22 17:04:09 +04:00
}
2012-10-09 13:48:59 +04:00
platform_set_drvdata ( pdev , pmic ) ;
2012-03-22 17:04:09 +04:00
return 0 ;
}
static struct platform_driver tps65090_regulator_driver = {
. driver = {
2012-10-09 13:49:00 +04:00
. name = " tps65090-pmic " ,
2012-03-22 17:04:09 +04:00
} ,
. probe = tps65090_regulator_probe ,
} ;
static int __init tps65090_regulator_init ( void )
{
return platform_driver_register ( & tps65090_regulator_driver ) ;
}
subsys_initcall ( tps65090_regulator_init ) ;
static void __exit tps65090_regulator_exit ( void )
{
platform_driver_unregister ( & tps65090_regulator_driver ) ;
}
module_exit ( tps65090_regulator_exit ) ;
MODULE_DESCRIPTION ( " tps65090 regulator driver " ) ;
MODULE_AUTHOR ( " Venu Byravarasu <vbyravarasu@nvidia.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2012-11-23 19:47:16 +04:00
MODULE_ALIAS ( " platform:tps65090-pmic " ) ;