2010-12-07 20:04:11 +03:00
/*
* 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
2012-03-09 07:37:30 +04:00
# define N_REGULATORS (N_DCDC + N_LDO + N_SWITCH)
2010-12-07 20:04:11 +03:00
# 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 ;
2012-06-20 18:30:15 +04:00
const unsigned int * voltages ;
2010-12-07 20:04:11 +03:00
int n_ilimsels ;
2012-06-20 18:32:08 +04:00
const unsigned int * ilimsels ;
2010-12-07 20:04:11 +03:00
struct field enable , voltage , ilimsel ;
} ;
struct tps6524x {
struct device * dev ;
struct spi_device * spi ;
struct mutex lock ;
struct regulator_desc desc [ N_REGULATORS ] ;
} ;
static int __read_reg ( struct tps6524x * hw , int reg )
{
int error = 0 ;
u16 cmd = CMD_READ ( reg ) , in ;
u8 status ;
struct spi_message m ;
struct spi_transfer t [ 3 ] ;
spi_message_init ( & m ) ;
memset ( t , 0 , sizeof ( t ) ) ;
t [ 0 ] . tx_buf = & cmd ;
t [ 0 ] . len = 2 ;
t [ 0 ] . bits_per_word = 12 ;
spi_message_add_tail ( & t [ 0 ] , & m ) ;
t [ 1 ] . rx_buf = & in ;
t [ 1 ] . len = 2 ;
t [ 1 ] . bits_per_word = 16 ;
spi_message_add_tail ( & t [ 1 ] , & m ) ;
t [ 2 ] . rx_buf = & status ;
t [ 2 ] . len = 1 ;
t [ 2 ] . bits_per_word = 4 ;
spi_message_add_tail ( & t [ 2 ] , & m ) ;
error = spi_sync ( hw - > spi , & m ) ;
if ( error < 0 )
return error ;
dev_dbg ( hw - > dev , " read reg %d, data %x, status %x \n " ,
reg , in , status ) ;
if ( ! ( status & STAT_CLK ) | | ( status & STAT_WRITE ) )
return - EIO ;
if ( status & STAT_INVALID )
return - EINVAL ;
return in ;
}
static int read_reg ( struct tps6524x * hw , int reg )
{
int ret ;
mutex_lock ( & hw - > lock ) ;
ret = __read_reg ( hw , reg ) ;
mutex_unlock ( & hw - > lock ) ;
return ret ;
}
static int __write_reg ( struct tps6524x * hw , int reg , int val )
{
int error = 0 ;
u16 cmd = CMD_WRITE ( reg ) , out = val ;
u8 status ;
struct spi_message m ;
struct spi_transfer t [ 3 ] ;
spi_message_init ( & m ) ;
memset ( t , 0 , sizeof ( t ) ) ;
t [ 0 ] . tx_buf = & cmd ;
t [ 0 ] . len = 2 ;
t [ 0 ] . bits_per_word = 12 ;
spi_message_add_tail ( & t [ 0 ] , & m ) ;
t [ 1 ] . tx_buf = & out ;
t [ 1 ] . len = 2 ;
t [ 1 ] . bits_per_word = 16 ;
spi_message_add_tail ( & t [ 1 ] , & m ) ;
t [ 2 ] . rx_buf = & status ;
t [ 2 ] . len = 1 ;
t [ 2 ] . bits_per_word = 4 ;
spi_message_add_tail ( & t [ 2 ] , & m ) ;
error = spi_sync ( hw - > spi , & m ) ;
if ( error < 0 )
return error ;
dev_dbg ( hw - > dev , " wrote reg %d, data %x, status %x \n " ,
reg , out , status ) ;
if ( ! ( status & STAT_CLK ) | | ! ( status & STAT_WRITE ) )
return - EIO ;
if ( status & ( STAT_INVALID | STAT_WP ) )
return - EINVAL ;
return error ;
}
static int __rmw_reg ( struct tps6524x * hw , int reg , int mask , int val )
{
int ret ;
ret = __read_reg ( hw , reg ) ;
if ( ret < 0 )
return ret ;
ret & = ~ mask ;
ret | = val ;
ret = __write_reg ( hw , reg , ret ) ;
return ( ret < 0 ) ? ret : 0 ;
}
static int rmw_protect ( struct tps6524x * hw , int reg , int mask , int val )
{
int ret ;
mutex_lock ( & hw - > lock ) ;
ret = __write_reg ( hw , REG_WRITE_ENABLE , 1 ) ;
if ( ret ) {
dev_err ( hw - > dev , " failed to set write enable \n " ) ;
goto error ;
}
ret = __rmw_reg ( hw , reg , mask , val ) ;
if ( ret )
dev_err ( hw - > dev , " failed to rmw register %d \n " , reg ) ;
ret = __write_reg ( hw , REG_WRITE_ENABLE , 0 ) ;
if ( ret ) {
dev_err ( hw - > dev , " failed to clear write enable \n " ) ;
goto error ;
}
error :
mutex_unlock ( & hw - > lock ) ;
return ret ;
}
static int read_field ( struct tps6524x * hw , const struct field * field )
{
int tmp ;
tmp = read_reg ( hw , field - > reg ) ;
if ( tmp < 0 )
return tmp ;
return ( tmp > > field - > shift ) & field - > mask ;
}
static int write_field ( struct tps6524x * hw , const struct field * field ,
int val )
{
if ( val & ~ field - > mask )
return - EOVERFLOW ;
return rmw_protect ( hw , field - > reg ,
field - > mask < < field - > shift ,
val < < field - > shift ) ;
}
2012-06-20 18:30:15 +04:00
static const unsigned int dcdc1_voltages [ ] = {
2010-12-07 20:04:11 +03:00
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 ,
} ;
2012-06-20 18:30:15 +04:00
static const unsigned int dcdc2_voltages [ ] = {
2010-12-07 20:04:11 +03:00
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 ,
} ;
2012-06-20 18:30:15 +04:00
static const unsigned int dcdc3_voltages [ ] = {
2010-12-07 20:04:11 +03:00
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 ,
} ;
2012-06-20 18:30:15 +04:00
static const unsigned int ldo1_voltages [ ] = {
2010-12-07 20:04:11 +03:00
4300000 , 4350000 , 4400000 , 4450000 ,
4500000 , 4550000 , 4600000 , 4650000 ,
4700000 , 4750000 , 4800000 , 4850000 ,
4900000 , 4950000 , 5000000 , 5050000 ,
} ;
2012-06-20 18:30:15 +04:00
static const unsigned int ldo2_voltages [ ] = {
2010-12-07 20:04:11 +03:00
1100000 , 1150000 , 1200000 , 1250000 ,
1300000 , 1700000 , 1750000 , 1800000 ,
1850000 , 1900000 , 3150000 , 3200000 ,
3250000 , 3300000 , 3350000 , 3400000 ,
} ;
2012-06-20 18:30:15 +04:00
static const unsigned int fixed_5000000_voltage [ ] = {
5000000
} ;
2012-06-20 18:32:08 +04:00
static const unsigned int ldo_ilimsel [ ] = {
2010-12-07 20:04:11 +03:00
400000 , 1500000
} ;
2012-06-20 18:32:08 +04:00
static const unsigned int usb_ilimsel [ ] = {
2010-12-07 20:04:11 +03:00
200000 , 400000 , 800000 , 1000000
} ;
2012-06-20 18:32:08 +04:00
static const unsigned int fixed_2400000_ilimsel [ ] = {
2400000
} ;
static const unsigned int fixed_1200000_ilimsel [ ] = {
1200000
} ;
static const unsigned int fixed_400000_ilimsel [ ] = {
400000
} ;
2010-12-07 20:04:11 +03:00
# define __MK_FIELD(_reg, _mask, _shift) \
{ . reg = ( _reg ) , . mask = ( _mask ) , . shift = ( _shift ) , }
static const struct supply_info supply_info [ N_REGULATORS ] = {
{
. name = " DCDC1 " ,
. n_voltages = ARRAY_SIZE ( dcdc1_voltages ) ,
. voltages = dcdc1_voltages ,
2012-06-20 18:32:08 +04:00
. n_ilimsels = ARRAY_SIZE ( fixed_2400000_ilimsel ) ,
. ilimsels = fixed_2400000_ilimsel ,
2010-12-07 20:04:11 +03:00
. 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 " ,
. n_voltages = ARRAY_SIZE ( dcdc2_voltages ) ,
. voltages = dcdc2_voltages ,
2012-06-20 18:32:08 +04:00
. n_ilimsels = ARRAY_SIZE ( fixed_1200000_ilimsel ) ,
. ilimsels = fixed_1200000_ilimsel ,
2010-12-07 20:04:11 +03:00
. 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 " ,
. n_voltages = ARRAY_SIZE ( dcdc3_voltages ) ,
. voltages = dcdc3_voltages ,
2012-06-20 18:32:08 +04:00
. n_ilimsels = ARRAY_SIZE ( fixed_1200000_ilimsel ) ,
. ilimsels = fixed_1200000_ilimsel ,
2010-12-07 20:04:11 +03:00
. 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 " ,
2012-06-20 18:30:15 +04:00
. n_voltages = ARRAY_SIZE ( fixed_5000000_voltage ) ,
. voltages = fixed_5000000_voltage ,
2010-12-07 20:04:11 +03:00
. 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 " ,
2012-06-20 18:30:15 +04:00
. n_voltages = ARRAY_SIZE ( fixed_5000000_voltage ) ,
. voltages = fixed_5000000_voltage ,
2012-06-20 18:32:08 +04:00
. n_ilimsels = ARRAY_SIZE ( fixed_400000_ilimsel ) ,
. ilimsels = fixed_400000_ilimsel ,
2010-12-07 20:04:11 +03:00
. enable = __MK_FIELD ( REG_BLOCK_EN , BLOCK_MASK ,
BLOCK_LCD_SHIFT ) ,
} ,
} ;
2012-03-28 15:45:43 +04:00
static int set_voltage_sel ( struct regulator_dev * rdev , unsigned selector )
2010-12-07 20:04:11 +03:00
{
const struct supply_info * info ;
struct tps6524x * hw ;
hw = rdev_get_drvdata ( rdev ) ;
info = & supply_info [ rdev_get_id ( rdev ) ] ;
2012-06-20 18:30:15 +04:00
if ( rdev - > desc - > n_voltages = = 1 )
2010-12-07 20:04:11 +03:00
return - EINVAL ;
2012-03-28 15:45:43 +04:00
return write_field ( hw , & info - > voltage , selector ) ;
2010-12-07 20:04:11 +03:00
}
2012-03-28 15:46:39 +04:00
static int get_voltage_sel ( struct regulator_dev * rdev )
2010-12-07 20:04:11 +03:00
{
const struct supply_info * info ;
struct tps6524x * hw ;
int ret ;
hw = rdev_get_drvdata ( rdev ) ;
info = & supply_info [ rdev_get_id ( rdev ) ] ;
2012-06-20 18:30:15 +04:00
if ( rdev - > desc - > n_voltages = = 1 )
2012-06-14 12:00:53 +04:00
return 0 ;
2010-12-07 20:04:11 +03:00
ret = read_field ( hw , & info - > voltage ) ;
if ( ret < 0 )
return ret ;
if ( WARN_ON ( ret > = info - > n_voltages ) )
return - EIO ;
2012-03-28 15:46:39 +04:00
return ret ;
2010-12-07 20:04:11 +03:00
}
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 ) ] ;
2012-06-20 18:32:08 +04:00
if ( info - > n_ilimsels = = 1 )
2010-12-07 20:04:11 +03:00
return - EINVAL ;
2012-08-08 16:21:30 +04:00
for ( i = info - > n_ilimsels - 1 ; i > = 0 ; i - - ) {
2010-12-07 20:04:11 +03:00
if ( min_uA < = info - > ilimsels [ i ] & &
max_uA > = info - > ilimsels [ i ] )
2012-08-08 16:21:30 +04:00
return write_field ( hw , & info - > ilimsel , i ) ;
}
2010-12-07 20:04:11 +03:00
2012-08-08 16:21:30 +04:00
return - EINVAL ;
2010-12-07 20:04:11 +03:00
}
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 ) ] ;
2012-06-20 18:32:08 +04:00
if ( info - > n_ilimsels = = 1 )
return info - > ilimsels [ 0 ] ;
2010-12-07 20:04:11 +03:00
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 ) ;
}
2019-04-13 10:30:01 +03:00
static const struct regulator_ops regulator_ops = {
2010-12-07 20:04:11 +03:00
. is_enabled = is_supply_enabled ,
. enable = enable_supply ,
. disable = disable_supply ,
2012-03-28 15:46:39 +04:00
. get_voltage_sel = get_voltage_sel ,
2012-03-28 15:45:43 +04:00
. set_voltage_sel = set_voltage_sel ,
2012-06-20 18:30:15 +04:00
. list_voltage = regulator_list_voltage_table ,
2013-04-26 10:25:52 +04:00
. map_voltage = regulator_map_voltage_ascend ,
2010-12-07 20:04:11 +03:00
. set_current_limit = set_current_limit ,
. get_current_limit = get_current_limit ,
} ;
2012-11-19 22:22:22 +04:00
static int pmic_probe ( struct spi_device * spi )
2010-12-07 20:04:11 +03:00
{
struct tps6524x * hw ;
struct device * dev = & spi - > dev ;
const struct supply_info * info = supply_info ;
struct regulator_init_data * init_data ;
2012-04-04 03:50:22 +04:00
struct regulator_config config = { } ;
2019-04-13 10:30:02 +03:00
struct regulator_dev * rdev ;
2013-09-30 04:58:36 +04:00
int i ;
2010-12-07 20:04:11 +03:00
2013-07-30 12:20:47 +04:00
init_data = dev_get_platdata ( dev ) ;
2010-12-07 20:04:11 +03:00
if ( ! init_data ) {
dev_err ( dev , " could not find regulator platform data \n " ) ;
return - EINVAL ;
}
2012-04-11 10:40:18 +04:00
hw = devm_kzalloc ( & spi - > dev , sizeof ( struct tps6524x ) , GFP_KERNEL ) ;
2014-02-20 12:53:16 +04:00
if ( ! hw )
2010-12-07 20:04:11 +03:00
return - ENOMEM ;
2014-02-20 12:53:16 +04:00
2010-12-07 20:04:11 +03:00
spi_set_drvdata ( spi , hw ) ;
memset ( hw , 0 , sizeof ( struct tps6524x ) ) ;
hw - > dev = dev ;
2016-04-19 20:19:08 +03:00
hw - > spi = spi ;
2010-12-07 20:04:11 +03:00
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 ;
2012-06-20 18:30:15 +04:00
hw - > desc [ i ] . volt_table = info - > voltages ;
2010-12-07 20:04:11 +03:00
hw - > desc [ i ] . ops = & regulator_ops ;
hw - > desc [ i ] . type = REGULATOR_VOLTAGE ;
hw - > desc [ i ] . owner = THIS_MODULE ;
2012-04-04 03:50:22 +04:00
config . dev = dev ;
config . init_data = init_data ;
config . driver_data = hw ;
2019-04-13 10:30:02 +03:00
rdev = devm_regulator_register ( dev , & hw - > desc [ i ] , & config ) ;
if ( IS_ERR ( rdev ) )
return PTR_ERR ( rdev ) ;
2010-12-07 20:04:11 +03:00
}
return 0 ;
}
static struct spi_driver pmic_driver = {
. probe = pmic_probe ,
. driver = {
. name = " tps6524x " ,
} ,
} ;
2012-04-04 03:34:23 +04:00
module_spi_driver ( pmic_driver ) ;
2010-12-07 20:04:11 +03:00
MODULE_DESCRIPTION ( " TPS6524X PMIC Driver " ) ;
MODULE_AUTHOR ( " Cyril Chemparathy " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " spi:tps6524x " ) ;