MIPS: BCM47XX: Prepare support for GPIO buttons
authorRafał Miłecki <zajec5@gmail.com>
Tue, 14 Jan 2014 11:36:29 +0000 (12:36 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 24 Jan 2014 21:39:51 +0000 (22:39 +0100)
So far this adds support for one Netgear model only, but it's designed
and ready to add many more device. We could hopefully import database
from OpenWrt.
Support for SSB is currently disabled, because SSB doesn't implement IRQ
domain yet.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/6300/

arch/mips/bcm47xx/Makefile
arch/mips/bcm47xx/bcm47xx_private.h
arch/mips/bcm47xx/buttons.c [new file with mode: 0644]
arch/mips/bcm47xx/setup.c

index 84e9aed25027698d3fc199aaf76c8ef18ab0b8b5..006a05e4cf6dd3a3e9a12e2f88d2d72036dcb54c 100644 (file)
@@ -4,5 +4,5 @@
 #
 
 obj-y                          += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
-obj-y                          += board.o leds.o
+obj-y                          += board.o buttons.o leds.o
 obj-$(CONFIG_BCM47XX_SSB)      += wgt634u.o
index 1a1e600b74e6e5d6e0dcfaf3d4087f9fb6a02a0f..5c94acebf76a7223a5cda0e640ac36ed796f0279 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <linux/kernel.h>
 
+/* buttons.c */
+int __init bcm47xx_buttons_register(void);
+
 /* leds.c */
 void __init bcm47xx_leds_register(void);
 
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
new file mode 100644 (file)
index 0000000..d93711b
--- /dev/null
@@ -0,0 +1,95 @@
+#include "bcm47xx_private.h"
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/interrupt.h>
+#include <linux/ssb/ssb_embedded.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx.h>
+
+/**************************************************
+ * Database
+ **************************************************/
+
+static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wndr4500_v1[] __initconst = {
+       {
+               .code           = KEY_WPS_BUTTON,
+               .gpio           = 4,
+               .active_low     = 1,
+       },
+       {
+               .code           = KEY_RFKILL,
+               .gpio           = 5,
+               .active_low     = 1,
+       },
+       {
+               .code           = KEY_RESTART,
+               .gpio           = 6,
+               .active_low     = 1,
+       },
+};
+
+/**************************************************
+ * Init
+ **************************************************/
+
+static struct gpio_keys_platform_data bcm47xx_button_pdata;
+
+static struct platform_device bcm47xx_buttons_gpio_keys = {
+       .name = "gpio-keys",
+       .dev = {
+               .platform_data = &bcm47xx_button_pdata,
+       }
+};
+
+/* Copy data from __initconst */
+static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons,
+                                      size_t nbuttons)
+{
+       size_t size = nbuttons * sizeof(*buttons);
+
+       bcm47xx_button_pdata.buttons = kmalloc(size, GFP_KERNEL);
+       if (!bcm47xx_button_pdata.buttons)
+               return -ENOMEM;
+       memcpy(bcm47xx_button_pdata.buttons, buttons, size);
+       bcm47xx_button_pdata.nbuttons = nbuttons;
+
+       return 0;
+}
+
+#define bcm47xx_copy_bdata(dev_buttons)                                        \
+       bcm47xx_buttons_copy(dev_buttons, ARRAY_SIZE(dev_buttons));
+
+int __init bcm47xx_buttons_register(void)
+{
+       enum bcm47xx_board board = bcm47xx_board_get();
+       int err;
+
+#ifdef CONFIG_BCM47XX_SSB
+       if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB) {
+               pr_debug("Buttons on SSB are not supported yet.\n");
+               return -ENOTSUPP;
+       }
+#endif
+
+       switch (board) {
+       case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
+               err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500_v1);
+               break;
+       default:
+               pr_debug("No buttons configuration found for this device\n");
+               return -ENOTSUPP;
+       }
+
+       if (err)
+               return -ENOMEM;
+
+       err = platform_device_register(&bcm47xx_buttons_gpio_keys);
+       if (err) {
+               pr_err("Failed to register platform device: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
index 91166967f8f7fd51def5169c228231a1fa7fd176..2d6e7cccae6bd8685b1c33e50ef2ac5a4bbce1a1 100644 (file)
@@ -255,6 +255,7 @@ static int __init bcm47xx_register_bus_complete(void)
                break;
 #endif
        }
+       bcm47xx_buttons_register();
        bcm47xx_leds_register();
 
        return 0;