2011-06-20 22:02:29 +04:00
/*
* Register map access API - I2C support
*
* Copyright 2011 Wolfson Microelectronics plc
*
* Author : Mark Brown < broonie @ opensource . wolfsonmicro . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/regmap.h>
# include <linux/i2c.h>
# include <linux/module.h>
# include <linux/init.h>
2012-04-05 01:48:30 +04:00
static int regmap_i2c_write ( void * context , const void * data , size_t count )
2011-06-20 22:02:29 +04:00
{
2012-04-05 01:48:30 +04:00
struct device * dev = context ;
2011-06-20 22:02:29 +04:00
struct i2c_client * i2c = to_i2c_client ( dev ) ;
int ret ;
ret = i2c_master_send ( i2c , data , count ) ;
if ( ret = = count )
return 0 ;
else if ( ret < 0 )
return ret ;
else
return - EIO ;
}
2012-04-05 01:48:30 +04:00
static int regmap_i2c_gather_write ( void * context ,
2011-06-20 22:02:29 +04:00
const void * reg , size_t reg_size ,
const void * val , size_t val_size )
{
2012-04-05 01:48:30 +04:00
struct device * dev = context ;
2011-06-20 22:02:29 +04:00
struct i2c_client * i2c = to_i2c_client ( dev ) ;
struct i2c_msg xfer [ 2 ] ;
int ret ;
/* If the I2C controller can't do a gather tell the core, it
* will substitute in a linear write for us .
*/
2012-05-30 12:55:34 +04:00
if ( ! i2c_check_functionality ( i2c - > adapter , I2C_FUNC_NOSTART ) )
2011-06-20 22:02:29 +04:00
return - ENOTSUPP ;
xfer [ 0 ] . addr = i2c - > addr ;
xfer [ 0 ] . flags = 0 ;
xfer [ 0 ] . len = reg_size ;
xfer [ 0 ] . buf = ( void * ) reg ;
xfer [ 1 ] . addr = i2c - > addr ;
xfer [ 1 ] . flags = I2C_M_NOSTART ;
xfer [ 1 ] . len = val_size ;
xfer [ 1 ] . buf = ( void * ) val ;
ret = i2c_transfer ( i2c - > adapter , xfer , 2 ) ;
if ( ret = = 2 )
return 0 ;
if ( ret < 0 )
return ret ;
else
return - EIO ;
}
2012-04-05 01:48:30 +04:00
static int regmap_i2c_read ( void * context ,
2011-06-20 22:02:29 +04:00
const void * reg , size_t reg_size ,
void * val , size_t val_size )
{
2012-04-05 01:48:30 +04:00
struct device * dev = context ;
2011-06-20 22:02:29 +04:00
struct i2c_client * i2c = to_i2c_client ( dev ) ;
struct i2c_msg xfer [ 2 ] ;
int ret ;
xfer [ 0 ] . addr = i2c - > addr ;
xfer [ 0 ] . flags = 0 ;
xfer [ 0 ] . len = reg_size ;
xfer [ 0 ] . buf = ( void * ) reg ;
xfer [ 1 ] . addr = i2c - > addr ;
xfer [ 1 ] . flags = I2C_M_RD ;
xfer [ 1 ] . len = val_size ;
xfer [ 1 ] . buf = val ;
ret = i2c_transfer ( i2c - > adapter , xfer , 2 ) ;
if ( ret = = 2 )
return 0 ;
else if ( ret < 0 )
return ret ;
else
return - EIO ;
}
static struct regmap_bus regmap_i2c = {
. write = regmap_i2c_write ,
. gather_write = regmap_i2c_gather_write ,
. read = regmap_i2c_read ,
} ;
/**
* regmap_init_i2c ( ) : Initialise register map
*
* @ i2c : Device that will be interacted with
* @ config : Configuration for register map
*
* The return value will be an ERR_PTR ( ) on error or a valid pointer to
* a struct regmap .
*/
struct regmap * regmap_init_i2c ( struct i2c_client * i2c ,
const struct regmap_config * config )
{
2012-04-05 01:48:30 +04:00
return regmap_init ( & i2c - > dev , & regmap_i2c , & i2c - > dev , config ) ;
2011-06-20 22:02:29 +04:00
}
EXPORT_SYMBOL_GPL ( regmap_init_i2c ) ;
2012-01-30 23:56:52 +04:00
/**
* devm_regmap_init_i2c ( ) : Initialise managed register map
*
* @ i2c : Device that will be interacted with
* @ config : Configuration for register map
*
* The return value will be an ERR_PTR ( ) on error or a valid pointer
* to a struct regmap . The regmap will be automatically freed by the
* device management code .
*/
struct regmap * devm_regmap_init_i2c ( struct i2c_client * i2c ,
const struct regmap_config * config )
{
2012-04-05 01:48:30 +04:00
return devm_regmap_init ( & i2c - > dev , & regmap_i2c , & i2c - > dev , config ) ;
2012-01-30 23:56:52 +04:00
}
EXPORT_SYMBOL_GPL ( devm_regmap_init_i2c ) ;
2011-08-11 21:59:10 +04:00
MODULE_LICENSE ( " GPL " ) ;