2010-07-02 15:22:10 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* License Terms : GNU General Public License , version 2
* Author : Rabin Vincent < rabin . vincent @ stericsson . com > for ST - Ericsson
*/
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/input.h>
# include <linux/interrupt.h>
# include <linux/platform_device.h>
# include <linux/input/matrix_keypad.h>
# include <linux/mfd/stmpe.h>
/* These are at the same addresses in all STMPE variants */
# define STMPE_KPC_COL 0x60
# define STMPE_KPC_ROW_MSB 0x61
# define STMPE_KPC_ROW_LSB 0x62
# define STMPE_KPC_CTRL_MSB 0x63
# define STMPE_KPC_CTRL_LSB 0x64
# define STMPE_KPC_COMBI_KEY_0 0x65
# define STMPE_KPC_COMBI_KEY_1 0x66
# define STMPE_KPC_COMBI_KEY_2 0x67
# define STMPE_KPC_DATA_BYTE0 0x68
# define STMPE_KPC_DATA_BYTE1 0x69
# define STMPE_KPC_DATA_BYTE2 0x6a
# define STMPE_KPC_DATA_BYTE3 0x6b
# define STMPE_KPC_DATA_BYTE4 0x6c
# define STMPE_KPC_CTRL_LSB_SCAN (0x1 << 0)
# define STMPE_KPC_CTRL_LSB_DEBOUNCE (0x7f << 1)
# define STMPE_KPC_CTRL_MSB_SCAN_COUNT (0xf << 4)
# define STMPE_KPC_ROW_MSB_ROWS 0xff
# define STMPE_KPC_DATA_UP (0x1 << 7)
# define STMPE_KPC_DATA_ROW (0xf << 3)
# define STMPE_KPC_DATA_COL (0x7 << 0)
# define STMPE_KPC_DATA_NOKEY_MASK 0x78
# define STMPE_KEYPAD_MAX_DEBOUNCE 127
# define STMPE_KEYPAD_MAX_SCAN_COUNT 15
# define STMPE_KEYPAD_MAX_ROWS 8
# define STMPE_KEYPAD_MAX_COLS 8
# define STMPE_KEYPAD_ROW_SHIFT 3
2014-11-04 03:51:26 +03:00
# define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
2010-07-02 15:22:10 +04:00
( STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS )
2018-03-10 21:16:41 +03:00
# define STMPE1601_NUM_DATA 5
# define STMPE2401_NUM_DATA 3
# define STMPE2403_NUM_DATA 5
/* Make sure it covers all cases above */
# define MAX_NUM_DATA 5
2010-07-02 15:22:10 +04:00
/**
* struct stmpe_keypad_variant - model - specific attributes
* @ auto_increment : whether the KPC_DATA_BYTE register address
* auto - increments on multiple read
2014-12-16 09:23:40 +03:00
* @ set_pullup : whether the pins need to have their pull - ups set
2010-07-02 15:22:10 +04:00
* @ num_data : number of data bytes
* @ num_normal_data : number of normal keys ' data bytes
* @ max_cols : maximum number of columns supported
* @ max_rows : maximum number of rows supported
* @ col_gpios : bitmask of gpios which can be used for columns
* @ row_gpios : bitmask of gpios which can be used for rows
*/
struct stmpe_keypad_variant {
bool auto_increment ;
2014-12-16 09:23:40 +03:00
bool set_pullup ;
2010-07-02 15:22:10 +04:00
int num_data ;
int num_normal_data ;
int max_cols ;
int max_rows ;
unsigned int col_gpios ;
unsigned int row_gpios ;
} ;
static const struct stmpe_keypad_variant stmpe_keypad_variants [ ] = {
[ STMPE1601 ] = {
. auto_increment = true ,
2018-03-10 21:16:41 +03:00
. num_data = STMPE1601_NUM_DATA ,
2010-07-02 15:22:10 +04:00
. num_normal_data = 3 ,
. max_cols = 8 ,
. max_rows = 8 ,
. col_gpios = 0x000ff , /* GPIO 0 - 7 */
. row_gpios = 0x0ff00 , /* GPIO 8 - 15 */
} ,
[ STMPE2401 ] = {
. auto_increment = false ,
2014-12-16 09:23:40 +03:00
. set_pullup = true ,
2018-03-10 21:16:41 +03:00
. num_data = STMPE2401_NUM_DATA ,
2010-07-02 15:22:10 +04:00
. num_normal_data = 2 ,
. max_cols = 8 ,
. max_rows = 12 ,
. col_gpios = 0x0000ff , /* GPIO 0 - 7*/
2014-10-25 01:36:54 +04:00
. row_gpios = 0x1f7f00 , /* GPIO 8-14, 16-20 */
2010-07-02 15:22:10 +04:00
} ,
[ STMPE2403 ] = {
. auto_increment = true ,
2014-12-16 09:23:40 +03:00
. set_pullup = true ,
2018-03-10 21:16:41 +03:00
. num_data = STMPE2403_NUM_DATA ,
2010-07-02 15:22:10 +04:00
. num_normal_data = 3 ,
. max_cols = 8 ,
. max_rows = 12 ,
. col_gpios = 0x0000ff , /* GPIO 0 - 7*/
. row_gpios = 0x1fef00 , /* GPIO 8-14, 16-20 */
} ,
} ;
2014-11-04 03:51:26 +03:00
/**
* struct stmpe_keypad - STMPE keypad state container
* @ stmpe : pointer to parent STMPE device
* @ input : spawned input device
* @ variant : STMPE variant
* @ debounce_ms : debounce interval , in ms . Maximum is
* % STMPE_KEYPAD_MAX_DEBOUNCE .
* @ scan_count : number of key scanning cycles to confirm key data .
* Maximum is % STMPE_KEYPAD_MAX_SCAN_COUNT .
* @ no_autorepeat : disable key autorepeat
* @ rows : bitmask for the rows
* @ cols : bitmask for the columns
* @ keymap : the keymap
*/
2010-07-02 15:22:10 +04:00
struct stmpe_keypad {
struct stmpe * stmpe ;
struct input_dev * input ;
const struct stmpe_keypad_variant * variant ;
2014-11-04 03:51:26 +03:00
unsigned int debounce_ms ;
unsigned int scan_count ;
bool no_autorepeat ;
2010-07-02 15:22:10 +04:00
unsigned int rows ;
unsigned int cols ;
2014-11-04 03:51:26 +03:00
unsigned short keymap [ STMPE_KEYPAD_KEYMAP_MAX_SIZE ] ;
2010-07-02 15:22:10 +04:00
} ;
static int stmpe_keypad_read_data ( struct stmpe_keypad * keypad , u8 * data )
{
const struct stmpe_keypad_variant * variant = keypad - > variant ;
struct stmpe * stmpe = keypad - > stmpe ;
int ret ;
int i ;
if ( variant - > auto_increment )
return stmpe_block_read ( stmpe , STMPE_KPC_DATA_BYTE0 ,
variant - > num_data , data ) ;
for ( i = 0 ; i < variant - > num_data ; i + + ) {
ret = stmpe_reg_read ( stmpe , STMPE_KPC_DATA_BYTE0 + i ) ;
if ( ret < 0 )
return ret ;
data [ i ] = ret ;
}
return 0 ;
}
static irqreturn_t stmpe_keypad_irq ( int irq , void * dev )
{
struct stmpe_keypad * keypad = dev ;
struct input_dev * input = keypad - > input ;
const struct stmpe_keypad_variant * variant = keypad - > variant ;
2018-03-10 21:16:41 +03:00
u8 fifo [ MAX_NUM_DATA ] ;
2010-07-02 15:22:10 +04:00
int ret ;
int i ;
ret = stmpe_keypad_read_data ( keypad , fifo ) ;
if ( ret < 0 )
return IRQ_NONE ;
for ( i = 0 ; i < variant - > num_normal_data ; i + + ) {
u8 data = fifo [ i ] ;
int row = ( data & STMPE_KPC_DATA_ROW ) > > 3 ;
int col = data & STMPE_KPC_DATA_COL ;
int code = MATRIX_SCAN_CODE ( row , col , STMPE_KEYPAD_ROW_SHIFT ) ;
bool up = data & STMPE_KPC_DATA_UP ;
if ( ( data & STMPE_KPC_DATA_NOKEY_MASK )
= = STMPE_KPC_DATA_NOKEY_MASK )
continue ;
input_event ( input , EV_MSC , MSC_SCAN , code ) ;
input_report_key ( input , keypad - > keymap [ code ] , ! up ) ;
input_sync ( input ) ;
}
return IRQ_HANDLED ;
}
2012-11-24 09:38:25 +04:00
static int stmpe_keypad_altfunc_init ( struct stmpe_keypad * keypad )
2010-07-02 15:22:10 +04:00
{
const struct stmpe_keypad_variant * variant = keypad - > variant ;
unsigned int col_gpios = variant - > col_gpios ;
unsigned int row_gpios = variant - > row_gpios ;
struct stmpe * stmpe = keypad - > stmpe ;
2014-12-16 09:23:40 +03:00
u8 pureg = stmpe - > regs [ STMPE_IDX_GPPUR_LSB ] ;
2010-07-02 15:22:10 +04:00
unsigned int pins = 0 ;
2014-12-16 09:23:40 +03:00
unsigned int pu_pins = 0 ;
int ret ;
2010-07-02 15:22:10 +04:00
int i ;
/*
* Figure out which pins need to be set to the keypad alternate
* function .
*
* { cols , rows } _gpios are bitmasks of which pins on the chip can be used
* for the keypad .
*
* keypad - > { cols , rows } are a bitmask of which pins ( of the ones useable
* for the keypad ) are used on the board .
*/
for ( i = 0 ; i < variant - > max_cols ; i + + ) {
int num = __ffs ( col_gpios ) ;
2014-12-16 09:23:40 +03:00
if ( keypad - > cols & ( 1 < < i ) ) {
2010-07-02 15:22:10 +04:00
pins | = 1 < < num ;
2014-12-16 09:23:40 +03:00
pu_pins | = 1 < < num ;
}
2010-07-02 15:22:10 +04:00
col_gpios & = ~ ( 1 < < num ) ;
}
for ( i = 0 ; i < variant - > max_rows ; i + + ) {
int num = __ffs ( row_gpios ) ;
if ( keypad - > rows & ( 1 < < i ) )
pins | = 1 < < num ;
row_gpios & = ~ ( 1 < < num ) ;
}
2014-12-16 09:23:40 +03:00
ret = stmpe_set_altfunc ( stmpe , pins , STMPE_BLOCK_KEYPAD ) ;
if ( ret )
return ret ;
/*
* On STMPE24xx , set pin bias to pull - up on all keypad input
* pins ( columns ) , this incidentally happen to be maximum 8 pins
* and placed at GPIO0 - 7 so only the LSB of the pull up register
* ever needs to be written .
*/
if ( variant - > set_pullup ) {
u8 val ;
ret = stmpe_reg_read ( stmpe , pureg ) ;
if ( ret )
return ret ;
/* Do not touch unused pins, may be used for GPIO */
val = ret & ~ pu_pins ;
val | = pu_pins ;
ret = stmpe_reg_write ( stmpe , pureg , val ) ;
}
return 0 ;
2010-07-02 15:22:10 +04:00
}
2012-11-24 09:38:25 +04:00
static int stmpe_keypad_chip_init ( struct stmpe_keypad * keypad )
2010-07-02 15:22:10 +04:00
{
const struct stmpe_keypad_variant * variant = keypad - > variant ;
struct stmpe * stmpe = keypad - > stmpe ;
int ret ;
2014-11-04 03:51:26 +03:00
if ( keypad - > debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE )
2010-07-02 15:22:10 +04:00
return - EINVAL ;
2014-11-04 03:51:26 +03:00
if ( keypad - > scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT )
2010-07-02 15:22:10 +04:00
return - EINVAL ;
ret = stmpe_enable ( stmpe , STMPE_BLOCK_KEYPAD ) ;
if ( ret < 0 )
return ret ;
ret = stmpe_keypad_altfunc_init ( keypad ) ;
if ( ret < 0 )
return ret ;
ret = stmpe_reg_write ( stmpe , STMPE_KPC_COL , keypad - > cols ) ;
if ( ret < 0 )
return ret ;
ret = stmpe_reg_write ( stmpe , STMPE_KPC_ROW_LSB , keypad - > rows ) ;
if ( ret < 0 )
return ret ;
if ( variant - > max_rows > 8 ) {
ret = stmpe_set_bits ( stmpe , STMPE_KPC_ROW_MSB ,
STMPE_KPC_ROW_MSB_ROWS ,
keypad - > rows > > 8 ) ;
if ( ret < 0 )
return ret ;
}
ret = stmpe_set_bits ( stmpe , STMPE_KPC_CTRL_MSB ,
STMPE_KPC_CTRL_MSB_SCAN_COUNT ,
2014-11-04 03:51:26 +03:00
keypad - > scan_count < < 4 ) ;
2010-07-02 15:22:10 +04:00
if ( ret < 0 )
return ret ;
return stmpe_set_bits ( stmpe , STMPE_KPC_CTRL_LSB ,
STMPE_KPC_CTRL_LSB_SCAN |
STMPE_KPC_CTRL_LSB_DEBOUNCE ,
STMPE_KPC_CTRL_LSB_SCAN |
2014-11-04 03:51:26 +03:00
( keypad - > debounce_ms < < 1 ) ) ;
2010-07-02 15:22:10 +04:00
}
2014-11-04 03:51:26 +03:00
static void stmpe_keypad_fill_used_pins ( struct stmpe_keypad * keypad ,
u32 used_rows , u32 used_cols )
2012-11-14 20:55:21 +04:00
{
int row , col ;
2014-11-04 03:51:26 +03:00
for ( row = 0 ; row < used_rows ; row + + ) {
for ( col = 0 ; col < used_cols ; col + + ) {
2012-11-14 20:55:21 +04:00
int code = MATRIX_SCAN_CODE ( row , col ,
2014-11-04 03:51:26 +03:00
STMPE_KEYPAD_ROW_SHIFT ) ;
2012-11-14 20:55:21 +04:00
if ( keypad - > keymap [ code ] ! = KEY_RESERVED ) {
keypad - > rows | = 1 < < row ;
keypad - > cols | = 1 < < col ;
}
}
}
}
2012-11-24 09:38:25 +04:00
static int stmpe_keypad_probe ( struct platform_device * pdev )
2010-07-02 15:22:10 +04:00
{
struct stmpe * stmpe = dev_get_drvdata ( pdev - > dev . parent ) ;
2014-11-04 03:51:26 +03:00
struct device_node * np = pdev - > dev . of_node ;
2010-07-02 15:22:10 +04:00
struct stmpe_keypad * keypad ;
struct input_dev * input ;
2014-11-04 03:51:26 +03:00
u32 rows ;
u32 cols ;
2012-11-10 12:11:10 +04:00
int error ;
2010-07-02 15:22:10 +04:00
int irq ;
irq = platform_get_irq ( pdev , 0 ) ;
if ( irq < 0 )
return irq ;
2012-11-10 12:11:10 +04:00
keypad = devm_kzalloc ( & pdev - > dev , sizeof ( struct stmpe_keypad ) ,
GFP_KERNEL ) ;
2010-07-02 15:22:10 +04:00
if ( ! keypad )
return - ENOMEM ;
2014-11-04 03:51:26 +03:00
keypad - > stmpe = stmpe ;
keypad - > variant = & stmpe_keypad_variants [ stmpe - > partnum ] ;
of_property_read_u32 ( np , " debounce-interval " , & keypad - > debounce_ms ) ;
of_property_read_u32 ( np , " st,scan-count " , & keypad - > scan_count ) ;
keypad - > no_autorepeat = of_property_read_bool ( np , " st,no-autorepeat " ) ;
2012-11-10 12:11:10 +04:00
input = devm_input_allocate_device ( & pdev - > dev ) ;
if ( ! input )
return - ENOMEM ;
2010-07-02 15:22:10 +04:00
input - > name = " STMPE keypad " ;
input - > id . bustype = BUS_I2C ;
input - > dev . parent = & pdev - > dev ;
2016-11-11 23:43:12 +03:00
error = matrix_keypad_parse_properties ( & pdev - > dev , & rows , & cols ) ;
2014-11-04 03:51:26 +03:00
if ( error )
return error ;
error = matrix_keypad_build_keymap ( NULL , NULL , rows , cols ,
2012-11-10 12:11:10 +04:00
keypad - > keymap , input ) ;
if ( error )
return error ;
2010-07-02 15:22:10 +04:00
2012-05-11 09:37:08 +04:00
input_set_capability ( input , EV_MSC , MSC_SCAN ) ;
2014-11-04 03:51:26 +03:00
if ( ! keypad - > no_autorepeat )
2010-07-02 15:22:10 +04:00
__set_bit ( EV_REP , input - > evbit ) ;
2014-11-04 03:51:26 +03:00
stmpe_keypad_fill_used_pins ( keypad , rows , cols ) ;
2010-07-02 15:22:10 +04:00
keypad - > input = input ;
2012-11-10 12:11:10 +04:00
error = stmpe_keypad_chip_init ( keypad ) ;
if ( error < 0 )
return error ;
2010-07-02 15:22:10 +04:00
2012-11-10 12:11:10 +04:00
error = devm_request_threaded_irq ( & pdev - > dev , irq ,
NULL , stmpe_keypad_irq ,
IRQF_ONESHOT , " stmpe-keypad " , keypad ) ;
if ( error ) {
dev_err ( & pdev - > dev , " unable to get irq: %d \n " , error ) ;
return error ;
2010-07-02 15:22:10 +04:00
}
2012-11-10 12:11:10 +04:00
error = input_register_device ( input ) ;
if ( error ) {
dev_err ( & pdev - > dev ,
" unable to register input device: %d \n " , error ) ;
return error ;
2010-07-02 15:22:10 +04:00
}
platform_set_drvdata ( pdev , keypad ) ;
return 0 ;
}
2012-11-24 09:50:47 +04:00
static int stmpe_keypad_remove ( struct platform_device * pdev )
2010-07-02 15:22:10 +04:00
{
struct stmpe_keypad * keypad = platform_get_drvdata ( pdev ) ;
2012-11-10 12:11:10 +04:00
stmpe_disable ( keypad - > stmpe , STMPE_BLOCK_KEYPAD ) ;
2010-07-02 15:22:10 +04:00
return 0 ;
}
static struct platform_driver stmpe_keypad_driver = {
. driver . name = " stmpe-keypad " ,
. driver . owner = THIS_MODULE ,
. probe = stmpe_keypad_probe ,
2012-11-24 09:27:39 +04:00
. remove = stmpe_keypad_remove ,
2010-07-02 15:22:10 +04:00
} ;
2011-11-29 23:08:39 +04:00
module_platform_driver ( stmpe_keypad_driver ) ;
2010-07-02 15:22:10 +04:00
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " STMPExxxx keypad driver " ) ;
MODULE_AUTHOR ( " Rabin Vincent <rabin.vincent@stericsson.com> " ) ;