Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1642652 > unrolled thread

[PATCH RESEND 00/13] platform/chrome: Add console debugfs, lpc and lightbar programming support

Started byEnric Balletbo i Serra <enric.balletbo@collabora.com>
First post2017-05-16 18:20 +0200
Last post2017-05-22 13:10 +0200
Articles 7 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH RESEND 00/13] platform/chrome: Add console debugfs, lpc and lightbar programming support Enric Balletbo i Serra <enric.balletbo@collabora.com> - 2017-05-16 18:20 +0200
    [PATCH RESEND 01/13] mfd: cros_ec: Add helper for event notifier. Enric Balletbo i Serra <enric.balletbo@collabora.com> - 2017-05-16 18:20 +0200
    [PATCH RESEND 09/13] platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI Enric Balletbo i Serra <enric.balletbo@collabora.com> - 2017-05-16 18:20 +0200
    [PATCH RESEND 13/13] platform/chrome: cros_ec_lightbar - Avoid I2C xfer to EC during suspend Enric Balletbo i Serra <enric.balletbo@collabora.com> - 2017-05-16 18:20 +0200
    [PATCH RESEND 04/13] mfd: cros_ec: Add support for dumping panic information Enric Balletbo i Serra <enric.balletbo@collabora.com> - 2017-05-16 18:20 +0200
    [PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants Enric Balletbo i Serra <enric.balletbo@collabora.com> - 2017-05-16 18:20 +0200
      Re: [PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W  helpers to LPC protocol variants Lee Jones <lee.jones@linaro.org> - 2017-05-22 13:10 +0200

#1642652 — [PATCH RESEND 00/13] platform/chrome: Add console debugfs, lpc and lightbar programming support

FromEnric Balletbo i Serra <enric.balletbo@collabora.com>
Date2017-05-16 18:20 +0200
Subject[PATCH RESEND 00/13] platform/chrome: Add console debugfs, lpc and lightbar programming support
Message-ID<tHNmy-7PP-11@gated-at.bofh.it>
Dear Olof, Benson,

We have some patches that stayed in the mailing list for long time and already missed some merge window. Please kindly take into consideration to not miss more merge windows.

As some patches depends on the other to apply cleanly I created a patch series with all includes to make easier the merge, so this series include the following patches.

 - https://lkml.org/lkml/2016/8/23/10
 - https://lkml.org/lkml/2016/12/2/360
 - https://lkml.org/lkml/2016/12/16/438
 - https://lkml.org/lkml/2017/1/11/579

This series is a rebase on top of linux-next

If you prefer to pick the patches from a git repository, the following
changes since commit 15efd2015d5e7265273187d37a89aa985565ab2d

  mfd: cros_ec: Add helper for event notifier.

are available in the git repository at:

  https://git.collabora.com/cgit/linux.git upstream/chromeos/for-4.13

for you to fetch changes up to ee7c27a73820c245af2a29cdd3810196c2b02b67

  platform/chrome: cros_ec_lightbar - Avoid I2C xfer to EC during suspend

Many thanks for your help,
 Enric

Archana Patni (1):
  platform/chrome: cros_ec_lpc: Add power management ops

Eric Caruso (4):
  mfd: cros_ec: add debugfs, console log file
  platform/chrome: cros_ec_lightbar - Add lightbar program feature to
    sysfs
  platform/chrome: cros_ec_lightbar - Control of suspend/resume lightbar
    sequence
  platform/chrome: cros_ec_lightbar - Add userspace lightbar control bit
    to EC

Gwendal Grignou (3):
  mfd: cros_ec: Add helper for event notifier.
  platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device
  platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

Jeffery Yu (1):
  platform/chrome: cros_ec_lightbar - Avoid I2C xfer to EC during
    suspend

Nicolas Boichat (2):
  mfd: cros_ec: Add EC console read structures definitions
  mfd: cros_ec: Add support for dumping panic information

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig            |  14 +-
 drivers/platform/chrome/Makefile           |   7 +-
 drivers/platform/chrome/cros_ec_debugfs.c  | 401 +++++++++++++++++++++++++++++
 drivers/platform/chrome/cros_ec_debugfs.h  |  27 ++
 drivers/platform/chrome/cros_ec_dev.c      |  40 +++
 drivers/platform/chrome/cros_ec_dev.h      |   6 +
 drivers/platform/chrome/cros_ec_lightbar.c | 197 +++++++++++++-
 drivers/platform/chrome/cros_ec_lpc.c      | 167 +++++++-----
 drivers/platform/chrome/cros_ec_lpc_mec.c  | 140 ++++++++++
 drivers/platform/chrome/cros_ec_lpc_reg.c  | 133 ++++++++++
 drivers/platform/chrome/cros_ec_proto.c    |  20 ++
 include/linux/mfd/cros_ec.h                |  14 +
 include/linux/mfd/cros_ec_commands.h       |  42 ++-
 include/linux/mfd/cros_ec_lpc_mec.h        |  90 +++++++
 include/linux/mfd/cros_ec_lpc_reg.h        |  61 +++++
 15 files changed, 1286 insertions(+), 73 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_debugfs.c
 create mode 100644 drivers/platform/chrome/cros_ec_debugfs.h
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.9.3

[toc] | [next] | [standalone]


#1642653 — [PATCH RESEND 01/13] mfd: cros_ec: Add helper for event notifier.

FromEnric Balletbo i Serra <enric.balletbo@collabora.com>
Date2017-05-16 18:20 +0200
Subject[PATCH RESEND 01/13] mfd: cros_ec: Add helper for event notifier.
Message-ID<tHNmy-7PP-31@gated-at.bofh.it>
In reply to#1642652
From: Gwendal Grignou <gwendal@chromium.org>

Add cros_ec_get_event() entry point to retrieve event within functions
called by the notifier.

Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/platform/chrome/cros_ec_proto.c | 20 ++++++++++++++++++++
 include/linux/mfd/cros_ec.h             | 10 ++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index ed5dee7..7428c2b 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -494,3 +494,23 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev)
 		return get_keyboard_state_event(ec_dev);
 }
 EXPORT_SYMBOL(cros_ec_get_next_event);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+	u32 host_event;
