On 12/10/2013 04:24 PM, Rafał Miłecki wrote: > 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@xxxxxxxxx> Acked-by: Hauke Mehrtens <hauke@xxxxxxxxxx> > --- > V3: Use __initconst and copy data for detected device. This will allow > us to free some memory after init. > --- > arch/mips/bcm47xx/Makefile | 2 +- > arch/mips/bcm47xx/bcm47xx_private.h | 3 ++ > arch/mips/bcm47xx/buttons.c | 95 +++++++++++++++++++++++++++++++++++ > arch/mips/bcm47xx/setup.c | 1 + > 4 files changed, 100 insertions(+), 1 deletion(-) > create mode 100644 arch/mips/bcm47xx/buttons.c > > diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile > index 84e9aed..006a05e 100644 > --- a/arch/mips/bcm47xx/Makefile > +++ b/arch/mips/bcm47xx/Makefile > @@ -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 > diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h > index 1a1e600..5c94ace 100644 > --- a/arch/mips/bcm47xx/bcm47xx_private.h > +++ b/arch/mips/bcm47xx/bcm47xx_private.h > @@ -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 > index 0000000..3138f03 > --- /dev/null > +++ b/arch/mips/bcm47xx/buttons.c > @@ -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 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(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; > +} > diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c > index 7e61c0b..a791124 100644 > --- a/arch/mips/bcm47xx/setup.c > +++ b/arch/mips/bcm47xx/setup.c > @@ -242,6 +242,7 @@ static int __init bcm47xx_register_bus_complete(void) > #endif > } > > + bcm47xx_buttons_register(); > bcm47xx_leds_register(); > > return 0; >