2012-10-27 15:21:37 +05:30
/*
* SPEAr platform PLGPIO driver
*
* Copyright ( C ) 2012 ST Microelectronics
* Viresh Kumar < viresh . kumar @ linaro . org >
*
* 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 .
*/
# include <linux/clk.h>
# include <linux/err.h>
2014-05-29 11:18:48 +02:00
# include <linux/gpio/driver.h>
2012-10-27 15:21:37 +05:30
# include <linux/io.h>
2017-02-06 03:03:51 -05:00
# include <linux/init.h>
2014-05-29 11:18:48 +02:00
# include <linux/of.h>
# include <linux/of_platform.h>
2012-10-27 15:21:37 +05:30
# include <linux/pinctrl/consumer.h>
# include <linux/platform_device.h>
# include <linux/pm.h>
# include <linux/spinlock.h>
# define MAX_GPIO_PER_REG 32
# define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG)
# define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \
* sizeof ( int * ) )
/*
* plgpio pins in all machines are not one to one mapped , bitwise with registers
* bits . These set of macros define register masks for which below functions
* ( pin_to_offset and offset_to_pin ) are required to be called .
*/
# define PTO_ENB_REG 0x001
# define PTO_WDATA_REG 0x002
# define PTO_DIR_REG 0x004
# define PTO_IE_REG 0x008
# define PTO_RDATA_REG 0x010
# define PTO_MIS_REG 0x020
struct plgpio_regs {
u32 enb ; /* enable register */
u32 wdata ; /* write data register */
u32 dir ; /* direction set register */
u32 rdata ; /* read data register */
u32 ie ; /* interrupt enable register */
u32 mis ; /* mask interrupt status register */
u32 eit ; /* edge interrupt type */
} ;
/*
* struct plgpio : plgpio driver specific structure
*
* lock : lock for guarding gpio registers
* base : base address of plgpio block
* chip : gpio framework specific chip information structure
* p2o : function ptr for pin to offset conversion . This is required only for
* machines where mapping b / w pin and offset is not 1 - to - 1.
* o2p : function ptr for offset to pin conversion . This is required only for
* machines where mapping b / w pin and offset is not 1 - to - 1.
* p2o_regs : mask of registers for which p2o and o2p are applicable
* regs : register offsets
* csave_regs : context save registers for standby / sleep / hibernate cases
*/
struct plgpio {
spinlock_t lock ;
void __iomem * base ;
struct clk * clk ;
struct gpio_chip chip ;
int ( * p2o ) ( int pin ) ; /* pin_to_offset */
int ( * o2p ) ( int offset ) ; /* offset_to_pin */
u32 p2o_regs ;
struct plgpio_regs regs ;
2013-03-25 18:59:38 +09:00
# ifdef CONFIG_PM_SLEEP
2012-10-27 15:21:37 +05:30
struct plgpio_regs * csave_regs ;
# endif
} ;
/* register manipulation inline functions */
static inline u32 is_plgpio_set ( void __iomem * base , u32 pin , u32 reg )
{
u32 offset = PIN_OFFSET ( pin ) ;
void __iomem * reg_off = REG_OFFSET ( base , reg , pin ) ;
u32 val = readl_relaxed ( reg_off ) ;
return ! ! ( val & ( 1 < < offset ) ) ;
}
static inline void plgpio_reg_set ( void __iomem * base , u32 pin , u32 reg )
{
u32 offset = PIN_OFFSET ( pin ) ;
void __iomem * reg_off = REG_OFFSET ( base , reg , pin ) ;
u32 val = readl_relaxed ( reg_off ) ;
writel_relaxed ( val | ( 1 < < offset ) , reg_off ) ;
}
static inline void plgpio_reg_reset ( void __iomem * base , u32 pin , u32 reg )
{
u32 offset = PIN_OFFSET ( pin ) ;
void __iomem * reg_off = REG_OFFSET ( base , reg , pin ) ;
u32 val = readl_relaxed ( reg_off ) ;
writel_relaxed ( val & ~ ( 1 < < offset ) , reg_off ) ;
}
/* gpio framework specific routines */
static int plgpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( chip ) ;
2012-10-27 15:21:37 +05:30
unsigned long flags ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_DIR_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 )
return - EINVAL ;
}
spin_lock_irqsave ( & plgpio - > lock , flags ) ;
plgpio_reg_set ( plgpio - > base , offset , plgpio - > regs . dir ) ;
spin_unlock_irqrestore ( & plgpio - > lock , flags ) ;
return 0 ;
}
static int plgpio_direction_output ( struct gpio_chip * chip , unsigned offset ,
int value )
{
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( chip ) ;
2012-10-27 15:21:37 +05:30
unsigned long flags ;
unsigned dir_offset = offset , wdata_offset = offset , tmp ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & ( PTO_DIR_REG | PTO_WDATA_REG ) ) ) {
tmp = plgpio - > p2o ( offset ) ;
if ( tmp = = - 1 )
return - EINVAL ;
if ( plgpio - > p2o_regs & PTO_DIR_REG )
dir_offset = tmp ;
if ( plgpio - > p2o_regs & PTO_WDATA_REG )
wdata_offset = tmp ;
}
spin_lock_irqsave ( & plgpio - > lock , flags ) ;
if ( value )
plgpio_reg_set ( plgpio - > base , wdata_offset ,
plgpio - > regs . wdata ) ;
else
plgpio_reg_reset ( plgpio - > base , wdata_offset ,
plgpio - > regs . wdata ) ;
plgpio_reg_reset ( plgpio - > base , dir_offset , plgpio - > regs . dir ) ;
spin_unlock_irqrestore ( & plgpio - > lock , flags ) ;
return 0 ;
}
static int plgpio_get_value ( struct gpio_chip * chip , unsigned offset )
{
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( chip ) ;
2012-10-27 15:21:37 +05:30
if ( offset > = chip - > ngpio )
return - EINVAL ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_RDATA_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 )
return - EINVAL ;
}
return is_plgpio_set ( plgpio - > base , offset , plgpio - > regs . rdata ) ;
}
static void plgpio_set_value ( struct gpio_chip * chip , unsigned offset , int value )
{
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( chip ) ;
2012-10-27 15:21:37 +05:30
if ( offset > = chip - > ngpio )
return ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_WDATA_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 )
return ;
}
if ( value )
plgpio_reg_set ( plgpio - > base , offset , plgpio - > regs . wdata ) ;
else
plgpio_reg_reset ( plgpio - > base , offset , plgpio - > regs . wdata ) ;
}
static int plgpio_request ( struct gpio_chip * chip , unsigned offset )
{
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( chip ) ;
2012-10-27 15:21:37 +05:30
int gpio = chip - > base + offset ;
unsigned long flags ;
int ret = 0 ;
if ( offset > = chip - > ngpio )
return - EINVAL ;
2017-09-22 11:02:10 +02:00
ret = pinctrl_gpio_request ( gpio ) ;
2012-10-27 15:21:37 +05:30
if ( ret )
return ret ;
if ( ! IS_ERR ( plgpio - > clk ) ) {
2012-11-14 14:44:07 +05:30
ret = clk_enable ( plgpio - > clk ) ;
2012-10-27 15:21:37 +05:30
if ( ret )
goto err0 ;
}
if ( plgpio - > regs . enb = = - 1 )
return 0 ;
/*
* put gpio in IN mode before enabling it . This make enabling gpio safe
*/
ret = plgpio_direction_input ( chip , offset ) ;
if ( ret )
goto err1 ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_ENB_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 ) {
ret = - EINVAL ;
goto err1 ;
}
}
spin_lock_irqsave ( & plgpio - > lock , flags ) ;
plgpio_reg_set ( plgpio - > base , offset , plgpio - > regs . enb ) ;
spin_unlock_irqrestore ( & plgpio - > lock , flags ) ;
return 0 ;
err1 :
2012-11-14 16:37:45 +08:00
if ( ! IS_ERR ( plgpio - > clk ) )
2012-11-14 14:44:07 +05:30
clk_disable ( plgpio - > clk ) ;
2012-10-27 15:21:37 +05:30
err0 :
2017-09-22 11:02:10 +02:00
pinctrl_gpio_free ( gpio ) ;
2012-10-27 15:21:37 +05:30
return ret ;
}
static void plgpio_free ( struct gpio_chip * chip , unsigned offset )
{
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( chip ) ;
2012-10-27 15:21:37 +05:30
int gpio = chip - > base + offset ;
unsigned long flags ;
if ( offset > = chip - > ngpio )
return ;
if ( plgpio - > regs . enb = = - 1 )
goto disable_clk ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_ENB_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 )
return ;
}
spin_lock_irqsave ( & plgpio - > lock , flags ) ;
plgpio_reg_reset ( plgpio - > base , offset , plgpio - > regs . enb ) ;
spin_unlock_irqrestore ( & plgpio - > lock , flags ) ;
disable_clk :
if ( ! IS_ERR ( plgpio - > clk ) )
2012-11-14 14:44:07 +05:30
clk_disable ( plgpio - > clk ) ;
2012-10-27 15:21:37 +05:30
2017-09-22 11:02:10 +02:00
pinctrl_gpio_free ( gpio ) ;
2012-10-27 15:21:37 +05:30
}
/* PLGPIO IRQ */
static void plgpio_irq_disable ( struct irq_data * d )
{
2014-05-29 11:18:48 +02:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( gc ) ;
2014-05-29 11:18:48 +02:00
int offset = d - > hwirq ;
2012-10-27 15:21:37 +05:30
unsigned long flags ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_IE_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 )
return ;
}
spin_lock_irqsave ( & plgpio - > lock , flags ) ;
plgpio_reg_set ( plgpio - > base , offset , plgpio - > regs . ie ) ;
spin_unlock_irqrestore ( & plgpio - > lock , flags ) ;
}
static void plgpio_irq_enable ( struct irq_data * d )
{
2014-05-29 11:18:48 +02:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( gc ) ;
2014-05-29 11:18:48 +02:00
int offset = d - > hwirq ;
2012-10-27 15:21:37 +05:30
unsigned long flags ;
/* get correct offset for "offset" pin */
if ( plgpio - > p2o & & ( plgpio - > p2o_regs & PTO_IE_REG ) ) {
offset = plgpio - > p2o ( offset ) ;
if ( offset = = - 1 )
return ;
}
spin_lock_irqsave ( & plgpio - > lock , flags ) ;
plgpio_reg_reset ( plgpio - > base , offset , plgpio - > regs . ie ) ;
spin_unlock_irqrestore ( & plgpio - > lock , flags ) ;
}
static int plgpio_irq_set_type ( struct irq_data * d , unsigned trigger )
{
2014-05-29 11:18:48 +02:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( gc ) ;
2014-05-29 11:18:48 +02:00
int offset = d - > hwirq ;
2012-10-27 15:21:37 +05:30
void __iomem * reg_off ;
unsigned int supported_type = 0 , val ;
if ( offset > = plgpio - > chip . ngpio )
return - EINVAL ;
if ( plgpio - > regs . eit = = - 1 )
supported_type = IRQ_TYPE_LEVEL_HIGH ;
else
supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING ;
if ( ! ( trigger & supported_type ) )
return - EINVAL ;
if ( plgpio - > regs . eit = = - 1 )
return 0 ;
reg_off = REG_OFFSET ( plgpio - > base , plgpio - > regs . eit , offset ) ;
val = readl_relaxed ( reg_off ) ;
offset = PIN_OFFSET ( offset ) ;
if ( trigger & IRQ_TYPE_EDGE_RISING )
writel_relaxed ( val | ( 1 < < offset ) , reg_off ) ;
else
writel_relaxed ( val & ~ ( 1 < < offset ) , reg_off ) ;
return 0 ;
}
static struct irq_chip plgpio_irqchip = {
. name = " PLGPIO " ,
. irq_enable = plgpio_irq_enable ,
. irq_disable = plgpio_irq_disable ,
. irq_set_type = plgpio_irq_set_type ,
} ;
2015-09-14 10:42:37 +02:00
static void plgpio_irq_handler ( struct irq_desc * desc )
2012-10-27 15:21:37 +05:30
{
2014-05-29 11:18:48 +02:00
struct gpio_chip * gc = irq_desc_get_handler_data ( desc ) ;
2015-12-08 10:31:35 +01:00
struct plgpio * plgpio = gpiochip_get_data ( gc ) ;
2012-10-27 15:21:37 +05:30
struct irq_chip * irqchip = irq_desc_get_chip ( desc ) ;
int regs_count , count , pin , offset , i = 0 ;
unsigned long pending ;
count = plgpio - > chip . ngpio ;
regs_count = DIV_ROUND_UP ( count , MAX_GPIO_PER_REG ) ;
chained_irq_enter ( irqchip , desc ) ;
/* check all plgpio MIS registers for a possible interrupt */
for ( ; i < regs_count ; i + + ) {
pending = readl_relaxed ( plgpio - > base + plgpio - > regs . mis +
i * sizeof ( int * ) ) ;
if ( ! pending )
continue ;
/* clear interrupts */
writel_relaxed ( ~ pending , plgpio - > base + plgpio - > regs . mis +
i * sizeof ( int * ) ) ;
/*
* clear extra bits in last register having gpios < MAX / REG
* ex : Suppose there are max 102 plgpios . then last register
* must have only ( 102 - MAX_GPIO_PER_REG * 3 ) = 6 relevant bits
* so , we must not take other 28 bits into consideration for
* checking interrupt . so clear those bits .
*/
count = count - i * MAX_GPIO_PER_REG ;
if ( count < MAX_GPIO_PER_REG )
pending & = ( 1 < < count ) - 1 ;
for_each_set_bit ( offset , & pending , MAX_GPIO_PER_REG ) {
/* get correct pin for "offset" */
if ( plgpio - > o2p & & ( plgpio - > p2o_regs & PTO_MIS_REG ) ) {
pin = plgpio - > o2p ( offset ) ;
if ( pin = = - 1 )
continue ;
} else
pin = offset ;
/* get correct irq line number */
pin = i * MAX_GPIO_PER_REG + pin ;
2014-05-29 11:18:48 +02:00
generic_handle_irq (
2017-11-07 19:15:47 +01:00
irq_find_mapping ( gc - > irq . domain , pin ) ) ;
2012-10-27 15:21:37 +05:30
}
}
chained_irq_exit ( irqchip , desc ) ;
}
/*
* pin to offset and offset to pin converter functions
*
* In spear310 there is inconsistency among bit positions in plgpio regiseters ,
* for different plgpio pins . For example : for pin 27 , bit offset is 23 , pin
* 28 - 33 are not supported , pin 95 has offset bit 95 , bit 100 has offset bit 1
*/
static int spear310_p2o ( int pin )
{
int offset = pin ;
if ( pin < = 27 )
offset + = 4 ;
else if ( pin < = 33 )
offset = - 1 ;
else if ( pin < = 97 )
offset - = 2 ;
else if ( pin < = 101 )
offset = 101 - pin ;
else
offset = - 1 ;
return offset ;
}
2013-06-18 14:34:26 +05:30
static int spear310_o2p ( int offset )
2012-10-27 15:21:37 +05:30
{
if ( offset < = 3 )
return 101 - offset ;
else if ( offset < = 31 )
return offset - 4 ;
else
return offset + 2 ;
}
2012-12-21 13:10:23 -08:00
static int plgpio_probe_dt ( struct platform_device * pdev , struct plgpio * plgpio )
2012-10-27 15:21:37 +05:30
{
struct device_node * np = pdev - > dev . of_node ;
int ret = - EINVAL ;
u32 val ;
if ( of_machine_is_compatible ( " st,spear310 " ) ) {
plgpio - > p2o = spear310_p2o ;
plgpio - > o2p = spear310_o2p ;
plgpio - > p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
PTO_RDATA_REG | PTO_MIS_REG ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,ngpio " , & val ) ) {
plgpio - > chip . ngpio = val ;
} else {
dev_err ( & pdev - > dev , " DT: Invalid ngpio field \n " ) ;
goto end ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,enb-reg " , & val ) )
plgpio - > regs . enb = val ;
else
plgpio - > regs . enb = - 1 ;
if ( ! of_property_read_u32 ( np , " st-plgpio,wdata-reg " , & val ) ) {
plgpio - > regs . wdata = val ;
} else {
dev_err ( & pdev - > dev , " DT: Invalid wdata reg \n " ) ;
goto end ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,dir-reg " , & val ) ) {
plgpio - > regs . dir = val ;
} else {
dev_err ( & pdev - > dev , " DT: Invalid dir reg \n " ) ;
goto end ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,ie-reg " , & val ) ) {
plgpio - > regs . ie = val ;
} else {
dev_err ( & pdev - > dev , " DT: Invalid ie reg \n " ) ;
goto end ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,rdata-reg " , & val ) ) {
plgpio - > regs . rdata = val ;
} else {
dev_err ( & pdev - > dev , " DT: Invalid rdata reg \n " ) ;
goto end ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,mis-reg " , & val ) ) {
plgpio - > regs . mis = val ;
} else {
dev_err ( & pdev - > dev , " DT: Invalid mis reg \n " ) ;
goto end ;
}
if ( ! of_property_read_u32 ( np , " st-plgpio,eit-reg " , & val ) )
plgpio - > regs . eit = val ;
else
plgpio - > regs . eit = - 1 ;
return 0 ;
end :
return ret ;
}
2012-12-21 13:10:23 -08:00
static int plgpio_probe ( struct platform_device * pdev )
2012-10-27 15:21:37 +05:30
{
struct plgpio * plgpio ;
2014-05-29 11:18:48 +02:00
int ret , irq ;
2012-10-27 15:21:37 +05:30
plgpio = devm_kzalloc ( & pdev - > dev , sizeof ( * plgpio ) , GFP_KERNEL ) ;
2017-12-27 22:34:28 +01:00
if ( ! plgpio )
2012-10-27 15:21:37 +05:30
return - ENOMEM ;
2019-11-04 22:26:54 +08:00
plgpio - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2013-01-21 11:09:14 +01:00
if ( IS_ERR ( plgpio - > base ) )
return PTR_ERR ( plgpio - > base ) ;
2012-10-27 15:21:37 +05:30
ret = plgpio_probe_dt ( pdev , plgpio ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " DT probe failed \n " ) ;
return ret ;
}
plgpio - > clk = devm_clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( plgpio - > clk ) )
dev_warn ( & pdev - > dev , " clk_get() failed, work without it \n " ) ;
2013-03-25 18:59:38 +09:00
# ifdef CONFIG_PM_SLEEP
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:07:58 -07:00
plgpio - > csave_regs = devm_kcalloc ( & pdev - > dev ,
2012-10-27 15:21:37 +05:30
DIV_ROUND_UP ( plgpio - > chip . ngpio , MAX_GPIO_PER_REG ) ,
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:07:58 -07:00
sizeof ( * plgpio - > csave_regs ) ,
2012-10-27 15:21:37 +05:30
GFP_KERNEL ) ;
2017-12-27 22:34:28 +01:00
if ( ! plgpio - > csave_regs )
2012-10-27 15:21:37 +05:30
return - ENOMEM ;
# endif
platform_set_drvdata ( pdev , plgpio ) ;
spin_lock_init ( & plgpio - > lock ) ;
plgpio - > chip . base = - 1 ;
plgpio - > chip . request = plgpio_request ;
plgpio - > chip . free = plgpio_free ;
plgpio - > chip . direction_input = plgpio_direction_input ;
plgpio - > chip . direction_output = plgpio_direction_output ;
plgpio - > chip . get = plgpio_get_value ;
plgpio - > chip . set = plgpio_set_value ;
plgpio - > chip . label = dev_name ( & pdev - > dev ) ;
2015-11-04 09:56:26 +01:00
plgpio - > chip . parent = & pdev - > dev ;
2012-10-27 15:21:37 +05:30
plgpio - > chip . owner = THIS_MODULE ;
2014-05-29 11:18:48 +02:00
plgpio - > chip . of_node = pdev - > dev . of_node ;
2012-10-27 15:21:37 +05:30
2012-11-14 14:44:07 +05:30
if ( ! IS_ERR ( plgpio - > clk ) ) {
ret = clk_prepare ( plgpio - > clk ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " clk prepare failed \n " ) ;
return ret ;
}
}
2012-10-27 15:21:37 +05:30
irq = platform_get_irq ( pdev , 0 ) ;
2019-09-13 13:35:27 +02:00
if ( irq > 0 ) {
struct gpio_irq_chip * girq ;
girq = & plgpio - > chip . irq ;
girq - > chip = & plgpio_irqchip ;
girq - > parent_handler = plgpio_irq_handler ;
girq - > num_parents = 1 ;
girq - > parents = devm_kcalloc ( & pdev - > dev , 1 ,
sizeof ( * girq - > parents ) ,
GFP_KERNEL ) ;
if ( ! girq - > parents )
return - ENOMEM ;
girq - > parents [ 0 ] = irq ;
girq - > default_type = IRQ_TYPE_NONE ;
girq - > handler = handle_simple_irq ;
dev_info ( & pdev - > dev , " PLGPIO registering with IRQs \n " ) ;
} else {
dev_info ( & pdev - > dev , " PLGPIO registering without IRQs \n " ) ;
2012-10-27 15:21:37 +05:30
}
2019-09-13 13:35:27 +02:00
ret = gpiochip_add_data ( & plgpio - > chip , plgpio ) ;
2014-05-29 11:18:48 +02:00
if ( ret ) {
2019-09-13 13:35:27 +02:00
dev_err ( & pdev - > dev , " unable to add gpio chip \n " ) ;
goto unprepare_clk ;
2012-10-27 15:21:37 +05:30
}
return 0 ;
2012-11-14 14:44:07 +05:30
unprepare_clk :
if ( ! IS_ERR ( plgpio - > clk ) )
clk_unprepare ( plgpio - > clk ) ;
2012-10-27 15:21:37 +05:30
return ret ;
}
2013-03-25 18:59:38 +09:00
# ifdef CONFIG_PM_SLEEP
2012-10-27 15:21:37 +05:30
static int plgpio_suspend ( struct device * dev )
{
struct plgpio * plgpio = dev_get_drvdata ( dev ) ;
int i , reg_count = DIV_ROUND_UP ( plgpio - > chip . ngpio , MAX_GPIO_PER_REG ) ;
void __iomem * off ;
for ( i = 0 ; i < reg_count ; i + + ) {
off = plgpio - > base + i * sizeof ( int * ) ;
if ( plgpio - > regs . enb ! = - 1 )
plgpio - > csave_regs [ i ] . enb =
readl_relaxed ( plgpio - > regs . enb + off ) ;
if ( plgpio - > regs . eit ! = - 1 )
plgpio - > csave_regs [ i ] . eit =
readl_relaxed ( plgpio - > regs . eit + off ) ;
plgpio - > csave_regs [ i ] . wdata = readl_relaxed ( plgpio - > regs . wdata +
off ) ;
plgpio - > csave_regs [ i ] . dir = readl_relaxed ( plgpio - > regs . dir +
off ) ;
plgpio - > csave_regs [ i ] . ie = readl_relaxed ( plgpio - > regs . ie + off ) ;
}
return 0 ;
}
/*
* This is used to correct the values in end registers . End registers contain
* extra bits that might be used for other purpose in platform . So , we shouldn ' t
* overwrite these bits . This macro , reads given register again , preserves other
* bit values ( non - plgpio bits ) , and retain captured value ( plgpio bits ) .
*/
# define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \
{ \
_tmp = readl_relaxed ( plgpio - > regs . __reg + _off ) ; \
_tmp & = ~ _mask ; \
plgpio - > csave_regs [ i ] . __reg = \
_tmp | ( plgpio - > csave_regs [ i ] . __reg & _mask ) ; \
}
static int plgpio_resume ( struct device * dev )
{
struct plgpio * plgpio = dev_get_drvdata ( dev ) ;
int i , reg_count = DIV_ROUND_UP ( plgpio - > chip . ngpio , MAX_GPIO_PER_REG ) ;
void __iomem * off ;
u32 mask , tmp ;
for ( i = 0 ; i < reg_count ; i + + ) {
off = plgpio - > base + i * sizeof ( int * ) ;
if ( i = = reg_count - 1 ) {
mask = ( 1 < < ( plgpio - > chip . ngpio - i *
MAX_GPIO_PER_REG ) ) - 1 ;
if ( plgpio - > regs . enb ! = - 1 )
plgpio_prepare_reg ( enb , off , mask , tmp ) ;
if ( plgpio - > regs . eit ! = - 1 )
plgpio_prepare_reg ( eit , off , mask , tmp ) ;
plgpio_prepare_reg ( wdata , off , mask , tmp ) ;
plgpio_prepare_reg ( dir , off , mask , tmp ) ;
plgpio_prepare_reg ( ie , off , mask , tmp ) ;
}
writel_relaxed ( plgpio - > csave_regs [ i ] . wdata , plgpio - > regs . wdata +
off ) ;
writel_relaxed ( plgpio - > csave_regs [ i ] . dir , plgpio - > regs . dir +
off ) ;
if ( plgpio - > regs . eit ! = - 1 )
writel_relaxed ( plgpio - > csave_regs [ i ] . eit ,
plgpio - > regs . eit + off ) ;
writel_relaxed ( plgpio - > csave_regs [ i ] . ie , plgpio - > regs . ie + off ) ;
if ( plgpio - > regs . enb ! = - 1 )
writel_relaxed ( plgpio - > csave_regs [ i ] . enb ,
plgpio - > regs . enb + off ) ;
}
return 0 ;
}
# endif
static SIMPLE_DEV_PM_OPS ( plgpio_dev_pm_ops , plgpio_suspend , plgpio_resume ) ;
static const struct of_device_id plgpio_of_match [ ] = {
{ . compatible = " st,spear-plgpio " } ,
{ }
} ;
static struct platform_driver plgpio_driver = {
. probe = plgpio_probe ,
. driver = {
. name = " spear-plgpio " ,
. pm = & plgpio_dev_pm_ops ,
2013-09-28 17:38:48 +05:30
. of_match_table = plgpio_of_match ,
2012-10-27 15:21:37 +05:30
} ,
} ;
static int __init plgpio_init ( void )
{
return platform_driver_register ( & plgpio_driver ) ;
}
subsys_initcall ( plgpio_init ) ;