[PATCH v2] mfd: cros_ec: Add ACPI GPE handler for LID0 devices

2017-02-01 Thread Thierry Escande
From: Archana Patni <archana.pa...@intel.com>

This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
ACPI core that this GPE should stay enabled for lid to work in suspend
to idle path.

Signed-off-by: Archana Patni <archana.pa...@intel.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

This patch depends on https://lkml.org/lkml/2017/1/13/446

v2:
- Sent as a separate patch as the other patches from the v1 patchset
  have already been merged.
- Moved ACPI specific APIs in a specific file so it's compiled only if
  CONFIG_ACPI is enabled.

 drivers/mfd/Makefile   |   4 +-
 drivers/mfd/cros_ec.c  |  15 --
 drivers/mfd/cros_ec_acpi_gpe.c | 103 +
 include/linux/mfd/cros_ec.h|  18 +++
 4 files changed, 136 insertions(+), 4 deletions(-)
 create mode 100644 drivers/mfd/cros_ec_acpi_gpe.c

diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index dda4d4f..7f48c00 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,7 +10,9 @@ obj-$(CONFIG_MFD_ACT8945A)+= act8945a.o
 obj-$(CONFIG_MFD_SM501)+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)+= asic3.o tmio_core.o
 obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
-obj-$(CONFIG_MFD_CROS_EC)  += cros_ec.o
+cros_ec_core-objs  := cros_ec.o
+cros_ec_core-$(CONFIG_ACPI)+= cros_ec_acpi_gpe.o
+obj-$(CONFIG_MFD_CROS_EC)  += cros_ec_core.o
 obj-$(CONFIG_MFD_CROS_EC_I2C)  += cros_ec_i2c.o
 obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
 obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 9b66a98..d4a407e 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -166,6 +166,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
dev_info(dev, "Chrome EC device registered\n");
 
+   cros_ec_acpi_install_gpe_handler(dev);
+
return 0;
 
 fail_mfd:
@@ -179,6 +181,8 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
mfd_remove_devices(ec_dev->dev);
 
+   cros_ec_acpi_remove_gpe_handler();
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_remove);
@@ -190,9 +194,14 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;
 
-   sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
- HOST_SLEEP_EVENT_S3_RESUME :
- HOST_SLEEP_EVENT_S0IX_RESUME;
+   if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) {
+   sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
+   } else {
+   sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
+
+   /* Clearing the GPE status for any pending event */
+   cros_ec_acpi_clear_gpe();
+   }
 
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
diff --git a/drivers/mfd/cros_ec_acpi_gpe.c b/drivers/mfd/cros_ec_acpi_gpe.c
new file mode 100644
index 000..56d305d
--- /dev/null
+++ b/drivers/mfd/cros_ec_acpi_gpe.c
@@ -0,0 +1,103 @@
+/*
+ * ChromeOS EC multi-function device
+ *
+ * Copyright (C) 2017 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.
+ *
+ * The ChromeOS EC multi function device is used to mux all the requests
+ * to the EC device for its multiple features: keyboard controller,
+ * battery charging and regulator control, firmware update.
+ */
+#include 
+
+#define ACPI_LID_DEVICE  "LID0"
+
+static int ec_wake_gpe = -EINVAL;
+
+/*
+ * This handler indicates to ACPI core that this GPE should stay enabled for
+ * lid to work in suspend to idle path.
+ */
+static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
+  void *data)
+{
+   return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+/*
+ * Get ACPI GPE for LID0 device.
+ */
+static int cros_ec_get_ec_wake_gpe(struct device *dev)
+{
+   struct acpi_device *cros_acpi_dev;
+   struct acpi_device *adev;
+   acpi_handle handle;
+   acpi_status status;
+   int ret;
+
+   cros_acpi_dev = ACPI_COMPANION(dev);
+
+   if (!cros_acpi_dev || !cros_acpi_dev->parent ||
+  !cros_acpi_dev->parent->handle)
+   return -EINVAL;
+
+   status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
+);
+   if (ACPI_FAILURE(status))
+   return -EINVAL;
+
+   ret = acpi_bus_get_device(handle, );
+   if (ret)
+   retu

[PATCH 3/3] cros_ec: Don't signal wake event for non-wake host events

2017-01-25 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

The subset of wake-enabled host events is defined by the EC, but the EC
may still send non-wake host events if we're in the process of
suspending. Get the mask of wake-enabled host events from the EC and
filter out non-wake events to prevent spurious aborted suspend
attempts.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c   | 14 ++--
 drivers/platform/chrome/cros_ec_proto.c | 60 +
 include/linux/mfd/cros_ec.h | 12 +++
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index abd8342..510dfbb 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -53,12 +53,22 @@ static const struct mfd_cell ec_pd_cell = {
 static irqreturn_t ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
+   u8 wake_event = 1;
+   u32 host_event;
int ret;
 
-   if (device_may_wakeup(ec_dev->dev))
+   ret = cros_ec_get_next_event(ec_dev);
+
+   if (ret > 0 && ec_dev->mkbp_event_supported) {
+   /* Don't signal wake event for non-wake host events */
+   host_event = cros_ec_get_host_event(ec_dev);
+   if (host_event && !(host_event & ec_dev->host_event_wake_mask))
+   wake_event = 0;
+   }
+
+   if (wake_event && device_may_wakeup(ec_dev->dev))
pm_wakeup_event(ec_dev->dev, 0);
 
-   ret = cros_ec_get_next_event(ec_dev);
if (ret > 0)
blocking_notifier_call_chain(_dev->event_notifier,
 0, ec_dev);
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 256249b..a216a32 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -150,6 +150,40 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_check_result);
 
+/*
+ * cros_ec_get_host_event_wake_mask
+ *
+ * Get the mask of host events that cause wake from suspend.
+ *
+ * @ec_dev: EC device to call
+ * @msg: message structure to use
+ * @mask: result when function returns >=0.
+ *
+ * LOCKING:
+ * the caller has ec_dev->lock mutex, or the caller knows there is
+ * no other command in progress.
+ */
+static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg,
+   uint32_t *mask)
+{
+   struct ec_response_host_event_mask *r;
+   int ret;
+
+   msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK;
+   msg->version = 0;
+   msg->outsize = 0;
+   msg->insize = sizeof(*r);
+
+   ret = send_command(ec_dev, msg);
+   if (ret > 0) {
+   r = (struct ec_response_host_event_mask *)msg->data;
+   *mask = r->mask;
+   }
+
+   return ret;
+}
+
 static int cros_ec_host_command_proto_query(struct cros_ec_device *ec_dev,
int devidx,
struct cros_ec_command *msg)
@@ -387,6 +421,15 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
else
ec_dev->mkbp_event_supported = 1;
 
+   /*
+* Get host event wake mask, assume all events are wake events
+* if unavailable.
+*/
+   ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg,
+  _dev->host_event_wake_mask);
+   if (ret < 0)
+   ec_dev->host_event_wake_mask = U32_MAX;
+
ret = 0;
 
 exit:
