Skip to contentSkip to conversation

ARM: tegra: add nvec keyboard support for paz00

PATCH New Andrey Danin 4 participants 12 messages Jul 19, 2013 – Jul 25, 2013

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover ARM: tegra: add nvec keyboard support for paz00

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
#1 lore raw

PATCH 1/3 ARM: tegra: add nvec driver

Adopted version of nvec driver from linux kernel with keyboard support only.

---
 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
arch/arm/include/asm/arch-tegra/tegra_nvec.h new file +117 -0
new file mode 100644
index 0000000..1c30028
@@ -0,0 +1,117 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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_ */
arch/arm/include/asm/arch-tegra/tegra_nvec_events.h new file +31 -0
new file mode 100644
index 0000000..7d65921
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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_ */
arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h new file +36 -0
new file mode 100644
index 0000000..b25a1d8
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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_ */
arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h new file +313 -0

313 lines not on this page · raw message

board/nvidia/common/board.c +12 -0
index f60f21f..e5da061 100644
@@ -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;
 }
 
drivers/i2c/Makefile +1 -0
index 72e85a3..6ff3b22 100644
@@ -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
drivers/i2c/tegra_nvec.c new file +462 -0

462 lines not on this page · raw message

drivers/i2c/tegra_nvec_keyboard.c new file +108 -0

108 lines not on this page · raw message

include/fdtdec.h +1 -0
index cd336fa..8917e34 100644
@@ -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 */
lib/Makefile +1 -0
index 5d58609..b338211 100644
@@ -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
lib/fdtdec.c +1 -0
index e322b82..4c70c79 100644
@@ -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"),
Signature · 1 line
1.7.1
#2 lore raw

PATCH 1/3 ARM: tegra: add nvec driver

Andrey,

Quoted 11 lines

-----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.

Quoted 6 lines
---
 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?

Quoted 4 lines
 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/?

Quoted 169 lines
 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

arch/arm/include/asm/arch-tegra/tegra_nvec.h new file +15 -0
new file mode 100644
index 0000000..1c30028
@@ -0,0 +1,117 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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
+ */

arch/arm/include/asm/arch-tegra/tegra_nvec.h new file +95 -0
+
+#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_ */
arch/arm/include/asm/arch-tegra/tegra_nvec_events.h new file +15 -0
new file mode 100644
index 0000000..7d65921
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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
+ */

arch/arm/include/asm/arch-tegra/tegra_nvec_events.h line 28

Quoted 6 lines
arch/arm/include/asm/arch-tegra/tegra_nvec_events.h new file +6 -0
+
+#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.

Quoted 1,036 lines
arch/arm/include/asm/arch-tegra/tegra_nvec_events.h new file +3 -0
+
+
+#endif /* _TEGRA_NVEC_EVENTS_H_ */
arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h new file +15 -0
new file mode 100644
index 0000000..b25a1d8
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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
+ */

arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h new file +13 -0
+
+#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_ */
arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h new file +15 -0
new file mode 100644
index 0000000..8fbf96c
@@ -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

arch/arm/include/asm/arch-tegra/tegra_nvec_keytable.h new file +305 -0
+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_ */
board/nvidia/common/board.c +11 -0
index f60f21f..e5da061 100644
@@ -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;
 }
 
drivers/i2c/Makefile index renamed from drivers/i2c/Makefile +0 -0

72e85a3..6ff3b22 100644

drivers/i2c/Makefile +0 -0
@@ -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

drivers/i2c/Makefile +1 -0
+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
drivers/i2c/tegra_nvec.c new file renamed from drivers/i2c/tegra_nvec.c +0 -0

mode 100644 index 0000000..1589003

drivers/i2c/tegra_nvec.c new file +15 -0
@@ -0,0 +1,462 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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
+ */

drivers/i2c/tegra_nvec.c new file +168 -0
+
+#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);

drivers/i2c/tegra_nvec.c new file +20 -0
+                             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");

drivers/i2c/tegra_nvec.c new file +11 -0
+                                     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;

drivers/i2c/tegra_nvec.c new file +105 -0
+                             ++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 |

drivers/i2c/tegra_nvec.c new file +31 -0
+         (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);

drivers/i2c/tegra_nvec.c new file +73 -0
+     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);

drivers/i2c/tegra_nvec.c new file +16 -0
+             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);

drivers/i2c/tegra_nvec.c new file +6 -0
+                     return 0;
+             }
+     }
+
+     return 0;
+}
drivers/i2c/tegra_nvec_keyboard.c new file +15 -0
new file mode 100644
index 0000000..0837f08
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2013
+ * Andrey Danin <[email protected]>
+ *
+ * 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
+ */

drivers/i2c/tegra_nvec_keyboard.c new file +13 -0
+
+#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

drivers/i2c/tegra_nvec_keyboard.c new file +13 -0
+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)); }

drivers/i2c/tegra_nvec_keyboard.c new file +12 -0
+
+
+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));

