All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hung-ying Tyan <tyanh@chromium.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 2/7] cros: add I2C support for cros_ec
Date: Tue, 19 Mar 2013 00:22:02 +0800	[thread overview]
Message-ID: <1363623727-22073-3-git-send-email-tyanh@chromium.org> (raw)
In-Reply-To: <1363623727-22073-1-git-send-email-tyanh@chromium.org>

This patch adds I2C support for carrying out the cros_ec protocol.

Signed-off-by: Randall Spangler <rspangler@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Hung-ying Tyan <tyanh@chromium.org>

---
Changes in v2:
- Wrapped lines to comply with the 80-char rule.

 drivers/misc/Makefile      |   1 +
 drivers/misc/cros_ec_i2c.c | 199 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 200 insertions(+)
 create mode 100644 drivers/misc/cros_ec_i2c.c

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 33fe822..9363ef9 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
 COBJS-$(CONFIG_GPIO_LED) += gpio_led.o
 COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
 COBJS-$(CONFIG_CROS_EC) += cros_ec.o
+COBJS-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
 COBJS-$(CONFIG_NS87308) += ns87308.o
 COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
 COBJS-$(CONFIG_STATUS_LED) += status_led.o
diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c
new file mode 100644
index 0000000..b0060ac
--- /dev/null
+++ b/drivers/misc/cros_ec_i2c.c
@@ -0,0 +1,199 @@
+/*
+ * Chromium OS cros_ec driver - I2C interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <cros_ec.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...)	debug(fmt, #b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len)
+{
+	int old_bus = 0;
+	/* version8, cmd8, arglen8, out8[dout_len], csum8 */
+	int out_bytes = dout_len + 4;
+	/* response8, arglen8, in8[din_len], checksum8 */
+	int in_bytes = din_len + 3;
+	uint8_t *ptr;
+	/* Receive input data, so that args will be dword aligned */
+	uint8_t *in_ptr;
+	int ret;
+
+	old_bus = i2c_get_bus_num();
+
+	/*
+	 * Sanity-check I/O sizes given transaction overhead in internal
+	 * buffers.
+	 */
+	if (out_bytes > sizeof(dev->dout)) {
+		debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+		return -1;
+	}
+	if (in_bytes > sizeof(dev->din)) {
+		debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+		return -1;
+	}
+	assert(dout_len >= 0);
+	assert(dinp);
+
+	/*
+	 * Copy command and data into output buffer so we can do a single I2C
+	 * burst transaction.
+	 */
+	ptr = dev->dout;
+
+	/*
+	 * in_ptr starts of pointing to a dword-aligned input data buffer.
+	 * We decrement it back by the number of header bytes we expect to
+	 * receive, so that the first parameter of the resulting input data
+	 * will be dword aligned.
+	 */
+	in_ptr = dev->din + sizeof(int64_t);
+	if (!dev->cmd_version_is_supported) {
+		/* Send an old-style command */
+		*ptr++ = cmd;
+		out_bytes = dout_len + 1;
+		in_bytes = din_len + 2;
+		in_ptr--;	/* Expect just a status byte */
+	} else {
+		*ptr++ = EC_CMD_VERSION0 + cmd_version;
+		*ptr++ = cmd;
+		*ptr++ = dout_len;
+		in_ptr -= 2;	/* Expect status, length bytes */
+	}
+	memcpy(ptr, dout, dout_len);
+	ptr += dout_len;
+
+	if (dev->cmd_version_is_supported)
+		*ptr++ = (uint8_t)
+			 cros_ec_calc_checksum(dev->dout, dout_len + 3);
+
+	/* Set to the proper i2c bus */
+	if (i2c_set_bus_num(dev->bus_num)) {
+		debug("%s: Cannot change to I2C bus %d\n", __func__,
+			dev->bus_num);
+		return -1;
+	}
+
+	/* Send output data */
+	cros_ec_dump_data("out", -1, dev->dout, out_bytes);
+	ret = i2c_write(dev->addr, 0, 0, dev->dout, out_bytes);
+	if (ret) {
+		debug("%s: Cannot complete I2C write to 0x%x\n",
+			__func__, dev->addr);
+		ret = -1;
+	}
+
+	if (!ret) {
+		ret = i2c_read(dev->addr, 0, 0, in_ptr, in_bytes);
+		if (ret) {
+			debug("%s: Cannot complete I2C read from 0x%x\n",
+				__func__, dev->addr);
+			ret = -1;
+		}
+	}
+
+	/* Return to original bus number */
+	i2c_set_bus_num(old_bus);
+	if (ret)
+		return ret;
+
+	if (*in_ptr != EC_RES_SUCCESS) {
+		debug("%s: Received bad result code %d\n", __func__, *in_ptr);
+		return -(int)*in_ptr;
+	}
+
+	if (dev->cmd_version_is_supported) {
+		int len, csum;
+
+		len = in_ptr[1];
+		if (len + 3 > sizeof(dev->din)) {
+			debug("%s: Received length %#02x too large\n",
+			      __func__, len);
+			return -1;
+		}
+		csum = cros_ec_calc_checksum(in_ptr, 2 + len);
+		if (csum != in_ptr[2 + len]) {
+			debug("%s: Invalid checksum rx %#02x, calced %#02x\n",
+			      __func__, in_ptr[2 + din_len], csum);
+			return -1;
+		}
+		din_len = min(din_len, len);
+		cros_ec_dump_data("in", -1, in_ptr, din_len + 3);
+	} else {
+		cros_ec_dump_data("in (old)", -1, in_ptr, in_bytes);
+	}
+
+	/* Return pointer to dword-aligned input data, if any */
+	*dinp = dev->din + sizeof(int64_t);
+
+	return din_len;
+}
+
+int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+{
+	/* Decode interface-specific FDT params */
+	dev->max_frequency = fdtdec_get_int(blob, dev->node,
+					    "i2c-max-frequency", 100000);
+	dev->bus_num = i2c_get_bus_num_fdt(dev->parent_node);
+	if (dev->bus_num == -1) {
+		debug("%s: Failed to read bus number\n", __func__);
+		return -1;
+	}
+	dev->addr = fdtdec_get_int(blob, dev->node, "reg", -1);
+	if (dev->addr == -1) {
+		debug("%s: Failed to read device address\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Initialize I2C protocol.
+ *
+ * @param dev		CROS_EC device
+ * @param blob		Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob)
+{
+	i2c_init(dev->max_frequency, dev->addr);
+
+	dev->cmd_version_is_supported = 0;
+
+	return 0;
+}
-- 
1.8.1.3

  parent reply	other threads:[~2013-03-18 16:22 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-18 16:22 [U-Boot] [PATCH v2 0/7] Add cros-ec protocol driver and enable it in smdk5250 Hung-ying Tyan
2013-03-18 16:22 ` [U-Boot] [PATCH v2 1/7] cros: add cros_ec driver Hung-ying Tyan
2013-03-21 16:56   ` Simon Glass
2013-03-18 16:22 ` Hung-ying Tyan [this message]
2013-03-21 16:57   ` [U-Boot] [PATCH v2 2/7] cros: add I2C support for cros_ec Simon Glass
2013-03-18 16:22 ` [U-Boot] [PATCH v2 3/7] cros: add SPI " Hung-ying Tyan
2013-03-21 16:58   ` Simon Glass
2013-03-18 16:22 ` [U-Boot] [PATCH v2 4/7] cros: add LPC " Hung-ying Tyan
2013-03-21 16:59   ` Simon Glass
2013-03-18 16:22 ` [U-Boot] [PATCH v2 5/7] cros: adds cros_ec keyboard driver Hung-ying Tyan
2013-03-21 17:02   ` Simon Glass
2013-03-18 16:22 ` [U-Boot] [PATCH v2 6/7] cros: exynos: add cros-ec device nodes to exynos5250-snow.dts Hung-ying Tyan
2013-03-21 17:49   ` Simon Glass
2013-03-18 16:22 ` [U-Boot] [PATCH v2 7/7] cros: enable cros-ec for smdk5250 Hung-ying Tyan
2013-03-23  0:39   ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1363623727-22073-3-git-send-email-tyanh@chromium.org \
    --to=tyanh@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.