@@ -507,3 +550,20 @@ 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)
+{
+   if (WARN_ON(!ec_dev->mkbp_event_supported))
+   return 0;
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(u32)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   return get_unaligned_le32(_dev->event_data.data.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 f62043a..8f37c4e 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -146,6 +146,7 @@ struct cros_ec_device {
 
struct ec_response_get_next_event event_data;
int event_size;
+   u32 host_event_wake_mask;
 };
 
 /**
@@ 

[PATCH 1/3] cros_ec: Don't return error when checking command version

2017-01-25 Thread Thierry Escande
With this patch, cros_ec_query_all() does not return an error if it
fails to check for MKBP events support. Instead, the EC device structure
indicates that it does not support MKBP events (mkbp_event_supported
field) and cros_ec_query_all() returns 0.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_proto.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 04053fe..403649a 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -371,6 +371,8 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
else
ec_dev->mkbp_event_supported = 1;
 
+   ret = 0;
+
 exit:
kfree(proto_msg);
return ret;
-- 
2.7.4



[PATCH 0/3] mfd: cros_ec: non-wake host events support

2017-01-25 Thread Thierry Escande
Hi,

This patchset adds support for non-wake host events. These are events
sent by the EC that should not wakeup the device.

This patchset also adds 2 fixes in cros_ec regarding a possible deadlock
and an error code returned when it should not.

Gwendal Grignou (1):
  cros_ec: Fix deadlock when EC is not responsive at probe

Shawn Nematbakhsh (1):
  cros_ec: Don't signal wake event for non-wake host events

Thierry Escande (1):
  cros_ec: Don't return error when checking command version

 drivers/mfd/cros_ec.c   | 14 +-
 drivers/platform/chrome/cros_ec_proto.c | 80 -
 include/linux/mfd/cros_ec.h | 12 +
 3 files changed, 103 insertions(+), 3 deletions(-)

-- 
2.7.4



[PATCH 2/3] cros_ec: Fix deadlock when EC is not responsive at probe

2017-01-25 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

When the EC is not responsive at probe, we try to get basic information
(protocol to use) later on through cros_xfer_cmd() call.
This patch makes sure there is no deadlock when re-probing the EC by
replacing call to cros_xfer_cmd() with send_command() in the function
cros_ec_get_host_command_version_mask(). Also, this patch adds the
function header indicating it must be called protected.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_proto.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 403649a..256249b 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -235,6 +235,22 @@ static int cros_ec_host_command_proto_query_v2(struct 
cros_ec_device *ec_dev)
return ret;
 }
 
+/*
+ * cros_ec_get_host_command_version_mask
+ *
+ * Get the version mask of a given command.
+ *
+ * @ec_dev: EC device to call
+ * @msg: message structure to use
+ * @cmd: command to get the version of.
+ * @mask: result when function returns 0.
+ *
+ * @return 0 on success, error code otherwise
+ *
+ * LOCKING:
+ * the caller has ec_dev->lock mutex or the caller knows there is
+ * no other command in progress.
+ */
 static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev,
u16 cmd, u32 *mask)
 {
@@ -256,7 +272,7 @@ static int cros_ec_get_host_command_version_mask(struct 
cros_ec_device *ec_dev,
pver = (struct ec_params_get_cmd_versions *)msg->data;
pver->cmd = cmd;
 
-   ret = cros_ec_cmd_xfer(ec_dev, msg);
+   ret = send_command(ec_dev, msg);
if (ret > 0) {
rver = (struct ec_response_get_cmd_versions *)msg->data;
*mask = rver->version_mask;
-- 
2.7.4



[PATCH v2 2/3] cros_ec: Fix deadlock when EC is not responsive at probe

2017-02-14 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

When the EC is not responsive at probe, we try to get basic information
(protocol to use) later on through cros_xfer_cmd() call.
This patch makes sure there is no deadlock when re-probing the EC by
replacing call to cros_xfer_cmd() with send_command() in the function
cros_ec_get_host_command_version_mask(). Also, this patch adds the
function header indicating it must be called protected.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_proto.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 8f57500..d6942a6 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -235,6 +235,22 @@ static int cros_ec_host_command_proto_query_v2(struct 
cros_ec_device *ec_dev)
return ret;
 }
 
+/*
+ * cros_ec_get_host_command_version_mask
+ *
+ * Get the version mask of a given command.
+ *
+ * @ec_dev: EC device to call
+ * @msg: message structure to use
+ * @cmd: command to get the version of.
+ * @mask: result when function returns 0.
+ *
+ * @return 0 on success, error code otherwise
+ *
+ * LOCKING:
+ * the caller has ec_dev->lock mutex or the caller knows there is
+ * no other command in progress.
+ */
 static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev,
u16 cmd, u32 *mask)
 {
@@ -256,7 +272,7 @@ static int cros_ec_get_host_command_version_mask(struct 
cros_ec_device *ec_dev,
pver = (struct ec_params_get_cmd_versions *)msg->data;
pver->cmd = cmd;
 
-   ret = cros_ec_cmd_xfer(ec_dev, msg);
+   ret = send_command(ec_dev, msg);
if (ret > 0) {
rver = (struct ec_response_get_cmd_versions *)msg->data;
*mask = rver->version_mask;
-- 
2.7.4



[PATCH v2 1/3] cros_ec: Don't return error when checking command version

2017-02-14 Thread Thierry Escande
With this patch, cros_ec_query_all() does not return an error if it
fails to check for MKBP events support. Instead, the EC device structure
indicates that it does not support MKBP events (mkbp_event_supported
field) and cros_ec_query_all() returns 0.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_proto.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 7428c2b..8f57500 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -371,6 +371,8 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
else
ec_dev->mkbp_event_supported = 1;
 
+   ret = 0;
+
 exit:
kfree(proto_msg);
return ret;
-- 
2.7.4



[PATCH v2 0/3] mfd: cros_ec: non-wake host events support

2017-02-14 Thread Thierry Escande
Hi,

This patchset adds support for non-wake host events. These are events
sent by the EC that should not wakeup the device.

This patchset also adds 2 fixes in cros_ec regarding a possible deadlock
and an error code returned when it should not.

This patchset depends on [1] to compile

v2:
- Check for wake_event state in cros_ec_get_next_event()
- Remove cros_ec_get_host_event() implementation already
  introduced by [1]

[1] https://lkml.org/lkml/2017/1/19/278

Gwendal Grignou (1):
  cros_ec: Fix deadlock when EC is not responsive at probe

Shawn Nematbakhsh (1):
  cros_ec: Don't signal wake event for non-wake host events

Thierry Escande (1):
  cros_ec: Don't return error when checking command version

 drivers/mfd/cros_ec.c   | 13 +++--
 drivers/platform/chrome/cros_ec_proto.c | 96 ++---
 include/linux/mfd/cros_ec.h | 16 +-
 3 files changed, 115 insertions(+), 10 deletions(-)

-- 
2.7.4



[PATCH v2 3/3] cros_ec: Don't signal wake event for non-wake host events

2017-02-14 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

The subset of wake-enabled host events is defined by the EC, but the EC
may still send non-wake host events if we're in the process of
suspending. Get the mask of wake-enabled host events from the EC and
filter out non-wake events to prevent spurious aborted suspend
attempts.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c   | 13 --
 drivers/platform/chrome/cros_ec_proto.c | 76 ++---
 include/linux/mfd/cros_ec.h |  5 ++-
 3 files changed, 85 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 9b66a98..1bcb502 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -54,12 +54,19 @@ static const struct mfd_cell ec_pd_cell = {
 static irqreturn_t ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
+   bool wake_event = true;
int ret;
 
-   if (device_may_wakeup(ec_dev->dev))
+   ret = cros_ec_get_next_event(ec_dev, _event);
+
+   /*
+* Signal only if wake host events or any interrupt if
+* cros_ec_get_next_event() returned an error (default value for
+* wake_event is true)
+*/
+   if (wake_event && device_may_wakeup(ec_dev->dev))
pm_wakeup_event(ec_dev->dev, 0);
 
-   ret = cros_ec_get_next_event(ec_dev);
if (ret > 0)
blocking_notifier_call_chain(_dev->event_notifier,
 0, ec_dev);
@@ -212,7 +219,7 @@ EXPORT_SYMBOL(cros_ec_suspend);
 
 static void cros_ec_drain_events(struct cros_ec_device *ec_dev)
 {
-   while (cros_ec_get_next_event(ec_dev) > 0)
+   while (cros_ec_get_next_event(ec_dev, NULL) > 0)
blocking_notifier_call_chain(_dev->event_notifier,
 1, ec_dev);
 }
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index d6942a6..8dfa7fc 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -150,6 +150,40 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_check_result);
 
+/*
+ * cros_ec_get_host_event_wake_mask
+ *
+ * Get the mask of host events that cause wake from suspend.
+ *
+ * @ec_dev: EC device to call
+ * @msg: message structure to use
+ * @mask: result when function returns >=0.
+ *
+ * LOCKING:
+ * the caller has ec_dev->lock mutex, or the caller knows there is
+ * no other command in progress.
+ */
+static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg,
+   uint32_t *mask)
+{
+   struct ec_response_host_event_mask *r;
+   int ret;
+
+   msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK;
+   msg->version = 0;
+   msg->outsize = 0;
+   msg->insize = sizeof(*r);
+
+   ret = send_command(ec_dev, msg);
+   if (ret > 0) {
+   r = (struct ec_response_host_event_mask *)msg->data;
+   *mask = r->mask;
+   }
+
+   return ret;
+}
+
 static int cros_ec_host_command_proto_query(struct cros_ec_device *ec_dev,
int devidx,
struct cros_ec_command *msg)
@@ -387,6 +421,15 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
else
ec_dev->mkbp_event_supported = 1;
 
+   /*
+* Get host event wake mask, assume all events are wake events
+* if unavailable.
+*/
+   ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg,
+  _dev->host_event_wake_mask);
+   if (ret < 0)
+   ec_dev->host_event_wake_mask = U32_MAX;
+
ret = 0;
 
 exit:
@@ -504,12 +547,35 @@ static int get_keyboard_state_event(struct cros_ec_device 
*ec_dev)
return ec_dev->event_size;
 }
 
-int cros_ec_get_next_event(struct cros_ec_device *ec_dev)
+int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
 {
-   if (ec_dev->mkbp_event_supported)
-   return get_next_event(ec_dev);
-   else
-   return get_keyboard_state_event(ec_dev);
+   u32 host_event;
+   int ret;
+
+   if (!ec_dev->mkbp_event_supported) {
+   ret = get_keyboard_state_event(ec_dev);
+   if (ret < 0)
+   return ret;
+
+   if (wake_event)
+   *wake_event = true;
+
+   return ret;
+   }
+
+   ret = get_next_event(ec_dev);
+   if (ret < 0)
+   return ret;
+
+   if (wake_event) {
+

Re: [PATCH 3/3] cros_ec: Don't signal wake event for non-wake host events

2017-02-13 Thread Thierry Escande

Hi Lee,

On 07/02/2017 17:12, Lee Jones wrote:

On Wed, 25 Jan 2017, Thierry Escande wrote:


From: Shawn Nematbakhsh <sha...@chromium.org>

The subset of wake-enabled host events is defined by the EC, but the EC
may still send non-wake host events if we're in the process of
suspending. Get the mask of wake-enabled host events from the EC and
filter out non-wake events to prevent spurious aborted suspend
attempts.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c   | 14 ++--
 drivers/platform/chrome/cros_ec_proto.c | 60 +
 include/linux/mfd/cros_ec.h | 12 +++
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index abd8342..510dfbb 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -53,12 +53,22 @@ static const struct mfd_cell ec_pd_cell = {
 static irqreturn_t ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
+   u8 wake_event = 1;


Bool, true?

Ok.




+   u32 host_event;
int ret;

-   if (device_may_wakeup(ec_dev->dev))
+   ret = cros_ec_get_next_event(ec_dev);


What does (ret == 0) mean?
The get_next_event() API called from cros_ec_get_next_event() only sets 
event_data in the ec_dev structure if the command has actually been 
sent. So (ret == 0) is not treated as an error and is silently ignored. 
In this case, the interrupt is treated as a wake event.




... and is is possible for (ret < 0)?


+   if (ret > 0 && ec_dev->mkbp_event_supported) {


cros_ec_get_host_event() checks for (ec_dev->mkbp_event_supported)
anyway, so you can drop it here no?
Sure but we only need to call cros_ec_get_host_event() if 
mkbp_event_supported is true. Anyway, I'll move the host_event check 
with cros_ec_get_host_event() into cros_ec_get_next_event() to avoid 
this double check.





+   /* Don't signal wake event for non-wake host events */
+   host_event = cros_ec_get_host_event(ec_dev);
+   if (host_event && !(host_event & ec_dev->host_event_wake_mask))
+   wake_event = 0;


false

Will do.

Thanks,
 Thierry




+   }
+
+   if (wake_event && device_may_wakeup(ec_dev->dev))
pm_wakeup_event(ec_dev->dev, 0);

-   ret = cros_ec_get_next_event(ec_dev);
if (ret > 0)
blocking_notifier_call_chain(_dev->event_notifier,
 0, ec_dev);
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 256249b..a216a32 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -150,6 +150,40 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_check_result);

+/*
+ * cros_ec_get_host_event_wake_mask
+ *
+ * Get the mask of host events that cause wake from suspend.
+ *
+ * @ec_dev: EC device to call
+ * @msg: message structure to use
+ * @mask: result when function returns >=0.
+ *
+ * LOCKING:
+ * the caller has ec_dev->lock mutex, or the caller knows there is
+ * no other command in progress.
+ */
+static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg,
+   uint32_t *mask)
+{
+   struct ec_response_host_event_mask *r;
+   int ret;
+
+   msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK;
+   msg->version = 0;
+   msg->outsize = 0;
+   msg->insize = sizeof(*r);
+
+   ret = send_command(ec_dev, msg);
+   if (ret > 0) {
+   r = (struct ec_response_host_event_mask *)msg->data;
+   *mask = r->mask;
+   }
+
+   return ret;
+}
+
 static int cros_ec_host_command_proto_query(struct cros_ec_device *ec_dev,
int devidx,
struct cros_ec_command *msg)
@@ -387,6 +421,15 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
else
ec_dev->mkbp_event_supported = 1;

+   /*
+* Get host event wake mask, assume all events are wake events
+* if unavailable.
+*/
+   ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg,
+  _dev->host_event_wake_mask);
+   if (ret < 0)
+   ec_dev->host_event_wake_mask = U32_MAX;
+
ret = 0;

 exit:
@@ -507,3 +550,20 @@ 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)
+{
+ 

[PATCH 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-09-07 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@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 <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 87 ++-
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 +++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 152 insertions(+), 49 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 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.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..617074e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#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, ) &
+   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, );
 
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, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   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,10 @@ 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 +120,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->outs

[PATCH 0/2] platform/chrome: Add support for mec1322 EC

2016-09-07 Thread Thierry Escande
Hi,

This serie adds support for the LPC Microchip Embedded Controller 1322.

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   |   9 ++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  92 +--
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 487 insertions(+), 49 deletions(-)
 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.7.4



[PATCH 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-09-07 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 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
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.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 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 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.
+ */
+
+#in

[PATCH] driver-core: add test module for asynchronous probing

2016-09-29 Thread Thierry Escande
From: Dmitry Torokhov <d...@chromium.org>

This test module tries to test asynchronous driver probing by having a
driver that sleeps for an extended period of time (5 secs) in its
probe() method. It measures the time needed to register this driver
(with device already registered) and a new device (with driver already
registered). The module will fail to load if the time spent in register
call is more than half the probing sleep time.

As a sanity check the driver will then try to synchronously register
driver and device and fail if registration takes less than half of the
probing sleep time.

Signed-off-by: Dmitry Torokhov <d...@chromium.org>
Reviewed-by: Olof Johansson <ol...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/base/Kconfig|   2 +
 drivers/base/Makefile   |   2 +
 drivers/base/test/Kconfig   |   9 ++
 drivers/base/test/Makefile  |   1 +
 drivers/base/test/test_async_driver_probe.c | 171 
 5 files changed, 185 insertions(+)
 create mode 100644 drivers/base/test/Kconfig
 create mode 100644 drivers/base/test/Makefile
 create mode 100644 drivers/base/test/test_async_driver_probe.c

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 98504ec..b31fba2 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -212,6 +212,8 @@ config DEBUG_DEVRES
 
  If you are unsure about this, Say N here.
 
+source "drivers/base/test/Kconfig"
+
 config SYS_HYPERVISOR
bool
default n
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 2609ba2..f2816f6 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -24,5 +24,7 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o
 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
 obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
 
+obj-y  += test/
+
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff --git a/drivers/base/test/Kconfig b/drivers/base/test/Kconfig
new file mode 100644
index 000..9aa0d45
--- /dev/null
+++ b/drivers/base/test/Kconfig
@@ -0,0 +1,9 @@
+config TEST_ASYNC_DRIVER_PROBE
+   tristate "Build kernel module to test asynchronous driver probing"
+   depends on m
+   help
+ Enabling this option produces a kernel module that allows
+ testing asynchronous driver probing by the device core.
+ The module name will be test_async_driver_probe.ko
+
+ If unsure say N.
diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile
new file mode 100644
index 000..90477c5
--- /dev/null
+++ b/drivers/base/test/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE)  += test_async_driver_probe.o
diff --git a/drivers/base/test/test_async_driver_probe.c 
b/drivers/base/test/test_async_driver_probe.c
new file mode 100644
index 000..3a71e83
--- /dev/null
+++ b/drivers/base/test/test_async_driver_probe.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TEST_PROBE_DELAY   (5 * 1000)  /* 5 sec */
+#define TEST_PROBE_THRESHOLD   (TEST_PROBE_DELAY / 2)
+
+static int test_probe(struct platform_device *pdev)
+{
+   dev_info(>dev, "sleeping for %d msecs in probe\n",
+TEST_PROBE_DELAY);
+   msleep(TEST_PROBE_DELAY);
+   dev_info(>dev, "done sleeping\n");
+
+   return 0;
+}
+
+static struct platform_driver async_driver = {
+   .driver = {
+   .name = "test_async_driver",
+   .owner = THIS_MODULE,
+   .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+   },
+   .probe = test_probe,
+};
+
+static struct platform_driver sync_driver = {
+   .driver = {
+   .name = "test_sync_driver",
+   .owner = THIS_MODULE,
+   .probe_type = PROBE_FORCE_SYNCHRONOUS,
+   },
+   .probe = test_probe,
+};
+
+static struct platform_device *async_dev_1, *async_dev_2;
+static struct platform_device *sync_dev_1;
+
+static int __init test_async_probe_init(void)
+{
+   ktime_t calltime, delta;
+   unsigned long long duration;
+   int error;
+
+   pr_info("registering first asynchronous device...\n");
+
+   async_dev_1 = platform_device_register_simple(&q

[PATCH RESEND 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-11-08 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@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 <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 87 ++-
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 +++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 152 insertions(+), 49 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 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.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..617074e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#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, ) &
+   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, );
 
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, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   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,10 @@ 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 +120,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->outs

[PATCH RESEND 0/2] platform/chrome: Add support for mec1322 EC

2016-11-08 Thread Thierry Escande
Hi,

This serie adds support for the LPC Microchip Embedded Controller 1322.

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   |   9 ++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  92 +--
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 487 insertions(+), 49 deletions(-)
 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.7.4



[PATCH RESEND 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-11-08 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 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
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.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 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 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.
+ */
+
+#in

[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-20 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

 drivers/media/v4l2-core/videobuf2-core.c |  9 +++--
 include/media/videobuf2-core.h   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..631f08b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -499,6 +502,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -554,6 +558,17 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Return the corresponding DMA direction given the vb2_queue type (capture or
+ * output). returns DMA_BIRECTIONAL for capture buffers if the vb2_queue field
+ * capture_dma_bidirectional is set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



Re: [PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-20 Thread Thierry Escande

Hi Sakari,

On 19/10/2016 23:29, Sakari Ailus wrote:

Hi Thierry,

On Wed, Oct 19, 2016 at 10:24:16AM +0200, Thierry Escande wrote:

From: Pawel Osciak <posc...@chromium.org>

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Owen Lin <owen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)

mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);


My bad, I guess I expressed myself unclearly.

Could you introduce the macro in this patch? You can then remove q->dma_dir
altogether.

My bad. Sorry for the confusion...

The v3 is on its way.

Regards,
 Thierry



[PATCH 0/2] [media] DMA direction support in vb2_queue

2016-10-14 Thread Thierry Escande
Hi,

This series adds a dma_dir field to the vb2_queue structure in order to
store the DMA direction once for all in vb2_queue_init();

It also adds a new use_dma_bidirectional flag to the vb2_queue structure
allowing the hardware to read from the CAPTURE buffer. This flag is
ignored for OUTPUT queues. This is used on ChromeOS by the rockchip-vpu
driver.

Pawel Osciak (2):
  [media] vb2: Store dma_dir in vb2_queue
  [media] vb2: Add support for use_dma_bidirectional queue flag

 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h   |  6 ++
 3 files changed, 15 insertions(+), 9 deletions(-)

-- 
2.7.4



[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-14 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Owen Lin <owen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef883..fde1e2d 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
+   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
+  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..38410dd 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -489,6 +489,7 @@ struct vb2_buf_ops {
  * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
  * @fileio:file io emulator internal data, used only if emulator is active
  * @threadio:  thread io internal data, used only if thread is active
+ * @dma_dir:   DMA direction to use for buffers on this queue
  */
 struct vb2_queue {
unsigned inttype;
@@ -540,6 +541,7 @@ struct vb2_queue {
 
struct vb2_fileio_data  *fileio;
struct vb2_threadio_data*threadio;
+   enum dma_data_direction dma_dir;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
/*
-- 
2.7.4



[PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag

2016-10-14 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++--
 include/media/videobuf2-core.h   | 4 
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..9255291 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+   if (V4L2_TYPE_IS_OUTPUT(q->type))
+   q->dma_dir = DMA_TO_DEVICE;
+   else
+   q->dma_dir = q->use_dma_bidirectional
+  ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..e613c74 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduse_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
-- 
2.7.4



[PATCH] [media] videobuf2-dma-contig: Support cacheable MMAP

2016-10-14 Thread Thierry Escande
From: Heng-Ruey Hsu <henry...@chromium.org>

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org>
Tested-by: Heng-ruey Hsu <henry...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..c953c24 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -42,6 +42,12 @@ struct vb2_dc_buf {
 };
 
 /*/
+/*   Forward declarations*/
+/*/
+
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf);
+
+/*/
 /*scatterlist table functions*/
 /*/
 
@@ -129,6 +135,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -170,6 +180,10 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+(buf->attrs & DMA_ATTR_NON_CONSISTENT))
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -205,6 +219,11 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   (buf->attrs & DMA_ATTR_NON_CONSISTENT) &&
+   !buf->dma_sgt)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v4] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-24 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes since v3:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro


 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 24 
 5 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;
 
offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_fail_pfnvec;
buf->vec = vec;
@@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
while (--i >= 0) {
-

Re: [PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag

2016-10-18 Thread Thierry Escande

Hi Sakari,

On 17/10/2016 12:06, Sakari Ailus wrote:

Hi Thierry,

Thanks for the set. A few comments below.

On Fri, Oct 14, 2016 at 02:08:14PM +0200, Thierry Escande wrote:

From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.


Just out of curiosity --- when do you return these buffers back to the user?
Once they're no longer needed as reference frames?
Tbh, I don't now. This is used by a rockchip vpu driver not yet 
upstreamed in the chromeos v4.4 kernel tree. Pawel might answer this 
question I guess.






This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++--
 include/media/videobuf2-core.h   | 4 
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..9255291 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+   if (V4L2_TYPE_IS_OUTPUT(q->type))
+   q->dma_dir = DMA_TO_DEVICE;
+   else
+   q->dma_dir = q->use_dma_bidirectional
+  ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;

return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..e613c74 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduse_dma_bidirectional:1;


This field is in the same struct as dma_dir which it directly affects.

How about adding a macro instead to give you the queue DMA direction
instead?

E.g.

#define vb2_dma_dir(q) \
(V4L2_TYPE_IS_OUTPUT((q)->type) ? DMA_TO_DEVICE : \
 (q)->use_dma_bidirectional ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE)

I would call this capture_dma_bidirectional as it only affects capture. Or
simply choose DMA_BIDIRECTIONAL whenever the flag is set.

Sure. Will do.

Regards,
 Thierry


[PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-25 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes in v2:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes in v3:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes in v4:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro

Changes in v5:
- Use is_output queue field in VB2_DMA_DIR() macro

 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 23 +++
 5 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;
 
offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_fail_pfnvec;
buf->vec = vec;
@@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->

[PATCH v2 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

2016-10-24 Thread Thierry Escande
This patch moves vb2_dc_get_base_sgt() function above mmap buffers
callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it
will be called for cacheable MMAP support introduced in the next patch.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +-
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index a44e383..0d9665d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
return size;
 }
 
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+   int ret;
+   struct sg_table *sgt;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (!sgt) {
+   dev_err(buf->dev, "failed to alloc sg table\n");
+   return NULL;
+   }
+
+   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+   buf->size, buf->attrs);
+   if (ret < 0) {
+   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+   kfree(sgt);
+   return NULL;
+   }
+
+   return sgt;
+}
+
 /*/
 /* callbacks for all buffers */
 /*/
@@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
.release = vb2_dc_dmabuf_ops_release,
 };
 
-static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
-{
-   int ret;
-   struct sg_table *sgt;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (!sgt) {
-   dev_err(buf->dev, "failed to alloc sg table\n");
-   return NULL;
-   }
-
-   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
-   buf->size, buf->attrs);
-   if (ret < 0) {
-   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
-   kfree(sgt);
-   return NULL;
-   }
-
-   return sgt;
-}
-
 static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
struct vb2_dc_buf *buf = buf_priv;
-- 
2.7.4



[PATCH v2 2/2] [media] videobuf2-dc: Support cacheable MMAP

2016-10-24 Thread Thierry Escande
From: Heng-Ruey Hsu <henry...@chromium.org>

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

This patch enables cacheable memory for DMA coherent allocator in mmap
buffer allocation if non-consistent DMA attribute is set and kernel
mapping is present. Even if userspace doesn't mmap the buffer, sync
still should be happening if kernel mapping is present.
If not done in allocation, it is enabled when memory is mapped from
userspace when no kernel mapping is present and non-consistent DMA
attribute set.

Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org>
Tested-by: Heng-ruey Hsu <henry...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 0d9665d..1f7649d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   /*
+* Enable cacheable memory. Even if userspace doesn't mmap the buffer,
+* sync still should be happening if kernel mapping is present.
+*/
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -227,6 +239,12 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   /* Enable cacheable memory if not enabled in allocation. */
+   if (!buf->dma_sgt &&
+   buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v2 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2016-10-24 Thread Thierry Escande
Hi,

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.

Changes in v2:
- Put function move in a separate patch
- Added comments

Heng-Ruey Hsu (1):
  [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
  [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

 drivers/media/v4l2-core/videobuf2-dma-contig.c | 62 +-
 1 file changed, 40 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-21 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes since v3:
- Fixed typos in include/media/videobuf2-core.h

 drivers/media/v4l2-core/videobuf2-core.c |  9 +++--
 include/media/videobuf2-core.h   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..a6cfdfb 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -499,6 +502,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -554,6 +558,17 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Returns the corresponding DMA direction given the vb2_queue type (capture or
+ * output). Returns DMA_BIDIRECTIONAL for capture buffers if the vb2_queue 
field
+ * capture_dma_bidirectional is set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH 2/2] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-19 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-v4l2.c |  3 +--
 include/media/videobuf2-core.h   | 14 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..c92197c 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,7 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   q->dma_dir = VB2_DMA_DIR(q);
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..cd55917 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -556,6 +560,16 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Return the corresponding DMA direction given the vb2_queue type (capture or
+ * output). returns DMA_BIRECTIONAL for capture buffers if set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-19 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Owen Lin <owen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef883..fde1e2d 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
+   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
+  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..38410dd 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -489,6 +489,7 @@ struct vb2_buf_ops {
  * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
  * @fileio:file io emulator internal data, used only if emulator is active
  * @threadio:  thread io internal data, used only if thread is active
+ * @dma_dir:   DMA direction to use for buffers on this queue
  */
 struct vb2_queue {
unsigned inttype;
@@ -540,6 +541,7 @@ struct vb2_queue {
 
struct vb2_fileio_data  *fileio;
struct vb2_threadio_data*threadio;
+   enum dma_data_direction dma_dir;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
/*
-- 
2.7.4



[PATCH 0/2] [media] DMA direction support in vb2_queue

2016-10-19 Thread Thierry Escande
Hi,

This series adds a dma_dir field to the vb2_queue structure in order to
store the DMA direction once for all in vb2_queue_init();

It also adds a new capture_dma_bidirectional flag to the vb2_queue
structure allowing the hardware to read from the CAPTURE buffer. This
flag is ignored for OUTPUT queues. This is used on ChromeOS by the
rockchip-vpu driver.

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Pawel Osciak (2):
  [media] vb2: Store dma_dir in vb2_queue
  [media] vb2: Add support for capture_dma_bidirectional queue flag

 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h   |  6 ++
 3 files changed, 15 insertions(+), 9 deletions(-)

-- 
2.7.4



Re: [PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-11-22 Thread Thierry Escande

Hi Mauro,

On 18/11/2016 19:59, Mauro Carvalho Chehab wrote:

Em Tue, 25 Oct 2016 10:22:29 +0200
Thierry Escande <thierry.esca...@collabora.com> escreveu:


From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.


Why to add it? There's no other patch on this series with would
justify its needs...


It is used by a Rockchip vpu driver which is only in the chromeos public 
tree for now and will be upstreamed soon.


Regards,
 Thierry



Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes in v2:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes in v3:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes in v4:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro

Changes in v5:
- Use is_output queue field in VB2_DMA_DIR() macro

 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 23 +++
 5 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;

memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;

memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;

offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, bu

Re: [PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-21 Thread Thierry Escande

Hi Sakari,

On 21/10/2016 09:48, Sakari Ailus wrote:

Hi Thierry,

On Fri, Oct 21, 2016 at 09:25:05AM +0200, Thierry Escande wrote:

From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>



Please also check where dma_dir is being used especially in memory type
implementation. There are several comparisons to DMA_FROM_DEVICE which will
have a different result if DMA_BIDIRECTIONAL is used instead.

Nice catch, thanks.

How about a macro like this:

#define VB2_DMA_DIR_CAPTURE(d) \
((d) == DMA_FROM_DEVICE || (d) == DMA_BIDIRECTIONAL)

Regards,
 Thierry



[PATCH v3 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

2016-10-26 Thread Thierry Escande
This patch moves vb2_dc_get_base_sgt() function above mmap buffers
callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it
will be called for cacheable MMAP support introduced in the next patch.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +-
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index a44e383..0d9665d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
return size;
 }
 
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+   int ret;
+   struct sg_table *sgt;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (!sgt) {
+   dev_err(buf->dev, "failed to alloc sg table\n");
+   return NULL;
+   }
+
+   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+   buf->size, buf->attrs);
+   if (ret < 0) {
+   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+   kfree(sgt);
+   return NULL;
+   }
+
+   return sgt;
+}
+
 /*/
 /* callbacks for all buffers */
 /*/
@@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
.release = vb2_dc_dmabuf_ops_release,
 };
 
-static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
-{
-   int ret;
-   struct sg_table *sgt;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (!sgt) {
-   dev_err(buf->dev, "failed to alloc sg table\n");
-   return NULL;
-   }
-
-   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
-   buf->size, buf->attrs);
-   if (ret < 0) {
-   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
-   kfree(sgt);
-   return NULL;
-   }
-
-   return sgt;
-}
-
 static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
struct vb2_dc_buf *buf = buf_priv;
-- 
2.7.4



[PATCH v3 2/2] [media] videobuf2-dc: Support cacheable MMAP

2016-10-26 Thread Thierry Escande
From: Heng-Ruey Hsu <henry...@chromium.org>

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

This patch enables cacheable memory for DMA coherent allocator in mmap
buffer allocation if non-consistent DMA attribute is set and kernel
mapping is present. Even if userspace doesn't mmap the buffer, sync
still should be happening if kernel mapping is present.
If not done in allocation, it is enabled when memory is mapped from
userspace (if non-consistent DMA attribute is set).

Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org>
Tested-by: Heng-ruey Hsu <henry...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 0d9665d..89b534a 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   /*
+* Enable cache maintenance. Even if userspace doesn't mmap the buffer,
+* sync still should be happening if kernel mapping is present.
+*/
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -227,6 +239,10 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   /* Enable cache maintenance if not enabled in allocation. */
+   if (!buf->dma_sgt && buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v3 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2016-10-26 Thread Thierry Escande
Hi,

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.

Changes in v2:
- Put function move in a separate patch
- Added comments

Changes in v3:
- Remove redundant test on NO_KERNEL_MAPPING DMA attribute in mmap()

Heng-Ruey Hsu (1):
  [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
  [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

 drivers/media/v4l2-core/videobuf2-dma-contig.c | 60 --
 1 file changed, 38 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH 0/3] mfd: cros_ec: various improvements

2016-12-16 Thread Thierry Escande
Hi,

This series adds some improvements to the ChromeOS EC driver.
- New EC host commands are sent through suspend/resume ops.
- A flag now protect data transfer while device is suspended.
- LID0 device GPE now stays enabled for lid to work in suspend to
  idle path.

This patchset depends on [1] to apply.
[1] https://lkml.org/lkml/2016/12/2/360

Regards,
 Thierry

Archana Patni (1):
  mfd: cros_ec: Add ACPI GPE handler for LID0 devices

Joseph Lo (1):
  mfd: cros_ec: Prevent data transfer while device is suspended

Shawn Nematbakhsh (1):
  mfd: cros_ec: Send suspend state notification to EC

 drivers/mfd/cros_ec.c   | 144 
 drivers/platform/chrome/cros_ec_proto.c |   5 ++
 include/linux/mfd/cros_ec.h |   2 +
 include/linux/mfd/cros_ec_commands.h|  14 
 4 files changed, 165 insertions(+)

-- 
2.7.4



[PATCH 1/3] mfd: cros_ec: Prevent data transfer while device is suspended

2016-12-16 Thread Thierry Escande
From: Joseph Lo <jose...@nvidia.com>

The cros_ec driver is still active while the device is suspended.
Besides that, it also tries to transfer data even after the I2C host had
been suspended. This patch uses a simple flag to prevent this.

Signed-off-by: Joseph Lo <jose...@nvidia.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c   | 2 ++
 drivers/platform/chrome/cros_ec_proto.c | 5 +
 include/linux/mfd/cros_ec.h | 2 ++
 3 files changed, 9 insertions(+)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index abd8342..ad48633 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -165,6 +165,7 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
 
disable_irq(ec_dev->irq);
ec_dev->was_wake_device = ec_dev->wake_enabled;
+   ec_dev->suspended = true;
 
return 0;
 }
@@ -179,6 +180,7 @@ static void cros_ec_drain_events(struct cros_ec_device 
*ec_dev)
 
 int cros_ec_resume(struct cros_ec_device *ec_dev)
 {
+   ec_dev->suspended = false;
enable_irq(ec_dev->irq);
 
/*
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 04053fe..ed5dee7 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -447,6 +447,11 @@ static int get_next_event(struct cros_ec_device *ec_dev)
struct cros_ec_command *msg = (struct cros_ec_command *)
int ret;
 
+   if (ec_dev->suspended) {
+   dev_dbg(ec_dev->dev, "Device suspended.\n");
+   return -EHOSTDOWN;
+   }
+
msg->version = 0;
msg->command = EC_CMD_GET_NEXT_EVENT;
msg->insize = sizeof(ec_dev->event_data);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 76f7ef4..d585bf0 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -103,6 +103,7 @@ struct cros_ec_command {
  * @din_size: size of din buffer to allocate (zero to use static din)
  * @dout_size: size of dout buffer to allocate (zero to use static dout)
  * @wake_enabled: true if this device can wake the system from sleep
+ * @suspended: true if this device had been suspended
  * @cmd_xfer: send command to EC and get response
  * Returns the number of bytes received if the communication succeeded, but
  * that doesn't mean the EC was happy with the command. The caller
@@ -136,6 +137,7 @@ struct cros_ec_device {
int din_size;
int dout_size;
bool wake_enabled;
+   bool suspended;
int (*cmd_xfer)(struct cros_ec_device *ec,
struct cros_ec_command *msg);
int (*pkt_xfer)(struct cros_ec_device *ec,
-- 
2.7.4



[PATCH 2/3] platform/chrome: cros_ec_lpc: Add power management ops

2016-12-16 Thread Thierry Escande
From: Archana Patni <archana.pa...@intel.com>

This patch adds suspend and resume pm ops to the LPC ChromeOS EC driver.
These LPC handlers call the croc_ec generic handlers.

Signed-off-by: Archana Patni <archana.pa...@intel.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_lpc.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 90703521..89afad7 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -333,10 +333,31 @@ static struct dmi_system_id cros_ec_lpc_dmi_table[] 
__initdata = {
 };
 MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_lpc_suspend(struct device *dev)
+{
+   struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
+
+   return cros_ec_suspend(ec_dev);
+}
+
+static int cros_ec_lpc_resume(struct device *dev)
+{
+   struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
+
+   return cros_ec_resume(ec_dev);
+}
+#endif
+
+const struct dev_pm_ops cros_ec_lpc_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
+};
+
 static struct platform_driver cros_ec_lpc_driver = {
.driver = {
.name = DRV_NAME,
.acpi_match_table = cros_ec_lpc_acpi_device_ids,
+   .pm = _ec_lpc_pm_ops,
},
.probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove,
-- 
2.7.4



[PATCH 3/3] platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

2016-12-16 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

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

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@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(_dev->event_notifier, 0,
+ec_dev);
+}
+
 static int cros_ec_lpc_probe(struct platform_device *pdev)
 {
struct device *dev = >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(>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.7.4



[PATCH 1/3] platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device

2016-12-16 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This patch removes platform_device_register() call and adds an ACPI
device id structure. The driver is now automatically probed for devices
with a GOOG0004 ACPI entry.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |  2 +-
 drivers/platform/chrome/cros_ec_lpc.c | 23 +--
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 6d80fb5..0ad6e29 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -49,7 +49,7 @@ config CROS_EC_CHARDEV
 
 config CROS_EC_LPC
 tristate "ChromeOS Embedded Controller (LPC)"
-depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
+depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
 help
   If you say Y here, you get support for talking to the ChromeOS EC
   over an LPC bus. This uses a simple byte-level protocol with a
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index bc2dc62..90703521 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -21,6 +21,7 @@
  * expensive.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -32,6 +33,7 @@
 #include 
 
 #define DRV_NAME "cros_ec_lpcs"
+#define ACPI_DRV_NAME "GOOG0004"
 
 static int ec_response_timed_out(void)
 {
@@ -288,6 +290,12 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
+   { ACPI_DRV_NAME, 0 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
+
 static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
{
/*
@@ -328,15 +336,12 @@ MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 static struct platform_driver cros_ec_lpc_driver = {
.driver = {
.name = DRV_NAME,
+   .acpi_match_table = cros_ec_lpc_acpi_device_ids,
},
.probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove,
 };
 
-static struct platform_device cros_ec_lpc_device = {
-   .name = DRV_NAME
-};
-
 static int __init cros_ec_lpc_init(void)
 {
int ret;
@@ -356,21 +361,11 @@ static int __init cros_ec_lpc_init(void)
return ret;
}
 
-   /* Register the device, and it'll get hooked up automatically */
-   ret = platform_device_register(_ec_lpc_device);
-   if (ret) {
-   pr_err(DRV_NAME ": can't register device: %d\n", ret);
-   platform_driver_unregister(_ec_lpc_driver);
-   cros_ec_lpc_reg_destroy();
-   return ret;
-   }
-
return 0;
 }
 
 static void __exit cros_ec_lpc_exit(void)
 {
-   platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
cros_ec_lpc_reg_destroy();
 }
-- 
2.7.4



[PATCH 0/3] platform/chrome: cros_ec_lpc: MKBP events over ACPI

2016-12-16 Thread Thierry Escande
Hi,

This series adds support for MKBP events over ACPI. The ChromeOS EC LCP
driver is also now probed upon detection of the ACPI GOOG0004 device.
Last, a patch adds power management suspend and resume handlers.

This patchset depends on [1] to apply.
[1] https://lkml.org/lkml/2016/12/2/360

Regards,
 Thierry

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

Gwendal Grignou (2):
  platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device
  platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

 drivers/platform/chrome/Kconfig   |  2 +-
 drivers/platform/chrome/cros_ec_lpc.c | 76 ---
 2 files changed, 63 insertions(+), 15 deletions(-)

-- 
2.7.4



[PATCH 2/3] mfd: cros_ec: Send suspend state notification to EC

2016-12-16 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

Notify EC when going to or returning from suspend so that proper actions
related to wake events can be taken.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c| 49 
 include/linux/mfd/cros_ec_commands.h | 14 +++
 2 files changed, 63 insertions(+)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index ad48633..b8a5080 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define CROS_EC_DEV_EC_INDEX 0
@@ -65,6 +66,24 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
return IRQ_HANDLED;
 }
 
+static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
+{
+   struct {
+   struct cros_ec_command msg;
+   struct ec_params_host_sleep_event req;
+   } __packed buf;
+
+   memset(, 0, sizeof(buf));
+
+   buf.req.sleep_event = sleep_event;
+
+   buf.msg.command = EC_CMD_HOST_SLEEP_EVENT;
+   buf.msg.version = 0;
+   buf.msg.outsize = sizeof(buf.req);
+
+   return cros_ec_cmd_xfer(ec_dev, );
+}
+
 int cros_ec_register(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
@@ -136,6 +155,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
}
}
 
+   /*
+* Clear sleep event - this will fail harmlessly on platforms that
+* don't implement the sleep event host command.
+*/
+   err = cros_ec_sleep_event(ec_dev, 0);
+   if (err < 0)
+   dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec",
+   err);
+
dev_info(dev, "Chrome EC device registered\n");
 
return 0;
@@ -159,6 +187,16 @@ EXPORT_SYMBOL(cros_ec_remove);
 int cros_ec_suspend(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
+   int ret;
+   u8 sleep_event;
+
+   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
+ HOST_SLEEP_EVENT_S0IX_RESUME;
+
+   ret = cros_ec_sleep_event(ec_dev, sleep_event);
+   if (ret < 0)
+   dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec",
+   ret);
 
if (device_may_wakeup(dev))
ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
@@ -180,9 +218,20 @@ static void cros_ec_drain_events(struct cros_ec_device 
*ec_dev)
 
 int cros_ec_resume(struct cros_ec_device *ec_dev)
 {
+   int ret;
+   u8 sleep_event;
+
ec_dev->suspended = false;
enable_irq(ec_dev->irq);
 
+   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
+ HOST_SLEEP_EVENT_S0IX_RESUME;
+
+   ret = cros_ec_sleep_event(ec_dev, sleep_event);
+   if (ret < 0)
+   dev_dbg(ec_dev->dev, "Error %d sending resume event to ec",
+   ret);
+
/*
 * In some cases, we need to distinguish between events that occur
 * during suspend if the EC is not a wake source. For example,
diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index 76728ff..4d55132 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -2304,6 +2304,20 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+/* Inform the EC when entering a sleep state */
+#define EC_CMD_HOST_SLEEP_EVENT 0xa9
+
+enum host_sleep_event {
+   HOST_SLEEP_EVENT_S3_SUSPEND   = 1,
+   HOST_SLEEP_EVENT_S3_RESUME= 2,
+   HOST_SLEEP_EVENT_S0IX_SUSPEND = 3,
+   HOST_SLEEP_EVENT_S0IX_RESUME  = 4
+};
+
+struct ec_params_host_sleep_event {
+   uint8_t sleep_event;
+} __packed;
+
 /*/
 /* Smart battery pass-through */
 
-- 
2.7.4



[PATCH 3/3] mfd: cros_ec: Add ACPI GPE handler for LID0 devices

2016-12-16 Thread Thierry Escande
From: Archana Patni <archana.pa...@intel.com>

This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
ACPI core that this GPE should stay enabled for lid to work in suspend
to idle path.

Signed-off-by: Archana Patni <archana.pa...@intel.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c | 97 +--
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b8a5080..628718e 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -17,6 +17,9 @@
  * battery charging and regulator control, firmware update.
  */
 
+#ifdef CONFIG_ACPI
+#include 
+#endif
 #include 
 #include 
 #include 
@@ -29,6 +32,73 @@
 #define CROS_EC_DEV_EC_INDEX 0
 #define CROS_EC_DEV_PD_INDEX 1
 
+#ifdef CONFIG_ACPI
+
+#define ACPI_LID_DEVICE  "LID0"
+
+static int ec_wake_gpe = -EINVAL;
+
+/*
+ * This handler indicates to ACPI core that this GPE should stay enabled for
+ * lid to work in suspend to idle path.
+ */
+static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
+  void *data)
+{
+   return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+/*
+ * Get ACPI GPE for LID0 device.
+ */
+static int cros_ec_get_ec_wake_gpe(struct device *dev)
+{
+   struct acpi_device *cros_acpi_dev;
+   struct acpi_device *adev;
+   acpi_handle handle;
+   acpi_status status;
+   int ret;
+
+   cros_acpi_dev = ACPI_COMPANION(dev);
+
+   if (!cros_acpi_dev || !cros_acpi_dev->parent ||
+  !cros_acpi_dev->parent->handle)
+   return -EINVAL;
+
+   status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
+);
+   if (ACPI_FAILURE(status))
+   return -EINVAL;
+
+   ret = acpi_bus_get_device(handle, );
+   if (ret)
+   return ret;
+
+   return adev->wakeup.gpe_number;
+}
+
+static int cros_ec_install_handler(struct device *dev)
+{
+   acpi_status status;
+
+   ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
+
+   if (ec_wake_gpe < 0)
+   return ec_wake_gpe;
+
+   status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
+ ACPI_GPE_EDGE_TRIGGERED,
+ _ec_gpe_handler, NULL);
+   if (ACPI_FAILURE(status))
+   return -ENODEV;
+
+   dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
+
+   return 0;
+}
+
+#endif
+
 static struct cros_ec_platform ec_p = {
.ec_name = CROS_EC_DEV_NAME,
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX),
@@ -166,6 +236,10 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
dev_info(dev, "Chrome EC device registered\n");
 
+#ifdef CONFIG_ACPI
+   cros_ec_install_handler(dev);
+#endif
+
return 0;
 
 fail_mfd:
@@ -179,6 +253,17 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
mfd_remove_devices(ec_dev->dev);
 
+#ifdef CONFIG_ACPI
+   if (ec_wake_gpe >= 0) {
+   acpi_status status;
+
+   status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
+_ec_gpe_handler);
+   if (ACPI_FAILURE(status))
+   pr_err("failed to remove gpe handler\n");
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_remove);
@@ -190,8 +275,16 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;
 
-   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
- HOST_SLEEP_EVENT_S0IX_RESUME;
+   if (!pm_suspend_via_firmware()) {
+   sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
+#ifdef CONFIG_ACPI
+   /* Clearing the GPE status for any pending event */
+   if (ec_wake_gpe >= 0)
+   acpi_clear_gpe(NULL, ec_wake_gpe);
+#endif
+   } else {
+   sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
+   }
 
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
-- 
2.7.4



[PATCH] mfd: cros_ec: Send correct suspend/resume event to EC

2017-01-13 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

pm_suspend_via_firmware() will return false for platforms with ACPI
disabled and ACPI is a prerequisite for S0ix support.

With this patch, sleep state event sent to EC is forced to S3 if ACPI is
disabled.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b8a5080..9b66a98 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -190,8 +190,9 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;
 
-   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
- HOST_SLEEP_EVENT_S0IX_RESUME;
+   sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
+ HOST_SLEEP_EVENT_S3_RESUME :
+ HOST_SLEEP_EVENT_S0IX_RESUME;
 
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
@@ -224,8 +225,9 @@ int cros_ec_resume(struct cros_ec_device *ec_dev)
ec_dev->suspended = false;
enable_irq(ec_dev->irq);
 
-   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
- HOST_SLEEP_EVENT_S0IX_RESUME;
+   sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
+ HOST_SLEEP_EVENT_S3_RESUME :
+ HOST_SLEEP_EVENT_S0IX_RESUME;
 
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
-- 
2.7.4



Re: [PATCH RESEND 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-12-01 Thread Thierry Escande

Hi Enric,

Thanks for the review.

On 30/11/2016 16:48, Enric Balletbo Serra wrote:

Hi Thierry,

I reviewed your patches and looks good to me, I only found a few style
things that is up to maintainer decide if are needed or not, most of
them are feedback I received on other subsystems. Ah, and I've a
question about runtime detection of the EC (see below), but guess the
answer is no.

Reviewed-by: Enric Balletbo i Serra <enric.balle...@collabora.com>

2016-11-08 13:27 GMT+01:00 Thierry Escande <thierry.esca...@collabora.com>:

From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.

+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+


As reported by checkpatch, write a paragraph that describes the config
symbol fully. Maybe adding something like this

  If you have a ChromeOS Embedded Controller Microchip EC variant
  choose Y here.

According to the help if you have a non-Microchip EC you should leave
this as N. Would be possible some kind of runtime detection of the EC
? Just thinking in out loud.
Well, we can use the EC_CMD_GET_CHIP_INFO command and check for the chip 
name as it is "mec1322" (at least on the cyan that I have).


Regards,
 Thierry




 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 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
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.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 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}

+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}

@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}

@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }

 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/ch

[PATCH 2/3] iio: core: Add double tap as possible gesture

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This adds the IIO_MOD_DOUBLE_TAP entry to the iio_modifier enum and the
corresponding "double_tap" string to the iio_modifier_names array.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/iio/industrialio-core.c | 1 +
 include/uapi/linux/iio/types.h  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index fc340ed..82ce05f 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -120,6 +120,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
+   [IIO_MOD_DOUBLE_TAP] = "double_tap",
 };
 
 /* relies on pairs of these shared then separate */
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 22e5e58..47d2768 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -80,6 +80,7 @@ enum iio_modifier {
IIO_MOD_CO2,
IIO_MOD_VOC,
IIO_MOD_LIGHT_UV,
+   IIO_MOD_DOUBLE_TAP,
 };
 
 enum iio_event_type {
-- 
2.7.4



[PATCH 1/3] mfd: cros_ec: Add activity motion sense definitions

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This adds motion sense definitions to the commands header related to the
activity sensors attached behind the ChromeOS Embedded Controller.
Supported activities are MOTION and DOUBLE_TAP.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 include/linux/mfd/cros_ec_commands.h | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index 1683003..80e6060 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -1417,6 +1417,18 @@ enum motionsense_command {
 */
MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
 
+   /*
+* List available activities for a MOTION sensor.
+* Indicates if they are enabled or disabled.
+*/
+   MOTIONSENSE_CMD_LIST_ACTIVITIES = 12,
+
+   /*
+* Activity management
+* Enable/Disable activity recognition.
+*/
+   MOTIONSENSE_CMD_SET_ACTIVITY = 13,
+
/* Number of motionsense sub-commands. */
MOTIONSENSE_NUM_CMDS
 };
@@ -1494,6 +1506,21 @@ struct ec_response_motion_sensor_data {
};
 } __packed;
 
+/* List supported activity recognition */
+enum motionsensor_activity {
+   MOTIONSENSE_ACTIVITY_RESERVED = 0,
+   MOTIONSENSE_ACTIVITY_SIG_MOTION = 1,
+   MOTIONSENSE_ACTIVITY_DOUBLE_TAP = 2,
+};
+
+struct ec_motion_sense_activity {
+   uint8_t sensor_num;
+   uint8_t activity;   /* one of enum motionsensor_activity */
+   uint8_t enable; /* 1: enable, 0: disable */
+   uint8_t reserved;
+   uint16_t parameters[3]; /* activity dependent parameters */
+};
+
 struct ec_params_motion_sense {
uint8_t cmd;
union {
@@ -1561,6 +1588,8 @@ struct ec_params_motion_sense {
/* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
int32_t data;
} sensor_odr, sensor_range;
+
+   struct ec_motion_sense_activity set_activity;
};
 } __packed;
 
@@ -1611,6 +1640,12 @@ struct ec_response_motion_sense {
int16_t temp;
int16_t offset[3];
} sensor_offset, perform_calib;
+
+   struct {
+   uint16_t reserved;
+   uint32_t enabled;
+   uint32_t disabled;
+   } __packed list_activities;
};
 } __packed;
 
-- 
2.7.4



[PATCH 0/3] Add ChromeOS EC Activity Sensors driver

2016-12-05 Thread Thierry Escande
Hi,

This patchset adds support for an activity sensors driver handling
activity/gesture recognition coming from the EC. Only significant motion
is currently supported. Moreover it is an incomplete driver: activity can
be set and ring buffer must be used to receive interruption.

This patchset depends on [1] to apply (which is merged into linux-next).

[1] https://lkml.org/lkml/2016/8/1/141

Regards,
 Thierry

Gwendal Grignou (3):
  mfd: cros_ec: update MOTIONSENSE definitions and commands
  iio: core: Add double tap as possible gesture
  iio: cros_ec_activity: add ChromeOS EC Activity Sensors

 drivers/iio/common/cros_ec_sensors/Kconfig |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile|   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 300 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  24 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   1 +
 drivers/iio/industrialio-core.c|   1 +
 include/linux/mfd/cros_ec_commands.h   |  35 +++
 include/uapi/linux/iio/types.h |   1 +
 8 files changed, 373 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

-- 
2.7.4



[PATCH 3/3] iio: cros_ec_activity: add ChromeOS EC Activity Sensors

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This patch adds a driver for handling activity/gesture recognition
coming from the EC. Only significant motion is currently supported. It
is an incomplete driver: activity can be set, but ring buffer must be
used to receive interruption.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/iio/common/cros_ec_sensors/Kconfig |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile|   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 300 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  24 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   1 +
 5 files changed, 336 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig 
b/drivers/iio/common/cros_ec_sensors/Kconfig
index 3349c9d..0a64928 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -21,3 +21,13 @@ config IIO_CROS_EC_SENSORS
  Accelerometers, Gyroscope and Magnetometer that are
  presented by the ChromeOS EC Sensor hub.
  Creates an IIO device for each functions.
+
+config IIO_CROS_EC_ACTIVITY
+   tristate "ChromeOS EC Activity Sensors"
+   select IIO_CROS_EC_SENSORS_CORE
+   help
+ Module to handle activity events detections presented by the ChromeOS
+ EC Sensor hub.
+ Activities can be simple (low/no motion) or more complex (riding 
train).
+ They are being reported by physical devices or the EC itself.
+ Creates an IIO device to manage all activities.
diff --git a/drivers/iio/common/cros_ec_sensors/Makefile 
b/drivers/iio/common/cros_ec_sensors/Makefile
index ec716ff..a4a2d6c 100644
--- a/drivers/iio/common/cros_ec_sensors/Makefile
+++ b/drivers/iio/common/cros_ec_sensors/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
 obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
+obj-$(CONFIG_IIO_CROS_EC_ACTIVITY) += cros_ec_activity.o
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
new file mode 100644
index 000..f14c3d3
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
@@ -0,0 +1,300 @@
+/*
+ * cros_ec_sensors_activity - Driver for activities/gesture recognition.
+ *
+ * Copyright (C) 2015 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 cros-ec interface to communicate with the Chrome OS
+ * EC about accelerometer data. Accelerometer access is presented through
+ * iio sysfs.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cros_ec_sensors_core.h"
+
+#define DRV_NAME "cros-ec-activity"
+
+/* st data for ec_sensors iio driver. */
+struct cros_ec_sensors_state {
+   /* Shared by all sensors */
+   struct cros_ec_sensors_core_state core;
+
+   struct iio_chan_spec *channels;
+   unsigned int nb_activities;
+};
+
+static const struct iio_event_spec cros_ec_activity_single_shot[] = {
+   {
+   .type = IIO_EV_TYPE_CHANGE,
+   /* significant motion trigger when we get out of still. */
+   .dir = IIO_EV_DIR_FALLING,
+   .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+},
+};
+
+static int ec_sensors_read(struct iio_dev *indio_dev,
+  struct iio_chan_spec const *chan,
+  int *val, int *val2, long mask)
+{
+   dev_warn(_dev->dev, "%s: Not Expected: %d\n", __func__,
+chan->channel2);
+
+   return -EPERM;
+}
+
+static int ec_sensors_write(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   int val, int val2, long mask)
+{
+   dev_warn(_dev->dev, "%s: Not Expected: %d\n", __func__,
+chan->channel2);
+
+   return -EPERM;
+}
+
+static int cros_ec_read_event_config(struct iio_dev *indio_dev,
+const struct iio_chan_spec *chan,
+enum iio_event_type type,
+enum iio_event_direction dir)
+{
+   struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (chan->type !

[PATCH v2 0/2] platform/chrome: Add support for mec1322 EC

2016-12-02 Thread Thierry Escande
Hi Benson,

This series adds support for the LPC Microchip Embedded Controller 1322.

v2:
-Add a few lines in Kconfig description
-Fixed coding style issues
-Updated copyright to year 2016

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   |  12 +++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  93 +---
 drivers/platform/chrome/cros_ec_lpc_mec.c | 140 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 
 include/linux/mfd/cros_ec_lpc_mec.h   |  90 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 482 insertions(+), 51 deletions(-)
 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.7.4



[PATCH v2 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-12-02 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@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 <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@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 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.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 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#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, ) &
+   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, );
 
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, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   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_xfe

[PATCH v2 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-12-02 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |  12 +++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 140 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  90 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 331 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..6d80fb5 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,18 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
+ If you have a ChromeOS Embedded Controller Microchip EC variant
+ choose Y here.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 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
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.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 6a782a6..bc2dc62 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -346,10 +346,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -358,6 +361,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -368,6 +372,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..2eda2c2
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,140 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * 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 
+#inc

Re: [PATCH 2/3] mfd: cros_ec: Send suspend state notification to EC

2017-01-04 Thread Thierry Escande

Hi Lee,

On 04/01/2017 10:07, Lee Jones wrote:

On Fri, 16 Dec 2016, Thierry Escande wrote:


From: Shawn Nematbakhsh <sha...@chromium.org>

Notify EC when going to or returning from suspend so that proper actions
related to wake events can be taken.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c| 49 
 include/linux/mfd/cros_ec_commands.h | 14 +++
 2 files changed, 63 insertions(+)


Can this patch be taken without 3/3?
Yes, both 1st and 2nd patches can be taken without the 3rd one. I'll 
send a v2 with 3/3 in a separate patch.


Regards,
 Thierry



For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jo...@linaro.org>


diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index ad48633..b8a5080 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 

 #define CROS_EC_DEV_EC_INDEX 0
@@ -65,6 +66,24 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
return IRQ_HANDLED;
 }

+static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
+{
+   struct {
+   struct cros_ec_command msg;
+   struct ec_params_host_sleep_event req;
+   } __packed buf;
+
+   memset(, 0, sizeof(buf));
+
+   buf.req.sleep_event = sleep_event;
+
+   buf.msg.command = EC_CMD_HOST_SLEEP_EVENT;
+   buf.msg.version = 0;
+   buf.msg.outsize = sizeof(buf.req);
+
+   return cros_ec_cmd_xfer(ec_dev, );
+}
+
 int cros_ec_register(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
@@ -136,6 +155,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
}
}

+   /*
+* Clear sleep event - this will fail harmlessly on platforms that
+* don't implement the sleep event host command.
+*/
+   err = cros_ec_sleep_event(ec_dev, 0);
+   if (err < 0)
+   dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec",
+   err);
+
dev_info(dev, "Chrome EC device registered\n");

return 0;
@@ -159,6 +187,16 @@ EXPORT_SYMBOL(cros_ec_remove);
 int cros_ec_suspend(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
+   int ret;
+   u8 sleep_event;
+
+   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
+ HOST_SLEEP_EVENT_S0IX_RESUME;
+
+   ret = cros_ec_sleep_event(ec_dev, sleep_event);
+   if (ret < 0)
+   dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec",
+   ret);

if (device_may_wakeup(dev))
ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
@@ -180,9 +218,20 @@ static void cros_ec_drain_events(struct cros_ec_device 
*ec_dev)

 int cros_ec_resume(struct cros_ec_device *ec_dev)
 {
+   int ret;
+   u8 sleep_event;
+
ec_dev->suspended = false;
enable_irq(ec_dev->irq);

+   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
+ HOST_SLEEP_EVENT_S0IX_RESUME;
+
+   ret = cros_ec_sleep_event(ec_dev, sleep_event);
+   if (ret < 0)
+   dev_dbg(ec_dev->dev, "Error %d sending resume event to ec",
+   ret);
+
/*
 * In some cases, we need to distinguish between events that occur
 * during suspend if the EC is not a wake source. For example,
diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index 76728ff..4d55132 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -2304,6 +2304,20 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;

+/* Inform the EC when entering a sleep state */
+#define EC_CMD_HOST_SLEEP_EVENT 0xa9
+
+enum host_sleep_event {
+   HOST_SLEEP_EVENT_S3_SUSPEND   = 1,
+   HOST_SLEEP_EVENT_S3_RESUME= 2,
+   HOST_SLEEP_EVENT_S0IX_SUSPEND = 3,
+   HOST_SLEEP_EVENT_S0IX_RESUME  = 4
+};
+
+struct ec_params_host_sleep_event {
+   uint8_t sleep_event;
+} __packed;
+
 /*/
 /* Smart battery pass-through */





Re: [PATCH 3/3] mfd: cros_ec: Add ACPI GPE handler for LID0 devices

2017-01-05 Thread Thierry Escande

Hi Lee,

On 05/01/2017 08:54, Lee Jones wrote:

On Wed, 04 Jan 2017, Thierry Escande wrote:


Hi Lee,

On 04/01/2017 10:06, Lee Jones wrote:

On Fri, 16 Dec 2016, Thierry Escande wrote:


From: Archana Patni <archana.pa...@intel.com>

This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
ACPI core that this GPE should stay enabled for lid to work in suspend
to idle path.

Signed-off-by: Archana Patni <archana.pa...@intel.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c | 97 +--
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b8a5080..628718e 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -17,6 +17,9 @@
  * battery charging and regulator control, firmware update.
  */

+#ifdef CONFIG_ACPI
+#include 
+#endif


Please don't place #ifery in C files.


 #include 
 #include 
 #include 
@@ -29,6 +32,73 @@
 #define CROS_EC_DEV_EC_INDEX 0
 #define CROS_EC_DEV_PD_INDEX 1

+#ifdef CONFIG_ACPI


Remove this.


+#define ACPI_LID_DEVICE  "LID0"
+
+static int ec_wake_gpe = -EINVAL;
+
+/*
+ * This handler indicates to ACPI core that this GPE should stay enabled for
+ * lid to work in suspend to idle path.
+ */
+static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
+  void *data)
+{
+   return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+/*
+ * Get ACPI GPE for LID0 device.
+ */
+static int cros_ec_get_ec_wake_gpe(struct device *dev)
+{

If it's ok for you, I'll keep one #ifdef CONFIG_ACPI around the body of this
function. Otherwise it won't compile if CONFIG_ACPI is not set.


Can you try placing:

if (IS_ENABLED(CONFIG_ACPI))

... before the call to cros_ec_get_ec_wake_gpe() and see if the
compiler will do-the-right-thing please?


With CONFIG_ACPI not defined, the acpi_dev structure is not defined as 
well as the acpi_bus_get_device() API. So no, the compiler is not smart 
enough even if the function body is skipped by the test:

if (!IS_ENABLED(CONFIG_ACPI))
return -ENODEV;

Regards,
 Thierry


+   struct acpi_device *cros_acpi_dev;
+   struct acpi_device *adev;
+   acpi_handle handle;
+   acpi_status status;
+   int ret;
+
+   cros_acpi_dev = ACPI_COMPANION(dev);
+
+   if (!cros_acpi_dev || !cros_acpi_dev->parent ||
+  !cros_acpi_dev->parent->handle)
+   return -EINVAL;
+
+   status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
+);
+   if (ACPI_FAILURE(status))
+   return -EINVAL;
+
+   ret = acpi_bus_get_device(handle, );
+   if (ret)
+   return ret;
+
+   return adev->wakeup.gpe_number;
+}
+
+static int cros_ec_install_handler(struct device *dev)
+{
+   acpi_status status;
+
+   ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
+
+   if (ec_wake_gpe < 0)
+   return ec_wake_gpe;
+
+   status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
+ ACPI_GPE_EDGE_TRIGGERED,
+ _ec_gpe_handler, NULL);
+   if (ACPI_FAILURE(status))
+   return -ENODEV;
+
+   dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
+
+   return 0;
+}
+
+#endif
+
 static struct cros_ec_platform ec_p = {
.ec_name = CROS_EC_DEV_NAME,
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX),
@@ -166,6 +236,10 @@ int cros_ec_register(struct cros_ec_device *ec_dev)

dev_info(dev, "Chrome EC device registered\n");

+#ifdef CONFIG_ACPI
+   cros_ec_install_handler(dev);
+#endif


Here, just do:

if (IS_ENABLED(CONFIG_ACPI))
cros_ec_install_handler(dev);

And let the compiler take care of the rest.


return 0;

 fail_mfd:
@@ -179,6 +253,17 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
mfd_remove_devices(ec_dev->dev);

+#ifdef CONFIG_ACPI
+   if (ec_wake_gpe >= 0) {


if (IS_ENABLED(CONFIG_ACPI) && ec_wake_gpe >= 0) {


+   acpi_status status;
+
+   status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
+_ec_gpe_handler);
+   if (ACPI_FAILURE(status))
+   pr_err("failed to remove gpe handler\n");
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_remove);
@@ -190,8 +275,16 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;

-   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
- HOST_SLEEP_EVENT_S0IX_RESUME;
+   if (!pm_suspend_via_firmware()) {
+   sleep_event = HOST_

Re: [PATCH 3/3] mfd: cros_ec: Add ACPI GPE handler for LID0 devices

2017-01-04 Thread Thierry Escande

Hi Lee,

On 04/01/2017 10:06, Lee Jones wrote:

On Fri, 16 Dec 2016, Thierry Escande wrote:


From: Archana Patni <archana.pa...@intel.com>

This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
ACPI core that this GPE should stay enabled for lid to work in suspend
to idle path.

Signed-off-by: Archana Patni <archana.pa...@intel.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c | 97 +--
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b8a5080..628718e 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -17,6 +17,9 @@
  * battery charging and regulator control, firmware update.
  */

+#ifdef CONFIG_ACPI
+#include 
+#endif


Please don't place #ifery in C files.


 #include 
 #include 
 #include 
@@ -29,6 +32,73 @@
 #define CROS_EC_DEV_EC_INDEX 0
 #define CROS_EC_DEV_PD_INDEX 1

+#ifdef CONFIG_ACPI


Remove this.


+#define ACPI_LID_DEVICE  "LID0"
+
+static int ec_wake_gpe = -EINVAL;
+
+/*
+ * This handler indicates to ACPI core that this GPE should stay enabled for
+ * lid to work in suspend to idle path.
+ */
+static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
+  void *data)
+{
+   return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+/*
+ * Get ACPI GPE for LID0 device.
+ */
+static int cros_ec_get_ec_wake_gpe(struct device *dev)
+{
If it's ok for you, I'll keep one #ifdef CONFIG_ACPI around the body of 
this function. Otherwise it won't compile if CONFIG_ACPI is not set.


Regards,
 Thierry


+   struct acpi_device *cros_acpi_dev;
+   struct acpi_device *adev;
+   acpi_handle handle;
+   acpi_status status;
+   int ret;
+
+   cros_acpi_dev = ACPI_COMPANION(dev);
+
+   if (!cros_acpi_dev || !cros_acpi_dev->parent ||
+  !cros_acpi_dev->parent->handle)
+   return -EINVAL;
+
+   status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
+);
+   if (ACPI_FAILURE(status))
+   return -EINVAL;
+
+   ret = acpi_bus_get_device(handle, );
+   if (ret)
+   return ret;
+
+   return adev->wakeup.gpe_number;
+}
+
+static int cros_ec_install_handler(struct device *dev)
+{
+   acpi_status status;
+
+   ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
+
+   if (ec_wake_gpe < 0)
+   return ec_wake_gpe;
+
+   status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
+ ACPI_GPE_EDGE_TRIGGERED,
+ _ec_gpe_handler, NULL);
+   if (ACPI_FAILURE(status))
+   return -ENODEV;
+
+   dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
+
+   return 0;
+}
+
+#endif
+
 static struct cros_ec_platform ec_p = {
.ec_name = CROS_EC_DEV_NAME,
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX),
@@ -166,6 +236,10 @@ int cros_ec_register(struct cros_ec_device *ec_dev)

dev_info(dev, "Chrome EC device registered\n");

+#ifdef CONFIG_ACPI
+   cros_ec_install_handler(dev);
+#endif


Here, just do:

if (IS_ENABLED(CONFIG_ACPI))
cros_ec_install_handler(dev);

And let the compiler take care of the rest.


return 0;

 fail_mfd:
@@ -179,6 +253,17 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
mfd_remove_devices(ec_dev->dev);

+#ifdef CONFIG_ACPI
+   if (ec_wake_gpe >= 0) {


if (IS_ENABLED(CONFIG_ACPI) && ec_wake_gpe >= 0) {


+   acpi_status status;
+
+   status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
+_ec_gpe_handler);
+   if (ACPI_FAILURE(status))
+   pr_err("failed to remove gpe handler\n");
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_remove);
@@ -190,8 +275,16 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;

-   sleep_event = pm_suspend_via_firmware() ? HOST_SLEEP_EVENT_S3_RESUME :
- HOST_SLEEP_EVENT_S0IX_RESUME;
+   if (!pm_suspend_via_firmware()) {
+   sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
+#ifdef CONFIG_ACPI
+   /* Clearing the GPE status for any pending event */
+   if (ec_wake_gpe >= 0)


As above.


+   acpi_clear_gpe(NULL, ec_wake_gpe);
+#endif
+   } else {
+   sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
+   }

ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)




Re: [PATCH 3/3] mfd: cros_ec: Add ACPI GPE handler for LID0 devices

2017-01-05 Thread Thierry Escande

On 05/01/2017 15:43, Lee Jones wrote:

Rafael,

On Thu, 05 Jan 2017, Thierry Escande wrote:


Hi Lee,

On 05/01/2017 08:54, Lee Jones wrote:

On Wed, 04 Jan 2017, Thierry Escande wrote:


Hi Lee,

On 04/01/2017 10:06, Lee Jones wrote:

On Fri, 16 Dec 2016, Thierry Escande wrote:


From: Archana Patni <archana.pa...@intel.com>

This patch installs an ACPI GPE handler for LID0 ACPI device to indicate
ACPI core that this GPE should stay enabled for lid to work in suspend
to idle path.

Signed-off-by: Archana Patni <archana.pa...@intel.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c | 97 +--
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b8a5080..628718e 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -17,6 +17,9 @@
  * battery charging and regulator control, firmware update.
  */

+#ifdef CONFIG_ACPI
+#include 
+#endif


Please don't place #ifery in C files.


 #include 
 #include 
 #include 
@@ -29,6 +32,73 @@
 #define CROS_EC_DEV_EC_INDEX 0
 #define CROS_EC_DEV_PD_INDEX 1

+#ifdef CONFIG_ACPI


Remove this.


+#define ACPI_LID_DEVICE  "LID0"
+
+static int ec_wake_gpe = -EINVAL;
+
+/*
+ * This handler indicates to ACPI core that this GPE should stay enabled for
+ * lid to work in suspend to idle path.
+ */
+static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
+  void *data)
+{
+   return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+/*
+ * Get ACPI GPE for LID0 device.
+ */
+static int cros_ec_get_ec_wake_gpe(struct device *dev)
+{

If it's ok for you, I'll keep one #ifdef CONFIG_ACPI around the body of this
function. Otherwise it won't compile if CONFIG_ACPI is not set.


Can you try placing:

if (IS_ENABLED(CONFIG_ACPI))

... before the call to cros_ec_get_ec_wake_gpe() and see if the
compiler will do-the-right-thing please?


With CONFIG_ACPI not defined, the acpi_dev structure is not defined as well
as the acpi_bus_get_device() API. So no, the compiler is not smart enough
even if the function body is skipped by the test:
if (!IS_ENABLED(CONFIG_ACPI))
return -ENODEV;


Is there any way we can make ACPI play nicely if it's not enabled?

I'm thinking stubs.  Like we do for most other things.


Or I can move the 2 functions into a separate file compiled only if ACPI 
is enabled.


Regards,
 Thierry




+   struct acpi_device *cros_acpi_dev;
+   struct acpi_device *adev;
+   acpi_handle handle;
+   acpi_status status;
+   int ret;
+
+   cros_acpi_dev = ACPI_COMPANION(dev);
+
+   if (!cros_acpi_dev || !cros_acpi_dev->parent ||
+  !cros_acpi_dev->parent->handle)
+   return -EINVAL;
+
+   status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
+);
+   if (ACPI_FAILURE(status))
+   return -EINVAL;
+
+   ret = acpi_bus_get_device(handle, );
+   if (ret)
+   return ret;
+
+   return adev->wakeup.gpe_number;
+}
+
+static int cros_ec_install_handler(struct device *dev)
+{
+   acpi_status status;
+
+   ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
+
+   if (ec_wake_gpe < 0)
+   return ec_wake_gpe;
+
+   status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
+ ACPI_GPE_EDGE_TRIGGERED,
+ _ec_gpe_handler, NULL);
+   if (ACPI_FAILURE(status))
+   return -ENODEV;
+
+   dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
+
+   return 0;
+}
+
+#endif
+
 static struct cros_ec_platform ec_p = {
.ec_name = CROS_EC_DEV_NAME,
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_EC_INDEX),
@@ -166,6 +236,10 @@ int cros_ec_register(struct cros_ec_device *ec_dev)

dev_info(dev, "Chrome EC device registered\n");

+#ifdef CONFIG_ACPI
+   cros_ec_install_handler(dev);
+#endif


Here, just do:

if (IS_ENABLED(CONFIG_ACPI))
cros_ec_install_handler(dev);

And let the compiler take care of the rest.


return 0;

 fail_mfd:
@@ -179,6 +253,17 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
mfd_remove_devices(ec_dev->dev);

+#ifdef CONFIG_ACPI
+   if (ec_wake_gpe >= 0) {


if (IS_ENABLED(CONFIG_ACPI) && ec_wake_gpe >= 0) {


+   acpi_status status;
+
+   status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
+_ec_gpe_handler);
+   if (ACPI_FAILURE(status))
+   pr_err("failed to remove gpe handler\n");
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_remove);
@@ -190,8 +275,16 @@ int cros_ec_susp

[PATCH 3/5] firmware: google memconsole: Add coreboot support

2017-03-23 Thread Thierry Escande
Coreboot (http://www.coreboot.org) allows to save the firmware console
output in a memory buffer. With this patch, the address of this memory
buffer is obtained from coreboot tables on x86 chromebook devices
declaring an ACPI device with name matching GOOGCB00 or BOOT.

If the memconsole-coreboot driver is able to find the coreboot table,
the memconsole driver sets the cbmem_console address and initializes the
memconsole sysfs entries.

The coreboot_table-acpi driver is responsible for setting the address of
the coreboot table header when probed. If this address is not yet set
when memconsole-coreboot is probed, then the probe is deferred by
returning -EPROBE_DEFER.

This patch is a rework/split/merge of patches from the chromeos v4.4
kernel tree originally authored by:
 Vadim Bendebury <vben...@chromium.org>
 Wei-Ning Huang <wnhu...@google.com>
 Yuji Sasaki <sasa...@google.com>
 Duncan Laurie <dlau...@chromium.org>
 Julius Werner <jwer...@chromium.org>
 Brian Norris <briannor...@chromium.org>

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig   |  25 +-
 drivers/firmware/google/Makefile  |   3 +
 drivers/firmware/google/coreboot_table-acpi.c |  88 +
 drivers/firmware/google/coreboot_table.c  |  94 ++
 drivers/firmware/google/coreboot_table.h  |  50 
 drivers/firmware/google/memconsole-coreboot.c | 109 ++
 6 files changed, 368 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/google/coreboot_table-acpi.c
 create mode 100644 drivers/firmware/google/coreboot_table.c
 create mode 100644 drivers/firmware/google/coreboot_table.h
 create mode 100644 drivers/firmware/google/memconsole-coreboot.c

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 27a0658..840bd62 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -19,9 +19,23 @@ config GOOGLE_SMI
  clearing the EFI event log and reading and writing NVRAM
  variables.
 
+config GOOGLE_COREBOOT_TABLE
+   tristate
+   depends on GOOGLE_COREBOOT_TABLE_ACPI
+
+config GOOGLE_COREBOOT_TABLE_ACPI
+   tristate "Coreboot Table Access - ACPI"
+   depends on ACPI
+   select GOOGLE_COREBOOT_TABLE
+   help
+ This option enables the coreboot_table module, which provides other
+ firmware modules to access to the coreboot table. The coreboot table
+ pointer is accessed through the ACPI "GOOGCB00" object.
+ If unsure say N.
+
 config GOOGLE_MEMCONSOLE
tristate
-   depends on GOOGLE_MEMCONSOLE_X86_LEGACY
+   depends on GOOGLE_MEMCONSOLE_X86_LEGACY || GOOGLE_MEMCONSOLE_COREBOOT
 
 config GOOGLE_MEMCONSOLE_X86_LEGACY
tristate "Firmware Memory Console - X86 Legacy support"
@@ -32,4 +46,13 @@ config GOOGLE_MEMCONSOLE_X86_LEGACY
  the EBDA on Google servers.  If found, this log is exported to
  userland in the file /sys/firmware/log.
 
+config GOOGLE_MEMCONSOLE_COREBOOT
+   tristate "Firmware Memory Console"
+   depends on GOOGLE_COREBOOT_TABLE
+   select GOOGLE_MEMCONSOLE
+   help
+ This option enables the kernel to search for a firmware log in
+ the coreboot table.  If found, this log is exported to userland
+ in the file /sys/firmware/log.
+
 endif # GOOGLE_FIRMWARE
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index 10683ef..662a83e 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -1,4 +1,7 @@
 
 obj-$(CONFIG_GOOGLE_SMI)   += gsmi.o
+obj-$(CONFIG_GOOGLE_COREBOOT_TABLE)+= coreboot_table.o
+obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_ACPI)   += coreboot_table-acpi.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT)   += memconsole-coreboot.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
diff --git a/drivers/firmware/google/coreboot_table-acpi.c 
b/drivers/firmware/google/coreboot_table-acpi.c
new file mode 100644
index 000..fb98db2
--- /dev/null
+++ b/drivers/firmware/google/coreboot_table-acpi.c
@@ -0,0 +1,88 @@
+/*
+ * coreboot_table-acpi.c
+ *
+ * Using ACPI to locate Coreboot table and provide coreboot table access.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#incl

[PATCH 5/5] firmware: google memconsole: Add ARM/ARM64 support

2017-03-23 Thread Thierry Escande
This patch expands the Google firmware memory console driver to also
work on certain tree based platforms running coreboot, such as ARM/ARM64
Chromebooks. This patch now adds another path to find the coreboot table
through the device tree. In order to find that, a second level
bootloader must have installed the 'coreboot' compatible device tree
node that describes its base address and size.

This patch is a rework/split/merge of patches from the chromeos v4.4
kernel tree originally authored by:
 Wei-Ning Huang <wnhu...@chromium.org>
 Julius Werner <jwer...@chromium.org>
 Brian Norris <briannor...@chromium.org>

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig | 13 -
 drivers/firmware/google/Makefile|  1 +
 drivers/firmware/google/coreboot_table-of.c | 82 +
 3 files changed, 94 insertions(+), 2 deletions(-)
 create mode 100644 drivers/firmware/google/coreboot_table-of.c

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 840bd62..baabd70 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -1,6 +1,5 @@
 menuconfig GOOGLE_FIRMWARE
bool "Google Firmware Drivers"
-   depends on X86
default n
help
  These firmware drivers are used by Google's servers.  They are
@@ -21,7 +20,7 @@ config GOOGLE_SMI
 
 config GOOGLE_COREBOOT_TABLE
tristate
-   depends on GOOGLE_COREBOOT_TABLE_ACPI
+   depends on GOOGLE_COREBOOT_TABLE_ACPI || GOOGLE_COREBOOT_TABLE_OF
 
 config GOOGLE_COREBOOT_TABLE_ACPI
tristate "Coreboot Table Access - ACPI"
@@ -33,6 +32,16 @@ config GOOGLE_COREBOOT_TABLE_ACPI
  pointer is accessed through the ACPI "GOOGCB00" object.
  If unsure say N.
 
+config GOOGLE_COREBOOT_TABLE_OF
+   tristate "Coreboot Table Access - Device Tree"
+   depends on OF
+   select GOOGLE_COREBOOT_TABLE
+   help
+ This option enable the coreboot_table module, which provide other
+ firmware modules to access coreboot table. The coreboot table pointer
+ is accessed through the device tree node /firmware/coreboot.
+ If unsure say N.
+
 config GOOGLE_MEMCONSOLE
tristate
depends on GOOGLE_MEMCONSOLE_X86_LEGACY || GOOGLE_MEMCONSOLE_COREBOOT
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index 662a83e..bb952c6 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -2,6 +2,7 @@
 obj-$(CONFIG_GOOGLE_SMI)   += gsmi.o
 obj-$(CONFIG_GOOGLE_COREBOOT_TABLE)+= coreboot_table.o
 obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_ACPI)   += coreboot_table-acpi.o
+obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_OF) += coreboot_table-of.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT)   += memconsole-coreboot.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
diff --git a/drivers/firmware/google/coreboot_table-of.c 
b/drivers/firmware/google/coreboot_table-of.c
new file mode 100644
index 000..727acdc
--- /dev/null
+++ b/drivers/firmware/google/coreboot_table-of.c
@@ -0,0 +1,82 @@
+/*
+ * coreboot_table-of.c
+ *
+ * Coreboot table access through open firmware.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "coreboot_table.h"
+
+static int coreboot_table_of_probe(struct platform_device *pdev)
+{
+   struct device_node *fw_dn = pdev->dev.of_node;
+   void __iomem *ptr;
+
+   ptr = of_iomap(fw_dn, 0);
+   of_node_put(fw_dn);
+   if (!ptr)
+   return -ENOMEM;
+
+   return coreboot_table_init(ptr);
+}
+
+static int coreboot_table_of_remove(struct platform_device *pdev)
+{
+   return coreboot_table_exit();
+}
+
+static const struct of_device_id coreboot_of_match[] = {
+   { .compatible = "coreboot" },
+   {},
+};
+
+static struct platform_driver coreboot_table_of_driver = {
+   .probe = coreboot_table_of_probe,
+   .remove = coreboot_table_of_remove,
+   .driver = {
+   .name = "coreboot_table_of",
+   .of_match_table = coreboot_of_match,
+   },
+};
+
+static int __init platform_coreboot_table_of_init(void)
+{
+   struct platform_device *pdev;
+   struct device_node *of_node;
+
+   /* Limit device creatio

[PATCH 1/5] firmware: google memconsole: Remove useless submenu in Kconfig

2017-03-23 Thread Thierry Escande
This patch removes the "Google Firmware Drivers" menu containing a
menuconfig entry with the exact same name. The menuconfig is now
directly under the "Firmware Drivers" entry.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 29c8cdd..475bd01 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -1,4 +1,4 @@
-config GOOGLE_FIRMWARE
+menuconfig GOOGLE_FIRMWARE
bool "Google Firmware Drivers"
depends on X86
default n
@@ -7,8 +7,7 @@ config GOOGLE_FIRMWARE
  only useful if you are working directly on one of their
  proprietary servers.  If in doubt, say "N".
 
-menu "Google Firmware Drivers"
-   depends on GOOGLE_FIRMWARE
+if GOOGLE_FIRMWARE
 
 config GOOGLE_SMI
tristate "SMI interface for Google platforms"
@@ -28,4 +27,4 @@ config GOOGLE_MEMCONSOLE
  the EBDA on Google servers.  If found, this log is exported to
  userland in the file /sys/firmware/log.
 
-endmenu
+endif # GOOGLE_FIRMWARE
-- 
2.7.4



[PATCH 2/5] firmware: google memconsole: Move specific EBDA parts

2017-03-23 Thread Thierry Escande
This patch splits memconsole.c in 2 parts. One containing the
architecture-independent part and the other one containing the EBDA
specific part. This prepares the integration of coreboot support for the
memconsole.

The memconsole driver is now named as memconsole-x86-legacy.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig |   9 +-
 drivers/firmware/google/Makefile|   3 +-
 drivers/firmware/google/memconsole-x86-legacy.c | 154 +++
 drivers/firmware/google/memconsole.c| 155 
 drivers/firmware/google/memconsole.h|  43 +++
 5 files changed, 229 insertions(+), 135 deletions(-)
 create mode 100644 drivers/firmware/google/memconsole-x86-legacy.c
 create mode 100644 drivers/firmware/google/memconsole.h

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 475bd01..27a0658 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -20,8 +20,13 @@ config GOOGLE_SMI
  variables.
 
 config GOOGLE_MEMCONSOLE
-   tristate "Firmware Memory Console"
-   depends on DMI
+   tristate
+   depends on GOOGLE_MEMCONSOLE_X86_LEGACY
+
+config GOOGLE_MEMCONSOLE_X86_LEGACY
+   tristate "Firmware Memory Console - X86 Legacy support"
+   depends on X86 && ACPI && DMI
+   select GOOGLE_MEMCONSOLE
help
  This option enables the kernel to search for a firmware log in
  the EBDA on Google servers.  If found, this log is exported to
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index 54a294e..10683ef 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_GOOGLE_SMI)   += gsmi.o
-obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
diff --git a/drivers/firmware/google/memconsole-x86-legacy.c 
b/drivers/firmware/google/memconsole-x86-legacy.c
new file mode 100644
index 000..529078c
--- /dev/null
+++ b/drivers/firmware/google/memconsole-x86-legacy.c
@@ -0,0 +1,154 @@
+/*
+ * memconsole-x86-legacy.c
+ *
+ * EBDA specific parts of the memory based BIOS console.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "memconsole.h"
+
+#define BIOS_MEMCONSOLE_V1_MAGIC   0xDEADBABE
+#define BIOS_MEMCONSOLE_V2_MAGIC   (('M')|('C'<<8)|('O'<<16)|('N'<<24))
+
+struct biosmemcon_ebda {
+   u32 signature;
+   union {
+   struct {
+   u8  enabled;
+   u32 buffer_addr;
+   u16 start;
+   u16 end;
+   u16 num_chars;
+   u8  wrapped;
+   } __packed v1;
+   struct {
+   u32 buffer_addr;
+   /* Misdocumented as number of pages! */
+   u16 num_bytes;
+   u16 start;
+   u16 end;
+   } __packed v2;
+   };
+} __packed;
+
+static void found_v1_header(struct biosmemcon_ebda *hdr)
+{
+   pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
+   hdr);
+   pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = 
%d, num = %d\n",
+   hdr->v1.buffer_addr, hdr->v1.start,
+   hdr->v1.end, hdr->v1.num_chars);
+
+   memconsole_setup(phys_to_virt(hdr->v1.buffer_addr), hdr->v1.num_chars);
+}
+
+static void found_v2_header(struct biosmemcon_ebda *hdr)
+{
+   pr_info("memconsole: BIOS console v2 EBDA structure found at %p\n",
+   hdr);
+   pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = 
%d, num_bytes = %d\n",
+   hdr->v2.buffer_addr, hdr->v2.start,
+   hdr->v2.end, hdr->v2.num_bytes);
+
+   memconsole_setup(phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start),
+hdr->v2.end - hdr->v2.start);
+}
+
+/*
+ * Search through the EBDA for the BIOS Memory Console, and
+ * set the global variables to point to it.  Return true if found.
+ */
+stati

