* [U-Boot] [PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00
@ 2013-07-19 8:47 Andrey Danin
2013-07-19 8:47 ` [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver Andrey Danin
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Andrey Danin @ 2013-07-19 8:47 UTC (permalink / raw)
To: u-boot
This patch series introduces keyboard support for AC100 (board paz00).
NVEC code is based on linux kernel driver. Keytable header file is
copied from linux kernel (with small style modifications).
NVEC initialization is implemented on later stage because early
initialization fails for unknown reason.
Based on u-boot-tegra/next.
Andrey Danin (3):
ARM: tegra: add nvec driver
ARM: tegra: add input driver for nvec keyboard
ARM: tegra: paz00: enable nvec keyboard support
arch/arm/include/asm/arch-tegra/tegra_nvec.h | 117 +++++
.../arm/include/asm/arch-tegra/tegra_nvec_events.h | 31 ++
.../include/asm/arch-tegra/tegra_nvec_keyboard.h | 36 ++
.../include/asm/arch-tegra/tegra_nvec_keytable.h | 313 +++++++++++++
board/compal/dts/tegra20-paz00.dts | 8 +
board/nvidia/common/board.c | 12 +
drivers/i2c/Makefile | 1 +
drivers/i2c/tegra_nvec.c | 462 ++++++++++++++++++++
drivers/i2c/tegra_nvec_keyboard.c | 108 +++++
drivers/input/Makefile | 1 +
drivers/input/tegra-nvec-kbc.c | 131 ++++++
include/configs/paz00.h | 8 +
include/configs/tegra-common-post.h | 2 +
include/fdtdec.h | 1 +
lib/Makefile | 1 +
lib/fdtdec.c | 1 +
16 files changed, 1233 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec.h
create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_events.h
create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h
create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h
create mode 100644 drivers/i2c/tegra_nvec.c
create mode 100644 drivers/i2c/tegra_nvec_keyboard.c
create mode 100644 drivers/input/tegra-nvec-kbc.c
^ permalink raw reply [flat|nested] 12+ messages in thread* [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver 2013-07-19 8:47 [U-Boot] [PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00 Andrey Danin @ 2013-07-19 8:47 ` Andrey Danin 2013-07-19 16:28 ` Tom Warren 2013-07-19 8:47 ` [U-Boot] [PATCH 2/3] ARM: tegra: add input driver for nvec keyboard Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 3/3] ARM: tegra: paz00: enable nvec keyboard support Andrey Danin 2 siblings, 1 reply; 12+ messages in thread From: Andrey Danin @ 2013-07-19 8:47 UTC (permalink / raw) To: u-boot Adopted version of nvec driver from linux kernel with keyboard support only. Signed-off-by: Andrey Danin <danindrey@mail.ru> --- arch/arm/include/asm/arch-tegra/tegra_nvec.h | 117 +++++ .../arm/include/asm/arch-tegra/tegra_nvec_events.h | 31 ++ .../include/asm/arch-tegra/tegra_nvec_keyboard.h | 36 ++ .../include/asm/arch-tegra/tegra_nvec_keytable.h | 313 +++++++++++++ board/nvidia/common/board.c | 12 + drivers/i2c/Makefile | 1 + drivers/i2c/tegra_nvec.c | 462 ++++++++++++++++++++ drivers/i2c/tegra_nvec_keyboard.c | 108 +++++ include/fdtdec.h | 1 + lib/Makefile | 1 + lib/fdtdec.c | 1 + 11 files changed, 1083 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec.h create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_events.h create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h create mode 100644 drivers/i2c/tegra_nvec.c create mode 100644 drivers/i2c/tegra_nvec_keyboard.c diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec.h b/arch/arm/include/asm/arch-tegra/tegra_nvec.h new file mode 100644 index 0000000..1c30028 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec.h @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2013 + * Andrey Danin <andreydanin@mail.ru> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _TEGRA_NVEC_H_ +#define _TEGRA_NVEC_H_ + +#define I2C_CNFG 0x00 +#define I2C_CNFG_PACKET_MODE_EN (1<<10) +#define I2C_CNFG_NEW_MASTER_SFM (1<<11) +#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12 + +#define I2C_SL_CNFG 0x20 +#define I2C_SL_NEWSL (1<<2) +#define I2C_SL_NACK (1<<1) +#define I2C_SL_RESP (1<<0) +#define I2C_SL_IRQ (1<<3) +#define END_TRANS (1<<4) +#define RCVD (1<<2) +#define RNW (1<<1) + +#define I2C_SL_RCVD 0x24 +#define I2C_SL_STATUS 0x28 +#define I2C_SL_ADDR1 0x2c +#define I2C_SL_ADDR2 0x30 +#define I2C_SL_DELAY_COUNT 0x3c + + +enum nvec_msg_type { + NVEC_KEYBOARD = 0, + NVEC_SYS = 1, + NVEC_BAT, + NVEC_GPIO, + NVEC_SLEEP, + NVEC_KBD, + NVEC_PS2, + NVEC_CNTL, + NVEC_OEM0 = 0x0d, + NVEC_KB_EVT = 0x80, + NVEC_PS2_EVT, +}; + +enum nvec_event_size { + NVEC_2BYTES, + NVEC_3BYTES, + NVEC_VAR_SIZE, +}; + +enum sys_subcmds { + SYS_GET_STATUS, + SYS_CNFG_EVENT_REPORTING, + SYS_ACK_STATUS, + SYS_CNFG_WAKE = 0xfd, +}; + +enum kbd_subcmds { + CNFG_WAKE = 3, + CNFG_WAKE_KEY_REPORTING, + SET_LEDS = 0xed, + ENABLE_KBD = 0xf4, + DISABLE_KBD, +}; + +enum cntl_subcmds { + CNTL_RESET_EC = 0x00, + CNTL_SELF_TEST = 0x01, + CNTL_NOOP = 0x02, + CNTL_GET_EC_SPEC_VER = 0x10, + CNTL_GET_FIRMWARE_VERSION = 0x15, +}; + +enum nvec_sleep_subcmds { + GLOBAL_EVENTS, + AP_PWR_DOWN, + AP_SUSPEND, +}; + +#define MOUSE_SEND_CMD 0x01 +#define MOUSE_RESET 0xff + + +int board_nvec_init(void); + +int nvec_msg_is_event(const unsigned char *msg); +int nvec_msg_event_type(const unsigned char *msg); + +/** + * Send request and read response. If write or read failed + * operation will be repeated NVEC_ATTEMPTS_MAX times. + * + * @param buf request data + * @param size request data size + * @return 0 if ok, -1 on error + */ +int nvec_do_request(char *buf, int size); + + +#endif /* _TEGRA_NVEC_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_events.h b/arch/arm/include/asm/arch-tegra/tegra_nvec_events.h new file mode 100644 index 0000000..7d65921 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_events.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2013 + * Andrey Danin <andreydanin@mail.ru> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _TEGRA_NVEC_EVENTS_H_ +#define _TEGRA_NVEC_EVENTS_H_ + + +int nvec_read_events(void); + + +#endif /* _TEGRA_NVEC_EVENTS_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h b/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h new file mode 100644 index 0000000..b25a1d8 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2013 + * Andrey Danin <andreydanin@mail.ru> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _TEGRA_NVEC_KEYBOARD_H_ +#define _TEGRA_NVEC_KEYBOARD_H_ + + +#define NVEC_KEYS_QUEUE_SIZE 256 + +void nvec_enable_kbd_events(void); +void nvec_process_keyboard_msg(const unsigned char *msg); +int nvec_pop_key(void); +int nvec_have_keys(void); + + +#endif /* _TEGRA_NVEC_KEYBOARD_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h b/arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h new file mode 100644 index 0000000..8fbf96c --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h @@ -0,0 +1,313 @@ +/* + * Keyboard class input driver for keyboards connected to an NvEc compliant + * embedded controller + * + * Copyright (c) 2009, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _TEGRA_NVEC_KEYTABLE_H_ +#define _TEGRA_NVEC_KEYTABLE_H_ + +#include <linux/input.h> + + +static unsigned short code_tab_102us[] = { + /* 0x00 */ + KEY_GRAVE, + KEY_ESC, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_0, + KEY_MINUS, + KEY_EQUAL, + KEY_BACKSPACE, + KEY_TAB, + /* 0x10 */ + KEY_Q, + KEY_W, + KEY_E, + KEY_R, + KEY_T, + KEY_Y, + KEY_U, + KEY_I, + KEY_O, + KEY_P, + KEY_LEFTBRACE, + KEY_RIGHTBRACE, + KEY_ENTER, + KEY_LEFTCTRL, + KEY_A, + KEY_S, + /* 0x20 */ + KEY_D, + KEY_F, + KEY_G, + KEY_H, + KEY_J, + KEY_K, + KEY_L, + KEY_SEMICOLON, + KEY_APOSTROPHE, + KEY_GRAVE, + KEY_LEFTSHIFT, + KEY_BACKSLASH, + KEY_Z, + KEY_X, + KEY_C, + KEY_V, + /* 0x30 */ + KEY_B, + KEY_N, + KEY_M, + KEY_COMMA, + KEY_DOT, + KEY_SLASH, + KEY_RIGHTSHIFT, + KEY_KPASTERISK, + KEY_LEFTALT, + KEY_SPACE, + KEY_CAPSLOCK, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + /* 0x40 */ + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + KEY_FN, + /* VK_SCROLL */ + 0, + KEY_KP7, + KEY_KP8, + KEY_KP9, + KEY_KPMINUS, + KEY_KP4, + KEY_KP5, + KEY_KP6, + KEY_KPPLUS, + KEY_KP1, + /* 0x50 */ + KEY_KP2, + KEY_KP3, + KEY_KP0, + KEY_KPDOT, + /* VK_SNAPSHOT */ + 0, /* KEY_MENU, */ + KEY_POWER, + /* VK_OEM_102 */ + KEY_102ND, + KEY_F11, + KEY_F12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x60 */ + 0, + 0, + 0, + 0, /* KEY_SEARCH, */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x70 */ + 0, + 0, + 0, + KEY_KP5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + KEY_KP9, +}; + +static unsigned short extcode_tab_us102[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x10 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* VK_MEDIA_NEXT_TRACK */ + 0, + 0, + 0, + /* VK_RETURN */ + 0, + KEY_RIGHTCTRL, + 0, + 0, + /* 0x20 */ + KEY_MUTE, + /* VK_LAUNCH_APP1 */ + 0, + /* VK_MEDIA_PLAY_PAUSE */ + 0, + 0, + /* VK_MEDIA_STOP */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x30 */ + KEY_VOLUMEUP, + 0, + /* VK_BROWSER_HOME */ + 0, + 0, + 0, + /* VK_DIVIDE */ + KEY_KPSLASH, + 0, + /* VK_SNAPSHOT */ + KEY_SYSRQ, + /* VK_RMENU */ + KEY_RIGHTALT, + /* VK_OEM_NV_BACKLIGHT_UP */ + 0, + /* VK_OEM_NV_BACKLIGHT_DN */ + 0, + /* VK_OEM_NV_BACKLIGHT_AUTOTOGGLE */ + 0, + /* VK_OEM_NV_POWER_INFO */ + 0, + /* VK_OEM_NV_WIFI_TOGGLE */ + 0, + /* VK_OEM_NV_DISPLAY_SELECT */ + 0, + /* VK_OEM_NV_AIRPLANE_TOGGLE */ + 0, + /* 0x40 */ + 0, + KEY_LEFT, + 0, + 0, + 0, + 0, + 0, /* KEY_CANCEL, */ + KEY_HOME, + KEY_UP, + KEY_PAGEUP, + 0, + KEY_LEFT, + 0, + KEY_RIGHT, + 0, + KEY_END, + /* 0x50 */ + KEY_DOWN, + KEY_PAGEDOWN, + KEY_INSERT, + KEY_DELETE, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + KEY_LEFTMETA, + 0, + KEY_ESC, + KEY_KPMINUS, + 0, + 0, + 0, + 0, + 0, + 0, + /* VK_BROWSER_SEARCH */ + 0, + /* VK_BROWSER_FAVORITES */ + 0, + /* VK_BROWSER_REFRESH */ + 0, + /* VK_BROWSER_STOP */ + 0, + /* VK_BROWSER_FORWARD */ + 0, + /* VK_BROWSER_BACK */ + 0, + /* VK_LAUNCH_APP2 */ + 0, + /* VK_LAUNCH_MAIL */ + 0, + /* VK_LAUNCH_MEDIA_SELECT */ + 0, +}; + +static unsigned short *code_tabs[] = { code_tab_102us, extcode_tab_us102 }; + +#endif /* _TEGRA_NVEC_KEYTABLE_H_ */ diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index f60f21f..e5da061 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -53,6 +53,9 @@ #include <asm/arch-tegra/tegra_mmc.h> #include <asm/arch-tegra/mmc.h> #endif +#ifdef CONFIG_TEGRA_NVEC +#include <asm/arch-tegra/tegra_nvec.h> +#endif #include <i2c.h> #include <spi.h> #include "emc.h" @@ -217,10 +220,19 @@ int board_early_init_f(void) int board_late_init(void) { + __maybe_unused int err; + #ifdef CONFIG_LCD /* Make sure we finish initing the LCD */ tegra_lcd_check_next_stage(gd->fdt_blob, 1); #endif + +#ifdef CONFIG_TEGRA_NVEC + err = board_nvec_init(); + if (err) + debug("NVEC controller init failed: %d\n", err); +#endif + return 0; } diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 72e85a3..6ff3b22 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -42,6 +42,7 @@ COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TEGRA_I2C) += tegra_i2c.o +COBJS-$(CONFIG_TEGRA_NVEC) += tegra_nvec.o tegra_nvec_keyboard.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o COBJS-$(CONFIG_SH_I2C) += sh_i2c.o diff --git a/drivers/i2c/tegra_nvec.c b/drivers/i2c/tegra_nvec.c new file mode 100644 index 0000000..1589003 --- /dev/null +++ b/drivers/i2c/tegra_nvec.c @@ -0,0 +1,462 @@ +/* + * (C) Copyright 2013 + * Andrey Danin <andreydanin@mail.ru> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/gpio.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch-tegra/tegra_nvec.h> +#include <asm/arch-tegra/tegra_nvec_keyboard.h> + +#ifndef CONFIG_TEGRA_NVEC +#error "You should enable CONFIG_TEGRA_NVEC" +#endif + +DECLARE_GLOBAL_DATA_PTR; + + +/* Nvec perfroms io interval is beteween 20 and 500 ms, +no response in 600 ms means error */ +enum { + NVEC_TIMEOUT_MIN = 20, + NVEC_TIMEOUT_MAX = 600, +}; +enum { + NVEC_WAIT_FOR_EC = 1, + NVEC_DONT_WAIT_FOR_EC = 0, + NVEC_ATTEMPTS_MAX = 10, +}; + +enum { + nvec_io_error = -1, + nvec_io_timeout, + nvec_io_read_ok, + nvec_io_write_ok, + nvec_io_not_ready, + nvec_io_retry, +}; + +enum { + NVST_BEGIN = 0, + NVST_CMD = 1, + NVST_SUBCMD = 2, + NVST_READ = 3, + NVST_WRITE_SIZE = 4, + NVST_WRITE = 5, +}; + +struct nvec_t { + int gpio; + int i2c_addr; + int i2c_clk; + void __iomem *base; + int state; + char rx_buf[34]; + int rx_pos; + char *tx_buf; + int tx_pos; + int tx_size; +} nvec_data; + +struct fdt_nvec_config { + int gpio; + int i2c_addr; + int i2c_clk; + fdt_addr_t base_addr; + struct fdt_gpio_state request_gpio; +}; + + +/* nvec commands */ +char noop[] = { NVEC_CNTL, CNTL_NOOP }; + + +int nvec_msg_is_event(const unsigned char *msg) +{ + return msg[0] >> 7; +} + + +int nvec_msg_event_type(const unsigned char *msg) +{ + return msg[0] & 0x0f; +} + + +/** + * Process incoming io message. + * If message is keyboard event then key code will + * be added to keys buffer. + * + * See: nvec_push_key, nvec_pop_key, nvec_have_key + * + * @param nvec nvec state struct + */ +void nvec_process_msg(struct nvec_t *nvec) +{ + const unsigned char *msg = (const unsigned char *)nvec->rx_buf; + int event_type; + + if (!nvec_msg_is_event(msg)) + return; + + event_type = nvec_msg_event_type(msg); + if (event_type == NVEC_KEYBOARD) + nvec_process_keyboard_msg(msg); +} + + +static inline int is_read(unsigned long status) +{ + return (status & RNW) == 0; +} + + +static inline int is_ready(unsigned long status) +{ + return status & I2C_SL_IRQ; +} + + +/** + * Perform complete io operation (read or write). + * NOTE: function will wait NVEC_TIMEOUT_MIN (20ms) + * before status check to avoid nvec hang. + * + * @param nvec nvec state struct + * @param wait_for_ec if 1(NVEC_WAIT_FOR_EC) operation + * timeout is NVEC_TIMEOUT_MAX (600ms), + * otherwise function will return if io + * is not ready. + * + * @return nvec_io_* code + */ +int nvec_do_io(struct nvec_t *nvec, int wait_for_ec) +{ + unsigned int poll_start_ms = 0; + unsigned long status; + unsigned int received = 0; + unsigned int to_send = 0; + unsigned int timeout_ms = NVEC_TIMEOUT_MAX; + int is_first_iteration = 1; + + poll_start_ms = get_timer(0); + mdelay(NVEC_TIMEOUT_MIN); + + while (1) { + status = readl(nvec->base + I2C_SL_STATUS); + if (!is_ready(status)) { + if (is_first_iteration && !wait_for_ec) + return nvec_io_not_ready; + + if (get_timer(poll_start_ms) > timeout_ms) + return nvec_io_timeout; + + is_first_iteration = 0; + udelay(100); + continue; + } + is_first_iteration = 0; + + if (is_read(status)) + received = readl(nvec->base + I2C_SL_RCVD); + + if (status == (I2C_SL_IRQ | RCVD)) { + nvec->state = NVST_BEGIN; + nvec->rx_pos = 0; + nvec->tx_pos = 0; + } + + switch (nvec->state) { + case NVST_BEGIN: + nvec->rx_pos = 0; + nvec->tx_pos = 0; + if (received != nvec->i2c_addr) { + error("NVEC io: unknown addr 0x%x\n", received); + return nvec_io_error; + } + nvec->state = NVST_CMD; + break; + + case NVST_CMD: + nvec->rx_buf[nvec->rx_pos++] = (char)received; + nvec->state = NVST_SUBCMD; + break; + + case NVST_SUBCMD: + if (status == (I2C_SL_IRQ | RNW | RCVD)) { + if (nvec->rx_buf[0] != 0x01) { + error("NVEC io: wrong read\n"); + nvec->state = NVST_BEGIN; + return nvec_io_error; + } + nvec->state = NVST_WRITE; + if (nvec->tx_buf == 0) { + debug("NVEC io: error, tx buffer is 0\n"); + nvec->tx_buf = noop; + nvec->tx_size = 2; + nvec->tx_pos = 0; + } + to_send = nvec->tx_size; + writel(to_send, nvec->base + I2C_SL_RCVD); + gpio_set_value(nvec_data.gpio, 1); + nvec->state = NVST_WRITE; + } else { + nvec->state = NVST_READ; + nvec->rx_buf[nvec->rx_pos] = (char)received; + ++nvec->rx_pos; + } + break; + + case NVST_READ: + if (nvec->rx_pos >= 34) { + error("NVEC io: read buffer is full\n"); + break; + } + nvec->rx_buf[nvec->rx_pos++] = (char)received; + if (status & END_TRANS) { + nvec_process_msg(nvec); + nvec->rx_pos = 0; + return nvec_io_read_ok; + } + break; + + case NVST_WRITE_SIZE: + to_send = nvec->tx_size; + writel(to_send, nvec->base + I2C_SL_RCVD); + nvec->state = NVST_WRITE; + break; + + case NVST_WRITE: + if (nvec->tx_pos >= nvec->tx_size) { + if (status & END_TRANS) + return nvec_io_write_ok; + + error("NVEC io: no data to write\n"); + return nvec_io_error; + } + to_send = nvec->tx_buf[nvec->tx_pos++]; + writel(to_send, nvec->base + I2C_SL_RCVD); + if (status & END_TRANS) { + nvec->tx_pos = 0; + nvec->tx_buf = 0; + return nvec_io_write_ok; + } + + break; + + default: + error("NVEC io: unknown state\n"); + break; + } + if (status & END_TRANS) + return nvec_io_retry; + } +} + + +/** + * Send request and read response. If write or read failed + * operation will be repeated NVEC_ATTEMPTS_MAX times. + * + * @param buf request data + * @param size request data size + * @return 0 if ok, -1 on error + */ +int nvec_do_request(char *buf, int size) +{ + int res = 0; + int i = 0; + + nvec_data.tx_buf = buf; + nvec_data.tx_size = size; + + while (i++ < NVEC_ATTEMPTS_MAX) { + nvec_data.tx_pos = 0; + + /* request */ + gpio_set_value(nvec_data.gpio, 0); + res = nvec_do_io(&nvec_data, NVEC_WAIT_FOR_EC); + if (res != nvec_io_write_ok) { + debug("warning: nvec failed to send request\n"); + continue; + } + + /* response */ + res = nvec_do_io(&nvec_data, NVEC_WAIT_FOR_EC); + if (res != nvec_io_read_ok) { + debug("warning: nvec failed to read response\n"); + continue; + } + + nvec_data.tx_buf = 0; + nvec_data.tx_size = 0; + nvec_data.tx_pos = 0; + + return 0; + } + + error("nvec failed to perform request\n"); + return -1; +} + + +/** + * Init i2c controller to operate in slave mode. + * + * @param nvec nvec state struct + */ +static void nvec_init_i2c_slave(struct nvec_t *nvec) +{ + unsigned long val; + + val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN | + (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); + writel(val, nvec->base + I2C_CNFG); + + /* i2c3 -> 67 */ + clock_start_periph_pll(67, CLOCK_ID_PERIPH, + nvec->i2c_clk * 8); + + reset_periph(67, 1); + + writel(I2C_SL_NEWSL, nvec->base + I2C_SL_CNFG); + writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); + + writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1); + writel(0, nvec->base + I2C_SL_ADDR2); + + funcmux_select(67, FUNCMUX_DEFAULT); +} + + +/** + * Decode the nvec information from the fdt. + * + * @param blob fdt blob + * @param config structure to store fdt config into + * @return 0 if ok, -ve on error + */ +static int nvec_decode_config(const void *blob, + struct fdt_nvec_config *config) +{ + int node; + + node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_NVEC); + if (node < 0) { + error("Cannot find NVEC node in fdt\n"); + return node; + } + + config->base_addr = fdtdec_get_addr(blob, node, "reg"); + if (config->base_addr == FDT_ADDR_T_NONE) { + error("No NVEC controller address\n"); + return -1; + } + + if (fdtdec_decode_gpio(blob, node, "request-gpios", + &config->request_gpio)) { + error("No NVEC request gpio\n"); + return -1; + } + + config->i2c_addr = fdtdec_get_int(blob, node, "slave-addr", -1); + config->i2c_clk = fdtdec_get_int(blob, node, "clock-frequency", -1); + + return 0; +} + + +int board_nvec_init(void) +{ + int res = 0; + + struct fdt_nvec_config cfg; + if (nvec_decode_config(gd->fdt_blob, &cfg)) { + debug("Can't parse NVEC node in device tree\n"); + return -1; + } + + nvec_data.rx_pos = 0; + nvec_data.tx_buf = 0; + nvec_data.tx_pos = 0; + nvec_data.tx_size = 0; + nvec_data.state = NVST_BEGIN; + + nvec_data.gpio = cfg.request_gpio.gpio; + nvec_data.i2c_addr = cfg.i2c_addr; + nvec_data.i2c_clk = cfg.i2c_clk; + nvec_data.base = (void __iomem *)cfg.base_addr; + + debug("NVEC initialization...\n"); + + res = gpio_request(nvec_data.gpio, NULL); + if (res != 0) + error("NVEC: err, gpio_request\n"); + res = gpio_direction_output(nvec_data.gpio, 1); + if (res != 0) + error("NVEC: err, gpio_direction\n"); + res = gpio_set_value(nvec_data.gpio, 1); + if (res != 0) + error("NVEC: err, gpio_set_value\n"); + udelay(100); + + nvec_init_i2c_slave(&nvec_data); + + nvec_enable_kbd_events(); + + return 1; +} + + +int nvec_read_events(void) +{ + int res; + int cnt = 0; + + while (++cnt <= 8) { + res = nvec_do_io(&nvec_data, NVEC_DONT_WAIT_FOR_EC); + switch (res) { + case nvec_io_not_ready: + return 0; + + case nvec_io_read_ok: + case nvec_io_retry: + break; + + case nvec_io_error: + case nvec_io_timeout: + debug("NVEC events: io failed %d\n", res); + return 0; + + case nvec_io_write_ok: + default: + debug("NVEC events: unexpected io result %d\n", res); + return 0; + } + } + + return 0; +} diff --git a/drivers/i2c/tegra_nvec_keyboard.c b/drivers/i2c/tegra_nvec_keyboard.c new file mode 100644 index 0000000..0837f08 --- /dev/null +++ b/drivers/i2c/tegra_nvec_keyboard.c @@ -0,0 +1,108 @@ +/* + * (C) Copyright 2013 + * Andrey Danin <andreydanin@mail.ru> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <circbuf.h> +#include <asm/arch-tegra/tegra_nvec_keyboard.h> +#include <asm/arch-tegra/tegra_nvec_keytable.h> +#include <asm/arch-tegra/tegra_nvec.h> + + +circbuf_t key_buf = { 0, 0, NULL, NULL, NULL, NULL }; + +/* nvec commands */ +static char enable_kbd[] = { NVEC_KBD, ENABLE_KBD }; +static char reset_kbd[] = { NVEC_PS2, MOUSE_SEND_CMD, MOUSE_RESET, 3 }; +static char clear_leds[] = { NVEC_KBD, SET_LEDS, 0 }; + + +void nvec_push_key(unsigned short code, unsigned short state) +{ + int code_state; + + assert(key_buf.totalsize > 0); + + if (key_buf.size == key_buf.totalsize) + return; + + code_state = ((state << 16) | code); + buf_push(&key_buf, (const char *)&code_state, sizeof(code_state)); +} + + +int nvec_have_keys(void) +{ + return key_buf.size > 0; +} + + +int nvec_pop_key(void) +{ + int code_state; + int len = buf_pop(&key_buf, (char *)&code_state, sizeof(code_state)); + + if (len < sizeof(code_state)) + return -1; + + return code_state; +} + + +void nvec_process_keyboard_msg(const unsigned char *msg) +{ + int code, state; + int event_type; + int _size; + + event_type = nvec_msg_event_type(msg); + if (event_type != NVEC_KEYBOARD) + return; + + _size = (msg[0] & (3 << 5)) >> 5; + + if (_size == NVEC_VAR_SIZE) + return; + + if (_size == NVEC_3BYTES) + msg++; + + code = msg[1] & 0x7f; + state = msg[1] & 0x80; + + nvec_push_key(code_tabs[_size][code], state); +} + + +void nvec_enable_kbd_events(void) +{ + buf_init(&key_buf, NVEC_KEYS_QUEUE_SIZE * sizeof(int)); + + if (nvec_do_request(reset_kbd, 4)) + error("NVEC: failed to reset keyboard\n"); + if (nvec_do_request(clear_leds, 3)) + error("NVEC: failed to clear leds\n"); + if (nvec_do_request(enable_kbd, 2)) + error("NVEC: failed to enable keyboard\n"); + + debug("NVEC: keyboard initialization finished\n"); +} diff --git a/include/fdtdec.h b/include/fdtdec.h index cd336fa..8917e34 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -79,6 +79,7 @@ enum fdt_compat_id { COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra20 SDMMC controller */ COMPAT_NVIDIA_TEGRA20_SFLASH, /* Tegra 2 SPI flash controller */ COMPAT_NVIDIA_TEGRA20_SLINK, /* Tegra 2 SPI SLINK controller */ + COMPAT_NVIDIA_TEGRA20_NVEC, /* Tegra 2 EC controller */ COMPAT_NVIDIA_TEGRA114_SPI, /* Tegra 114 SPI controller */ COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */ COMPAT_SAMSUNG_EXYNOS5_SROMC, /* Exynos5 SROMC */ diff --git a/lib/Makefile b/lib/Makefile index 5d58609..b338211 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_BZIP2) += bzlib_decompress.o COBJS-$(CONFIG_BZIP2) += bzlib_randtable.o COBJS-$(CONFIG_BZIP2) += bzlib_huffman.o COBJS-$(CONFIG_USB_TTY) += circbuf.o +COBJS-$(CONFIG_TEGRA_NVEC) += circbuf.o COBJS-y += crc7.o COBJS-y += crc16.o COBJS-y += display_options.o diff --git a/lib/fdtdec.c b/lib/fdtdec.c index e322b82..4c70c79 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -52,6 +52,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"), COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"), + COMPAT(NVIDIA_TEGRA20_NVEC, "nvidia,tegra20-nvec"), COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"), COMPAT(SMSC_LAN9215, "smsc,lan9215"), COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"), -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver 2013-07-19 8:47 ` [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver Andrey Danin @ 2013-07-19 16:28 ` Tom Warren 0 siblings, 0 replies; 12+ messages in thread From: Tom Warren @ 2013-07-19 16:28 UTC (permalink / raw) To: u-boot Andrey, > -----Original Message----- > From: Andrey Danin [mailto:danindrey at mail.ru] > Sent: Friday, July 19, 2013 1:48 AM > To: Tom Warren; u-boot at lists.denx.de > Cc: Stephen Warren; Marc Dietrich; Julian Andres Klode; > ac100 at lists.launchpad.net; Andrey Danin > Subject: [PATCH 1/3] ARM: tegra: add nvec driver > > Adopted version of nvec driver from linux kernel with keyboard support > only. > > Signed-off-by: Andrey Danin <danindrey@mail.ru> > --- > arch/arm/include/asm/arch-tegra/tegra_nvec.h | 117 +++++ > .../arm/include/asm/arch-tegra/tegra_nvec_events.h | 31 ++ > .../include/asm/arch-tegra/tegra_nvec_keyboard.h | 36 ++ > .../include/asm/arch-tegra/tegra_nvec_keytable.h | 313 +++++++++++++ I think some of these header files could be reduced / combined - do we really need this many header files in common arch-tegra for NVEC kbd support? > board/nvidia/common/board.c | 12 + > drivers/i2c/Makefile | 1 + > drivers/i2c/tegra_nvec.c | 462 ++++++++++++++++++++ > drivers/i2c/tegra_nvec_keyboard.c | 108 +++++ Shouldn't all input drivers (keyboard, etc.) go in driver/input/? > include/fdtdec.h | 1 + > lib/Makefile | 1 + > lib/fdtdec.c | 1 + > 11 files changed, 1083 insertions(+), 0 deletions(-) create mode 100644 > arch/arm/include/asm/arch-tegra/tegra_nvec.h > create mode 100644 arch/arm/include/asm/arch- > tegra/tegra_nvec_events.h > create mode 100644 arch/arm/include/asm/arch- > tegra/tegra_nvec_keyboard.h > create mode 100644 arch/arm/include/asm/arch- > tegra/tegra_nvec_keytable.h > create mode 100644 drivers/i2c/tegra_nvec.c create mode 100644 > drivers/i2c/tegra_nvec_keyboard.c > > diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec.h > b/arch/arm/include/asm/arch-tegra/tegra_nvec.h > new file mode 100644 > index 0000000..1c30028 > --- /dev/null > +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec.h > @@ -0,0 +1,117 @@ > +/* > + * (C) Copyright 2013 > + * Andrey Danin <andreydanin@mail.ru> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#ifndef _TEGRA_NVEC_H_ > +#define _TEGRA_NVEC_H_ > + > +#define I2C_CNFG 0x00 > +#define I2C_CNFG_PACKET_MODE_EN (1<<10) > +#define I2C_CNFG_NEW_MASTER_SFM (1<<11) > +#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12 > + > +#define I2C_SL_CNFG 0x20 > +#define I2C_SL_NEWSL (1<<2) > +#define I2C_SL_NACK (1<<1) > +#define I2C_SL_RESP (1<<0) > +#define I2C_SL_IRQ (1<<3) > +#define END_TRANS (1<<4) > +#define RCVD (1<<2) > +#define RNW (1<<1) > + > +#define I2C_SL_RCVD 0x24 > +#define I2C_SL_STATUS 0x28 > +#define I2C_SL_ADDR1 0x2c > +#define I2C_SL_ADDR2 0x30 > +#define I2C_SL_DELAY_COUNT 0x3c > + > + > +enum nvec_msg_type { > + NVEC_KEYBOARD = 0, > + NVEC_SYS = 1, > + NVEC_BAT, > + NVEC_GPIO, > + NVEC_SLEEP, > + NVEC_KBD, > + NVEC_PS2, > + NVEC_CNTL, > + NVEC_OEM0 = 0x0d, > + NVEC_KB_EVT = 0x80, > + NVEC_PS2_EVT, > +}; > + > +enum nvec_event_size { > + NVEC_2BYTES, > + NVEC_3BYTES, > + NVEC_VAR_SIZE, > +}; > + > +enum sys_subcmds { > + SYS_GET_STATUS, > + SYS_CNFG_EVENT_REPORTING, > + SYS_ACK_STATUS, > + SYS_CNFG_WAKE = 0xfd, > +}; > + > +enum kbd_subcmds { > + CNFG_WAKE = 3, > + CNFG_WAKE_KEY_REPORTING, > + SET_LEDS = 0xed, > + ENABLE_KBD = 0xf4, > + DISABLE_KBD, > +}; > + > +enum cntl_subcmds { > + CNTL_RESET_EC = 0x00, > + CNTL_SELF_TEST = 0x01, > + CNTL_NOOP = 0x02, > + CNTL_GET_EC_SPEC_VER = 0x10, > + CNTL_GET_FIRMWARE_VERSION = 0x15, > +}; > + > +enum nvec_sleep_subcmds { > + GLOBAL_EVENTS, > + AP_PWR_DOWN, > + AP_SUSPEND, > +}; > + > +#define MOUSE_SEND_CMD 0x01 > +#define MOUSE_RESET 0xff > + > + > +int board_nvec_init(void); > + > +int nvec_msg_is_event(const unsigned char *msg); int > +nvec_msg_event_type(const unsigned char *msg); > + > +/** > + * Send request and read response. If write or read failed > + * operation will be repeated NVEC_ATTEMPTS_MAX times. > + * > + * @param buf request data > + * @param size request data size > + * @return 0 if ok, -1 on error > + */ > +int nvec_do_request(char *buf, int size); > + > + > +#endif /* _TEGRA_NVEC_H_ */ > diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_events.h > b/arch/arm/include/asm/arch-tegra/tegra_nvec_events.h > new file mode 100644 > index 0000000..7d65921 > --- /dev/null > +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_events.h > @@ -0,0 +1,31 @@ > +/* > + * (C) Copyright 2013 > + * Andrey Danin <andreydanin@mail.ru> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#ifndef _TEGRA_NVEC_EVENTS_H_ > +#define _TEGRA_NVEC_EVENTS_H_ > + > + > +int nvec_read_events(void); For instance, combine this file with tegra_nvec.h and tegra_nvec_keyboard.h into one file, tegra_nvec.h. And all protos should have their arguments spelled out in a header, as you did for nvec_do_request above. > + > + > +#endif /* _TEGRA_NVEC_EVENTS_H_ */ > diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h > b/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h > new file mode 100644 > index 0000000..b25a1d8 > --- /dev/null > +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h > @@ -0,0 +1,36 @@ > +/* > + * (C) Copyright 2013 > + * Andrey Danin <andreydanin@mail.ru> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#ifndef _TEGRA_NVEC_KEYBOARD_H_ > +#define _TEGRA_NVEC_KEYBOARD_H_ > + > + > +#define NVEC_KEYS_QUEUE_SIZE 256 > + > +void nvec_enable_kbd_events(void); > +void nvec_process_keyboard_msg(const unsigned char *msg); int > +nvec_pop_key(void); int nvec_have_keys(void); > + > + > +#endif /* _TEGRA_NVEC_KEYBOARD_H_ */ > diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h > b/arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h > new file mode 100644 > index 0000000..8fbf96c > --- /dev/null > +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h > @@ -0,0 +1,313 @@ > +/* > + * Keyboard class input driver for keyboards connected to an NvEc > +compliant > + * embedded controller > + * > + * Copyright (c) 2009, NVIDIA Corporation. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, but > +WITHOUT > + * ANY WARRANTY; without even the implied warranty of > MERCHANTABILITY > +or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public > +License for > + * more details. > + * > + * You should have received a copy of the GNU General Public License > +along > + * with this program; if not, write to the Free Software Foundation, > +Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. > + */ > + > +#ifndef _TEGRA_NVEC_KEYTABLE_H_ > +#define _TEGRA_NVEC_KEYTABLE_H_ > + > +#include <linux/input.h> > + > + > +static unsigned short code_tab_102us[] = { > + /* 0x00 */ > + KEY_GRAVE, > + KEY_ESC, > + KEY_1, > + KEY_2, > + KEY_3, > + KEY_4, > + KEY_5, > + KEY_6, > + KEY_7, > + KEY_8, > + KEY_9, > + KEY_0, > + KEY_MINUS, > + KEY_EQUAL, > + KEY_BACKSPACE, > + KEY_TAB, > + /* 0x10 */ > + KEY_Q, > + KEY_W, > + KEY_E, > + KEY_R, > + KEY_T, > + KEY_Y, > + KEY_U, > + KEY_I, > + KEY_O, > + KEY_P, > + KEY_LEFTBRACE, > + KEY_RIGHTBRACE, > + KEY_ENTER, > + KEY_LEFTCTRL, > + KEY_A, > + KEY_S, > + /* 0x20 */ > + KEY_D, > + KEY_F, > + KEY_G, > + KEY_H, > + KEY_J, > + KEY_K, > + KEY_L, > + KEY_SEMICOLON, > + KEY_APOSTROPHE, > + KEY_GRAVE, > + KEY_LEFTSHIFT, > + KEY_BACKSLASH, > + KEY_Z, > + KEY_X, > + KEY_C, > + KEY_V, > + /* 0x30 */ > + KEY_B, > + KEY_N, > + KEY_M, > + KEY_COMMA, > + KEY_DOT, > + KEY_SLASH, > + KEY_RIGHTSHIFT, > + KEY_KPASTERISK, > + KEY_LEFTALT, > + KEY_SPACE, > + KEY_CAPSLOCK, > + KEY_F1, > + KEY_F2, > + KEY_F3, > + KEY_F4, > + KEY_F5, > + /* 0x40 */ > + KEY_F6, > + KEY_F7, > + KEY_F8, > + KEY_F9, > + KEY_F10, > + KEY_FN, > + /* VK_SCROLL */ > + 0, > + KEY_KP7, > + KEY_KP8, > + KEY_KP9, > + KEY_KPMINUS, > + KEY_KP4, > + KEY_KP5, > + KEY_KP6, > + KEY_KPPLUS, > + KEY_KP1, > + /* 0x50 */ > + KEY_KP2, > + KEY_KP3, > + KEY_KP0, > + KEY_KPDOT, > + /* VK_SNAPSHOT */ > + 0, /* KEY_MENU, */ > + KEY_POWER, > + /* VK_OEM_102 */ > + KEY_102ND, > + KEY_F11, > + KEY_F12, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + /* 0x60 */ > + 0, > + 0, > + 0, > + 0, /* KEY_SEARCH, */ > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + /* 0x70 */ > + 0, > + 0, > + 0, > + KEY_KP5, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + KEY_KP9, > +}; > + > +static unsigned short extcode_tab_us102[] = { > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + /* 0x10 */ > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + /* VK_MEDIA_NEXT_TRACK */ > + 0, > + 0, > + 0, > + /* VK_RETURN */ > + 0, > + KEY_RIGHTCTRL, > + 0, > + 0, > + /* 0x20 */ > + KEY_MUTE, > + /* VK_LAUNCH_APP1 */ > + 0, > + /* VK_MEDIA_PLAY_PAUSE */ > + 0, > + 0, > + /* VK_MEDIA_STOP */ > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + /* 0x30 */ > + KEY_VOLUMEUP, > + 0, > + /* VK_BROWSER_HOME */ > + 0, > + 0, > + 0, > + /* VK_DIVIDE */ > + KEY_KPSLASH, > + 0, > + /* VK_SNAPSHOT */ > + KEY_SYSRQ, > + /* VK_RMENU */ > + KEY_RIGHTALT, > + /* VK_OEM_NV_BACKLIGHT_UP */ > + 0, > + /* VK_OEM_NV_BACKLIGHT_DN */ > + 0, > + /* VK_OEM_NV_BACKLIGHT_AUTOTOGGLE */ > + 0, > + /* VK_OEM_NV_POWER_INFO */ > + 0, > + /* VK_OEM_NV_WIFI_TOGGLE */ > + 0, > + /* VK_OEM_NV_DISPLAY_SELECT */ > + 0, > + /* VK_OEM_NV_AIRPLANE_TOGGLE */ > + 0, > + /* 0x40 */ > + 0, > + KEY_LEFT, > + 0, > + 0, > + 0, > + 0, > + 0, /* KEY_CANCEL, */ > + KEY_HOME, > + KEY_UP, > + KEY_PAGEUP, > + 0, > + KEY_LEFT, > + 0, > + KEY_RIGHT, > + 0, > + KEY_END, > + /* 0x50 */ > + KEY_DOWN, > + KEY_PAGEDOWN, > + KEY_INSERT, > + KEY_DELETE, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + KEY_LEFTMETA, > + 0, > + KEY_ESC, > + KEY_KPMINUS, > + 0, > + 0, > + 0, > + 0, > + 0, > + 0, > + /* VK_BROWSER_SEARCH */ > + 0, > + /* VK_BROWSER_FAVORITES */ > + 0, > + /* VK_BROWSER_REFRESH */ > + 0, > + /* VK_BROWSER_STOP */ > + 0, > + /* VK_BROWSER_FORWARD */ > + 0, > + /* VK_BROWSER_BACK */ > + 0, > + /* VK_LAUNCH_APP2 */ > + 0, > + /* VK_LAUNCH_MAIL */ > + 0, > + /* VK_LAUNCH_MEDIA_SELECT */ > + 0, > +}; > + > +static unsigned short *code_tabs[] = { code_tab_102us, > +extcode_tab_us102 }; > + > +#endif /* _TEGRA_NVEC_KEYTABLE_H_ */ > diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c > index f60f21f..e5da061 100644 > --- a/board/nvidia/common/board.c > +++ b/board/nvidia/common/board.c > @@ -53,6 +53,9 @@ > #include <asm/arch-tegra/tegra_mmc.h> > #include <asm/arch-tegra/mmc.h> > #endif > +#ifdef CONFIG_TEGRA_NVEC > +#include <asm/arch-tegra/tegra_nvec.h> > +#endif > #include <i2c.h> > #include <spi.h> > #include "emc.h" > @@ -217,10 +220,19 @@ int board_early_init_f(void) > > int board_late_init(void) > { > + __maybe_unused int err; > + > #ifdef CONFIG_LCD > /* Make sure we finish initing the LCD */ > tegra_lcd_check_next_stage(gd->fdt_blob, 1); #endif > + > +#ifdef CONFIG_TEGRA_NVEC > + err = board_nvec_init(); > + if (err) > + debug("NVEC controller init failed: %d\n", err); #endif > + > return 0; > } > > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index > 72e85a3..6ff3b22 100644 > --- a/drivers/i2c/Makefile > +++ b/drivers/i2c/Makefile > @@ -42,6 +42,7 @@ COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += > s3c24x0_i2c.o > COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o > COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o > COBJS-$(CONFIG_TEGRA_I2C) += tegra_i2c.o > +COBJS-$(CONFIG_TEGRA_NVEC) += tegra_nvec.o tegra_nvec_keyboard.o > COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o > COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o > COBJS-$(CONFIG_SH_I2C) += sh_i2c.o > diff --git a/drivers/i2c/tegra_nvec.c b/drivers/i2c/tegra_nvec.c new file > mode 100644 index 0000000..1589003 > --- /dev/null > +++ b/drivers/i2c/tegra_nvec.c > @@ -0,0 +1,462 @@ > +/* > + * (C) Copyright 2013 > + * Andrey Danin <andreydanin@mail.ru> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#include <common.h> > +#include <fdtdec.h> > +#include <asm/io.h> > +#include <asm/gpio.h> > +#include <asm/arch/clock.h> > +#include <asm/arch/funcmux.h> > +#include <asm/arch-tegra/tegra_nvec.h> > +#include <asm/arch-tegra/tegra_nvec_keyboard.h> > + > +#ifndef CONFIG_TEGRA_NVEC > +#error "You should enable CONFIG_TEGRA_NVEC" > +#endif > + > +DECLARE_GLOBAL_DATA_PTR; > + > + > +/* Nvec perfroms io interval is beteween 20 and 500 ms, no response in > +600 ms means error */ enum { > + NVEC_TIMEOUT_MIN = 20, > + NVEC_TIMEOUT_MAX = 600, > +}; > +enum { > + NVEC_WAIT_FOR_EC = 1, > + NVEC_DONT_WAIT_FOR_EC = 0, > + NVEC_ATTEMPTS_MAX = 10, > +}; > + > +enum { > + nvec_io_error = -1, > + nvec_io_timeout, > + nvec_io_read_ok, > + nvec_io_write_ok, > + nvec_io_not_ready, > + nvec_io_retry, > +}; > + > +enum { > + NVST_BEGIN = 0, > + NVST_CMD = 1, > + NVST_SUBCMD = 2, > + NVST_READ = 3, > + NVST_WRITE_SIZE = 4, > + NVST_WRITE = 5, > +}; > + > +struct nvec_t { > + int gpio; > + int i2c_addr; > + int i2c_clk; > + void __iomem *base; > + int state; > + char rx_buf[34]; > + int rx_pos; > + char *tx_buf; > + int tx_pos; > + int tx_size; > +} nvec_data; > + > +struct fdt_nvec_config { > + int gpio; > + int i2c_addr; > + int i2c_clk; > + fdt_addr_t base_addr; > + struct fdt_gpio_state request_gpio; > +}; > + > + > +/* nvec commands */ > +char noop[] = { NVEC_CNTL, CNTL_NOOP }; > + > + > +int nvec_msg_is_event(const unsigned char *msg) { > + return msg[0] >> 7; > +} > + > + > +int nvec_msg_event_type(const unsigned char *msg) { > + return msg[0] & 0x0f; > +} > + > + > +/** > + * Process incoming io message. > + * If message is keyboard event then key code will > + * be added to keys buffer. > + * > + * See: nvec_push_key, nvec_pop_key, nvec_have_key > + * > + * @param nvec nvec state struct > + */ > +void nvec_process_msg(struct nvec_t *nvec) { > + const unsigned char *msg = (const unsigned char *)nvec->rx_buf; > + int event_type; > + > + if (!nvec_msg_is_event(msg)) > + return; > + > + event_type = nvec_msg_event_type(msg); > + if (event_type == NVEC_KEYBOARD) > + nvec_process_keyboard_msg(msg); > +} > + > + > +static inline int is_read(unsigned long status) { > + return (status & RNW) == 0; > +} > + > + > +static inline int is_ready(unsigned long status) { > + return status & I2C_SL_IRQ; > +} > + > + > +/** > + * Perform complete io operation (read or write). > + * NOTE: function will wait NVEC_TIMEOUT_MIN (20ms) > + * before status check to avoid nvec hang. > + * > + * @param nvec nvec state struct > + * @param wait_for_ec if 1(NVEC_WAIT_FOR_EC) operation > + * timeout is NVEC_TIMEOUT_MAX (600ms), > + * otherwise function will return if io > + * is not ready. > + * > + * @return nvec_io_* code > + */ > +int nvec_do_io(struct nvec_t *nvec, int wait_for_ec) { > + unsigned int poll_start_ms = 0; > + unsigned long status; > + unsigned int received = 0; > + unsigned int to_send = 0; > + unsigned int timeout_ms = NVEC_TIMEOUT_MAX; > + int is_first_iteration = 1; > + > + poll_start_ms = get_timer(0); > + mdelay(NVEC_TIMEOUT_MIN); > + > + while (1) { > + status = readl(nvec->base + I2C_SL_STATUS); > + if (!is_ready(status)) { > + if (is_first_iteration && !wait_for_ec) > + return nvec_io_not_ready; > + > + if (get_timer(poll_start_ms) > timeout_ms) > + return nvec_io_timeout; > + > + is_first_iteration = 0; > + udelay(100); > + continue; > + } > + is_first_iteration = 0; > + > + if (is_read(status)) > + received = readl(nvec->base + I2C_SL_RCVD); > + > + if (status == (I2C_SL_IRQ | RCVD)) { > + nvec->state = NVST_BEGIN; > + nvec->rx_pos = 0; > + nvec->tx_pos = 0; > + } > + > + switch (nvec->state) { > + case NVST_BEGIN: > + nvec->rx_pos = 0; > + nvec->tx_pos = 0; > + if (received != nvec->i2c_addr) { > + error("NVEC io: unknown addr 0x%x\n", > received); > + return nvec_io_error; > + } > + nvec->state = NVST_CMD; > + break; > + > + case NVST_CMD: > + nvec->rx_buf[nvec->rx_pos++] = (char)received; > + nvec->state = NVST_SUBCMD; > + break; > + > + case NVST_SUBCMD: > + if (status == (I2C_SL_IRQ | RNW | RCVD)) { > + if (nvec->rx_buf[0] != 0x01) { > + error("NVEC io: wrong read\n"); > + nvec->state = NVST_BEGIN; > + return nvec_io_error; > + } > + nvec->state = NVST_WRITE; > + if (nvec->tx_buf == 0) { > + debug("NVEC io: error, tx buffer is > 0\n"); > + nvec->tx_buf = noop; > + nvec->tx_size = 2; > + nvec->tx_pos = 0; > + } > + to_send = nvec->tx_size; > + writel(to_send, nvec->base + I2C_SL_RCVD); > + gpio_set_value(nvec_data.gpio, 1); > + nvec->state = NVST_WRITE; > + } else { > + nvec->state = NVST_READ; > + nvec->rx_buf[nvec->rx_pos] = > (char)received; > + ++nvec->rx_pos; > + } > + break; > + > + case NVST_READ: > + if (nvec->rx_pos >= 34) { > + error("NVEC io: read buffer is full\n"); > + break; > + } > + nvec->rx_buf[nvec->rx_pos++] = (char)received; > + if (status & END_TRANS) { > + nvec_process_msg(nvec); > + nvec->rx_pos = 0; > + return nvec_io_read_ok; > + } > + break; > + > + case NVST_WRITE_SIZE: > + to_send = nvec->tx_size; > + writel(to_send, nvec->base + I2C_SL_RCVD); > + nvec->state = NVST_WRITE; > + break; > + > + case NVST_WRITE: > + if (nvec->tx_pos >= nvec->tx_size) { > + if (status & END_TRANS) > + return nvec_io_write_ok; > + > + error("NVEC io: no data to write\n"); > + return nvec_io_error; > + } > + to_send = nvec->tx_buf[nvec->tx_pos++]; > + writel(to_send, nvec->base + I2C_SL_RCVD); > + if (status & END_TRANS) { > + nvec->tx_pos = 0; > + nvec->tx_buf = 0; > + return nvec_io_write_ok; > + } > + > + break; > + > + default: > + error("NVEC io: unknown state\n"); > + break; > + } > + if (status & END_TRANS) > + return nvec_io_retry; > + } > +} > + > + > +/** > + * Send request and read response. If write or read failed > + * operation will be repeated NVEC_ATTEMPTS_MAX times. > + * > + * @param buf request data > + * @param size request data size > + * @return 0 if ok, -1 on error > + */ > +int nvec_do_request(char *buf, int size) { > + int res = 0; > + int i = 0; > + > + nvec_data.tx_buf = buf; > + nvec_data.tx_size = size; > + > + while (i++ < NVEC_ATTEMPTS_MAX) { > + nvec_data.tx_pos = 0; > + > + /* request */ > + gpio_set_value(nvec_data.gpio, 0); > + res = nvec_do_io(&nvec_data, NVEC_WAIT_FOR_EC); > + if (res != nvec_io_write_ok) { > + debug("warning: nvec failed to send request\n"); > + continue; > + } > + > + /* response */ > + res = nvec_do_io(&nvec_data, NVEC_WAIT_FOR_EC); > + if (res != nvec_io_read_ok) { > + debug("warning: nvec failed to read response\n"); > + continue; > + } > + > + nvec_data.tx_buf = 0; > + nvec_data.tx_size = 0; > + nvec_data.tx_pos = 0; > + > + return 0; > + } > + > + error("nvec failed to perform request\n"); > + return -1; > +} > + > + > +/** > + * Init i2c controller to operate in slave mode. > + * > + * @param nvec nvec state struct > + */ > +static void nvec_init_i2c_slave(struct nvec_t *nvec) { > + unsigned long val; > + > + val = I2C_CNFG_NEW_MASTER_SFM | > I2C_CNFG_PACKET_MODE_EN | > + (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); > + writel(val, nvec->base + I2C_CNFG); > + > + /* i2c3 -> 67 */ > + clock_start_periph_pll(67, CLOCK_ID_PERIPH, > + nvec->i2c_clk * 8); > + > + reset_periph(67, 1); > + > + writel(I2C_SL_NEWSL, nvec->base + I2C_SL_CNFG); > + writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); > + > + writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1); > + writel(0, nvec->base + I2C_SL_ADDR2); > + > + funcmux_select(67, FUNCMUX_DEFAULT); > +} > + > + > +/** > + * Decode the nvec information from the fdt. > + * > + * @param blob fdt blob > + * @param config structure to store fdt config into > + * @return 0 if ok, -ve on error > + */ > +static int nvec_decode_config(const void *blob, > + struct fdt_nvec_config *config) { > + int node; > + > + node = fdtdec_next_compatible(blob, 0, > COMPAT_NVIDIA_TEGRA20_NVEC); > + if (node < 0) { > + error("Cannot find NVEC node in fdt\n"); > + return node; > + } > + > + config->base_addr = fdtdec_get_addr(blob, node, "reg"); > + if (config->base_addr == FDT_ADDR_T_NONE) { > + error("No NVEC controller address\n"); > + return -1; > + } > + > + if (fdtdec_decode_gpio(blob, node, "request-gpios", > + &config->request_gpio)) { > + error("No NVEC request gpio\n"); > + return -1; > + } > + > + config->i2c_addr = fdtdec_get_int(blob, node, "slave-addr", -1); > + config->i2c_clk = fdtdec_get_int(blob, node, "clock-frequency", -1); > + > + return 0; > +} > + > + > +int board_nvec_init(void) > +{ > + int res = 0; > + > + struct fdt_nvec_config cfg; > + if (nvec_decode_config(gd->fdt_blob, &cfg)) { > + debug("Can't parse NVEC node in device tree\n"); > + return -1; > + } > + > + nvec_data.rx_pos = 0; > + nvec_data.tx_buf = 0; > + nvec_data.tx_pos = 0; > + nvec_data.tx_size = 0; > + nvec_data.state = NVST_BEGIN; > + > + nvec_data.gpio = cfg.request_gpio.gpio; > + nvec_data.i2c_addr = cfg.i2c_addr; > + nvec_data.i2c_clk = cfg.i2c_clk; > + nvec_data.base = (void __iomem *)cfg.base_addr; > + > + debug("NVEC initialization...\n"); > + > + res = gpio_request(nvec_data.gpio, NULL); > + if (res != 0) > + error("NVEC: err, gpio_request\n"); > + res = gpio_direction_output(nvec_data.gpio, 1); > + if (res != 0) > + error("NVEC: err, gpio_direction\n"); > + res = gpio_set_value(nvec_data.gpio, 1); > + if (res != 0) > + error("NVEC: err, gpio_set_value\n"); > + udelay(100); > + > + nvec_init_i2c_slave(&nvec_data); > + > + nvec_enable_kbd_events(); > + > + return 1; > +} > + > + > +int nvec_read_events(void) > +{ > + int res; > + int cnt = 0; > + > + while (++cnt <= 8) { > + res = nvec_do_io(&nvec_data, > NVEC_DONT_WAIT_FOR_EC); > + switch (res) { > + case nvec_io_not_ready: > + return 0; > + > + case nvec_io_read_ok: > + case nvec_io_retry: > + break; > + > + case nvec_io_error: > + case nvec_io_timeout: > + debug("NVEC events: io failed %d\n", res); > + return 0; > + > + case nvec_io_write_ok: > + default: > + debug("NVEC events: unexpected io result %d\n", > res); > + return 0; > + } > + } > + > + return 0; > +} > diff --git a/drivers/i2c/tegra_nvec_keyboard.c > b/drivers/i2c/tegra_nvec_keyboard.c > new file mode 100644 > index 0000000..0837f08 > --- /dev/null > +++ b/drivers/i2c/tegra_nvec_keyboard.c > @@ -0,0 +1,108 @@ > +/* > + * (C) Copyright 2013 > + * Andrey Danin <andreydanin@mail.ru> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#include <common.h> > +#include <circbuf.h> > +#include <asm/arch-tegra/tegra_nvec_keyboard.h> > +#include <asm/arch-tegra/tegra_nvec_keytable.h> > +#include <asm/arch-tegra/tegra_nvec.h> > + > + > +circbuf_t key_buf = { 0, 0, NULL, NULL, NULL, NULL }; > + > +/* nvec commands */ > +static char enable_kbd[] = { NVEC_KBD, ENABLE_KBD }; static char > +reset_kbd[] = { NVEC_PS2, MOUSE_SEND_CMD, MOUSE_RESET, 3 }; static > char > +clear_leds[] = { NVEC_KBD, SET_LEDS, 0 }; > + > + > +void nvec_push_key(unsigned short code, unsigned short state) { > + int code_state; > + > + assert(key_buf.totalsize > 0); > + > + if (key_buf.size == key_buf.totalsize) > + return; > + > + code_state = ((state << 16) | code); > + buf_push(&key_buf, (const char *)&code_state, > sizeof(code_state)); } > + > + > +int nvec_have_keys(void) > +{ > + return key_buf.size > 0; > +} > + > + > +int nvec_pop_key(void) > +{ > + int code_state; > + int len = buf_pop(&key_buf, (char *)&code_state, > sizeof(code_state)); > + > + if (len < sizeof(code_state)) > + return -1; > + > + return code_state; > +} > + > + > +void nvec_process_keyboard_msg(const unsigned char *msg) { > + int code, state; > + int event_type; > + int _size; > + > + event_type = nvec_msg_event_type(msg); > + if (event_type != NVEC_KEYBOARD) > + return; > + > + _size = (msg[0] & (3 << 5)) >> 5; > + > + if (_size == NVEC_VAR_SIZE) > + return; > + > + if (_size == NVEC_3BYTES) > + msg++; > + > + code = msg[1] & 0x7f; > + state = msg[1] & 0x80; > + > + nvec_push_key(code_tabs[_size][code], state); } > + > + > +void nvec_enable_kbd_events(void) > +{ > + buf_init(&key_buf, NVEC_KEYS_QUEUE_SIZE * sizeof(int)); > + > + if (nvec_do_request(reset_kbd, 4)) > + error("NVEC: failed to reset keyboard\n"); > + if (nvec_do_request(clear_leds, 3)) > + error("NVEC: failed to clear leds\n"); > + if (nvec_do_request(enable_kbd, 2)) > + error("NVEC: failed to enable keyboard\n"); > + > + debug("NVEC: keyboard initialization finished\n"); } > diff --git a/include/fdtdec.h b/include/fdtdec.h index cd336fa..8917e34 > 100644 > --- a/include/fdtdec.h > +++ b/include/fdtdec.h > @@ -79,6 +79,7 @@ enum fdt_compat_id { > COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra20 SDMMC controller > */ > COMPAT_NVIDIA_TEGRA20_SFLASH, /* Tegra 2 SPI flash controller > */ > COMPAT_NVIDIA_TEGRA20_SLINK, /* Tegra 2 SPI SLINK > controller */ > + COMPAT_NVIDIA_TEGRA20_NVEC, /* Tegra 2 EC controller */ > COMPAT_NVIDIA_TEGRA114_SPI, /* Tegra 114 SPI controller */ > COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet > LAN9215 */ > COMPAT_SAMSUNG_EXYNOS5_SROMC, /* Exynos5 SROMC */ > diff --git a/lib/Makefile b/lib/Makefile index 5d58609..b338211 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -34,6 +34,7 @@ COBJS-$(CONFIG_BZIP2) += bzlib_decompress.o > COBJS-$(CONFIG_BZIP2) += bzlib_randtable.o > COBJS-$(CONFIG_BZIP2) += bzlib_huffman.o > COBJS-$(CONFIG_USB_TTY) += circbuf.o > +COBJS-$(CONFIG_TEGRA_NVEC) += circbuf.o > COBJS-y += crc7.o > COBJS-y += crc16.o > COBJS-y += display_options.o > diff --git a/lib/fdtdec.c b/lib/fdtdec.c index e322b82..4c70c79 100644 > --- a/lib/fdtdec.c > +++ b/lib/fdtdec.c > @@ -52,6 +52,7 @@ static const char * const > compat_names[COMPAT_COUNT] = { > COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), > COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"), > COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"), > + COMPAT(NVIDIA_TEGRA20_NVEC, "nvidia,tegra20-nvec"), > COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"), > COMPAT(SMSC_LAN9215, "smsc,lan9215"), > COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"), > -- > 1.7.1 Tom -- nvpublic ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [PATCH 2/3] ARM: tegra: add input driver for nvec keyboard 2013-07-19 8:47 [U-Boot] [PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00 Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver Andrey Danin @ 2013-07-19 8:47 ` Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 3/3] ARM: tegra: paz00: enable nvec keyboard support Andrey Danin 2 siblings, 0 replies; 12+ messages in thread From: Andrey Danin @ 2013-07-19 8:47 UTC (permalink / raw) To: u-boot Signed-off-by: Andrey Danin <danindrey@mail.ru> --- drivers/input/Makefile | 1 + drivers/input/tegra-nvec-kbc.c | 131 +++++++++++++++++++++++++++++++++++ include/configs/tegra-common-post.h | 2 + 3 files changed, 134 insertions(+), 0 deletions(-) create mode 100644 drivers/input/tegra-nvec-kbc.c diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 0805e86..20ef7b2 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libinput.o COBJS-$(CONFIG_I8042_KBD) += i8042.o COBJS-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o +COBJS-$(CONFIG_TEGRA_NVEC_KEYBOARD) += tegra-nvec-kbc.o ifdef CONFIG_PS2KBD COBJS-y += keyboard.o pc_keyb.o COBJS-$(CONFIG_PS2MULT) += ps2mult.o ps2ser.o diff --git a/drivers/input/tegra-nvec-kbc.c b/drivers/input/tegra-nvec-kbc.c new file mode 100644 index 0000000..2799492 --- /dev/null +++ b/drivers/input/tegra-nvec-kbc.c @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2011,2013 + * Andrey Danin <danindrey@mail.ru> + * NVIDIA Corporation <www.nvidia.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <input.h> +#include <asm/arch-tegra/tegra_nvec_events.h> +#include <asm/arch-tegra/tegra_nvec_keyboard.h> + +enum { + KBC_MAX_KPENT = 8, +}; + +/* keyboard config/state */ +static struct keyb { + struct input_config input; /* The input layer */ +} config; + + +/** + * Check the tegra nvec keyboard, and send any keys that are pressed. + * + * This is called by input_tstc() and input_getc() when they need more + * characters + * + * @param input Input configuration + * @return 1, to indicate that we have something to look at + */ +int tegra_nvec_kbc_check(struct input_config *input) +{ + int res = 0; + int fifo[KBC_MAX_KPENT]; + int cnt = 0; + + if (!nvec_have_keys()) + nvec_read_events(); + + while (nvec_have_keys() && cnt < KBC_MAX_KPENT) { + res = 1; + fifo[cnt++] = nvec_pop_key(); + if (cnt == KBC_MAX_KPENT) { + input_send_keycodes(input, fifo, cnt); + cnt = 0; + } + } + + if (cnt > 0) + input_send_keycodes(input, fifo, cnt); + + return res; +} + +/** + * Test if keys are available to be read + * + * @return 0 if no keys available, 1 if keys are available + */ +static int kbd_tstc(void) +{ + /* Just get input to do this for us */ + return input_tstc(&config.input); +} + +/** + * Read a key + * + * TODO: U-Boot wants 0 for no key, but Ctrl-@ is a valid key... + * + * @return ASCII key code, or 0 if no key, or -1 if error + */ +static int kbd_getc(void) +{ + /* Just get input to do this for us */ + return input_getc(&config.input); +} + + +int drv_keyboard_init(void) +{ + struct stdio_dev dev; + char *stdinname = getenv("stdin"); + int error; + + if (input_init(&config.input, 0)) { + printf("nvec kbc: cannot set up input\n"); + return -1; + } + config.input.read_keys = tegra_nvec_kbc_check; + + memset(&dev, '\0', sizeof(dev)); + strcpy(dev.name, "tegra-nvec-kbc"); + dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.getc = kbd_getc; + dev.tstc = kbd_tstc; + + /* Register the device. init_tegra_keyboard() will be called soon */ + error = input_stdio_register(&dev); + if (error) { + printf("nvec kbc: failed to register stdio device, %d\n", + error); + return error; + } +#ifdef CONFIG_CONSOLE_MUX + error = iomux_doenv(stdin, stdinname); + if (error) { + printf("nvec kbc: iomux_doenv failed, %d\n", error); + return error; + } +#endif + return 0; +} diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h index 6ed2fde..b01a072 100644 --- a/include/configs/tegra-common-post.h +++ b/include/configs/tegra-common-post.h @@ -121,6 +121,8 @@ #ifdef CONFIG_TEGRA_KEYBOARD #define STDIN_KBD_KBC ",tegra-kbc" +#elif defined(CONFIG_TEGRA_NVEC_KEYBOARD) +#define STDIN_KBD_KBC ",tegra-nvec-kbc" #else #define STDIN_KBD_KBC "" #endif -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [U-Boot] [PATCH 3/3] ARM: tegra: paz00: enable nvec keyboard support 2013-07-19 8:47 [U-Boot] [PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00 Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 2/3] ARM: tegra: add input driver for nvec keyboard Andrey Danin @ 2013-07-19 8:47 ` Andrey Danin 2013-07-19 19:14 ` [U-Boot] [Ac100] " Stephen Warren 2 siblings, 1 reply; 12+ messages in thread From: Andrey Danin @ 2013-07-19 8:47 UTC (permalink / raw) To: u-boot Signed-off-by: Andrey Danin <danindrey@mail.ru> --- board/compal/dts/tegra20-paz00.dts | 8 ++++++++ include/configs/paz00.h | 8 ++++++++ 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/board/compal/dts/tegra20-paz00.dts b/board/compal/dts/tegra20-paz00.dts index 780203c..2df5446 100644 --- a/board/compal/dts/tegra20-paz00.dts +++ b/board/compal/dts/tegra20-paz00.dts @@ -88,4 +88,12 @@ nvidia,panel-vdd-gpios = <&gpio 4 0>; /* PA4 */ nvidia,panel-timings = <400 4 203 17 15>; }; + + nvec { + compatible = "nvidia,tegra20-nvec"; + reg = <0x7000c500 0x100>; + clock-frequency = <80000>; + request-gpios = <&gpio 170 0>; /* gpio PV2 */ + slave-addr = <138>; + }; }; diff --git a/include/configs/paz00.h b/include/configs/paz00.h index eac1ef9..d711be8 100644 --- a/include/configs/paz00.h +++ b/include/configs/paz00.h @@ -72,6 +72,14 @@ #define CONFIG_SYS_WHITE_ON_BLACK #define CONFIG_CONSOLE_SCROLL_LINES 10 +/* Keyboard support */ +#define CONFIG_KEYBOARD +#define CONFIG_TEGRA_NVEC_KEYBOARD +/* NVEC support */ +#define CONFIG_TEGRA_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_TEGRA_NVEC + #include "tegra-common-post.h" #endif /* __CONFIG_H */ -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nvec keyboard support 2013-07-19 8:47 ` [U-Boot] [PATCH 3/3] ARM: tegra: paz00: enable nvec keyboard support Andrey Danin @ 2013-07-19 19:14 ` Stephen Warren 2013-07-20 9:12 ` [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboard support Marc Dietrich 0 siblings, 1 reply; 12+ messages in thread From: Stephen Warren @ 2013-07-19 19:14 UTC (permalink / raw) To: u-boot On 07/19/2013 02:47 AM, Andrey Danin wrote: > Signed-off-by: Andrey Danin <danindrey@mail.ru> (Some patch descriptions would be useful) > diff --git a/board/compal/dts/tegra20-paz00.dts b/board/compal/dts/tegra20-paz00.dts > + nvec { > + compatible = "nvidia,tegra20-nvec"; > + reg = <0x7000c500 0x100>; > + clock-frequency = <80000>; > + request-gpios = <&gpio 170 0>; /* gpio PV2 */ > + slave-addr = <138>; > + }; I would rather not propagate this DT binding. We need to fix the binding to clearly separate the concepts of: a) The I2C slave controller (which should be a standalone driver for the Tegra I2C slave HW). b) The protocol sent over the I2C slave channel (which would be specific to NVEC, implement the GPIO hand-shaking, etc.). c) The devices that communicate over the protocol (keyboard in this case). I suspect we need separate DT nodes/sub-nodes for all of those, and a method of hooking them all together. ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboard support 2013-07-19 19:14 ` [U-Boot] [Ac100] " Stephen Warren @ 2013-07-20 9:12 ` Marc Dietrich 2013-07-21 3:20 ` Stephen Warren 0 siblings, 1 reply; 12+ messages in thread From: Marc Dietrich @ 2013-07-20 9:12 UTC (permalink / raw) To: u-boot On Friday 19 July 2013 13:14:13 Stephen Warren wrote: > On 07/19/2013 02:47 AM, Andrey Danin wrote: > > Signed-off-by: Andrey Danin <danindrey@mail.ru> > > (Some patch descriptions would be useful) > > > diff --git a/board/compal/dts/tegra20-paz00.dts > > b/board/compal/dts/tegra20-paz00.dts > > > > + nvec { > > + compatible = "nvidia,tegra20-nvec"; > > + reg = <0x7000c500 0x100>; > > + clock-frequency = <80000>; > > + request-gpios = <&gpio 170 0>; /* gpio PV2 */ > > + slave-addr = <138>; > > + }; > > I would rather not propagate this DT binding. We need to fix the binding > to clearly separate the concepts of: so here we go again. I think I have to take this on my shoulders since I didn't got it right yet in the kernel. > a) The I2C slave controller (which should be a standalone driver for the > Tegra I2C slave HW). > > b) The protocol sent over the I2C slave channel (which would be specific > to NVEC, implement the GPIO hand-shaking, etc.). > > c) The devices that communicate over the protocol (keyboard in this case). > > I suspect we need separate DT nodes/sub-nodes for all of those, and a > method of hooking them all together. Let's skip how this may actually look like in software. Given the discussions we had in the past, I propose the following binding: i2c-slave at 7000c500 { compatible = "nvidia,tegra20-i2c-slave"; reg = <0x7000c500 0x100>; interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; clock-frequency = <80000>; slave-addr = <138>; clocks = <&tegra_car 67>, <&tegra_car 124>; clock-names = "div-clk", "fast-clk"; nvec { compatible = "nvidia,nvec", "simple-bus"; protocol = "smbus-request-gpio"; request-gpios = <&gpio 170 0>; /* gpio PV2 */ keyboard { compatible = "nvidia,nvec-keyboard"; }; }; }; Does this looks better? Marc ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboard support 2013-07-20 9:12 ` [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboard support Marc Dietrich @ 2013-07-21 3:20 ` Stephen Warren 2013-07-22 8:09 ` [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport Marc Dietrich 0 siblings, 1 reply; 12+ messages in thread From: Stephen Warren @ 2013-07-21 3:20 UTC (permalink / raw) To: u-boot On 07/20/2013 03:12 AM, Marc Dietrich wrote: > On Friday 19 July 2013 13:14:13 Stephen Warren wrote: ... > Let's skip how this may actually look like in software. Given the discussions > we had in the past, I propose the following binding: > > i2c-slave at 7000c500 { > compatible = "nvidia,tegra20-i2c-slave"; > reg = <0x7000c500 0x100>; > interrupts = <0 92 0x04>; > #address-cells = <1>; > #size-cells = <0>; > clock-frequency = <80000>; > slave-addr = <138>; Hex would be more common, but that's a minor issue. > clocks = <&tegra_car 67>, <&tegra_car 124>; > clock-names = "div-clk", "fast-clk"; > > nvec { Above, it says #address-cells=<1>, which means this node needs a reg property. Perhaps slave-addr should be part of the child nodes (and the Tegra I2C controller binding would limit itself to supporting only a single node), so that the same binding style could be applicable to I2C slave devices that support multiple slave addresses. > compatible = "nvidia,nvec", "simple-bus"; > protocol = "smbus-request-gpio"; What is that property for; doesn't compatible="nvidia,nvec" already imply this, or does the NVEC spec define multiple different protocols? > request-gpios = <&gpio 170 0>; /* gpio PV2 */ We should use the C pre-processor to provide named constants there, although I guess U-Boot isn't set up for that yet. The kernel is once this is ported there, and once the 2013.07 release is out, U-Boot should be able to support this very soon too. > keyboard { Simple-bus might require a reg property; I forget. Does the NVEC protocol include any form of "virtual device address" that it would make sense to put into a reg property? > compatible = "nvidia,nvec-keyboard"; > }; > }; > }; > > Does this looks better? Yes, overall much better. New DT bindings should be sent to devicetree at vger.kernel.org for review. Note that's a branch new list (it moved from a different server), so it might be best to wait a few days for people to subscribe before sending mail to it. ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport 2013-07-21 3:20 ` Stephen Warren @ 2013-07-22 8:09 ` Marc Dietrich 2013-07-23 15:40 ` Stephen Warren 0 siblings, 1 reply; 12+ messages in thread From: Marc Dietrich @ 2013-07-22 8:09 UTC (permalink / raw) To: u-boot Am Samstag, 20. Juli 2013, 21:20:52 schrieb Stephen Warren: > On 07/20/2013 03:12 AM, Marc Dietrich wrote: > > On Friday 19 July 2013 13:14:13 Stephen Warren wrote: > ... > > > Let's skip how this may actually look like in software. Given the > > discussions we had in the past, I propose the following binding: > > > > i2c-slave at 7000c500 { > > > > compatible = "nvidia,tegra20-i2c-slave"; > > reg = <0x7000c500 0x100>; > > interrupts = <0 92 0x04>; > > #address-cells = <1>; > > #size-cells = <0>; > > clock-frequency = <80000>; > > slave-addr = <138>; > > Hex would be more common, but that's a minor issue. ok. > > clocks = <&tegra_car 67>, <&tegra_car 124>; > > clock-names = "div-clk", "fast-clk"; > > > > nvec { > > Above, it says #address-cells=<1>, which means this node needs a reg > property. Perhaps slave-addr should be part of the child nodes (and the > Tegra I2C controller binding would limit itself to supporting only a > single node), so that the same binding style could be applicable to I2C > slave devices that support multiple slave addresses. you mean nvec at 87 { reg = <0x87>; ... } ? I think that's ok. Didn't know that Tegra can support multiple slave addresses. To make the binding as general as possible, we could support multi- slave for the binding, but only support single slave in the code for now. I guess that also warrants a "simple-bus" compatibility in the i2c-slave node. > > > compatible = "nvidia,nvec", "simple-bus"; > > protocol = "smbus-request-gpio"; > > What is that property for; doesn't compatible="nvidia,nvec" already > imply this, or does the NVEC spec define multiple different protocols? The GPIO is optional, but SMBUS is required. Maybe to support master initiated communications only. To get rid of the ugly protocol property, we could just check if a valid gpio is given. I think that's what the downstream kernel also does. The nvec still needs to tell the slave driver which protocol to use, but that can be hard coded. > > request-gpios = <&gpio 170 0>; /* gpio PV2 */ > > We should use the C pre-processor to provide named constants there, > although I guess U-Boot isn't set up for that yet. The kernel is once > this is ported there, and once the 2013.07 release is out, U-Boot should > be able to support this very soon too. > > > keyboard { > > Simple-bus might require a reg property; I forget. Does the NVEC > protocol include any form of "virtual device address" that it would make > sense to put into a reg property? > > > compatible = "nvidia,nvec-keyboard"; well, we could misuse the nvec function select byte for this (e.g. 5 for keyboard, 6 for mouse, ...), but we may run into trouble with the "system command = 1" which is used by several drivers. > > > > Does this looks better? > > Yes, overall much better. > > New DT bindings should be sent to devicetree at vger.kernel.org for review. > Note that's a branch new list (it moved from a different server), so it > might be best to wait a few days for people to subscribe before sending > mail to it. Ok, I'll send out a new version and cc dtml. Maybe this some more people respond ;-) Thanks for review! Marc ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport 2013-07-22 8:09 ` [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport Marc Dietrich @ 2013-07-23 15:40 ` Stephen Warren 2013-07-24 17:52 ` Marc Dietrich 0 siblings, 1 reply; 12+ messages in thread From: Stephen Warren @ 2013-07-23 15:40 UTC (permalink / raw) To: u-boot On 07/22/2013 01:09 AM, Marc Dietrich wrote: > Am Samstag, 20. Juli 2013, 21:20:52 schrieb Stephen Warren: >> On 07/20/2013 03:12 AM, Marc Dietrich wrote: >>> On Friday 19 July 2013 13:14:13 Stephen Warren wrote: >> ... >> >>> Let's skip how this may actually look like in software. Given the >>> discussions we had in the past, I propose the following binding: >>> >>> i2c-slave at 7000c500 { >>> #address-cells = <1>; >>> #size-cells = <0>; >>> nvec { >> >> Above, it says #address-cells=<1>, which means this node needs a reg >> property. Perhaps slave-addr should be part of the child nodes (and the >> Tegra I2C controller binding would limit itself to supporting only a >> single node), so that the same binding style could be applicable to I2C >> slave devices that support multiple slave addresses. > > you mean > > nvec at 87 { > reg = <0x87>; > ... > } ? Yes. > I think that's ok. Didn't know that Tegra can support multiple slave > addresses. To make the binding as general as possible, we could support multi- > slave for the binding, but only support single slave in the code for now. Tegra can't, but that doesn't mean some future Tegra or some other SoC can't/won't. Putting the slave address inside the child node makes sure the same DT schema will work in other situations, and hence be consistent. > I guess that also warrants a "simple-bus" compatibility in the i2c-slave node. > >> >>> compatible = "nvidia,nvec", "simple-bus"; >>> protocol = "smbus-request-gpio"; >> >> What is that property for; doesn't compatible="nvidia,nvec" already >> imply this, or does the NVEC spec define multiple different protocols? > > The GPIO is optional, but SMBUS is required. Maybe to support master initiated > communications only. To get rid of the ugly protocol property, we could just > check if a valid gpio is given. I think that's what the downstream kernel also > does. Yes, I believe nvidia,nvec implies everything about the protocol then, except for the optional GPIO which can be checked directly. > The nvec still needs to tell the slave driver which protocol to use, but > that can be hard coded. I'm not sure what that means. At the controller/HW level, aren't I2C and SMBUS the same; it's just the data within the transactions that may be more defined by one or the other? ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport 2013-07-23 15:40 ` Stephen Warren @ 2013-07-24 17:52 ` Marc Dietrich 2013-07-25 17:40 ` Stephen Warren 0 siblings, 1 reply; 12+ messages in thread From: Marc Dietrich @ 2013-07-24 17:52 UTC (permalink / raw) To: u-boot On Tuesday 23 July 2013 08:40:42 Stephen Warren wrote: > On 07/22/2013 01:09 AM, Marc Dietrich wrote: [ snip the stuff we agreed upon ] > > The nvec still needs to tell the slave driver which protocol to use, but > > that can be hard coded. > > I'm not sure what that means. At the controller/HW level, aren't I2C and > SMBUS the same; it's just the data within the transactions that may be > more defined by one or the other? at this level yes, but we need to handle the underlying protocol in the ISR, which means that depending on the protocol (smbus or I2C), we need a different interrupt service routine. Currently we are doing most of the smbus protocol in the ISR because of timing reasons and I'm not sure if we can change this. We are already suffering from nvec timeouts and I fear that splitting the protocol out of the ISR would make things even worse. I'm going to submit a new DT binding during the weekend. Meanwhile, Andrey is trying to split the uboot driver in the hw and nvec parts and also adapting it for the new binding. Marc ^ permalink raw reply [flat|nested] 12+ messages in thread
* [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport 2013-07-24 17:52 ` Marc Dietrich @ 2013-07-25 17:40 ` Stephen Warren 0 siblings, 0 replies; 12+ messages in thread From: Stephen Warren @ 2013-07-25 17:40 UTC (permalink / raw) To: u-boot On 07/24/2013 10:52 AM, Marc Dietrich wrote: > On Tuesday 23 July 2013 08:40:42 Stephen Warren wrote: >> On 07/22/2013 01:09 AM, Marc Dietrich wrote: > > [ snip the stuff we agreed upon ] > >>> The nvec still needs to tell the slave driver which protocol to use, but >>> that can be hard coded. >> >> I'm not sure what that means. At the controller/HW level, aren't I2C and >> SMBUS the same; it's just the data within the transactions that may be >> more defined by one or the other? > > at this level yes, but we need to handle the underlying protocol in the ISR, > which means that depending on the protocol (smbus or I2C), we need a different > interrupt service routine. Currently we are doing most of the smbus protocol > in the ISR because of timing reasons and I'm not sure if we can change this. > We are already suffering from nvec timeouts and I fear that splitting the > protocol out of the ISR would make things even worse. I assume that the I2C slave driver's ISR would simply directly/immediately call a function in the "protocol driver". That should allow sufficient separation of the layers while still maintaining minimal latency, assuming a good design of the callback's function prototype and/or the list of I2C slave controller functions that the callback is allowed to call into. ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-07-25 17:40 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-07-19 8:47 [U-Boot] [PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00 Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 1/3] ARM: tegra: add nvec driver Andrey Danin 2013-07-19 16:28 ` Tom Warren 2013-07-19 8:47 ` [U-Boot] [PATCH 2/3] ARM: tegra: add input driver for nvec keyboard Andrey Danin 2013-07-19 8:47 ` [U-Boot] [PATCH 3/3] ARM: tegra: paz00: enable nvec keyboard support Andrey Danin 2013-07-19 19:14 ` [U-Boot] [Ac100] " Stephen Warren 2013-07-20 9:12 ` [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboard support Marc Dietrich 2013-07-21 3:20 ` Stephen Warren 2013-07-22 8:09 ` [U-Boot] [Ac100] [PATCH 3/3] ARM: tegra: paz00: enable nveckeyboardsupport Marc Dietrich 2013-07-23 15:40 ` Stephen Warren 2013-07-24 17:52 ` Marc Dietrich 2013-07-25 17:40 ` Stephen Warren
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox