2011-12-25 21:36:02 +01:00
/*
* Generic GPIO card - detect helper
*
* Copyright ( C ) 2011 , Guennadi Liakhovetski < g . liakhovetski @ gmx . de >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/err.h>
# include <linux/gpio.h>
# include <linux/interrupt.h>
# include <linux/jiffies.h>
# include <linux/mmc/host.h>
2012-04-30 23:31:57 +02:00
# include <linux/mmc/slot-gpio.h>
2011-12-25 21:36:02 +01:00
# include <linux/module.h>
# include <linux/slab.h>
2012-04-30 23:31:57 +02:00
struct mmc_gpio {
2012-05-01 16:59:38 +02:00
int ro_gpio ;
2012-05-01 16:27:25 +02:00
int cd_gpio ;
2012-05-01 16:59:38 +02:00
char * ro_label ;
2012-04-30 23:31:57 +02:00
char cd_label [ 0 ] ;
2011-12-25 21:36:02 +01:00
} ;
2012-04-30 23:31:57 +02:00
static irqreturn_t mmc_gpio_cd_irqt ( int irq , void * dev_id )
2011-12-25 21:36:02 +01:00
{
/* Schedule a card detection after a debounce timeout */
2012-12-04 16:51:36 +01:00
struct mmc_host * host = dev_id ;
if ( host - > ops - > card_event )
host - > ops - > card_event ( host ) ;
mmc_detect_change ( host , msecs_to_jiffies ( 200 ) ) ;
2011-12-25 21:36:02 +01:00
return IRQ_HANDLED ;
}
2012-05-01 16:51:38 +02:00
static int mmc_gpio_alloc ( struct mmc_host * host )
{
size_t len = strlen ( dev_name ( host - > parent ) ) + 4 ;
struct mmc_gpio * ctx ;
mutex_lock ( & host - > slot . lock ) ;
ctx = host - > slot . handler_priv ;
if ( ! ctx ) {
/*
* devm_kzalloc ( ) can be called after device_initialize ( ) , even
* before device_add ( ) , i . e . , between mmc_alloc_host ( ) and
* mmc_add_host ( )
*/
2012-05-01 16:59:38 +02:00
ctx = devm_kzalloc ( & host - > class_dev , sizeof ( * ctx ) + 2 * len ,
2012-05-01 16:51:38 +02:00
GFP_KERNEL ) ;
if ( ctx ) {
2012-05-01 16:59:38 +02:00
ctx - > ro_label = ctx - > cd_label + len ;
2012-05-01 16:51:38 +02:00
snprintf ( ctx - > cd_label , len , " %s cd " , dev_name ( host - > parent ) ) ;
2012-05-01 16:59:38 +02:00
snprintf ( ctx - > ro_label , len , " %s ro " , dev_name ( host - > parent ) ) ;
2012-05-01 16:51:38 +02:00
ctx - > cd_gpio = - EINVAL ;
2012-05-01 16:59:38 +02:00
ctx - > ro_gpio = - EINVAL ;
2012-05-01 16:51:38 +02:00
host - > slot . handler_priv = ctx ;
}
}
mutex_unlock ( & host - > slot . lock ) ;
return ctx ? 0 : - ENOMEM ;
}
2012-05-01 16:59:38 +02:00
int mmc_gpio_get_ro ( struct mmc_host * host )
{
struct mmc_gpio * ctx = host - > slot . handler_priv ;
if ( ! ctx | | ! gpio_is_valid ( ctx - > ro_gpio ) )
return - ENOSYS ;
return ! gpio_get_value_cansleep ( ctx - > ro_gpio ) ^
! ! ( host - > caps2 & MMC_CAP2_RO_ACTIVE_HIGH ) ;
}
EXPORT_SYMBOL ( mmc_gpio_get_ro ) ;
2012-05-01 16:27:25 +02:00
int mmc_gpio_get_cd ( struct mmc_host * host )
{
struct mmc_gpio * ctx = host - > slot . handler_priv ;
if ( ! ctx | | ! gpio_is_valid ( ctx - > cd_gpio ) )
return - ENOSYS ;
return ! gpio_get_value_cansleep ( ctx - > cd_gpio ) ^
! ! ( host - > caps2 & MMC_CAP2_CD_ACTIVE_HIGH ) ;
}
EXPORT_SYMBOL ( mmc_gpio_get_cd ) ;
2012-12-11 22:32:18 +08:00
/**
* mmc_gpio_request_ro - request a gpio for write - protection
* @ host : mmc host
* @ gpio : gpio number requested
*
* As devm_ * managed functions are used in mmc_gpio_request_ro ( ) , client
* drivers do not need to explicitly call mmc_gpio_free_ro ( ) for freeing up ,
* if the requesting and freeing are only needed at probing and unbinding time
* for once . However , if client drivers do something special like runtime
* switching for write - protection , they are responsible for calling
* mmc_gpio_request_ro ( ) and mmc_gpio_free_ro ( ) as a pair on their own .
*
* Returns zero on success , else an error .
*/
2012-05-01 16:59:38 +02:00
int mmc_gpio_request_ro ( struct mmc_host * host , unsigned int gpio )
{
struct mmc_gpio * ctx ;
int ret ;
if ( ! gpio_is_valid ( gpio ) )
return - EINVAL ;
ret = mmc_gpio_alloc ( host ) ;
if ( ret < 0 )
return ret ;
ctx = host - > slot . handler_priv ;
2012-12-11 22:32:18 +08:00
ret = devm_gpio_request_one ( & host - > class_dev , gpio , GPIOF_DIR_IN ,
ctx - > ro_label ) ;
2012-09-09 22:56:48 -04:00
if ( ret < 0 )
return ret ;
ctx - > ro_gpio = gpio ;
return 0 ;
2012-05-01 16:59:38 +02:00
}
EXPORT_SYMBOL ( mmc_gpio_request_ro ) ;
2012-12-11 22:32:18 +08:00
/**
* mmc_gpio_request_cd - request a gpio for card - detection
* @ host : mmc host
* @ gpio : gpio number requested
2013-08-08 12:38:31 +02:00
* @ debounce : debounce time in microseconds
2012-12-11 22:32:18 +08:00
*
* As devm_ * managed functions are used in mmc_gpio_request_cd ( ) , client
* drivers do not need to explicitly call mmc_gpio_free_cd ( ) for freeing up ,
* if the requesting and freeing are only needed at probing and unbinding time
* for once . However , if client drivers do something special like runtime
* switching for card - detection , they are responsible for calling
* mmc_gpio_request_cd ( ) and mmc_gpio_free_cd ( ) as a pair on their own .
*
2013-08-08 12:38:31 +02:00
* If GPIO debouncing is desired , set the debounce parameter to a non - zero
* value . The caller is responsible for ensuring that the GPIO driver associated
* with the GPIO supports debouncing , otherwise an error will be returned .
*
2012-12-11 22:32:18 +08:00
* Returns zero on success , else an error .
*/
2013-08-08 12:38:31 +02:00
int mmc_gpio_request_cd ( struct mmc_host * host , unsigned int gpio ,
unsigned int debounce )
2011-12-25 21:36:02 +01:00
{
2012-04-30 23:31:57 +02:00
struct mmc_gpio * ctx ;
2012-02-09 22:57:07 +01:00
int irq = gpio_to_irq ( gpio ) ;
2011-12-25 21:36:02 +01:00
int ret ;
2012-05-01 16:51:38 +02:00
ret = mmc_gpio_alloc ( host ) ;
if ( ret < 0 )
return ret ;
2011-12-25 21:36:02 +01:00
2012-05-01 16:51:38 +02:00
ctx = host - > slot . handler_priv ;
2011-12-25 21:36:02 +01:00
2012-12-11 22:32:18 +08:00
ret = devm_gpio_request_one ( & host - > class_dev , gpio , GPIOF_DIR_IN ,
ctx - > cd_label ) ;
2011-12-25 21:36:02 +01:00
if ( ret < 0 )
2012-05-01 16:51:38 +02:00
/*
* don ' t bother freeing memory . It might still get used by other
* slot functions , in any case it will be freed , when the device
* is destroyed .
*/
return ret ;
2011-12-25 21:36:02 +01:00
2013-08-08 12:38:31 +02:00
if ( debounce ) {
ret = gpio_set_debounce ( gpio , debounce ) ;
if ( ret < 0 )
return ret ;
}
2012-05-01 16:27:25 +02:00
/*
* Even if gpio_to_irq ( ) returns a valid IRQ number , the platform might
* still prefer to poll , e . g . , because that IRQ number is already used
* by another unit and cannot be shared .
*/
if ( irq > = 0 & & host - > caps & MMC_CAP_NEEDS_POLL )
irq = - EINVAL ;
if ( irq > = 0 ) {
2012-12-11 22:32:18 +08:00
ret = devm_request_threaded_irq ( & host - > class_dev , irq ,
NULL , mmc_gpio_cd_irqt ,
2012-04-30 23:31:57 +02:00
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
ctx - > cd_label , host ) ;
2012-05-01 16:27:25 +02:00
if ( ret < 0 )
irq = ret ;
}
2011-12-25 21:36:02 +01:00
2012-05-01 15:40:15 +02:00
host - > slot . cd_irq = irq ;
2012-05-01 16:27:25 +02:00
if ( irq < 0 )
host - > caps | = MMC_CAP_NEEDS_POLL ;
ctx - > cd_gpio = gpio ;
2011-12-25 21:36:02 +01:00
return 0 ;
}
2012-04-30 23:31:57 +02:00
EXPORT_SYMBOL ( mmc_gpio_request_cd ) ;
2011-12-25 21:36:02 +01:00
2012-12-11 22:32:18 +08:00
/**
* mmc_gpio_free_ro - free the write - protection gpio
* @ host : mmc host
*
* It ' s provided only for cases that client drivers need to manually free
* up the write - protection gpio requested by mmc_gpio_request_ro ( ) .
*/
2012-05-01 16:59:38 +02:00
void mmc_gpio_free_ro ( struct mmc_host * host )
{
struct mmc_gpio * ctx = host - > slot . handler_priv ;
int gpio ;
if ( ! ctx | | ! gpio_is_valid ( ctx - > ro_gpio ) )
return ;
gpio = ctx - > ro_gpio ;
ctx - > ro_gpio = - EINVAL ;
2012-12-11 22:32:18 +08:00
devm_gpio_free ( & host - > class_dev , gpio ) ;
2012-05-01 16:59:38 +02:00
}
EXPORT_SYMBOL ( mmc_gpio_free_ro ) ;
2012-12-11 22:32:18 +08:00
/**
* mmc_gpio_free_cd - free the card - detection gpio
* @ host : mmc host
*
* It ' s provided only for cases that client drivers need to manually free
* up the card - detection gpio requested by mmc_gpio_request_cd ( ) .
*/
2012-04-30 23:31:57 +02:00
void mmc_gpio_free_cd ( struct mmc_host * host )
2011-12-25 21:36:02 +01:00
{
2012-05-01 15:40:15 +02:00
struct mmc_gpio * ctx = host - > slot . handler_priv ;
2012-05-01 16:27:25 +02:00
int gpio ;
2011-12-25 21:36:02 +01:00
2012-05-01 16:27:25 +02:00
if ( ! ctx | | ! gpio_is_valid ( ctx - > cd_gpio ) )
2012-04-24 17:56:29 +02:00
return ;
2012-05-01 16:27:25 +02:00
if ( host - > slot . cd_irq > = 0 ) {
2012-12-11 22:32:18 +08:00
devm_free_irq ( & host - > class_dev , host - > slot . cd_irq , host ) ;
2012-05-01 16:27:25 +02:00
host - > slot . cd_irq = - EINVAL ;
}
gpio = ctx - > cd_gpio ;
ctx - > cd_gpio = - EINVAL ;
2012-12-11 22:32:18 +08:00
devm_gpio_free ( & host - > class_dev , gpio ) ;
2011-12-25 21:36:02 +01:00
}
2012-04-30 23:31:57 +02:00
EXPORT_SYMBOL ( mmc_gpio_free_cd ) ;