[PATCH 4/5] firmware: Add coreboot device tree binding documentation

2017-03-23 Thread Thierry Escande
From: Julius Werner <jwer...@chromium.org>

This patch adds documentation describing a device tree binding for the
coreboot firmware. It is meant to be dynamically added during boot and
contains address definitions for the coreboot table (a list of
variable-sized descriptors providing information about various compile-
and run-time generated firmware parameters) and the CBMEM area (the
structure containing most run-time resident memory regions set up by
coreboot).

These definitions allow kernel drivers to easily access data contained
in and pointed to by these regions (such as coreboot's in-memory log).
(An example implementation can be seen in the following patch)

Signed-off-by: Julius Werner <jwer...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 .../devicetree/bindings/firmware/coreboot.txt  | 33 ++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/coreboot.txt

diff --git a/Documentation/devicetree/bindings/firmware/coreboot.txt 
b/Documentation/devicetree/bindings/firmware/coreboot.txt
new file mode 100644
index 000..4c95570
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/coreboot.txt
@@ -0,0 +1,33 @@
+COREBOOT firmware information
+
+The device tree node to communicate the location of coreboot's memory-resident
+bookkeeping structures to the kernel. Since coreboot itself cannot boot a
+device-tree-based kernel (yet), this node needs to be inserted by a
+second-stage bootloader (a coreboot "payload").
+
+Required properties:
+ - compatible: Should be "coreboot"
+ - reg: Address and length of the following two memory regions, in order:
+   1.) The coreboot table. This is a list of variable-sized descriptors
+   that contain various compile- and run-time generated firmware
+   parameters. It is identified by the magic string "LBIO" in its first
+   four bytes.
+   See coreboot's src/commonlib/include/commonlib/coreboot_tables.h for
+   details.
+   2.) The CBMEM area. This is a downward-growing memory region used by
+   coreboot to dynamically allocate data structures that remain resident.
+   It may or may not include the coreboot table as one of its members. It
+   is identified by a root node descriptor with the magic number
+   0xc0389481 that resides in the topmost 8 bytes of the area.
+   See coreboot's src/include/imd.h for details.
+
+Example:
+   firmware {
+   ranges;
+
+   coreboot {
+   compatible = "coreboot";
+   reg = <0xfdfea000 0x264>,
+ <0xfdfea000 0x16000>;
+   }
+   };
-- 
2.7.4



