xref: /linux/arch/mips/bcm47xx/buttons.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "bcm47xx_private.h"
3 
4 #include "linux/err.h"
5 #include <linux/gpio/machine.h>
6 #include <linux/gpio/property.h>
7 #include <linux/input-event-codes.h>
8 #include <linux/interrupt.h>
9 #include <linux/platform_device.h>
10 #include <linux/property.h>
11 
12 #include <bcm47xx_board.h>
13 #include <bcm47xx.h>
14 
15 /**************************************************
16  * Database
17  **************************************************/
18 
19 struct bcm47xx_gpio_key {
20 	u16 code;
21 	u8 pin;
22 	u8 flags;
23 };
24 
25 #define BCM47XX_GPIO_KEY(_gpio, _code)			\
26 	{						\
27 		.code	= _code,			\
28 		.pin	= _gpio,			\
29 		.flags	= GPIO_ACTIVE_LOW,		\
30 	}
31 
32 #define BCM47XX_GPIO_KEY_H(_gpio, _code)		\
33 	{						\
34 		.code	= _code,			\
35 		.pin	= _gpio,			\
36 		.flags	= GPIO_ACTIVE_HIGH,		\
37 	}
38 
39 /* Asus */
40 
41 static const struct bcm47xx_gpio_key bcm47xx_buttons_asus_rtn10u[] __initconst = {
42 	BCM47XX_GPIO_KEY(20, KEY_WPS_BUTTON),
43 	BCM47XX_GPIO_KEY(21, KEY_RESTART),
44 };
45 
46 static const struct bcm47xx_gpio_key bcm47xx_buttons_asus_rtn12[] __initconst = {
47 	BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
48 	BCM47XX_GPIO_KEY(1, KEY_RESTART),
49 	BCM47XX_GPIO_KEY(4, BTN_0), /* Router mode */
50 	BCM47XX_GPIO_KEY(5, BTN_1), /* Repeater mode */
51 	BCM47XX_GPIO_KEY(6, BTN_2), /* AP mode */
52 };
53 
54 static const struct bcm47xx_gpio_key bcm47xx_buttons_asus_rtn16[] __initconst = {
55 	BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
56 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
57 };
58 
59 static const struct bcm47xx_gpio_key
60 bcm47xx_buttons_asus_rtn66u[] __initconst = {
61 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
62 	BCM47XX_GPIO_KEY(9, KEY_RESTART),
63 };
64 
65 static const struct bcm47xx_gpio_key
66 bcm47xx_buttons_asus_wl300g[] __initconst = {
67 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
68 };
69 
70 static const struct bcm47xx_gpio_key
71 bcm47xx_buttons_asus_wl320ge[] __initconst = {
72 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
73 };
74 
75 static const struct bcm47xx_gpio_key
76 bcm47xx_buttons_asus_wl330ge[] __initconst = {
77 	BCM47XX_GPIO_KEY(2, KEY_RESTART),
78 };
79 
80 static const struct bcm47xx_gpio_key
81 bcm47xx_buttons_asus_wl500g[] __initconst = {
82 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
83 };
84 
85 static const struct bcm47xx_gpio_key
86 bcm47xx_buttons_asus_wl500gd[] __initconst = {
87 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
88 };
89 
90 static const struct bcm47xx_gpio_key
91 bcm47xx_buttons_asus_wl500gpv1[] __initconst = {
92 	BCM47XX_GPIO_KEY(0, KEY_RESTART),
93 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
94 };
95 
96 static const struct bcm47xx_gpio_key
97 bcm47xx_buttons_asus_wl500gpv2[] __initconst = {
98 	BCM47XX_GPIO_KEY(2, KEY_RESTART),
99 	BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
100 };
101 
102 static const struct bcm47xx_gpio_key
103 bcm47xx_buttons_asus_wl500w[] __initconst = {
104 	BCM47XX_GPIO_KEY_H(6, KEY_RESTART),
105 	BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON),
106 };
107 
108 static const struct bcm47xx_gpio_key
109 bcm47xx_buttons_asus_wl520gc[] __initconst = {
110 	BCM47XX_GPIO_KEY(2, KEY_RESTART),
111 	BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
112 };
113 
114 static const struct bcm47xx_gpio_key
115 bcm47xx_buttons_asus_wl520gu[] __initconst = {
116 	BCM47XX_GPIO_KEY(2, KEY_RESTART),
117 	BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
118 };
119 
120 static const struct bcm47xx_gpio_key
121 bcm47xx_buttons_asus_wl700ge[] __initconst = {
122 	BCM47XX_GPIO_KEY(0, KEY_POWER), /* Hard disk power switch */
123 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), /* EZSetup */
124 	BCM47XX_GPIO_KEY(6, KEY_COPY), /* Copy data from USB to internal disk */
125 	BCM47XX_GPIO_KEY(7, KEY_RESTART), /* Hard reset */
126 };
127 
128 static const struct bcm47xx_gpio_key
129 bcm47xx_buttons_asus_wlhdd[] __initconst = {
130 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
131 };
132 
133 /* Huawei */
134 
135 static const struct bcm47xx_gpio_key
136 bcm47xx_buttons_huawei_e970[] __initconst = {
137 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
138 };
139 
140 /* Belkin */
141 
142 static const struct bcm47xx_gpio_key
143 bcm47xx_buttons_belkin_f7d4301[] __initconst = {
144 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
145 	BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
146 };
147 
148 /* Buffalo */
149 
150 static const struct bcm47xx_gpio_key
151 bcm47xx_buttons_buffalo_whr2_a54g54[] __initconst = {
152 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
153 };
154 
155 static const struct bcm47xx_gpio_key
156 bcm47xx_buttons_buffalo_whr_g125[] __initconst = {
157 	BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
158 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
159 	BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode switch */
160 };
161 
162 static const struct bcm47xx_gpio_key
163 bcm47xx_buttons_buffalo_whr_g54s[] __initconst = {
164 	BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
165 	BCM47XX_GPIO_KEY_H(4, KEY_RESTART),
166 	BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode switch */
167 };
168 
169 static const struct bcm47xx_gpio_key
170 bcm47xx_buttons_buffalo_whr_hp_g54[] __initconst = {
171 	BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
172 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
173 	BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode switch */
174 };
175 
176 static const struct bcm47xx_gpio_key
177 bcm47xx_buttons_buffalo_wzr_g300n[] __initconst = {
178 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
179 };
180 
181 static const struct bcm47xx_gpio_key
182 bcm47xx_buttons_buffalo_wzr_rs_g54[] __initconst = {
183 	BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
184 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
185 };
186 
187 static const struct bcm47xx_gpio_key
188 bcm47xx_buttons_buffalo_wzr_rs_g54hp[] __initconst = {
189 	BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
190 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
191 };
192 
193 /* Dell */
194 
195 static const struct bcm47xx_gpio_key
196 bcm47xx_buttons_dell_tm2300[] __initconst = {
197 	BCM47XX_GPIO_KEY(0, KEY_RESTART),
198 };
199 
200 /* D-Link */
201 
202 static const struct bcm47xx_gpio_key
203 bcm47xx_buttons_dlink_dir130[] __initconst = {
204 	BCM47XX_GPIO_KEY(3, KEY_RESTART),
205 	BCM47XX_GPIO_KEY(7, KEY_UNKNOWN),
206 };
207 
208 static const struct bcm47xx_gpio_key
209 bcm47xx_buttons_dlink_dir330[] __initconst = {
210 	BCM47XX_GPIO_KEY(3, KEY_RESTART),
211 	BCM47XX_GPIO_KEY(7, KEY_UNKNOWN),
212 };
213 
214 /* Linksys */
215 
216 static const struct bcm47xx_gpio_key
217 bcm47xx_buttons_linksys_e1000v1[] __initconst = {
218 	BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
219 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
220 };
221 
222 static const struct bcm47xx_gpio_key
223 bcm47xx_buttons_linksys_e1000v21[] __initconst = {
224 	BCM47XX_GPIO_KEY(9, KEY_WPS_BUTTON),
225 	BCM47XX_GPIO_KEY(10, KEY_RESTART),
226 };
227 
228 static const struct bcm47xx_gpio_key
229 bcm47xx_buttons_linksys_e2000v1[] __initconst = {
230 	BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
231 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
232 };
233 
234 static const struct bcm47xx_gpio_key
235 bcm47xx_buttons_linksys_e2500v3[] __initconst = {
236 	BCM47XX_GPIO_KEY(9, KEY_WPS_BUTTON),
237 	BCM47XX_GPIO_KEY(10, KEY_RESTART),
238 };
239 
240 static const struct bcm47xx_gpio_key
241 bcm47xx_buttons_linksys_e3000v1[] __initconst = {
242 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
243 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
244 };
245 
246 static const struct bcm47xx_gpio_key
247 bcm47xx_buttons_linksys_e3200v1[] __initconst = {
248 	BCM47XX_GPIO_KEY(5, KEY_RESTART),
249 	BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
250 };
251 
252 static const struct bcm47xx_gpio_key
253 bcm47xx_buttons_linksys_e4200v1[] __initconst = {
254 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
255 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
256 };
257 
258 static const struct bcm47xx_gpio_key
259 bcm47xx_buttons_linksys_wrt150nv1[] __initconst = {
260 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
261 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
262 };
263 
264 static const struct bcm47xx_gpio_key
265 bcm47xx_buttons_linksys_wrt150nv11[] __initconst = {
266 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
267 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
268 };
269 
270 static const struct bcm47xx_gpio_key
271 bcm47xx_buttons_linksys_wrt160nv1[] __initconst = {
272 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
273 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
274 };
275 
276 static const struct bcm47xx_gpio_key
277 bcm47xx_buttons_linksys_wrt160nv3[] __initconst = {
278 	BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
279 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
280 };
281 
282 static const struct bcm47xx_gpio_key
283 bcm47xx_buttons_linksys_wrt300n_v1[] __initconst = {
284 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
285 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
286 };
287 
288 static const struct bcm47xx_gpio_key
289 bcm47xx_buttons_linksys_wrt300nv11[] __initconst = {
290 	BCM47XX_GPIO_KEY(4, KEY_UNKNOWN),
291 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
292 };
293 
294 static const struct bcm47xx_gpio_key
295 bcm47xx_buttons_linksys_wrt310nv1[] __initconst = {
296 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
297 	BCM47XX_GPIO_KEY(8, KEY_UNKNOWN),
298 };
299 
300 static const struct bcm47xx_gpio_key
301 bcm47xx_buttons_linksys_wrt310n_v2[] __initconst = {
302 	BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
303 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
304 };
305 
306 static const struct bcm47xx_gpio_key
307 bcm47xx_buttons_linksys_wrt320n_v1[] __initconst = {
308 	BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
309 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
310 };
311 
312 static const struct bcm47xx_gpio_key
313 bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = {
314 	BCM47XX_GPIO_KEY(5, KEY_WIMAX),
315 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
316 };
317 
318 static const struct bcm47xx_gpio_key
319 bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
320 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
321 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
322 };
323 
324 static const struct bcm47xx_gpio_key
325 bcm47xx_buttons_linksys_wrt610nv1[] __initconst = {
326 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
327 	BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
328 };
329 
330 static const struct bcm47xx_gpio_key
331 bcm47xx_buttons_linksys_wrt610nv2[] __initconst = {
332 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
333 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
334 };
335 
336 static const struct bcm47xx_gpio_key
337 bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
338 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
339 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
340 };
341 
342 /* Luxul */
343 
344 static const struct bcm47xx_gpio_key
345 bcm47xx_buttons_luxul_abr_4400_v1[] = {
346 	BCM47XX_GPIO_KEY(14, KEY_RESTART),
347 };
348 
349 static const struct bcm47xx_gpio_key
350 bcm47xx_buttons_luxul_xap_310_v1[] = {
351 	BCM47XX_GPIO_KEY(20, KEY_RESTART),
352 };
353 
354 static const struct bcm47xx_gpio_key
355 bcm47xx_buttons_luxul_xap_1210_v1[] = {
356 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
357 };
358 
359 static const struct bcm47xx_gpio_key
360 bcm47xx_buttons_luxul_xap_1230_v1[] = {
361 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
362 };
363 
364 static const struct bcm47xx_gpio_key
365 bcm47xx_buttons_luxul_xap_1240_v1[] = {
366 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
367 };
368 
369 static const struct bcm47xx_gpio_key
370 bcm47xx_buttons_luxul_xap_1500_v1[] = {
371 	BCM47XX_GPIO_KEY(14, KEY_RESTART),
372 };
373 
374 static const struct bcm47xx_gpio_key
375 bcm47xx_buttons_luxul_xbr_4400_v1[] = {
376 	BCM47XX_GPIO_KEY(14, KEY_RESTART),
377 };
378 
379 static const struct bcm47xx_gpio_key
380 bcm47xx_buttons_luxul_xvw_p30_v1[] = {
381 	BCM47XX_GPIO_KEY(20, KEY_RESTART),
382 };
383 
384 static const struct bcm47xx_gpio_key
385 bcm47xx_buttons_luxul_xwr_600_v1[] = {
386 	BCM47XX_GPIO_KEY(8, KEY_RESTART),
387 };
388 
389 static const struct bcm47xx_gpio_key
390 bcm47xx_buttons_luxul_xwr_1750_v1[] = {
391 	BCM47XX_GPIO_KEY(14, KEY_RESTART),
392 };
393 
394 /* Microsoft */
395 
396 static const struct bcm47xx_gpio_key
397 bcm47xx_buttons_microsoft_nm700[] __initconst = {
398 	BCM47XX_GPIO_KEY(7, KEY_RESTART),
399 };
400 
401 /* Motorola */
402 
403 static const struct bcm47xx_gpio_key
404 bcm47xx_buttons_motorola_we800g[] __initconst = {
405 	BCM47XX_GPIO_KEY(0, KEY_RESTART),
406 };
407 
408 static const struct bcm47xx_gpio_key
409 bcm47xx_buttons_motorola_wr850gp[] __initconst = {
410 	BCM47XX_GPIO_KEY(5, KEY_RESTART),
411 };
412 
413 static const struct bcm47xx_gpio_key
414 bcm47xx_buttons_motorola_wr850gv2v3[] __initconst = {
415 	BCM47XX_GPIO_KEY(5, KEY_RESTART),
416 };
417 
418 /* Netgear */
419 
420 static const struct bcm47xx_gpio_key
421 bcm47xx_buttons_netgear_r6200_v1[] __initconst = {
422 	BCM47XX_GPIO_KEY(2, KEY_RFKILL),
423 	BCM47XX_GPIO_KEY(3, KEY_RESTART),
424 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
425 };
426 
427 static const struct bcm47xx_gpio_key
428 bcm47xx_buttons_netgear_r6300_v1[] __initconst = {
429 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
430 };
431 
432 static const struct bcm47xx_gpio_key
433 bcm47xx_buttons_netgear_wn2500rp_v1[] __initconst = {
434 	BCM47XX_GPIO_KEY(12, KEY_RESTART),
435 	BCM47XX_GPIO_KEY(31, KEY_WPS_BUTTON),
436 };
437 
438 static const struct bcm47xx_gpio_key
439 bcm47xx_buttons_netgear_wndr3400v1[] __initconst = {
440 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
441 	BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
442 	BCM47XX_GPIO_KEY(8, KEY_RFKILL),
443 };
444 
445 static const struct bcm47xx_gpio_key
446 bcm47xx_buttons_netgear_wndr3400_v3[] __initconst = {
447 	BCM47XX_GPIO_KEY(12, KEY_RESTART),
448 	BCM47XX_GPIO_KEY(23, KEY_WPS_BUTTON),
449 };
450 
451 static const struct bcm47xx_gpio_key
452 bcm47xx_buttons_netgear_wndr3700v3[] __initconst = {
453 	BCM47XX_GPIO_KEY(2, KEY_RFKILL),
454 	BCM47XX_GPIO_KEY(3, KEY_RESTART),
455 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
456 };
457 
458 static const struct bcm47xx_gpio_key
459 bcm47xx_buttons_netgear_wndr4500v1[] __initconst = {
460 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
461 	BCM47XX_GPIO_KEY(5, KEY_RFKILL),
462 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
463 };
464 
465 static const struct bcm47xx_gpio_key
466 bcm47xx_buttons_netgear_wnr1000_v3[] __initconst = {
467 	BCM47XX_GPIO_KEY(2, KEY_WPS_BUTTON),
468 	BCM47XX_GPIO_KEY(3, KEY_RESTART),
469 };
470 
471 static const struct bcm47xx_gpio_key
472 bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
473 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
474 	BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
475 };
476 
477 static const struct bcm47xx_gpio_key
478 bcm47xx_buttons_netgear_wnr3500lv2[] __initconst = {
479 	BCM47XX_GPIO_KEY(4, KEY_RESTART),
480 	BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
481 	BCM47XX_GPIO_KEY(8, KEY_RFKILL),
482 };
483 
484 static const struct bcm47xx_gpio_key
485 bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
486 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
487 };
488 
489 /* SimpleTech */
490 
491 static const struct bcm47xx_gpio_key
492 bcm47xx_buttons_simpletech_simpleshare[] __initconst = {
493 	BCM47XX_GPIO_KEY(0, KEY_RESTART),
494 };
495 
496 /**************************************************
497  * Init
498  **************************************************/
499 
500 static int __init
501 bcm47xx_buttons_add(const struct bcm47xx_gpio_key *buttons, int nbuttons)
502 {
503 	struct platform_device *pdev;
504 	const struct software_node *gpio_swnode;
505 	struct property_entry *p;
506 	int error;
507 	int i;
508 
509 	switch (bcm47xx_bus_type) {
510 #ifdef CONFIG_BCM47XX_BCMA
511 	case BCM47XX_BUS_TYPE_BCMA:
512 		gpio_swnode = &bcma_gpio_swnode;
513 		break;
514 #endif
515 #ifdef CONFIG_BCM47XX_SSB
516 	case BCM47XX_BUS_TYPE_SSB:
517 		gpio_swnode = &ssb_gpio_swnode;
518 		break;
519 #endif
520 	default:
521 		return -ENODEV;
522 	}
523 
524 	/* 1 node for gpio-keys device, 1 node for each button, 1 terminator */
525 	const struct software_node **node_group __free(kfree) =
526 		kzalloc_objs(*node_group, 1 + nbuttons + 1);
527 	if (!node_group)
528 		return -ENOMEM;
529 
530 	/* 1 code property, 1 gpio property, 1 terminator */
531 	struct property_entry *props __free(kfree) =
532 		kzalloc_objs(*props, nbuttons * 3);
533 	if (!props)
534 		return -ENOMEM;
535 
536 	/* 1 node for gpio-keys device, 1 node for each button */
537 	struct software_node *nodes __free(kfree) =
538 		kzalloc_objs(*nodes, 1 + nbuttons);
539 	if (!nodes)
540 		return -ENOMEM;
541 
542 	struct software_node_ref_args *ref_args __free(kfree) =
543 		kzalloc_objs(*ref_args, nbuttons);
544 	if (!ref_args)
545 		return -ENOMEM;
546 
547 	/* gpio-keys node */
548 	nodes[0].name = "bcm47xx-gpio-buttons";
549 
550 	p = props;
551 	for (i = 0; i < nbuttons; i++) {
552 		const struct bcm47xx_gpio_key *button = &buttons[i];
553 		struct software_node *node = &nodes[1 + i];
554 		struct software_node_ref_args *ref = &ref_args[i];
555 
556 		node->parent = &nodes[0];
557 		node->properties = p;
558 
559 		*ref = SOFTWARE_NODE_REFERENCE(gpio_swnode, button->pin, button->flags);
560 		*p++ = PROPERTY_ENTRY_REF("gpios", &ref_args[i]);
561 		*p++ = PROPERTY_ENTRY_U32("linux,code", button->code);
562 		p++;
563 	}
564 
565 	for (i = 0; i < nbuttons + 1; i++)
566 		node_group[i] = &nodes[i];
567 
568 	error = software_node_register_node_group(node_group);
569 	if (error)
570 		return error;
571 
572 	pdev = platform_device_register_full(&(struct platform_device_info){
573 		.name = "gpio-keys",
574 		.swnode = &nodes[0],
575 	});
576 	error = PTR_ERR_OR_ZERO(pdev);
577 	if (error) {
578 		software_node_unregister_node_group(node_group);
579 		return error;
580 	}
581 
582 	retain_and_null_ptr(props);
583 	retain_and_null_ptr(nodes);
584 	retain_and_null_ptr(ref_args);
585 	return 0;
586 }
587 
588 #define bcm47xx_add_bdata(dev_buttons)					\
589 	bcm47xx_buttons_add(dev_buttons, ARRAY_SIZE(dev_buttons))
590 
591 int __init bcm47xx_buttons_register(void)
592 {
593 	enum bcm47xx_board board = bcm47xx_board_get();
594 	int err;
595 
596 	switch (board) {
597 	case BCM47XX_BOARD_ASUS_RTN10U:
598 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn10u);
599 		break;
600 	case BCM47XX_BOARD_ASUS_RTN12:
601 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn12);
602 		break;
603 	case BCM47XX_BOARD_ASUS_RTN16:
604 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn16);
605 		break;
606 	case BCM47XX_BOARD_ASUS_RTN66U:
607 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn66u);
608 		break;
609 	case BCM47XX_BOARD_ASUS_WL300G:
610 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl300g);
611 		break;
612 	case BCM47XX_BOARD_ASUS_WL320GE:
613 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl320ge);
614 		break;
615 	case BCM47XX_BOARD_ASUS_WL330GE:
616 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl330ge);
617 		break;
618 	case BCM47XX_BOARD_ASUS_WL500G:
619 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500g);
620 		break;
621 	case BCM47XX_BOARD_ASUS_WL500GD:
622 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500gd);
623 		break;
624 	case BCM47XX_BOARD_ASUS_WL500GPV1:
625 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500gpv1);
626 		break;
627 	case BCM47XX_BOARD_ASUS_WL500GPV2:
628 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500gpv2);
629 		break;
630 	case BCM47XX_BOARD_ASUS_WL500W:
631 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500w);
632 		break;
633 	case BCM47XX_BOARD_ASUS_WL520GC:
634 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl520gc);
635 		break;
636 	case BCM47XX_BOARD_ASUS_WL520GU:
637 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl520gu);
638 		break;
639 	case BCM47XX_BOARD_ASUS_WL700GE:
640 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl700ge);
641 		break;
642 	case BCM47XX_BOARD_ASUS_WLHDD:
643 		err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wlhdd);
644 		break;
645 
646 	case BCM47XX_BOARD_BELKIN_F7D3301:
647 	case BCM47XX_BOARD_BELKIN_F7D3302:
648 	case BCM47XX_BOARD_BELKIN_F7D4301:
649 	case BCM47XX_BOARD_BELKIN_F7D4302:
650 	case BCM47XX_BOARD_BELKIN_F7D4401:
651 		err = bcm47xx_add_bdata(bcm47xx_buttons_belkin_f7d4301);
652 		break;
653 
654 	case BCM47XX_BOARD_BUFFALO_WHR2_A54G54:
655 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr2_a54g54);
656 		break;
657 	case BCM47XX_BOARD_BUFFALO_WHR_G125:
658 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr_g125);
659 		break;
660 	case BCM47XX_BOARD_BUFFALO_WHR_G54S:
661 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr_g54s);
662 		break;
663 	case BCM47XX_BOARD_BUFFALO_WHR_HP_G54:
664 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr_hp_g54);
665 		break;
666 	case BCM47XX_BOARD_BUFFALO_WZR_G300N:
667 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_wzr_g300n);
668 		break;
669 	case BCM47XX_BOARD_BUFFALO_WZR_RS_G54:
670 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54);
671 		break;
672 	case BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP:
673 		err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54hp);
674 		break;
675 
676 	case BCM47XX_BOARD_DELL_TM2300:
677 		err = bcm47xx_add_bdata(bcm47xx_buttons_dell_tm2300);
678 		break;
679 
680 	case BCM47XX_BOARD_DLINK_DIR130:
681 		err = bcm47xx_add_bdata(bcm47xx_buttons_dlink_dir130);
682 		break;
683 	case BCM47XX_BOARD_DLINK_DIR330:
684 		err = bcm47xx_add_bdata(bcm47xx_buttons_dlink_dir330);
685 		break;
686 
687 	case BCM47XX_BOARD_HUAWEI_E970:
688 		err = bcm47xx_add_bdata(bcm47xx_buttons_huawei_e970);
689 		break;
690 
691 	case BCM47XX_BOARD_LINKSYS_E1000V1:
692 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e1000v1);
693 		break;
694 	case BCM47XX_BOARD_LINKSYS_E1000V21:
695 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e1000v21);
696 		break;
697 	case BCM47XX_BOARD_LINKSYS_E2000V1:
698 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e2000v1);
699 		break;
700 	case BCM47XX_BOARD_LINKSYS_E2500V3:
701 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e2500v3);
702 		break;
703 	case BCM47XX_BOARD_LINKSYS_E3000V1:
704 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e3000v1);
705 		break;
706 	case BCM47XX_BOARD_LINKSYS_E3200V1:
707 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e3200v1);
708 		break;
709 	case BCM47XX_BOARD_LINKSYS_E4200V1:
710 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e4200v1);
711 		break;
712 	case BCM47XX_BOARD_LINKSYS_WRT150NV1:
713 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt150nv1);
714 		break;
715 	case BCM47XX_BOARD_LINKSYS_WRT150NV11:
716 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt150nv11);
717 		break;
718 	case BCM47XX_BOARD_LINKSYS_WRT160NV1:
719 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt160nv1);
720 		break;
721 	case BCM47XX_BOARD_LINKSYS_WRT160NV3:
722 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt160nv3);
723 		break;
724 	case BCM47XX_BOARD_LINKSYS_WRT300N_V1:
725 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt300n_v1);
726 		break;
727 	case BCM47XX_BOARD_LINKSYS_WRT300NV11:
728 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt300nv11);
729 		break;
730 	case BCM47XX_BOARD_LINKSYS_WRT310NV1:
731 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt310nv1);
732 		break;
733 	case BCM47XX_BOARD_LINKSYS_WRT310NV2:
734 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt310n_v2);
735 		break;
736 	case BCM47XX_BOARD_LINKSYS_WRT320N_V1:
737 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt320n_v1);
738 		break;
739 	case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
740 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
741 		break;
742 	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
743 	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
744 	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
745 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
746 		break;
747 	case BCM47XX_BOARD_LINKSYS_WRT610NV1:
748 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt610nv1);
749 		break;
750 	case BCM47XX_BOARD_LINKSYS_WRT610NV2:
751 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt610nv2);
752 		break;
753 	case BCM47XX_BOARD_LINKSYS_WRTSL54GS:
754 		err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
755 		break;
756 
757 	case BCM47XX_BOARD_LUXUL_ABR_4400_V1:
758 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_abr_4400_v1);
759 		break;
760 	case BCM47XX_BOARD_LUXUL_XAP_310_V1:
761 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_310_v1);
762 		break;
763 	case BCM47XX_BOARD_LUXUL_XAP_1210_V1:
764 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1210_v1);
765 		break;
766 	case BCM47XX_BOARD_LUXUL_XAP_1230_V1:
767 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1230_v1);
768 		break;
769 	case BCM47XX_BOARD_LUXUL_XAP_1240_V1:
770 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1240_v1);
771 		break;
772 	case BCM47XX_BOARD_LUXUL_XAP_1500_V1:
773 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1500_v1);
774 		break;
775 	case BCM47XX_BOARD_LUXUL_XBR_4400_V1:
776 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xbr_4400_v1);
777 		break;
778 	case BCM47XX_BOARD_LUXUL_XVW_P30_V1:
779 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xvw_p30_v1);
780 		break;
781 	case BCM47XX_BOARD_LUXUL_XWR_600_V1:
782 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xwr_600_v1);
783 		break;
784 	case BCM47XX_BOARD_LUXUL_XWR_1750_V1:
785 		err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xwr_1750_v1);
786 		break;
787 
788 	case BCM47XX_BOARD_MICROSOFT_MN700:
789 		err = bcm47xx_add_bdata(bcm47xx_buttons_microsoft_nm700);
790 		break;
791 
792 	case BCM47XX_BOARD_MOTOROLA_WE800G:
793 		err = bcm47xx_add_bdata(bcm47xx_buttons_motorola_we800g);
794 		break;
795 	case BCM47XX_BOARD_MOTOROLA_WR850GP:
796 		err = bcm47xx_add_bdata(bcm47xx_buttons_motorola_wr850gp);
797 		break;
798 	case BCM47XX_BOARD_MOTOROLA_WR850GV2V3:
799 		err = bcm47xx_add_bdata(bcm47xx_buttons_motorola_wr850gv2v3);
800 		break;
801 
802 	case BCM47XX_BOARD_NETGEAR_R6200_V1:
803 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_r6200_v1);
804 		break;
805 	case BCM47XX_BOARD_NETGEAR_R6300_V1:
806 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_r6300_v1);
807 		break;
808 	case BCM47XX_BOARD_NETGEAR_WN2500RP_V1:
809 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wn2500rp_v1);
810 		break;
811 	case BCM47XX_BOARD_NETGEAR_WNDR3400V1:
812 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr3400v1);
813 		break;
814 	case BCM47XX_BOARD_NETGEAR_WNDR3400_V3:
815 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr3400_v3);
816 		break;
817 	case BCM47XX_BOARD_NETGEAR_WNDR3700V3:
818 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr3700v3);
819 		break;
820 	case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
821 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr4500v1);
822 		break;
823 	case BCM47XX_BOARD_NETGEAR_WNR1000_V3:
824 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr1000_v3);
825 		break;
826 	case BCM47XX_BOARD_NETGEAR_WNR3500L:
827 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
828 		break;
829 	case BCM47XX_BOARD_NETGEAR_WNR3500L_V2:
830 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr3500lv2);
831 		break;
832 	case BCM47XX_BOARD_NETGEAR_WNR834BV2:
833 		err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr834bv2);
834 		break;
835 
836 	case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE:
837 		err = bcm47xx_add_bdata(bcm47xx_buttons_simpletech_simpleshare);
838 		break;
839 
840 	default:
841 		pr_debug("No buttons configuration found for this device\n");
842 		return -ENOTSUPP;
843 	}
844 
845 	if (err)
846 		return err;
847 
848 	return 0;
849 }
850