+
+	BUG_ON(!ec_dev->mkbp_event_supported);
+
+	if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+		return 0;
+
+	if (ec_dev->event_size != sizeof(host_event)) {
+		dev_warn(ec_dev->dev, "Invalid host event size\n");
+		return 0;
+	}
+
+	host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event);
+
+	return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 28baee6..b61b2e0 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -300,6 +300,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * When MKBP is supported, when the EC raises an interrupt,
+ * We collect the events raised and call the functions in the ec notifier.
+ *
+ * This function is a helper to know which events are raised.
+ */
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1642654 — [PATCH RESEND 09/13] platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

FromEnric Balletbo i Serra <enric.balletbo@collabora.com>
Date2017-05-16 18:20 +0200
Subject[PATCH RESEND 09/13] platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI
Message-ID<tHNmz-7PP-35@gated-at.bofh.it>
In reply to#1642652
From: Gwendal Grignou <gwendal@chromium.org>

This patch installs a notify handler to process MKBP events for EC
firmware directing them over ACPI.

Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
---
 drivers/platform/chrome/cros_ec_lpc.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index 89afad7..eeb187e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -227,9 +227,20 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
 	return cnt;
 }
 
+static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
+{
+	struct cros_ec_device *ec_dev = data;
+
+	if (ec_dev->mkbp_event_supported && cros_ec_get_next_event(ec_dev) > 0)
+		blocking_notifier_call_chain(&ec_dev->event_notifier, 0,
+					     ec_dev);
+}
+
 static int cros_ec_lpc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct acpi_device *adev;
+	acpi_status status;
 	struct cros_ec_device *ec_dev;
 	u8 buf[2];
 	int ret;
@@ -277,12 +288,33 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/*
+	 * Connect a notify handler to process MKBP messages if we have a
+	 * companion ACPI device.
+	 */
+	adev = ACPI_COMPANION(dev);
+	if (adev) {
+		status = acpi_install_notify_handler(adev->handle,
+						     ACPI_ALL_NOTIFY,
+						     cros_ec_lpc_acpi_notify,
+						     ec_dev);
+		if (ACPI_FAILURE(status))
+			dev_warn(dev, "Failed to register notifier %08x\n",
+				 status);
+	}
+
 	return 0;
 }
 
 static int cros_ec_lpc_remove(struct platform_device *pdev)
 {
 	struct cros_ec_device *ec_dev;
+	struct acpi_device *adev;
+
+	adev = ACPI_COMPANION(&pdev->dev);
+	if (adev)
+		acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
+					   cros_ec_lpc_acpi_notify);
 
 	ec_dev = platform_get_drvdata(pdev);
 	cros_ec_remove(ec_dev);
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1642655 — [PATCH RESEND 13/13] platform/chrome: cros_ec_lightbar - Avoid I2C xfer to EC during suspend

FromEnric Balletbo i Serra <enric.balletbo@collabora.com>
Date2017-05-16 18:20 +0200
Subject[PATCH RESEND 13/13] platform/chrome: cros_ec_lightbar - Avoid I2C xfer to EC during suspend
Message-ID<tHNmz-7PP-33@gated-at.bofh.it>
In reply to#1642652
From: Jeffery Yu <jefferyy@nvidia.com>

A Mutex lock in cros_ec_cmd_xfer which may be held by frozen
Userspace thread during system suspending. So should not
call this routine in suspend thread.