[PATCH 0/5] firmware: google memconsole

2017-03-23 Thread Thierry Escande
Hi,

This series extends the Google memory console driver to work on x86 and
ARM platforms running coreboot.

The legacy x86 memconsole driver is now named memconsole-x86-legacy and
a new driver named memconsole-coreboot is added.

On coreboot devices and depending on the device architecture, the driver
coreboot_table-acpi on x86 platforms or coreboot_table-of on ARM/ARM64
platforms is responsible to get the coreboot table header memory address
and then obtain the memory console address.

Regards,
 Thierry

Julius Werner (1):
  firmware: Add coreboot device tree binding documentation

Thierry Escande (4):
  firmware: google memconsole: Remove useless submenu in Kconfig
  firmware: google memconsole: Move specific EBDA parts
  firmware: google memconsole: Add coreboot support
  firmware: google memconsole: Add ARM/ARM64 support

 .../devicetree/bindings/firmware/coreboot.txt  |  33 +
 drivers/firmware/google/Kconfig|  50 ++-
 drivers/firmware/google/Makefile   |   7 +-
 drivers/firmware/google/coreboot_table-acpi.c  |  88 
 drivers/firmware/google/coreboot_table-of.c|  82 +++
 drivers/firmware/google/coreboot_table.c   |  94 +
 drivers/firmware/google/coreboot_table.h   |  50 +++
 drivers/firmware/google/memconsole-coreboot.c  | 109 +++
 drivers/firmware/google/memconsole-x86-legacy.c| 154 
 drivers/firmware/google/memconsole.c   | 155 +++--
 drivers/firmware/google/memconsole.h   |  43 ++
 11 files changed, 725 insertions(+), 140 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/coreboot.txt
 create mode 100644 drivers/firmware/google/coreboot_table-acpi.c
 create mode 100644 drivers/firmware/google/coreboot_table-of.c
 create mode 100644 drivers/firmware/google/coreboot_table.c
 create mode 100644 drivers/firmware/google/coreboot_table.h
 create mode 100644 drivers/firmware/google/memconsole-coreboot.c
 create mode 100644 drivers/firmware/google/memconsole-x86-legacy.c
 create mode 100644 drivers/firmware/google/memconsole.h

