2014-10-03 11:31:57 +04:00
/*
* 74 xx MMIO GPIO driver
*
* Copyright ( C ) 2014 Alexander Shiyan < shc_work @ mail . ru >
*
* 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 .
*/
# include <linux/err.h>
# include <linux/module.h>
# include <linux/of_device.h>
2015-12-04 16:02:58 +03:00
# include <linux/gpio/driver.h>
2014-10-03 11:31:57 +04:00
# include <linux/platform_device.h>
# define MMIO_74XX_DIR_IN (0 << 8)
# define MMIO_74XX_DIR_OUT (1 << 8)
# define MMIO_74XX_BIT_CNT(x) ((x) & 0xff)
struct mmio_74xx_gpio_priv {
2015-12-04 16:02:58 +03:00
struct gpio_chip gc ;
2014-10-03 11:31:57 +04:00
unsigned flags ;
} ;
static const struct of_device_id mmio_74xx_gpio_ids [ ] = {
{
. compatible = " ti,741g125 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_IN | 1 ) ,
} ,
{
. compatible = " ti,742g125 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_IN | 2 ) ,
} ,
{
. compatible = " ti,74125 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_IN | 4 ) ,
} ,
{
. compatible = " ti,74365 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_IN | 6 ) ,
} ,
{
. compatible = " ti,74244 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_IN | 8 ) ,
} ,
{
. compatible = " ti,741624 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_IN | 16 ) ,
} ,
{
. compatible = " ti,741g74 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_OUT | 1 ) ,
} ,
{
. compatible = " ti,7474 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_OUT | 2 ) ,
} ,
{
. compatible = " ti,74175 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_OUT | 4 ) ,
} ,
{
. compatible = " ti,74174 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_OUT | 6 ) ,
} ,
{
. compatible = " ti,74273 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_OUT | 8 ) ,
} ,
{
. compatible = " ti,7416374 " ,
. data = ( const void * ) ( MMIO_74XX_DIR_OUT | 16 ) ,
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , mmio_74xx_gpio_ids ) ;
static int mmio_74xx_get_direction ( struct gpio_chip * gc , unsigned offset )
{
2015-12-04 16:02:58 +03:00
struct mmio_74xx_gpio_priv * priv = gpiochip_get_data ( gc ) ;
2014-10-03 11:31:57 +04:00
2015-12-04 16:02:58 +03:00
return ! ( priv - > flags & MMIO_74XX_DIR_OUT ) ;
2014-10-03 11:31:57 +04:00
}
static int mmio_74xx_dir_in ( struct gpio_chip * gc , unsigned int gpio )
{
2015-12-04 16:02:58 +03:00
struct mmio_74xx_gpio_priv * priv = gpiochip_get_data ( gc ) ;
2014-10-03 11:31:57 +04:00
return ( priv - > flags & MMIO_74XX_DIR_OUT ) ? - ENOTSUPP : 0 ;
}
static int mmio_74xx_dir_out ( struct gpio_chip * gc , unsigned int gpio , int val )
{
2015-12-04 16:02:58 +03:00
struct mmio_74xx_gpio_priv * priv = gpiochip_get_data ( gc ) ;
2014-10-03 11:31:57 +04:00
if ( priv - > flags & MMIO_74XX_DIR_OUT ) {
gc - > set ( gc , gpio , val ) ;
return 0 ;
}
return - ENOTSUPP ;
}
static int mmio_74xx_gpio_probe ( struct platform_device * pdev )
{
2015-11-11 23:27:34 +03:00
const struct of_device_id * of_id ;
2014-10-03 11:31:57 +04:00
struct mmio_74xx_gpio_priv * priv ;
struct resource * res ;
void __iomem * dat ;
int err ;
2015-11-11 23:27:34 +03:00
of_id = of_match_device ( mmio_74xx_gpio_ids , & pdev - > dev ) ;
if ( ! of_id )
return - ENODEV ;
2014-10-03 11:31:57 +04:00
priv = devm_kzalloc ( & pdev - > dev , sizeof ( * priv ) , GFP_KERNEL ) ;
if ( ! priv )
return - ENOMEM ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
dat = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( dat ) )
return PTR_ERR ( dat ) ;
2015-07-04 23:34:32 +03:00
priv - > flags = ( uintptr_t ) of_id - > data ;
2014-10-03 11:31:57 +04:00
2015-12-04 16:02:58 +03:00
err = bgpio_init ( & priv - > gc , & pdev - > dev ,
2014-10-03 11:31:57 +04:00
DIV_ROUND_UP ( MMIO_74XX_BIT_CNT ( priv - > flags ) , 8 ) ,
dat , NULL , NULL , NULL , NULL , 0 ) ;
if ( err )
return err ;
2015-12-04 16:02:58 +03:00
priv - > gc . direction_input = mmio_74xx_dir_in ;
priv - > gc . direction_output = mmio_74xx_dir_out ;
priv - > gc . get_direction = mmio_74xx_get_direction ;
priv - > gc . ngpio = MMIO_74XX_BIT_CNT ( priv - > flags ) ;
priv - > gc . owner = THIS_MODULE ;
2014-10-03 11:31:57 +04:00
platform_set_drvdata ( pdev , priv ) ;
2016-02-22 15:13:28 +03:00
return devm_gpiochip_add_data ( & pdev - > dev , & priv - > gc , priv ) ;
2014-10-03 11:31:57 +04:00
}
static struct platform_driver mmio_74xx_gpio_driver = {
. driver = {
. name = " 74xx-mmio-gpio " ,
. of_match_table = mmio_74xx_gpio_ids ,
} ,
. probe = mmio_74xx_gpio_probe ,
} ;
module_platform_driver ( mmio_74xx_gpio_driver ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Alexander Shiyan <shc_work@mail.ru> " ) ;
MODULE_DESCRIPTION ( " 74xx MMIO GPIO driver " ) ;