Signed-off-by: Jeffery Yu <jefferyy@nvidia.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---
 drivers/platform/chrome/cros_ec_dev.c      | 12 ++++--------
 drivers/platform/chrome/cros_ec_lightbar.c | 13 +++++++++----
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index 7c26223..b9bf086 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -437,8 +437,7 @@ static int ec_device_probe(struct platform_device *pdev)
 		cros_ec_sensors_register(ec);
 
 	/* Take control of the lightbar from the EC. */
-	if (ec_has_lightbar(ec))
-		lb_manual_suspend_ctrl(ec, 1);
+	lb_manual_suspend_ctrl(ec, 1);
 
 	return 0;
 
@@ -452,8 +451,7 @@ static int ec_device_remove(struct platform_device *pdev)
 	struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
 
 	/* Let the EC take over the lightbar again. */
-	if (ec_has_lightbar(ec))
-		lb_manual_suspend_ctrl(ec, 0);
+	lb_manual_suspend_ctrl(ec, 0);
 
 	cros_ec_debugfs_remove(ec);
 
@@ -472,8 +470,7 @@ static int ec_device_suspend(struct device *dev)
 {
 	struct cros_ec_dev *ec = dev_get_drvdata(dev);
 
-	if (ec_has_lightbar(ec))
-		lb_suspend(ec);
+	lb_suspend(ec);
 
 	return 0;
 }
@@ -482,8 +479,7 @@ static int ec_device_resume(struct device *dev)
 {
 	struct cros_ec_dev *ec = dev_get_drvdata(dev);
 
-	if (ec_has_lightbar(ec))
-		lb_resume(ec);
+	lb_resume(ec);
 
 	return 0;
 }
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
index e570c1e..fd2b047 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -43,6 +43,7 @@ static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
  * If this is true, we won't do anything during suspend/resume.
  */
 static bool userspace_control;
+static struct cros_ec_dev *ec_with_lightbar;
 
 static ssize_t interval_msec_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
@@ -384,6 +385,9 @@ int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
 	struct cros_ec_command *msg;
 	int ret;
 
+	if (ec != ec_with_lightbar)
+		return 0;
+
 	msg = alloc_lightbar_cmd_msg(ec);
 	if (!msg)
 		return -ENOMEM;
@@ -413,7 +417,7 @@ int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
 
 int lb_suspend(struct cros_ec_dev *ec)
 {
-	if (userspace_control)
+	if (userspace_control || ec != ec_with_lightbar)
 		return 0;
 
 	return lb_send_empty_cmd(ec, LIGHTBAR_CMD_SUSPEND);
@@ -421,7 +425,7 @@ int lb_suspend(struct cros_ec_dev *ec)
 
 int lb_resume(struct cros_ec_dev *ec)
 {
-	if (userspace_control)
+	if (userspace_control || ec != ec_with_lightbar)
 		return 0;
 
 	return lb_send_empty_cmd(ec, LIGHTBAR_CMD_RESUME);
@@ -606,9 +610,10 @@ static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj,
 		return 0;
 
 	/* Only instantiate this stuff if the EC has a lightbar */
-	if (ec_has_lightbar(ec))
+	if (ec_has_lightbar(ec)) {
+		ec_with_lightbar = ec;
 		return a->mode;
-
+	}
 	return 0;
 }
 
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1642656 — [PATCH RESEND 04/13] mfd: cros_ec: Add support for dumping panic information

FromEnric Balletbo i Serra <enric.balletbo@collabora.com>
Date2017-05-16 18:20 +0200
Subject[PATCH RESEND 04/13] mfd: cros_ec: Add support for dumping panic information
Message-ID<tHNmz-7PP-37@gated-at.bofh.it>
In reply to#1642652
From: Nicolas Boichat <drinkcat@chromium.org>

This dumps the EC panic information from the previous reboot.

Similar to the information presented by ectool panicinfo, except
that we do not bother doing any parsing (we should write a small
offline tool for that).

Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Tested-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---
 drivers/platform/chrome/cros_ec_debugfs.c | 54 +++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
index f8195bb..8133c33 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -47,15 +47,19 @@
  * @log_mutex: mutex to protect circular buffer
  * @log_wq: waitqueue for log readers
  * @log_poll_work: recurring task to poll EC for new console log data
+ * @panicinfo_blob: panicinfo debugfs blob
  */
 struct cros_ec_debugfs {
 	struct cros_ec_dev *ec;
 	struct dentry *dir;
+	/* EC log */
 	struct circ_buf log_buffer;
 	struct cros_ec_command *read_msg;
 	struct mutex log_mutex;
 	wait_queue_head_t log_wq;
 	struct delayed_work log_poll_work;
+	/* EC panicinfo */
+	struct debugfs_blob_wrapper panicinfo_blob;
 };
 
 /*
@@ -308,6 +312,52 @@ static void cros_ec_cleanup_console_log(struct cros_ec_debugfs *debug_info)
 	}
 }
 
+static int cros_ec_create_panicinfo(struct cros_ec_debugfs *debug_info)
+{
+	struct cros_ec_device *ec_dev = debug_info->ec->ec_dev;
+	int ret;
+	struct cros_ec_command *msg;
+	int insize;
+
+	insize = ec_dev->max_response;
+
+	msg = devm_kzalloc(debug_info->ec->dev,
+			sizeof(*msg) + insize, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->command = EC_CMD_GET_PANIC_INFO;
+	msg->insize = insize;
+
+	ret = cros_ec_cmd_xfer(ec_dev, msg);
+	if (ret < 0) {
+		dev_warn(debug_info->ec->dev, "Cannot read panicinfo.\n");
+		ret = 0;
+		goto free;
+	}
+
+	/* No panic data */
+	if (ret == 0)
+		goto free;
+
+	debug_info->panicinfo_blob.data = msg->data;
+	debug_info->panicinfo_blob.size = ret;
+
+	if (!debugfs_create_blob("panicinfo",
+				 S_IFREG | S_IRUGO,
+				 debug_info->dir,
+				 &debug_info->panicinfo_blob)) {
+		ret = -ENOMEM;
+		goto free;
+	}
+
+	return 0;
+
+free:
+	devm_kfree(debug_info->ec->dev, msg);
+	return ret;
+}
+
 int cros_ec_debugfs_init(struct cros_ec_dev *ec)
 {
 	struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev);