-- 
2.7.4



[PATCH v2 5/5] firmware: google memconsole: Add ARM/ARM64 support

2017-03-28 Thread Thierry Escande
This patch expands the Google firmware memory console driver to also
work on certain tree based platforms running coreboot, such as ARM/ARM64
Chromebooks. This patch now adds another path to find the coreboot table
through the device tree. In order to find that, a second level
bootloader must have installed the 'coreboot' compatible device tree
node that describes its base address and size.

This patch is a rework/split/merge of patches from the chromeos v4.4
kernel tree originally authored by:
 Wei-Ning Huang <wnhu...@chromium.org>
 Julius Werner <jwer...@chromium.org>
 Brian Norris <briannor...@chromium.org>

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

In this v2:
Adds a missing dependency on X86 for the GOOGLE_SMI symbol reported by
the kbuild test robot as the X86 dependency is removed from the
GOOGLE_FIRMWARE symbol for ARM support.

 drivers/firmware/google/Kconfig | 15 --
 drivers/firmware/google/Makefile|  1 +
 drivers/firmware/google/coreboot_table-of.c | 82 +
 3 files changed, 95 insertions(+), 3 deletions(-)
 create mode 100644 drivers/firmware/google/coreboot_table-of.c

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 840bd62..0e0 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -1,6 +1,5 @@
 menuconfig GOOGLE_FIRMWARE
bool "Google Firmware Drivers"
-   depends on X86
default n
help
  These firmware drivers are used by Google's servers.  They are
@@ -11,7 +10,7 @@ if GOOGLE_FIRMWARE
 
 config GOOGLE_SMI
tristate "SMI interface for Google platforms"
-   depends on ACPI && DMI && EFI
+   depends on X86 && ACPI && DMI && EFI
select EFI_VARS
help
  Say Y here if you want to enable SMI callbacks for Google
@@ -21,7 +20,7 @@ config GOOGLE_SMI
 
 config GOOGLE_COREBOOT_TABLE
tristate
-   depends on GOOGLE_COREBOOT_TABLE_ACPI
+   depends on GOOGLE_COREBOOT_TABLE_ACPI || GOOGLE_COREBOOT_TABLE_OF
 
 config GOOGLE_COREBOOT_TABLE_ACPI
tristate "Coreboot Table Access - ACPI"
@@ -33,6 +32,16 @@ config GOOGLE_COREBOOT_TABLE_ACPI
  pointer is accessed through the ACPI "GOOGCB00" object.
  If unsure say N.
 
+config GOOGLE_COREBOOT_TABLE_OF
+   tristate "Coreboot Table Access - Device Tree"
+   depends on OF
+   select GOOGLE_COREBOOT_TABLE
+   help
+ This option enable the coreboot_table module, which provide other
+ firmware modules to access coreboot table. The coreboot table pointer
+ is accessed through the device tree node /firmware/coreboot.
+ If unsure say N.
+
 config GOOGLE_MEMCONSOLE
tristate
depends on GOOGLE_MEMCONSOLE_X86_LEGACY || GOOGLE_MEMCONSOLE_COREBOOT
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index 662a83e..bb952c6 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -2,6 +2,7 @@
 obj-$(CONFIG_GOOGLE_SMI)   += gsmi.o
 obj-$(CONFIG_GOOGLE_COREBOOT_TABLE)+= coreboot_table.o
 obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_ACPI)   += coreboot_table-acpi.o
+obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_OF) += coreboot_table-of.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT)   += memconsole-coreboot.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
diff --git a/drivers/firmware/google/coreboot_table-of.c 
b/drivers/firmware/google/coreboot_table-of.c
new file mode 100644
index 000..727acdc
--- /dev/null
+++ b/drivers/firmware/google/coreboot_table-of.c
@@ -0,0 +1,82 @@
+/*
+ * coreboot_table-of.c
+ *
+ * Coreboot table access through open firmware.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "coreboot_table.h"
+
+static int coreboot_table_of_probe(struct platform_device *pdev)
+{
+   struct device_node *fw_dn = pdev->dev.of_node;
+   void __iomem *ptr;
+
+   ptr = of_iomap(fw_dn, 0);
+   of_node_put(fw_dn);
+   if (!ptr)
+   return -ENOMEM;
+
+   return coreboot_table_init(ptr);
+}
+
+static int coreboot_table_of_remove(struct platform_device *pdev)
+{
+   return coreboot_table_exit();
+}
+
+static const struct of_device_id coreboot

[PATCH v2 3/5] firmware: google memconsole: Add coreboot support

2017-03-28 Thread Thierry Escande
Coreboot (http://www.coreboot.org) allows to save the firmware console
output in a memory buffer. With this patch, the address of this memory
buffer is obtained from coreboot tables on x86 chromebook devices
declaring an ACPI device with name matching GOOGCB00 or BOOT.

If the memconsole-coreboot driver is able to find the coreboot table,
the memconsole driver sets the cbmem_console address and initializes the
memconsole sysfs entries.

The coreboot_table-acpi driver is responsible for setting the address of
the coreboot table header when probed. If this address is not yet set
when memconsole-coreboot is probed, then the probe is deferred by
returning -EPROBE_DEFER.

This patch is a rework/split/merge of patches from the chromeos v4.4
kernel tree originally authored by:
 Vadim Bendebury <vben...@chromium.org>
 Wei-Ning Huang <wnhu...@google.com>
 Yuji Sasaki <sasa...@google.com>
 Duncan Laurie <dlau...@chromium.org>
 Julius Werner <jwer...@chromium.org>
 Brian Norris <briannor...@chromium.org>

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig   |  25 +-
 drivers/firmware/google/Makefile  |   3 +
 drivers/firmware/google/coreboot_table-acpi.c |  88 +
 drivers/firmware/google/coreboot_table.c  |  94 ++
 drivers/firmware/google/coreboot_table.h  |  50 
 drivers/firmware/google/memconsole-coreboot.c | 109 ++
 6 files changed, 368 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/google/coreboot_table-acpi.c
 create mode 100644 drivers/firmware/google/coreboot_table.c
 create mode 100644 drivers/firmware/google/coreboot_table.h
 create mode 100644 drivers/firmware/google/memconsole-coreboot.c

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 27a0658..840bd62 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -19,9 +19,23 @@ config GOOGLE_SMI
  clearing the EFI event log and reading and writing NVRAM
  variables.
 
+config GOOGLE_COREBOOT_TABLE
+   tristate
+   depends on GOOGLE_COREBOOT_TABLE_ACPI
+
+config GOOGLE_COREBOOT_TABLE_ACPI
+   tristate "Coreboot Table Access - ACPI"
+   depends on ACPI
+   select GOOGLE_COREBOOT_TABLE
+   help
+ This option enables the coreboot_table module, which provides other
+ firmware modules to access to the coreboot table. The coreboot table
+ pointer is accessed through the ACPI "GOOGCB00" object.
+ If unsure say N.
+
 config GOOGLE_MEMCONSOLE
tristate
-   depends on GOOGLE_MEMCONSOLE_X86_LEGACY
+   depends on GOOGLE_MEMCONSOLE_X86_LEGACY || GOOGLE_MEMCONSOLE_COREBOOT
 
 config GOOGLE_MEMCONSOLE_X86_LEGACY
tristate "Firmware Memory Console - X86 Legacy support"
@@ -32,4 +46,13 @@ config GOOGLE_MEMCONSOLE_X86_LEGACY
  the EBDA on Google servers.  If found, this log is exported to
  userland in the file /sys/firmware/log.
 
+config GOOGLE_MEMCONSOLE_COREBOOT
+   tristate "Firmware Memory Console"
+   depends on GOOGLE_COREBOOT_TABLE
+   select GOOGLE_MEMCONSOLE
+   help
+ This option enables the kernel to search for a firmware log in
+ the coreboot table.  If found, this log is exported to userland
+ in the file /sys/firmware/log.
+
 endif # GOOGLE_FIRMWARE
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index 10683ef..662a83e 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -1,4 +1,7 @@
 
 obj-$(CONFIG_GOOGLE_SMI)   += gsmi.o
+obj-$(CONFIG_GOOGLE_COREBOOT_TABLE)+= coreboot_table.o
+obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_ACPI)   += coreboot_table-acpi.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT)   += memconsole-coreboot.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
diff --git a/drivers/firmware/google/coreboot_table-acpi.c 
b/drivers/firmware/google/coreboot_table-acpi.c
new file mode 100644
index 000..fb98db2
--- /dev/null
+++ b/drivers/firmware/google/coreboot_table-acpi.c
@@ -0,0 +1,88 @@
+/*
+ * coreboot_table-acpi.c
+ *
+ * Using ACPI to locate Coreboot table and provide coreboot table access.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#incl

[PATCH v2 1/5] firmware: google memconsole: Remove useless submenu in Kconfig

2017-03-28 Thread Thierry Escande
This patch removes the "Google Firmware Drivers" menu containing a
menuconfig entry with the exact same name. The menuconfig is now
directly under the "Firmware Drivers" entry.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 29c8cdd..475bd01 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -1,4 +1,4 @@
-config GOOGLE_FIRMWARE
+menuconfig GOOGLE_FIRMWARE
bool "Google Firmware Drivers"
depends on X86
default n
@@ -7,8 +7,7 @@ config GOOGLE_FIRMWARE
  only useful if you are working directly on one of their
  proprietary servers.  If in doubt, say "N".
 
-menu "Google Firmware Drivers"
-   depends on GOOGLE_FIRMWARE
+if GOOGLE_FIRMWARE
 
 config GOOGLE_SMI
tristate "SMI interface for Google platforms"
@@ -28,4 +27,4 @@ config GOOGLE_MEMCONSOLE
  the EBDA on Google servers.  If found, this log is exported to
  userland in the file /sys/firmware/log.
 
-endmenu
+endif # GOOGLE_FIRMWARE
-- 
2.7.4



[PATCH v2 2/5] firmware: google memconsole: Move specific EBDA parts

2017-03-28 Thread Thierry Escande
This patch splits memconsole.c in 2 parts. One containing the
architecture-independent part and the other one containing the EBDA
specific part. This prepares the integration of coreboot support for the
memconsole.

The memconsole driver is now named as memconsole-x86-legacy.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig |   9 +-
 drivers/firmware/google/Makefile|   3 +-
 drivers/firmware/google/memconsole-x86-legacy.c | 154 +++
 drivers/firmware/google/memconsole.c| 155 
 drivers/firmware/google/memconsole.h|  43 +++
 5 files changed, 229 insertions(+), 135 deletions(-)
 create mode 100644 drivers/firmware/google/memconsole-x86-legacy.c
 create mode 100644 drivers/firmware/google/memconsole.h

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 475bd01..27a0658 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -20,8 +20,13 @@ config GOOGLE_SMI
  variables.
 
 config GOOGLE_MEMCONSOLE
-   tristate "Firmware Memory Console"
-   depends on DMI
+   tristate
+   depends on GOOGLE_MEMCONSOLE_X86_LEGACY
+
+config GOOGLE_MEMCONSOLE_X86_LEGACY
+   tristate "Firmware Memory Console - X86 Legacy support"
+   depends on X86 && ACPI && DMI
+   select GOOGLE_MEMCONSOLE
help
  This option enables the kernel to search for a firmware log in
  the EBDA on Google servers.  If found, this log is exported to
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index 54a294e..10683ef 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_GOOGLE_SMI)   += gsmi.o
-obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
diff --git a/drivers/firmware/google/memconsole-x86-legacy.c 
b/drivers/firmware/google/memconsole-x86-legacy.c
new file mode 100644
index 000..529078c
--- /dev/null
+++ b/drivers/firmware/google/memconsole-x86-legacy.c
@@ -0,0 +1,154 @@
+/*
+ * memconsole-x86-legacy.c
+ *
+ * EBDA specific parts of the memory based BIOS console.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "memconsole.h"
+
+#define BIOS_MEMCONSOLE_V1_MAGIC   0xDEADBABE
+#define BIOS_MEMCONSOLE_V2_MAGIC   (('M')|('C'<<8)|('O'<<16)|('N'<<24))
+
+struct biosmemcon_ebda {
+   u32 signature;
+   union {
+   struct {
+   u8  enabled;
+   u32 buffer_addr;
+   u16 start;
+   u16 end;
+   u16 num_chars;
+   u8  wrapped;
+   } __packed v1;
+   struct {
+   u32 buffer_addr;
+   /* Misdocumented as number of pages! */
+   u16 num_bytes;
+   u16 start;
+   u16 end;
+   } __packed v2;
+   };
+} __packed;
+
+static void found_v1_header(struct biosmemcon_ebda *hdr)
+{
+   pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
+   hdr);
+   pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = 
%d, num = %d\n",
+   hdr->v1.buffer_addr, hdr->v1.start,
+   hdr->v1.end, hdr->v1.num_chars);
+
+   memconsole_setup(phys_to_virt(hdr->v1.buffer_addr), hdr->v1.num_chars);
+}
+
+static void found_v2_header(struct biosmemcon_ebda *hdr)
+{
+   pr_info("memconsole: BIOS console v2 EBDA structure found at %p\n",
+   hdr);
+   pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = 
%d, num_bytes = %d\n",
+   hdr->v2.buffer_addr, hdr->v2.start,
+   hdr->v2.end, hdr->v2.num_bytes);
+
+   memconsole_setup(phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start),
+hdr->v2.end - hdr->v2.start);
+}
+
+/*
+ * Search through the EBDA for the BIOS Memory Console, and
+ * set the global variables to point to it.  Return true if found.
+ */
+stati

[PATCH v2 4/5] firmware: Add coreboot device tree binding documentation

2017-03-28 Thread Thierry Escande
From: Julius Werner <jwer...@chromium.org>

This patch adds documentation describing a device tree binding for the
coreboot firmware. It is meant to be dynamically added during boot and
contains address definitions for the coreboot table (a list of
variable-sized descriptors providing information about various compile-
and run-time generated firmware parameters) and the CBMEM area (the
structure containing most run-time resident memory regions set up by
coreboot).

