brcm47xx: add new led and button support
[openwrt.git] / target / linux / brcm47xx / patches-3.10 / 121-MIPS-BCM47XX-Prepare-support-for-GPIO-buttons.patch
1 From e352ec3c581df40f159771b30c262c2bc7fb802e Mon Sep 17 00:00:00 2001
2 From: Rafa? Mi?ecki <zajec5@gmail.com>
3 Date: Thu, 2 Jan 2014 13:31:32 +0100
4 Subject: [PATCH 030/110] MIPS: BCM47XX: Prepare support for GPIO buttons
5
6 So far this adds support for one Netgear model only, but it's designed
7 and ready to add many more device. We could hopefully import database
8 from OpenWrt.
9 Support for SSB is currently disabled, because SSB doesn't implement IRQ
10 domain yet.
11
12 Signed-off-by: Rafa? Mi?ecki <zajec5@gmail.com>
13 Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
14 Acked-by: John Crispin <blogic@openwrt.org>
15 Patchwork: http://patchwork.linux-mips.org/patch/6300/
16 ---
17  arch/mips/bcm47xx/Makefile          |    2 +-
18  arch/mips/bcm47xx/bcm47xx_private.h |    3 ++
19  arch/mips/bcm47xx/buttons.c         |   95 +++++++++++++++++++++++++++++++++++
20  arch/mips/bcm47xx/setup.c           |    1 +
21  4 files changed, 100 insertions(+), 1 deletion(-)
22  create mode 100644 arch/mips/bcm47xx/buttons.c
23
24 --- a/arch/mips/bcm47xx/Makefile
25 +++ b/arch/mips/bcm47xx/Makefile
26 @@ -4,5 +4,5 @@
27  #
28  
29  obj-y                          += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
30 -obj-y                          += board.o leds.o
31 +obj-y                          += board.o buttons.o leds.o
32  obj-$(CONFIG_BCM47XX_SSB)      += wgt634u.o
33 --- a/arch/mips/bcm47xx/bcm47xx_private.h
34 +++ b/arch/mips/bcm47xx/bcm47xx_private.h
35 @@ -3,6 +3,9 @@
36  
37  #include <linux/kernel.h>
38  
39 +/* buttons.c */
40 +int __init bcm47xx_buttons_register(void);
41 +
42  /* leds.c */
43  void __init bcm47xx_leds_register(void);
44  
45 --- /dev/null
46 +++ b/arch/mips/bcm47xx/buttons.c
47 @@ -0,0 +1,95 @@
48 +#include "bcm47xx_private.h"
49 +
50 +#include <linux/input.h>
51 +#include <linux/gpio_keys.h>
52 +#include <linux/interrupt.h>
53 +#include <linux/ssb/ssb_embedded.h>
54 +#include <bcm47xx_board.h>
55 +#include <bcm47xx.h>
56 +
57 +/**************************************************
58 + * Database
59 + **************************************************/
60 +
61 +static const struct gpio_keys_button
62 +bcm47xx_buttons_netgear_wndr4500_v1[] __initconst = {
63 +       {
64 +               .code           = KEY_WPS_BUTTON,
65 +               .gpio           = 4,
66 +               .active_low     = 1,
67 +       },
68 +       {
69 +               .code           = KEY_RFKILL,
70 +               .gpio           = 5,
71 +               .active_low     = 1,
72 +       },
73 +       {
74 +               .code           = KEY_RESTART,
75 +               .gpio           = 6,
76 +               .active_low     = 1,
77 +       },
78 +};
79 +
80 +/**************************************************
81 + * Init
82 + **************************************************/
83 +
84 +static struct gpio_keys_platform_data bcm47xx_button_pdata;
85 +
86 +static struct platform_device bcm47xx_buttons_gpio_keys = {
87 +       .name = "gpio-keys",
88 +       .dev = {
89 +               .platform_data = &bcm47xx_button_pdata,
90 +       }
91 +};
92 +
93 +/* Copy data from __initconst */
94 +static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons,
95 +                                      size_t nbuttons)
96 +{
97 +       size_t size = nbuttons * sizeof(*buttons);
98 +
99 +       bcm47xx_button_pdata.buttons = kmalloc(size, GFP_KERNEL);
100 +       if (!bcm47xx_button_pdata.buttons)
101 +               return -ENOMEM;
102 +       memcpy(bcm47xx_button_pdata.buttons, buttons, size);
103 +       bcm47xx_button_pdata.nbuttons = nbuttons;
104 +
105 +       return 0;
106 +}
107 +
108 +#define bcm47xx_copy_bdata(dev_buttons)                                        \
109 +       bcm47xx_buttons_copy(dev_buttons, ARRAY_SIZE(dev_buttons));
110 +
111 +int __init bcm47xx_buttons_register(void)
112 +{
113 +       enum bcm47xx_board board = bcm47xx_board_get();
114 +       int err;
115 +
116 +#ifdef CONFIG_BCM47XX_SSB
117 +       if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB) {
118 +               pr_debug("Buttons on SSB are not supported yet.\n");
119 +               return -ENOTSUPP;
120 +       }
121 +#endif
122 +
123 +       switch (board) {
124 +       case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
125 +               err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500_v1);
126 +               break;
127 +       default:
128 +               pr_debug("No buttons configuration found for this device\n");
129 +               return -ENOTSUPP;
130 +       }
131 +
132 +       if (err)
133 +               return -ENOMEM;
134 +
135 +       err = platform_device_register(&bcm47xx_buttons_gpio_keys);
136 +       if (err) {
137 +               pr_err("Failed to register platform device: %d\n", err);
138 +               return err;
139 +       }
140 +
141 +       return 0;
142 +}
143 --- a/arch/mips/bcm47xx/setup.c
144 +++ b/arch/mips/bcm47xx/setup.c
145 @@ -246,6 +246,7 @@ static int __init bcm47xx_register_bus_c
146  #endif
147         }
148  
149 +       bcm47xx_buttons_register();
150         bcm47xx_leds_register();
151  
152         return 0;