2011-06-09 23:50:00 +04:00
/*
* tps65912 - core . c - - TI TPS65912x
*
* Copyright 2011 Texas Instruments Inc .
*
* Author : Margarita Olaya Cabrera < magi @ slimlogic . co . uk >
*
* 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 .
*
* This driver is based on wm8350 implementation .
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/gpio.h>
# include <linux/mfd/core.h>
# include <linux/mfd/tps65912.h>
static struct mfd_cell tps65912s [ ] = {
{
. name = " tps65912-pmic " ,
} ,
} ;
int tps65912_set_bits ( struct tps65912 * tps65912 , u8 reg , u8 mask )
{
u8 data ;
int err ;
mutex_lock ( & tps65912 - > io_mutex ) ;
err = tps65912 - > read ( tps65912 , reg , 1 , & data ) ;
if ( err ) {
dev_err ( tps65912 - > dev , " Read from reg 0x%x failed \n " , reg ) ;
goto out ;
}
data | = mask ;
err = tps65912 - > write ( tps65912 , reg , 1 , & data ) ;
if ( err )
dev_err ( tps65912 - > dev , " Write to reg 0x%x failed \n " , reg ) ;
out :
mutex_unlock ( & tps65912 - > io_mutex ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( tps65912_set_bits ) ;
int tps65912_clear_bits ( struct tps65912 * tps65912 , u8 reg , u8 mask )
{
u8 data ;
int err ;
mutex_lock ( & tps65912 - > io_mutex ) ;
err = tps65912 - > read ( tps65912 , reg , 1 , & data ) ;
if ( err ) {
dev_err ( tps65912 - > dev , " Read from reg 0x%x failed \n " , reg ) ;
goto out ;
}
data & = ~ mask ;
err = tps65912 - > write ( tps65912 , reg , 1 , & data ) ;
if ( err )
dev_err ( tps65912 - > dev , " Write to reg 0x%x failed \n " , reg ) ;
out :
mutex_unlock ( & tps65912 - > io_mutex ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( tps65912_clear_bits ) ;
static inline int tps65912_read ( struct tps65912 * tps65912 , u8 reg )
{
u8 val ;
int err ;
err = tps65912 - > read ( tps65912 , reg , 1 , & val ) ;
if ( err < 0 )
return err ;
return val ;
}
static inline int tps65912_write ( struct tps65912 * tps65912 , u8 reg , u8 val )
{
return tps65912 - > write ( tps65912 , reg , 1 , & val ) ;
}
int tps65912_reg_read ( struct tps65912 * tps65912 , u8 reg )
{
int data ;
mutex_lock ( & tps65912 - > io_mutex ) ;
data = tps65912_read ( tps65912 , reg ) ;
if ( data < 0 )
dev_err ( tps65912 - > dev , " Read from reg 0x%x failed \n " , reg ) ;
mutex_unlock ( & tps65912 - > io_mutex ) ;
return data ;
}
EXPORT_SYMBOL_GPL ( tps65912_reg_read ) ;
int tps65912_reg_write ( struct tps65912 * tps65912 , u8 reg , u8 val )
{
int err ;
mutex_lock ( & tps65912 - > io_mutex ) ;
err = tps65912_write ( tps65912 , reg , val ) ;
if ( err < 0 )
dev_err ( tps65912 - > dev , " Write for reg 0x%x failed \n " , reg ) ;
mutex_unlock ( & tps65912 - > io_mutex ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( tps65912_reg_write ) ;
int tps65912_device_init ( struct tps65912 * tps65912 )
{
struct tps65912_board * pmic_plat_data = tps65912 - > dev - > platform_data ;
2011-06-09 23:50:13 +04:00
struct tps65912_platform_data * init_data ;
2011-06-09 23:50:00 +04:00
int ret , dcdc_avs , value ;
2011-06-09 23:50:13 +04:00
init_data = kzalloc ( sizeof ( struct tps65912_platform_data ) , GFP_KERNEL ) ;
if ( init_data = = NULL )
return - ENOMEM ;
2011-06-09 23:50:00 +04:00
mutex_init ( & tps65912 - > io_mutex ) ;
dev_set_drvdata ( tps65912 - > dev , tps65912 ) ;
dcdc_avs = ( pmic_plat_data - > is_dcdc1_avs < < 0 |
pmic_plat_data - > is_dcdc2_avs < < 1 |
pmic_plat_data - > is_dcdc3_avs < < 2 |
pmic_plat_data - > is_dcdc4_avs < < 3 ) ;
if ( dcdc_avs ) {
tps65912 - > read ( tps65912 , TPS65912_I2C_SPI_CFG , 1 , & value ) ;
dcdc_avs | = value ;
tps65912 - > write ( tps65912 , TPS65912_I2C_SPI_CFG , 1 , & dcdc_avs ) ;
}
ret = mfd_add_devices ( tps65912 - > dev , - 1 ,
tps65912s , ARRAY_SIZE ( tps65912s ) ,
NULL , 0 ) ;
if ( ret < 0 )
goto err ;
2011-09-21 01:13:06 +04:00
init_data - > irq = pmic_plat_data - > irq ;
init_data - > irq_base = pmic_plat_data - > irq ;
2011-06-09 23:50:13 +04:00
ret = tps65912_irq_init ( tps65912 , init_data - > irq , init_data ) ;
if ( ret < 0 )
goto err ;
2011-09-21 01:13:06 +04:00
kfree ( init_data ) ;
2011-06-09 23:50:00 +04:00
return ret ;
err :
2011-06-09 23:50:13 +04:00
kfree ( init_data ) ;
2011-06-09 23:50:00 +04:00
mfd_remove_devices ( tps65912 - > dev ) ;
kfree ( tps65912 ) ;
return ret ;
}
void tps65912_device_exit ( struct tps65912 * tps65912 )
{
mfd_remove_devices ( tps65912 - > dev ) ;
kfree ( tps65912 ) ;
}
MODULE_AUTHOR ( " Margarita Olaya <magi@slimlogic.co.uk> " ) ;
MODULE_DESCRIPTION ( " TPS65912x chip family multi-function driver " ) ;
MODULE_LICENSE ( " GPL " ) ;