2013-07-30 01:29:10 +04:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 2011 , 2012 Cavium Inc .
*/
# include <linux/platform_device.h>
# include <linux/kernel.h>
# include <linux/module.h>
2018-05-24 15:22:04 +03:00
# include <linux/gpio/driver.h>
2013-07-30 01:29:10 +04:00
# include <linux/io.h>
# include <asm/octeon/octeon.h>
# include <asm/octeon/cvmx-gpio-defs.h>
# define RX_DAT 0x80
# define TX_SET 0x88
# define TX_CLEAR 0x90
/*
* The address offset of the GPIO configuration register for a given
* line .
*/
static unsigned int bit_cfg_reg ( unsigned int offset )
{
/*
* The register stride is 8 , with a discontinuity after the
* first 16.
*/
if ( offset < 16 )
return 8 * offset ;
else
return 8 * ( offset - 16 ) + 0x100 ;
}
struct octeon_gpio {
struct gpio_chip chip ;
u64 register_base ;
} ;
static int octeon_gpio_dir_in ( struct gpio_chip * chip , unsigned offset )
{
2015-12-07 13:13:27 +03:00
struct octeon_gpio * gpio = gpiochip_get_data ( chip ) ;
2013-07-30 01:29:10 +04:00
cvmx_write_csr ( gpio - > register_base + bit_cfg_reg ( offset ) , 0 ) ;
return 0 ;
}
static void octeon_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2015-12-07 13:13:27 +03:00
struct octeon_gpio * gpio = gpiochip_get_data ( chip ) ;
2013-07-30 01:29:10 +04:00
u64 mask = 1ull < < offset ;
u64 reg = gpio - > register_base + ( value ? TX_SET : TX_CLEAR ) ;
cvmx_write_csr ( reg , mask ) ;
}
static int octeon_gpio_dir_out ( struct gpio_chip * chip , unsigned offset ,
int value )
{
2015-12-07 13:13:27 +03:00
struct octeon_gpio * gpio = gpiochip_get_data ( chip ) ;
2013-07-30 01:29:10 +04:00
union cvmx_gpio_bit_cfgx cfgx ;
octeon_gpio_set ( chip , offset , value ) ;
cfgx . u64 = 0 ;
cfgx . s . tx_oe = 1 ;
cvmx_write_csr ( gpio - > register_base + bit_cfg_reg ( offset ) , cfgx . u64 ) ;
return 0 ;
}
static int octeon_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2015-12-07 13:13:27 +03:00
struct octeon_gpio * gpio = gpiochip_get_data ( chip ) ;
2013-07-30 01:29:10 +04:00
u64 read_bits = cvmx_read_csr ( gpio - > register_base + RX_DAT ) ;
return ( ( 1ull < < offset ) & read_bits ) ! = 0 ;
}
static int octeon_gpio_probe ( struct platform_device * pdev )
{
struct octeon_gpio * gpio ;
struct gpio_chip * chip ;
2016-03-18 16:05:16 +03:00
void __iomem * reg_base ;
2013-07-30 01:29:10 +04:00
int err = 0 ;
gpio = devm_kzalloc ( & pdev - > dev , sizeof ( * gpio ) , GFP_KERNEL ) ;
if ( ! gpio )
return - ENOMEM ;
chip = & gpio - > chip ;
2019-03-11 22:48:21 +03:00
reg_base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2016-03-18 16:05:16 +03:00
if ( IS_ERR ( reg_base ) )
return PTR_ERR ( reg_base ) ;
2013-07-30 01:29:10 +04:00
2016-03-18 16:05:16 +03:00
gpio - > register_base = ( u64 ) reg_base ;
2013-07-30 01:29:10 +04:00
pdev - > dev . platform_data = chip ;
chip - > label = " octeon-gpio " ;
2015-11-04 11:56:26 +03:00
chip - > parent = & pdev - > dev ;
2013-07-30 01:29:10 +04:00
chip - > owner = THIS_MODULE ;
chip - > base = 0 ;
2013-12-04 17:42:46 +04:00
chip - > can_sleep = false ;
2013-07-30 01:29:10 +04:00
chip - > ngpio = 20 ;
chip - > direction_input = octeon_gpio_dir_in ;
chip - > get = octeon_gpio_get ;
chip - > direction_output = octeon_gpio_dir_out ;
chip - > set = octeon_gpio_set ;
2016-02-22 15:13:28 +03:00
err = devm_gpiochip_add_data ( & pdev - > dev , chip , gpio ) ;
2013-07-30 01:29:10 +04:00
if ( err )
2016-03-18 16:05:16 +03:00
return err ;
2013-07-30 01:29:10 +04:00
dev_info ( & pdev - > dev , " OCTEON GPIO driver probed. \n " ) ;
2016-03-18 16:05:16 +03:00
return 0 ;
2013-07-30 01:29:10 +04:00
}
2016-03-18 16:06:06 +03:00
static const struct of_device_id octeon_gpio_match [ ] = {
2013-07-30 01:29:10 +04:00
{
. compatible = " cavium,octeon-3860-gpio " ,
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , octeon_gpio_match ) ;
static struct platform_driver octeon_gpio_driver = {
. driver = {
. name = " octeon_gpio " ,
. of_match_table = octeon_gpio_match ,
} ,
. probe = octeon_gpio_probe ,
} ;
module_platform_driver ( octeon_gpio_driver ) ;
MODULE_DESCRIPTION ( " Cavium Inc. OCTEON GPIO Driver " ) ;
MODULE_AUTHOR ( " David Daney " ) ;
MODULE_LICENSE ( " GPL " ) ;