@@ -324,6 +374,10 @@ int cros_ec_debugfs_init(struct cros_ec_dev *ec)
 	if (!debug_info->dir)
 		return -ENOMEM;
 
+	ret = cros_ec_create_panicinfo(debug_info);
+	if (ret)
+		goto remove_debugfs;
+
 	ret = cros_ec_create_console_log(debug_info);
 	if (ret)
 		goto remove_debugfs;
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1642658 — [PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

FromEnric Balletbo i Serra <enric.balletbo@collabora.com>
Date2017-05-16 18:20 +0200
Subject[PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
Message-ID<tHNmz-7PP-39@gated-at.bofh.it>
In reply to#1642652
From: Shawn Nematbakhsh <shawnn@chromium.org>

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
---
 drivers/platform/chrome/Makefile          |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c     | 88 +++++++++++++------------------
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 ++++++++++++++++++++++
 include/linux/mfd/cros_ec_lpc_reg.h       | 47 +++++++++++++++++
 4 files changed, 151 insertions(+), 51 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 3870afe..61182fd 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs			:= cros_ec_dev.o cros_ec_sysfs.o \
 					   cros_ec_lightbar.o cros_ec_vbc.o \
 					   cros_ec_debugfs.o
 obj-$(CONFIG_CROS_EC_CHARDEV)		+= cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)		+= cros_ec_lpc.o
+cros_ec_lpcs-objs			:= cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)		+= cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)		+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)	+= cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..6a782a6 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include <linux/io.h>
 #include <linux/mfd/cros_ec.h>
 #include <linux/mfd/cros_ec_commands.h>
+#include <linux/mfd/cros_ec_lpc_reg.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/printk.h>
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
 	unsigned long one_second = jiffies + HZ;
+	u8 data;
 
 	usleep_range(200, 300);
 	do {
-		if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+		if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, &data) &
+		    EC_LPC_STATUS_BUSY_MASK))
 			return 0;
 		usleep_range(100, 200);
 	} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
 	struct ec_host_request *request;
 	struct ec_host_response response;
-	u8 sum = 0;
-	int i;
+	u8 sum;
 	int ret = 0;
 	u8 *dout;
 
 	ret = cros_ec_prepare_tx(ec, msg);
 
 	/* Write buffer */
-	for (i = 0; i < ret; i++)
-		outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
 	request = (struct ec_host_request *)ec->dout;
 
 	/* Here we go */
-	outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+	sum = EC_COMMAND_PROTOCOL_3;
+	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum);
 
 	if (ec_response_timed_out()) {
 		dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 	}
 
 	/* Check result */
-	msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+	msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum);
 	ret = cros_ec_check_result(ec, msg);
 	if (ret)
 		goto done;
 
 	/* Read back response */
 	dout = (u8 *)&response;
-	for (i = 0; i < sizeof(response); i++) {
-		dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-		sum += dout[i];
-	}
+	sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
+				     dout);
 
 	msg->result = response.result;
 
@@ -97,11 +97,9 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 	}
 
 	/* Read response and process checksum */
