2020-01-20 16:47:37 +03:00
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (C) 2018 ROHM Semiconductors
# include <linux/gpio/driver.h>
# include <linux/mfd/rohm-bd71828.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# define GPIO_OUT_REG(off) (BD71828_REG_GPIO_CTRL1 + (off))
# define HALL_GPIO_OFFSET 3
struct bd71828_gpio {
2021-01-05 15:53:35 +03:00
struct regmap * regmap ;
struct device * dev ;
2020-01-20 16:47:37 +03:00
struct gpio_chip gpio ;
} ;
static void bd71828_gpio_set ( struct gpio_chip * chip , unsigned int offset ,
int value )
{
int ret ;
struct bd71828_gpio * bdgpio = gpiochip_get_data ( chip ) ;
u8 val = ( value ) ? BD71828_GPIO_OUT_HI : BD71828_GPIO_OUT_LO ;
/*
* The HALL input pin can only be used as input . If this is the pin
* we are dealing with - then we are done
*/
if ( offset = = HALL_GPIO_OFFSET )
return ;
2021-01-05 15:53:35 +03:00
ret = regmap_update_bits ( bdgpio - > regmap , GPIO_OUT_REG ( offset ) ,
2020-01-20 16:47:37 +03:00
BD71828_GPIO_OUT_MASK , val ) ;
if ( ret )
2021-01-05 15:53:35 +03:00
dev_err ( bdgpio - > dev , " Could not set gpio to %d \n " , value ) ;
2020-01-20 16:47:37 +03:00
}
static int bd71828_gpio_get ( struct gpio_chip * chip , unsigned int offset )
{
int ret ;
unsigned int val ;
struct bd71828_gpio * bdgpio = gpiochip_get_data ( chip ) ;
if ( offset = = HALL_GPIO_OFFSET )
2021-01-05 15:53:35 +03:00
ret = regmap_read ( bdgpio - > regmap , BD71828_REG_IO_STAT ,
2020-01-20 16:47:37 +03:00
& val ) ;
else
2021-01-05 15:53:35 +03:00
ret = regmap_read ( bdgpio - > regmap , GPIO_OUT_REG ( offset ) ,
2020-01-20 16:47:37 +03:00
& val ) ;
if ( ! ret )
ret = ( val & BD71828_GPIO_OUT_MASK ) ;
return ret ;
}
static int bd71828_gpio_set_config ( struct gpio_chip * chip , unsigned int offset ,
unsigned long config )
{
struct bd71828_gpio * bdgpio = gpiochip_get_data ( chip ) ;
if ( offset = = HALL_GPIO_OFFSET )
return - ENOTSUPP ;
switch ( pinconf_to_config_param ( config ) ) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN :
2021-01-05 15:53:35 +03:00
return regmap_update_bits ( bdgpio - > regmap ,
2020-01-20 16:47:37 +03:00
GPIO_OUT_REG ( offset ) ,
BD71828_GPIO_DRIVE_MASK ,
BD71828_GPIO_OPEN_DRAIN ) ;
case PIN_CONFIG_DRIVE_PUSH_PULL :
2021-01-05 15:53:35 +03:00
return regmap_update_bits ( bdgpio - > regmap ,
2020-01-20 16:47:37 +03:00
GPIO_OUT_REG ( offset ) ,
BD71828_GPIO_DRIVE_MASK ,
BD71828_GPIO_PUSH_PULL ) ;
default :
break ;
}
return - ENOTSUPP ;
}
static int bd71828_get_direction ( struct gpio_chip * chip , unsigned int offset )
{
/*
* Pin usage is selected by OTP data . We can ' t read it runtime . Hence
* we trust that if the pin is not excluded by " gpio-reserved-ranges "
* the OTP configuration is set to OUT . ( Other pins but HALL input pin
* on BD71828 can ' t really be used for general purpose input - input
* states are used for specific cases like regulator control or
* PMIC_ON_REQ .
*/
if ( offset = = HALL_GPIO_OFFSET )
return GPIO_LINE_DIRECTION_IN ;
return GPIO_LINE_DIRECTION_OUT ;
}
static int bd71828_probe ( struct platform_device * pdev )
{
2021-01-06 13:11:33 +03:00
struct device * dev = & pdev - > dev ;
2020-01-20 16:47:37 +03:00
struct bd71828_gpio * bdgpio ;
2021-01-06 13:11:33 +03:00
bdgpio = devm_kzalloc ( dev , sizeof ( * bdgpio ) , GFP_KERNEL ) ;
2020-01-20 16:47:37 +03:00
if ( ! bdgpio )
return - ENOMEM ;
2021-01-06 13:11:33 +03:00
bdgpio - > dev = dev ;
bdgpio - > gpio . parent = dev - > parent ;
2020-01-20 16:47:37 +03:00
bdgpio - > gpio . label = " bd71828-gpio " ;
bdgpio - > gpio . owner = THIS_MODULE ;
bdgpio - > gpio . get_direction = bd71828_get_direction ;
bdgpio - > gpio . set_config = bd71828_gpio_set_config ;
bdgpio - > gpio . can_sleep = true ;
bdgpio - > gpio . get = bd71828_gpio_get ;
bdgpio - > gpio . set = bd71828_gpio_set ;
bdgpio - > gpio . base = - 1 ;
/*
* See if we need some implementation to mark some PINs as
* not controllable based on DT info or if core can handle
* " gpio-reserved-ranges " and exclude them from control
*/
bdgpio - > gpio . ngpio = 4 ;
2021-01-06 13:11:33 +03:00
bdgpio - > regmap = dev_get_regmap ( dev - > parent , NULL ) ;
2021-01-05 15:53:35 +03:00
if ( ! bdgpio - > regmap )
return - ENODEV ;
2020-01-20 16:47:37 +03:00
2021-01-06 13:11:33 +03:00
return devm_gpiochip_add_data ( dev , & bdgpio - > gpio , bdgpio ) ;
2020-01-20 16:47:37 +03:00
}
static struct platform_driver bd71828_gpio = {
. driver = {
. name = " bd71828-gpio "
} ,
. probe = bd71828_probe ,
} ;
module_platform_driver ( bd71828_gpio ) ;
MODULE_AUTHOR ( " Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> " ) ;
MODULE_DESCRIPTION ( " BD71828 voltage regulator driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:bd71828-gpio " ) ;