These definitions allow kernel drivers to easily access data contained
in and pointed to by these regions (such as coreboot's in-memory log).
(An example implementation can be seen in the following patch)

Signed-off-by: Julius Werner <jwer...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 .../devicetree/bindings/firmware/coreboot.txt  | 33 ++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/coreboot.txt

diff --git a/Documentation/devicetree/bindings/firmware/coreboot.txt 
b/Documentation/devicetree/bindings/firmware/coreboot.txt
new file mode 100644
index 000..4c95570
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/coreboot.txt
@@ -0,0 +1,33 @@
+COREBOOT firmware information
+
+The device tree node to communicate the location of coreboot's memory-resident
+bookkeeping structures to the kernel. Since coreboot itself cannot boot a
+device-tree-based kernel (yet), this node needs to be inserted by a
+second-stage bootloader (a coreboot "payload").
+
+Required properties:
+ - compatible: Should be "coreboot"
+ - reg: Address and length of the following two memory regions, in order:
+   1.) The coreboot table. This is a list of variable-sized descriptors
+   that contain various compile- and run-time generated firmware
+   parameters. It is identified by the magic string "LBIO" in its first
+   four bytes.
+   See coreboot's src/commonlib/include/commonlib/coreboot_tables.h for
+   details.
+   2.) The CBMEM area. This is a downward-growing memory region used by
+   coreboot to dynamically allocate data structures that remain resident.
+   It may or may not include the coreboot table as one of its members. It
+   is identified by a root node descriptor with the magic number
+   0xc0389481 that resides in the topmost 8 bytes of the area.
+   See coreboot's src/include/imd.h for details.
+
+Example:
+   firmware {
+   ranges;
+
+   coreboot {
+   compatible = "coreboot";
+   reg = <0xfdfea000 0x264>,
+ <0xfdfea000 0x16000>;
+   }
+   };
-- 
2.7.4



[PATCH v2 0/5] firmware: google memconsole

2017-03-28 Thread Thierry Escande
Hi,

This series extends the Google memory console driver to work on x86 and
ARM platforms running coreboot.

The Google memory console driver provides access to an in-memory log of
the firmware's output.

The legacy x86 memconsole driver is now named memconsole-x86-legacy and
a new driver named memconsole-coreboot is added.

On coreboot devices and depending on the device architecture, the driver
coreboot_table-acpi on x86 platforms or coreboot_table-of on ARM/ARM64
platforms is responsible to get the coreboot table header memory address
and then obtain the memory console address.

Thus, this series adds device tree binding for coreboot entries under
the '/firmware' node. The place where this should be/have been declared
has been discussed years ago when first submitted. Please see previous
discussions [1] and [2]. In the meantime a lot of chromebook devices
have been shipped with this binding in their firmware making it hard to
change/update.

[1] https://patchwork.ozlabs.org/patch/359672/
[2] https://patchwork.kernel.org/patch/4362661/

Regards,
 Thierry

This v2 adds a dependency on X86 for the GOOGLE_SMI symbol and few more
comments in this cover letter.

Julius Werner (1):
  firmware: Add coreboot device tree binding documentation

Thierry Escande (4):
  firmware: google memconsole: Remove useless submenu in Kconfig
  firmware: google memconsole: Move specific EBDA parts
  firmware: google memconsole: Add coreboot support
  firmware: google memconsole: Add ARM/ARM64 support

 .../devicetree/bindings/firmware/coreboot.txt  |  33 +
 drivers/firmware/google/Kconfig|  50 ++-
 drivers/firmware/google/Makefile   |   7 +-
 drivers/firmware/google/coreboot_table-acpi.c  |  88 
 drivers/firmware/google/coreboot_table-of.c|  82 +++
 drivers/firmware/google/coreboot_table.c   |  94 +
 drivers/firmware/google/coreboot_table.h   |  50 +++
 drivers/firmware/google/memconsole-coreboot.c  | 109 +++
 drivers/firmware/google/memconsole-x86-legacy.c| 154 
 drivers/firmware/google/memconsole.c   | 155 +++--
 drivers/firmware/google/memconsole.h   |  43 ++
 11 files changed, 725 insertions(+), 140 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/coreboot.txt
 create mode 100644 drivers/firmware/google/coreboot_table-acpi.c
 create mode 100644 drivers/firmware/google/coreboot_table-of.c
 create mode 100644 drivers/firmware/google/coreboot_table.c
 create mode 100644 drivers/firmware/google/coreboot_table.h
 create mode 100644 drivers/firmware/google/memconsole-coreboot.c
 create mode 100644 drivers/firmware/google/memconsole-x86-legacy.c
 create mode 100644 drivers/firmware/google/memconsole.h

-- 
2.7.4



[PATCH] sd: Ignore sync cache failures when not supported

2017-03-16 Thread Thierry Escande
From: Derek Basehore <dbaseh...@chromium.org>

Some external hard drives don't support the sync command even though the
hard drive has write cache enabled. In this case, upon suspend request,
sync cache failures are ignored if the error code in the sense header is
ILLEGAL_REQUEST. There's not much we can do for these drives, so we
shouldn't fail to suspend for this error case. The drive may stay
powered if that's the setup for the port it's plugged into.

Signed-off-by: Derek Basehore <dbaseh...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/scsi/sd.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b193304..c0388ff 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1492,7 +1492,7 @@ static unsigned int sd_check_events(struct gendisk *disk, 
unsigned int clearing)
return retval;
 }
 
-static int sd_sync_cache(struct scsi_disk *sdkp)
+static int sd_sync_cache(struct scsi_disk *sdkp, int *sense_key)
 {
int retries, res;
struct scsi_device *sdp = sdkp->device;
@@ -1521,8 +1521,11 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
if (res) {
sd_print_result(sdkp, "Synchronize Cache(10) failed", res);
 
-   if (driver_byte(res) & DRIVER_SENSE)
+   if (driver_byte(res) & DRIVER_SENSE) {
sd_print_sense_hdr(sdkp, );
+   if (sense_key)
+   *sense_key = sshdr.sense_key;
+   }
/* we need to evaluate the error return  */
if (scsi_sense_valid() &&
(sshdr.asc == 0x3a ||   /* medium not present */
@@ -3304,7 +3307,7 @@ static void sd_shutdown(struct device *dev)
 
if (sdkp->WCE && sdkp->media_present) {
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
-   sd_sync_cache(sdkp);
+   sd_sync_cache(sdkp, NULL);
}
 
if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
@@ -3316,6 +3319,7 @@ static void sd_shutdown(struct device *dev)
 static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
 {
struct scsi_disk *sdkp = dev_get_drvdata(dev);
+   int sense_key = NO_SENSE;
int ret = 0;
 
if (!sdkp)  /* E.g.: runtime suspend following sd_remove() */
@@ -3323,8 +3327,17 @@ static int sd_suspend_common(struct device *dev, bool 
ignore_stop_errors)
 
if (sdkp->WCE && sdkp->media_present) {
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
-   ret = sd_sync_cache(sdkp);
+   ret = sd_sync_cache(sdkp, _key);
if (ret) {
+   /*
+* If this drive doesn't support sync, there's not much
+* to do and suspend shouldn't fail.
+*/
+   if (sense_key == ILLEGAL_REQUEST) {
+   ret = 0;
+   goto start_stop;
+   }
+
/* ignore OFFLINE device */
if (ret == -ENODEV)
ret = 0;
@@ -3332,6 +3345,7 @@ static int sd_suspend_common(struct device *dev, bool 
ignore_stop_errors)
}
}
 
+start_stop:
if (sdkp->device->manage_start_stop) {
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
/* an error is not worth aborting a system sleep */
-- 
2.7.4



Re: [PATCH 1/2] firmware: Google VPD: import lib_vpd source files

2017-04-11 Thread Thierry Escande


On 11/04/2017 16:11, Greg Kroah-Hartman wrote:

On Tue, Apr 11, 2017 at 04:10:12PM +0200, Greg Kroah-Hartman wrote:

On Tue, Apr 11, 2017 at 11:14:30AM +0200, Thierry Escande wrote:

...

+   }
+
+   return VPD_OK;
+}
+EXPORT_SYMBOL(decode_vpd_string);


Normally put the prefix for the driver you are exporting from:
vpd_string_decode()?

And EXPORT_SYMBOL_GPL() perhaps?


Wait, why is this even exported?  You build this into the module that
needs it...



Right. Will fix that as well.

Regards,
 Thierry


Re: [PATCH 1/2] firmware: Google VPD: import lib_vpd source files

2017-04-11 Thread Thierry Escande

Hi Greg

On 11/04/2017 16:09, Greg Kroah-Hartman wrote:

On Tue, Apr 11, 2017 at 11:14:30AM +0200, Thierry Escande wrote:

+#include 
+
+#include "vpd_decode.h"
+
+static int decode_len(const int32_t max_len, const uint8_t *in,
+ int32_t *length, int32_t *decoded_len)
+{
+   uint8_t more;


Care to use "real" kernel variable types please?  u8, u16, and others
are you friend, uint8_t really isn't what we prefer, and checkpatch
should tell you that...


By default checkpatch doesn't warn about types unless --strict is 
specified... Sorry about that.


Regards,
 Thierry


[PATCH v2 1/2] firmware: Google VPD: import lib_vpd source files

2017-04-12 Thread Thierry Escande
From: Wei-Ning Huang <wnhu...@google.com>

This patch imports lib_vpd.h and vpd_decode.c from the Chromium Vital
Product Data project.

This library is used to parse VPD sections obtained from coreboot table
entries describing Chromebook devices product data. Only the sections of
type VPD_TYPE_STRING are decoded.

The VPD string sections in the coreboot tables contain the type (1 byte
set to 0x01 for strings), the key length, the key ascii array, the value
length, and the value ascii array. The key and value arrays are not null
terminated.

Signed-off-by: Wei-Ning Huang <wnhu...@google.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

In this v2:
 - Fix coding style issues reported by 'checkpatch --strict'
 - Add missing vpd_ prefix to some functions
 - Remove uneeded EXPORT_SYMBOL for vpd_decode_string()

---
 drivers/firmware/google/vpd_decode.c | 99 
 drivers/firmware/google/vpd_decode.h | 58 +
 2 files changed, 157 insertions(+)
 create mode 100644 drivers/firmware/google/vpd_decode.c
 create mode 100644 drivers/firmware/google/vpd_decode.h

diff --git a/drivers/firmware/google/vpd_decode.c 
b/drivers/firmware/google/vpd_decode.c
new file mode 100644
index 000..943acaa
--- /dev/null
+++ b/drivers/firmware/google/vpd_decode.c
@@ -0,0 +1,99 @@
+/*
+ * vpd_decode.c
+ *
+ * Google VPD decoding routines.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+
+#include "vpd_decode.h"
+
+static int vpd_decode_len(const s32 max_len, const u8 *in,
+ s32 *length, s32 *decoded_len)
+{
+   u8 more;
+   int i = 0;
+
+   if (!length || !decoded_len)
+   return VPD_FAIL;
+
+   *length = 0;
+   do {
+   if (i >= max_len)
+   return VPD_FAIL;
+
+   more = in[i] & 0x80;
+   *length <<= 7;
+   *length |= in[i] & 0x7f;
+   ++i;
+   } while (more);
+
+   *decoded_len = i;
+
+   return VPD_OK;
+}
+
+int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed,
+ vpd_decode_callback callback, void *callback_arg)
+{
+   int type;
+   int res;
+   s32 key_len;
+   s32 value_len;
+   s32 decoded_len;
+   const u8 *key;
+   const u8 *value;
+
+   /* type */
+   if (*consumed >= max_len)
+   return VPD_FAIL;
+
+   type = input_buf[*consumed];
+
+   switch (type) {
+   case VPD_TYPE_INFO:
+   case VPD_TYPE_STRING:
+   (*consumed)++;
+
+   /* key */
+   res = vpd_decode_len(max_len - *consumed, _buf[*consumed],
+_len, _len);
+   if (res != VPD_OK || *consumed + decoded_len >= max_len)
+   return VPD_FAIL;
+
+   *consumed += decoded_len;
+   key = _buf[*consumed];
+   *consumed += key_len;
+
+   /* value */
+   res = vpd_decode_len(max_len - *consumed, _buf[*consumed],
+_len, _len);
+   if (res != VPD_OK || *consumed + decoded_len > max_len)
+   return VPD_FAIL;
+
+   *consumed += decoded_len;
+   value = _buf[*consumed];
+   *consumed += value_len;
+
+   if (type == VPD_TYPE_STRING)
+   return callback(key, key_len, value, value_len,
+   callback_arg);
+   break;
+
+   default:
+   return VPD_FAIL;
+   }
+
+   return VPD_OK;
+}
diff --git a/drivers/firmware/google/vpd_decode.h 
b/drivers/firmware/google/vpd_decode.h
new file mode 100644
index 000..be3d62c
--- /dev/null
+++ b/drivers/firmware/google/vpd_decode.h
@@ -0,0 +1,58 @@
+/*
+ * vpd_decode.h
+ *
+ * Google VPD decoding routines.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __VPD_DECODE_H
+#define __VPD_DECODE_H
+
+#include 
+
+en

[PATCH v2 0/2] Google VPD sysfs driver

2017-04-12 Thread Thierry Escande
Hi,

This patchset adds support for accessing Google Vital Product Data (VPD)
through the sysfs interface under /sys/firmware/vpd.

This patchset contains the VPD decoding routines read from coreboot
table entries and the driver responsible for creating the sysfs
interface.

This patchset depends on [1] for coreboot support in the Google memory
console.

This v2 fixes style issues reported by 'checkpatch --strict', adds the
vpd_ prefix to a few function names, and removes the EXPORT_SYMBOL for
vpd_decode_string().

Regards,
 Thierry

[1] https://lkml.org/lkml/2017/3/28/902

Wei-Ning Huang (2):
  firmware: Google Vital Product Data: import lib_vpd source files
  firmware: Google VPD sysfs driver

 drivers/firmware/google/Kconfig  |   7 +
 drivers/firmware/google/Makefile |   3 +
 drivers/firmware/google/vpd.c| 333 +++
 drivers/firmware/google/vpd_decode.c | 102 +++
 drivers/firmware/google/vpd_decode.h |  59 +++
 5 files changed, 504 insertions(+)
 create mode 100644 drivers/firmware/google/vpd.c
 create mode 100644 drivers/firmware/google/vpd_decode.c
 create mode 100644 drivers/firmware/google/vpd_decode.h

-- 
2.7.4



[PATCH v2 2/2] firmware: Google VPD sysfs driver

2017-04-12 Thread Thierry Escande
From: Wei-Ning Huang <wnhu...@google.com>

This patch introduces the Google Vital Product Data driver.

This driver reads Vital Product Data from coreboot tables and then
creates the corresponding sysfs entries under /sys/firmware/vpd to
provide easy access for userspace programs (does not require flashrom).

The sysfs is structured as follow:

 /sys/firmware/vpd
 |-- ro
 |   |-- key1
 |   `-- key2
 |-- ro_raw
 |-- rw
 |   `-- key1
 `-- rw_raw

Where ro_raw and rw_raw contain the raw VPD partition. The files under
ro and rw correspond to the key name in the VPD and the the file content
is the value for the key.

Signed-off-by: Wei-Ning Huang <wnhu...@google.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

In this v2:
 - Fix coding style issues reported by 'checkpatch --strict'
 - Add missing vpd_ prefix to some functions

---
 drivers/firmware/google/Kconfig  |   7 +
 drivers/firmware/google/Makefile |   3 +
 drivers/firmware/google/vpd.c| 332 +++
 3 files changed, 342 insertions(+)
 create mode 100644 drivers/firmware/google/vpd.c

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 0e0..f16b381 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -64,4 +64,11 @@ config GOOGLE_MEMCONSOLE_COREBOOT
  the coreboot table.  If found, this log is exported to userland
  in the file /sys/firmware/log.
 
+config GOOGLE_VPD
+   tristate "Vital Product Data"
+   depends on GOOGLE_COREBOOT_TABLE
+   help
+ This option enables the kernel to expose the content of Google VPD
+ under /sys/firmware/vpd.
+
 endif # GOOGLE_FIRMWARE
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index bb952c6..bc4de02 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -6,3 +6,6 @@ obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_OF) += 
coreboot_table-of.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT)   += memconsole-coreboot.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
+
+vpd-sysfs-y := vpd.o vpd_decode.o
+obj-$(CONFIG_GOOGLE_VPD)   += vpd-sysfs.o
diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c
new file mode 100644
index 000..619f4ba
--- /dev/null
+++ b/drivers/firmware/google/vpd.c
@@ -0,0 +1,332 @@
+/*
+ * vpd.c
+ *
+ * Driver for exporting VPD content to sysfs.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "coreboot_table.h"
+#include "vpd_decode.h"
+
+#define CB_TAG_VPD  0x2c
+#define VPD_CBMEM_MAGIC 0x43524f53
+
+static struct kobject *vpd_kobj;
+
+struct vpd_cbmem {
+   u32 magic;
+   u32 version;
+   u32 ro_size;
+   u32 rw_size;
+   u8  blob[0];
+};
+
+struct vpd_section {
+   bool enabled;
+   const char *name;
+   char *raw_name;/* the string name_raw */
+   struct kobject *kobj;  /* vpd/name directory */
+   char *baseaddr;
+   struct bin_attribute bin_attr; /* vpd/name_raw bin_attribute */
+   struct list_head attribs;  /* key/value in vpd_attrib_info list */
+};
+
+struct vpd_attrib_info {
+   char *key;
+   const char *value;
+   struct bin_attribute bin_attr;
+   struct list_head list;
+};
+
+static struct vpd_section ro_vpd;
+static struct vpd_section rw_vpd;
+
+static ssize_t vpd_attrib_read(struct file *filp, struct kobject *kobp,
+  struct bin_attribute *bin_attr, char *buf,
+  loff_t pos, size_t count)
+{
+   struct vpd_attrib_info *info = bin_attr->private;
+
+   return memory_read_from_buffer(buf, count, , info->value,
+  info->bin_attr.size);
+}
+
+/*
+ * vpd_section_check_key_name()
+ *
+ * The VPD specification supports only [a-zA-Z0-9_]+ characters in key names 
but
+ * old firmware versions may have entries like "S/N" which are problematic when
+ * exporting them as sysfs attributes. These keys present in old firmwares are
+ * ignored.
+ *
+ * Returns VPD_OK for a valid key name, VPD_FAIL otherwise.
+ *
+ * @key: The key name to check
+ * @key_len: key name length
+ */
+static int vpd_section_check_key_name(const u8 

[PATCH] HID: magicmouse: Set multi-touch keybits for Magic Mouse

2017-04-07 Thread Thierry Escande
From: Che-Liang Chiou <clch...@chromium.org>

The driver emits multi-touch events for Magic Trackpad as well as Magic
Mouse, but it does not set keybits that are related to multi-touch event
for Magic Mouse; so set these keybits.

The keybits that are not set cause trouble because user programs often
probe these keybits for self-configuration and thus they cannot operate
properly if the keybits are not set.

One of such troubles is that libevdev will not be able to emit correct
touch count, causing gestures library failed to do fling stop.

Signed-off-by: Che-Liang Chiou <clch...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/hid/hid-magicmouse.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 20b40ad..1d6c997 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -349,6 +349,7 @@ static int magicmouse_raw_event(struct hid_device *hdev,
 
if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
magicmouse_emit_buttons(msc, clicks & 3);
+   input_mt_report_pointer_emulation(input, true);
input_report_rel(input, REL_X, x);
input_report_rel(input, REL_Y, y);
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
@@ -388,16 +389,16 @@ static int magicmouse_setup_input(struct input_dev 
*input, struct hid_device *hd
__clear_bit(BTN_RIGHT, input->keybit);
__clear_bit(BTN_MIDDLE, input->keybit);
__set_bit(BTN_MOUSE, input->keybit);
-   __set_bit(BTN_TOOL_FINGER, input->keybit);
-   __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
-   __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
-   __set_bit(BTN_TOOL_QUADTAP, input->keybit);
-   __set_bit(BTN_TOOL_QUINTTAP, input->keybit);
-   __set_bit(BTN_TOUCH, input->keybit);
-   __set_bit(INPUT_PROP_POINTER, input->propbit);
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
}
 
+   __set_bit(BTN_TOOL_FINGER, input->keybit);
+   __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
+   __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
+   __set_bit(BTN_TOOL_QUADTAP, input->keybit);
+   __set_bit(BTN_TOOL_QUINTTAP, input->keybit);
+   __set_bit(BTN_TOUCH, input->keybit);
+   __set_bit(INPUT_PROP_POINTER, input->propbit);
 
__set_bit(EV_ABS, input->evbit);
 
-- 
2.7.4



[PATCH 1/2] firmware: Google VPD: import lib_vpd source files

2017-04-11 Thread Thierry Escande
From: Wei-Ning Huang <wnhu...@google.com>

This patch imports lib_vpd.h and vpd_decode.c from the Chromium Vital
Product Data project.

This library is used to parse VPD sections obtained from coreboot table
entries describing Chromebook devices product data. Only the sections of
type VPD_TYPE_STRING are decoded.

The VPD string sections in the coreboot tables contain the type (1 byte
set to 0x01 for strings), the key length, the key ascii array, the value
length, and the value ascii array. The key and value arrays are not null
terminated.

Signed-off-by: Wei-Ning Huang <wnhu...@google.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/vpd_decode.c | 99 
 drivers/firmware/google/vpd_decode.h | 59 +
 2 files changed, 158 insertions(+)
 create mode 100644 drivers/firmware/google/vpd_decode.c
 create mode 100644 drivers/firmware/google/vpd_decode.h

diff --git a/drivers/firmware/google/vpd_decode.c 
b/drivers/firmware/google/vpd_decode.c
new file mode 100644
index 000..75e4027
--- /dev/null
+++ b/drivers/firmware/google/vpd_decode.c
@@ -0,0 +1,99 @@
+/*
+ * vpd_decode.c
+ *
+ * Google VPD decoding routines.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+
+#include "vpd_decode.h"
+
+static int decode_len(const int32_t max_len, const uint8_t *in,
+ int32_t *length, int32_t *decoded_len)
+{
+   uint8_t more;
+   int i = 0;
+
+   if (!length || !decoded_len)
+   return VPD_FAIL;
+
+   *length = 0;
+   do {
+   if (i >= max_len)
+   return VPD_FAIL;
+
+   more = in[i] & 0x80;
+   *length <<= 7;
+   *length |= in[i] & 0x7f;
+   ++i;
+   } while (more);
+
+   *decoded_len = i;
+
+   return VPD_OK;
+}
+
+int decode_vpd_string(const int32_t max_len, const uint8_t *input_buf,
+ int32_t *consumed, vpd_decode_callback callback,
+ void *callback_arg)
+{
+   int type;
+   int res;
+   int32_t key_len, value_len;
+   int32_t decoded_len;
+   const uint8_t *key, *value;
+
+   /* type */
+   if (*consumed >= max_len)
+   return VPD_FAIL;
+
+   type = input_buf[*consumed];
+
+   switch (type) {
+   case VPD_TYPE_INFO:
+   case VPD_TYPE_STRING:
+   (*consumed)++;
+
+   /* key */
+   res = decode_len(max_len - *consumed, _buf[*consumed],
+_len, _len);
+   if (res != VPD_OK || *consumed + decoded_len >= max_len)
+   return VPD_FAIL;
+
+   *consumed += decoded_len;
+   key = _buf[*consumed];
+   *consumed += key_len;
+
+   /* value */
+   res = decode_len(max_len - *consumed, _buf[*consumed],
+_len, _len);
+   if (res != VPD_OK || *consumed + decoded_len > max_len)
+   return VPD_FAIL;
+
+   *consumed += decoded_len;
+   value = _buf[*consumed];
+   *consumed += value_len;
+
+   if (type == VPD_TYPE_STRING)
+   return callback(key, key_len, value, value_len,
+   callback_arg);
+   break;
+
+   default:
+   return VPD_FAIL;
+   }
+
+   return VPD_OK;
+}
+EXPORT_SYMBOL(decode_vpd_string);
diff --git a/drivers/firmware/google/vpd_decode.h 
b/drivers/firmware/google/vpd_decode.h
new file mode 100644
index 000..c6c9b75
--- /dev/null
+++ b/drivers/firmware/google/vpd_decode.h
@@ -0,0 +1,59 @@
+/*
+ * vpd_decode.h
+ *
+ * Google VPD decoding routines.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __VPD_DECODE_H
+#define __VPD_DECODE_H
+
+#include 
+
+enum {
+   VPD_OK = 0,
+   VPD_FAIL,
+};
+
+enum {
+   VPD_TYPE_TERMINATOR = 0,
+   VPD_TYPE_STRING,
+   VPD_TYPE_INFO 

[PATCH 0/2] Google VPD sysfs driver

2017-04-11 Thread Thierry Escande
Hi,

This patchset adds support for accessing Google Vital Product Data (VPD)
through the sysfs interface under /sys/firmware/vpd.

This patchset contains the VPD decoding routines read from coreboot
table entries and the driver responsible for creating the sysfs
interface.

This patchset depends on [1] for coreboot support in the Google memory
console.

Regards,
 Thierry
 
[1] https://lkml.org/lkml/2017/3/28/902

Wei-Ning Huang (2):
  firmware: Google Vital Product Data: import lib_vpd source files
  firmware: Google VPD sysfs driver

 drivers/firmware/google/Kconfig  |   7 +
 drivers/firmware/google/Makefile |   3 +
 drivers/firmware/google/vpd.c| 333 +++
 drivers/firmware/google/vpd_decode.c | 102 +++
 drivers/firmware/google/vpd_decode.h |  59 +++
 5 files changed, 504 insertions(+)
 create mode 100644 drivers/firmware/google/vpd.c
 create mode 100644 drivers/firmware/google/vpd_decode.c
 create mode 100644 drivers/firmware/google/vpd_decode.h

-- 
2.7.4



[PATCH 2/2] firmware: Google VPD sysfs driver

2017-04-11 Thread Thierry Escande
From: Wei-Ning Huang <wnhu...@google.com>

This patch introduces the Google Vital Product Data driver.

This driver reads Vital Product Data from coreboot tables and then
creates the corresponding sysfs entries under /sys/firmware/vpd to
provide easy access for userspace programs (does not require flashrom).

The sysfs is structured as follow:

 /sys/firmware/vpd
 |-- ro
 |   |-- key1
 |   `-- key2
 |-- ro_raw
 |-- rw
 |   `-- key1
 `-- rw_raw

Where ro_raw and rw_raw contain the raw VPD partition. The files under
ro and rw correspond to the key name in the VPD and the the file content
is the value for the key.

Signed-off-by: Wei-Ning Huang <wnhu...@google.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/firmware/google/Kconfig  |   7 +
 drivers/firmware/google/Makefile |   3 +
 drivers/firmware/google/vpd.c| 333 +++
 3 files changed, 343 insertions(+)
 create mode 100644 drivers/firmware/google/vpd.c

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index 0e0..f16b381 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -64,4 +64,11 @@ config GOOGLE_MEMCONSOLE_COREBOOT
  the coreboot table.  If found, this log is exported to userland
  in the file /sys/firmware/log.
 
+config GOOGLE_VPD
+   tristate "Vital Product Data"
+   depends on GOOGLE_COREBOOT_TABLE
+   help
+ This option enables the kernel to expose the content of Google VPD
+ under /sys/firmware/vpd.
+
 endif # GOOGLE_FIRMWARE
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index bb952c6..bc4de02 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -6,3 +6,6 @@ obj-$(CONFIG_GOOGLE_COREBOOT_TABLE_OF) += 
coreboot_table-of.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE)+= memconsole.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT)   += memconsole-coreboot.o
 obj-$(CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY) += memconsole-x86-legacy.o
+
+vpd-sysfs-y := vpd.o vpd_decode.o
+obj-$(CONFIG_GOOGLE_VPD)   += vpd-sysfs.o
diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c
new file mode 100644
index 000..e167f33
--- /dev/null
+++ b/drivers/firmware/google/vpd.c
@@ -0,0 +1,333 @@
+/*
+ * vpd.c
+ *
+ * Driver for exporting VPD content to sysfs.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "coreboot_table.h"
+#include "vpd_decode.h"
+
+#define CB_TAG_VPD  0x2c
+#define VPD_CBMEM_MAGIC 0x43524f53
+
+static struct kobject *vpd_kobj;
+
+struct vpd_cbmem {
+   uint32_t magic;
+   uint32_t version;
+   uint32_t ro_size;
+   uint32_t rw_size;
+   uint8_t blob[0];
+};
+
+struct vpd_section {
+   bool enabled;
+   const char *name;
+   char *raw_name;/* the string name_raw */
+   struct kobject *kobj;  /* vpd/name directory */
+   char *baseaddr;
+   struct bin_attribute bin_attr; /* vpd/name_raw bin_attribute */
+   struct list_head attribs;  /* key/value in vpd_attrib_info list */
+};
+
+struct vpd_attrib_info {
+   char *key;
+   const char *value;
+   struct bin_attribute bin_attr;
+   struct list_head list;
+};
+
+static struct vpd_section ro_vpd;
+static struct vpd_section rw_vpd;
+
+static ssize_t vpd_attrib_read(struct file *filp, struct kobject *kobp,
+  struct bin_attribute *bin_attr, char *buf,
+  loff_t pos, size_t count)
+{
+   struct vpd_attrib_info *info = bin_attr->private;
+
+   return memory_read_from_buffer(buf, count, , info->value,
+  info->bin_attr.size);
+}
+
+/*
+ * vpd_section_check_key_name()
+ *
+ * The VPD specification supports only [a-zA-Z0-9_]+ characters in key names 
but
+ * old firmware versions may have entries like "S/N" which are problematic when
+ * exporting them as sysfs attributes. These keys present in old firmwares are
+ * ignored.
+ *
+ * Returns VPD_OK for a valid key name, VPD_FAIL otherwise.
+ *
+ * @key: The key name to check
+ * @key_len: key name length
+ */
+static int vpd_section_check_key_name(const uint8_t *key, int32_t key_len)
+{
+   int c;
+
+   while (key_len-- > 0) {
+   c = *key++;
+
+

Re: [PATCH 7/8] platform/chrome: cros_ec: Add sysfs entry to set keyboard wake lid angle

2017-08-11 Thread Thierry Escande

Hi Benson,

On 11/08/2017 07:29, Benson Leung wrote:


+/* Keyboard wake angle control */
+
+static ssize_t show_kb_wake_angle(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct ec_response_motion_sense *resp;
+   struct ec_params_motion_sense *param;
+   struct cros_ec_command *msg;
+   int ret;
+   struct cros_ec_dev *ec = container_of(
+   dev, struct cros_ec_dev, class_dev);
+
+   msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   param = (struct ec_params_motion_sense *)msg->data;
+   msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+   msg->version = 2;
+   param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE;
+   param->kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE;
+   msg->outsize = sizeof(*param);
+   msg->insize = sizeof(*resp);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);


Original CHROMIUM commit uses cros_ec_cmd_xfer here.
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/refs/changes/15/456415/5/drivers/platform/chrome/cros_ec_sysfs.c#303



+   if (ret < 0)
+   return ret;


Original commit also has this check:
if (msg->result != EC_RES_SUCCESS)
return scnprintf(buf, PAGE_SIZE, "ERROR: EC returned %d\n",
 msg->result);

Now, in the CHROMIUM commits, Gwendal removes this in the next patch, which
is "[PATCH 8/8] platform/chrome: cros_ec: sysfs: Modify error handling" in your
series, but can we try to keep these as close to the originals as possible?


Ok, sure. With the original patches I was pretty sure to get something 
like "hey, you modify something you've just added on the previous patch!" :)


I'll repost the whole series even if you've applied 2 of them already.

Regards,
 Thierry




+   resp = (struct ec_response_motion_sense *)msg->data;
+   return scnprintf(buf, PAGE_SIZE, "%d\n",
+   resp->kb_wake_angle.ret);
+}
+
+static ssize_t store_kb_wake_angle(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct ec_params_motion_sense *param;
+   struct cros_ec_command *msg;
+   int ret;
+   struct cros_ec_dev *ec = container_of(
+   dev, struct cros_ec_dev, class_dev);
+   uint16_t angle;
+
+   ret = kstrtou16(buf, 0, );
+   if (ret)
+   return ret;
+
+   msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   param = (struct ec_params_motion_sense *)msg->data;
+   msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+   msg->version = 2;
+   param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE;
+   param->kb_wake_angle.data = angle;
+   msg->outsize = sizeof(*param);
+   msg->insize = sizeof(struct ec_response_motion_sense);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
+   if (ret < 0)
+   return ret;
+   return count;
+}
+
  /* Module initialization */
  
  static DEVICE_ATTR(reboot, S_IWUSR | S_IRUGO, show_ec_reboot, store_ec_reboot);

  static DEVICE_ATTR(version, S_IRUGO, show_ec_version, NULL);
  static DEVICE_ATTR(flashinfo, S_IRUGO, show_ec_flashinfo, NULL);
+static DEVICE_ATTR(kb_wake_angle, S_IWUSR | S_IRUGO, show_kb_wake_angle,
+  store_kb_wake_angle);
  
  static struct attribute *__ec_attrs[] = {

+   _attr_kb_wake_angle.attr,
_attr_reboot.attr,
_attr_version.attr,
_attr_flashinfo.attr,
NULL,
  };
  
+static umode_t cros_ec_ctrl_visible(struct kobject *kobj,

+   struct attribute *a, int n)
+{
+   struct device *dev = container_of(kobj, struct device, kobj);
+   struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+ class_dev);
+
+   if (a == _attr_kb_wake_angle.attr && !ec->has_kb_wake_angle)
+   return 0;
+
+   return a->mode;
+}
+
  struct attribute_group cros_ec_attr_group = {
.attrs = __ec_attrs,
+   .is_visible = cros_ec_ctrl_visible,
  };
  
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h

index 4e887ba..350b8a4 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -191,6 +191,7 @@ struct cros_ec_dev {
struct cros_ec_device *ec_dev;
struct device *dev;
struct cros_ec_debugfs *debug_info;
+   bool has_kb_wake_angle;
u16 cmd_offset;
u32 features[2];
  };
--
2.7.4





[PATCH 2/8] mfd: cros_ec_i2c: move the system sleep pm ops to late

2017-08-10 Thread Thierry Escande
From: Joseph Lo <jose...@nvidia.com>

The cros_ec_i2c driver is still active after it had suspended or before it
resumes. Besides that, it also tried to transfer data even after the I2C
host had been suspended. This leads the system to crash.

During the test, we also observed that the EC needs to be resumed
earlier due to some status polling from the EC firmware (e.g. battery
status). This patch moves the PM ops to late stage to make it work
normally.

Signed-off-by: Joseph Lo <jose...@nvidia.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec_i2c.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 9f70de1..576fcc4 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -341,8 +341,9 @@ static int cros_ec_i2c_resume(struct device *dev)
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
- cros_ec_i2c_resume);
+const struct dev_pm_ops cros_ec_i2c_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
+};
 
 static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
