diff options
79 files changed, 1217 insertions, 260 deletions
diff --git a/Documentation/devicetree/bindings/input/pxa27x-keypad.txt b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt new file mode 100644 index 0000000..f8674f7 --- /dev/null +++ b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt @@ -0,0 +1,60 @@ +* Marvell PXA Keypad controller + +Required Properties +- compatible : should be "marvell,pxa27x-keypad" +- reg : Address and length of the register set for the device +- interrupts : The interrupt for the keypad controller +- marvell,debounce-interval : How long time the key will be + recognized when it is pressed. It is a u32 value, and bit[31:16] + is debounce interval for direct key and bit[15:0] is debounce + interval for matrix key. The value is in binary number of 2ms + +Optional Properties For Matrix Keyes +Please refer to matrix-keymap.txt + +Optional Properties for Direct Keyes +- marvell,direct-key-count : How many direct keyes are used. +- marvell,direct-key-mask : The mask indicates which keyes + are used. If bit[X] of the mask is set, the direct key X + is used. +- marvell,direct-key-low-active : Direct key status register + tells the level of pins that connects to the direct keyes. + When this property is set, it means that when the pin level + is low, the key is pressed(active). +- marvell,direct-key-map : It is a u16 array. Each item indicates + the linux key-code for the direct key. + +Optional Properties For Rotary +- marvell,rotary0 : It is a u32 value. Bit[31:16] is the + linux key-code for rotary up. Bit[15:0] is the linux key-code + for rotary down. It is for rotary 0. +- marvell,rotary1 : Same as marvell,rotary0. It is for rotary 1. +- marvell,rotary-rel-key : When rotary is used for relative axes + in the device, the value indicates the key-code for relative + axes measurement in the device. It is a u32 value. Bit[31:16] + is for rotary 1, and Bit[15:0] is for rotary 0. + +Examples: + keypad: keypad@d4012000 { + keypad,num-rows = <3>; + keypad,num-columns = <5>; + linux,keymap = <0x0000000e /* KEY_BACKSPACE */ + 0x0001006b /* KEY_END */ + 0x00020061 /* KEY_RIGHTCTRL */ + 0x0003000b /* KEY_0 */ + 0x00040002 /* KEY_1 */ + 0x0100008b /* KEY_MENU */ + 0x01010066 /* KEY_HOME */ + 0x010200e7 /* KEY_SEND */ + 0x01030009 /* KEY_8 */ + 0x0104000a /* KEY_9 */ + 0x02000160 /* KEY_OK */ + 0x02010003 /* KEY_2 */ + 0x02020004 /* KEY_3 */ + 0x02030005 /* KEY_4 */ + 0x02040006>; /* KEY_5 */ + marvell,rotary0 = <0x006c0067>; /* KEY_UP & KEY_DOWN */ + marvell,direct-key-count = <1>; + marvell,direct-key-map = <0x001c>; + marvell,debounce-interval = <0x001e001e>; + }; diff --git a/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt new file mode 100644 index 0000000..513d94d --- /dev/null +++ b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt @@ -0,0 +1,60 @@ +TI-NSPIRE Keypad + +Required properties: +- compatible: Compatible property value should be "ti,nspire-keypad". + +- reg: Physical base address of the peripheral and length of memory mapped + region. + +- interrupts: The interrupt number for the peripheral. + +- scan-interval: How often to scan in us. Based on a APB speed of 33MHz, the + maximum and minimum delay time is ~2000us and ~500us respectively + +- row-delay: How long to wait before scanning each row. + +- clocks: The clock this peripheral is attached to. + +- linux,keymap: The keymap to use + (see Documentation/devicetree/bindings/input/matrix-keymap.txt) + +Optional properties: +- active-low: Specify that the keypad is active low (i.e. logical low signifies + a key press). + +Example: + +input { + compatible = "ti,nspire-keypad"; + reg = <0x900E0000 0x1000>; + interrupts = <16>; + + scan-interval = <1000>; + row-delay = <200>; + + clocks = <&apb_pclk>; + + linux,keymap = < + 0x0000001c 0x0001001c 0x00040039 + 0x0005002c 0x00060015 0x0007000b + 0x0008000f 0x0100002d 0x01010011 + 0x0102002f 0x01030004 0x01040016 + 0x01050014 0x0106001f 0x01070002 + 0x010a006a 0x02000013 0x02010010 + 0x02020019 0x02030007 0x02040018 + 0x02050031 0x02060032 0x02070005 + 0x02080028 0x0209006c 0x03000026 + 0x03010025 0x03020024 0x0303000a + 0x03040017 0x03050023 0x03060022 + 0x03070008 0x03080035 0x03090069 + 0x04000021 0x04010012 0x04020020 + 0x0404002e 0x04050030 0x0406001e + 0x0407000d 0x04080037 0x04090067 + 0x05010038 0x0502000c 0x0503001b + 0x05040034 0x0505001a 0x05060006 + 0x05080027 0x0509000e 0x050a006f + 0x0600002b 0x0602004e 0x06030068 + 0x06040003 0x0605006d 0x06060009 + 0x06070001 0x0609000f 0x0708002a + 0x0709001d 0x070a0033 >; +}; diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 5b660ec..0c00209 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -210,7 +210,7 @@ struct pxa168fb_mach_info aspenite_lcd_info = { .invert_pixclock = 0, }; -static unsigned int aspenite_matrix_key_map[] = { +static const unsigned int aspenite_matrix_key_map[] = { KEY(0, 6, KEY_UP), /* SW 4 */ KEY(0, 7, KEY_DOWN), /* SW 5 */ KEY(1, 6, KEY_LEFT), /* SW 6 */ @@ -219,11 +219,15 @@ static unsigned int aspenite_matrix_key_map[] = { KEY(4, 7, KEY_ESC), /* SW 9 */ }; +static struct matrix_keymap_data aspenite_matrix_keymap_data = { + .keymap = aspenite_matrix_key_map, + .keymap_size = ARRAY_SIZE(aspenite_matrix_key_map), +}; + static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = { .matrix_key_rows = 5, .matrix_key_cols = 8, - .matrix_key_map = aspenite_matrix_key_map, - .matrix_key_map_size = ARRAY_SIZE(aspenite_matrix_key_map), + .matrix_keymap_data = &aspenite_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c index e4d95b4..6aa53fb 100644 --- a/arch/arm/mach-mmp/teton_bga.c +++ b/arch/arm/mach-mmp/teton_bga.c @@ -61,11 +61,15 @@ static unsigned int teton_bga_matrix_key_map[] = { KEY(1, 7, KEY_RIGHT), }; +static struct matrix_keymap_data teton_bga_matrix_keymap_data = { + .keymap = teton_bga_matrix_key_map, + .keymap_size = ARRAY_SIZE(teton_bga_matrix_key_map), +}; + static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = { .matrix_key_rows = 2, .matrix_key_cols = 8, - .matrix_key_map = teton_bga_matrix_key_map, - .matrix_key_map_size = ARRAY_SIZE(teton_bga_matrix_key_map), + .matrix_keymap_data = &teton_bga_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 446563a..f6726bb 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -833,21 +833,25 @@ static inline void em_x270_init_ac97(void) {} #endif #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int em_x270_module_matrix_keys[] = { +static const unsigned int em_x270_module_matrix_keys[] = { KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B), KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT), KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D), }; +static struct matrix_keymap_data em_x270_matrix_keymap_data = { + .keymap = em_x270_module_matrix_keys, + .keymap_size = ARRAY_SIZE(em_x270_module_matrix_keys), +}; + struct pxa27x_keypad_platform_data em_x270_module_keypad_info = { /* code map for the matrix keys */ .matrix_key_rows = 3, .matrix_key_cols = 3, - .matrix_key_map = em_x270_module_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(em_x270_module_matrix_keys), + .matrix_keymap_data = &em_x270_matrix_keymap_data, }; -static unsigned int em_x270_exeda_matrix_keys[] = { +static const unsigned int em_x270_exeda_matrix_keys[] = { KEY(0, 0, KEY_RIGHTSHIFT), KEY(0, 1, KEY_RIGHTCTRL), KEY(0, 2, KEY_RIGHTALT), KEY(0, 3, KEY_SPACE), KEY(0, 4, KEY_LEFTALT), KEY(0, 5, KEY_LEFTCTRL), @@ -889,12 +893,16 @@ static unsigned int em_x270_exeda_matrix_keys[] = { KEY(7, 6, 0), KEY(7, 7, 0), }; +static struct matrix_keymap_data em_x270_exeda_matrix_keymap_data = { + .keymap = em_x270_exeda_matrix_keys, + .keymap_size = ARRAY_SIZE(em_x270_exeda_matrix_keys), +}; + struct pxa27x_keypad_platform_data em_x270_exeda_keypad_info = { /* code map for the matrix keys */ .matrix_key_rows = 8, .matrix_key_cols = 8, - .matrix_key_map = em_x270_exeda_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(em_x270_exeda_matrix_keys), + .matrix_keymap_data = &em_x270_exeda_matrix_keymap_data, }; static void __init em_x270_init_keypad(void) diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index dca1070..fe2eb83 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@ -392,7 +392,7 @@ static unsigned long e6_pin_config[] __initdata = { /* KEYPAD */ #ifdef CONFIG_MACH_EZX_A780 -static unsigned int a780_key_map[] = { +static const unsigned int a780_key_map[] = { KEY(0, 0, KEY_SEND), KEY(0, 1, KEY_BACK), KEY(0, 2, KEY_END), @@ -424,11 +424,15 @@ static unsigned int a780_key_map[] = { KEY(4, 4, KEY_DOWN), }; +static struct matrix_keymap_data a780_matrix_keymap_data = { + .keymap = a780_key_map, + .keymap_size = ARRAY_SIZE(a780_key_map), +}; + static struct pxa27x_keypad_platform_data a780_keypad_platform_data = { .matrix_key_rows = 5, .matrix_key_cols = 5, - .matrix_key_map = a780_key_map, - .matrix_key_map_size = ARRAY_SIZE(a780_key_map), + .matrix_keymap_data = &a780_matrix_keymap_data, .direct_key_map = { KEY_CAMERA }, .direct_key_num = 1, @@ -438,7 +442,7 @@ static struct pxa27x_keypad_platform_data a780_keypad_platform_data = { #endif /* CONFIG_MACH_EZX_A780 */ #ifdef CONFIG_MACH_EZX_E680 -static unsigned int e680_key_map[] = { +static const unsigned int e680_key_map[] = { KEY(0, 0, KEY_UP), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_RESERVED), @@ -455,11 +459,15 @@ static unsigned int e680_key_map[] = { KEY(2, 3, KEY_KPENTER), }; +static struct matrix_keymap_data e680_matrix_keymap_data = { + .keymap = e680_key_map, + .keymap_size = ARRAY_SIZE(e680_key_map), +}; + static struct pxa27x_keypad_platform_data e680_keypad_platform_data = { .matrix_key_rows = 3, .matrix_key_cols = 4, - .matrix_key_map = e680_key_map, - .matrix_key_map_size = ARRAY_SIZE(e680_key_map), + .matrix_keymap_data = &e680_matrix_keymap_data, .direct_key_map = { KEY_CAMERA, @@ -476,7 +484,7 @@ static struct pxa27x_keypad_platform_data e680_keypad_platform_data = { #endif /* CONFIG_MACH_EZX_E680 */ #ifdef CONFIG_MACH_EZX_A1200 -static unsigned int a1200_key_map[] = { +static const unsigned int a1200_key_map[] = { KEY(0, 0, KEY_RESERVED), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_PAGEDOWN), @@ -513,18 +521,22 @@ static unsigned int a1200_key_map[] = { KEY(4, 5, KEY_RESERVED), }; +static struct matrix_keymap_data a1200_matrix_keymap_data = { + .keymap = a1200_key_map, + .keymap_size = ARRAY_SIZE(a1200_key_map), +}; + static struct pxa27x_keypad_platform_data a1200_keypad_platform_data = { .matrix_key_rows = 5, .matrix_key_cols = 6, - .matrix_key_map = a1200_key_map, - .matrix_key_map_size = ARRAY_SIZE(a1200_key_map), + .matrix_keymap_data = &a1200_matrix_keymap_data, .debounce_interval = 30, }; #endif /* CONFIG_MACH_EZX_A1200 */ #ifdef CONFIG_MACH_EZX_E6 -static unsigned int e6_key_map[] = { +static const unsigned int e6_key_map[] = { KEY(0, 0, KEY_RESERVED), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_PAGEDOWN), @@ -561,18 +573,22 @@ static unsigned int e6_key_map[] = { KEY(4, 5, KEY_PREVIOUSSONG), }; +static struct matrix_keymap_data e6_keymap_data = { + .keymap = e6_key_map, + .keymap_size = ARRAY_SIZE(e6_key_map), +}; + static struct pxa27x_keypad_platform_data e6_keypad_platform_data = { .matrix_key_rows = 5, .matrix_key_cols = 6, - .matrix_key_map = e6_key_map, - .matrix_key_map_size = ARRAY_SIZE(e6_key_map), + .matrix_keymap_data = &e6_keymap_data, .debounce_interval = 30, }; #endif /* CONFIG_MACH_EZX_E6 */ #ifdef CONFIG_MACH_EZX_A910 -static unsigned int a910_key_map[] = { +static const unsigned int a910_key_map[] = { KEY(0, 0, KEY_NUMERIC_6), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_PAGEDOWN), @@ -609,18 +625,22 @@ static unsigned int a910_key_map[] = { KEY(4, 5, KEY_RESERVED), }; +static struct matrix_keymap_data a910_matrix_keymap_data = { + .keymap = a910_key_map, + .keymap_size = ARRAY_SIZE(a910_key_map), +}; + static struct pxa27x_keypad_platform_data a910_keypad_platform_data = { .matrix_key_rows = 5, .matrix_key_cols = 6, - .matrix_key_map = a910_key_map, - .matrix_key_map_size = ARRAY_SIZE(a910_key_map), + .matrix_keymap_data = &a910_matrix_keymap_data, .debounce_interval = 30, }; #endif /* CONFIG_MACH_EZX_A910 */ #ifdef CONFIG_MACH_EZX_E2 -static unsigned int e2_key_map[] = { +static const unsigned int e2_key_map[] = { KEY(0, 0, KEY_NUMERIC_6), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_NUMERIC_9), @@ -657,11 +677,15 @@ static unsigned int e2_key_map[] = { KEY(4, 5, KEY_RESERVED), }; +static struct matrix_keymap_data e2_matrix_keymap_data = { + .keymap = e2_key_map, + .keymap_size = ARRAY_SIZE(e2_key_map), +}; + static struct pxa27x_keypad_platform_data e2_keypad_platform_data = { .matrix_key_rows = 5, .matrix_key_cols = 6, - .matrix_key_map = e2_key_map, - .matrix_key_map_size = ARRAY_SIZE(e2_key_map), + .matrix_keymap_data = &e2_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index e848c46..5d66558 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -222,7 +222,7 @@ static inline void littleton_init_spi(void) {} #endif #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int littleton_matrix_key_map[] = { +static const unsigned int littleton_matrix_key_map[] = { /* KEY(row, col, key_code) */ KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3), KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7), @@ -249,11 +249,15 @@ static unsigned int littleton_matrix_key_map[] = { KEY(3, 1, KEY_F23), /* soft2 */ }; +static struct matrix_keymap_data littleton_matrix_keymap_data = { + .keymap = littleton_matrix_key_map, + .keymap_size = ARRAY_SIZE(littleton_matrix_key_map), +}; + static struct pxa27x_keypad_platform_data littleton_keypad_info = { .matrix_key_rows = 6, .matrix_key_cols = 5, - .matrix_key_map = littleton_matrix_key_map, - .matrix_key_map_size = ARRAY_SIZE(littleton_matrix_key_map), + .matrix_keymap_data = &littleton_matrix_keymap_data, .enable_rotary0 = 1, .rotary0_up_key = KEY_UP, diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 7a12c1b..d2c6523 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -498,7 +498,7 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = { }; #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int mainstone_matrix_keys[] = { +static const unsigned int mainstone_matrix_keys[] = { KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C), KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F), KEY(0, 1, KEY_G), KEY(1, 1, KEY_H), KEY(2, 1, KEY_I), @@ -527,11 +527,15 @@ static unsigned int mainstone_matrix_keys[] = { KEY(4, 6, KEY_SELECT), }; +static struct matrix_keymap_data mainstone_matrix_keymap_data = { + .keymap = mainstone_matrix_keys, + .keymap_size = ARRAY_SIZE(mainstone_matrix_keys), +}; + struct pxa27x_keypad_platform_data mainstone_keypad_info = { .matrix_key_rows = 6, .matrix_key_cols = 7, - .matrix_key_map = mainstone_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(mainstone_matrix_keys), + .matrix_keymap_data = &mainstone_matrix_keymap_data, .enable_rotary0 = 1, .rotary0_up_key = KEY_UP, diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index f8979b94..654b0ac 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -222,7 +222,7 @@ static struct pxafb_mach_info mioa701_pxafb_info = { /* * Keyboard configuration */ -static unsigned int mioa701_matrix_keys[] = { +static const unsigned int mioa701_matrix_keys[] = { KEY(0, 0, KEY_UP), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_MEDIA), @@ -233,11 +233,16 @@ static unsigned int mioa701_matrix_keys[] = { KEY(2, 1, KEY_PHONE), /* Phone Green key */ KEY(2, 2, KEY_CAMERA) /* Camera key */ }; + +static struct matrix_keymap_data mioa701_matrix_keymap_data = { + .keymap = mioa701_matrix_keys, + .keymap_size = ARRAY_SIZE(mioa701_matrix_keys), +}; + static struct pxa27x_keypad_platform_data mioa701_keypad_info = { .matrix_key_rows = 3, .matrix_key_cols = 3, - .matrix_key_map = mioa701_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(mioa701_matrix_keys), + .matrix_keymap_data = &mioa701_matrix_keymap_data, }; /* diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index 909b713..cf210b1 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c @@ -173,7 +173,7 @@ static inline void palmld_nor_init(void) {} * GPIO keyboard ******************************************************************************/ #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int palmld_matrix_keys[] = { +static const unsigned int palmld_matrix_keys[] = { KEY(0, 1, KEY_F2), KEY(0, 2, KEY_UP), @@ -190,11 +190,15 @@ static unsigned int palmld_matrix_keys[] = { KEY(3, 2, KEY_LEFT), }; +static struct matrix_keymap_data palmld_matrix_keymap_data = { + .keymap = palmld_matrix_keys, + .keymap_size = ARRAY_SIZE(palmld_matrix_keys), +}; + static struct pxa27x_keypad_platform_data palmld_keypad_platform_data = { .matrix_key_rows = 4, .matrix_key_cols = 3, - .matrix_key_map = palmld_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(palmld_matrix_keys), + .matrix_keymap_data = &palmld_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index 5033fd0..3ed9b02 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c @@ -108,7 +108,7 @@ static unsigned long palmt5_pin_config[] __initdata = { * GPIO keyboard ******************************************************************************/ #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int palmt5_matrix_keys[] = { +static const unsigned int palmt5_matrix_keys[] = { KEY(0, 0, KEY_POWER), KEY(0, 1, KEY_F1), KEY(0, 2, KEY_ENTER), @@ -124,11 +124,15 @@ static unsigned int palmt5_matrix_keys[] = { KEY(3, 2, KEY_LEFT), }; +static struct matrix_keymap_data palmt5_matrix_keymap_data = { + .keymap = palmt5_matrix_keys, + .keymap_size = ARRAY_SIZE(palmt5_matrix_keys), +}; + static struct pxa27x_keypad_platform_data palmt5_keypad_platform_data = { .matrix_key_rows = 4, .matrix_key_cols = 3, - .matrix_key_map = palmt5_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(palmt5_matrix_keys), + .matrix_keymap_data = &palmt5_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index d82a50b..d8b937c 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -168,7 +168,7 @@ static unsigned long centro685_pin_config[] __initdata = { * GPIO keyboard ******************************************************************************/ #if IS_ENABLED(CONFIG_KEYBOARD_PXA27x) -static unsigned int treo680_matrix_keys[] = { +static const unsigned int treo680_matrix_keys[] = { KEY(0, 0, KEY_F8), /* Red/Off/Power */ KEY(0, 1, KEY_LEFT), KEY(0, 2, KEY_LEFTCTRL), /* Alternate */ @@ -227,7 +227,7 @@ static unsigned int treo680_matrix_keys[] = { KEY(7, 5, KEY_I), }; -static unsigned int centro_matrix_keys[] = { +static const unsigned int centro_matrix_keys[] = { KEY(0, 0, KEY_F9), /* Home */ KEY(0, 1, KEY_LEFT), KEY(0, 2, KEY_LEFTCTRL), /* Alternate */ @@ -286,11 +286,20 @@ static unsigned int centro_matrix_keys[] = { KEY(7, 5, KEY_I), }; +static struct matrix_keymap_data treo680_matrix_keymap_data = { + .keymap = treo680_matrix_keys, + .keymap_size = ARRAY_SIZE(treo680_matrix_keys), +}; + +static struct matrix_keymap_data centro_matrix_keymap_data = { + .keymap = centro_matrix_keys, + .keymap_size = ARRAY_SIZE(centro_matrix_keys), +}; + static struct pxa27x_keypad_platform_data treo680_keypad_pdata = { .matrix_key_rows = 8, .matrix_key_cols = 7, - .matrix_key_map = treo680_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(treo680_matrix_keys), + .matrix_keymap_data = &treo680_matrix_keymap_data, .direct_key_map = { KEY_CONNECT }, .direct_key_num = 1, @@ -301,10 +310,8 @@ static void __init palmtreo_kpc_init(void) { static struct pxa27x_keypad_platform_data *data = &treo680_keypad_pdata; - if (machine_is_centro()) { - data->matrix_key_map = centro_matrix_keys; - data->matrix_key_map_size = ARRAY_SIZE(centro_matrix_keys); - } + if (machine_is_centro()) + data->matrix_keymap_data = ¢ro_matrix_keymap_data; pxa_set_keypad_info(&treo680_keypad_pdata); } diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 627c93a..83f830d 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -176,7 +176,7 @@ static inline void palmtx_nor_init(void) {} * GPIO keyboard ******************************************************************************/ #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int palmtx_matrix_keys[] = { +static const unsigned int palmtx_matrix_keys[] = { KEY(0, 0, KEY_POWER), KEY(0, 1, KEY_F1), KEY(0, 2, KEY_ENTER), @@ -192,11 +192,15 @@ static unsigned int palmtx_matrix_keys[] = { KEY(3, 2, KEY_LEFT), }; +static struct matrix_keymap_data palmtx_matrix_keymap_data = { + .keymap = palmtx_matrix_keys, + .keymap_size = ARRAY_SIZE(palmtx_matrix_keys), +}; + static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = { .matrix_key_rows = 4, .matrix_key_cols = 3, - .matrix_key_map = palmtx_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(palmtx_matrix_keys), + .matrix_keymap_data = &palmtx_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 18b7fcd..1a35ddf 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -140,7 +140,7 @@ static unsigned long palmz72_pin_config[] __initdata = { * GPIO keyboard ******************************************************************************/ #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int palmz72_matrix_keys[] = { +static const unsigned int palmz72_matrix_keys[] = { KEY(0, 0, KEY_POWER), KEY(0, 1, KEY_F1), KEY(0, 2, KEY_ENTER), @@ -156,11 +156,15 @@ static unsigned int palmz72_matrix_keys[] = { KEY(3, 2, KEY_LEFT), }; +static struct matrix_keymap_data almz72_matrix_keymap_data = { + .keymap = palmz72_matrix_keys, + .keymap_size = ARRAY_SIZE(palmz72_matrix_keys), +}; + static struct pxa27x_keypad_platform_data palmz72_keypad_platform_data = { .matrix_key_rows = 4, .matrix_key_cols = 3, - .matrix_key_map = palmz72_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(palmz72_matrix_keys), + .matrix_keymap_data = &almz72_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index f55979c..4680efe 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c @@ -106,7 +106,7 @@ static struct platform_device smc91x_device = { }; #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int tavorevb_matrix_key_map[] = { +static const unsigned int tavorevb_matrix_key_map[] = { /* KEY(row, col, key_code) */ KEY(0, 4, KEY_A), KEY(0, 5, KEY_B), KEY(0, 6, KEY_C), KEY(1, 4, KEY_E), KEY(1, 5, KEY_F), KEY(1, 6, KEY_G), @@ -147,11 +147,15 @@ static unsigned int tavorevb_matrix_key_map[] = { KEY(3, 3, KEY_F23), /* soft2 */ }; +static struct matrix_keymap_data tavorevb_matrix_keymap_data = { + .keymap = tavorevb_matrix_key_map, + .keymap_size = ARRAY_SIZE(tavorevb_matrix_key_map), +}; + static struct pxa27x_keypad_platform_data tavorevb_keypad_info = { .matrix_key_rows = 7, .matrix_key_cols = 7, - .matrix_key_map = tavorevb_matrix_key_map, - .matrix_key_map_size = ARRAY_SIZE(tavorevb_matrix_key_map), + .matrix_keymap_data = &tavorevb_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index 989903a..2513d8f 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -345,7 +345,7 @@ static inline void z2_leds_init(void) {} * GPIO keyboard ******************************************************************************/ #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int z2_matrix_keys[] = { +static const unsigned int z2_matrix_keys[] = { KEY(0, 0, KEY_OPTION), KEY(1, 0, KEY_UP), KEY(2, 0, KEY_DOWN), @@ -405,11 +405,15 @@ static unsigned int z2_matrix_keys[] = { KEY(5, 7, KEY_DOT), }; +static struct matrix_keymap_data z2_matrix_keymap_data = { + .keymap = z2_matrix_keys, + .keymap_size = ARRAY_SIZE(z2_matrix_keys), +}; + static struct pxa27x_keypad_platform_data z2_keypad_platform_data = { .matrix_key_rows = 7, .matrix_key_cols = 8, - .matrix_key_map = z2_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(z2_matrix_keys), + .matrix_keymap_data = &z2_matrix_keymap_data, .debounce_interval = 30, }; diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 1f00d65..36cf7cf 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -263,7 +263,7 @@ static inline void zylonite_init_mmc(void) {} #endif #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int zylonite_matrix_key_map[] = { +static const unsigned int zylonite_matrix_key_map[] = { /* KEY(row, col, key_code) */ KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D), KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H), @@ -306,11 +306,15 @@ static unsigned int zylonite_matrix_key_map[] = { KEY(0, 3, KEY_AUX), /* contact */ }; +static struct matrix_keymap_data zylonite_matrix_keymap_data = { + .keymap = zylonite_matrix_key_map, + .keymap_size = ARRAY_SIZE(zylonite_matrix_key_map), +}; + static struct pxa27x_keypad_platform_data zylonite_keypad_info = { .matrix_key_rows = 8, .matrix_key_cols = 8, - .matrix_key_map = zylonite_matrix_key_map, - .matrix_key_map_size = ARRAY_SIZE(zylonite_matrix_key_map), + .matrix_keymap_data = &zylonite_matrix_keymap_data, .enable_rotary0 = 1, .rotary0_up_key = KEY_UP, diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f0f8928..d2b34fb 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -52,6 +52,82 @@ struct evdev_client { struct input_event buffer[]; }; +/* flush queued events of type @type, caller must hold client->buffer_lock */ +static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) +{ + unsigned int i, head, num; + unsigned int mask = client->bufsize - 1; + bool is_report; + struct input_event *ev; + + BUG_ON(type == EV_SYN); + + head = client->tail; + client->packet_head = client->tail; + + /* init to 1 so a leading SYN_REPORT will not be dropped */ + num = 1; + + for (i = client->tail; i != client->head; i = (i + 1) & mask) { + ev = &client->buffer[i]; + is_report = ev->type == EV_SYN && ev->code == SYN_REPORT; + + if (ev->type == type) { + /* drop matched entry */ + continue; + } else if (is_report && !num) { + /* drop empty SYN_REPORT groups */ + continue; + } else if (head != i) { + /* move entry to fill the gap */ + client->buffer[head].time = ev->time; + client->buffer[head].type = ev->type; + client->buffer[head].code = ev->code; + client->buffer[head].value = ev->value; + } + + num++; + head = (head + 1) & mask; + + if (is_report) { + num = 0; + client->packet_head = head; + } + } + + client->head = head; +} + +/* queue SYN_DROPPED event */ +static void evdev_queue_syn_dropped(struct evdev_client *client) +{ + unsigned long flags; + struct input_event ev; + ktime_t time; + + time = ktime_get(); + if (client->clkid != CLOCK_MONOTONIC) + time = ktime_sub(time, ktime_get_monotonic_offset()); + + ev.time = ktime_to_timeval(time); + ev.type = EV_SYN; + ev.code = SYN_DROPPED; + ev.value = 0; + + spin_lock_irqsave(&client->buffer_lock, flags); + + client->buffer[client->head++] = ev; + client->head &= client->bufsize - 1; + + if (unlikely(client->head == client->tail)) { + /* drop queue but keep our SYN_DROPPED event */ + client->tail = (client->head - 1) & (client->bufsize - 1); + client->packet_head = client->tail; + } + + spin_unlock_irqrestore(&client->buffer_lock, flags); +} + static void __pass_event(struct evdev_client *client, const struct input_event *event) { @@ -650,6 +726,51 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) return input_set_keycode(dev, &ke); } +/* + * If we transfer state to the user, we should flush all pending events + * of the same type from the client's queue. Otherwise, they might end up + * with duplicate events, which can screw up client's state tracking. + * If bits_to_user fails after flushing the queue, we queue a SYN_DROPPED + * event so user-space will notice missing events. + * + * LOCKING: + * We need to take event_lock before buffer_lock to avoid dead-locks. But we + * need the even_lock only to guarantee consistent state. We can safely release + * it while flushing the queue. This allows input-core to handle filters while + * we flush the queue. + */ +static int evdev_handle_get_val(struct evdev_client *client, + struct input_dev *dev, unsigned int type, + unsigned long *bits, unsigned int max, + unsigned int size, void __user *p, int compat) +{ + int ret; + unsigned long *mem; + + mem = kmalloc(sizeof(unsigned long) * max, GFP_KERNEL); + if (!mem) + return -ENOMEM; + + spin_lock_irq(&dev->event_lock); + spin_lock(&client->buffer_lock); + + memcpy(mem, bits, sizeof(unsigned long) * max); + + spin_unlock(&dev->event_lock); + + __evdev_flush_queue(client, type); + + spin_unlock_irq(&client->buffer_lock); + + ret = bits_to_user(mem, max, size, p, compat); + if (ret < 0) + evdev_queue_syn_dropped(client); + + kfree(mem); + + return ret; +} + static int evdev_handle_mt_request(struct input_dev *dev, unsigned int size, int __user *ip) @@ -771,16 +892,20 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return evdev_handle_mt_request(dev, size, ip); case EVIOCGKEY(0): - return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_KEY, dev->key, + KEY_MAX, size, p, compat_mode); case EVIOCGLED(0): - return bits_to_user(dev->led, LED_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_LED, dev->led, + LED_MAX, size, p, compat_mode); case EVIOCGSND(0): - return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_SND, dev->snd, + SND_MAX, size, p, compat_mode); case EVIOCGSW(0): - return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_SW, dev->sw, + SW_MAX, size, p, compat_mode); case EVIOCGNAME(0): return str_to_user(dev->name, size, p); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 62a2c0e..77412d8 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -418,6 +418,16 @@ config KEYBOARD_NOMADIK To compile this driver as a module, choose M here: the module will be called nmk-ske-keypad. +config KEYBOARD_NSPIRE + tristate "TI-NSPIRE built-in keyboard" + depends on ARCH_NSPIRE && OF + select INPUT_MATRIXKMAP + help + Say Y here if you want to use the built-in keypad on TI-NSPIRE. + + To compile this driver as a module, choose M here: the + module will be called nspire-keypad. + config KEYBOARD_TEGRA tristate "NVIDIA Tegra internal matrix keyboard controller support" depends on ARCH_TEGRA && OF @@ -441,6 +451,7 @@ config KEYBOARD_OPENCORES config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" depends on PXA27x || PXA3xx || ARCH_MMP + select INPUT_MATRIXKMAP help Enable support for PXA27x/PXA3xx keypad controller. diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 0c43e8c..a699b61 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o +obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index ba0b36f..096d606 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -246,7 +246,6 @@ static int __exit amikbd_remove(struct platform_device *pdev) { struct input_dev *dev = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); free_irq(IRQ_AMIGA_CIAA_SP, dev); input_unregister_device(dev); return 0; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 20b9fa9..fc88fb4 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -326,7 +326,6 @@ out0: kfree(bf54x_kpad->keycode); out: kfree(bf54x_kpad); - platform_set_drvdata(pdev, NULL); return error; } @@ -346,7 +345,6 @@ static int bfin_kpad_remove(struct platform_device *pdev) kfree(bf54x_kpad->keycode); kfree(bf54x_kpad); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 8297537..d15977a 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -314,8 +314,6 @@ static int davinci_ks_remove(struct platform_device *pdev) iounmap(davinci_ks->base); release_mem_region(davinci_ks->pbase, davinci_ks->base_size); - platform_set_drvdata(pdev, NULL); - kfree(davinci_ks); return 0; diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 9857e8f..47206bd 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -329,8 +329,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) return 0; failed_free_irq: - free_irq(keypad->irq, pdev); - platform_set_drvdata(pdev, NULL); + free_irq(keypad->irq, keypad); failed_free_dev: input_free_device(input_dev); failed_put_clk: @@ -351,9 +350,7 @@ static int ep93xx_keypad_remove(struct platform_device *pdev) struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; - free_irq(keypad->irq, pdev); - - platform_set_drvdata(pdev, NULL); + free_irq(keypad->irq, keypad); if (keypad->enabled) clk_disable(keypad->clk); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index b29ca65..440ce32 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -767,7 +767,6 @@ static int gpio_keys_probe(struct platform_device *pdev) while (--i >= 0) gpio_remove_key(&ddata->data[i]); - platform_set_drvdata(pdev, NULL); fail1: input_free_device(input); kfree(ddata); diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 2114716..cd5ed9e 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -324,7 +324,6 @@ err_free_gpio: err_free_bdev: kfree(bdev); - platform_set_drvdata(pdev, NULL); err_free_pdata: /* If we have no platform_data, we allocated pdata dynamically. */ @@ -355,7 +354,6 @@ static int gpio_keys_polled_remove(struct platform_device *pdev) kfree(pdata); kfree(bdev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 74e75a6..a2a034c 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -233,7 +233,6 @@ static int jornada680kbd_probe(struct platform_device *pdev) failed: printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", error); - platform_set_drvdata(pdev, NULL); input_free_polled_device(poll_dev); kfree(jornadakbd); return error; @@ -244,7 +243,6 @@ static int jornada680kbd_remove(struct platform_device *pdev) { struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); input_unregister_polled_device(jornadakbd->poll_dev); input_free_polled_device(jornadakbd->poll_dev); kfree(jornadakbd); diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 5ceef63..b0ad457 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c @@ -146,7 +146,6 @@ static int jornada720_kbd_probe(struct platform_device *pdev) fail2: /* IRQ, DEVICE, MEMORY */ free_irq(IRQ_GPIO0, pdev); fail1: /* DEVICE, MEMORY */ - platform_set_drvdata(pdev, NULL); input_free_device(input_dev); kfree(jornadakbd); return err; @@ -157,7 +156,6 @@ static int jornada720_kbd_remove(struct platform_device *pdev) struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); free_irq(IRQ_GPIO0, pdev); - platform_set_drvdata(pdev, NULL); input_unregister_device(jornadakbd->input); kfree(jornadakbd); diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 71d7719..90ff73a 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -549,8 +549,6 @@ static int matrix_keypad_remove(struct platform_device *pdev) input_unregister_device(keypad->input_dev); kfree(keypad); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c new file mode 100644 index 0000000..1b0d04c --- /dev/null +++ b/drivers/input/keyboard/nspire-keypad.c @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> + * + * 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/input/matrix_keypad.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/of.h> + +#define KEYPAD_SCAN_MODE 0x00 +#define KEYPAD_CNTL 0x04 +#define KEYPAD_INT 0x08 +#define KEYPAD_INTMSK 0x0C + +#define KEYPAD_DATA 0x10 +#define KEYPAD_GPIO 0x30 + +#define KEYPAD_UNKNOWN_INT 0x40 +#define KEYPAD_UNKNOWN_INT_STS 0x44 + +#define KEYPAD_BITMASK_COLS 11 +#define KEYPAD_BITMASK_ROWS 8 + +struct nspire_keypad { + void __iomem *reg_base; + u32 int_mask; + + struct input_dev *input; + struct clk *clk; + + struct matrix_keymap_data *keymap; + int row_shift; + + /* Maximum delay estimated assuming 33MHz APB */ + u32 scan_interval; /* In microseconds (~2000us max) */ + u32 row_delay; /* In microseconds (~500us max) */ + + u16 state[KEYPAD_BITMASK_ROWS]; + + bool active_low; +}; + +static irqreturn_t nspire_keypad_irq(int irq, void *dev_id) +{ + struct nspire_keypad *keypad = dev_id; + struct input_dev *input = keypad->input; + unsigned short *keymap = input->keycode; + unsigned int code; + int row, col; + u32 int_sts; + u16 state[8]; + u16 bits, changed; + + int_sts = readl(keypad->reg_base + KEYPAD_INT) & keypad->int_mask; + if (!int_sts) + return IRQ_NONE; + + memcpy_fromio(state, keypad->reg_base + KEYPAD_DATA, sizeof(state)); + + for (row = 0; row < KEYPAD_BITMASK_ROWS; row++) { + bits = state[row]; + if (keypad->active_low) + bits = ~bits; + + changed = bits ^ keypad->state[row]; + if (!changed) + continue; + + keypad->state[row] = bits; + + for (col = 0; col < KEYPAD_BITMASK_COLS; col++) { + if (!(changed & (1U << col))) + continue; + + code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); + input_event(input, EV_MSC, MSC_SCAN, code); + input_report_key(input, keymap[code], + bits & (1U << col)); + } + } + + input_sync(input); + + writel(0x3, keypad->reg_base + KEYPAD_INT); + + return IRQ_HANDLED; +} + +static int nspire_keypad_chip_init(struct nspire_keypad *keypad) +{ + unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles; + + cycles_per_us = (clk_get_rate(keypad->clk) / 1000000); + if (cycles_per_us == 0) + cycles_per_us = 1; + + delay_cycles = cycles_per_us * keypad->scan_interval; + WARN_ON(delay_cycles >= (1 << 16)); /* Overflow */ + delay_cycles &= 0xffff; + + row_delay_cycles = cycles_per_us * keypad->row_delay; + WARN_ON(row_delay_cycles >= (1 << 14)); /* Overflow */ + row_delay_cycles &= 0x3fff; + + val |= 3 << 0; /* Set scan mode to 3 (continuous scan) */ + val |= row_delay_cycles << 2; /* Delay between scanning each row */ + val |= delay_cycles << 16; /* Delay between scans */ + writel(val, keypad->reg_base + KEYPAD_SCAN_MODE); + + val = (KEYPAD_BITMASK_ROWS & 0xff) | (KEYPAD_BITMASK_COLS & 0xff)<<8; + writel(val, keypad->reg_base + KEYPAD_CNTL); + + /* Enable interrupts */ + keypad->int_mask = 1 << 1; + writel(keypad->int_mask, keypad->reg_base + 0xc); + + /* Disable GPIO interrupts to prevent hanging on touchpad */ + /* Possibly used to detect touchpad events */ + writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); + /* Acknowledge existing interrupts */ + writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); + + return 0; +} + +static int nspire_keypad_open(struct input_dev *input) +{ + struct nspire_keypad *keypad = input_get_drvdata(input); + int error; + + error = clk_prepare_enable(keypad->clk); + if (error) + return error; + + error = nspire_keypad_chip_init(keypad); + if (error) + return error; + + return 0; +} + +static void nspire_keypad_close(struct input_dev *input) +{ + struct nspire_keypad *keypad = input_get_drvdata(input); + + clk_disable_unprepare(keypad->clk); +} + +static int nspire_keypad_probe(struct platform_device *pdev) +{ + const struct device_node *of_node = pdev->dev.of_node; + struct nspire_keypad *keypad; + struct input_dev *input; + struct resource *res; + int irq; + int error; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get keypad irq\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "missing platform resources\n"); + return -EINVAL; + } + + keypad = devm_kzalloc(&pdev->dev, sizeof(struct nspire_keypad), + GFP_KERNEL); + if (!keypad) { + dev_err(&pdev->dev, "failed to allocate keypad memory\n"); + return -ENOMEM; + } + + keypad->row_shift = get_count_order(KEYPAD_BITMASK_COLS); + + error = of_property_read_u32(of_node, "scan-interval", + &keypad->scan_interval); + if (error) { + dev_err(&pdev->dev, "failed to get scan-interval\n"); + return error; + } + + error = of_property_read_u32(of_node, "row-delay", + &keypad->row_delay); + if (error) { + dev_err(&pdev->dev, "failed to get row-delay\n"); + return error; + } + + keypad->active_low = of_property_read_bool(of_node, "active-low"); + + keypad->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(keypad->clk)) { + dev_err(&pdev->dev, "unable to get clock\n"); + return PTR_ERR(keypad->clk); + } + + keypad->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(keypad->reg_base)) { + dev_err(&pdev->dev, "failed to remap I/O memory\n"); + return PTR_ERR(keypad->reg_base); + } + + keypad->input = input = devm_input_allocate_device(&pdev->dev); + if (!input) { + dev_err(&pdev->dev, "failed to allocate input device\n"); + return -ENOMEM; + } + + input_set_drvdata(input, keypad); + + input->id.bustype = BUS_HOST; + input->name = "nspire-keypad"; + input->open = nspire_keypad_open; + input->close = nspire_keypad_close; + + __set_bit(EV_KEY, input->evbit); + __set_bit(EV_REP, input->evbit); + input_set_capability(input, EV_MSC, MSC_SCAN); + + error = matrix_keypad_build_keymap(NULL, NULL, + KEYPAD_BITMASK_ROWS, + KEYPAD_BITMASK_COLS, + NULL, input); + if (error) { + dev_err(&pdev->dev, "building keymap failed\n"); + return error; + } + + error = devm_request_irq(&pdev->dev, irq, nspire_keypad_irq, 0, + "nspire_keypad", keypad); + if (error) { + dev_err(&pdev->dev, "allocate irq %d failed\n", irq); + return error; + } + + error = input_register_device(input); + if (error) { + dev_err(&pdev->dev, + "unable to register input device: %d\n", error); + return error; + } + + platform_set_drvdata(pdev, keypad); + + dev_dbg(&pdev->dev, + "TI-NSPIRE keypad at %pR (scan_interval=%uus, row_delay=%uus%s)\n", + res, keypad->row_delay, keypad->scan_interval, + keypad->active_low ? ", active_low" : ""); + + return 0; +} + +static const struct of_device_id nspire_keypad_dt_match[] = { + { .compatible = "ti,nspire-keypad" }, + { }, +}; +MODULE_DEVICE_TABLE(of, nspire_keypad_dt_match); + +static struct platform_driver nspire_keypad_driver = { + .driver = { + .name = "nspire-keypad", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(nspire_keypad_dt_match), + }, + .probe = nspire_keypad_probe, +}; + +module_platform_driver(nspire_keypad_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TI-NSPIRE Keypad Driver"); diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 1b28909..f4aa53a 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -419,8 +419,6 @@ static int omap4_keypad_remove(struct platform_device *pdev) kfree(keypad_data->keymap); kfree(keypad_data); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index 7ac5f17..7b9b441 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c @@ -151,8 +151,6 @@ static int opencores_kbd_remove(struct platform_device *pdev) input_unregister_device(opencores_kbd->input); kfree(opencores_kbd); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 74339e1..2c9f19a 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -707,7 +707,6 @@ err_gpio_config: err_get_irq: input_free_device(kp->input); err_alloc_device: - platform_set_drvdata(pdev, NULL); kfree(kp); return rc; } @@ -722,7 +721,6 @@ static int pmic8xxx_kp_remove(struct platform_device *pdev) input_unregister_device(kp->input); kfree(kp); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 5330d8f..134c3b4 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -100,7 +100,7 @@ #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) struct pxa27x_keypad { - struct pxa27x_keypad_platform_data *pdata; + const struct pxa27x_keypad_platform_data *pdata; struct clk *clk; struct input_dev *input_dev; @@ -118,25 +118,254 @@ struct pxa27x_keypad { unsigned int direct_key_mask; }; -static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) +#ifdef CONFIG_OF +static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad, + struct pxa27x_keypad_platform_data *pdata) { - struct pxa27x_keypad_platform_data *pdata = keypad->pdata; struct input_dev *input_dev = keypad->input_dev; - unsigned short keycode; + struct device *dev = input_dev->dev.parent; + u32 rows, cols; + int error; + + error = matrix_keypad_parse_of_params(dev, &rows, &cols); + if (error) + return error; + + if (rows > MAX_MATRIX_KEY_ROWS || cols > MAX_MATRIX_KEY_COLS) { + dev_err(dev, "rows or cols exceeds maximum value\n"); + return -EINVAL; + } + + pdata->matrix_key_rows = rows; + pdata->matrix_key_cols = cols; + + error = matrix_keypad_build_keymap(NULL, NULL, + pdata->matrix_key_rows, + pdata->matrix_key_cols, + keypad->keycodes, input_dev); + if (error) + return error; + + return 0; +} + +static int pxa27x_keypad_direct_key_parse_dt(struct pxa27x_keypad *keypad, + struct pxa27x_keypad_platform_data *pdata) +{ + struct input_dev *input_dev = keypad->input_dev; + struct device *dev = input_dev->dev.parent; + struct device_node *np = dev->of_node; + const __be16 *prop; + unsigned short code; + unsigned int proplen, size; int i; + int error; - for (i = 0; i < pdata->matrix_key_map_size; i++) { - unsigned int key = pdata->matrix_key_map[i]; - unsigned int row = KEY_ROW(key); - unsigned int col = KEY_COL(key); - unsigned int scancode = MATRIX_SCAN_CODE(row, col, - MATRIX_ROW_SHIFT); + error = of_property_read_u32(np, "marvell,direct-key-count", + &pdata->direct_key_num); + if (error) { + /* + * If do not have marvel,direct-key-count defined, + * it means direct key is not supported. + */ + return error == -EINVAL ? 0 : error; + } - keycode = KEY_VAL(key); - keypad->keycodes[scancode] = keycode; - __set_bit(keycode, input_dev->keybit); + error = of_property_read_u32(np, "marvell,direct-key-mask", + &pdata->direct_key_mask); + if (error) { + if (error != -EINVAL) + return error; + + /* + * If marvell,direct-key-mask is not defined, driver will use + * default value. Default value is set when configure the keypad. + */ + pdata->direct_key_mask = 0; + } + + pdata->direct_key_low_active = of_property_read_bool(np, + "marvell,direct-key-low-active"); + + prop = of_get_property(np, "marvell,direct-key-map", &proplen); + if (!prop) + return -EINVAL; + + if (proplen % sizeof(u16)) + return -EINVAL; + + size = proplen / sizeof(u16); + + /* Only MAX_DIRECT_KEY_NUM is accepted.*/ + if (size > MAX_DIRECT_KEY_NUM) + return -EINVAL; + + for (i = 0; i < size; i++) { + code = be16_to_cpup(prop + i); + keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = code; + __set_bit(code, input_dev->keybit); + } + + return 0; +} + +static int pxa27x_keypad_rotary_parse_dt(struct pxa27x_keypad *keypad, + struct pxa27x_keypad_platform_data *pdata) +{ + const __be32 *prop; + int i, relkey_ret; + unsigned int code, proplen; + const char *rotaryname[2] = { + "marvell,rotary0", "marvell,rotary1"}; + const char relkeyname[] = {"marvell,rotary-rel-key"}; + struct input_dev *input_dev = keypad->input_dev; + struct device *dev = input_dev->dev.parent; + struct device_node *np = dev->of_node; + + relkey_ret = of_property_read_u32(np, relkeyname, &code); + /* if can read correct rotary key-code, we do not need this. */ + if (relkey_ret == 0) { + unsigned short relcode; + + /* rotary0 taks lower half, rotary1 taks upper half. */ + relcode = code & 0xffff; + pdata->rotary0_rel_code = (code & 0xffff); + __set_bit(relcode, input_dev->relbit); + + relcode = code >> 16; + pdata->rotary1_rel_code = relcode; + __set_bit(relcode, input_dev->relbit); + } + + for (i = 0; i < 2; i++) { + prop = of_get_property(np, rotaryname[i], &proplen); + /* + * If the prop is not set, it means keypad does not need + * initialize the rotaryX. + */ + if (!prop) + continue; + + code = be32_to_cpup(prop); + /* + * Not all up/down key code are valid. + * Now we depends on direct-rel-code. + */ + if ((!(code & 0xffff) || !(code >> 16)) && relkey_ret) { + return relkey_ret; + } else { + unsigned int n = MAX_MATRIX_KEY_NUM + (i << 1); + unsigned short keycode; + + keycode = code & 0xffff; + keypad->keycodes[n] = keycode; + __set_bit(keycode, input_dev->keybit); + + keycode = code >> 16; + keypad->keycodes[n + 1] = keycode; + __set_bit(keycode, input_dev->keybit); + + if (i == 0) + pdata->rotary0_rel_code = -1; + else + pdata->rotary1_rel_code = -1; + } + if (i == 0) + pdata->enable_rotary0 = 1; + else + pdata->enable_rotary1 = 1; + } + + keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; + keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; + + return 0; +} + +static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) +{ + struct input_dev *input_dev = keypad->input_dev; + struct device *dev = input_dev->dev.parent; + struct device_node *np = dev->of_node; + struct pxa27x_keypad_platform_data *pdata; + int error; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "failed to allocate memory for pdata\n"); + return -ENOMEM; + } + + error = pxa27x_keypad_matrix_key_parse_dt(keypad, pdata); + if (error) { + dev_err(dev, "failed to parse matrix key\n"); + return error; + } + + error = pxa27x_keypad_direct_key_parse_dt(keypad, pdata); + if (error) { + dev_err(dev, "failed to parse direct key\n"); + return error; + } + + error = pxa27x_keypad_rotary_parse_dt(keypad, pdata); + if (error) { + dev_err(dev, "failed to parse rotary key\n"); + return error; + } + + error = of_property_read_u32(np, "marvell,debounce-interval", + &pdata->debounce_interval); + if (error) { + dev_err(dev, "failed to parse debpunce-interval\n"); + return error; } + /* + * The keycodes may not only includes matrix key but also the direct + * key or rotary key. + */ + input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); + + keypad->pdata = pdata; + return 0; +} + +#else + +static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) +{ + dev_info(keypad->input_dev->dev.parent, "missing platform data\n"); + + return -EINVAL; +} + +#endif + +static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) +{ + const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + struct input_dev *input_dev = keypad->input_dev; + const struct matrix_keymap_data *keymap_data = + pdata ? pdata->matrix_keymap_data : NULL; + unsigned short keycode; + int i; + int error; + + error = matrix_keypad_build_keymap(keymap_data, NULL, + pdata->matrix_key_rows, + pdata->matrix_key_cols, + keypad->keycodes, input_dev); + if (error) + return error; + + /* + * The keycodes may not only include matrix keys but also the direct + * or rotary keys. + */ + input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); + + /* For direct keys. */ for (i = 0; i < pdata->direct_key_num; i++) { keycode = pdata->direct_key_map[i]; keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; @@ -178,11 +407,13 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) } __clear_bit(KEY_RESERVED, input_dev->keybit); + + return 0; } static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) { - struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; struct input_dev *input_dev = keypad->input_dev; int row, col, num_keys_pressed = 0; uint32_t new_state[MAX_MATRIX_KEY_COLS]; @@ -284,7 +515,7 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) { - struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; uint32_t kprec; /* read and reset to default count value */ @@ -300,7 +531,7 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) { - struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; struct input_dev *input_dev = keypad->input_dev; unsigned int new_state; uint32_t kpdk, bits_changed; @@ -340,7 +571,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) static void clear_wakeup_event(struct pxa27x_keypad *keypad) { - struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; if (pdata->clear_wakeup_event) (pdata->clear_wakeup_event)(); @@ -364,7 +595,7 @@ static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) { - struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; unsigned int mask = 0, direct_key_num = 0; unsigned long kpc = 0; @@ -431,7 +662,7 @@ static void pxa27x_keypad_close(struct input_dev *dev) clk_disable_unprepare(keypad->clk); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int pxa27x_keypad_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -475,25 +706,25 @@ static int pxa27x_keypad_resume(struct device *dev) return 0; } - -static const struct dev_pm_ops pxa27x_keypad_pm_ops = { - .suspend = pxa27x_keypad_suspend, - .resume = pxa27x_keypad_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops, + pxa27x_keypad_suspend, pxa27x_keypad_resume); + + static int pxa27x_keypad_probe(struct platform_device *pdev) { - struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; + const struct pxa27x_keypad_platform_data *pdata = + dev_get_platdata(&pdev->dev); + struct device_node *np = pdev->dev.of_node; struct pxa27x_keypad *keypad; struct input_dev *input_dev; struct resource *res; int irq, error; - if (pdata == NULL) { - dev_err(&pdev->dev, "no platform data defined\n"); + /* Driver need build keycode from device tree or pdata */ + if (!np && !pdata) return -EINVAL; - } irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -555,7 +786,14 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); input_set_capability(input_dev, EV_MSC, MSC_SCAN); - pxa27x_keypad_build_keycode(keypad); + if (pdata) + error = pxa27x_keypad_build_keycode(keypad); + else + error = pxa27x_keypad_build_keycode_from_dt(keypad); + if (error) { + dev_err(&pdev->dev, "failed to build keycode\n"); + goto failed_put_clk; + } if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { @@ -582,7 +820,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) return 0; failed_free_irq: - free_irq(irq, pdev); + free_irq(irq, keypad); failed_put_clk: clk_put(keypad->clk); failed_free_io: @@ -600,7 +838,7 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; - free_irq(keypad->irq, pdev); + free_irq(keypad->irq, keypad); clk_put(keypad->clk); input_unregister_device(keypad->input_dev); @@ -609,7 +847,6 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); kfree(keypad); return 0; @@ -618,15 +855,22 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) /* work with hotplug and coldplug */ MODULE_ALIAS("platform:pxa27x-keypad"); +#ifdef CONFIG_OF +static const struct of_device_id pxa27x_keypad_dt_match[] = { + { .compatible = "marvell,pxa27x-keypad" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match); +#endif + static struct platform_driver pxa27x_keypad_driver = { .probe = pxa27x_keypad_probe, .remove = pxa27x_keypad_remove, .driver = { .name = "pxa27x-keypad", + .of_match_table = of_match_ptr(pxa27x_keypad_dt_match), .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &pxa27x_keypad_pm_ops, -#endif }, }; module_platform_driver(pxa27x_keypad_driver); diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index bcad95b..248cdcf 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -181,7 +181,6 @@ static int pxa930_rotary_remove(struct platform_device *pdev) free_irq(platform_get_irq(pdev, 0), r); input_unregister_device(r->input_dev); iounmap(r->mmio_base); - platform_set_drvdata(pdev, NULL); kfree(r); return 0; diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 22e357b..7b938b4 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -487,7 +487,6 @@ static int samsung_keypad_probe(struct platform_device *pdev) err_disable_runtime_pm: pm_runtime_disable(&pdev->dev); device_init_wakeup(&pdev->dev, 0); - platform_set_drvdata(pdev, NULL); err_unprepare_clk: clk_unprepare(keypad->clk); return error; @@ -499,7 +498,6 @@ static int samsung_keypad_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); device_init_wakeup(&pdev->dev, 0); - platform_set_drvdata(pdev, NULL); input_unregister_device(keypad->input_dev); diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index fdb9eb2..fe0e498 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -266,7 +266,6 @@ static int sh_keysc_probe(struct platform_device *pdev) err2: iounmap(priv->iomem_base); err1: - platform_set_drvdata(pdev, NULL); kfree(priv); err0: return error; @@ -285,7 +284,6 @@ static int sh_keysc_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - platform_set_drvdata(pdev, NULL); kfree(priv); return 0; diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index cb1e8f6..7111124 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -290,7 +290,6 @@ static int spear_kbd_remove(struct platform_device *pdev) clk_unprepare(kbd->clk); device_init_wakeup(&pdev->dev, 0); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index ee16350..5f7b427 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -296,7 +296,6 @@ error_clk: error_map: release_mem_region(kp->res->start, resource_size(kp->res)); error_res: - platform_set_drvdata(pdev, NULL); kfree(kp); return error; } @@ -311,7 +310,6 @@ static int keypad_remove(struct platform_device *pdev) clk_put(kp->clk); iounmap(kp->regs); release_mem_region(kp->res->start, resource_size(kp->res)); - platform_set_drvdata(pdev, NULL); kfree(kp); return 0; diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 04f84fd..d2d178c 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -422,7 +422,7 @@ static int twl4030_kp_probe(struct platform_device *pdev) err3: /* mask all events - we don't care about the result */ (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); - free_irq(kp->irq, NULL); + free_irq(kp->irq, kp); err2: input_unregister_device(input); input = NULL; @@ -438,7 +438,6 @@ static int twl4030_kp_remove(struct platform_device *pdev) free_irq(kp->irq, kp); input_unregister_device(kp->input); - platform_set_drvdata(pdev, NULL); kfree(kp); return 0; diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index ee163be..7b03916 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -221,7 +221,7 @@ static int w90p910_keypad_probe(struct platform_device *pdev) return 0; failed_free_irq: - free_irq(irq, pdev); + free_irq(irq, keypad); failed_put_clk: clk_put(keypad->clk); failed_free_io: @@ -239,7 +239,7 @@ static int w90p910_keypad_remove(struct platform_device *pdev) struct w90p910_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; - free_irq(keypad->irq, pdev); + free_irq(keypad->irq, keypad); clk_put(keypad->clk); @@ -249,7 +249,6 @@ static int w90p910_keypad_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); kfree(keypad); return 0; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index bb698e1..0b541cd 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -637,4 +637,14 @@ config INPUT_XEN_KBDDEV_FRONTEND To compile this driver as a module, choose M here: the module will be called xen-kbdfront. +config INPUT_SIRFSOC_ONKEY + bool "CSR SiRFSoC power on/off/suspend key support" + depends on ARCH_SIRF && OF + default y + help + Say Y here if you want to support for the SiRFSoC power on/off/suspend key + in Linux, after you press the onkey, system will suspend. + + If unsure, say N. + endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index d7fc17f..829de43 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o +obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index 2f090b4..f2fbdd8 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c @@ -127,8 +127,6 @@ static int ab8500_ponkey_remove(struct platform_device *pdev) input_unregister_device(ponkey->idev); kfree(ponkey); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index a6666e1..cd139cb 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -208,7 +208,6 @@ static int bfin_rotary_remove(struct platform_device *pdev) peripheral_free_list(per_cnt); kfree(rotary); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c index da05cca..714c683 100644 --- a/drivers/input/misc/gpio_tilt_polled.c +++ b/drivers/input/misc/gpio_tilt_polled.c @@ -184,8 +184,6 @@ static int gpio_tilt_polled_remove(struct platform_device *pdev) struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev); const struct gpio_tilt_platform_data *pdata = tdev->pdata; - platform_set_drvdata(pdev, NULL); - input_unregister_polled_device(tdev->poll_dev); input_free_polled_device(tdev->poll_dev); diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 6ab3dec..f34beb2 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -125,7 +125,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev) return 0; err_free_irq: - free_irq(IRQ_IXP4XX_TIMER2, dev); + free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id); err_free_device: input_free_device(input_dev); @@ -138,13 +138,12 @@ static int ixp4xx_spkr_remove(struct platform_device *dev) unsigned int pin = (unsigned int) input_get_drvdata(input_dev); input_unregister_device(input_dev); - platform_set_drvdata(dev, NULL); /* turn the speaker off */ disable_irq(IRQ_IXP4XX_TIMER2); ixp4xx_spkr_control(pin, 0); - free_irq(IRQ_IXP4XX_TIMER2, dev); + free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id); return 0; } diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c index b40ee4b..def21dc 100644 --- a/drivers/input/misc/m68kspkr.c +++ b/drivers/input/misc/m68kspkr.c @@ -85,7 +85,6 @@ static int m68kspkr_remove(struct platform_device *dev) struct input_dev *input_dev = platform_get_drvdata(dev); input_unregister_device(input_dev); - platform_set_drvdata(dev, NULL); /* turn off the speaker */ m68kspkr_event(NULL, EV_SND, SND_BELL, 0); diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index f9179b2..eef41cf 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c @@ -148,8 +148,6 @@ static int max8925_onkey_remove(struct platform_device *pdev) input_unregister_device(info->idev); kfree(info); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c index 0906ca5..d0277a7 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c @@ -250,7 +250,6 @@ static int mc13783_pwrbutton_remove(struct platform_device *pdev) input_unregister_device(priv->pwr); kfree(priv); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 199db78..7288b26 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -100,7 +100,6 @@ static int pcspkr_remove(struct platform_device *dev) struct input_dev *pcspkr_dev = platform_get_drvdata(dev); input_unregister_device(pcspkr_dev); - platform_set_drvdata(dev, NULL); /* turn off the speaker */ pcspkr_event(NULL, EV_SND, SND_BELL, 0); diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index a9da65e..ec086f6 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -249,8 +249,6 @@ static int pm8xxx_vib_remove(struct platform_device *pdev) input_unregister_device(vib->vib_input_dev); kfree(vib); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 4b811be..b49b738 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -175,9 +175,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) return 0; free_press_irq: - free_irq(key_press_irq, NULL); + free_irq(key_press_irq, pwrkey); unreg_input_dev: - platform_set_drvdata(pdev, NULL); input_unregister_device(pwr); pwr = NULL; free_input_dev: @@ -198,7 +197,6 @@ static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) free_irq(key_press_irq, pwrkey); free_irq(key_release_irq, pwrkey); input_unregister_device(pwrkey->pwr); - platform_set_drvdata(pdev, NULL); kfree(pwrkey); return 0; diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 0808868..a37f0c9 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -133,7 +133,6 @@ static int pwm_beeper_remove(struct platform_device *pdev) { struct pwm_beeper *beeper = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); input_unregister_device(beeper->input); pwm_disable(beeper->pwm); diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index aff47b2..5b1aff8 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -317,8 +317,6 @@ static int rotary_encoder_remove(struct platform_device *pdev) if (!dev_get_platdata(&pdev->dev)) kfree(pdata); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index ad6415c..95cf299 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -128,7 +128,7 @@ static int sgi_buttons_probe(struct platform_device *pdev) __clear_bit(KEY_RESERVED, input->keybit); bdev->poll_dev = poll_dev; - dev_set_drvdata(&pdev->dev, bdev); + platform_set_drvdata(pdev, bdev); error = input_register_polled_device(poll_dev); if (error) @@ -139,19 +139,16 @@ static int sgi_buttons_probe(struct platform_device *pdev) err_free_mem: input_free_polled_device(poll_dev); kfree(bdev); - dev_set_drvdata(&pdev->dev, NULL); return error; } static int sgi_buttons_remove(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct buttons_dev *bdev = dev_get_drvdata(dev); + struct buttons_dev *bdev = platform_get_drvdata(pdev); input_unregister_polled_device(bdev->poll_dev); input_free_polled_device(bdev->poll_dev); kfree(bdev); - dev_set_drvdata(dev, NULL); return 0; } diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c new file mode 100644 index 0000000..0621c36 --- /dev/null +++ b/drivers/input/misc/sirfsoc-onkey.c @@ -0,0 +1,165 @@ +/* + * Power key driver for SiRF PrimaII + * + * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/rtc/sirfsoc_rtciobrg.h> +#include <linux/of.h> + +struct sirfsoc_pwrc_drvdata { + u32 pwrc_base; + struct input_dev *input; +}; + +#define PWRC_ON_KEY_BIT (1 << 0) + +#define PWRC_INT_STATUS 0xc +#define PWRC_INT_MASK 0x10 + +static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) +{ + struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_id; + u32 int_status; + + int_status = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + + PWRC_INT_STATUS); + sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, + pwrcdrv->pwrc_base + PWRC_INT_STATUS); + + /* + * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c + * to queue a SUSPEND APM event + */ + input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); + input_sync(pwrcdrv->input); + + /* + * Todo: report KEY_POWER event for Android platforms, Android PowerManager + * will handle the suspend and powerdown/hibernation + */ + + return IRQ_HANDLED; +} + +static const struct of_device_id sirfsoc_pwrc_of_match[] = { + { .compatible = "sirf,prima2-pwrc" }, + {}, +} +MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match); + +static int sirfsoc_pwrc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct sirfsoc_pwrc_drvdata *pwrcdrv; + int irq; + int error; + + pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(struct sirfsoc_pwrc_drvdata), + GFP_KERNEL); + if (!pwrcdrv) { + dev_info(&pdev->dev, "Not enough memory for the device data\n"); + return -ENOMEM; + } + + /* + * we can't use of_iomap because pwrc is not mapped in memory, + * the so-called base address is only offset in rtciobrg + */ + error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); + if (error) { + dev_err(&pdev->dev, + "unable to find base address of pwrc node in dtb\n"); + return error; + } + + pwrcdrv->input = devm_input_allocate_device(&pdev->dev); + if (!pwrcdrv->input) + return -ENOMEM; + + pwrcdrv->input->name = "sirfsoc pwrckey"; + pwrcdrv->input->phys = "pwrc/input0"; + pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); + + irq = platform_get_irq(pdev, 0); + error = devm_request_irq(&pdev->dev, irq, + sirfsoc_pwrc_isr, IRQF_SHARED, + "sirfsoc_pwrc_int", pwrcdrv); + if (error) { + dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", + irq, error); + return error; + } + + sirfsoc_rtc_iobrg_writel( + sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) | + PWRC_ON_KEY_BIT, + pwrcdrv->pwrc_base + PWRC_INT_MASK); + + error = input_register_device(pwrcdrv->input); + if (error) { + dev_err(&pdev->dev, + "unable to register input device, error: %d\n", + error); + return error; + } + + platform_set_drvdata(pdev, pwrcdrv); + device_init_wakeup(&pdev->dev, 1); + + return 0; +} + +static int sirfsoc_pwrc_remove(struct platform_device *pdev) +{ + device_init_wakeup(&pdev->dev, 0); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pwrc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev); + + /* + * Do not mask pwrc interrupt as we want pwrc work as a wakeup source + * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c + */ + sirfsoc_rtc_iobrg_writel( + sirfsoc_rtc_iobrg_readl( + pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, + pwrcdrv->pwrc_base + PWRC_INT_MASK); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume); + +static struct platform_driver sirfsoc_pwrc_driver = { + .probe = sirfsoc_pwrc_probe, + .remove = sirfsoc_pwrc_remove, + .driver = { + .name = "sirfsoc-pwrc", + .owner = THIS_MODULE, + .pm = &sirfsoc_pwrc_pm_ops, + .of_match_table = of_match_ptr(sirfsoc_pwrc_of_match), + } +}; + +module_platform_driver(sirfsoc_pwrc_driver); + +MODULE_LICENSE("GPLv2"); +MODULE_AUTHOR("Binghua Duan <Binghua.Duan@csr.com>, Xianglong Du <Xianglong.Du@csr.com>"); +MODULE_DESCRIPTION("CSR Prima2 PWRC Driver"); +MODULE_ALIAS("platform:sirfsoc-pwrc"); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index a53586a..65fd315 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -175,7 +175,7 @@ static int sparcspkr_probe(struct device *dev) static void sparcspkr_shutdown(struct platform_device *dev) { - struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); + struct sparcspkr_state *state = platform_get_drvdata(dev); struct input_dev *input_dev = state->input_dev; /* turn off the speaker */ @@ -211,7 +211,7 @@ static int bbc_beep_probe(struct platform_device *op) if (!info->regs) goto out_free; - dev_set_drvdata(&op->dev, state); + platform_set_drvdata(op, state); err = sparcspkr_probe(&op->dev); if (err) @@ -220,7 +220,6 @@ static int bbc_beep_probe(struct platform_device *op) return 0; out_clear_drvdata: - dev_set_drvdata(&op->dev, NULL); of_iounmap(&op->resource[0], info->regs, 6); out_free: @@ -231,7 +230,7 @@ out_err: static int bbc_remove(struct platform_device *op) { - struct sparcspkr_state *state = dev_get_drvdata(&op->dev); + struct sparcspkr_state *state = platform_get_drvdata(op); struct input_dev *input_dev = state->input_dev; struct bbc_beep_info *info = &state->u.bbc; @@ -242,7 +241,6 @@ static int bbc_remove(struct platform_device *op) of_iounmap(&op->resource[0], info->regs, 6); - dev_set_drvdata(&op->dev, NULL); kfree(state); return 0; @@ -290,7 +288,7 @@ static int grover_beep_probe(struct platform_device *op) if (!info->enable_reg) goto out_unmap_freq_regs; - dev_set_drvdata(&op->dev, state); + platform_set_drvdata(op, state); err = sparcspkr_probe(&op->dev); if (err) @@ -299,7 +297,6 @@ static int grover_beep_probe(struct platform_device *op) return 0; out_clear_drvdata: - dev_set_drvdata(&op->dev, NULL); of_iounmap(&op->resource[3], info->enable_reg, 1); out_unmap_freq_regs: @@ -312,7 +309,7 @@ out_err: static int grover_remove(struct platform_device *op) { - struct sparcspkr_state *state = dev_get_drvdata(&op->dev); + struct sparcspkr_state *state = platform_get_drvdata(op); struct grover_beep_info *info = &state->u.grover; struct input_dev *input_dev = state->input_dev; @@ -324,7 +321,6 @@ static int grover_remove(struct platform_device *op) of_iounmap(&op->resource[3], info->enable_reg, 1); of_iounmap(&op->resource[2], info->freq_regs, 2); - dev_set_drvdata(&op->dev, NULL); kfree(state); return 0; diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index b55d5af..62ec52b 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c @@ -133,7 +133,6 @@ static int __exit amimouse_remove(struct platform_device *pdev) { struct input_dev *dev = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); input_unregister_device(dev); return 0; } diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 532eaca..6b44413 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -138,7 +138,6 @@ static int gpio_mouse_probe(struct platform_device *pdev) out_free_polldev: input_free_polled_device(input_poll); - platform_set_drvdata(pdev, NULL); out_free_gpios: while (--i >= 0) { @@ -165,8 +164,6 @@ static int gpio_mouse_remove(struct platform_device *pdev) gpio_free(pin); } - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c index 8e1b98e..0b8d335 100644 --- a/drivers/input/mouse/navpoint.c +++ b/drivers/input/mouse/navpoint.c @@ -287,7 +287,7 @@ static int navpoint_probe(struct platform_device *pdev) return 0; err_free_irq: - free_irq(ssp->irq, &pdev->dev); + free_irq(ssp->irq, navpoint); err_free_mem: input_free_device(input); kfree(navpoint); diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 479ce5f..a0a2657 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -163,7 +163,6 @@ static int altera_ps2_remove(struct platform_device *pdev) { struct ps2if *ps2if = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); serio_unregister_port(ps2if->io); free_irq(ps2if->irq, ps2if); iounmap(ps2if->base); diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 190ce35..3290b28 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c @@ -314,8 +314,6 @@ static int __exit psif_remove(struct platform_device *pdev) clk_put(psif->pclk); kfree(psif); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 436a343..7a65a1b 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -181,7 +181,6 @@ static int q40kbd_remove(struct platform_device *pdev) free_irq(Q40_IRQ_KEYBOARD, q40kbd); kfree(q40kbd); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 17be859..4b7662a 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -349,8 +349,6 @@ static int xps2_of_remove(struct platform_device *of_dev) kfree(drvdata); - platform_set_drvdata(of_dev, NULL); - return 0; } diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index c706894..f7de14a 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -237,7 +237,7 @@ static int pm860x_touch_probe(struct platform_device *pdev) touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); if (touch == NULL) return -ENOMEM; - dev_set_drvdata(&pdev->dev, touch); + platform_set_drvdata(pdev, touch); touch->idev = input_allocate_device(); if (touch->idev == NULL) { @@ -299,7 +299,6 @@ static int pm860x_touch_remove(struct platform_device *pdev) input_unregister_device(touch->idev); free_irq(touch->irq, touch); - platform_set_drvdata(pdev, NULL); kfree(touch); return 0; } diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index 2c1e46b..268a35e 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c @@ -372,7 +372,6 @@ static int __init atmel_wm97xx_probe(struct platform_device *pdev) err_irq: free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); err: - platform_set_drvdata(pdev, NULL); kfree(atmel_wm97xx); return ret; } @@ -386,7 +385,6 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev) free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); del_timer_sync(&atmel_wm97xx->pen_timer); wm97xx_unregister_mach_ops(wm); - platform_set_drvdata(pdev, NULL); kfree(atmel_wm97xx); return 0; diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 95f6785..bddabc5 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -183,10 +183,13 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) struct input_dev *input_dev; struct resource *res; struct at91_tsadcc_data *pdata = pdev->dev.platform_data; - int err = 0; + int err; unsigned int prsc; unsigned int reg; + if (!pdata) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "no mmio resource defined.\n"); @@ -265,9 +268,6 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) prsc = clk_get_rate(ts_dev->clk); dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); - if (!pdata) - goto err_fail; - if (!pdata->adc_clock) pdata->adc_clock = ADC_DEFAULT_CLOCK; @@ -325,7 +325,7 @@ err_free_mem: static int atmel_tsadcc_remove(struct platform_device *pdev) { - struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev); + struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev); struct resource *res; free_irq(ts_dev->irq, ts_dev); diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c index 8f561e2..ab64d58 100644 --- a/drivers/input/touchscreen/da9052_tsi.c +++ b/drivers/input/touchscreen/da9052_tsi.c @@ -329,8 +329,6 @@ static int da9052_ts_remove(struct platform_device *pdev) input_unregister_device(tsi->dev); kfree(tsi); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 39f3df8..ef5fcb0 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -166,24 +166,22 @@ static int egalax_firmware_version(struct i2c_client *client) } static int egalax_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct egalax_ts *ts; struct input_dev *input_dev; - int ret; int error; - ts = kzalloc(sizeof(struct egalax_ts), GFP_KERNEL); + ts = devm_kzalloc(&client->dev, sizeof(struct egalax_ts), GFP_KERNEL); if (!ts) { dev_err(&client->dev, "Failed to allocate memory\n"); return -ENOMEM; } - input_dev = input_allocate_device(); + input_dev = devm_input_allocate_device(&client->dev); if (!input_dev) { dev_err(&client->dev, "Failed to allocate memory\n"); - error = -ENOMEM; - goto err_free_ts; + return -ENOMEM; } ts->client = client; @@ -193,19 +191,17 @@ static int egalax_ts_probe(struct i2c_client *client, error = egalax_wake_up_device(client); if (error) { dev_err(&client->dev, "Failed to wake up the controller\n"); - goto err_free_dev; + return error; } - ret = egalax_firmware_version(client); - if (ret < 0) { + error = egalax_firmware_version(client); + if (error < 0) { dev_err(&client->dev, "Failed to read firmware version\n"); - error = -EIO; - goto err_free_dev; + return error; } input_dev->name = "EETI eGalax Touch Screen"; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; __set_bit(EV_ABS, input_dev->evbit); __set_bit(EV_KEY, input_dev->evbit); @@ -221,41 +217,21 @@ static int egalax_ts_probe(struct i2c_client *client, input_set_drvdata(input_dev, ts); - error = request_threaded_irq(client->irq, NULL, egalax_ts_interrupt, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "egalax_ts", ts); + error = devm_request_threaded_irq(&client->dev, client->irq, NULL, + egalax_ts_interrupt, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "egalax_ts", ts); if (error < 0) { dev_err(&client->dev, "Failed to register interrupt\n"); - goto err_free_dev; + return error; } error = input_register_device(ts->input_dev); if (error) - goto err_free_irq; + return error; i2c_set_clientdata(client, ts); return 0; - -err_free_irq: - free_irq(client->irq, ts); -err_free_dev: - input_free_device(input_dev); -err_free_ts: - kfree(ts); - - return error; -} - -static int egalax_ts_remove(struct i2c_client *client) -{ - struct egalax_ts *ts = i2c_get_clientdata(client); - - free_irq(client->irq, ts); - - input_unregister_device(ts->input_dev); - kfree(ts); - - return 0; } static const struct i2c_device_id egalax_ts_id[] = { @@ -301,7 +277,6 @@ static struct i2c_driver egalax_ts_driver = { }, .id_table = egalax_ts_id, .probe = egalax_ts_probe, - .remove = egalax_ts_remove, }; module_i2c_driver(egalax_ts_driver); diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index 465db5d..e30d837 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c @@ -651,8 +651,6 @@ static int mrstouch_remove(struct platform_device *pdev) input_unregister_device(tsdev->input); kfree(tsdev); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 282d7c7..e463a79 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -145,7 +145,6 @@ static int jornada720_ts_probe(struct platform_device *pdev) fail2: free_irq(IRQ_GPIO9, pdev); fail1: - platform_set_drvdata(pdev, NULL); input_free_device(input_dev); kfree(jornada_ts); return error; @@ -156,7 +155,6 @@ static int jornada720_ts_remove(struct platform_device *pdev) struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); free_irq(IRQ_GPIO9, pdev); - platform_set_drvdata(pdev, NULL); input_unregister_device(jornada_ts->dev); kfree(jornada_ts); diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index 89308fe..d6f099c 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c @@ -233,8 +233,6 @@ static int mc13783_ts_remove(struct platform_device *pdev) { struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - destroy_workqueue(priv->workq); input_unregister_device(priv->idev); kfree(priv); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 51e7b87..50fb129 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -336,7 +336,6 @@ static int titsc_remove(struct platform_device *pdev) input_unregister_device(ts_dev->input); - platform_set_drvdata(pdev, NULL); kfree(ts_dev); return 0; } diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index acfb876..c47827a 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -351,7 +351,6 @@ error_clk: error_map: release_mem_region(ts->res->start, resource_size(ts->res)); error_res: - platform_set_drvdata(pdev, NULL); kfree(ts); return error; @@ -366,7 +365,6 @@ static int tsc_remove(struct platform_device *pdev) clk_put(ts->clk); iounmap(ts->regs); release_mem_region(ts->res->start, resource_size(ts->res)); - platform_set_drvdata(pdev, NULL); kfree(ts); return 0; diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index d2ef8f0..003d0c3 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c @@ -318,8 +318,6 @@ static int w90x900ts_remove(struct platform_device *pdev) input_unregister_device(w90p910_ts->input); kfree(w90p910_ts); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index bf0d076..7ccaa1b 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -1,7 +1,7 @@ /* * Wacom Penabled Driver for I2C * - * Copyright (c) 2011 Tatsunosuke Tobita, Wacom. + * Copyright (c) 2011 - 2013 Tatsunosuke Tobita, Wacom. * <tobita.tatsunosuke@wacom.co.jp> * * This program is free software; you can redistribute it @@ -27,7 +27,6 @@ #define WACOM_CMD_THROW0 0x05 #define WACOM_CMD_THROW1 0x00 #define WACOM_QUERY_SIZE 19 -#define WACOM_RETRY_CNT 100 struct wacom_features { int x_max; @@ -40,6 +39,8 @@ struct wacom_i2c { struct i2c_client *client; struct input_dev *input; u8 data[WACOM_QUERY_SIZE]; + bool prox; + int tool; }; static int wacom_query_device(struct i2c_client *client, @@ -112,9 +113,14 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) y = le16_to_cpup((__le16 *)&data[6]); pressure = le16_to_cpup((__le16 *)&data[8]); + if (!wac_i2c->prox) + wac_i2c->tool = (data[3] & 0x0c) ? + BTN_TOOL_RUBBER : BTN_TOOL_PEN; + + wac_i2c->prox = data[3] & 0x20; + input_report_key(input, BTN_TOUCH, tsw || ers); - input_report_key(input, BTN_TOOL_PEN, tsw); - input_report_key(input, BTN_TOOL_RUBBER, ers); + input_report_key(input, wac_i2c->tool, wac_i2c->prox); input_report_key(input, BTN_STYLUS, f1); input_report_key(input, BTN_STYLUS2, f2); input_report_abs(input, ABS_X, x); diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b51c154..55ba46f 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -44,6 +44,7 @@ #include <linux/uaccess.h> #include <linux/moduleparam.h> #include <linux/jiffies.h> +#include <linux/syscalls.h> #include <asm/ptrace.h> #include <asm/irq_regs.h> @@ -586,6 +587,7 @@ struct sysrq_state { /* reset sequence handling */ bool reset_canceled; + bool reset_requested; unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)]; int reset_seq_len; int reset_seq_cnt; @@ -624,18 +626,26 @@ static void sysrq_parse_reset_sequence(struct sysrq_state *state) state->reset_seq_version = sysrq_reset_seq_version; } -static void sysrq_do_reset(unsigned long dummy) +static void sysrq_do_reset(unsigned long _state) { - __handle_sysrq(sysrq_xlate[KEY_B], false); + struct sysrq_state *state = (struct sysrq_state *) _state; + + state->reset_requested = true; + + sys_sync(); + kernel_restart(NULL); } static void sysrq_handle_reset_request(struct sysrq_state *state) { + if (state->reset_requested) + __handle_sysrq(sysrq_xlate[KEY_B], false); + if (sysrq_reset_downtime_ms) mod_timer(&state->keyreset_timer, jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms)); else - sysrq_do_reset(0); + sysrq_do_reset((unsigned long)state); } static void sysrq_detect_reset_sequence(struct sysrq_state *state, @@ -837,7 +847,8 @@ static int sysrq_connect(struct input_handler *handler, sysrq->handle.handler = handler; sysrq->handle.name = "sysrq"; sysrq->handle.private = sysrq; - setup_timer(&sysrq->keyreset_timer, sysrq_do_reset, 0); + setup_timer(&sysrq->keyreset_timer, + sysrq_do_reset, (unsigned long)sysrq); error = input_register_handle(&sysrq->handle); if (error) { diff --git a/include/linux/platform_data/keypad-pxa27x.h b/include/linux/platform_data/keypad-pxa27x.h index 5ce8d5e6..2462556 100644 --- a/include/linux/platform_data/keypad-pxa27x.h +++ b/include/linux/platform_data/keypad-pxa27x.h @@ -36,10 +36,9 @@ struct pxa27x_keypad_platform_data { /* code map for the matrix keys */ + const struct matrix_keymap_data *matrix_keymap_data; unsigned int matrix_key_rows; unsigned int matrix_key_cols; - unsigned int *matrix_key_map; - int matrix_key_map_size; /* direct keys */ int direct_key_num; |