-	for (i = 0; i < response.data_len; i++) {
-		msg->data[i] =
-			inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-		sum += msg->data[i];
-	}
+	sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET +
+				      sizeof(response), response.data_len,
+				      msg->data);
 
 	if (sum) {
 		dev_err(ec->dev,
@@ -121,8 +119,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
 				struct cros_ec_command *msg)
 {
 	struct ec_lpc_host_args args;
-	int csum;
-	int i;
+	u8 sum;
 	int ret = 0;
 
 	if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
@@ -139,24 +136,20 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
 	args.data_size = msg->outsize;
 
 	/* Initialize checksum */
-	csum = msg->command + args.flags +
-		args.command_version + args.data_size;
+	sum = msg->command + args.flags + args.command_version + args.data_size;
 
 	/* Copy data and update checksum */
-	for (i = 0; i < msg->outsize; i++) {
-		outb(msg->data[i], EC_LPC_ADDR_HOST_PARAM + i);
-		csum += msg->data[i];
-	}
+	sum += cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
+				       msg->data);
 
 	/* Finalize checksum and write args */
-	args.checksum = csum & 0xFF;
-	outb(args.flags, EC_LPC_ADDR_HOST_ARGS);
-	outb(args.command_version, EC_LPC_ADDR_HOST_ARGS + 1);
-	outb(args.data_size, EC_LPC_ADDR_HOST_ARGS + 2);
-	outb(args.checksum, EC_LPC_ADDR_HOST_ARGS + 3);
+	args.checksum = sum;
+	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
+				(u8 *)&args);
 
 	/* Here we go */
-	outb(msg->command, EC_LPC_ADDR_HOST_CMD);
+	sum = msg->command;
+	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum);
 
 	if (ec_response_timed_out()) {
 		dev_warn(ec->dev, "EC responsed timed out\n");
@@ -165,16 +158,14 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
 	}
 
 	/* Check result */
-	msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+	msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum);
 	ret = cros_ec_check_result(ec, msg);
 	if (ret)
 		goto done;
 
 	/* Read back args */
-	args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
-	args.command_version = inb(EC_LPC_ADDR_HOST_ARGS + 1);
-	args.data_size = inb(EC_LPC_ADDR_HOST_ARGS + 2);
-	args.checksum = inb(EC_LPC_ADDR_HOST_ARGS + 3);
+	cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
+			       (u8 *)&args);
 
 	if (args.data_size > msg->insize) {
 		dev_err(ec->dev,
@@ -185,20 +176,17 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
 	}
 
 	/* Start calculating response checksum */
-	csum = msg->command + args.flags +
-		args.command_version + args.data_size;
+	sum = msg->command + args.flags + args.command_version + args.data_size;
 
 	/* Read response and update checksum */
-	for (i = 0; i < args.data_size; i++) {
-		msg->data[i] = inb(EC_LPC_ADDR_HOST_PARAM + i);
-		csum += msg->data[i];
-	}
+	sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PARAM, args.data_size,
+				      msg->data);
 
 	/* Verify checksum */
-	if (args.checksum != (csum & 0xFF)) {
+	if (args.checksum != sum) {
 		dev_err(ec->dev,
 			"bad packet checksum, expected %02x, got %02x\n",
-			args.checksum, csum & 0xFF);
+			args.checksum, sum);
 		ret = -EBADMSG;
 		goto done;
 	}
@@ -222,14 +210,13 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
 
 	/* fixed length */
 	if (bytes) {
-		for (; cnt < bytes; i++, s++, cnt++)
-			*s = inb(EC_LPC_ADDR_MEMMAP + i);
-		return cnt;
+		cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
+		return bytes;
 	}
 
 	/* string */
 	for (; i < EC_MEMMAP_SIZE; i++, s++) {
-		*s = inb(EC_LPC_ADDR_MEMMAP + i);
+		cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + i, 1, s);
 		cnt++;
 		if (!*s)
 			break;
@@ -242,6 +229,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct cros_ec_device *ec_dev;
+	u8 buf[2];
 	int ret;
 
 	if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
@@ -250,8 +238,8 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
 		return -EBUSY;
 	}
 
