2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2012-01-30 10:31:20 +04:00
/*
* Copyright 2009 - 2012 Freescale Semiconductor , Inc . All Rights Reserved .
*
* Author : Wu Guoxing < b39297 @ freescale . com >
*/
# include <linux/kernel.h>
2016-03-27 18:44:43 +03:00
# include <linux/init.h>
2012-01-30 10:31:20 +04:00
# include <linux/slab.h>
# include <linux/i2c.h>
2018-04-13 16:11:30 +03:00
# include <linux/gpio/driver.h>
2012-01-30 10:31:20 +04:00
# define GPIO_GROUP_NUM 2
# define GPIO_NUM_PER_GROUP 8
# define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
struct mc9s08dz60 {
struct i2c_client * client ;
struct gpio_chip chip ;
} ;
static void mc9s_gpio_to_reg_and_bit ( int offset , u8 * reg , u8 * bit )
{
* reg = 0x20 + offset / GPIO_NUM_PER_GROUP ;
* bit = offset % GPIO_NUM_PER_GROUP ;
}
static int mc9s08dz60_get_value ( struct gpio_chip * gc , unsigned offset )
{
u8 reg , bit ;
s32 value ;
2015-12-07 12:07:07 +03:00
struct mc9s08dz60 * mc9s = gpiochip_get_data ( gc ) ;
2012-01-30 10:31:20 +04:00
mc9s_gpio_to_reg_and_bit ( offset , & reg , & bit ) ;
value = i2c_smbus_read_byte_data ( mc9s - > client , reg ) ;
return ( value > = 0 ) ? ( value > > bit ) & 0x1 : 0 ;
}
static int mc9s08dz60_set ( struct mc9s08dz60 * mc9s , unsigned offset , int val )
{
u8 reg , bit ;
s32 value ;
mc9s_gpio_to_reg_and_bit ( offset , & reg , & bit ) ;
value = i2c_smbus_read_byte_data ( mc9s - > client , reg ) ;
if ( value > = 0 ) {
if ( val )
value | = 1 < < bit ;
else
value & = ~ ( 1 < < bit ) ;
return i2c_smbus_write_byte_data ( mc9s - > client , reg , value ) ;
} else
return value ;
}
static void mc9s08dz60_set_value ( struct gpio_chip * gc , unsigned offset , int val )
{
2015-12-07 12:07:07 +03:00
struct mc9s08dz60 * mc9s = gpiochip_get_data ( gc ) ;
2012-01-30 10:31:20 +04:00
mc9s08dz60_set ( mc9s , offset , val ) ;
}
static int mc9s08dz60_direction_output ( struct gpio_chip * gc ,
unsigned offset , int val )
{
2015-12-07 12:07:07 +03:00
struct mc9s08dz60 * mc9s = gpiochip_get_data ( gc ) ;
2012-01-30 10:31:20 +04:00
return mc9s08dz60_set ( mc9s , offset , val ) ;
}
static int mc9s08dz60_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct mc9s08dz60 * mc9s ;
2012-08-29 05:36:54 +04:00
mc9s = devm_kzalloc ( & client - > dev , sizeof ( * mc9s ) , GFP_KERNEL ) ;
2012-01-30 10:31:20 +04:00
if ( ! mc9s )
return - ENOMEM ;
mc9s - > chip . label = client - > name ;
mc9s - > chip . base = - 1 ;
2015-11-04 11:56:26 +03:00
mc9s - > chip . parent = & client - > dev ;
2012-01-30 10:31:20 +04:00
mc9s - > chip . owner = THIS_MODULE ;
mc9s - > chip . ngpio = GPIO_NUM ;
2013-12-04 17:42:46 +04:00
mc9s - > chip . can_sleep = true ;
2012-01-30 10:31:20 +04:00
mc9s - > chip . get = mc9s08dz60_get_value ;
mc9s - > chip . set = mc9s08dz60_set_value ;
mc9s - > chip . direction_output = mc9s08dz60_direction_output ;
mc9s - > client = client ;
i2c_set_clientdata ( client , mc9s ) ;
2016-02-22 15:13:28 +03:00
return devm_gpiochip_add_data ( & client - > dev , & mc9s - > chip , mc9s ) ;
2012-01-30 10:31:20 +04:00
}
static const struct i2c_device_id mc9s08dz60_id [ ] = {
{ " mc9s08dz60 " , 0 } ,
{ } ,
} ;
static struct i2c_driver mc9s08dz60_i2c_driver = {
. driver = {
. name = " mc9s08dz60 " ,
} ,
. probe = mc9s08dz60_probe ,
. id_table = mc9s08dz60_id ,
} ;
2016-03-27 18:44:43 +03:00
builtin_i2c_driver ( mc9s08dz60_i2c_driver ) ;