Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1642652 > unrolled thread
| Started by | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| First post | 2017-05-16 18:20 +0200 |
| Last post | 2017-05-22 13:10 +0200 |
| Articles | 7 — 2 participants |
Back to article view | Back to linux.kernel
[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
| From | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| Date | 2017-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]
| From | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| Date | 2017-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]
| From | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| Date | 2017-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]
| From | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| Date | 2017-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]
| From | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| Date | 2017-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]
| From | Enric Balletbo i Serra <enric.balletbo@collabora.com> |
|---|---|
| Date | 2017-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]
| From | Lee Jones <lee.jones@linaro.org> |
|---|---|
| Date | 2017-05-22 13:10 +0200 |
| Subject | Re: [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