2008-11-07 14:15:42 +00:00
/*
2010-03-01 14:41:59 +00:00
* Driver for GE FPGA based GPIO
2008-11-07 14:15:42 +00:00
*
2010-03-01 14:41:59 +00:00
* Author : Martyn Welch < martyn . welch @ ge . com >
2008-11-07 14:15:42 +00:00
*
2010-03-01 14:41:59 +00:00
* 2008 ( c ) GE Intelligent Platforms Embedded Systems , Inc .
2008-11-07 14:15:42 +00:00
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed " as is " without any warranty of any
* kind , whether express or implied .
*/
/* TODO
*
* Configuration of output modes ( totem - pole / open - drain )
* Interrupt configuration - interrupts are always generated the FPGA relies on
2012-03-12 17:12:58 +00:00
* the I / O interrupt controllers mask to stop them propergating
2008-11-07 14:15:42 +00:00
*/
# include <linux/kernel.h>
# include <linux/io.h>
# include <linux/of_device.h>
# include <linux/of_gpio.h>
2011-05-27 13:23:32 -04:00
# include <linux/module.h>
2008-11-07 14:15:42 +00:00
# define GEF_GPIO_DIRECT 0x00
# define GEF_GPIO_IN 0x04
# define GEF_GPIO_OUT 0x08
# define GEF_GPIO_TRIG 0x0C
# define GEF_GPIO_POLAR_A 0x10
# define GEF_GPIO_POLAR_B 0x14
# define GEF_GPIO_INT_STAT 0x18
# define GEF_GPIO_OVERRUN 0x1C
# define GEF_GPIO_MODE 0x20
2014-04-12 09:41:31 +04:00
static void gef_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
2008-11-07 14:15:42 +00:00
{
2014-04-12 09:41:31 +04:00
struct of_mm_gpio_chip * mmchip = to_of_mm_gpio_chip ( chip ) ;
2008-11-07 14:15:42 +00:00
unsigned int data ;
2014-04-12 09:41:31 +04:00
data = ioread32be ( mmchip - > regs + GEF_GPIO_OUT ) ;
if ( value )
data = data | BIT ( offset ) ;
2008-11-07 14:15:42 +00:00
else
2014-04-12 09:41:31 +04:00
data = data & ~ BIT ( offset ) ;
iowrite32be ( data , mmchip - > regs + GEF_GPIO_OUT ) ;
2008-11-07 14:15:42 +00:00
}
static int gef_gpio_dir_in ( struct gpio_chip * chip , unsigned offset )
{
unsigned int data ;
struct of_mm_gpio_chip * mmchip = to_of_mm_gpio_chip ( chip ) ;
data = ioread32be ( mmchip - > regs + GEF_GPIO_DIRECT ) ;
2014-04-12 09:41:31 +04:00
data = data | BIT ( offset ) ;
2008-11-07 14:15:42 +00:00
iowrite32be ( data , mmchip - > regs + GEF_GPIO_DIRECT ) ;
return 0 ;
}
static int gef_gpio_dir_out ( struct gpio_chip * chip , unsigned offset , int value )
{
unsigned int data ;
struct of_mm_gpio_chip * mmchip = to_of_mm_gpio_chip ( chip ) ;
2014-04-12 09:41:31 +04:00
/* Set value before switching to output */
gef_gpio_set ( mmchip - > regs + GEF_GPIO_OUT , offset , value ) ;
2008-11-07 14:15:42 +00:00
data = ioread32be ( mmchip - > regs + GEF_GPIO_DIRECT ) ;
2014-04-12 09:41:31 +04:00
data = data & ~ BIT ( offset ) ;
2008-11-07 14:15:42 +00:00
iowrite32be ( data , mmchip - > regs + GEF_GPIO_DIRECT ) ;
return 0 ;
}
static int gef_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
struct of_mm_gpio_chip * mmchip = to_of_mm_gpio_chip ( chip ) ;
2014-04-12 09:41:31 +04:00
return ! ! ( ioread32be ( mmchip - > regs + GEF_GPIO_IN ) & BIT ( offset ) ) ;
2008-11-07 14:15:42 +00:00
}
2014-04-12 09:41:31 +04:00
static const struct of_device_id gef_gpio_ids [ ] = {
{
. compatible = " gef,sbc610-gpio " ,
. data = ( void * ) 19 ,
} , {
. compatible = " gef,sbc310-gpio " ,
. data = ( void * ) 6 ,
} , {
. compatible = " ge,imp3a-gpio " ,
. data = ( void * ) 16 ,
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , gef_gpio_ids ) ;
2008-11-07 14:15:42 +00:00
2014-04-12 09:41:31 +04:00
static int __init gef_gpio_probe ( struct platform_device * pdev )
2008-11-07 14:15:42 +00:00
{
2014-04-12 09:41:31 +04:00
const struct of_device_id * of_id =
of_match_device ( gef_gpio_ids , & pdev - > dev ) ;
struct of_mm_gpio_chip * mmchip ;
mmchip = devm_kzalloc ( & pdev - > dev , sizeof ( * mmchip ) , GFP_KERNEL ) ;
if ( ! mmchip )
return - ENOMEM ;
/* Setup pointers to chip functions */
mmchip - > gc . ngpio = ( u16 ) ( uintptr_t ) of_id - > data ;
mmchip - > gc . of_gpio_n_cells = 2 ;
mmchip - > gc . direction_input = gef_gpio_dir_in ;
mmchip - > gc . direction_output = gef_gpio_dir_out ;
mmchip - > gc . get = gef_gpio_get ;
mmchip - > gc . set = gef_gpio_set ;
/* This function adds a memory mapped GPIO chip */
return of_mm_gpiochip_add ( pdev - > dev . of_node , mmchip ) ;
} ;
2012-03-12 17:13:00 +00:00
2014-04-12 09:41:31 +04:00
static struct platform_driver gef_gpio_driver = {
. driver = {
. name = " gef-gpio " ,
. owner = THIS_MODULE ,
. of_match_table = gef_gpio_ids ,
} ,
2008-11-07 14:15:42 +00:00
} ;
2014-04-12 09:41:31 +04:00
module_platform_driver_probe ( gef_gpio_driver , gef_gpio_probe ) ;
2008-11-07 14:15:42 +00:00
2010-03-01 14:41:59 +00:00
MODULE_DESCRIPTION ( " GE I/O FPGA GPIO driver " ) ;
MODULE_AUTHOR ( " Martyn Welch <martyn.welch@ge.com " ) ;
2008-11-07 14:15:42 +00:00
MODULE_LICENSE ( " GPL " ) ;