-	if ((inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E') ||
-	    (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C')) {
+	cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
+	if (buf[0] != 'E' || buf[1] != 'C') {
 		dev_err(dev, "EC ID not detected\n");
 		return -ENODEV;
 	}
diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.c b/drivers/platform/chrome/cros_ec_lpc_reg.c
new file mode 100644
index 0000000..03c9781
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_reg.c
@@ -0,0 +1,64 @@
+/*
+ * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include <linux/io.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+
+static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest)
+{
+	int i;
+	int sum = 0;
+
+	for (i = 0; i < length; ++i) {
+		dest[i] = inb(offset + i);
+		sum += dest[i];
+	}
+
+	/* Return checksum of all bytes read */
+	return sum;
+}
+
+static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg)
+{
+	int i;
+	int sum = 0;
+
+	for (i = 0; i < length; ++i) {
+		outb(msg[i], offset + i);
+		sum += msg[i];
+	}
+
+	/* Return checksum of all bytes written */
+	return sum;
+}
+
+u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest)
+{
+	return lpc_read_bytes(offset, length, dest);
+}
+
+u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg)
+{
+	return lpc_write_bytes(offset, length, msg);
+}
diff --git a/include/linux/mfd/cros_ec_lpc_reg.h b/include/linux/mfd/cros_ec_lpc_reg.h
new file mode 100644
index 0000000..4089bd5
--- /dev/null
+++ b/include/linux/mfd/cros_ec_lpc_reg.h
@@ -0,0 +1,47 @@
+/*
+ * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#ifndef __LINUX_MFD_CROS_EC_REG_H
+#define __LINUX_MFD_CROS_EC_REG_H
+
+/**
+ * cros_ec_lpc_read_bytes - Read bytes from a given LPC-mapped address.
+ * Returns 8-bit checksum of all bytes read.
+ *
+ * @offset: Base read address
+ * @length: Number of bytes to read
+ * @dest: Destination buffer
+ */
+u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest);
+
+/**
+ * cros_ec_lpc_write_bytes - Write bytes to a given LPC-mapped address.
+ * Returns 8-bit checksum of all bytes written.
+ *
+ * @offset: Base write address
+ * @length: Number of bytes to write
+ * @msg: Write data buffer
+ */
+u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg);
+
+#endif /* __LINUX_MFD_CROS_EC_REG_H */
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1646747 — Re: [PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

FromLee Jones <lee.jones@linaro.org>
Date2017-05-22 13:10 +0200
SubjectRe: [PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
Message-ID<tJTnQ-4Xw-25@gated-at.bofh.it>
In reply to#1642658
On Tue, 16 May 2017, Enric Balletbo i Serra wrote:

> From: Shawn Nematbakhsh <shawnn@chromium.org>
> 
> Call common functions for read / write to prepare support for future
> LPC protocol variants which use different I/O ops than inb / outb.
> 
> Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
> Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
> ---
>  drivers/platform/chrome/Makefile          |  3 +-
>  drivers/platform/chrome/cros_ec_lpc.c     | 88 +++++++++++++------------------
>  drivers/platform/chrome/cros_ec_lpc_reg.c | 64 ++++++++++++++++++++++
>  include/linux/mfd/cros_ec_lpc_reg.h       | 47 +++++++++++++++++

Acked-by: Lee Jones <lee.jones@linaro.org>

>  4 files changed, 151 insertions(+), 51 deletions(-)
>  create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
>  create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h
> 
> diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
> index 3870afe..61182fd 100644
> --- a/drivers/platform/chrome/Makefile
> +++ b/drivers/platform/chrome/Makefile
> @@ -5,6 +5,7 @@ cros_ec_devs-objs			:= cros_ec_dev.o cros_ec_sysfs.o \
>  					   cros_ec_lightbar.o cros_ec_vbc.o \
>  					   cros_ec_debugfs.o
>  obj-$(CONFIG_CROS_EC_CHARDEV)		+= cros_ec_devs.o
> -obj-$(CONFIG_CROS_EC_LPC)		+= cros_ec_lpc.o
> +cros_ec_lpcs-objs			:= cros_ec_lpc.o cros_ec_lpc_reg.o
> +obj-$(CONFIG_CROS_EC_LPC)		+= cros_ec_lpcs.o
>  obj-$(CONFIG_CROS_EC_PROTO)		+= cros_ec_proto.o
>  obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)	+= cros_kbd_led_backlight.o
> diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
> index f9a2454..6a782a6 100644
> --- a/drivers/platform/chrome/cros_ec_lpc.c
> +++ b/drivers/platform/chrome/cros_ec_lpc.c
> @@ -26,19 +26,22 @@
>  #include <linux/io.h>
>  #include <linux/mfd/cros_ec.h>
>  #include <linux/mfd/cros_ec_commands.h>
> +#include <linux/mfd/cros_ec_lpc_reg.h>
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <linux/printk.h>
>  
> -#define DRV_NAME "cros_ec_lpc"
> +#define DRV_NAME "cros_ec_lpcs"
>  
>  static int ec_response_timed_out(void)
>  {
>  	unsigned long one_second = jiffies + HZ;
> +	u8 data;
>  
>  	usleep_range(200, 300);
>  	do {
> -		if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
> +		if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, &data) &
> +		    EC_LPC_STATUS_BUSY_MASK))
>  			return 0;
>  		usleep_range(100, 200);
>  	} while (time_before(jiffies, one_second));
> @@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
>  {
>  	struct ec_host_request *request;
>  	struct ec_host_response response;
> -	u8 sum = 0;
> -	int i;
> +	u8 sum;
>  	int ret = 0;
>  	u8 *dout;
>  
>  	ret = cros_ec_prepare_tx(ec, msg);
>  
>  	/* Write buffer */
> -	for (i = 0; i < ret; i++)
> -		outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
> +	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
>  
>  	request = (struct ec_host_request *)ec->dout;
>  
>  	/* Here we go */
> -	outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
> +	sum = EC_COMMAND_PROTOCOL_3;
> +	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum);
>  
>  	if (ec_response_timed_out()) {
>  		dev_warn(ec->dev, "EC responsed timed out\n");
> @@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
>  	}
>  
>  	/* Check result */
> -	msg->result = inb(EC_LPC_ADDR_HOST_DATA);
> +	msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum);
>  	ret = cros_ec_check_result(ec, msg);
>  	if (ret)
>  		goto done;
>  
>  	/* Read back response */
>  	dout = (u8 *)&response;
> -	for (i = 0; i < sizeof(response); i++) {
> -		dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
> -		sum += dout[i];
> -	}
> +	sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
> +				     dout);
>  
>  	msg->result = response.result;
>  
> @@ -97,11 +97,9 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
>  	}
>  
>  	/* Read response and process checksum */
> -	for (i = 0; i < response.data_len; i++) {
> -		msg->data[i] =
> -			inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
> -		sum += msg->data[i];
> -	}
> +	sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET +
> +				      sizeof(response), response.data_len,
> +				      msg->data);
>  
>  	if (sum) {
>  		dev_err(ec->dev,
> @@ -121,8 +119,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
>  				struct cros_ec_command *msg)
>  {
>  	struct ec_lpc_host_args args;
> -	int csum;
> -	int i;
> +	u8 sum;
>  	int ret = 0;
>  
>  	if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
> @@ -139,24 +136,20 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
>  	args.data_size = msg->outsize;
>  
>  	/* Initialize checksum */
> -	csum = msg->command + args.flags +
> -		args.command_version + args.data_size;
> +	sum = msg->command + args.flags + args.command_version + args.data_size;
>  
>  	/* Copy data and update checksum */
> -	for (i = 0; i < msg->outsize; i++) {
> -		outb(msg->data[i], EC_LPC_ADDR_HOST_PARAM + i);
> -		csum += msg->data[i];
> -	}
> +	sum += cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
> +				       msg->data);
>  
>  	/* Finalize checksum and write args */
> -	args.checksum = csum & 0xFF;
> -	outb(args.flags, EC_LPC_ADDR_HOST_ARGS);
> -	outb(args.command_version, EC_LPC_ADDR_HOST_ARGS + 1);
> -	outb(args.data_size, EC_LPC_ADDR_HOST_ARGS + 2);
> -	outb(args.checksum, EC_LPC_ADDR_HOST_ARGS + 3);
> +	args.checksum = sum;
> +	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
> +				(u8 *)&args);
>  
>  	/* Here we go */
> -	outb(msg->command, EC_LPC_ADDR_HOST_CMD);
> +	sum = msg->command;
> +	cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum);
>  
>  	if (ec_response_timed_out()) {
>  		dev_warn(ec->dev, "EC responsed timed out\n");
> @@ -165,16 +158,14 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
>  	}
>  
>  	/* Check result */
> -	msg->result = inb(EC_LPC_ADDR_HOST_DATA);
> +	msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum);
>  	ret = cros_ec_check_result(ec, msg);
>  	if (ret)
>  		goto done;
>  
>  	/* Read back args */
> -	args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
> -	args.command_version = inb(EC_LPC_ADDR_HOST_ARGS + 1);
> -	args.data_size = inb(EC_LPC_ADDR_HOST_ARGS + 2);
> -	args.checksum = inb(EC_LPC_ADDR_HOST_ARGS + 3);
> +	cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
> +			       (u8 *)&args);
>  
>  	if (args.data_size > msg->insize) {
>  		dev_err(ec->dev,
> @@ -185,20 +176,17 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
>  	}
>  
>  	/* Start calculating response checksum */
> -	csum = msg->command + args.flags +
> -		args.command_version + args.data_size;
> +	sum = msg->command + args.flags + args.command_version + args.data_size;
>  
>  	/* Read response and update checksum */
> -	for (i = 0; i < args.data_size; i++) {
> -		msg->data[i] = inb(EC_LPC_ADDR_HOST_PARAM + i);
> -		csum += msg->data[i];
> -	}
> +	sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PARAM, args.data_size,
> +				      msg->data);
>  
>  	/* Verify checksum */
> -	if (args.checksum != (csum & 0xFF)) {
> +	if (args.checksum != sum) {
>  		dev_err(ec->dev,
>  			"bad packet checksum, expected %02x, got %02x\n",
> -			args.checksum, csum & 0xFF);
> +			args.checksum, sum);
>  		ret = -EBADMSG;
>  		goto done;
>  	}
> @@ -222,14 +210,13 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
>  
>  	/* fixed length */
>  	if (bytes) {
> -		for (; cnt < bytes; i++, s++, cnt++)
> -			*s = inb(EC_LPC_ADDR_MEMMAP + i);
> -		return cnt;
> +		cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
> +		return bytes;
>  	}
>  
>  	/* string */
>  	for (; i < EC_MEMMAP_SIZE; i++, s++) {
> -		*s = inb(EC_LPC_ADDR_MEMMAP + i);
> +		cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + i, 1, s);
>  		cnt++;
>  		if (!*s)
>  			break;
> @@ -242,6 +229,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	struct cros_ec_device *ec_dev;
> +	u8 buf[2];
>  	int ret;
>  
>  	if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
> @@ -250,8 +238,8 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
>  		return -EBUSY;
>  	}
>  
> -	if ((inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E') ||
> -	    (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C')) {
> +	cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
> +	if (buf[0] != 'E' || buf[1] != 'C') {
>  		dev_err(dev, "EC ID not detected\n");
>  		return -ENODEV;
>  	}
> diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.c b/drivers/platform/chrome/cros_ec_lpc_reg.c
> new file mode 100644
> index 0000000..03c9781
> --- /dev/null
> +++ b/drivers/platform/chrome/cros_ec_lpc_reg.c
> @@ -0,0 +1,64 @@
> +/*
> + * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller
> + *
> + * Copyright (C) 2016 Google, Inc
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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.
> + *
> + * This driver uses the Chrome OS EC byte-level message-based protocol for
> + * communicating the keyboard state (which keys are pressed) from a keyboard EC
> + * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
> + * but everything else (including deghosting) is done here.  The main
> + * motivation for this is to keep the EC firmware as simple as possible, since
> + * it cannot be easily upgraded and EC flash/IRAM space is relatively
> + * expensive.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/mfd/cros_ec.h>
> +#include <linux/mfd/cros_ec_commands.h>
> +
> +static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest)
> +{
> +	int i;
> +	int sum = 0;
> +
> +	for (i = 0; i < length; ++i) {
> +		dest[i] = inb(offset + i);
> +		sum += dest[i];
> +	}
> +
> +	/* Return checksum of all bytes read */
> +	return sum;
> +}
> +
> +static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg)
> +{
> +	int i;
> +	int sum = 0;
> +
> +	for (i = 0; i < length; ++i) {
> +		outb(msg[i], offset + i);
> +		sum += msg[i];
> +	}
> +
> +	/* Return checksum of all bytes written */
> +	return sum;
> +}
> +
> +u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest)
> +{
> +	return lpc_read_bytes(offset, length, dest);
> +}
> +
> +u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg)
> +{
> +	return lpc_write_bytes(offset, length, msg);
> +}
> diff --git a/include/linux/mfd/cros_ec_lpc_reg.h b/include/linux/mfd/cros_ec_lpc_reg.h
> new file mode 100644
> index 0000000..4089bd5
> --- /dev/null
> +++ b/include/linux/mfd/cros_ec_lpc_reg.h
> @@ -0,0 +1,47 @@
> +/*
> + * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller
> + *
> + * Copyright (C) 2016 Google, Inc
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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.
> + *
> + * This driver uses the Chrome OS EC byte-level message-based protocol for
> + * communicating the keyboard state (which keys are pressed) from a keyboard EC
> + * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
> + * but everything else (including deghosting) is done here.  The main
> + * motivation for this is to keep the EC firmware as simple as possible, since
> + * it cannot be easily upgraded and EC flash/IRAM space is relatively
> + * expensive.
> + */
> +
> +#ifndef __LINUX_MFD_CROS_EC_REG_H
> +#define __LINUX_MFD_CROS_EC_REG_H
> +
> +/**
> + * cros_ec_lpc_read_bytes - Read bytes from a given LPC-mapped address.
> + * Returns 8-bit checksum of all bytes read.
> + *
> + * @offset: Base read address
> + * @length: Number of bytes to read
> + * @dest: Destination buffer
> + */
> +u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest);
> +
> +/**
> + * cros_ec_lpc_write_bytes - Write bytes to a given LPC-mapped address.
> + * Returns 8-bit checksum of all bytes written.
> + *
> + * @offset: Base write address
> + * @length: Number of bytes to write
> + * @msg: Write data buffer
> + */
> +u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg);
> +
> +#endif /* __LINUX_MFD_CROS_EC_REG_H */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web