From ef654d161766c13e002f2bf738007ccf44d84749 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 11 Feb 2012 21:49:38 +0800 Subject: [PATCH 1/4] add gpio keyboard support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/input/Kconfig | 19 +++++++ drivers/input/Makefile | 1 + drivers/input/gpio_keys.c | 115 ++++++++++++++++++++++++++++++++++++++ include/driver.h | 5 ++ include/gpio_keys.h | 30 ++++++++++ 7 files changed, 172 insertions(+) create mode 100644 drivers/input/Kconfig create mode 100644 drivers/input/Makefile create mode 100644 drivers/input/gpio_keys.c create mode 100644 include/gpio_keys.h diff --git a/drivers/Kconfig b/drivers/Kconfig index c4e1517ca..c058b2599 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -14,5 +14,6 @@ source "drivers/clk/Kconfig" source "drivers/mfd/Kconfig" source "drivers/led/Kconfig" source "drivers/eeprom/Kconfig" +source "drivers/input/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 592c39e6d..61e85afaf 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -13,3 +13,4 @@ obj-y += clk/ obj-y += mfd/ obj-$(CONFIG_LED) += led/ obj-y += eeprom/ +obj-y += input/ diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig new file mode 100644 index 000000000..b48855368 --- /dev/null +++ b/drivers/input/Kconfig @@ -0,0 +1,19 @@ +# +# Input device configuration +# + +menu "Input device support" + +config KEYBOARD_GPIO + bool "GPIO Buttons" + depends on GENERIC_GPIO + help + This driver implements support for buttons connected + to GPIO pins of various CPUs (and some other chips). + + Say Y here if your device has buttons connected + directly to such GPIO pins. Your board-specific + setup logic must also provide a platform device, + with configuration data saying which GPIOs are used. + +endmenu diff --git a/drivers/input/Makefile b/drivers/input/Makefile new file mode 100644 index 000000000..7784d522a --- /dev/null +++ b/drivers/input/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o diff --git a/drivers/input/gpio_keys.c b/drivers/input/gpio_keys.c new file mode 100644 index 000000000..4d0f6ab2e --- /dev/null +++ b/drivers/input/gpio_keys.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD + * + * Under GPLv2 + */ + +#include +#include +#include +#include +#include +#include +#include + +static inline struct gpio_keys_platform_data * +poller_to_gk_pdata(struct poller_struct *poller) +{ + return container_of(poller, struct gpio_keys_platform_data, poller); +} + +static inline struct gpio_keys_platform_data * +cdev_to_gk_pdata(struct console_device *cdev) +{ + return container_of(cdev, struct gpio_keys_platform_data, cdev); +} + +static void gpio_key_poller(struct poller_struct *poller) +{ + struct gpio_keys_platform_data *pdata = poller_to_gk_pdata(poller); + struct gpio_keys_button *gb; + int i, val; + + for (i = 0; i < pdata->nbuttons; i++) { + + gb = &pdata->buttons[i]; + val = gpio_get_value(gb->gpio); + + if (val != gb->previous_state && val != gb->active_low) { + kfifo_put(pdata->recv_fifo, (u_char*)&gb->code, sizeof(int)); + debug("pressed gpio(%d) as %d\n", gb->gpio, gb->code); + } + gb->previous_state = val; + } +} + +static int gpio_keys_tstc(struct console_device *cdev) +{ + struct gpio_keys_platform_data *pdata = cdev_to_gk_pdata(cdev); + + return (kfifo_len(pdata->recv_fifo) == 0) ? 0 : 1; +} + +static int gpio_keys_getc(struct console_device *cdev) +{ + int code = 0; + struct gpio_keys_platform_data *pdata = cdev_to_gk_pdata(cdev); + + kfifo_get(pdata->recv_fifo, (u_char*)&code, sizeof(int)); + return code; +} + +static int __init gpio_keys_probe(struct device_d *dev) +{ + int ret, i, gpio; + struct gpio_keys_platform_data *pdata; + struct console_device *cdev; + + pdata = dev->platform_data; + + if (!pdata) { + /* small (so we copy it) but critical! */ + pr_err("missing platform_data\n"); + return -ENODEV; + } + + if (!pdata->fifo_size) + pdata->fifo_size = 50; + + pdata->recv_fifo = kfifo_alloc(pdata->fifo_size); + + for (i = 0; i < pdata->nbuttons; i++) { + gpio = pdata->buttons->gpio; + ret = gpio_request(gpio, "gpio_keys"); + if (ret) { + pr_err("gpio_keys: (%d) can not be requested\n", gpio); + return ret; + } + gpio_direction_input(gpio); + } + + pdata->poller.func = gpio_key_poller; + + cdev = &pdata->cdev; + dev->type_data = cdev; + cdev->dev = dev; + cdev->f_caps = CONSOLE_STDIN; + cdev->tstc = gpio_keys_tstc; + cdev->getc = gpio_keys_getc; + + console_register(&pdata->cdev); + + return poller_register(&pdata->poller); +} + +static struct driver_d gpio_keys_driver = { + .name = "gpio_keys", + .probe = gpio_keys_probe, +}; + +static int gpio_keys_init(void) +{ + register_driver(&gpio_keys_driver); + return 0; +} +device_initcall(gpio_keys_init); diff --git a/include/driver.h b/include/driver.h index 1b8b16dd1..51d63936c 100644 --- a/include/driver.h +++ b/include/driver.h @@ -260,6 +260,11 @@ static inline struct device_d *add_generic_usb_ehci_device(int id, return add_usb_ehci_device(id, base + 0x100, base + 0x140, pdata); } +static inline struct device_d *add_gpio_keys_device(int id, void *pdata) +{ + return add_generic_device_res("gpio_keys", id, 0, 0, pdata); +} + /* linear list over all available devices */ extern struct list_head device_list; diff --git a/include/gpio_keys.h b/include/gpio_keys.h new file mode 100644 index 000000000..fc548fabc --- /dev/null +++ b/include/gpio_keys.h @@ -0,0 +1,30 @@ +#ifndef _GPIO_KEYS_H +#define _GPIO_KEYS_H + +#include +#include + +struct gpio_keys_button { + /* Configuration parameters */ + int code; + + int gpio; + int active_low; + + /* internal */ + int previous_state; +}; + +struct gpio_keys_platform_data { + struct gpio_keys_button *buttons; + int nbuttons; + + /* optional */ + int fifo_size; + + struct kfifo *recv_fifo; + struct poller_struct poller; + struct console_device cdev; +}; + +#endif From 1f22d10f1570ccf83a842886ff016e9781dfed3e Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 13 Feb 2012 01:59:21 +0800 Subject: [PATCH 2/4] readkey: add define for Ascii keys this will simplify the usage of gpio keyboard Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- common/menu.c | 6 +++--- include/readkey.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/common/menu.c b/common/menu.c index 5291fcb15..fd21e52a3 100644 --- a/common/menu.c +++ b/common/menu.c @@ -296,7 +296,7 @@ int menu_show(struct menu *m) do { if (m->auto_select >= 0) - ch = '\n'; + ch = KEY_ENTER; else ch = getc(); @@ -339,8 +339,8 @@ int menu_show(struct menu *m) m->selected->action(m, m->selected); print_menu_entry(m, m->selected, 1); break; - case '\n': - case '\r': + case KEY_ENTER: + case KEY_RETURN: clear(); gotoXY(1,1); m->selected->action(m, m->selected); diff --git a/include/readkey.h b/include/readkey.h index aabb835e8..f134846af 100644 --- a/include/readkey.h +++ b/include/readkey.h @@ -3,6 +3,10 @@ #define CTL_CH(c) ((c) - 'a' + 1) +/* Ascii keys */ +#define KEY_ENTER '\n' +#define KEY_RETURN '\r' + /* Misc. non-Ascii keys */ #define KEY_UP CTL_CH('p') /* cursor key Up */ #define KEY_DOWN CTL_CH('n') /* cursor key Down */ From 77a8d36b902f4f83add3332b6058997dd37fa403 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 12 Feb 2012 00:35:05 +0800 Subject: [PATCH 3/4] at91: at91_register_uart return device this will allow to set the active parameter from C Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/mach-at91/at91rm9200_devices.c | 6 +++--- arch/arm/mach-at91/at91sam9260_devices.c | 6 +++--- arch/arm/mach-at91/at91sam9261_devices.c | 6 +++--- arch/arm/mach-at91/at91sam9263_devices.c | 6 +++--- arch/arm/mach-at91/at91sam9g45_devices.c | 6 +++--- arch/arm/mach-at91/include/mach/board.h | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 599eb79ee..bda73e604 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -265,7 +265,7 @@ static inline void configure_usart3_pins(unsigned pins) at91_set_B_periph(AT91_PIN_PB0, 0); /* RTS3 */ } -void __init at91_register_uart(unsigned id, unsigned pins) +struct device_d * __init at91_register_uart(unsigned id, unsigned pins) { resource_size_t start; @@ -296,9 +296,9 @@ void __init at91_register_uart(unsigned id, unsigned pins) id = 4; break; default: - return; + return NULL; } - add_generic_device("atmel_usart", id, NULL, start, 4096, + return add_generic_device("atmel_usart", id, NULL, start, 4096, IORESOURCE_MEM, NULL); } diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 3ddd0cfd9..3bdcd4f40 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -282,7 +282,7 @@ static inline void configure_usart5_pins(void) at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */ } -void at91_register_uart(unsigned id, unsigned pins) +struct device_d * __init at91_register_uart(unsigned id, unsigned pins) { resource_size_t start; @@ -323,10 +323,10 @@ void at91_register_uart(unsigned id, unsigned pins) id = 6; break; default: - return; + return NULL; } - add_generic_device("atmel_usart", id, NULL, start, 4096, + return add_generic_device("atmel_usart", id, NULL, start, 4096, IORESOURCE_MEM, NULL); } diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 7805c27b0..d4f7b5eff 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -203,7 +203,7 @@ static inline void configure_usart2_pins(unsigned pins) at91_set_B_periph(AT91_PIN_PA16, 0); /* CTS2 */ } -void at91_register_uart(unsigned id, unsigned pins) +struct device_d * __init at91_register_uart(unsigned id, unsigned pins) { resource_size_t start; @@ -229,10 +229,10 @@ void at91_register_uart(unsigned id, unsigned pins) id = 3; break; default: - return; + return NULL; } - add_generic_device("atmel_usart", id, NULL, start, 4096, + return add_generic_device("atmel_usart", id, NULL, start, 4096, IORESOURCE_MEM, NULL); } diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index fc7dc1432..87a1726d3 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -253,7 +253,7 @@ static inline void configure_usart2_pins(unsigned pins) at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ } -void at91_register_uart(unsigned id, unsigned pins) +struct device_d * __init at91_register_uart(unsigned id, unsigned pins) { resource_size_t start; @@ -279,10 +279,10 @@ void at91_register_uart(unsigned id, unsigned pins) id = 3; break; default: - return; + return NULL; } - add_generic_device("atmel_usart", id, NULL, start, 4096, + return add_generic_device("atmel_usart", id, NULL, start, 4096, IORESOURCE_MEM, NULL); } diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index bb252bdd4..6931a3f65 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -182,7 +182,7 @@ static inline void configure_usart3_pins(unsigned pins) at91_set_B_periph(AT91_PIN_PA24, 0); /* CTS3 */ } -void at91_register_uart(unsigned id, unsigned pins) +struct device_d * __init at91_register_uart(unsigned id, unsigned pins) { resource_size_t start; @@ -213,10 +213,10 @@ void at91_register_uart(unsigned id, unsigned pins) id = 4; break; default: - return; + return NULL; } - add_generic_device("atmel_usart", id, NULL, start, 4096, + return add_generic_device("atmel_usart", id, NULL, start, 4096, IORESOURCE_MEM, NULL); } diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 755ddc886..9f1abc134 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -83,7 +83,7 @@ void at91_add_device_sdram(u32 size); #define ATMEL_UART_DCD 0x10 #define ATMEL_UART_RI 0x20 -void at91_register_uart(unsigned id, unsigned pins); +struct device_d * __init at91_register_uart(unsigned id, unsigned pins); /* Multimedia Card Interface */ struct atmel_mci_platform_data { From 4f7b18e937ee3862e5b4b6ae0aea514b6caa0196 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 12 Feb 2012 00:35:05 +0800 Subject: [PATCH 4/4] usb-a926x: add DAB MMX Daughter board support - gpio_keys support - leds - uarts 2 and 4 (for oled) Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/boards/usb-a926x/init.c | 108 +++++++++++++++++++++++++++++++ arch/arm/mach-at91/Kconfig | 9 +++ 2 files changed, 117 insertions(+) diff --git a/arch/arm/boards/usb-a926x/init.c b/arch/arm/boards/usb-a926x/init.c index 364c1ba95..af025b414 100644 --- a/arch/arm/boards/usb-a926x/init.c +++ b/arch/arm/boards/usb-a926x/init.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include static void usb_a9260_set_board_type(void) { @@ -219,6 +221,101 @@ static void __init ek_add_device_button(void) export_env_ull("dfu_button", AT91_PIN_PB10); } +#ifdef CONFIG_CALAO_DAB_MMX +struct gpio_led dab_mmx_leds[] = { + { + .gpio = AT91_PIN_PB20, + .led = { + .name = "user_led1", + }, + }, { + .gpio = AT91_PIN_PB21, + .led = { + .name = "user_led2", + }, + }, { + .gpio = AT91_PIN_PB22, + .led = { + .name = "user_led3", + }, + }, { + .gpio = AT91_PIN_PB23, + .led = { + .name = "user_led4", + }, + }, { + .gpio = AT91_PIN_PB24, + .led = { + .name = "red", + }, + }, { + .gpio = AT91_PIN_PB30, + .led = { + .name = "orange", + }, + }, { + .gpio = AT91_PIN_PB31, + .led = { + .name = "green", + }, + }, +}; + +#ifdef CONFIG_KEYBOARD_GPIO +struct gpio_keys_button keys[] = { + { + .code = KEY_UP, + .gpio = AT91_PIN_PB25, + }, { + .code = KEY_HOME, + .gpio = AT91_PIN_PB13, + }, { + .code = KEY_DOWN, + .gpio = AT91_PIN_PA26, + }, { + .code = KEY_ENTER, + .gpio = AT91_PIN_PC9, + }, +}; + +struct gpio_keys_platform_data gk_pdata = { + .buttons = keys, + .nbuttons = ARRAY_SIZE(keys), +}; + +static void usb_a9260_keyboard_device_dab_mmx(void) +{ + int i; + + for (i = 0; i < gk_pdata.nbuttons; i++) { + /* user push button, pull up enabled */ + keys[i].active_low = 1; + at91_set_GPIO_periph(keys[i].gpio, keys[i].active_low); + at91_set_deglitch(keys[i].gpio, 1); + } + + add_gpio_keys_device(-1, &gk_pdata); +} +#else +static void usb_a9260_keyboard_device_dab_mmx(void) {} +#endif + +static void usb_a9260_device_dab_mmx(void) +{ + int i; + + usb_a9260_keyboard_device_dab_mmx(); + + for (i = 0; i < ARRAY_SIZE(dab_mmx_leds); i++) { + dab_mmx_leds[i].active_low = 1; + at91_set_gpio_output(dab_mmx_leds[i].gpio, dab_mmx_leds[i].active_low); + led_gpio_register(&dab_mmx_leds[i]); + } +} +#else +static void usb_a9260_device_dab_mmx(void) {} +#endif + static int usb_a9260_devices_init(void) { usb_a9260_add_device_nand(); @@ -229,6 +326,7 @@ static int usb_a9260_devices_init(void) ek_add_device_udc(); ek_add_led(); ek_add_device_button(); + usb_a9260_device_dab_mmx(); armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100)); usb_a9260_set_board_type(); @@ -248,7 +346,17 @@ device_initcall(usb_a9260_devices_init); static int usb_a9260_console_init(void) { + struct device_d *dev; + at91_register_uart(0, 0); + + if (IS_ENABLED(CONFIG_CALAO_DAB_MMX)) { + at91_register_uart(2, 0); + + dev = at91_register_uart(4, 0); + dev_set_param(dev, "active", ""); + } + return 0; } console_initcall(usb_a9260_console_init); diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 41e9b9970..d2bb7bc8a 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -93,6 +93,9 @@ config ARCH_BAREBOX_MAX_BARE_INIT_SIZE default 0xF000 if ARCH_AT91SAM9G45 default 0xffffffff +config SUPPORT_CALAO_DAB_MMX + bool + # ---------------------------------------------------------- if ARCH_AT91RM9200 @@ -133,6 +136,7 @@ config MACH_TNY_A9260 config MACH_USB_A9260 bool "CALAO USB-A9260" + select SUPPORT_CALAO_DAB_MMX help Select this if you are using a Calao Systems USB-A9260. @@ -209,6 +213,7 @@ config MACH_TNY_A9G20 config MACH_USB_A9G20 bool "CALAO USB-A9G20" + select SUPPORT_CALAO_DAB_MMX help Select this if you are using a Calao Systems USB-A9G20. @@ -328,4 +333,8 @@ config LCD_LG_LB043WQ1 endchoice +config CALAO_DAB_MMX + bool "DAB MMX Daughter Board support" + depends on SUPPORT_CALAO_DAB_MMX + endif