-- 
2.7.4



[PATCH 1/8] iio: cros_ec: Relax sampling frequency before suspending

2017-08-10 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

If an application set a tight sampling frequency, given the interrupt
use is a wakup source, suspend will not happen: the kernel will receive
a wake up interrupt and will cancel the suspend process.

Given cros_ec sensors type is non wake up, this patch adds prepare and
complete callbacks to set 1s sampling period just before suspend. This
ensures the sensor hub will not be a source of interrupt during the
suspend process.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |  1 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 49 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |  2 +
 drivers/iio/light/cros_ec_light_prox.c |  1 +
 4 files changed, 53 insertions(+)

diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
index 38e8783..116da2c 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -292,6 +292,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
 static struct platform_driver cros_ec_sensors_platform_driver = {
.driver = {
.name   = "cros-ec-sensors",
+   .pm = _ec_sensors_pm_ops,
},
.probe  = cros_ec_sensors_probe,
.id_table   = cros_ec_sensors_ids,
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
index 416cae5..a620eb5 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -446,5 +446,54 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
 
+static int __maybe_unused cros_ec_sensors_prepare(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   if (st->curr_sampl_freq == 0)
+   return 0;
+
+   /*
+* If the sensors are sampled at high frequency, we will not be able to
+* sleep. Set sampling to a long period if necessary.
+*/
+   if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
+   mutex_lock(>cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY;
+   cros_ec_motion_send_host_cmd(st, 0);
+   mutex_unlock(>cmd_lock);
+   }
+   return 0;
+}
+
+static void __maybe_unused cros_ec_sensors_complete(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   if (st->curr_sampl_freq == 0)
+   return;
+
+   if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
+   mutex_lock(>cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = st->curr_sampl_freq;
+   cros_ec_motion_send_host_cmd(st, 0);
+   mutex_unlock(>cmd_lock);
+   }
+}
+
+const struct dev_pm_ops cros_ec_sensors_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+   .prepare = cros_ec_sensors_prepare,
+   .complete = cros_ec_sensors_complete
+#endif
+};
+EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops);
+
 MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h 
b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
index 8bc2ca3..2edf68d 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
@@ -169,6 +169,8 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
   struct iio_chan_spec const *chan,
   int val, int val2, long mask);
 
+extern const struct dev_pm_ops cros_ec_sensors_pm_ops;
+
 /* List of extended channel specification for all sensors */
 extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
 
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 7217223..f8658d4 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -279,6 +279,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
 static struct platform_driver cros_ec_light_prox_platform_drive

[PATCH 8/8] platform/chrome: cros_ec: sysfs: Modify error handling

2017-08-10 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

When accessing a sysfs attribute, if the EC command fails, -EPROTO is
now returned instead of an error message as it is unlikely an app is
parsing the error message to do something meaningful.
Also, this patch makes use of cros_ec_cmd_xfer_status() instead of
cros_ec_cmd_xfer() so an error message is printed in the syslog.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_sysfs.c | 25 -
 1 file changed, 4 insertions(+), 21 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index 60ff122..ba69fe9 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -116,15 +116,9 @@ static ssize_t store_ec_reboot(struct device *dev,
msg->command = EC_CMD_REBOOT_EC + ec->cmd_offset;
msg->outsize = sizeof(*param);
msg->insize = 0;
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
-   if (ret < 0) {
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
+   if (ret < 0)
count = ret;
-   goto exit;
-   }
-   if (msg->result != EC_RES_SUCCESS) {
-   dev_dbg(ec->dev, "EC result %d\n", msg->result);
-   count = -EINVAL;
-   }
 exit:
kfree(msg);
return count;
@@ -152,17 +146,11 @@ static ssize_t show_ec_version(struct device *dev,
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
msg->insize = sizeof(*r_ver);
msg->outsize = 0;
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0) {
count = ret;
goto exit;
}
-   if (msg->result != EC_RES_SUCCESS) {
-   count = scnprintf(buf, PAGE_SIZE,
- "ERROR: EC returned %d\n", msg->result);
-   goto exit;
-   }
-
r_ver = (struct ec_response_get_version *)msg->data;
/* Strings should be null-terminated, but let's be sure. */
r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0';
@@ -257,14 +245,9 @@ static ssize_t show_ec_flashinfo(struct device *dev,
msg->command = EC_CMD_FLASH_INFO + ec->cmd_offset;
msg->insize = sizeof(*resp);
msg->outsize = 0;
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0)
goto exit;
-   if (msg->result != EC_RES_SUCCESS) {
-   ret = scnprintf(buf, PAGE_SIZE,
-   "ERROR: EC returned %d\n", msg->result);
-   goto exit;
-   }
 
resp = (struct ec_response_flash_info *)msg->data;
 
-- 
2.7.4



[PATCH 6/8] mfd: cros_ec_i2c: add ACPI module device table

2017-08-10 Thread Thierry Escande
From: Wei-Ning Huang <wnhu...@google.com>

Add ACPI module device table for matching cros-ec devices to load the
cros_ec_i2c driver automatically.

Signed-off-by: Wei-Ning Huang <wnhu...@google.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec_i2c.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 576fcc4..56fc667 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -345,11 +346,13 @@ const struct dev_pm_ops cros_ec_i2c_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
 };
 
+#ifdef CONFIG_OF
 static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
+#endif
 
 static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 },
@@ -357,9 +360,18 @@ static const struct i2c_device_id cros_ec_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cros_ec_i2c_acpi_id[] = {
+   { "GOOG0008", 0 },
+   { },
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_acpi_id);
+#endif
+
 static struct i2c_driver cros_ec_driver = {
.driver = {
.name   = "cros-ec-i2c",
+   .acpi_match_table = ACPI_PTR(cros_ec_i2c_acpi_id),
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = _ec_i2c_pm_ops,
},
-- 
2.7.4



[PATCH 7/8] platform/chrome: cros_ec: Add sysfs entry to set keyboard wake lid angle

2017-08-10 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This adds a sysfs attribute (/sys/class/chromeos/cros_ec/kb_wake_angle)
used to set and get the keyboard wake lid angle. This attribute is
present only if 2 accelerometers are controlled by the EC.

This patch also moves the cros_ec features check before the device is
added so the features map obtained from the EC is ready on time.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_dev.c   | 32 ++---
 drivers/platform/chrome/cros_ec_sysfs.c | 80 +
 include/linux/mfd/cros_ec.h |  1 +
 3 files changed, 94 insertions(+), 19 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index 225d8e9..a7d711c 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -304,8 +304,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
 
resp = (struct ec_response_motion_sense *)msg->data;
sensor_num = resp->dump.sensor_count;
-   /* Allocate 2 extra sensors in case lid angle or FIFO are needed */
-   sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
+   /* Allocate one extra sensor for MOTION_SENSE_FIFO if needed */
+   sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 1),
   GFP_KERNEL);
if (sensor_cells == NULL)
goto error;
@@ -361,16 +361,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev 
*ec)
sensor_type[resp->info.type]++;
id++;
}
-   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
-   sensor_platforms[id].sensor_num = sensor_num;
-
-   sensor_cells[id].name = "cros-ec-angle";
-   sensor_cells[id].id = 0;
-   sensor_cells[id].platform_data = _platforms[id];
-   sensor_cells[id].pdata_size =
-   sizeof(struct cros_ec_sensor_platform);
-   id++;
-   }
+   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
+   ec->has_kb_wake_angle = true;
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
sensor_cells[id].name = "cros-ec-ring";
id++;
@@ -423,6 +415,15 @@ static int ec_device_probe(struct platform_device *pdev)
goto failed;
}
 
+   /* check whether this EC is a sensor hub. */
+   if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) {
+   pr_err("has EC_FEATURE_MOTION_SENSE\n");
+   cros_ec_sensors_register(ec);
+   }
+
+   /* Take control of the lightbar from the EC. */
+   lb_manual_suspend_ctrl(ec, 1);
+
retval = cdev_device_add(>cdev, >class_dev);
if (retval) {
dev_err(dev, "cdev_device_add failed => %d\n", retval);
@@ -432,13 +433,6 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_debugfs_init(ec))
dev_warn(dev, "failed to create debugfs directory\n");
 
-   /* check whether this EC is a sensor hub. */
-   if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
-   cros_ec_sensors_register(ec);
-
-   /* Take control of the lightbar from the EC. */
-   lb_manual_suspend_ctrl(ec, 1);
-
return 0;
 
 failed:
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index f3baf99..60ff122 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -278,20 +278,100 @@ static ssize_t show_ec_flashinfo(struct device *dev,
return ret;
 }
 
