2018-09-25 10:08:48 +03:00
// SPDX-License-Identifier: GPL-2.0+
2010-10-28 02:33:15 +04:00
/*
2011-06-05 04:38:28 +04:00
* Generic driver for memory - mapped GPIO controllers .
2010-10-28 02:33:15 +04:00
*
* Copyright 2008 MontaVista Software , Inc .
* Copyright 2008 , 2010 Anton Vorontsov < cbouatmailru @ gmail . com >
*
* . . . . ` ` . ` ` ` ~ ~ ~ ~ ` ` ` ` . ` . ` . ` . ` . ` ` ` ` ` ` ` ' ' , , , . . . . . . . . . ` ` ` ` ` . . . . . . ` . . . . . . .
* . . . ` ` ` ` ` ` ` ` ` . .
* . . The simplest form of a GPIO controller that the driver supports is ` `
* ` . just a single " data " register , where GPIO state can be read and / or `
* ` , . . written . , , . . ` ` ~ ~ ~ ~ . . . . . ` ` . ` . ` . ~ ~ . ` ` ` . ` . . . . . . . . . ` ` ` ` ` ` . ` ` ` ` ` ` `
* ` ` ` ` ` ` ` ` `
___
_ / ~ ~ | ___ / ~ | . ` ` ` ~ ~ ~ ~ ~ ~ ___ / ___ \ ___ , ~ . ` . ` . ` . ` ` ` ` ` . ~ ~ . . . , , , , . . .
__________ | ~ $ @ ~ ~ ~ % ~ / o * o * o * o * o * o \ . . Implementing such a GPIO .
o ` ~ ~ ~ ~ \ ___ / ~ ~ ~ ~ ` controller in FPGA is , . `
` . . . . trivial . . ' ~ ` . ` ` ` . ` ` `
* ` ` ` ` ` ` `
* . ` ` ` ` ` ` ` ~ ~ ~ ~ ` . . ` . ` ` . ` ` .
* . The driver supports ` . . . , . . ` ` ` . ` ~ ~ ~ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` . . . . ` ` ` ` . ` ` , ,
* . big - endian notation , just ` . . . A bit more sophisticated controllers ,
* . register the device with - be ` . . with a pair of set / clear - bit registers ,
* ` . . suffix . ` ` ` ~ ~ ` ` ` ` ` . . . . ` . ` . affecting the data register and the . `
* ` ` . ` . ` ` . . . ` ` ` ` ` ` . . output pins are also supported . `
* ^ ^ ` ` ` ` ` . ` ` ` ` ` ` ` ` ` . , ` ` ~ ` ` ~ ` ` ~ ~ ` ` ` ` ` `
* . ^ ^
* , . . ` . ` . ` . . . ` ` ` ` ` ` ` ` ` ` ` ` . . . . . . ` . ` . ` . ` . ` . ` . . ` . ` . ` . .
* . . The expectation is that in at least some cases . , - ~ ~ ~ - ,
* . this will be used with roll - your - own ASIC / FPGA . ` \ /
* . logic in Verilog or VHDL . ~ ~ ~ ` ` ` ` ` ` ` ` ` . . ` ` ` ` ` ~ ~ ` \ /
* . . ` ` ` ` ` ` ` ` . . . . . . ` ` ` ` ` ` ` ` ` ` ` \ o_
* |
* ^ ^ / \
*
* . . . ` ` ` ` ` ~ ~ ` . . . . . ` ` . ` . . . . . . . . . . ` ` ` ` ` ` . ` . ` ` . ` ` ` . . . . . . . . ` ` .
* ` 8 , 16 , 32 and 64 bits registers are supported , and ` ` .
* . the number of GPIOs is determined by the width of ~
* . . the registers . , . . . . . . . . . . . . ` ` ` . ` . ` . . ` . ` . ~ ~ ~ . ` . ` . ` ~
* ` . . . . . . . ` ` ` ` . ` ` `
*/
# include <linux/init.h>
2011-05-20 10:40:19 +04:00
# include <linux/err.h>
2010-10-28 02:33:15 +04:00
# include <linux/bug.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/spinlock.h>
# include <linux/compiler.h>
# include <linux/types.h>
# include <linux/errno.h>
# include <linux/log2.h>
# include <linux/ioport.h>
# include <linux/io.h>
2015-12-04 16:02:58 +03:00
# include <linux/gpio/driver.h>
2010-10-28 02:33:15 +04:00
# include <linux/slab.h>
2016-01-05 13:13:28 +03:00
# include <linux/bitops.h>
2010-10-28 02:33:15 +04:00
# include <linux/platform_device.h>
# include <linux/mod_devicetable.h>
2016-05-14 00:07:11 +03:00
# include <linux/of.h>
# include <linux/of_device.h>
2010-10-28 02:33:15 +04:00
2011-05-20 10:40:14 +04:00
static void bgpio_write8 ( void __iomem * reg , unsigned long data )
2010-10-28 02:33:15 +04:00
{
2011-05-20 10:40:17 +04:00
writeb ( data , reg ) ;
2010-10-28 02:33:15 +04:00
}
2011-05-20 10:40:14 +04:00
static unsigned long bgpio_read8 ( void __iomem * reg )
2010-10-28 02:33:15 +04:00
{
2011-05-20 10:40:17 +04:00
return readb ( reg ) ;
2011-05-20 10:40:14 +04:00
}
static void bgpio_write16 ( void __iomem * reg , unsigned long data )
{
2011-05-20 10:40:17 +04:00
writew ( data , reg ) ;
2011-05-20 10:40:14 +04:00
}
static unsigned long bgpio_read16 ( void __iomem * reg )
{
2011-05-20 10:40:17 +04:00
return readw ( reg ) ;
2011-05-20 10:40:14 +04:00
}
static void bgpio_write32 ( void __iomem * reg , unsigned long data )
{
2011-05-20 10:40:17 +04:00
writel ( data , reg ) ;
2011-05-20 10:40:14 +04:00
}
static unsigned long bgpio_read32 ( void __iomem * reg )
{
2011-05-20 10:40:17 +04:00
return readl ( reg ) ;
2011-05-20 10:40:14 +04:00
}
2010-10-28 02:33:15 +04:00
# if BITS_PER_LONG >= 64
2011-05-20 10:40:14 +04:00
static void bgpio_write64 ( void __iomem * reg , unsigned long data )
{
2011-05-20 10:40:17 +04:00
writeq ( data , reg ) ;
2011-05-20 10:40:14 +04:00
}
static unsigned long bgpio_read64 ( void __iomem * reg )
{
2011-05-20 10:40:17 +04:00
return readq ( reg ) ;
2010-10-28 02:33:15 +04:00
}
2011-05-20 10:40:14 +04:00
# endif /* BITS_PER_LONG >= 64 */
2010-10-28 02:33:15 +04:00
2013-03-15 17:45:38 +04:00
static void bgpio_write16be ( void __iomem * reg , unsigned long data )
{
iowrite16be ( data , reg ) ;
}
static unsigned long bgpio_read16be ( void __iomem * reg )
{
return ioread16be ( reg ) ;
}
static void bgpio_write32be ( void __iomem * reg , unsigned long data )
{
iowrite32be ( data , reg ) ;
}
static unsigned long bgpio_read32be ( void __iomem * reg )
{
return ioread32be ( reg ) ;
}
2017-10-20 17:31:27 +03:00
static unsigned long bgpio_line2mask ( struct gpio_chip * gc , unsigned int line )
2010-10-28 02:33:15 +04:00
{
2017-10-20 17:31:27 +03:00
if ( gc - > be_bits )
return BIT ( gc - > bgpio_bits - 1 - line ) ;
return BIT ( line ) ;
2010-10-28 02:33:15 +04:00
}
2015-04-29 18:34:59 +03:00
static int bgpio_get_set ( struct gpio_chip * gc , unsigned int gpio )
{
2017-10-20 17:31:27 +03:00
unsigned long pinmask = bgpio_line2mask ( gc , gpio ) ;
2018-08-03 01:52:18 +03:00
bool dir = ! ! ( gc - > bgpio_dir & pinmask ) ;
2015-04-29 18:34:59 +03:00
2018-08-03 01:52:18 +03:00
if ( dir )
2015-12-04 16:02:58 +03:00
return ! ! ( gc - > read_reg ( gc - > reg_set ) & pinmask ) ;
2015-04-29 18:34:59 +03:00
else
2015-12-04 16:02:58 +03:00
return ! ! ( gc - > read_reg ( gc - > reg_dat ) & pinmask ) ;
2015-04-29 18:34:59 +03:00
}
2017-10-20 00:30:12 +03:00
/*
* This assumes that the bits in the GPIO register are in native endianness .
* We only assign the function pointer if we have that .
*/
static int bgpio_get_set_multiple ( struct gpio_chip * gc , unsigned long * mask ,
unsigned long * bits )
{
unsigned long get_mask = 0 ;
unsigned long set_mask = 0 ;
2018-01-16 11:51:51 +03:00
/* Make sure we first clear any bits that are zero when we read the register */
* bits & = ~ * mask ;
2019-04-01 12:09:42 +03:00
set_mask = * mask & gc - > bgpio_dir ;
get_mask = * mask & ~ gc - > bgpio_dir ;
2017-10-20 00:30:12 +03:00
if ( set_mask )
* bits | = gc - > read_reg ( gc - > reg_set ) & set_mask ;
if ( get_mask )
* bits | = gc - > read_reg ( gc - > reg_dat ) & get_mask ;
return 0 ;
}
2010-10-28 02:33:15 +04:00
static int bgpio_get ( struct gpio_chip * gc , unsigned int gpio )
{
2017-10-20 17:31:27 +03:00
return ! ! ( gc - > read_reg ( gc - > reg_dat ) & bgpio_line2mask ( gc , gpio ) ) ;
2010-10-28 02:33:15 +04:00
}
2017-10-20 00:30:12 +03:00
/*
* This only works if the bits in the GPIO register are in native endianness .
*/
static int bgpio_get_multiple ( struct gpio_chip * gc , unsigned long * mask ,
unsigned long * bits )
{
2018-01-16 11:51:51 +03:00
/* Make sure we first clear any bits that are zero when we read the register */
* bits & = ~ * mask ;
* bits | = gc - > read_reg ( gc - > reg_dat ) & * mask ;
2017-10-20 00:30:12 +03:00
return 0 ;
}
/*
* With big endian mirrored bit order it becomes more tedious .
*/
static int bgpio_get_multiple_be ( struct gpio_chip * gc , unsigned long * mask ,
unsigned long * bits )
{
unsigned long readmask = 0 ;
unsigned long val ;
int bit ;
2018-01-16 11:51:51 +03:00
/* Make sure we first clear any bits that are zero when we read the register */
* bits & = ~ * mask ;
2017-10-20 00:30:12 +03:00
/* Create a mirrored mask */
2020-07-13 18:44:29 +03:00
for_each_set_bit ( bit , mask , gc - > ngpio )
2017-10-20 00:30:12 +03:00
readmask | = bgpio_line2mask ( gc , bit ) ;
/* Read the register */
val = gc - > read_reg ( gc - > reg_dat ) & readmask ;
/*
* Mirror the result into the " bits " result , this will give line 0
* in bit 0 . . . line 31 in bit 31 for a 32 bit register .
*/
2020-07-13 18:44:29 +03:00
for_each_set_bit ( bit , & val , gc - > ngpio )
2017-10-20 00:30:12 +03:00
* bits | = bgpio_line2mask ( gc , bit ) ;
return 0 ;
}
2015-07-22 16:05:18 +03:00
static void bgpio_set_none ( struct gpio_chip * gc , unsigned int gpio , int val )
{
}
2010-10-28 02:33:15 +04:00
static void bgpio_set ( struct gpio_chip * gc , unsigned int gpio , int val )
{
2017-10-20 17:31:27 +03:00
unsigned long mask = bgpio_line2mask ( gc , gpio ) ;
2010-10-28 02:33:15 +04:00
unsigned long flags ;
2015-12-04 16:02:58 +03:00
spin_lock_irqsave ( & gc - > bgpio_lock , flags ) ;
2010-10-28 02:33:15 +04:00
if ( val )
2015-12-04 16:02:58 +03:00
gc - > bgpio_data | = mask ;
2010-10-28 02:33:15 +04:00
else
2015-12-04 16:02:58 +03:00
gc - > bgpio_data & = ~ mask ;
2010-10-28 02:33:15 +04:00
2015-12-04 16:02:58 +03:00
gc - > write_reg ( gc - > reg_dat , gc - > bgpio_data ) ;
2010-10-28 02:33:15 +04:00
2015-12-04 16:02:58 +03:00
spin_unlock_irqrestore ( & gc - > bgpio_lock , flags ) ;
2010-10-28 02:33:15 +04:00
}
2011-05-20 10:40:16 +04:00
static void bgpio_set_with_clear ( struct gpio_chip * gc , unsigned int gpio ,
int val )
{
2017-10-20 17:31:27 +03:00
unsigned long mask = bgpio_line2mask ( gc , gpio ) ;
2011-05-20 10:40:16 +04:00
if ( val )
2015-12-04 16:02:58 +03:00
gc - > write_reg ( gc - > reg_set , mask ) ;
2011-05-20 10:40:16 +04:00
else
2015-12-04 16:02:58 +03:00
gc - > write_reg ( gc - > reg_clr , mask ) ;
2011-05-20 10:40:16 +04:00
}
2011-05-20 10:40:16 +04:00
static void bgpio_set_set ( struct gpio_chip * gc , unsigned int gpio , int val )
{
2017-10-20 17:31:27 +03:00
unsigned long mask = bgpio_line2mask ( gc , gpio ) ;
2011-05-20 10:40:16 +04:00
unsigned long flags ;
2015-12-04 16:02:58 +03:00
spin_lock_irqsave ( & gc - > bgpio_lock , flags ) ;
2011-05-20 10:40:16 +04:00
if ( val )
2015-12-04 16:02:58 +03:00
gc - > bgpio_data | = mask ;
2011-05-20 10:40:16 +04:00
else
2015-12-04 16:02:58 +03:00
gc - > bgpio_data & = ~ mask ;
2011-05-20 10:40:16 +04:00
2015-12-04 16:02:58 +03:00
gc - > write_reg ( gc - > reg_set , gc - > bgpio_data ) ;
2011-05-20 10:40:16 +04:00
2015-12-04 16:02:58 +03:00
spin_unlock_irqrestore ( & gc - > bgpio_lock , flags ) ;
2011-05-20 10:40:16 +04:00
}
2015-12-04 16:02:58 +03:00
static void bgpio_multiple_get_masks ( struct gpio_chip * gc ,
2015-01-14 17:46:38 +03:00
unsigned long * mask , unsigned long * bits ,
unsigned long * set_mask ,
unsigned long * clear_mask )
{
int i ;
* set_mask = 0 ;
* clear_mask = 0 ;
2020-07-13 18:44:29 +03:00
for_each_set_bit ( i , mask , gc - > bgpio_bits ) {
if ( test_bit ( i , bits ) )
* set_mask | = bgpio_line2mask ( gc , i ) ;
else
* clear_mask | = bgpio_line2mask ( gc , i ) ;
2015-01-14 17:46:38 +03:00
}
}
2015-12-04 16:02:58 +03:00
static void bgpio_set_multiple_single_reg ( struct gpio_chip * gc ,
2015-01-14 17:46:38 +03:00
unsigned long * mask ,
unsigned long * bits ,
void __iomem * reg )
{
unsigned long flags ;
unsigned long set_mask , clear_mask ;
2015-12-04 16:02:58 +03:00
spin_lock_irqsave ( & gc - > bgpio_lock , flags ) ;
2015-01-14 17:46:38 +03:00
2015-12-04 16:02:58 +03:00
bgpio_multiple_get_masks ( gc , mask , bits , & set_mask , & clear_mask ) ;
2015-01-14 17:46:38 +03:00
2015-12-04 16:02:58 +03:00
gc - > bgpio_data | = set_mask ;
gc - > bgpio_data & = ~ clear_mask ;
2015-01-14 17:46:38 +03:00
2015-12-04 16:02:58 +03:00
gc - > write_reg ( reg , gc - > bgpio_data ) ;
2015-01-14 17:46:38 +03:00
2015-12-04 16:02:58 +03:00
spin_unlock_irqrestore ( & gc - > bgpio_lock , flags ) ;
2015-01-14 17:46:38 +03:00
}
static void bgpio_set_multiple ( struct gpio_chip * gc , unsigned long * mask ,
unsigned long * bits )
{
2015-12-04 16:02:58 +03:00
bgpio_set_multiple_single_reg ( gc , mask , bits , gc - > reg_dat ) ;
2015-01-14 17:46:38 +03:00
}
static void bgpio_set_multiple_set ( struct gpio_chip * gc , unsigned long * mask ,
unsigned long * bits )
{
2015-12-04 16:02:58 +03:00
bgpio_set_multiple_single_reg ( gc , mask , bits , gc - > reg_set ) ;
2015-01-14 17:46:38 +03:00
}
static void bgpio_set_multiple_with_clear ( struct gpio_chip * gc ,
unsigned long * mask ,
unsigned long * bits )
{
unsigned long set_mask , clear_mask ;
2015-12-04 16:02:58 +03:00
bgpio_multiple_get_masks ( gc , mask , bits , & set_mask , & clear_mask ) ;
2015-01-14 17:46:38 +03:00
if ( set_mask )
2015-12-04 16:02:58 +03:00
gc - > write_reg ( gc - > reg_set , set_mask ) ;
2015-01-14 17:46:38 +03:00
if ( clear_mask )
2015-12-04 16:02:58 +03:00
gc - > write_reg ( gc - > reg_clr , clear_mask ) ;
2015-01-14 17:46:38 +03:00
}
2011-05-20 10:40:17 +04:00
static int bgpio_simple_dir_in ( struct gpio_chip * gc , unsigned int gpio )
{
return 0 ;
}
2015-07-22 16:05:18 +03:00
static int bgpio_dir_out_err ( struct gpio_chip * gc , unsigned int gpio ,
int val )
{
return - EINVAL ;
}
2011-05-20 10:40:17 +04:00
static int bgpio_simple_dir_out ( struct gpio_chip * gc , unsigned int gpio ,
int val )
{
gc - > set ( gc , gpio , val ) ;
return 0 ;
}
2010-10-28 02:33:15 +04:00
static int bgpio_dir_in ( struct gpio_chip * gc , unsigned int gpio )
{
2011-05-20 10:40:17 +04:00
unsigned long flags ;
2015-12-04 16:02:58 +03:00
spin_lock_irqsave ( & gc - > bgpio_lock , flags ) ;
2011-05-20 10:40:17 +04:00
2019-02-22 13:14:44 +03:00
gc - > bgpio_dir & = ~ bgpio_line2mask ( gc , gpio ) ;
if ( gc - > reg_dir_in )
gc - > write_reg ( gc - > reg_dir_in , ~ gc - > bgpio_dir ) ;
if ( gc - > reg_dir_out )
gc - > write_reg ( gc - > reg_dir_out , gc - > bgpio_dir ) ;
2011-05-20 10:40:17 +04:00
2015-12-04 16:02:58 +03:00
spin_unlock_irqrestore ( & gc - > bgpio_lock , flags ) ;
2011-05-20 10:40:17 +04:00
2010-10-28 02:33:15 +04:00
return 0 ;
}
2015-06-12 19:20:35 +03:00
static int bgpio_get_dir ( struct gpio_chip * gc , unsigned int gpio )
{
2019-02-22 13:14:44 +03:00
/* Return 0 if output, 1 if input */
2019-11-06 11:54:12 +03:00
if ( gc - > bgpio_dir_unreadable ) {
if ( gc - > bgpio_dir & bgpio_line2mask ( gc , gpio ) )
return GPIO_LINE_DIRECTION_OUT ;
return GPIO_LINE_DIRECTION_IN ;
}
if ( gc - > reg_dir_out ) {
if ( gc - > read_reg ( gc - > reg_dir_out ) & bgpio_line2mask ( gc , gpio ) )
return GPIO_LINE_DIRECTION_OUT ;
return GPIO_LINE_DIRECTION_IN ;
}
2019-02-22 13:14:44 +03:00
if ( gc - > reg_dir_in )
2019-11-06 11:54:12 +03:00
if ( ! ( gc - > read_reg ( gc - > reg_dir_in ) & bgpio_line2mask ( gc , gpio ) ) )
return GPIO_LINE_DIRECTION_OUT ;
2019-02-22 13:14:44 +03:00
2019-11-06 11:54:12 +03:00
return GPIO_LINE_DIRECTION_IN ;
2015-06-12 19:20:35 +03:00
}
2020-03-15 15:13:37 +03:00
static void bgpio_dir_out ( struct gpio_chip * gc , unsigned int gpio , int val )
2010-10-28 02:33:15 +04:00
{
2011-05-20 10:40:17 +04:00
unsigned long flags ;
2015-12-04 16:02:58 +03:00
spin_lock_irqsave ( & gc - > bgpio_lock , flags ) ;
2011-05-20 10:40:17 +04:00
2019-02-22 13:14:44 +03:00
gc - > bgpio_dir | = bgpio_line2mask ( gc , gpio ) ;
if ( gc - > reg_dir_in )
gc - > write_reg ( gc - > reg_dir_in , ~ gc - > bgpio_dir ) ;
if ( gc - > reg_dir_out )
gc - > write_reg ( gc - > reg_dir_out , gc - > bgpio_dir ) ;
2011-05-20 10:40:17 +04:00
2015-12-04 16:02:58 +03:00
spin_unlock_irqrestore ( & gc - > bgpio_lock , flags ) ;
2020-03-15 15:13:37 +03:00
}
2011-05-20 10:40:17 +04:00
2020-03-15 15:13:37 +03:00
static int bgpio_dir_out_dir_first ( struct gpio_chip * gc , unsigned int gpio ,
int val )
{
bgpio_dir_out ( gc , gpio , val ) ;
gc - > set ( gc , gpio , val ) ;
return 0 ;
}
static int bgpio_dir_out_val_first ( struct gpio_chip * gc , unsigned int gpio ,
int val )
{
gc - > set ( gc , gpio , val ) ;
bgpio_dir_out ( gc , gpio , val ) ;
2010-10-28 02:33:15 +04:00
return 0 ;
}
2011-05-20 10:40:19 +04:00
static int bgpio_setup_accessors ( struct device * dev ,
2015-12-04 16:02:58 +03:00
struct gpio_chip * gc ,
2013-03-15 17:45:38 +04:00
bool byte_be )
2010-10-28 02:33:15 +04:00
{
2011-05-20 10:40:14 +04:00
2015-12-04 16:02:58 +03:00
switch ( gc - > bgpio_bits ) {
2011-05-20 10:40:14 +04:00
case 8 :
2015-12-04 16:02:58 +03:00
gc - > read_reg = bgpio_read8 ;
gc - > write_reg = bgpio_write8 ;
2011-05-20 10:40:14 +04:00
break ;
case 16 :
2013-03-15 17:45:38 +04:00
if ( byte_be ) {
2015-12-04 16:02:58 +03:00
gc - > read_reg = bgpio_read16be ;
gc - > write_reg = bgpio_write16be ;
2013-03-15 17:45:38 +04:00
} else {
2015-12-04 16:02:58 +03:00
gc - > read_reg = bgpio_read16 ;
gc - > write_reg = bgpio_write16 ;
2013-03-15 17:45:38 +04:00
}
2011-05-20 10:40:14 +04:00
break ;
case 32 :
2013-03-15 17:45:38 +04:00
if ( byte_be ) {
2015-12-04 16:02:58 +03:00
gc - > read_reg = bgpio_read32be ;
gc - > write_reg = bgpio_write32be ;
2013-03-15 17:45:38 +04:00
} else {
2015-12-04 16:02:58 +03:00
gc - > read_reg = bgpio_read32 ;
gc - > write_reg = bgpio_write32 ;
2013-03-15 17:45:38 +04:00
}
2011-05-20 10:40:14 +04:00
break ;
# if BITS_PER_LONG >= 64
case 64 :
2013-03-15 17:45:38 +04:00
if ( byte_be ) {
dev_err ( dev ,
" 64 bit big endian byte order unsupported \n " ) ;
return - EINVAL ;
} else {
2015-12-04 16:02:58 +03:00
gc - > read_reg = bgpio_read64 ;
gc - > write_reg = bgpio_write64 ;
2013-03-15 17:45:38 +04:00
}
2011-05-20 10:40:14 +04:00
break ;
# endif /* BITS_PER_LONG >= 64 */
default :
2015-12-04 16:02:58 +03:00
dev_err ( dev , " unsupported data width %u bits \n " , gc - > bgpio_bits ) ;
2011-05-20 10:40:14 +04:00
return - EINVAL ;
}
return 0 ;
}
2011-05-20 10:40:16 +04:00
/*
* Create the device and allocate the resources . For setting GPIO ' s there are
2011-05-20 10:40:16 +04:00
* three supported configurations :
2011-05-20 10:40:16 +04:00
*
2011-05-20 10:40:16 +04:00
* - single input / output register resource ( named " dat " ) .
2011-05-20 10:40:16 +04:00
* - set / clear pair ( named " set " and " clr " ) .
2011-05-20 10:40:16 +04:00
* - single output register resource and single input resource ( " set " and
* dat " ).
2011-05-20 10:40:16 +04:00
*
* For the single output register , this drives a 1 by setting a bit and a zero
* by clearing a bit . For the set clr pair , this drives a 1 by setting a bit
* in the set register and clears it by setting a bit in the clear register .
* The configuration is detected by which resources are present .
2011-05-20 10:40:17 +04:00
*
* For setting the GPIO direction , there are three supported configurations :
*
* - simple bidirection GPIO that requires no configuration .
* - an output direction register ( named " dirout " ) where a 1 bit
* indicates the GPIO is an output .
* - an input direction register ( named " dirin " ) where a 1 bit indicates
* the GPIO is an input .
2011-05-20 10:40:16 +04:00
*/
2015-12-04 16:02:58 +03:00
static int bgpio_setup_io ( struct gpio_chip * gc ,
2011-05-20 10:40:19 +04:00
void __iomem * dat ,
void __iomem * set ,
2015-04-29 18:34:59 +03:00
void __iomem * clr ,
unsigned long flags )
2011-05-20 10:40:14 +04:00
{
2010-10-28 02:33:15 +04:00
2015-12-04 16:02:58 +03:00
gc - > reg_dat = dat ;
if ( ! gc - > reg_dat )
2011-05-20 10:40:19 +04:00
return - EINVAL ;
2011-05-20 10:40:16 +04:00
2011-05-20 10:40:19 +04:00
if ( set & & clr ) {
2015-12-04 16:02:58 +03:00
gc - > reg_set = set ;
gc - > reg_clr = clr ;
gc - > set = bgpio_set_with_clear ;
gc - > set_multiple = bgpio_set_multiple_with_clear ;
2011-05-20 10:40:19 +04:00
} else if ( set & & ! clr ) {
2015-12-04 16:02:58 +03:00
gc - > reg_set = set ;
gc - > set = bgpio_set_set ;
gc - > set_multiple = bgpio_set_multiple_set ;
2015-07-22 16:05:18 +03:00
} else if ( flags & BGPIOF_NO_OUTPUT ) {
2015-12-04 16:02:58 +03:00
gc - > set = bgpio_set_none ;
gc - > set_multiple = NULL ;
2011-05-20 10:40:16 +04:00
} else {
2015-12-04 16:02:58 +03:00
gc - > set = bgpio_set ;
gc - > set_multiple = bgpio_set_multiple ;
2010-10-28 02:33:15 +04:00
}
2015-04-29 18:34:59 +03:00
if ( ! ( flags & BGPIOF_UNREADABLE_REG_SET ) & &
2017-10-20 00:30:12 +03:00
( flags & BGPIOF_READ_OUTPUT_REG_SET ) ) {
2015-12-04 16:02:58 +03:00
gc - > get = bgpio_get_set ;
2017-10-20 00:30:12 +03:00
if ( ! gc - > be_bits )
gc - > get_multiple = bgpio_get_set_multiple ;
/*
* We deliberately avoid assigning the - > get_multiple ( ) call
* for big endian mirrored registers which are ALSO reflecting
* their value in the set register when used as output . It is
* simply too much complexity , let the GPIO core fall back to
* reading each line individually in that fringe case .
*/
} else {
2015-12-04 16:02:58 +03:00
gc - > get = bgpio_get ;
2017-10-20 00:30:12 +03:00
if ( gc - > be_bits )
gc - > get_multiple = bgpio_get_multiple_be ;
else
gc - > get_multiple = bgpio_get_multiple ;
}
2011-05-20 10:40:16 +04:00
2011-05-20 10:40:16 +04:00
return 0 ;
}
2015-12-04 16:02:58 +03:00
static int bgpio_setup_direction ( struct gpio_chip * gc ,
2011-05-20 10:40:19 +04:00
void __iomem * dirout ,
2015-07-22 16:05:18 +03:00
void __iomem * dirin ,
unsigned long flags )
2011-05-20 10:40:17 +04:00
{
2019-02-22 13:14:44 +03:00
if ( dirout | | dirin ) {
gc - > reg_dir_out = dirout ;
gc - > reg_dir_in = dirin ;
2020-03-15 15:13:37 +03:00
if ( flags & BGPIOF_NO_SET_ON_INPUT )
gc - > direction_output = bgpio_dir_out_dir_first ;
else
gc - > direction_output = bgpio_dir_out_val_first ;
2018-08-03 01:52:18 +03:00
gc - > direction_input = bgpio_dir_in ;
gc - > get_direction = bgpio_get_dir ;
2011-05-20 10:40:17 +04:00
} else {
2015-07-22 16:05:18 +03:00
if ( flags & BGPIOF_NO_OUTPUT )
2015-12-04 16:02:58 +03:00
gc - > direction_output = bgpio_dir_out_err ;
2015-07-22 16:05:18 +03:00
else
2015-12-04 16:02:58 +03:00
gc - > direction_output = bgpio_simple_dir_out ;
gc - > direction_input = bgpio_simple_dir_in ;
2011-05-20 10:40:17 +04:00
}
return 0 ;
}
2014-05-19 21:49:14 +04:00
static int bgpio_request ( struct gpio_chip * chip , unsigned gpio_pin )
{
if ( gpio_pin < chip - > ngpio )
return 0 ;
return - EINVAL ;
}
2018-08-03 01:52:18 +03:00
/**
* bgpio_init ( ) - Initialize generic GPIO accessor functions
* @ gc : the GPIO chip to set up
* @ dev : the parent device of the new GPIO chip ( compulsory )
* @ sz : the size ( width ) of the MMIO registers in bytes , typically 1 , 2 or 4
* @ dat : MMIO address for the register to READ the value of the GPIO lines , it
* is expected that a 1 in the corresponding bit in this register means the
* line is asserted
* @ set : MMIO address for the register to SET the value of the GPIO lines , it is
* expected that we write the line with 1 in this register to drive the GPIO line
* high .
* @ clr : MMIO address for the register to CLEAR the value of the GPIO lines , it is
* expected that we write the line with 1 in this register to drive the GPIO line
* low . It is allowed to leave this address as NULL , in that case the SET register
* will be assumed to also clear the GPIO lines , by actively writing the line
* with 0.
* @ dirout : MMIO address for the register to set the line as OUTPUT . It is assumed
* that setting a line to 1 in this register will turn that line into an
* output line . Conversely , setting the line to 0 will turn that line into
2019-02-22 13:14:44 +03:00
* an input .
2018-08-03 01:52:18 +03:00
* @ dirin : MMIO address for the register to set this line as INPUT . It is assumed
* that setting a line to 1 in this register will turn that line into an
* input line . Conversely , setting the line to 0 will turn that line into
2019-02-22 13:14:44 +03:00
* an output .
2018-08-03 01:52:18 +03:00
* @ flags : Different flags that will affect the behaviour of the device , such as
* endianness etc .
*/
2015-12-04 16:02:58 +03:00
int bgpio_init ( struct gpio_chip * gc , struct device * dev ,
2011-09-15 03:22:29 +04:00
unsigned long sz , void __iomem * dat , void __iomem * set ,
void __iomem * clr , void __iomem * dirout , void __iomem * dirin ,
2012-05-19 17:34:58 +04:00
unsigned long flags )
2011-05-20 10:40:16 +04:00
{
int ret ;
2011-05-20 10:40:19 +04:00
if ( ! is_power_of_2 ( sz ) )
return - EINVAL ;
2011-05-20 10:40:16 +04:00
2015-12-04 16:02:58 +03:00
gc - > bgpio_bits = sz * 8 ;
if ( gc - > bgpio_bits > BITS_PER_LONG )
2011-05-20 10:40:19 +04:00
return - EINVAL ;
2015-12-04 16:02:58 +03:00
spin_lock_init ( & gc - > bgpio_lock ) ;
gc - > parent = dev ;
gc - > label = dev_name ( dev ) ;
gc - > base = - 1 ;
gc - > ngpio = gc - > bgpio_bits ;
gc - > request = bgpio_request ;
2017-10-20 00:30:12 +03:00
gc - > be_bits = ! ! ( flags & BGPIOF_BIG_ENDIAN ) ;
2011-05-20 10:40:19 +04:00
2015-12-04 16:02:58 +03:00
ret = bgpio_setup_io ( gc , dat , set , clr , flags ) ;
2011-05-20 10:40:16 +04:00
if ( ret )
return ret ;
2010-10-28 02:33:15 +04:00
2017-10-20 17:31:27 +03:00
ret = bgpio_setup_accessors ( dev , gc , flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER ) ;
2011-05-20 10:40:14 +04:00
if ( ret )
return ret ;
2010-10-28 02:33:15 +04:00
2015-12-04 16:02:58 +03:00
ret = bgpio_setup_direction ( gc , dirout , dirin , flags ) ;
2011-05-20 10:40:17 +04:00
if ( ret )
return ret ;
2015-12-04 16:02:58 +03:00
gc - > bgpio_data = gc - > read_reg ( gc - > reg_dat ) ;
if ( gc - > set = = bgpio_set_set & &
2012-05-19 17:34:58 +04:00
! ( flags & BGPIOF_UNREADABLE_REG_SET ) )
2015-12-04 16:02:58 +03:00
gc - > bgpio_data = gc - > read_reg ( gc - > reg_set ) ;
2019-02-22 13:14:44 +03:00
if ( flags & BGPIOF_UNREADABLE_REG_DIR )
gc - > bgpio_dir_unreadable = true ;
/*
* Inspect hardware to find initial direction setting .
*/
if ( ( gc - > reg_dir_out | | gc - > reg_dir_in ) & &
! ( flags & BGPIOF_UNREADABLE_REG_DIR ) ) {
if ( gc - > reg_dir_out )
gc - > bgpio_dir = gc - > read_reg ( gc - > reg_dir_out ) ;
else if ( gc - > reg_dir_in )
gc - > bgpio_dir = ~ gc - > read_reg ( gc - > reg_dir_in ) ;
/*
* If we have two direction registers , synchronise
* input setting to output setting , the library
* can not handle a line being input and output at
* the same time .
*/
if ( gc - > reg_dir_out & & gc - > reg_dir_in )
gc - > write_reg ( gc - > reg_dir_in , ~ gc - > bgpio_dir ) ;
}
2011-05-20 10:40:15 +04:00
2011-05-20 10:40:19 +04:00
return ret ;
}
EXPORT_SYMBOL_GPL ( bgpio_init ) ;
2010-10-28 02:33:15 +04:00
2016-04-29 03:53:14 +03:00
# if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM)
2010-10-28 02:33:15 +04:00
2011-05-20 10:40:19 +04:00
static void __iomem * bgpio_map ( struct platform_device * pdev ,
const char * name ,
2015-10-01 00:52:36 +03:00
resource_size_t sane_sz )
2011-05-20 10:40:19 +04:00
{
struct resource * r ;
resource_size_t sz ;
r = platform_get_resource_byname ( pdev , IORESOURCE_MEM , name ) ;
2015-10-01 00:52:36 +03:00
if ( ! r )
2015-10-21 10:12:00 +03:00
return NULL ;
2011-05-20 10:40:19 +04:00
sz = resource_size ( r ) ;
2015-10-01 00:52:36 +03:00
if ( sz ! = sane_sz )
return IOMEM_ERR_PTR ( - EINVAL ) ;
2011-05-20 10:40:19 +04:00
2015-10-01 00:52:36 +03:00
return devm_ioremap_resource ( & pdev - > dev , r ) ;
2010-10-28 02:33:15 +04:00
}
2016-05-14 00:07:11 +03:00
# ifdef CONFIG_OF
static const struct of_device_id bgpio_of_match [ ] = {
2016-08-03 15:05:57 +03:00
{ . compatible = " brcm,bcm6345-gpio " } ,
2016-05-14 00:07:12 +03:00
{ . compatible = " wd,mbl-gpio " } ,
2017-03-14 19:13:22 +03:00
{ . compatible = " ni,169445-nand-gpio " } ,
2016-05-14 00:07:11 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( of , bgpio_of_match ) ;
static struct bgpio_pdata * bgpio_parse_dt ( struct platform_device * pdev ,
unsigned long * flags )
{
struct bgpio_pdata * pdata ;
if ( ! of_match_device ( bgpio_of_match , & pdev - > dev ) )
return NULL ;
pdata = devm_kzalloc ( & pdev - > dev , sizeof ( struct bgpio_pdata ) ,
GFP_KERNEL ) ;
if ( ! pdata )
return ERR_PTR ( - ENOMEM ) ;
pdata - > base = - 1 ;
2016-08-03 15:05:57 +03:00
if ( of_device_is_big_endian ( pdev - > dev . of_node ) )
* flags | = BGPIOF_BIG_ENDIAN_BYTE_ORDER ;
2016-05-14 00:07:12 +03:00
if ( of_property_read_bool ( pdev - > dev . of_node , " no-output " ) )
* flags | = BGPIOF_NO_OUTPUT ;
2016-05-14 00:07:11 +03:00
return pdata ;
}
# else
static struct bgpio_pdata * bgpio_parse_dt ( struct platform_device * pdev ,
unsigned long * flags )
{
return NULL ;
}
# endif /* CONFIG_OF */
2012-11-19 22:22:34 +04:00
static int bgpio_pdev_probe ( struct platform_device * pdev )
2011-05-20 10:40:19 +04:00
{
struct device * dev = & pdev - > dev ;
struct resource * r ;
void __iomem * dat ;
void __iomem * set ;
void __iomem * clr ;
void __iomem * dirout ;
void __iomem * dirin ;
unsigned long sz ;
2016-05-14 00:07:11 +03:00
unsigned long flags = 0 ;
2011-05-20 10:40:19 +04:00
int err ;
2015-12-04 16:02:58 +03:00
struct gpio_chip * gc ;
2016-05-14 00:07:11 +03:00
struct bgpio_pdata * pdata ;
pdata = bgpio_parse_dt ( pdev , & flags ) ;
if ( IS_ERR ( pdata ) )
return PTR_ERR ( pdata ) ;
if ( ! pdata ) {
pdata = dev_get_platdata ( dev ) ;
flags = pdev - > id_entry - > driver_data ;
}
2011-05-20 10:40:19 +04:00
r = platform_get_resource_byname ( pdev , IORESOURCE_MEM , " dat " ) ;
if ( ! r )
return - EINVAL ;
sz = resource_size ( r ) ;
2015-10-01 00:52:36 +03:00
dat = bgpio_map ( pdev , " dat " , sz ) ;
if ( IS_ERR ( dat ) )
return PTR_ERR ( dat ) ;
2011-05-20 10:40:19 +04:00
2015-10-01 00:52:36 +03:00
set = bgpio_map ( pdev , " set " , sz ) ;
if ( IS_ERR ( set ) )
return PTR_ERR ( set ) ;
2011-05-20 10:40:19 +04:00
2015-10-01 00:52:36 +03:00
clr = bgpio_map ( pdev , " clr " , sz ) ;
if ( IS_ERR ( clr ) )
return PTR_ERR ( clr ) ;
2011-05-20 10:40:19 +04:00
2015-10-01 00:52:36 +03:00
dirout = bgpio_map ( pdev , " dirout " , sz ) ;
if ( IS_ERR ( dirout ) )
return PTR_ERR ( dirout ) ;
2011-05-20 10:40:19 +04:00
2015-10-01 00:52:36 +03:00
dirin = bgpio_map ( pdev , " dirin " , sz ) ;
if ( IS_ERR ( dirin ) )
return PTR_ERR ( dirin ) ;
2011-05-20 10:40:19 +04:00
2015-12-04 16:02:58 +03:00
gc = devm_kzalloc ( & pdev - > dev , sizeof ( * gc ) , GFP_KERNEL ) ;
if ( ! gc )
2011-05-20 10:40:19 +04:00
return - ENOMEM ;
2015-12-04 16:02:58 +03:00
err = bgpio_init ( gc , dev , sz , dat , set , clr , dirout , dirin , flags ) ;
2011-05-20 10:40:19 +04:00
if ( err )
return err ;
if ( pdata ) {
2014-01-30 17:18:57 +04:00
if ( pdata - > label )
2015-12-04 16:02:58 +03:00
gc - > label = pdata - > label ;
gc - > base = pdata - > base ;
2011-05-20 10:40:19 +04:00
if ( pdata - > ngpio > 0 )
2015-12-04 16:02:58 +03:00
gc - > ngpio = pdata - > ngpio ;
2011-05-20 10:40:19 +04:00
}
2015-12-04 16:02:58 +03:00
platform_set_drvdata ( pdev , gc ) ;
2011-05-20 10:40:19 +04:00
2016-02-22 15:13:28 +03:00
return devm_gpiochip_add_data ( & pdev - > dev , gc , NULL ) ;
2010-10-28 02:33:15 +04:00
}
static const struct platform_device_id bgpio_id_table [ ] = {
2014-03-16 09:10:34 +04:00
{
. name = " basic-mmio-gpio " ,
. driver_data = 0 ,
} , {
. name = " basic-mmio-gpio-be " ,
. driver_data = BGPIOF_BIG_ENDIAN ,
} ,
{ }
2010-10-28 02:33:15 +04:00
} ;
MODULE_DEVICE_TABLE ( platform , bgpio_id_table ) ;
static struct platform_driver bgpio_driver = {
. driver = {
. name = " basic-mmio-gpio " ,
2016-05-14 00:07:11 +03:00
. of_match_table = of_match_ptr ( bgpio_of_match ) ,
2010-10-28 02:33:15 +04:00
} ,
. id_table = bgpio_id_table ,
2011-05-20 10:40:19 +04:00
. probe = bgpio_pdev_probe ,
2010-10-28 02:33:15 +04:00
} ;
2011-12-07 20:24:00 +04:00
module_platform_driver ( bgpio_driver ) ;
2011-05-20 10:40:19 +04:00
2011-06-05 04:38:28 +04:00
# endif /* CONFIG_GPIO_GENERIC_PLATFORM */
2010-10-28 02:33:15 +04:00
MODULE_DESCRIPTION ( " Driver for basic memory-mapped GPIO controllers " ) ;
MODULE_AUTHOR ( " Anton Vorontsov <cbouatmailru@gmail.com> " ) ;
MODULE_LICENSE ( " GPL " ) ;