aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/brcm,bcm-keypad.txt108
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/bcm-keypad.c458
4 files changed, 578 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/input/brcm,bcm-keypad.txt b/Documentation/devicetree/bindings/input/brcm,bcm-keypad.txt
new file mode 100644
index 000000000000..b77f50bd6403
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/brcm,bcm-keypad.txt
@@ -0,0 +1,108 @@
1* Broadcom Keypad Controller device tree bindings
2
3Broadcom Keypad controller is used to interface a SoC with a matrix-type
4keypad device. The keypad controller supports multiple row and column lines.
5A key can be placed at each intersection of a unique row and a unique column.
6The keypad controller can sense a key-press and key-release and report the
7event using a interrupt to the cpu.
8
9This binding is based on the matrix-keymap binding with the following
10changes:
11
12keypad,num-rows and keypad,num-columns are required.
13
14Required SoC Specific Properties:
15- compatible: should be "brcm,bcm-keypad"
16
17- reg: physical base address of the controller and length of memory mapped
18 region.
19
20- interrupts: The interrupt number to the cpu.
21
22Board Specific Properties:
23- keypad,num-rows: Number of row lines connected to the keypad
24 controller.
25
26- keypad,num-columns: Number of column lines connected to the
27 keypad controller.
28
29- col-debounce-filter-period: The debounce period for the Column filter.
30
31 KEYPAD_DEBOUNCE_1_ms = 0
32 KEYPAD_DEBOUNCE_2_ms = 1
33 KEYPAD_DEBOUNCE_4_ms = 2
34 KEYPAD_DEBOUNCE_8_ms = 3
35 KEYPAD_DEBOUNCE_16_ms = 4
36 KEYPAD_DEBOUNCE_32_ms = 5
37 KEYPAD_DEBOUNCE_64_ms = 6
38 KEYPAD_DEBOUNCE_128_ms = 7
39
40- status-debounce-filter-period: The debounce period for the Status filter.
41
42 KEYPAD_DEBOUNCE_1_ms = 0
43 KEYPAD_DEBOUNCE_2_ms = 1
44 KEYPAD_DEBOUNCE_4_ms = 2
45 KEYPAD_DEBOUNCE_8_ms = 3
46 KEYPAD_DEBOUNCE_16_ms = 4
47 KEYPAD_DEBOUNCE_32_ms = 5
48 KEYPAD_DEBOUNCE_64_ms = 6
49 KEYPAD_DEBOUNCE_128_ms = 7
50
51- row-output-enabled: An optional property indicating whether the row or
52 column is being used as output. If specified the row is being used
53 as the output. Else defaults to column.
54
55- pull-up-enabled: An optional property indicating the Keypad scan mode.
56 If specified implies the keypad scan pull-up has been enabled.
57
58- autorepeat: Boolean, Enable auto repeat feature of Linux input
59 subsystem (optional).
60
61- linux,keymap: The keymap for keys as described in the binding document
62 devicetree/bindings/input/matrix-keymap.txt.
63
64Example:
65#include "dt-bindings/input/input.h"
66
67/ {
68 keypad: keypad@180ac000 {
69 /* Required SoC specific properties */
70 compatible = "brcm,bcm-keypad";
71
72 /* Required Board specific properties */
73 keypad,num-rows = <5>;
74 keypad,num-columns = <5>;
75 status = "okay";
76
77 linux,keymap = <MATRIX_KEY(0x00, 0x02, KEY_F) /* key_forward */
78 MATRIX_KEY(0x00, 0x03, KEY_HOME) /* key_home */
79 MATRIX_KEY(0x00, 0x04, KEY_M) /* key_message */
80 MATRIX_KEY(0x01, 0x00, KEY_A) /* key_contacts */
81 MATRIX_KEY(0x01, 0x01, KEY_1) /* key_1 */
82 MATRIX_KEY(0x01, 0x02, KEY_2) /* key_2 */
83 MATRIX_KEY(0x01, 0x03, KEY_3) /* key_3 */
84 MATRIX_KEY(0x01, 0x04, KEY_S) /* key_speaker */
85 MATRIX_KEY(0x02, 0x00, KEY_P) /* key_phone */
86 MATRIX_KEY(0x02, 0x01, KEY_4) /* key_4 */
87 MATRIX_KEY(0x02, 0x02, KEY_5) /* key_5 */
88 MATRIX_KEY(0x02, 0x03, KEY_6) /* key_6 */
89 MATRIX_KEY(0x02, 0x04, KEY_VOLUMEUP) /* key_vol_up */
90 MATRIX_KEY(0x03, 0x00, KEY_C) /* key_call_log */
91 MATRIX_KEY(0x03, 0x01, KEY_7) /* key_7 */
92 MATRIX_KEY(0x03, 0x02, KEY_8) /* key_8 */
93 MATRIX_KEY(0x03, 0x03, KEY_9) /* key_9 */
94 MATRIX_KEY(0x03, 0x04, KEY_VOLUMEDOWN) /* key_vol_down */
95 MATRIX_KEY(0x04, 0x00, KEY_H) /* key_headset */
96 MATRIX_KEY(0x04, 0x01, KEY_KPASTERISK) /* key_* */
97 MATRIX_KEY(0x04, 0x02, KEY_0) /* key_0 */
98 MATRIX_KEY(0x04, 0x03, KEY_GRAVE) /* key_# */
99 MATRIX_KEY(0x04, 0x04, KEY_MUTE) /* key_mute */
100 >;
101
102 /* Optional board specific properties */
103 col-debounce-filter-period = <5>;
104 row-output-enabled;
105 pull-up-enabled;
106
107 };
108};
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a89ba7cb96f1..17de1dcac637 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -686,4 +686,15 @@ config KEYBOARD_CAP11XX
686 To compile this driver as a module, choose M here: the 686 To compile this driver as a module, choose M here: the
687 module will be called cap11xx. 687 module will be called cap11xx.
688 688
689config KEYBOARD_BCM
690 tristate "Broadcom keypad driver"
691 depends on OF && HAVE_CLK
692 select INPUT_MATRIXKMAP
693 default ARCH_BCM_CYGNUS
694 help
695 Say Y here if you want to use Broadcom keypad.
696
697 To compile this driver as a module, choose M here: the
698 module will be called bcm-keypad.
699
689endif 700endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 470767884bd8..a648f6c6bbfa 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o
10obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o 10obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
11obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o 11obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
12obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o 12obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
13obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o
13obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o 14obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
14obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o 15obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o
15obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o 16obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c
new file mode 100644
index 000000000000..86a8b723ae15
--- /dev/null
+++ b/drivers/input/keyboard/bcm-keypad.c
@@ -0,0 +1,458 @@
1/*
2 * Copyright (C) 2014 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/bitops.h>
15#include <linux/clk.h>
16#include <linux/gfp.h>
17#include <linux/io.h>
18#include <linux/input.h>
19#include <linux/input/matrix_keypad.h>
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/platform_device.h>
24#include <linux/stddef.h>
25#include <linux/types.h>
26
27#define DEFAULT_CLK_HZ 31250
28#define MAX_ROWS 8
29#define MAX_COLS 8
30
31/* Register/field definitions */
32#define KPCR_OFFSET 0x00000080
33#define KPCR_MODE 0x00000002
34#define KPCR_MODE_SHIFT 1
35#define KPCR_MODE_MASK 1
36#define KPCR_ENABLE 0x00000001
37#define KPCR_STATUSFILTERENABLE 0x00008000
38#define KPCR_STATUSFILTERTYPE_SHIFT 12
39#define KPCR_COLFILTERENABLE 0x00000800
40#define KPCR_COLFILTERTYPE_SHIFT 8
41#define KPCR_ROWWIDTH_SHIFT 20
42#define KPCR_COLUMNWIDTH_SHIFT 16
43
44#define KPIOR_OFFSET 0x00000084
45#define KPIOR_ROWOCONTRL_SHIFT 24
46#define KPIOR_ROWOCONTRL_MASK 0xFF000000
47#define KPIOR_COLUMNOCONTRL_SHIFT 16
48#define KPIOR_COLUMNOCONTRL_MASK 0x00FF0000
49#define KPIOR_COLUMN_IO_DATA_SHIFT 0
50
51#define KPEMR0_OFFSET 0x00000090
52#define KPEMR1_OFFSET 0x00000094
53#define KPEMR2_OFFSET 0x00000098
54#define KPEMR3_OFFSET 0x0000009C
55#define KPEMR_EDGETYPE_BOTH 3
56
57#define KPSSR0_OFFSET 0x000000A0
58#define KPSSR1_OFFSET 0x000000A4
59#define KPSSRN_OFFSET(reg_n) (KPSSR0_OFFSET + 4 * (reg_n))
60#define KPIMR0_OFFSET 0x000000B0
61#define KPIMR1_OFFSET 0x000000B4
62#define KPICR0_OFFSET 0x000000B8
63#define KPICR1_OFFSET 0x000000BC
64#define KPICRN_OFFSET(reg_n) (KPICR0_OFFSET + 4 * (reg_n))
65#define KPISR0_OFFSET 0x000000C0
66#define KPISR1_OFFSET 0x000000C4
67
68#define KPCR_STATUSFILTERTYPE_MAX 7
69#define KPCR_COLFILTERTYPE_MAX 7
70
71/* Macros to determine the row/column from a bit that is set in SSR0/1. */
72#define BIT_TO_ROW_SSRN(bit_nr, reg_n) (((bit_nr) >> 3) + 4 * (reg_n))
73#define BIT_TO_COL(bit_nr) ((bit_nr) % 8)
74
75/* Structure representing various run-time entities */
76struct bcm_kp {
77 void __iomem *base;
78 int irq;
79 struct clk *clk;
80 struct input_dev *input_dev;
81 unsigned long last_state[2];
82 unsigned int n_rows;
83 unsigned int n_cols;
84 u32 kpcr;
85 u32 kpior;
86 u32 kpemr;
87 u32 imr0_val;
88 u32 imr1_val;
89};
90
91/*
92 * Returns the keycode from the input device keymap given the row and
93 * column.
94 */
95static int bcm_kp_get_keycode(struct bcm_kp *kp, int row, int col)
96{
97 unsigned int row_shift = get_count_order(kp->n_cols);
98 unsigned short *keymap = kp->input_dev->keycode;
99
100 return keymap[MATRIX_SCAN_CODE(row, col, row_shift)];
101}
102
103static void bcm_kp_report_keys(struct bcm_kp *kp, int reg_num, int pull_mode)
104{
105 unsigned long state, change;
106 int bit_nr;
107 int key_press;
108 int row, col;
109 unsigned int keycode;
110
111 /* Clear interrupts */
112 writel(0xFFFFFFFF, kp->base + KPICRN_OFFSET(reg_num));
113
114 state = readl(kp->base + KPSSRN_OFFSET(reg_num));
115 change = kp->last_state[reg_num] ^ state;
116 kp->last_state[reg_num] = state;
117
118 for_each_set_bit(bit_nr, &change, BITS_PER_LONG) {
119 key_press = state & BIT(bit_nr);
120 /* The meaning of SSR register depends on pull mode. */
121 key_press = pull_mode ? !key_press : key_press;
122 row = BIT_TO_ROW_SSRN(bit_nr, reg_num);
123 col = BIT_TO_COL(bit_nr);
124 keycode = bcm_kp_get_keycode(kp, row, col);
125 input_report_key(kp->input_dev, keycode, key_press);
126 }
127}
128
129static irqreturn_t bcm_kp_isr_thread(int irq, void *dev_id)
130{
131 struct bcm_kp *kp = dev_id;
132 int pull_mode = (kp->kpcr >> KPCR_MODE_SHIFT) & KPCR_MODE_MASK;
133 int reg_num;
134
135 for (reg_num = 0; reg_num <= 1; reg_num++)
136 bcm_kp_report_keys(kp, reg_num, pull_mode);
137
138 input_sync(kp->input_dev);
139
140 return IRQ_HANDLED;
141}
142
143static int bcm_kp_start(struct bcm_kp *kp)
144{
145 int error;
146
147 if (kp->clk) {
148 error = clk_prepare_enable(kp->clk);
149 if (error)
150 return error;
151 }
152
153 writel(kp->kpior, kp->base + KPIOR_OFFSET);
154
155 writel(kp->imr0_val, kp->base + KPIMR0_OFFSET);
156 writel(kp->imr1_val, kp->base + KPIMR1_OFFSET);
157
158 writel(kp->kpemr, kp->base + KPEMR0_OFFSET);
159 writel(kp->kpemr, kp->base + KPEMR1_OFFSET);
160 writel(kp->kpemr, kp->base + KPEMR2_OFFSET);
161 writel(kp->kpemr, kp->base + KPEMR3_OFFSET);
162
163 writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET);
164 writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET);
165
166 kp->last_state[0] = readl(kp->base + KPSSR0_OFFSET);
167 kp->last_state[0] = readl(kp->base + KPSSR1_OFFSET);
168
169 writel(kp->kpcr | KPCR_ENABLE, kp->base + KPCR_OFFSET);
170
171 return 0;
172}
173
174static void bcm_kp_stop(const struct bcm_kp *kp)
175{
176 u32 val;
177
178 val = readl(kp->base + KPCR_OFFSET);
179 val &= ~KPCR_ENABLE;
180 writel(0, kp->base + KPCR_OFFSET);
181 writel(0, kp->base + KPIMR0_OFFSET);
182 writel(0, kp->base + KPIMR1_OFFSET);
183 writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET);
184 writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET);
185
186 if (kp->clk)
187 clk_disable_unprepare(kp->clk);
188}
189
190static int bcm_kp_open(struct input_dev *dev)
191{
192 struct bcm_kp *kp = input_get_drvdata(dev);
193
194 return bcm_kp_start(kp);
195}
196
197static void bcm_kp_close(struct input_dev *dev)
198{
199 struct bcm_kp *kp = input_get_drvdata(dev);
200
201 bcm_kp_stop(kp);
202}
203
204static int bcm_kp_matrix_key_parse_dt(struct bcm_kp *kp)
205{
206 struct device *dev = kp->input_dev->dev.parent;
207 struct device_node *np = dev->of_node;
208 int error;
209 unsigned int dt_val;
210 unsigned int i;
211 unsigned int num_rows, col_mask, rows_set;
212
213 /* Initialize the KPCR Keypad Configuration Register */
214 kp->kpcr = KPCR_STATUSFILTERENABLE | KPCR_COLFILTERENABLE;
215
216 error = matrix_keypad_parse_of_params(dev, &kp->n_rows, &kp->n_cols);
217 if (error) {
218 dev_err(dev, "failed to parse kp params\n");
219 return error;
220 }
221
222 /* Set row width for the ASIC block. */
223 kp->kpcr |= (kp->n_rows - 1) << KPCR_ROWWIDTH_SHIFT;
224
225 /* Set column width for the ASIC block. */
226 kp->kpcr |= (kp->n_cols - 1) << KPCR_COLUMNWIDTH_SHIFT;
227
228 /* Configure the IMR registers */
229
230 /*
231 * IMR registers contain interrupt enable bits for 8x8 matrix
232 * IMR0 register format: <row3> <row2> <row1> <row0>
233 * IMR1 register format: <row7> <row6> <row5> <row4>
234 */
235 col_mask = (1 << (kp->n_cols)) - 1;
236 num_rows = kp->n_rows;
237
238 /* Set column bits in rows 0 to 3 in IMR0 */
239 kp->imr0_val = col_mask;
240
241 rows_set = 1;
242 while (--num_rows && rows_set++ < 4)
243 kp->imr0_val |= kp->imr0_val << MAX_COLS;
244
245 /* Set column bits in rows 4 to 7 in IMR1 */
246 kp->imr1_val = 0;
247 if (num_rows) {
248 kp->imr1_val = col_mask;
249 while (--num_rows)
250 kp->imr1_val |= kp->imr1_val << MAX_COLS;
251 }
252
253 /* Initialize the KPEMR Keypress Edge Mode Registers */
254 /* Trigger on both edges */
255 kp->kpemr = 0;
256 for (i = 0; i <= 30; i += 2)
257 kp->kpemr |= (KPEMR_EDGETYPE_BOTH << i);
258
259 /*
260 * Obtain the Status filter debounce value and verify against the
261 * possible values specified in the DT binding.
262 */
263 of_property_read_u32(np, "status-debounce-filter-period", &dt_val);
264
265 if (dt_val > KPCR_STATUSFILTERTYPE_MAX) {
266 dev_err(dev, "Invalid Status filter debounce value %d\n",
267 dt_val);
268 return -EINVAL;
269 }
270
271 kp->kpcr |= dt_val << KPCR_STATUSFILTERTYPE_SHIFT;
272
273 /*
274 * Obtain the Column filter debounce value and verify against the
275 * possible values specified in the DT binding.
276 */
277 of_property_read_u32(np, "col-debounce-filter-period", &dt_val);
278
279 if (dt_val > KPCR_COLFILTERTYPE_MAX) {
280 dev_err(dev, "Invalid Column filter debounce value %d\n",
281 dt_val);
282 return -EINVAL;
283 }
284
285 kp->kpcr |= dt_val << KPCR_COLFILTERTYPE_SHIFT;
286
287 /*
288 * Determine between the row and column,
289 * which should be configured as output.
290 */
291 if (of_property_read_bool(np, "row-output-enabled")) {
292 /*
293 * Set RowOContrl or ColumnOContrl in KPIOR
294 * to the number of pins to drive as outputs
295 */
296 kp->kpior = ((1 << kp->n_rows) - 1) <<
297 KPIOR_ROWOCONTRL_SHIFT;
298 } else {
299 kp->kpior = ((1 << kp->n_cols) - 1) <<
300 KPIOR_COLUMNOCONTRL_SHIFT;
301 }
302
303 /*
304 * Determine if the scan pull up needs to be enabled
305 */
306 if (of_property_read_bool(np, "pull-up-enabled"))
307 kp->kpcr |= KPCR_MODE;
308
309 dev_dbg(dev, "n_rows=%d n_col=%d kpcr=%x kpior=%x kpemr=%x\n",
310 kp->n_rows, kp->n_cols,
311 kp->kpcr, kp->kpior, kp->kpemr);
312
313 return 0;
314}
315
316
317static int bcm_kp_probe(struct platform_device *pdev)
318{
319 struct bcm_kp *kp;
320 struct input_dev *input_dev;
321 struct resource *res;
322 int error;
323
324 kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
325 if (!kp)
326 return -ENOMEM;
327
328 input_dev = devm_input_allocate_device(&pdev->dev);
329 if (!input_dev) {
330 dev_err(&pdev->dev, "failed to allocate the input device\n");
331 return -ENOMEM;
332 }
333
334 __set_bit(EV_KEY, input_dev->evbit);
335
336 /* Enable auto repeat feature of Linux input subsystem */
337 if (of_property_read_bool(pdev->dev.of_node, "autorepeat"))
338 __set_bit(EV_REP, input_dev->evbit);
339
340 input_dev->name = pdev->name;
341 input_dev->phys = "keypad/input0";
342 input_dev->dev.parent = &pdev->dev;
343 input_dev->open = bcm_kp_open;
344 input_dev->close = bcm_kp_close;
345
346 input_dev->id.bustype = BUS_HOST;
347 input_dev->id.vendor = 0x0001;
348 input_dev->id.product = 0x0001;
349 input_dev->id.version = 0x0100;
350
351 input_set_drvdata(input_dev, kp);
352
353 kp->input_dev = input_dev;
354
355 platform_set_drvdata(pdev, kp);
356
357 error = bcm_kp_matrix_key_parse_dt(kp);
358 if (error)
359 return error;
360
361 error = matrix_keypad_build_keymap(NULL, NULL,
362 kp->n_rows, kp->n_cols,
363 NULL, input_dev);
364 if (error) {
365 dev_err(&pdev->dev, "failed to build keymap\n");
366 return error;
367 }
368
369 /* Get the KEYPAD base address */
370 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
371 if (!res) {
372 dev_err(&pdev->dev, "Missing keypad base address resource\n");
373 return -ENODEV;
374 }
375
376 kp->base = devm_ioremap_resource(&pdev->dev, res);
377 if (IS_ERR(kp->base))
378 return PTR_ERR(kp->base);
379
380 /* Enable clock */
381 kp->clk = devm_clk_get(&pdev->dev, "peri_clk");
382 if (IS_ERR(kp->clk)) {
383 error = PTR_ERR(kp->clk);
384 if (error != -ENOENT) {
385 if (error != -EPROBE_DEFER)
386 dev_err(&pdev->dev, "Failed to get clock\n");
387 return error;
388 }
389 dev_dbg(&pdev->dev,
390 "No clock specified. Assuming it's enabled\n");
391 kp->clk = NULL;
392 } else {
393 unsigned int desired_rate;
394 long actual_rate;
395
396 error = of_property_read_u32(pdev->dev.of_node,
397 "clock-frequency", &desired_rate);
398 if (error < 0)
399 desired_rate = DEFAULT_CLK_HZ;
400
401 actual_rate = clk_round_rate(kp->clk, desired_rate);
402 if (actual_rate <= 0)
403 return -EINVAL;
404
405 error = clk_set_rate(kp->clk, actual_rate);
406 if (error)
407 return error;
408
409 error = clk_prepare_enable(kp->clk);
410 if (error)
411 return error;
412 }
413
414 /* Put the kp into a known sane state */
415 bcm_kp_stop(kp);
416
417 kp->irq = platform_get_irq(pdev, 0);
418 if (kp->irq < 0) {
419 dev_err(&pdev->dev, "no IRQ specified\n");
420 return -EINVAL;
421 }
422
423 error = devm_request_threaded_irq(&pdev->dev, kp->irq,
424 NULL, bcm_kp_isr_thread,
425 IRQF_ONESHOT, pdev->name, kp);
426 if (error) {
427 dev_err(&pdev->dev, "failed to request IRQ\n");
428 return error;
429 }
430
431 error = input_register_device(input_dev);
432 if (error) {
433 dev_err(&pdev->dev, "failed to register input device\n");
434 return error;
435 }
436
437 return 0;
438}
439
440static const struct of_device_id bcm_kp_of_match[] = {
441 { .compatible = "brcm,bcm-keypad" },
442 { },
443};
444MODULE_DEVICE_TABLE(of, bcm_kp_of_match);
445
446static struct platform_driver bcm_kp_device_driver = {
447 .probe = bcm_kp_probe,
448 .driver = {
449 .name = "bcm-keypad",
450 .of_match_table = of_match_ptr(bcm_kp_of_match),
451 }
452};
453
454module_platform_driver(bcm_kp_device_driver);
455
456MODULE_AUTHOR("Broadcom Corporation");
457MODULE_DESCRIPTION("BCM Keypad Driver");
458MODULE_LICENSE("GPL v2");