+/* Keyboard wake angle control */
+
+static ssize_t show_kb_wake_angle(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct ec_response_motion_sense *resp;
+   struct ec_params_motion_sense *param;
+   struct cros_ec_command *msg;
+   int ret;
+   struct cros_ec_dev *ec = container_of(
+   dev, struct cros_ec_dev, class_dev);
+
+   msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   param = (struct ec_params_motion_sense *)msg->data;
+   msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+   msg->version = 2;
+   param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE;
+   param->kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE;
+   msg->outsize = sizeof(*param);
+   msg->insize = sizeof(*resp);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
+   if (ret < 0)
+   return ret;
+   resp = (struct ec_response_motion_sense *)msg->data;
+   return scnprintf(buf, 

[PATCH 5/8] mfd: cros_ec: fail early if we cannot identify the EC

2017-08-10 Thread Thierry Escande
From: Vincent Palatin <vpala...@chromium.org>

If we cannot communicate with the EC chip to detect the protocol version
and its features, it's very likely useless to continue. Else we will
commit all kind of uninformed mistakes (using the wrong protocol, the
wrong buffer size, mixing the EC with other chips).

Signed-off-by: Vincent Palatin <vpala...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/mfd/cros_ec.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b0ca5a4c..c5528ae 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -112,7 +112,11 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
mutex_init(_dev->lock);
 
-   cros_ec_query_all(ec_dev);
+   err = cros_ec_query_all(ec_dev);
+   if (err) {
+   dev_err(dev, "Cannot identify the EC: error %d\n", err);
+   return err;
+   }
 
if (ec_dev->irq) {
err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
-- 
2.7.4



[PATCH 0/8] platform/chrome: cros_ec: Fixes and improvements

2017-08-10 Thread Thierry Escande
Hi,

This series contains various fixes and improvements for the ChromeOS
Embedded Controller drivers. These concern PM suspend/resume fixes,
sysfs interface, and module initialization.

Regards,
 Thierry

Daniel Hung-yu Wu (1):
  platform/chrome: cros_ec: register shutdown function for debugfs

Douglas Anderson (1):
  mfd: cros_ec: Stop the debugfs work when suspended

Gwendal Grignou (3):
  iio: cros_ec: Relax sampling frequency before suspending
  platform/chrome: cros_ec: Add sysfs entry to set keyboard wake lid
angle
  platform/chrome: cros_ec: sysfs: Modify error handling

Joseph Lo (1):
  mfd: cros_ec_i2c: move the system sleep pm ops to late

Vincent Palatin (1):
  mfd: cros_ec: fail early if we cannot identify the EC

Wei-Ning Huang (1):
  mfd: cros_ec_i2c: add ACPI module device table

 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |   1 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  52 +++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   2 +
 drivers/iio/light/cros_ec_light_prox.c |   1 +
 drivers/mfd/cros_ec.c  |   6 +-
 drivers/mfd/cros_ec_i2c.c  |  17 +++-
 drivers/platform/chrome/cros_ec_debugfs.c  |  18 
 drivers/platform/chrome/cros_ec_debugfs.h  |   2 +
 drivers/platform/chrome/cros_ec_dev.c  |  45 +
 drivers/platform/chrome/cros_ec_sysfs.c| 104 -
 include/linux/mfd/cros_ec.h|   1 +
 11 files changed, 206 insertions(+), 43 deletions(-)

-- 
2.7.4



[PATCH 4/8] platform/chrome: cros_ec: register shutdown function for debugfs

2017-08-10 Thread Thierry Escande
From: Daniel Hung-yu Wu <h...@google.com>

Reboot or shutdown during delayed works could corrupt communication with
EC and certain I2C controller may not be able to recover from the error
state.

This patch registers a shutdown callback used to cancel the debugfs log
worker thread.

Signed-off-by: Daniel Hung-yu Wu <h...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_dev.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index 2571f5e..225d8e9 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -460,6 +460,14 @@ static int ec_device_remove(struct platform_device *pdev)
return 0;
 }
 
+static void ec_device_shutdown(struct platform_device *pdev)
+{
+   struct cros_ec_dev *ec = dev_get_drvdata(>dev);
+
+   /* Be sure to clear up debugfs delayed works */
+   cros_ec_debugfs_remove(ec);
+}
+
 static const struct platform_device_id cros_ec_id[] = {
{ "cros-ec-ctl", 0 },
{ /* sentinel */ },
@@ -502,6 +510,7 @@ static struct platform_driver cros_ec_dev_driver = {
},
.probe = ec_device_probe,
.remove = ec_device_remove,
+   .shutdown = ec_device_shutdown,
 };
 
 static int __init cros_ec_dev_init(void)
-- 
2.7.4



[PATCH 3/8] mfd: cros_ec: Stop the debugfs work when suspended

2017-08-10 Thread Thierry Escande
From: Douglas Anderson <diand...@chromium.org>

This patch stops the debugfs worker thread when the device is suspended.
This change avoids messages like:

  cros-ec-spi spi5.0: spi transfer failed: -108
  cros-ec-spi spi5.0: cs-deassert spi transfer failed: -108
  cros-ec-ctl cros-ec-ctl.0.auto: EC communication failed

Signed-off-by: Douglas Anderson <diand...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_debugfs.c | 18 ++
 drivers/platform/chrome/cros_ec_debugfs.h |  2 ++
 drivers/platform/chrome/cros_ec_dev.c |  4 
 3 files changed, 24 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_debugfs.c 
b/drivers/platform/chrome/cros_ec_debugfs.c
index 4cc66f4..515f411 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -399,3 +399,21 @@ void cros_ec_debugfs_remove(struct cros_ec_dev *ec)
debugfs_remove_recursive(ec->debug_info->dir);
cros_ec_cleanup_console_log(ec->debug_info);
 }
+
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec)
+{
+   /*
+* cros_ec_debugfs_init() failures are non-fatal; it's also possible
+* that we initted things but decided that console log wasn't supported.
+* We'll use the same set of checks that cros_ec_debugfs_remove() +
+* cros_ec_cleanup_console_log() end up using to handle those cases.
+*/
+   if (ec->debug_info && ec->debug_info->log_buffer.buf)
+   cancel_delayed_work_sync(>debug_info->log_poll_work);
+}
+
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec)
+{
+   if (ec->debug_info && ec->debug_info->log_buffer.buf)
+   schedule_delayed_work(>debug_info->log_poll_work, 0);
+}
diff --git a/drivers/platform/chrome/cros_ec_debugfs.h 
b/drivers/platform/chrome/cros_ec_debugfs.h
index 1ff3a50..d29e410 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.h
+++ b/drivers/platform/chrome/cros_ec_debugfs.h
@@ -23,5 +23,7 @@
 /* debugfs stuff */
 int cros_ec_debugfs_init(struct cros_ec_dev *ec);
 void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec);
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec);
 
 #endif  /* _DRV_CROS_EC_DEBUGFS_H_ */
diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index cf6c4f0..2571f5e 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -470,6 +470,8 @@ static __maybe_unused int ec_device_suspend(struct device 
*dev)
 {
struct cros_ec_dev *ec = dev_get_drvdata(dev);
 
+   cros_ec_debugfs_suspend(ec);
+
lb_suspend(ec);
 
return 0;
@@ -481,6 +483,8 @@ static __maybe_unused int ec_device_resume(struct device 
*dev)
 
lb_resume(ec);
 
+   cros_ec_debugfs_resume(ec);
+
return 0;
 }
 
-- 
2.7.4



[PATCH v2 3/8] mfd: cros_ec: Stop the debugfs work when suspended

2017-08-11 Thread Thierry Escande
From: Douglas Anderson <diand...@chromium.org>

This patch stops the debugfs worker thread when the device is suspended.
This change avoids messages like:

  cros-ec-spi spi5.0: spi transfer failed: -108
  cros-ec-spi spi5.0: cs-deassert spi transfer failed: -108
  cros-ec-ctl cros-ec-ctl.0.auto: EC communication failed

Signed-off-by: Douglas Anderson <diand...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_debugfs.c | 18 ++
 drivers/platform/chrome/cros_ec_debugfs.h |  2 ++
 drivers/platform/chrome/cros_ec_dev.c |  4 
 3 files changed, 24 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_debugfs.c 
b/drivers/platform/chrome/cros_ec_debugfs.c
index 4cc66f4..515f411 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -399,3 +399,21 @@ void cros_ec_debugfs_remove(struct cros_ec_dev *ec)
debugfs_remove_recursive(ec->debug_info->dir);
cros_ec_cleanup_console_log(ec->debug_info);
 }
+
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec)
+{
+   /*
+* cros_ec_debugfs_init() failures are non-fatal; it's also possible
+* that we initted things but decided that console log wasn't supported.
+* We'll use the same set of checks that cros_ec_debugfs_remove() +
+* cros_ec_cleanup_console_log() end up using to handle those cases.
+*/
+   if (ec->debug_info && ec->debug_info->log_buffer.buf)
+   cancel_delayed_work_sync(>debug_info->log_poll_work);
+}
+
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec)
+{
+   if (ec->debug_info && ec->debug_info->log_buffer.buf)
+   schedule_delayed_work(>debug_info->log_poll_work, 0);
+}
diff --git a/drivers/platform/chrome/cros_ec_debugfs.h 
b/drivers/platform/chrome/cros_ec_debugfs.h
index 1ff3a50..d29e410 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.h
+++ b/drivers/platform/chrome/cros_ec_debugfs.h
@@ -23,5 +23,7 @@
 /* debugfs stuff */
 int cros_ec_debugfs_init(struct cros_ec_dev *ec);
 void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec);
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec);
 
 #endif  /* _DRV_CROS_EC_DEBUGFS_H_ */
diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index cf6c4f0..2571f5e 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -470,6 +470,8 @@ static __maybe_unused int ec_device_suspend(struct device 
*dev)
 {
struct cros_ec_dev *ec = dev_get_drvdata(dev);
 
+   cros_ec_debugfs_suspend(ec);
+
lb_suspend(ec);
 
return 0;
@@ -481,6 +483,8 @@ static __maybe_unused int ec_device_resume(struct device 
*dev)
 
lb_resume(ec);
 
+   cros_ec_debugfs_resume(ec);
+
return 0;
 }
 
-- 
2.7.4



[PATCH v2 5/8] mfd: cros_ec: fail early if we cannot identify the EC

2017-08-11 Thread Thierry Escande
From: Vincent Palatin <vpala...@chromium.org>

If we cannot communicate with the EC chip to detect the protocol version
and its features, it's very likely useless to continue. Else we will
commit all kind of uninformed mistakes (using the wrong protocol, the
wrong buffer size, mixing the EC with other chips).

Signed-off-by: Vincent Palatin <vpala...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
Acked-by: Benson Leung <ble...@chromium.org>
---
 drivers/mfd/cros_ec.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b0ca5a4c..c5528ae 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -112,7 +112,11 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
mutex_init(_dev->lock);
 
-   cros_ec_query_all(ec_dev);
+   err = cros_ec_query_all(ec_dev);
+   if (err) {
+   dev_err(dev, "Cannot identify the EC: error %d\n", err);
+   return err;
+   }
 
if (ec_dev->irq) {
err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
-- 
2.7.4



[PATCH v2 0/8] platform/chrome: cros_ec: Fixes and improvements

2017-08-11 Thread Thierry Escande
Hi,

This series contains various fixes and improvements for the ChromeOS
Embedded Controller drivers. These concern PM suspend/resume fixes,
sysfs interface, and module initialization.

Regards,
 Thierry

v2 changes:
- Restore original changes from ChromeOS kernel tree (a function is
  added in patch #7 and then modified in patch #8). This keeps the
  changes as closed to the originals as possible.
- Replace a uint16_t declaration with u16.

Daniel Hung-yu Wu (1):
  platform/chrome: cros_ec: register shutdown function for debugfs

Douglas Anderson (1):
  mfd: cros_ec: Stop the debugfs work when suspended

Gwendal Grignou (3):
  iio: cros_ec: Relax sampling frequency before suspending
  platform/chrome: cros_ec: Add sysfs entry to set keyboard wake lid
angle
  platform/chrome: cros_ec: sysfs: Modify error handling

Joseph Lo (1):
  mfd: cros_ec_i2c: move the system sleep pm ops to late

Vincent Palatin (1):
  mfd: cros_ec: fail early if we cannot identify the EC

Wei-Ning Huang (1):
  mfd: cros_ec_i2c: add ACPI module device table

 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |   1 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  49 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   2 +
 drivers/iio/light/cros_ec_light_prox.c |   1 +
 drivers/mfd/cros_ec.c  |   6 +-
 drivers/mfd/cros_ec_i2c.c  |  17 +++-
 drivers/platform/chrome/cros_ec_debugfs.c  |  18 
 drivers/platform/chrome/cros_ec_debugfs.h  |   2 +
 drivers/platform/chrome/cros_ec_dev.c  |  45 +
 drivers/platform/chrome/cros_ec_sysfs.c| 105 -
 include/linux/mfd/cros_ec.h|   1 +
 11 files changed, 204 insertions(+), 43 deletions(-)

-- 
2.7.4



[PATCH v2 8/8] platform/chrome: cros_ec: sysfs: Modify error handling

2017-08-11 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

When accessing a sysfs attribute, if the EC command fails, -EPROTO is
now returned instead of an error message as it is unlikely an app is
parsing the error message to do something meaningful.
Also, this patch makes use of cros_ec_cmd_xfer_status() instead of
cros_ec_cmd_xfer() so an error message is printed in the syslog.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_sysfs.c | 30 +-
 1 file changed, 5 insertions(+), 25 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index 77b4ba5..0fd88eb 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -116,15 +116,9 @@ static ssize_t store_ec_reboot(struct device *dev,
msg->command = EC_CMD_REBOOT_EC + ec->cmd_offset;
msg->outsize = sizeof(*param);
msg->insize = 0;
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
-   if (ret < 0) {
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
+   if (ret < 0)
count = ret;
-   goto exit;
-   }
-   if (msg->result != EC_RES_SUCCESS) {
-   dev_dbg(ec->dev, "EC result %d\n", msg->result);
-   count = -EINVAL;
-   }
 exit:
kfree(msg);
return count;
@@ -152,17 +146,11 @@ static ssize_t show_ec_version(struct device *dev,
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
msg->insize = sizeof(*r_ver);
msg->outsize = 0;
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0) {
count = ret;
goto exit;
}
-   if (msg->result != EC_RES_SUCCESS) {
-   count = scnprintf(buf, PAGE_SIZE,
- "ERROR: EC returned %d\n", msg->result);
-   goto exit;
-   }
-
r_ver = (struct ec_response_get_version *)msg->data;
/* Strings should be null-terminated, but let's be sure. */
r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0';
@@ -257,14 +245,9 @@ static ssize_t show_ec_flashinfo(struct device *dev,
msg->command = EC_CMD_FLASH_INFO + ec->cmd_offset;
msg->insize = sizeof(*resp);
msg->outsize = 0;
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0)
goto exit;
-   if (msg->result != EC_RES_SUCCESS) {
-   ret = scnprintf(buf, PAGE_SIZE,
-   "ERROR: EC returned %d\n", msg->result);
-   goto exit;
-   }
 
resp = (struct ec_response_flash_info *)msg->data;
 
@@ -301,12 +284,9 @@ static ssize_t show_kb_wake_angle(struct device *dev,
param->kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE;
msg->outsize = sizeof(*param);
msg->insize = sizeof(*resp);
-   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0)
return ret;
-   if (msg->result != EC_RES_SUCCESS)
-   return scnprintf(buf, PAGE_SIZE, "ERROR: EC returned %d\n",
-msg->result);
resp = (struct ec_response_motion_sense *)msg->data;
return scnprintf(buf, PAGE_SIZE, "%d\n",
 resp->kb_wake_angle.ret);
-- 
2.7.4



[PATCH v2 7/8] platform/chrome: cros_ec: Add sysfs entry to set keyboard wake lid angle

2017-08-11 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This adds a sysfs attribute (/sys/class/chromeos/cros_ec/kb_wake_angle)
used to set and get the keyboard wake lid angle. This attribute is
present only if 2 accelerometers are controlled by the EC.

This patch also moves the cros_ec features check before the device is
added so the features map obtained from the EC is ready on time.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_dev.c   | 32 ++---
 drivers/platform/chrome/cros_ec_sysfs.c | 83 +
 include/linux/mfd/cros_ec.h |  1 +
 3 files changed, 97 insertions(+), 19 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index 225d8e9..a7d711c 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -304,8 +304,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
 
resp = (struct ec_response_motion_sense *)msg->data;
sensor_num = resp->dump.sensor_count;
-   /* Allocate 2 extra sensors in case lid angle or FIFO are needed */
-   sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
+   /* Allocate one extra sensor for MOTION_SENSE_FIFO if needed */
+   sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 1),
   GFP_KERNEL);
if (sensor_cells == NULL)
goto error;
@@ -361,16 +361,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev 
*ec)
sensor_type[resp->info.type]++;
id++;
}
-   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
-   sensor_platforms[id].sensor_num = sensor_num;
-
-   sensor_cells[id].name = "cros-ec-angle";
-   sensor_cells[id].id = 0;
-   sensor_cells[id].platform_data = _platforms[id];
-   sensor_cells[id].pdata_size =
-   sizeof(struct cros_ec_sensor_platform);
-   id++;
-   }
+   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
+   ec->has_kb_wake_angle = true;
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
sensor_cells[id].name = "cros-ec-ring";
id++;
@@ -423,6 +415,15 @@ static int ec_device_probe(struct platform_device *pdev)
goto failed;
}
 
+   /* check whether this EC is a sensor hub. */
+   if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) {
+   pr_err("has EC_FEATURE_MOTION_SENSE\n");
+   cros_ec_sensors_register(ec);
+   }
+
+   /* Take control of the lightbar from the EC. */
+   lb_manual_suspend_ctrl(ec, 1);
+
retval = cdev_device_add(>cdev, >class_dev);
if (retval) {
dev_err(dev, "cdev_device_add failed => %d\n", retval);
@@ -432,13 +433,6 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_debugfs_init(ec))
dev_warn(dev, "failed to create debugfs directory\n");
 
-   /* check whether this EC is a sensor hub. */
-   if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
-   cros_ec_sensors_register(ec);
-
-   /* Take control of the lightbar from the EC. */
-   lb_manual_suspend_ctrl(ec, 1);
-
return 0;
 
 failed:
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index f3baf99..77b4ba5 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -278,20 +278,103 @@ static ssize_t show_ec_flashinfo(struct device *dev,
return ret;
 }
 
+/* Keyboard wake angle control */
+
+static ssize_t show_kb_wake_angle(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct ec_response_motion_sense *resp;
+   struct ec_params_motion_sense *param;
+   struct cros_ec_command *msg;
+   int ret;
+   struct cros_ec_dev *ec = container_of(
+   dev, struct cros_ec_dev, class_dev);
+
+   msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   param = (struct ec_params_motion_sense *)msg->data;
+   msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+   msg->version = 2;
+   param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE;
+   param->kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE;
+   msg->outsize = sizeof(*param);
+   msg->insize = sizeof(*resp);
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   if (ret < 0)
+   return ret;
+   if (msg->result != EC_RES_SUCCESS)
+   return scnprintf(buf, PAGE_SIZE, "

[PATCH v2 6/8] mfd: cros_ec_i2c: add ACPI module device table

2017-08-11 Thread Thierry Escande
From: Wei-Ning Huang <wnhu...@google.com>

Add ACPI module device table for matching cros-ec devices to load the
cros_ec_i2c driver automatically.

Signed-off-by: Wei-Ning Huang <wnhu...@google.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
Acked-by: Benson Leung <ble...@chromium.org>
---
 drivers/mfd/cros_ec_i2c.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 576fcc4..56fc667 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -345,11 +346,13 @@ const struct dev_pm_ops cros_ec_i2c_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
 };
 
+#ifdef CONFIG_OF
 static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
+#endif
 
 static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 },
@@ -357,9 +360,18 @@ static const struct i2c_device_id cros_ec_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cros_ec_i2c_acpi_id[] = {
+   { "GOOG0008", 0 },
+   { },
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_acpi_id);
+#endif
+
 static struct i2c_driver cros_ec_driver = {
.driver = {
.name   = "cros-ec-i2c",
+   .acpi_match_table = ACPI_PTR(cros_ec_i2c_acpi_id),
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = _ec_i2c_pm_ops,
},
-- 
2.7.4



[PATCH v2 1/8] iio: cros_ec: Relax sampling frequency before suspending

2017-08-11 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

If an application set a tight sampling frequency, given the interrupt
use is a wakup source, suspend will not happen: the kernel will receive
a wake up interrupt and will cancel the suspend process.

Given cros_ec sensors type is non wake up, this patch adds prepare and
complete callbacks to set 1s sampling period just before suspend. This
ensures the sensor hub will not be a source of interrupt during the
suspend process.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |  1 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 49 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |  2 +
 drivers/iio/light/cros_ec_light_prox.c |  1 +
 4 files changed, 53 insertions(+)

diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
index 38e8783..116da2c 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -292,6 +292,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
 static struct platform_driver cros_ec_sensors_platform_driver = {
.driver = {
.name   = "cros-ec-sensors",
+   .pm = _ec_sensors_pm_ops,
},
.probe  = cros_ec_sensors_probe,
.id_table   = cros_ec_sensors_ids,
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
index 416cae5..a620eb5 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -446,5 +446,54 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
 
+static int __maybe_unused cros_ec_sensors_prepare(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   if (st->curr_sampl_freq == 0)
+   return 0;
+
+   /*
+* If the sensors are sampled at high frequency, we will not be able to
+* sleep. Set sampling to a long period if necessary.
+*/
+   if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
+   mutex_lock(>cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY;
+   cros_ec_motion_send_host_cmd(st, 0);
+   mutex_unlock(>cmd_lock);
+   }
+   return 0;
+}
+
+static void __maybe_unused cros_ec_sensors_complete(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   if (st->curr_sampl_freq == 0)
+   return;
+
+   if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
+   mutex_lock(>cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = st->curr_sampl_freq;
+   cros_ec_motion_send_host_cmd(st, 0);
+   mutex_unlock(>cmd_lock);
+   }
+}
+
+const struct dev_pm_ops cros_ec_sensors_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+   .prepare = cros_ec_sensors_prepare,
+   .complete = cros_ec_sensors_complete
+#endif
+};
+EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops);
+
 MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h 
b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
index 8bc2ca3..2edf68d 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
@@ -169,6 +169,8 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
   struct iio_chan_spec const *chan,
   int val, int val2, long mask);
 
+extern const struct dev_pm_ops cros_ec_sensors_pm_ops;
+
 /* List of extended channel specification for all sensors */
 extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
 
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 7217223..f8658d4 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -279,6 +279,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
 static struct platform_driver cros_ec_light_prox_platform_drive

[PATCH v2 4/8] platform/chrome: cros_ec: register shutdown function for debugfs

2017-08-11 Thread Thierry Escande
From: Daniel Hung-yu Wu <h...@google.com>

Reboot or shutdown during delayed works could corrupt communication with
EC and certain I2C controller may not be able to recover from the error
state.

This patch registers a shutdown callback used to cancel the debugfs log
worker thread.

Signed-off-by: Daniel Hung-yu Wu <h...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/cros_ec_dev.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index 2571f5e..225d8e9 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -460,6 +460,14 @@ static int ec_device_remove(struct platform_device *pdev)
return 0;
 }
 
+static void ec_device_shutdown(struct platform_device *pdev)
+{
+   struct cros_ec_dev *ec = dev_get_drvdata(>dev);
+
+   /* Be sure to clear up debugfs delayed works */
+   cros_ec_debugfs_remove(ec);
+}
+
 static const struct platform_device_id cros_ec_id[] = {
{ "cros-ec-ctl", 0 },
{ /* sentinel */ },
@@ -502,6 +510,7 @@ static struct platform_driver cros_ec_dev_driver = {
},
.probe = ec_device_probe,
.remove = ec_device_remove,
+   .shutdown = ec_device_shutdown,
 };
 
 static int __init cros_ec_dev_init(void)
-- 
2.7.4



[PATCH v2 2/8] mfd: cros_ec_i2c: move the system sleep pm ops to late

2017-08-11 Thread Thierry Escande
From: Joseph Lo <jose...@nvidia.com>

The cros_ec_i2c driver is still active after it had suspended or before it
resumes. Besides that, it also tried to transfer data even after the I2C
host had been suspended. This leads the system to crash.

During the test, we also observed that the EC needs to be resumed
earlier due to some status polling from the EC firmware (e.g. battery
status). This patch moves the PM ops to late stage to make it work
normally.

Signed-off-by: Joseph Lo <jose...@nvidia.com>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
Acked-by: Benson Leung <ble...@chromium.org>
---
 drivers/mfd/cros_ec_i2c.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 9f70de1..576fcc4 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -341,8 +341,9 @@ static int cros_ec_i2c_resume(struct device *dev)
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
- cros_ec_i2c_resume);
+const struct dev_pm_ops cros_ec_i2c_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
+};
 
 static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
-- 
2.7.4



  1   2   3   4   5   6   7   8   >