2018-08-29 17:49:14 +03:00
// SPDX-License-Identifier: GPL-2.0+
2011-05-03 01:19:52 +04:00
/*
2011-06-05 04:38:28 +04:00
* TI TPS6591x GPIO driver
2011-05-03 01:19:52 +04:00
*
* Copyright 2010 Texas Instruments Inc .
*
* Author : Graeme Gregory < gg @ slimlogic . co . uk >
2016-04-01 21:49:37 +03:00
* Author : Jorge Eduardo Candelaria < jedu @ slimlogic . co . uk >
2011-05-03 01:19:52 +04:00
*/
# include <linux/kernel.h>
2016-04-01 21:49:37 +03:00
# include <linux/init.h>
2011-05-03 01:19:52 +04:00
# include <linux/errno.h>
2018-08-29 17:45:30 +03:00
# include <linux/gpio/driver.h>
2011-05-03 01:19:52 +04:00
# include <linux/i2c.h>
2012-05-11 20:18:27 +04:00
# include <linux/platform_device.h>
2011-05-03 01:19:52 +04:00
# include <linux/mfd/tps65910.h>
2012-05-19 00:31:43 +04:00
# include <linux/of_device.h>
2011-05-03 01:19:52 +04:00
2012-05-11 20:18:27 +04:00
struct tps65910_gpio {
struct gpio_chip gpio_chip ;
struct tps65910 * tps65910 ;
} ;
2011-05-03 01:19:52 +04:00
static int tps65910_gpio_get ( struct gpio_chip * gc , unsigned offset )
{
2015-12-07 16:48:49 +03:00
struct tps65910_gpio * tps65910_gpio = gpiochip_get_data ( gc ) ;
2012-05-11 20:18:27 +04:00
struct tps65910 * tps65910 = tps65910_gpio - > tps65910 ;
2012-05-08 22:42:38 +04:00
unsigned int val ;
2011-05-03 01:19:52 +04:00
2020-09-27 02:59:15 +03:00
regmap_read ( tps65910 - > regmap , TPS65910_GPIO0 + offset , & val ) ;
2011-05-03 01:19:52 +04:00
2011-05-17 03:35:42 +04:00
if ( val & GPIO_STS_MASK )
2011-05-03 01:19:52 +04:00
return 1 ;
return 0 ;
}
static void tps65910_gpio_set ( struct gpio_chip * gc , unsigned offset ,
int value )
{
2015-12-07 16:48:49 +03:00
struct tps65910_gpio * tps65910_gpio = gpiochip_get_data ( gc ) ;
2012-05-11 20:18:27 +04:00
struct tps65910 * tps65910 = tps65910_gpio - > tps65910 ;
2011-05-03 01:19:52 +04:00
if ( value )
2020-09-27 02:59:15 +03:00
regmap_set_bits ( tps65910 - > regmap , TPS65910_GPIO0 + offset ,
2011-05-17 03:35:42 +04:00
GPIO_SET_MASK ) ;
2011-05-03 01:19:52 +04:00
else
2020-09-27 02:59:15 +03:00
regmap_clear_bits ( tps65910 - > regmap , TPS65910_GPIO0 + offset ,
2011-05-17 03:35:42 +04:00
GPIO_SET_MASK ) ;
2011-05-03 01:19:52 +04:00
}
static int tps65910_gpio_output ( struct gpio_chip * gc , unsigned offset ,
int value )
{
2015-12-07 16:48:49 +03:00
struct tps65910_gpio * tps65910_gpio = gpiochip_get_data ( gc ) ;
2012-05-11 20:18:27 +04:00
struct tps65910 * tps65910 = tps65910_gpio - > tps65910 ;
2011-05-03 01:19:52 +04:00
/* Set the initial value */
2012-01-18 18:37:35 +04:00
tps65910_gpio_set ( gc , offset , value ) ;
2011-05-03 01:19:52 +04:00
2020-09-27 02:59:15 +03:00
return regmap_set_bits ( tps65910 - > regmap , TPS65910_GPIO0 + offset ,
2011-05-17 03:35:42 +04:00
GPIO_CFG_MASK ) ;
2011-05-03 01:19:52 +04:00
}
static int tps65910_gpio_input ( struct gpio_chip * gc , unsigned offset )
{
2015-12-07 16:48:49 +03:00
struct tps65910_gpio * tps65910_gpio = gpiochip_get_data ( gc ) ;
2012-05-11 20:18:27 +04:00
struct tps65910 * tps65910 = tps65910_gpio - > tps65910 ;
2011-05-03 01:19:52 +04:00
2020-09-27 02:59:15 +03:00
return regmap_clear_bits ( tps65910 - > regmap , TPS65910_GPIO0 + offset ,
2011-05-17 03:35:42 +04:00
GPIO_CFG_MASK ) ;
2011-05-03 01:19:52 +04:00
}
2012-05-19 00:31:43 +04:00
# ifdef CONFIG_OF
static struct tps65910_board * tps65910_parse_dt_for_gpio ( struct device * dev ,
struct tps65910 * tps65910 , int chip_ngpio )
{
struct tps65910_board * tps65910_board = tps65910 - > of_plat_data ;
unsigned int prop_array [ TPS6591X_MAX_NUM_GPIO ] ;
int ngpio = min ( chip_ngpio , TPS6591X_MAX_NUM_GPIO ) ;
int ret ;
int idx ;
tps65910_board - > gpio_base = - 1 ;
ret = of_property_read_u32_array ( tps65910 - > dev - > of_node ,
" ti,en-gpio-sleep " , prop_array , ngpio ) ;
if ( ret < 0 ) {
dev_dbg ( dev , " ti,en-gpio-sleep not specified \n " ) ;
return tps65910_board ;
}
for ( idx = 0 ; idx < ngpio ; idx + + )
tps65910_board - > en_gpio_sleep [ idx ] = ( prop_array [ idx ] ! = 0 ) ;
return tps65910_board ;
}
# else
static struct tps65910_board * tps65910_parse_dt_for_gpio ( struct device * dev ,
struct tps65910 * tps65910 , int chip_ngpio )
{
return NULL ;
}
# endif
2012-11-19 22:22:34 +04:00
static int tps65910_gpio_probe ( struct platform_device * pdev )
2011-05-03 01:19:52 +04:00
{
2012-05-11 20:18:27 +04:00
struct tps65910 * tps65910 = dev_get_drvdata ( pdev - > dev . parent ) ;
struct tps65910_board * pdata = dev_get_platdata ( tps65910 - > dev ) ;
struct tps65910_gpio * tps65910_gpio ;
2011-05-03 01:19:52 +04:00
int ret ;
2012-05-11 20:18:27 +04:00
int i ;
2021-12-06 16:18:52 +03:00
device_set_node ( & pdev - > dev , dev_fwnode ( pdev - > dev . parent ) ) ;
2012-05-11 20:18:27 +04:00
tps65910_gpio = devm_kzalloc ( & pdev - > dev ,
sizeof ( * tps65910_gpio ) , GFP_KERNEL ) ;
2014-04-29 12:45:46 +04:00
if ( ! tps65910_gpio )
2012-05-11 20:18:27 +04:00
return - ENOMEM ;
2011-05-03 01:19:52 +04:00
2012-05-11 20:18:27 +04:00
tps65910_gpio - > tps65910 = tps65910 ;
2011-05-03 01:19:52 +04:00
2012-05-11 20:18:27 +04:00
tps65910_gpio - > gpio_chip . owner = THIS_MODULE ;
tps65910_gpio - > gpio_chip . label = tps65910 - > i2c_client - > name ;
2011-05-17 03:35:42 +04:00
2013-03-20 16:16:04 +04:00
switch ( tps65910_chip_id ( tps65910 ) ) {
2011-05-17 03:35:42 +04:00
case TPS65910 :
2012-05-11 20:18:27 +04:00
tps65910_gpio - > gpio_chip . ngpio = TPS65910_NUM_GPIO ;
2011-07-06 06:08:27 +04:00
break ;
2011-05-17 03:35:42 +04:00
case TPS65911 :
2012-05-11 20:18:27 +04:00
tps65910_gpio - > gpio_chip . ngpio = TPS65911_NUM_GPIO ;
2011-07-06 06:08:27 +04:00
break ;
2011-05-17 03:35:42 +04:00
default :
2012-05-11 20:18:27 +04:00
return - EINVAL ;
2011-05-17 03:35:42 +04:00
}
2013-12-04 17:42:46 +04:00
tps65910_gpio - > gpio_chip . can_sleep = true ;
2012-05-11 20:18:27 +04:00
tps65910_gpio - > gpio_chip . direction_input = tps65910_gpio_input ;
tps65910_gpio - > gpio_chip . direction_output = tps65910_gpio_output ;
tps65910_gpio - > gpio_chip . set = tps65910_gpio_set ;
tps65910_gpio - > gpio_chip . get = tps65910_gpio_get ;
2015-11-04 11:56:26 +03:00
tps65910_gpio - > gpio_chip . parent = & pdev - > dev ;
2021-12-06 16:18:52 +03:00
2012-05-11 20:18:27 +04:00
if ( pdata & & pdata - > gpio_base )
tps65910_gpio - > gpio_chip . base = pdata - > gpio_base ;
else
tps65910_gpio - > gpio_chip . base = - 1 ;
2012-05-19 00:31:43 +04:00
if ( ! pdata & & tps65910 - > dev - > of_node )
pdata = tps65910_parse_dt_for_gpio ( & pdev - > dev , tps65910 ,
tps65910_gpio - > gpio_chip . ngpio ) ;
2012-05-11 20:18:27 +04:00
if ( ! pdata )
goto skip_init ;
/* Configure sleep control for gpios if provided */
for ( i = 0 ; i < tps65910_gpio - > gpio_chip . ngpio ; + + i ) {
if ( ! pdata - > en_gpio_sleep [ i ] )
continue ;
2020-09-27 02:59:15 +03:00
ret = regmap_set_bits ( tps65910 - > regmap ,
2012-05-11 20:18:27 +04:00
TPS65910_GPIO0 + i , GPIO_SLEEP_MASK ) ;
if ( ret < 0 )
dev_warn ( tps65910 - > dev ,
" GPIO Sleep setting failed with err %d \n " , ret ) ;
}
skip_init :
2021-05-21 21:17:08 +03:00
return devm_gpiochip_add_data ( & pdev - > dev , & tps65910_gpio - > gpio_chip ,
tps65910_gpio ) ;
2011-05-03 01:19:52 +04:00
}
2012-05-11 20:18:27 +04:00
static struct platform_driver tps65910_gpio_driver = {
. driver . name = " tps65910-gpio " ,
. probe = tps65910_gpio_probe ,
} ;
static int __init tps65910_gpio_init ( void )
{
return platform_driver_register ( & tps65910_gpio_driver ) ;
}
subsys_initcall ( tps65910_gpio_init ) ;