drivers/i2c/tegra_nvec_keyboard.c new file +43 -0
+
+     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"); }
include/fdtdec.h index cd336fa..8917e34 renamed from include/fdtdec.h +0 -0

100644

include/fdtdec.h +0 -0
@@ -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 */

lib/Makefile +1 -0
@@ -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
lib/fdtdec.c +1 -0
@@ -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"),
Quoted 3 lines

COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
--
1.7.1

Tom
--
nvpublic

#3 lore raw

PATCH 2/3 ARM: tegra: add input driver for nvec keyboard

In reply to Andrey Danin
---
 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
drivers/input/Makefile +1 -0
index 0805e86..20ef7b2 100644
@@ -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
drivers/input/tegra-nvec-kbc.c new file +131 -0

131 lines not on this page · raw message

include/configs/tegra-common-post.h +2 -0
index 6ed2fde..b01a072 100644
@@ -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
Signature · 1 line
1.7.1
#4 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nvec keyboard support

In reply to Andrey Danin
---
 board/compal/dts/tegra20-paz00.dts |    8 ++++++++
 include/configs/paz00.h            |    8 ++++++++
 2 files changed, 16 insertions(+), 0 deletions(-)
board/compal/dts/tegra20-paz00.dts +8 -0
index 780203c..2df5446 100644
@@ -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>;
+	};
 };
include/configs/paz00.h +8 -0
index eac1ef9..d711be8 100644
@@ -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 */
Signature · 1 line
1.7.1
#5 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nvec keyboard support

Quoted 1 line · Andrey Danin

(Some patch descriptions would be useful)

board/compal/dts/tegra20-paz00.dts line 98

Quoted 9 lines
board/compal/dts/tegra20-paz00.dts +7 -0
 
+	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.

#6 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nveckeyboard support

Quoted 8 lines · On Friday 19 July 2013 13:14:13 Stephen Warren wrote:
Quoted 1 line · Andrey Danin

(Some patch descriptions would be useful)

Quoted 3 lines
board/compal/dts/tegra20-paz00.dts +0 -0
Quoted 10 lines

board/compal/dts/tegra20-paz00.dts line 98

Quoted 7 lines
board/compal/dts/tegra20-paz00.dts +7 -0
+	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.

Quoted 10 lines

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

#7 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nveckeyboard support

Quoted 1 line · Marc Dietrich

On Friday 19 July 2013 13:14:13 Stephen Warren wrote:

...

Quoted 11 lines

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.

Quoted 4 lines
	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.

Quoted 2 lines
		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?

Quoted 1 line
		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.

Quoted 1 line
		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?

Quoted 6 lines
			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.

#8 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nveckeyboardsupport

Am Samstag, 20. Juli 2013, 21:20:52 schrieb Stephen Warren:

Quoted 17 lines · Marc Dietrich
Quoted 1 line · On Friday 19 July 2013 13:14:13 Stephen Warren wrote:

...

Quoted 5 lines

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 {

Quoted 7 lines
	compatible = "nvidia,tegra20-i2c-slave";
	reg = <0x7000c500 0x100>;
	interrupts = <0 92 0x04>;
	#address-cells = <1>;
	#size-cells = <0>;
	clock-frequency = <80000>;
	slave-addr = <138>;
Quoted 1 line

Hex would be more common, but that's a minor issue.

ok.

Quoted 10 lines
Quoted 4 lines
	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.

Quoted 6 lines
Quoted 3 lines
		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.

Quoted 7 lines
Quoted 1 line
		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.

Quoted 7 lines
Quoted 1 line
		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?

Quoted 1 line
			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.

Quoted 9 lines
Quoted 2 lines

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

#9 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nveckeyboardsupport

Quoted 21 lines · Marc Dietrich

Am Samstag, 20. Juli 2013, 21:20:52 schrieb Stephen Warren:

Quoted 12 lines · Marc Dietrich
Quoted 1 line · On Friday 19 July 2013 13:14:13 Stephen Warren wrote:

...

Quoted 7 lines

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>;
Quoted 7 lines
Quoted 1 line
	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.

Quoted 6 lines

you mean

nvec at 87 {
		reg = <0x87>;
		...
} ?

Yes.

Quoted 3 lines

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.

Quoted 6 lines

I guess that also warrants a "simple-bus" compatibility in the i2c-slave node.

Quoted 4 lines
Quoted 3 lines
		compatible = "nvidia,nvec", "simple-bus";
		protocol = "smbus-request-gpio";
Quoted 7 lines
Quoted 2 lines

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.

Quoted 2 lines

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?

#10 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nveckeyboardsupport

Quoted 1 line · 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 ]

Quoted 6 lines
Quoted 2 lines

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

#11 lore raw

PATCH 3/3 ARM: tegra: paz00: enable nveckeyboardsupport

Quoted 12 lines · Marc Dietrich
Quoted 1 line · 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 ]

Quoted 6 lines
Quoted 2 lines

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?

Quoted 6 lines

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.