[PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip event v2

2016-03-31 Thread Tomeu Vizoso
As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
updated is requested and there is an earlier updated pending".

v2: Use the status of the workqueue instead of vop->event, and don't add
a superfluous wait on the workqueue.

Signed-off-by: Tomeu Vizoso 
---
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 3b8f652698f8..285f8cd5afe1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -282,6 +282,9 @@ int rockchip_drm_atomic_commit(struct drm_device *dev,
struct rockchip_atomic_commit *commit = >commit;
int ret;
 
+   if (async && work_busy(>work))
+   return -EBUSY;
+
ret = drm_atomic_helper_prepare_planes(dev, state);
if (ret)
return ret;
-- 
2.5.5



Re: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip event

2016-03-31 Thread Tomeu Vizoso
On 31 March 2016 at 03:25, Mark yao <mark@rock-chips.com> wrote:
> On 2016年03月30日 21:48, Tomeu Vizoso wrote:
>>
>> As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
>> updated is requested and there is an earlier updated pending".
>>
>> Also wait for the pending event to complete when a sync update is
>> requested.
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
>> ---
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 14 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  6 ++
>>   3 files changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> index 3529f692edb8..37952eefd33d 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> @@ -69,6 +69,7 @@ int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
>>   void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
>>   int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int
>> connector_type,
>>   int out_mode);
>> +bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc);
>>   int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
>>struct device *dev);
>>   void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> index 3b8f652698f8..028fd2f8f47b 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> @@ -280,7 +280,19 @@ int rockchip_drm_atomic_commit(struct drm_device
>> *dev,
>>   {
>> struct rockchip_drm_private *private = dev->dev_private;
>> struct rockchip_atomic_commit *commit = >commit;
>> -   int ret;
>> +   struct drm_crtc_state *crtc_state;
>> +   struct drm_crtc *crtc;
>> +   int i, ret;
>> +
>> +   for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> +   if (crtc->state->event ||
>> +   rockchip_drm_crtc_has_pending_event(crtc)) {
>> +   if (async)
>> +   return -EBUSY;
>> +   else
>> +   rockchip_crtc_wait_for_update(crtc);
>
>
>> +   }
>> +   }
>> ret = drm_atomic_helper_prepare_planes(dev, state);
>> if (ret)
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index e2118e62345b..5240bc8fe088 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -848,6 +848,12 @@ int rockchip_drm_crtc_mode_config(struct drm_crtc
>> *crtc,
>>   }
>>   EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
>>   +bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc)
>> +{
>> +   return to_vop(crtc)->event;
>> +}
>> +EXPORT_SYMBOL_GPL(rockchip_drm_crtc_has_pending_event);
>> +
>
>
> No need to do EXPORT_SYMBOL_GPL, rockchip_drm_vop.c and rockchip_drm_fb.c
> will build into same object.
>
>
>>   static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
>>   {
>> struct vop *vop = to_vop(crtc);
>
> Hi Tomeu
>
> Since rockchip atomic async use "serialize outstanding asynchronous
> commits", async commit will wait on "flush_work(>work);" to ensure
> last pending event is done, so vop->event should be NULL after flush. if
> not, it should be a BUG.

I missed that, thanks.

> Anyway, serialize async commits is not a good way, but I don't think your
> patch is better way.

Per-CRTC workqueues should improve that, but I'm right now more
interested in correctness than performance.

> I think maybe we can check the "commit->work" status(finish or running) to
> judge return BUSY or not, instead of flush it.

That sounds better indeed.

Thanks,

Tomeu

> Thanks.
>
> --
> Mark Yao
>
>
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip event

2016-03-31 Thread Tomeu Vizoso
On 31 March 2016 at 03:25, Mark yao  wrote:
> On 2016年03月30日 21:48, Tomeu Vizoso wrote:
>>
>> As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
>> updated is requested and there is an earlier updated pending".
>>
>> Also wait for the pending event to complete when a sync update is
>> requested.
>>
>> Signed-off-by: Tomeu Vizoso 
>> ---
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 14 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  6 ++
>>   3 files changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> index 3529f692edb8..37952eefd33d 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> @@ -69,6 +69,7 @@ int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
>>   void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
>>   int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int
>> connector_type,
>>   int out_mode);
>> +bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc);
>>   int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
>>struct device *dev);
>>   void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> index 3b8f652698f8..028fd2f8f47b 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> @@ -280,7 +280,19 @@ int rockchip_drm_atomic_commit(struct drm_device
>> *dev,
>>   {
>> struct rockchip_drm_private *private = dev->dev_private;
>> struct rockchip_atomic_commit *commit = >commit;
>> -   int ret;
>> +   struct drm_crtc_state *crtc_state;
>> +   struct drm_crtc *crtc;
>> +   int i, ret;
>> +
>> +   for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> +   if (crtc->state->event ||
>> +   rockchip_drm_crtc_has_pending_event(crtc)) {
>> +   if (async)
>> +   return -EBUSY;
>> +   else
>> +   rockchip_crtc_wait_for_update(crtc);
>
>
>> +   }
>> +   }
>> ret = drm_atomic_helper_prepare_planes(dev, state);
>> if (ret)
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index e2118e62345b..5240bc8fe088 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -848,6 +848,12 @@ int rockchip_drm_crtc_mode_config(struct drm_crtc
>> *crtc,
>>   }
>>   EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
>>   +bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc)
>> +{
>> +   return to_vop(crtc)->event;
>> +}
>> +EXPORT_SYMBOL_GPL(rockchip_drm_crtc_has_pending_event);
>> +
>
>
> No need to do EXPORT_SYMBOL_GPL, rockchip_drm_vop.c and rockchip_drm_fb.c
> will build into same object.
>
>
>>   static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
>>   {
>> struct vop *vop = to_vop(crtc);
>
> Hi Tomeu
>
> Since rockchip atomic async use "serialize outstanding asynchronous
> commits", async commit will wait on "flush_work(>work);" to ensure
> last pending event is done, so vop->event should be NULL after flush. if
> not, it should be a BUG.

I missed that, thanks.

> Anyway, serialize async commits is not a good way, but I don't think your
> patch is better way.

Per-CRTC workqueues should improve that, but I'm right now more
interested in correctness than performance.

> I think maybe we can check the "commit->work" status(finish or running) to
> judge return BUSY or not, instead of flush it.

That sounds better indeed.

Thanks,

Tomeu

> Thanks.
>
> --
> Mark Yao
>
>
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip event

2016-03-30 Thread Tomeu Vizoso
As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
updated is requested and there is an earlier updated pending".

Also wait for the pending event to complete when a sync update is
requested.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 14 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  6 ++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3529f692edb8..37952eefd33d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -69,6 +69,7 @@ int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
 void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
  int out_mode);
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc);
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 3b8f652698f8..028fd2f8f47b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -280,7 +280,19 @@ int rockchip_drm_atomic_commit(struct drm_device *dev,
 {
struct rockchip_drm_private *private = dev->dev_private;
struct rockchip_atomic_commit *commit = >commit;
-   int ret;
+   struct drm_crtc_state *crtc_state;
+   struct drm_crtc *crtc;
+   int i, ret;
+
+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
+   if (crtc->state->event ||
+   rockchip_drm_crtc_has_pending_event(crtc)) {
+   if (async)
+   return -EBUSY;
+   else
+   rockchip_crtc_wait_for_update(crtc);
+   }
+   }
 
ret = drm_atomic_helper_prepare_planes(dev, state);
if (ret)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index e2118e62345b..5240bc8fe088 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -848,6 +848,12 @@ int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
 
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc)
+{
+   return to_vop(crtc)->event;
+}
+EXPORT_SYMBOL_GPL(rockchip_drm_crtc_has_pending_event);
+
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
-- 
2.5.5



[PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip event

2016-03-30 Thread Tomeu Vizoso
As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
updated is requested and there is an earlier updated pending".

Also wait for the pending event to complete when a sync update is
requested.

Signed-off-by: Tomeu Vizoso 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 14 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  6 ++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3529f692edb8..37952eefd33d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -69,6 +69,7 @@ int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
 void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
  int out_mode);
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc);
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 3b8f652698f8..028fd2f8f47b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -280,7 +280,19 @@ int rockchip_drm_atomic_commit(struct drm_device *dev,
 {
struct rockchip_drm_private *private = dev->dev_private;
struct rockchip_atomic_commit *commit = >commit;
-   int ret;
+   struct drm_crtc_state *crtc_state;
+   struct drm_crtc *crtc;
+   int i, ret;
+
+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
+   if (crtc->state->event ||
+   rockchip_drm_crtc_has_pending_event(crtc)) {
+   if (async)
+   return -EBUSY;
+   else
+   rockchip_crtc_wait_for_update(crtc);
+   }
+   }
 
ret = drm_atomic_helper_prepare_planes(dev, state);
if (ret)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index e2118e62345b..5240bc8fe088 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -848,6 +848,12 @@ int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
 
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc)
+{
+   return to_vop(crtc)->event;
+}
+EXPORT_SYMBOL_GPL(rockchip_drm_crtc_has_pending_event);
+
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
-- 
2.5.5



Re: [RFC 00/29] De-stage android's sync framework

2016-03-23 Thread Tomeu Vizoso
On 19 January 2016 at 17:12, John Harrison  wrote:
> On 19/01/2016 15:23, Gustavo Padovan wrote:
>>
>> Hi Daniel,
>>
>> 2016-01-19 Daniel Vetter :
>>
>>> On Fri, Jan 15, 2016 at 12:55:10PM -0200, Gustavo Padovan wrote:

 From: Gustavo Padovan 

 This patch series de-stage the sync framework, and in order to
 accomplish that
 a bunch of cleanups/improvements on the sync and fence were made.

 The sync framework contained some abstractions around struct fence and
 those
 were removed in the de-staging process among other changes:

 Userspace visible changes
 -

   * The sw_sync file was moved from /dev/sw_sync to
 /sync/sw_sync. No
   other change.

 Kernel API changes
 --

   * struct sync_timeline is now struct fence_timeline
   * sync_timeline_ops is now fence_timeline_ops and they now carry
 struct
   fence as parameter instead of struct sync_pt
   * a .cleanup() fence op was added to allow sync_fence to run a cleanup
 when
   the fence_timeline is destroyed
   * added fence_add_used_data() to pass a private point to struct fence.
 This
   pointer is sent back on the .cleanup op.
   * The sync timeline function were moved to be fence_timeline
 functions:
  - sync_timeline_create()   -> fence_timeline_create()
  - sync_timeline_get()  -> fence_timeline_get()
  - sync_timeline_put()  -> fence_timeline_put()
  - sync_timeline_destroy()  -> fence_timeline_destroy()
  - sync_timeline_signal()   -> fence_timeline_signal()

* sync_pt_create() was replaced be fence_create_on_timeline()

 Internal changes
 

   * fence_timeline_ops was removed in favor of direct use fence_ops
   * fence default functions were created for fence_ops
   * removed structs sync_pt, sw_sync_timeline and sw_sync_pt
>>>
>>> Bunch of fairly random comments all over:
>>>
>>> - include/uapi/linux/sw_sync.h imo should be dropped, it's just a private
>>>debugfs interface between fence fds and the testsuite. Since the plan
>>> is
>>>to have the testcases integrated into the kernel tree too we don't
>>> need
>>>a public header.
>>>
>>> - similar for include/linux/sw_sync.h Imo that should all be moved into
>>>sync_debug.c. Same for sw_sync.c, that should all land in sync_debug
>>>imo, and made optional with a Kconfig option. At least we should reuse
>>>CONFIG_DEBUGFS.
>>
>> These two items sounds reasonable to me.
>
>
> I have just posted our in-progress IGT for testing i915 syncs (with a CC of
> Gustavo). It uses the sw_sync mechanisms. Can you take a quick look and see
> if it is the kind of thing you would expect us to be doing? Or is it using
> interfaces that you are planning to remove and/or make kernel only?
>
> I'm not sure having a kernel only test is the best way to go. Having user
> land tests like IGT would be much more versatile.

Hi John,

I'm working on making the tests in igt useful for drivers other than
i915 and would love to have tests for the fence functionality. Have
you made any progress since you posted that RFC?

Thanks,

Tomeu


Re: [RFC 00/29] De-stage android's sync framework

2016-03-23 Thread Tomeu Vizoso
On 19 January 2016 at 17:12, John Harrison  wrote:
> On 19/01/2016 15:23, Gustavo Padovan wrote:
>>
>> Hi Daniel,
>>
>> 2016-01-19 Daniel Vetter :
>>
>>> On Fri, Jan 15, 2016 at 12:55:10PM -0200, Gustavo Padovan wrote:

 From: Gustavo Padovan 

 This patch series de-stage the sync framework, and in order to
 accomplish that
 a bunch of cleanups/improvements on the sync and fence were made.

 The sync framework contained some abstractions around struct fence and
 those
 were removed in the de-staging process among other changes:

 Userspace visible changes
 -

   * The sw_sync file was moved from /dev/sw_sync to
 /sync/sw_sync. No
   other change.

 Kernel API changes
 --

   * struct sync_timeline is now struct fence_timeline
   * sync_timeline_ops is now fence_timeline_ops and they now carry
 struct
   fence as parameter instead of struct sync_pt
   * a .cleanup() fence op was added to allow sync_fence to run a cleanup
 when
   the fence_timeline is destroyed
   * added fence_add_used_data() to pass a private point to struct fence.
 This
   pointer is sent back on the .cleanup op.
   * The sync timeline function were moved to be fence_timeline
 functions:
  - sync_timeline_create()   -> fence_timeline_create()
  - sync_timeline_get()  -> fence_timeline_get()
  - sync_timeline_put()  -> fence_timeline_put()
  - sync_timeline_destroy()  -> fence_timeline_destroy()
  - sync_timeline_signal()   -> fence_timeline_signal()

* sync_pt_create() was replaced be fence_create_on_timeline()

 Internal changes
 

   * fence_timeline_ops was removed in favor of direct use fence_ops
   * fence default functions were created for fence_ops
   * removed structs sync_pt, sw_sync_timeline and sw_sync_pt
>>>
>>> Bunch of fairly random comments all over:
>>>
>>> - include/uapi/linux/sw_sync.h imo should be dropped, it's just a private
>>>debugfs interface between fence fds and the testsuite. Since the plan
>>> is
>>>to have the testcases integrated into the kernel tree too we don't
>>> need
>>>a public header.
>>>
>>> - similar for include/linux/sw_sync.h Imo that should all be moved into
>>>sync_debug.c. Same for sw_sync.c, that should all land in sync_debug
>>>imo, and made optional with a Kconfig option. At least we should reuse
>>>CONFIG_DEBUGFS.
>>
>> These two items sounds reasonable to me.
>
>
> I have just posted our in-progress IGT for testing i915 syncs (with a CC of
> Gustavo). It uses the sw_sync mechanisms. Can you take a quick look and see
> if it is the kind of thing you would expect us to be doing? Or is it using
> interfaces that you are planning to remove and/or make kernel only?
>
> I'm not sure having a kernel only test is the best way to go. Having user
> land tests like IGT would be much more versatile.

Hi John,

I'm working on making the tests in igt useful for drivers other than
i915 and would love to have tests for the fence functionality. Have
you made any progress since you posted that RFC?

Thanks,

Tomeu


[PATCH] iommu/rockchip: Only log stall errors when attaching

2016-03-22 Thread Tomeu Vizoso
Move the logging of timeouts when stalling the MMU to
rk_iommu_attach_device, as it's expected that sometimes the MMU won't
get stalled when detaching a device, and it's not a real problem that
would need to be communicated to the user.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---
 drivers/iommu/rockchip-iommu.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0253ab35c33b..65325b6742e6 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -346,13 +346,7 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
 
-   ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
-   if (ret)
-   for (i = 0; i < iommu->num_mmu; i++)
-   dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
-   rk_iommu_read(iommu->bases[i], RK_MMU_STATUS));
-
-   return ret;
+   return rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
 }
 
 static int rk_iommu_disable_stall(struct rk_iommu *iommu)
@@ -798,8 +792,12 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
return 0;
 
ret = rk_iommu_enable_stall(iommu);
-   if (ret)
+   if (ret) {
+   for (i = 0; i < iommu->num_mmu; i++)
+   dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
+   rk_iommu_read(iommu->bases[i], RK_MMU_STATUS));
return ret;
+   }
 
ret = rk_iommu_force_reset(iommu);
if (ret)
-- 
2.5.0



[PATCH] iommu/rockchip: Only log stall errors when attaching

2016-03-22 Thread Tomeu Vizoso
Move the logging of timeouts when stalling the MMU to
rk_iommu_attach_device, as it's expected that sometimes the MMU won't
get stalled when detaching a device, and it's not a real problem that
would need to be communicated to the user.

Signed-off-by: Tomeu Vizoso 
---
 drivers/iommu/rockchip-iommu.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0253ab35c33b..65325b6742e6 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -346,13 +346,7 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
 
-   ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
-   if (ret)
-   for (i = 0; i < iommu->num_mmu; i++)
-   dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
-   rk_iommu_read(iommu->bases[i], RK_MMU_STATUS));
-
-   return ret;
+   return rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
 }
 
 static int rk_iommu_disable_stall(struct rk_iommu *iommu)
@@ -798,8 +792,12 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
return 0;
 
ret = rk_iommu_enable_stall(iommu);
-   if (ret)
+   if (ret) {
+   for (i = 0; i < iommu->num_mmu; i++)
+   dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
+   rk_iommu_read(iommu->bases[i], RK_MMU_STATUS));
return ret;
+   }
 
ret = rk_iommu_force_reset(iommu);
if (ret)
-- 
2.5.0



[PATCH v2] drm/rockchip: vop: Disable planes when disabling CRTC

2016-03-22 Thread Tomeu Vizoso
When a VOP is re-enabled, it will start scanning right away the
framebuffers that were configured from the last time, even if those have
been destroyed already.

To prevent the VOP from trying to access freed memory, disable all its
windows when the CRTC is being disabled, then each window will get a
valid framebuffer address before it's enabled again.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Link: 
http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 5e57f5b2e4b0..e2118e62345b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -499,10 +499,25 @@ err_disable_hclk:
 static void vop_crtc_disable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int i;
 
if (!vop->is_enabled)
return;
 
+   /*
+* We need to make sure that all windows are disabled before we
+* disable that crtc. Otherwise we might try to scan from a destroyed
+* buffer later.
+*/
+   for (i = 0; i < vop->data->win_size; i++) {
+   struct vop_win *vop_win = >win[i];
+   const struct vop_win_data *win = vop_win->data;
+
+   spin_lock(>reg_lock);
+   VOP_WIN_SET(vop, win, enable, 0);
+   spin_unlock(>reg_lock);
+   }
+
drm_crtc_vblank_off(crtc);
 
/*
-- 
2.5.0



[PATCH v2] drm/rockchip: vop: Disable planes when disabling CRTC

2016-03-22 Thread Tomeu Vizoso
When a VOP is re-enabled, it will start scanning right away the
framebuffers that were configured from the last time, even if those have
been destroyed already.

To prevent the VOP from trying to access freed memory, disable all its
windows when the CRTC is being disabled, then each window will get a
valid framebuffer address before it's enabled again.

Signed-off-by: Tomeu Vizoso 
Link: 
http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 5e57f5b2e4b0..e2118e62345b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -499,10 +499,25 @@ err_disable_hclk:
 static void vop_crtc_disable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int i;
 
if (!vop->is_enabled)
return;
 
+   /*
+* We need to make sure that all windows are disabled before we
+* disable that crtc. Otherwise we might try to scan from a destroyed
+* buffer later.
+*/
+   for (i = 0; i < vop->data->win_size; i++) {
+   struct vop_win *vop_win = >win[i];
+   const struct vop_win_data *win = vop_win->data;
+
+   spin_lock(>reg_lock);
+   VOP_WIN_SET(vop, win, enable, 0);
+   spin_unlock(>reg_lock);
+   }
+
drm_crtc_vblank_off(crtc);
 
/*
-- 
2.5.0



Re: [PATCH] drm/rockchip: vop: Reset yrgb_mst when re-enabling

2016-03-21 Thread Tomeu Vizoso
On 19 March 2016 at 02:15, Mark yao <mark@rock-chips.com> wrote:
> On 2016年03月18日 19:22, Tomeu Vizoso wrote:
>>
>> When the VOP is re-enabled, it will start scanning right away the
>> framebuffers that were configured from the last time, even if those have
>> been destroyed already. To prevent the VOP from trying to access freed
>> memory, reset the registers that hold pointers to framebuffers right
>> after we can write to them, but before the VOP is awaken from standby.
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
>> Link:
>> http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
>> ---
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 +
>>   1 file changed, 13 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index 5e57f5b2e4b0..0df91c28740b 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -429,6 +429,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop
>> *vop)
>>   static void vop_enable(struct drm_crtc *crtc)
>>   {
>> struct vop *vop = to_vop(crtc);
>> +   int i;
>> int ret;
>> if (vop->is_enabled)
>> @@ -476,6 +477,18 @@ static void vop_enable(struct drm_crtc *crtc)
>>  */
>> vop->is_enabled = true;
>>   + /*
>> +* Before turning the VOP completely on, unset the registers
>> +* containing FB addresses to avoid the HW start scanning old FBs.
>> +*/
>> +   for (i = 0; i < vop->data->win_size; i++) {
>> +   struct vop_win *vop_win = >win[i];
>> +   const struct vop_win_data *win = vop_win->data;
>> +
>> +   VOP_WIN_SET(vop, win, yrgb_mst, 0x0);
>> +   VOP_WIN_SET(vop, win, uv_mst, 0x0);
>> +   }
>> +
>
> Hi Tomeu
>
> Thanks for your fix.
>
> Set yrgb_mst and uv_mst is not a good idea, because 0x0 also is a memory
> buffer address, ddr will access the 0x0 buffer.
> I think you may enable DRM_FBDEV_EMULATION, the 0x0 address is iommu mmaped
> address for fbdev, so your test can works.
> but if DRM_FBDEV_EMULATION is not define, may be 0x0 address is unmmaped,
> would get the iommu crash.

I have checked with DRM_FBDEV_EMULATION disabled and seems to work equally well.

> I think we can use atomic disable function like this:
> for_each_plane_in_state(old_state, plane, old_plane_state, i) {
> const struct drm_plane_helper_funcs *funcs;
> funcs = plane->helper_private;
> funcs->atomic_disable(plane, old_plane_state);
> }
>
> But I think we'd better find why we need do this hack here.
>
> Does the old FB address is ummaped when crtc disabling? why plane is not
> disabled?

Planes aren't being disabled because the CRTC is being disabled
already, see 
http://lxr.free-electrons.com/source/drivers/gpu/drm/drm_atomic_helper.c#L1306

Exynos is already disabling all planes when a crtc is disabled:

http://lxr.free-electrons.com/source/drivers/gpu/drm/exynos/exynos_drm_fimd.c#L782

I don't like it because there's state in the drm core and in the
drivers that is left inconsistent.

Regards,

Tomeu

> Thanks.
>
>> spin_lock(>reg_lock);
>> VOP_CTRL_SET(vop, standby, 0);
>
>
>
> --
> Mark Yao
>
>
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/rockchip: vop: Reset yrgb_mst when re-enabling

2016-03-21 Thread Tomeu Vizoso
On 19 March 2016 at 02:15, Mark yao  wrote:
> On 2016年03月18日 19:22, Tomeu Vizoso wrote:
>>
>> When the VOP is re-enabled, it will start scanning right away the
>> framebuffers that were configured from the last time, even if those have
>> been destroyed already. To prevent the VOP from trying to access freed
>> memory, reset the registers that hold pointers to framebuffers right
>> after we can write to them, but before the VOP is awaken from standby.
>>
>> Signed-off-by: Tomeu Vizoso 
>> Link:
>> http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
>> ---
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 +
>>   1 file changed, 13 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index 5e57f5b2e4b0..0df91c28740b 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -429,6 +429,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop
>> *vop)
>>   static void vop_enable(struct drm_crtc *crtc)
>>   {
>> struct vop *vop = to_vop(crtc);
>> +   int i;
>> int ret;
>> if (vop->is_enabled)
>> @@ -476,6 +477,18 @@ static void vop_enable(struct drm_crtc *crtc)
>>  */
>> vop->is_enabled = true;
>>   + /*
>> +* Before turning the VOP completely on, unset the registers
>> +* containing FB addresses to avoid the HW start scanning old FBs.
>> +*/
>> +   for (i = 0; i < vop->data->win_size; i++) {
>> +   struct vop_win *vop_win = >win[i];
>> +   const struct vop_win_data *win = vop_win->data;
>> +
>> +   VOP_WIN_SET(vop, win, yrgb_mst, 0x0);
>> +   VOP_WIN_SET(vop, win, uv_mst, 0x0);
>> +   }
>> +
>
> Hi Tomeu
>
> Thanks for your fix.
>
> Set yrgb_mst and uv_mst is not a good idea, because 0x0 also is a memory
> buffer address, ddr will access the 0x0 buffer.
> I think you may enable DRM_FBDEV_EMULATION, the 0x0 address is iommu mmaped
> address for fbdev, so your test can works.
> but if DRM_FBDEV_EMULATION is not define, may be 0x0 address is unmmaped,
> would get the iommu crash.

I have checked with DRM_FBDEV_EMULATION disabled and seems to work equally well.

> I think we can use atomic disable function like this:
> for_each_plane_in_state(old_state, plane, old_plane_state, i) {
> const struct drm_plane_helper_funcs *funcs;
> funcs = plane->helper_private;
> funcs->atomic_disable(plane, old_plane_state);
> }
>
> But I think we'd better find why we need do this hack here.
>
> Does the old FB address is ummaped when crtc disabling? why plane is not
> disabled?

Planes aren't being disabled because the CRTC is being disabled
already, see 
http://lxr.free-electrons.com/source/drivers/gpu/drm/drm_atomic_helper.c#L1306

Exynos is already disabling all planes when a crtc is disabled:

http://lxr.free-electrons.com/source/drivers/gpu/drm/exynos/exynos_drm_fimd.c#L782

I don't like it because there's state in the drm core and in the
drivers that is left inconsistent.

Regards,

Tomeu

> Thanks.
>
>> spin_lock(>reg_lock);
>> VOP_CTRL_SET(vop, standby, 0);
>
>
>
> --
> Mark Yao
>
>
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] iommu/rockchip: Don't feed NULL res pointers to devres

2016-03-21 Thread Tomeu Vizoso
If we do, devres prints a "invalid resource" string in the error
loglevel.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---
 drivers/iommu/rockchip-iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index a6f593a0a29e..0253ab35c33b 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1049,6 +1049,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
for (i = 0; i < pdev->num_resources; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+   if (!res)
+   continue;
iommu->bases[i] = devm_ioremap_resource(>dev, res);
if (IS_ERR(iommu->bases[i]))
continue;
-- 
2.5.0



[PATCH] iommu/rockchip: Don't feed NULL res pointers to devres

2016-03-21 Thread Tomeu Vizoso
If we do, devres prints a "invalid resource" string in the error
loglevel.

Signed-off-by: Tomeu Vizoso 
---
 drivers/iommu/rockchip-iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index a6f593a0a29e..0253ab35c33b 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1049,6 +1049,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
for (i = 0; i < pdev->num_resources; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+   if (!res)
+   continue;
iommu->bases[i] = devm_ioremap_resource(>dev, res);
if (IS_ERR(iommu->bases[i]))
continue;
-- 
2.5.0



Re: [PATCH] ARM: dts: rockchip: Add mdio node to ethernet node

2016-03-21 Thread Tomeu Vizoso
On 18 March 2016 at 22:34, Andreas Färber <afaer...@suse.de> wrote:
> Am 18.03.2016 um 12:20 schrieb Tomeu Vizoso:
>> So the dwmac device manages to probe again.
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
>> Fixes: 88f8b1bb41c6 ("stmmac: Fix 'eth0: No PHY found' regression")
>> ---
>>  arch/arm/boot/dts/rk3288-rock2-som.dtsi | 8 
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi 
>> b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
>> index 1ece66f3e162..4ba7ddecb478 100644
>> --- a/arch/arm/boot/dts/rk3288-rock2-som.dtsi
>> +++ b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
>> @@ -101,6 +101,14 @@
>>   snps,reset-delays-us = <0 1 3>;
>>   rx_delay = <0x10>;
>>   tx_delay = <0x30>;
>> + mdio0 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + compatible = "snps,dwmac-mdio";
>> + ethphy1: ethernet-phy@1 {
>> + reg = <1>;
>> + };
>> + };
>
> This is a) ugly for lack of white lines in between, b) unnecessary since
> this is being fixed in the stmmac driver where it will benefit more than
> just this one SoM.

So is this redundant information, or just not necessary with the
present kernel driver because of some assumption in its current
implementation?

Thanks,

Tomeu

> Regards,
> Andreas
>
>>  };
>>
>>   {
>
> --
> SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg)


Re: [PATCH] ARM: dts: rockchip: Add mdio node to ethernet node

2016-03-21 Thread Tomeu Vizoso
On 18 March 2016 at 22:34, Andreas Färber  wrote:
> Am 18.03.2016 um 12:20 schrieb Tomeu Vizoso:
>> So the dwmac device manages to probe again.
>>
>> Signed-off-by: Tomeu Vizoso 
>> Fixes: 88f8b1bb41c6 ("stmmac: Fix 'eth0: No PHY found' regression")
>> ---
>>  arch/arm/boot/dts/rk3288-rock2-som.dtsi | 8 
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi 
>> b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
>> index 1ece66f3e162..4ba7ddecb478 100644
>> --- a/arch/arm/boot/dts/rk3288-rock2-som.dtsi
>> +++ b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
>> @@ -101,6 +101,14 @@
>>   snps,reset-delays-us = <0 1 3>;
>>   rx_delay = <0x10>;
>>   tx_delay = <0x30>;
>> + mdio0 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + compatible = "snps,dwmac-mdio";
>> + ethphy1: ethernet-phy@1 {
>> + reg = <1>;
>> + };
>> + };
>
> This is a) ugly for lack of white lines in between, b) unnecessary since
> this is being fixed in the stmmac driver where it will benefit more than
> just this one SoM.

So is this redundant information, or just not necessary with the
present kernel driver because of some assumption in its current
implementation?

Thanks,

Tomeu

> Regards,
> Andreas
>
>>  };
>>
>>   {
>
> --
> SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg)


[PATCH] drm/rockchip: vop: Reset yrgb_mst when re-enabling

2016-03-20 Thread Tomeu Vizoso
When the VOP is re-enabled, it will start scanning right away the
framebuffers that were configured from the last time, even if those have
been destroyed already. To prevent the VOP from trying to access freed
memory, reset the registers that hold pointers to framebuffers right
after we can write to them, but before the VOP is awaken from standby.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Link: 
http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 5e57f5b2e4b0..0df91c28740b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -429,6 +429,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int i;
int ret;
 
if (vop->is_enabled)
@@ -476,6 +477,18 @@ static void vop_enable(struct drm_crtc *crtc)
 */
vop->is_enabled = true;
 
+   /*
+* Before turning the VOP completely on, unset the registers
+* containing FB addresses to avoid the HW start scanning old FBs.
+*/
+   for (i = 0; i < vop->data->win_size; i++) {
+   struct vop_win *vop_win = >win[i];
+   const struct vop_win_data *win = vop_win->data;
+
+   VOP_WIN_SET(vop, win, yrgb_mst, 0x0);
+   VOP_WIN_SET(vop, win, uv_mst, 0x0);
+   }
+
spin_lock(>reg_lock);
 
VOP_CTRL_SET(vop, standby, 0);
-- 
2.5.0



[PATCH] drm/rockchip: vop: Reset yrgb_mst when re-enabling

2016-03-20 Thread Tomeu Vizoso
When the VOP is re-enabled, it will start scanning right away the
framebuffers that were configured from the last time, even if those have
been destroyed already. To prevent the VOP from trying to access freed
memory, reset the registers that hold pointers to framebuffers right
after we can write to them, but before the VOP is awaken from standby.

Signed-off-by: Tomeu Vizoso 
Link: 
http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 5e57f5b2e4b0..0df91c28740b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -429,6 +429,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int i;
int ret;
 
if (vop->is_enabled)
@@ -476,6 +477,18 @@ static void vop_enable(struct drm_crtc *crtc)
 */
vop->is_enabled = true;
 
+   /*
+* Before turning the VOP completely on, unset the registers
+* containing FB addresses to avoid the HW start scanning old FBs.
+*/
+   for (i = 0; i < vop->data->win_size; i++) {
+   struct vop_win *vop_win = >win[i];
+   const struct vop_win_data *win = vop_win->data;
+
+   VOP_WIN_SET(vop, win, yrgb_mst, 0x0);
+   VOP_WIN_SET(vop, win, uv_mst, 0x0);
+   }
+
spin_lock(>reg_lock);
 
VOP_CTRL_SET(vop, standby, 0);
-- 
2.5.0



Re: [PATCH v15 1/3] drm: rockchip: Add basic drm driver

2016-03-19 Thread Tomeu Vizoso
On 15 March 2016 at 02:30, Mark yao <mark@rock-chips.com> wrote:
> On 2016年03月14日 21:35, Tomeu Vizoso wrote:
>>
>> On 2 December 2014 at 10:15, Mark Yao <mark@rock-chips.com> wrote:
>>>
>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> new file mode 100644
>>> index 000..e7ca25b
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> @@ -0,0 +1,1455 @@
>>
>> ...
>>>
>>> +static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
>>> +   const struct drm_display_mode *mode,
>>> +   struct drm_display_mode *adjusted_mode)
>>> +{
>>> +   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
>>> +   return false;
>>
>> Hi Mark,
>>
>> what's the rationale for this?
>>
>> Disabling a CRTC as in [0] will cause mode_fixup() to be called with
>> an empty mode, failing that test.
>>
>> Removing the check seems to get things working fine for a short while,
>> but a later modeset invariably gets the VOP to hang (as reported by
>> [1]).
>>
>> Do you know why that check was put in place and what exactly could be
>> causing the hw to hang?
>>
>> [0]
>> https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/lib/igt_kms.c#n1616
>> [1]
>> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop.c#n873
>>
>> Thanks,
>>
>> Tomeu
>>
> Hi Tomeu
>
> Just thinking that "adjusted_mode->htotal == 0 || adjusted_mode->vtotal ==
> 0" is not a good mode for vop.

Ah, ok. Guess it should be removed then so we don't break userspace?

> And you said VOP hang, only WARN_ON error message? or system hang, die?

Sorry, the symptom was only the warning, I just went a bit too far and
assumed the VOP had stopped working at all.

> I think maybe crtc disable too fast, vblank is off, then no one can feed the
> wait_update_complete.
> Can you test it again with following patch?

Actually, in today's testing I don't see that happening any more,
sorry about that :/

What I have been looking at today is a related issue when running the
kms_flip_event_leak test from intel-gpu-tools. If I remove the check
mentioned above so CRTCs can be disabled with the SetCRTC IOCTL, I see
this page fault the second and subsequent times I run the test.

[   75.809031] rk_iommu ff930300.iommu: Page fault at 0x0100 of type read
[   75.809035] rk_iommu ff930300.iommu: iova = 0x0100: dte_index:
0x4 pte_index: 0x0 page_offset: 0x0
[   75.809040] rk_iommu ff930300.iommu: mmu_dte_addr: 0x2c258000
dte@0x2c258010: 0x2c561001 valid: 1 pte@0x2c561000: 0x2a06 valid:
0 page@0x flags: 0x0
[   76.951288] rk_iommu ff930300.iommu: Enable stall request timed
out, status: 0x4b

I have written a smaller standalone test that is attached in case you
want to check it out, but I haven't been able to find out why it only
happens when the test is rerun.

Apparently the VOP is still trying to read a BO (0x0100) right
when the kernel frees it, but from what I can see, it should be
scanning another BO at that point.

Do you have any ideas on what could be happening?

Thanks,

Tomeu

> drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -503,6 +503,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
> if (!vop->is_enabled)
> return;
>  +   vop_crtc_wait_for_update(crtc);
> +
> drm_crtc_vblank_off(crtc);
>
> Thanks.
>
> --
> Mark Yao
>
>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

__attribute__((format(printf, 1, 2)))
static void kmsg(const char *format, ...)
#define KERN_EMER	"<0>"
#define KERN_ALERT	"<1>"
#define KERN_CRIT	"<2>"
#define KERN_ERR	"<3>"
#define KERN_WARNING	"<4>"
#define KERN_NOTICE	"<5>"
#define KERN_INFO	"<6>"
#define KERN_DEBUG	"<7>"
{
	va_list ap;
	FILE *file;

	file = fopen("/dev/kmsg", "w");
	if (file == NULL)
		return;

	va_start(ap, format);
	fprintf(file, "userspace: ");
	vfprintf(file, format, ap);
	va_end(ap);

	fclose(file);
}

static uint32_t dumb_create(int fd, int width, int height, int bpp)
{
	struct drm_mode_create_dumb create = {};

	create.width = width;
	create.height = height;
	create.bpp = bpp;

	create.handle = 0;
	drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, );

	return create.handle;
}

static uint32_t fb_create(int fd, int width, int height, int format, int

Re: [PATCH v15 1/3] drm: rockchip: Add basic drm driver

2016-03-19 Thread Tomeu Vizoso
On 15 March 2016 at 02:30, Mark yao  wrote:
> On 2016年03月14日 21:35, Tomeu Vizoso wrote:
>>
>> On 2 December 2014 at 10:15, Mark Yao  wrote:
>>>
>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> new file mode 100644
>>> index 000..e7ca25b
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> @@ -0,0 +1,1455 @@
>>
>> ...
>>>
>>> +static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
>>> +   const struct drm_display_mode *mode,
>>> +   struct drm_display_mode *adjusted_mode)
>>> +{
>>> +   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
>>> +   return false;
>>
>> Hi Mark,
>>
>> what's the rationale for this?
>>
>> Disabling a CRTC as in [0] will cause mode_fixup() to be called with
>> an empty mode, failing that test.
>>
>> Removing the check seems to get things working fine for a short while,
>> but a later modeset invariably gets the VOP to hang (as reported by
>> [1]).
>>
>> Do you know why that check was put in place and what exactly could be
>> causing the hw to hang?
>>
>> [0]
>> https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/lib/igt_kms.c#n1616
>> [1]
>> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop.c#n873
>>
>> Thanks,
>>
>> Tomeu
>>
> Hi Tomeu
>
> Just thinking that "adjusted_mode->htotal == 0 || adjusted_mode->vtotal ==
> 0" is not a good mode for vop.

Ah, ok. Guess it should be removed then so we don't break userspace?

> And you said VOP hang, only WARN_ON error message? or system hang, die?

Sorry, the symptom was only the warning, I just went a bit too far and
assumed the VOP had stopped working at all.

> I think maybe crtc disable too fast, vblank is off, then no one can feed the
> wait_update_complete.
> Can you test it again with following patch?

Actually, in today's testing I don't see that happening any more,
sorry about that :/

What I have been looking at today is a related issue when running the
kms_flip_event_leak test from intel-gpu-tools. If I remove the check
mentioned above so CRTCs can be disabled with the SetCRTC IOCTL, I see
this page fault the second and subsequent times I run the test.

[   75.809031] rk_iommu ff930300.iommu: Page fault at 0x0100 of type read
[   75.809035] rk_iommu ff930300.iommu: iova = 0x0100: dte_index:
0x4 pte_index: 0x0 page_offset: 0x0
[   75.809040] rk_iommu ff930300.iommu: mmu_dte_addr: 0x2c258000
dte@0x2c258010: 0x2c561001 valid: 1 pte@0x2c561000: 0x2a06 valid:
0 page@0x flags: 0x0
[   76.951288] rk_iommu ff930300.iommu: Enable stall request timed
out, status: 0x4b

I have written a smaller standalone test that is attached in case you
want to check it out, but I haven't been able to find out why it only
happens when the test is rerun.

Apparently the VOP is still trying to read a BO (0x0100) right
when the kernel frees it, but from what I can see, it should be
scanning another BO at that point.

Do you have any ideas on what could be happening?

Thanks,

Tomeu

> drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -503,6 +503,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
> if (!vop->is_enabled)
> return;
>  +   vop_crtc_wait_for_update(crtc);
> +
> drm_crtc_vblank_off(crtc);
>
> Thanks.
>
> --
> Mark Yao
>
>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

__attribute__((format(printf, 1, 2)))
static void kmsg(const char *format, ...)
#define KERN_EMER	"<0>"
#define KERN_ALERT	"<1>"
#define KERN_CRIT	"<2>"
#define KERN_ERR	"<3>"
#define KERN_WARNING	"<4>"
#define KERN_NOTICE	"<5>"
#define KERN_INFO	"<6>"
#define KERN_DEBUG	"<7>"
{
	va_list ap;
	FILE *file;

	file = fopen("/dev/kmsg", "w");
	if (file == NULL)
		return;

	va_start(ap, format);
	fprintf(file, "userspace: ");
	vfprintf(file, format, ap);
	va_end(ap);

	fclose(file);
}

static uint32_t dumb_create(int fd, int width, int height, int bpp)
{
	struct drm_mode_create_dumb create = {};

	create.width = width;
	create.height = height;
	create.bpp = bpp;

	create.handle = 0;
	drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, );

	return create.handle;
}

static uint32_t fb_create(int fd, int width, int height, int format, int bo, int pitch)
{
	struct drm_mode_fb_cmd2 f = {};

	f.width =

[PATCH v6 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-19 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v6:
- Return 0 if the EC doesn't support MKBP, as expected by callers.

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index aaccdde1c9d5..3e1e83874edf 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return 0;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[PATCH v6 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-19 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso 
---

Changes in v6:
- Return 0 if the EC doesn't support MKBP, as expected by callers.

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index aaccdde1c9d5..3e1e83874edf 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return 0;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[PATCH] ARM: dts: rockchip: Add mdio node to ethernet node

2016-03-19 Thread Tomeu Vizoso
So the dwmac device manages to probe again.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Fixes: 88f8b1bb41c6 ("stmmac: Fix 'eth0: No PHY found' regression")
---
 arch/arm/boot/dts/rk3288-rock2-som.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi 
b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
index 1ece66f3e162..4ba7ddecb478 100644
--- a/arch/arm/boot/dts/rk3288-rock2-som.dtsi
+++ b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
@@ -101,6 +101,14 @@
snps,reset-delays-us = <0 1 3>;
rx_delay = <0x10>;
tx_delay = <0x30>;
+   mdio0 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   compatible = "snps,dwmac-mdio";
+   ethphy1: ethernet-phy@1 {
+   reg = <1>;
+   };
+   };
 };
 
  {
-- 
2.5.0



[PATCH] ARM: dts: rockchip: Add mdio node to ethernet node

2016-03-19 Thread Tomeu Vizoso
So the dwmac device manages to probe again.

Signed-off-by: Tomeu Vizoso 
Fixes: 88f8b1bb41c6 ("stmmac: Fix 'eth0: No PHY found' regression")
---
 arch/arm/boot/dts/rk3288-rock2-som.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi 
b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
index 1ece66f3e162..4ba7ddecb478 100644
--- a/arch/arm/boot/dts/rk3288-rock2-som.dtsi
+++ b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
@@ -101,6 +101,14 @@
snps,reset-delays-us = <0 1 3>;
rx_delay = <0x10>;
tx_delay = <0x30>;
+   mdio0 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   compatible = "snps,dwmac-mdio";
+   ethphy1: ethernet-phy@1 {
+   reg = <1>;
+   };
+   };
 };
 
  {
-- 
2.5.0



[PATCH v6 1/6] mfd: cros_ec: Add MKBP event support

2016-03-19 Thread Tomeu Vizoso
From: Vic Yang <victory...@google.com>

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang <victory...@chromium.org>
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung <ble...@chromium.org>
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Randall Spangler <rspang...@chromium.org>
Cc: Vincent Palatin <vpala...@chromium.org>
---

Changes in v6: None
Changes in v5: None
Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_

[PATCH v6 1/6] mfd: cros_ec: Add MKBP event support

2016-03-19 Thread Tomeu Vizoso
From: Vic Yang 

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang 
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung 
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso 
Cc: Randall Spangler 
Cc: Vincent Palatin 
---

Changes in v6: None
Changes in v5: None
Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)

[PATCH v6 6/6] platform/chrome: Register USB PD charger device

2016-03-19 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[PATCH v6 6/6] platform/chrome: Register USB PD charger device

2016-03-19 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[PATCH v6 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-19 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define

[PATCH v6 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-19 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 <&

[PATCH v6 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-19 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Reviewed-by: Benson Leung <ble...@chromium.org>
---

Changes in v6: None
Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c792e116e621..aaccdde1c9d5 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result != EC_RES_SUCCESS)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[PATCH v6 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-19 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso 
Reviewed-by: Benson Leung 
---

Changes in v6: None
Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c792e116e621..aaccdde1c9d5 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result != EC_RES_SUCCESS)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[PATCH v6 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-19 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

This series may be best integrated through the MFD tree, for which we'll
need ACKs from Olof (for the changes to platform/chrome), from Dmitry
(for changes to cros_ec_keyb.c) and from Sebastian Reichel for the
new driver.

Thanks,

Tomeu

Changes in v6:
- Return 0 if the EC doesn't support MKBP, as expected by callers.

Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.
- Fix type of variable passed to do_div.

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.
- Declare size parameters in ec_command as size_t

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[PATCH v6 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-19 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

This series may be best integrated through the MFD tree, for which we'll
need ACKs from Olof (for the changes to platform/chrome), from Dmitry
(for changes to cros_ec_keyb.c) and from Sebastian Reichel for the
new driver.

Thanks,

Tomeu

Changes in v6:
- Return 0 if the EC doesn't support MKBP, as expected by callers.

Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.
- Fix type of variable passed to do_div.

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.
- Declare size parameters in ec_command as size_t

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[PATCH] drm/rockchip: vop: Don't reject empty modesets

2016-03-19 Thread Tomeu Vizoso
So that when DRM_IOCTL_MODE_SETCRTC is called without a FB nor mode, the
CRTC gets disabled.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Link: 
http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fd370548d7d7..5e57f5b2e4b0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -885,9 +885,6 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
 {
struct vop *vop = to_vop(crtc);
 
-   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
-   return false;
-
adjusted_mode->clock =
clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
 
-- 
2.5.0



[PATCH] drm/rockchip: vop: Don't reject empty modesets

2016-03-19 Thread Tomeu Vizoso
So that when DRM_IOCTL_MODE_SETCRTC is called without a FB nor mode, the
CRTC gets disabled.

Signed-off-by: Tomeu Vizoso 
Link: 
http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_nsjgmhfxyhehr8xxxmaczs+p5...@mail.gmail.com
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fd370548d7d7..5e57f5b2e4b0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -885,9 +885,6 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
 {
struct vop *vop = to_vop(crtc);
 
-   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
-   return false;
-
adjusted_mode->clock =
clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
 
-- 
2.5.0



[PATCH v6 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-19 Thread Tomeu Vizoso
From: Sameer Nanda <sna...@chromium.org>

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Sameer Nanda <sna...@chromium.org>
Cc: Benson Leung <ble...@chromium.org>
Cc: Shawn Nematbakhsh <sha...@chromium.org>
---

Changes in v6: None
Changes in v5:
- Fix type of variable passed to do_div.

Changes in v4:
- Declare size parameters in ec_command as size_t

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..7ba983286dc0
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   

[PATCH v6 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-19 Thread Tomeu Vizoso
From: Sameer Nanda 

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso 
Cc: Sameer Nanda 
Cc: Benson Leung 
Cc: Shawn Nematbakhsh 
---

Changes in v6: None
Changes in v5:
- Fix type of variable passed to do_div.

Changes in v4:
- Declare size parameters in ec_command as size_t

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..7ba983286dc0
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+
+static enum power_supply_property cros_usb_pd_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+ 

Re: [PATCH v15 1/3] drm: rockchip: Add basic drm driver

2016-03-18 Thread Tomeu Vizoso
On 16 March 2016 at 16:23, Tomeu Vizoso <to...@tomeuvizoso.net> wrote:
> On 15 March 2016 at 02:30, Mark yao <mark@rock-chips.com> wrote:
>> On 2016年03月14日 21:35, Tomeu Vizoso wrote:
>>>
>>> On 2 December 2014 at 10:15, Mark Yao <mark@rock-chips.com> wrote:
>>>>
>>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> new file mode 100644
>>>> index 000..e7ca25b
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> @@ -0,0 +1,1455 @@
>>>
>>> ...
>>>>
>>>> +static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
>>>> +   const struct drm_display_mode *mode,
>>>> +   struct drm_display_mode *adjusted_mode)
>>>> +{
>>>> +   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
>>>> +   return false;
>>>
>>> Hi Mark,
>>>
>>> what's the rationale for this?
>>>
>>> Disabling a CRTC as in [0] will cause mode_fixup() to be called with
>>> an empty mode, failing that test.
>>>
>>> Removing the check seems to get things working fine for a short while,
>>> but a later modeset invariably gets the VOP to hang (as reported by
>>> [1]).
>>>
>>> Do you know why that check was put in place and what exactly could be
>>> causing the hw to hang?
>>>
>>> [0]
>>> https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/lib/igt_kms.c#n1616
>>> [1]
>>> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop.c#n873
>>>
>>> Thanks,
>>>
>>> Tomeu
>>>
>> Hi Tomeu
>>
>> Just thinking that "adjusted_mode->htotal == 0 || adjusted_mode->vtotal ==
>> 0" is not a good mode for vop.
>
> Ah, ok. Guess it should be removed then so we don't break userspace?
>
>> And you said VOP hang, only WARN_ON error message? or system hang, die?
>
> Sorry, the symptom was only the warning, I just went a bit too far and
> assumed the VOP had stopped working at all.
>
>> I think maybe crtc disable too fast, vblank is off, then no one can feed the
>> wait_update_complete.
>> Can you test it again with following patch?
>
> Actually, in today's testing I don't see that happening any more,
> sorry about that :/
>
> What I have been looking at today is a related issue when running the
> kms_flip_event_leak test from intel-gpu-tools. If I remove the check
> mentioned above so CRTCs can be disabled with the SetCRTC IOCTL, I see
> this page fault the second and subsequent times I run the test.
>
> [   75.809031] rk_iommu ff930300.iommu: Page fault at 0x0100 of type read
> [   75.809035] rk_iommu ff930300.iommu: iova = 0x0100: dte_index:
> 0x4 pte_index: 0x0 page_offset: 0x0
> [   75.809040] rk_iommu ff930300.iommu: mmu_dte_addr: 0x2c258000
> dte@0x2c258010: 0x2c561001 valid: 1 pte@0x2c561000: 0x2a06 valid:
> 0 page@0x flags: 0x0
> [   76.951288] rk_iommu ff930300.iommu: Enable stall request timed
> out, status: 0x4b
>
> I have written a smaller standalone test that is attached in case you
> want to check it out, but I haven't been able to find out why it only
> happens when the test is rerun.
>
> Apparently the VOP is still trying to read a BO (0x0100) right
> when the kernel frees it, but from what I can see, it should be
> scanning another BO at that point.
>
> Do you have any ideas on what could be happening?

Apparently, when the VOP is re-enabled, it will start scanning from
the framebuffer address that had been set last.

Because DMA addresses are recycled and there's going to be a low
number of framebuffers, this isn't going to be obvious unless we make
sure that there isn't a FB allocated at that DMA address any more.

The attached test case does just that.

Regards,

Tomeu

> Thanks,
>
> Tomeu
>
>> drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -503,6 +503,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
>> if (!vop->is_enabled)
>> return;
>>  +   vop_crtc_wait_for_update(crtc);
>> +
>> drm_crtc_vblank_off(crtc);
>>
>> Thanks.
>>
>> --
>> Mark Yao
>>
>>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

__attribute__((format(printf, 1, 2)))
static void kmsg(const char *format, ...)
#define KERN_EM

Re: [PATCH v15 1/3] drm: rockchip: Add basic drm driver

2016-03-18 Thread Tomeu Vizoso
On 16 March 2016 at 16:23, Tomeu Vizoso  wrote:
> On 15 March 2016 at 02:30, Mark yao  wrote:
>> On 2016年03月14日 21:35, Tomeu Vizoso wrote:
>>>
>>> On 2 December 2014 at 10:15, Mark Yao  wrote:
>>>>
>>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> new file mode 100644
>>>> index 000..e7ca25b
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> @@ -0,0 +1,1455 @@
>>>
>>> ...
>>>>
>>>> +static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
>>>> +   const struct drm_display_mode *mode,
>>>> +   struct drm_display_mode *adjusted_mode)
>>>> +{
>>>> +   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
>>>> +   return false;
>>>
>>> Hi Mark,
>>>
>>> what's the rationale for this?
>>>
>>> Disabling a CRTC as in [0] will cause mode_fixup() to be called with
>>> an empty mode, failing that test.
>>>
>>> Removing the check seems to get things working fine for a short while,
>>> but a later modeset invariably gets the VOP to hang (as reported by
>>> [1]).
>>>
>>> Do you know why that check was put in place and what exactly could be
>>> causing the hw to hang?
>>>
>>> [0]
>>> https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/lib/igt_kms.c#n1616
>>> [1]
>>> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop.c#n873
>>>
>>> Thanks,
>>>
>>> Tomeu
>>>
>> Hi Tomeu
>>
>> Just thinking that "adjusted_mode->htotal == 0 || adjusted_mode->vtotal ==
>> 0" is not a good mode for vop.
>
> Ah, ok. Guess it should be removed then so we don't break userspace?
>
>> And you said VOP hang, only WARN_ON error message? or system hang, die?
>
> Sorry, the symptom was only the warning, I just went a bit too far and
> assumed the VOP had stopped working at all.
>
>> I think maybe crtc disable too fast, vblank is off, then no one can feed the
>> wait_update_complete.
>> Can you test it again with following patch?
>
> Actually, in today's testing I don't see that happening any more,
> sorry about that :/
>
> What I have been looking at today is a related issue when running the
> kms_flip_event_leak test from intel-gpu-tools. If I remove the check
> mentioned above so CRTCs can be disabled with the SetCRTC IOCTL, I see
> this page fault the second and subsequent times I run the test.
>
> [   75.809031] rk_iommu ff930300.iommu: Page fault at 0x0100 of type read
> [   75.809035] rk_iommu ff930300.iommu: iova = 0x0100: dte_index:
> 0x4 pte_index: 0x0 page_offset: 0x0
> [   75.809040] rk_iommu ff930300.iommu: mmu_dte_addr: 0x2c258000
> dte@0x2c258010: 0x2c561001 valid: 1 pte@0x2c561000: 0x2a06 valid:
> 0 page@0x flags: 0x0
> [   76.951288] rk_iommu ff930300.iommu: Enable stall request timed
> out, status: 0x4b
>
> I have written a smaller standalone test that is attached in case you
> want to check it out, but I haven't been able to find out why it only
> happens when the test is rerun.
>
> Apparently the VOP is still trying to read a BO (0x0100) right
> when the kernel frees it, but from what I can see, it should be
> scanning another BO at that point.
>
> Do you have any ideas on what could be happening?

Apparently, when the VOP is re-enabled, it will start scanning from
the framebuffer address that had been set last.

Because DMA addresses are recycled and there's going to be a low
number of framebuffers, this isn't going to be obvious unless we make
sure that there isn't a FB allocated at that DMA address any more.

The attached test case does just that.

Regards,

Tomeu

> Thanks,
>
> Tomeu
>
>> drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -503,6 +503,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
>> if (!vop->is_enabled)
>> return;
>>  +   vop_crtc_wait_for_update(crtc);
>> +
>> drm_crtc_vblank_off(crtc);
>>
>> Thanks.
>>
>> --
>> Mark Yao
>>
>>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

__attribute__((format(printf, 1, 2)))
static void kmsg(const char *format, ...)
#define KERN_EMER	"<0>"
#define KERN_ALERT	"<1>"
#define KERN_CRIT	"&

Re: [PATCH v3 0/8] arm64: rockchip: Initial GeekBox enablement

2016-03-15 Thread Tomeu Vizoso
On 14 March 2016 at 17:20, Giuseppe CAVALLARO <peppe.cavall...@st.com> wrote:
> Hi Tomeu
>
> On 3/14/2016 12:43 PM, Tomeu Vizoso wrote:
>>
>> Hi Peppe,
>>
>> with that patch I don't see any difference at all in my setup.
>>
>> So to be clear, with these commits on top of next-20160314, I still
>> get the hang during boot:
>>
>> 209afef6f0cd ARM: dts: rockchip: Add mdio node to ethernet node
>> 2315acc6cf7f Revert "stmmac: first frame prep at the end of xmit routine"
>> b5e08e810c63 stmmac: fix tx prepare for normal desc
>> 37c15a31d850 i2c: immediately mark ourselves as registered
>> 4342eec3c5a2 Add linux-next specific files for 20160314
>>
>> [   27.521026] WARNING: CPU: 1 PID: 0 at net/sched/sch_generic.c:303
>> dev_watchdog+0x284/0x288
>> [   27.529460] NETDEV WATCHDOG: eth0 (rk_gmac-dwmac): transmit queue 0
>> timed out
>
>
> I do not reproduce the WATCHDOG but i am continuing to look at the code
> to understand if normal descriptor management is ok or not. I keep you
> informed.
>
> Just an info, did you test with 2315acc6cf7f included? Just to
> understand if it is introducing a problem. It works in case of
> enhanced descriptors are used instead of.
>
>>
>>
>> https://git.collabora.com/cgit/user/tomeu/linux.git/log/?h=broken-eth-on-rock2
>
>
> thx I will take a look at this

Thanks.

Btw, I have rebased on top of 4.5 this morning and I have noticed that
88f8b1bb41c6 ("stmmac: Fix 'eth0: No PHY found' regression") got in
there, so I guess we have now a bunch of boards with broken network on
that release :(

Regards,

Tomeu

> Regards
> Peppe
>
>


Re: [PATCH v3 0/8] arm64: rockchip: Initial GeekBox enablement

2016-03-15 Thread Tomeu Vizoso
On 14 March 2016 at 17:20, Giuseppe CAVALLARO  wrote:
> Hi Tomeu
>
> On 3/14/2016 12:43 PM, Tomeu Vizoso wrote:
>>
>> Hi Peppe,
>>
>> with that patch I don't see any difference at all in my setup.
>>
>> So to be clear, with these commits on top of next-20160314, I still
>> get the hang during boot:
>>
>> 209afef6f0cd ARM: dts: rockchip: Add mdio node to ethernet node
>> 2315acc6cf7f Revert "stmmac: first frame prep at the end of xmit routine"
>> b5e08e810c63 stmmac: fix tx prepare for normal desc
>> 37c15a31d850 i2c: immediately mark ourselves as registered
>> 4342eec3c5a2 Add linux-next specific files for 20160314
>>
>> [   27.521026] WARNING: CPU: 1 PID: 0 at net/sched/sch_generic.c:303
>> dev_watchdog+0x284/0x288
>> [   27.529460] NETDEV WATCHDOG: eth0 (rk_gmac-dwmac): transmit queue 0
>> timed out
>
>
> I do not reproduce the WATCHDOG but i am continuing to look at the code
> to understand if normal descriptor management is ok or not. I keep you
> informed.
>
> Just an info, did you test with 2315acc6cf7f included? Just to
> understand if it is introducing a problem. It works in case of
> enhanced descriptors are used instead of.
>
>>
>>
>> https://git.collabora.com/cgit/user/tomeu/linux.git/log/?h=broken-eth-on-rock2
>
>
> thx I will take a look at this

Thanks.

Btw, I have rebased on top of 4.5 this morning and I have noticed that
88f8b1bb41c6 ("stmmac: Fix 'eth0: No PHY found' regression") got in
there, so I guess we have now a bunch of boards with broken network on
that release :(

Regards,

Tomeu

> Regards
> Peppe
>
>


[PATCH v5 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-14 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define

[PATCH v5 6/6] platform/chrome: Register USB PD charger device

2016-03-14 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[PATCH v5 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-14 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso 
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 << 0) /* Commun

[PATCH v5 6/6] platform/chrome: Register USB PD charger device

2016-03-14 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso 
---

Changes in v5: None
Changes in v4: None
Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[PATCH v5 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-14 Thread Tomeu Vizoso
From: Sameer Nanda <sna...@chromium.org>

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Sameer Nanda <sna...@chromium.org>
Cc: Benson Leung <ble...@chromium.org>
Cc: Shawn Nematbakhsh <sha...@chromium.org>
---

Changes in v5:
- Fix type of variable passed to do_div.

Changes in v4:
- Declare size parameters in ec_command as size_t

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..7ba983286dc0
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+

[PATCH v5 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-14 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c792e116e621..aaccdde1c9d5 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result != EC_RES_SUCCESS)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[PATCH v5 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-14 Thread Tomeu Vizoso
From: Sameer Nanda 

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso 
Cc: Sameer Nanda 
Cc: Benson Leung 
Cc: Shawn Nematbakhsh 
---

Changes in v5:
- Fix type of variable passed to do_div.

Changes in v4:
- Declare size parameters in ec_command as size_t

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..7ba983286dc0
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+
+static enum power_supply_property cros_usb_pd_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+   POWER_SUPPLY_PROP_STATUS,
+  

[PATCH v5 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-14 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso 
---

Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c792e116e621..aaccdde1c9d5 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result != EC_RES_SUCCESS)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[PATCH v5 1/6] mfd: cros_ec: Add MKBP event support

2016-03-14 Thread Tomeu Vizoso
From: Vic Yang <victory...@google.com>

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang <victory...@chromium.org>
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung <ble...@chromium.org>
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Randall Spangler <rspang...@chromium.org>
Cc: Vincent Palatin <vpala...@chromium.org>
---

Changes in v5: None
Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ 

[PATCH v5 1/6] mfd: cros_ec: Add MKBP event support

2016-03-14 Thread Tomeu Vizoso
From: Vic Yang 

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang 
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung 
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso 
Cc: Randall Spangler 
Cc: Vincent Palatin 
---

Changes in v5: None
Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
+   ret

[PATCH v5 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-14 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

Thanks,

Tomeu

Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.
- Fix type of variable passed to do_div.

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.
- Declare size parameters in ec_command as size_t

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[PATCH v5 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-14 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index aaccdde1c9d5..97c287cfd0c0 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return -EPROTONOSUPPORT;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[PATCH v5 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-14 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

Thanks,

Tomeu

Changes in v5:
- Check explicitly for !EC_RES_SUCCESS as suggested by Benson Leung.
- Fix type of variable passed to do_div.

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.
- Declare size parameters in ec_command as size_t

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[PATCH v5 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-14 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso 
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index aaccdde1c9d5..97c287cfd0c0 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return -EPROTONOSUPPORT;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



Re: [PATCH v15 1/3] drm: rockchip: Add basic drm driver

2016-03-14 Thread Tomeu Vizoso
On 2 December 2014 at 10:15, Mark Yao  wrote:
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> new file mode 100644
> index 000..e7ca25b
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -0,0 +1,1455 @@
...
> +static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
> +   const struct drm_display_mode *mode,
> +   struct drm_display_mode *adjusted_mode)
> +{
> +   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
> +   return false;

Hi Mark,

what's the rationale for this?

Disabling a CRTC as in [0] will cause mode_fixup() to be called with
an empty mode, failing that test.

Removing the check seems to get things working fine for a short while,
but a later modeset invariably gets the VOP to hang (as reported by
[1]).

Do you know why that check was put in place and what exactly could be
causing the hw to hang?

[0] 
https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/lib/igt_kms.c#n1616
[1] 
https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop.c#n873

Thanks,

Tomeu

> +
> +   return true;
> +}


Re: [PATCH v15 1/3] drm: rockchip: Add basic drm driver

2016-03-14 Thread Tomeu Vizoso
On 2 December 2014 at 10:15, Mark Yao  wrote:
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> new file mode 100644
> index 000..e7ca25b
> --- /dev/null
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -0,0 +1,1455 @@
...
> +static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
> +   const struct drm_display_mode *mode,
> +   struct drm_display_mode *adjusted_mode)
> +{
> +   if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
> +   return false;

Hi Mark,

what's the rationale for this?

Disabling a CRTC as in [0] will cause mode_fixup() to be called with
an empty mode, failing that test.

Removing the check seems to get things working fine for a short while,
but a later modeset invariably gets the VOP to hang (as reported by
[1]).

Do you know why that check was put in place and what exactly could be
causing the hw to hang?

[0] 
https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/lib/igt_kms.c#n1616
[1] 
https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop.c#n873

Thanks,

Tomeu

> +
> +   return true;
> +}


Re: [PATCH v3 0/8] arm64: rockchip: Initial GeekBox enablement

2016-03-14 Thread Tomeu Vizoso
On 11 March 2016 at 10:09, Giuseppe CAVALLARO  wrote:
> On 3/10/2016 5:47 PM, Dinh Nguyen wrote:
>>
>> On Thu, Mar 10, 2016 at 3:13 AM, Giuseppe CAVALLARO
>>  wrote:
>>>
>>> On 3/9/2016 5:31 PM, Dinh Nguyen wrote:


 On Wed, Mar 9, 2016 at 8:53 AM, Giuseppe CAVALLARO
  wrote:
>
>
> Hi Tomeu, Dinh, Andreas
>
> I need a sum and help from you to go ahead on the
> tx timeout.
>
> The "stmmac: MDIO fixes" seems to be the candidate to
> fix the phy connection and I will send the V2 asap (Andreas' comment).
>
> So, supposing the probe is ok and phy is connected,
> I need your input ...
>
>Tomeu: after revering the 0e80bdc9a72d (stmmac: first frame
>   prep at the end of xmit routine) the network is
>   not stable and there is a timeout after a while.
>   The box has 3.50 with normal desc settings.
>
>Dinh: the network is ok, I wonder if you can share a boot
>  log just to understand if the normal or enhanced
>  descriptors are used.
>

 Here it is:
>>>
>>>
>>> ...


 [0.850523] stmmac - user ID: 0x10, Synopsys ID: 0x37
 [0.855570]  Ring mode enabled
 [0.858611]  DMA HW capability register supported
 [0.863128]  Enhanced/Alternate descriptors
 [0.867482]  Enabled extended descriptors
 [0.871482]  RX Checksum Offload Engine supported (type 2)
 [0.876948]  TX Checksum insertion supported
 [0.881204]  Enable RX Mitigation via HW Watchdog Timer
 [0.886863] socfpga-dwmac ff702000.ethernet eth0: No MDIO subnode
 found
 [0.899090] libphy: stmmac: probed
 [0.902484] eth0: PHY ID 00221611 at 4 IRQ POLL (stmmac-0:04) active
>>>
>>>
>>>
>>> Thx Dinh, so you are using the Enhanced/Alternate descriptors
>>> I am debugging on my side on a setup with normal descriptors, I let you
>>> know
>>>
>>
>> Doesn't the printout "Enhanced/Alternate descriptors"  mean that I'm using
>> Enhanced/Alternate descriptors?
>
>
> yes this means that you have the Databook 3.70a and, from the HW
> capability register, the driver will use the Enhanced/Alternate
> descriptors. This is the same HW I am using on my side where the
> stmmac is working fine.
>
> In the case where it is failing on net-next, although on Databook 3.50a,
> the HW  capability register says that there is no enhanced descriptors
> and the driver uses the normal ones.
>
> Tomeu, I kindly ask you to try the patch attached. I found a bug on Tx
> path for normal descriptors. Please let me know if this help.
> Also let me know if we actually need to revert the 0e80bdc9a72d.

Hi Peppe,

with that patch I don't see any difference at all in my setup.

So to be clear, with these commits on top of next-20160314, I still
get the hang during boot:

209afef6f0cd ARM: dts: rockchip: Add mdio node to ethernet node
2315acc6cf7f Revert "stmmac: first frame prep at the end of xmit routine"
b5e08e810c63 stmmac: fix tx prepare for normal desc
37c15a31d850 i2c: immediately mark ourselves as registered
4342eec3c5a2 Add linux-next specific files for 20160314

[   27.521026] WARNING: CPU: 1 PID: 0 at net/sched/sch_generic.c:303
dev_watchdog+0x284/0x288
[   27.529460] NETDEV WATCHDOG: eth0 (rk_gmac-dwmac): transmit queue 0 timed out

https://git.collabora.com/cgit/user/tomeu/linux.git/log/?h=broken-eth-on-rock2

> I am trying to find some HW where test the normal descriptors to
> speed-up the tests on my side directly.

Maybe get your tree in kernelci.org? I'm not sure if it's currently
doing any nfsroot boots, though.

Regards,

Tomeu

> Let me know and thx in advance.
>
> Regards,
> Peppe
>
>>
>> Dinh
>>
>


Re: [PATCH v3 0/8] arm64: rockchip: Initial GeekBox enablement

2016-03-14 Thread Tomeu Vizoso
On 11 March 2016 at 10:09, Giuseppe CAVALLARO  wrote:
> On 3/10/2016 5:47 PM, Dinh Nguyen wrote:
>>
>> On Thu, Mar 10, 2016 at 3:13 AM, Giuseppe CAVALLARO
>>  wrote:
>>>
>>> On 3/9/2016 5:31 PM, Dinh Nguyen wrote:


 On Wed, Mar 9, 2016 at 8:53 AM, Giuseppe CAVALLARO
  wrote:
>
>
> Hi Tomeu, Dinh, Andreas
>
> I need a sum and help from you to go ahead on the
> tx timeout.
>
> The "stmmac: MDIO fixes" seems to be the candidate to
> fix the phy connection and I will send the V2 asap (Andreas' comment).
>
> So, supposing the probe is ok and phy is connected,
> I need your input ...
>
>Tomeu: after revering the 0e80bdc9a72d (stmmac: first frame
>   prep at the end of xmit routine) the network is
>   not stable and there is a timeout after a while.
>   The box has 3.50 with normal desc settings.
>
>Dinh: the network is ok, I wonder if you can share a boot
>  log just to understand if the normal or enhanced
>  descriptors are used.
>

 Here it is:
>>>
>>>
>>> ...


 [0.850523] stmmac - user ID: 0x10, Synopsys ID: 0x37
 [0.855570]  Ring mode enabled
 [0.858611]  DMA HW capability register supported
 [0.863128]  Enhanced/Alternate descriptors
 [0.867482]  Enabled extended descriptors
 [0.871482]  RX Checksum Offload Engine supported (type 2)
 [0.876948]  TX Checksum insertion supported
 [0.881204]  Enable RX Mitigation via HW Watchdog Timer
 [0.886863] socfpga-dwmac ff702000.ethernet eth0: No MDIO subnode
 found
 [0.899090] libphy: stmmac: probed
 [0.902484] eth0: PHY ID 00221611 at 4 IRQ POLL (stmmac-0:04) active
>>>
>>>
>>>
>>> Thx Dinh, so you are using the Enhanced/Alternate descriptors
>>> I am debugging on my side on a setup with normal descriptors, I let you
>>> know
>>>
>>
>> Doesn't the printout "Enhanced/Alternate descriptors"  mean that I'm using
>> Enhanced/Alternate descriptors?
>
>
> yes this means that you have the Databook 3.70a and, from the HW
> capability register, the driver will use the Enhanced/Alternate
> descriptors. This is the same HW I am using on my side where the
> stmmac is working fine.
>
> In the case where it is failing on net-next, although on Databook 3.50a,
> the HW  capability register says that there is no enhanced descriptors
> and the driver uses the normal ones.
>
> Tomeu, I kindly ask you to try the patch attached. I found a bug on Tx
> path for normal descriptors. Please let me know if this help.
> Also let me know if we actually need to revert the 0e80bdc9a72d.

Hi Peppe,

with that patch I don't see any difference at all in my setup.

So to be clear, with these commits on top of next-20160314, I still
get the hang during boot:

209afef6f0cd ARM: dts: rockchip: Add mdio node to ethernet node
2315acc6cf7f Revert "stmmac: first frame prep at the end of xmit routine"
b5e08e810c63 stmmac: fix tx prepare for normal desc
37c15a31d850 i2c: immediately mark ourselves as registered
4342eec3c5a2 Add linux-next specific files for 20160314

[   27.521026] WARNING: CPU: 1 PID: 0 at net/sched/sch_generic.c:303
dev_watchdog+0x284/0x288
[   27.529460] NETDEV WATCHDOG: eth0 (rk_gmac-dwmac): transmit queue 0 timed out

https://git.collabora.com/cgit/user/tomeu/linux.git/log/?h=broken-eth-on-rock2

> I am trying to find some HW where test the normal descriptors to
> speed-up the tests on my side directly.

Maybe get your tree in kernelci.org? I'm not sure if it's currently
doing any nfsroot boots, though.

Regards,

Tomeu

> Let me know and thx in advance.
>
> Regards,
> Peppe
>
>>
>> Dinh
>>
>


Re: [PATCH v3 0/8] arm64: rockchip: Initial GeekBox enablement

2016-03-09 Thread Tomeu Vizoso
On 9 March 2016 at 11:27, Giuseppe CAVALLARO  wrote:
> Hello Tomeu, Andreas,
>
> On 3/9/2016 10:52 AM, Giuseppe CAVALLARO wrote:
>>>
>>> * today's linux-next: probe failed
>>>
>>> * today's linux-next + revert of 88f8b1bb41c6 stmmac: Fix 'eth0: No
>>> PHY found' regression: probe succeeded but no network at all
>>>
>>> * today's linux-next + revert of 88f8b1bb41c6 (stmmac: Fix 'eth0: No
>>> PHY found' regression) + revert of 0e80bdc9a72d (stmmac: first frame
>>> prep at the end of xmit routine): probe succeeded, dhcp succeeds and
>>> nfsroot works for a few seconds before timing out
>>
>>
>> ok, I was looking at this problem now that seems to related
>> the "stmmac: first frame prep at the end of xmit routine"
>> that, at first glance, is breaking the gmac 3.50 with normal descriptor.
>
>
> I have no Hw where to test this use case. So, I wonder if may I ask you to
> test some patch.
>
> This first patch adds a missing barrier to the normal routine that inits the
> descriptor. Barrier was needed to well manage the OWN
> descriptor and it was not added in case of normal desc case after
> the xmit rework.
>
> Then I will check the algo behind the new xmit and in case of problems,
> if you agree, we will decide to revert it because it aimed to add an
> optimization.
>
> Let me know if you agree.

I'm not sure what you would like to be tested, but just in case, I
have just tried your patch on top of these commits and the result is
the "transmit queue 0 timed out" error during boot:

6542b30d0a67 Revert "stmmac: first frame prep at the end of xmit routine"
eb5274cbc0f7 Revert "stmmac: do not poll phy handler when attach a switch"
e88e625a68d9 Revert "stmmac: fix phy init when attached to a phy"
ef5dd3777876 stmmac: fix MDIO settings
77634ba1f25c Revert "stmmac: Fix 'eth0: No PHY found' regression"
7811b4ffc312 Add linux-next specific files for 20160309

Regards,

Tomeu

> Regards
> Peppe


Re: [PATCH v3 0/8] arm64: rockchip: Initial GeekBox enablement

2016-03-09 Thread Tomeu Vizoso
On 9 March 2016 at 11:27, Giuseppe CAVALLARO  wrote:
> Hello Tomeu, Andreas,
>
> On 3/9/2016 10:52 AM, Giuseppe CAVALLARO wrote:
>>>
>>> * today's linux-next: probe failed
>>>
>>> * today's linux-next + revert of 88f8b1bb41c6 stmmac: Fix 'eth0: No
>>> PHY found' regression: probe succeeded but no network at all
>>>
>>> * today's linux-next + revert of 88f8b1bb41c6 (stmmac: Fix 'eth0: No
>>> PHY found' regression) + revert of 0e80bdc9a72d (stmmac: first frame
>>> prep at the end of xmit routine): probe succeeded, dhcp succeeds and
>>> nfsroot works for a few seconds before timing out
>>
>>
>> ok, I was looking at this problem now that seems to related
>> the "stmmac: first frame prep at the end of xmit routine"
>> that, at first glance, is breaking the gmac 3.50 with normal descriptor.
>
>
> I have no Hw where to test this use case. So, I wonder if may I ask you to
> test some patch.
>
> This first patch adds a missing barrier to the normal routine that inits the
> descriptor. Barrier was needed to well manage the OWN
> descriptor and it was not added in case of normal desc case after
> the xmit rework.
>
> Then I will check the algo behind the new xmit and in case of problems,
> if you agree, we will decide to revert it because it aimed to add an
> optimization.
>
> Let me know if you agree.

I'm not sure what you would like to be tested, but just in case, I
have just tried your patch on top of these commits and the result is
the "transmit queue 0 timed out" error during boot:

6542b30d0a67 Revert "stmmac: first frame prep at the end of xmit routine"
eb5274cbc0f7 Revert "stmmac: do not poll phy handler when attach a switch"
e88e625a68d9 Revert "stmmac: fix phy init when attached to a phy"
ef5dd3777876 stmmac: fix MDIO settings
77634ba1f25c Revert "stmmac: Fix 'eth0: No PHY found' regression"
7811b4ffc312 Add linux-next specific files for 20160309

Regards,

Tomeu

> Regards
> Peppe


[PATCH v4 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-08 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

Thanks,

Tomeu

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.
- Declare size parameters in ec_command as size_t

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[PATCH v4 6/6] platform/chrome: Register USB PD charger device

2016-03-08 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v4: None
Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[PATCH v4 1/6] mfd: cros_ec: Add MKBP event support

2016-03-08 Thread Tomeu Vizoso
From: Vic Yang <victory...@google.com>

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang <victory...@chromium.org>
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung <ble...@chromium.org>
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Randall Spangler <rspang...@chromium.org>
Cc: Vincent Palatin <vpala...@chromium.org>
---

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ 

[PATCH v4 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-08 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

Thanks,

Tomeu

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.
- Declare size parameters in ec_command as size_t

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[PATCH v4 6/6] platform/chrome: Register USB PD charger device

2016-03-08 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso 
---

Changes in v4: None
Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[PATCH v4 1/6] mfd: cros_ec: Add MKBP event support

2016-03-08 Thread Tomeu Vizoso
From: Vic Yang 

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang 
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung 
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso 
Cc: Randall Spangler 
Cc: Vincent Palatin 
---

Changes in v4:
- Calculate correctly the size of the payloads in
  cros_ec_get_host_command_version_mask.

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
+   ret

[PATCH v4 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-08 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 <

[PATCH v4 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-08 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 << 0) /* Communication enabled */
+#d

[PATCH v4 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-08 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index e45d6750bbdf..bbcced87e46c 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return -EPROTONOSUPPORT;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[PATCH v4 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-08 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c792e116e621..e45d6750bbdf 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[PATCH v4 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-08 Thread Tomeu Vizoso
From: Sameer Nanda <sna...@chromium.org>

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Sameer Nanda <sna...@chromium.org>
Cc: Benson Leung <ble...@chromium.org>
Cc: Shawn Nematbakhsh <sha...@chromium.org>
---

Changes in v4:
- Declare size parameters in ec_command as size_t

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..b9ca6abc8dbf
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+
+static enum power_supply_property cros

[PATCH v4 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-08 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c792e116e621..e45d6750bbdf 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[PATCH v4 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-08 Thread Tomeu Vizoso
From: Sameer Nanda 

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso 
Cc: Sameer Nanda 
Cc: Benson Leung 
Cc: Shawn Nematbakhsh 
---

Changes in v4:
- Declare size parameters in ec_command as size_t

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..b9ca6abc8dbf
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+
+static enum power_supply_property cros_usb_pd_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+   POWER_SUPPLY_PROP_STATUS,
+   POWER_SUPPLY_PROP_CURRENT_MAX,
+   POWER_

[PATCH v4 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-08 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index e45d6750bbdf..bbcced87e46c 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return -EPROTONOSUPPORT;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[RESEND PATCH v3 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-02 Thread Tomeu Vizoso
From: Sameer Nanda <sna...@chromium.org>

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Sameer Nanda <sna...@chromium.org>
Cc: Benson Leung <ble...@chromium.org>
Cc: Shawn Nematbakhsh <sha...@chromium.org>
---

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..2c05f0545a57
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+
+static enum power_supply_property cros_usb_pd_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+   POW

[RESEND PATCH v3 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-02 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 00beacbf7645..c95d68dee3c9 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[RESEND PATCH v3 6/6] platform/chrome: Register USB PD charger device

2016-03-02 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[RESEND PATCH v3 5/6] power: cros_usbpd-charger: Add EC-based USB PD charger driver

2016-03-02 Thread Tomeu Vizoso
From: Sameer Nanda 

This driver exposes the charger functionality in the PD EC to userspace.

Signed-off-by: Tomeu Vizoso 
Cc: Sameer Nanda 
Cc: Benson Leung 
Cc: Shawn Nematbakhsh 
---

Changes in v3:
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.

Changes in v2:
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.

 drivers/power/Kconfig  |  10 +
 drivers/power/Makefile |   1 +
 drivers/power/cros_usbpd-charger.c | 780 +
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/power/cros_usbpd-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13cc0c07..26355850d91b 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -502,6 +502,16 @@ config AXP20X_POWER
  This driver provides support for the power supply features of
  AXP20x PMIC.
 
+config CHARGER_CROS_USB_PD
+   tristate "Chrome OS EC based USB PD charger"
+   depends on MFD_CROS_EC
+   default y
+   help
+ Say Y here to enable Chrome OS EC based USB PD charger driver. This
+ driver gets various bits of information about what is connected to
+ USB PD ports from the EC and converts that into power_supply
+ properties.
+
 endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab55f8d7..b83685bfae61 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USB_PD)  += cros_usbpd-charger.o
diff --git a/drivers/power/cros_usbpd-charger.c 
b/drivers/power/cros_usbpd-charger.c
new file mode 100644
index ..2c05f0545a57
--- /dev/null
+++ b/drivers/power/cros_usbpd-charger.c
@@ -0,0 +1,780 @@
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CROS_USB_PD_MAX_PORTS  8
+#define CROS_USB_PD_MAX_LOG_ENTRIES30
+
+#define CROS_USB_PD_LOG_UPDATE_DELAY msecs_to_jiffies(6)
+#define CROS_USB_PD_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+
+/* Buffer + macro for building PDLOG string */
+#define BUF_SIZE 80
+#define APPEND_STRING(buf, len, str, ...) ((len) += \
+   snprintf((buf) + (len), max(BUF_SIZE - (len), 0), (str), ##__VA_ARGS__))
+
+#define CHARGER_DIR_NAME   "CROS_USB_PD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTHsizeof(CHARGER_DIR_NAME)
+
+#define MANUFACTURER_MODEL_LENGTH  32
+
+struct port_data {
+   int port_number;
+   char name[CHARGER_DIR_NAME_LENGTH];
+   char manufacturer[MANUFACTURER_MODEL_LENGTH];
+   char model_name[MANUFACTURER_MODEL_LENGTH];
+   struct power_supply *psy;
+   struct power_supply_desc psy_desc;
+   int psy_type;
+   int psy_online;
+   int psy_status;
+   int psy_current_max;
+   int psy_voltage_max_design;
+   int psy_voltage_now;
+   int psy_power_max;
+   struct charger_data *charger;
+   unsigned long last_update;
+};
+
+struct charger_data {
+   struct device *dev;
+   struct cros_ec_dev *ec_dev;
+   struct cros_ec_device *ec_device;
+   int num_charger_ports;
+   int num_registered_psy;
+   struct port_data *ports[CROS_USB_PD_MAX_PORTS];
+   struct delayed_work log_work;
+   struct workqueue_struct *log_workqueue;
+   struct notifier_block notifier;
+   bool suspended;
+};
+
+static enum power_supply_property cros_usb_pd_charger_props[] = {
+   POWER_SUPPLY_PROP_ONLINE,
+   POWER_SUPPLY_PROP_STATUS,
+   POWER_SUPPLY_PROP_CURRENT_MAX,
+   POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+  

[RESEND PATCH v3 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-03-02 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso 
---

Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 00beacbf7645..c95d68dee3c9 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



[RESEND PATCH v3 6/6] platform/chrome: Register USB PD charger device

2016-03-02 Thread Tomeu Vizoso
Check if a EC has andy PD ports and register a USB PD charger device if
so.

Signed-off-by: Tomeu Vizoso 
---

Changes in v3:
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

 drivers/platform/chrome/cros_ec_dev.c | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c 
b/drivers/platform/chrome/cros_ec_dev.c
index d45cd254ed1c..b1251f4a04c1 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "cros_ec_dev.h"
 
@@ -87,6 +88,30 @@ exit:
return ret;
 }
 
+static int cros_ec_has_usb_pd_ports(struct cros_ec_dev *ec)
+{
+   struct cros_ec_command *msg;
+   struct ec_response_usb_pd_ports *resp;
+   int ret;
+
+   msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->version = 0;
+   msg->command = EC_CMD_USB_PD_PORTS + ec->cmd_offset;
+   msg->insize = sizeof(struct ec_response_usb_pd_ports);
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+   resp = (struct ec_response_usb_pd_ports *)msg->data;
+   ret = ret >= 0 && msg->result == EC_RES_SUCCESS && resp->num_ports;
+
+   kfree(msg);
+
+   return ret;
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -217,6 +242,13 @@ static void __remove(struct device *dev)
kfree(ec);
 }
 
+static const struct mfd_cell cros_usb_pd_charger_devs[] = {
+   {
+   .name = "cros-usb-pd-charger",
+   .id   = -1,
+   },
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
int retval = -ENOMEM;
@@ -269,8 +301,20 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
 
+   if (cros_ec_has_usb_pd_ports(ec)) {
+   retval = mfd_add_devices(dev, 0, cros_usb_pd_charger_devs,
+ARRAY_SIZE(cros_usb_pd_charger_devs),
+NULL, 0, NULL);
+   if (retval) {
+   dev_err(dev, "failed to add usb-pd-charger device\n");
+   goto pd_reg_failed;
+   }
+   }
+
return 0;
 
+pd_reg_failed:
+   put_device(>class_dev);
 dev_reg_failed:
 set_named_failed:
dev_set_drvdata(dev, NULL);
-- 
2.5.0



[RESEND PATCH v3 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-02 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c95d68dee3c9..65e285dc3bef 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return -EPROTONOSUPPORT;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[RESEND PATCH v3 1/6] mfd: cros_ec: Add MKBP event support

2016-03-02 Thread Tomeu Vizoso
From: Vic Yang <victory...@google.com>

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang <victory...@chromium.org>
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung <ble...@chromium.org>
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Randall Spangler <rspang...@chromium.org>
Cc: Vincent Palatin <vpala...@chromium.org>
---

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.even

[RESEND PATCH v3 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-02 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 << 0) /* Communicat

[RESEND PATCH v3 3/6] mfd: cros_ec: Add cros_ec_get_host_event

2016-03-02 Thread Tomeu Vizoso
This function returns the code for the host event that triggered the
interrupt that is being currently handled.

Is to be used by observers of the event_notifier in the EC device.

Signed-off-by: Tomeu Vizoso 
---

Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 23 +++
 include/linux/mfd/cros_ec.h | 10 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index c95d68dee3c9..65e285dc3bef 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -486,3 +486,26 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+
+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
+{
+   u32 host_event;
+
+   if (!ec_dev->mkbp_event_supported) {
+   dev_warn(ec_dev->dev,
+"This EC does not support EC_MKBP_EVENT_HOST_EVENT");
+   return -EPROTONOSUPPORT;
+   }
+
+   if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
+   return 0;
+
+   if (ec_dev->event_size != sizeof(host_event)) {
+   dev_warn(ec_dev->dev, "Invalid host event size\n");
+   return 0;
+   }
+
+   host_event = get_unaligned_le32(_dev->event_data.data.host_event);
+   return host_event;
+}
+EXPORT_SYMBOL(cros_ec_get_host_event);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index b6961c717209..1ef98d41870b 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -304,6 +304,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_host_event - Return a mask of event set by the EC.
+ *
+ * Returns the mask of the event that caused the last interrupt to be raised.
+ *
+ * @ec_dev: Device to fetch event from
+ * @return event mask, 0 on error
+ */
+uint32_t cros_ec_get_host_event(struct cros_ec_device *ec_dev);
+
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
-- 
2.5.0



[RESEND PATCH v3 1/6] mfd: cros_ec: Add MKBP event support

2016-03-02 Thread Tomeu Vizoso
From: Vic Yang 

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang 
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung 
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso 
Cc: Randall Spangler 
Cc: Vincent Palatin 
---

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
+   return NOTIFY_DONE;
+   /*
+* If EC is not the wake source, discard key state changes during
+* suspend.
+

[RESEND PATCH v3 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-03-02 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso 
---

Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 << 0) /* Communication enabled */
+#d

[RESEND PATCH v3 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-02 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

Thanks,

Tomeu

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



[RESEND PATCH v3 0/6] EC-based USB Power Delivery support for Chrome machines

2016-03-02 Thread Tomeu Vizoso
Hi,

this series contains a driver that exposes a power_supply to userspace
representing a port that support USB PD charging.

Allows userspace to display to the user if the machine is charging and
on which port, and if another device is being charged by a port.

Thanks,

Tomeu

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.
- Use do_div so it builds on 32bit (suggested by 0-day kbuild bot).
- Remove sysfs attributes ext_current_lim and ext_voltage_lim because
  I don't know yet where they should be placed (and don't have HW to
  test them).
- Remove superfluous pre-allocated buffers ec_inbuf and ec_outbuf.
- Lots of misc comments from Stephen Boyd were addressed.
- Unregister notification listener in .remove callback.
- Only register the PD charger device if there are any PD ports in this
  EC.
- Dropped patch using EC_CMD_GET_FEATURES to decide whether to create a
  charger device because we are now only creating one if a EC has any PD
  ports.
- Dropped patch adding power_supply types because it has been merged
  already.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.
- Split out changes to cros_ec_commands.h and the helpers added to
  mfd/cros_ec.h from the patch that adds the charger driver, as
  suggested by Lee.
- Actually call get_ec_num_ports.
- Move cros_ec_usb_pd_charger_register into cros_ec_dev.c.

Sameer Nanda (1):
  power: cros_usbpd-charger: Add EC-based USB PD charger driver

Tomeu Vizoso (4):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
  mfd: cros_ec: Add cros_ec_get_host_event
  mfd: cros_ec: Add more definitions for PD commands
  platform/chrome: Register USB PD charger device

Vic Yang (1):
  mfd: cros_ec: Add MKBP event support

 drivers/input/keyboard/cros_ec_keyb.c   | 135 ++
 drivers/mfd/cros_ec.c   |  57 ++-
 drivers/platform/chrome/cros_ec_dev.c   |  44 ++
 drivers/platform/chrome/cros_ec_proto.c | 129 ++
 drivers/power/Kconfig   |  10 +
 drivers/power/Makefile  |   1 +
 drivers/power/cros_usbpd-charger.c  | 780 
 include/linux/mfd/cros_ec.h |  62 +++
 include/linux/mfd/cros_ec_commands.h| 358 ++-
 9 files changed, 1464 insertions(+), 112 deletions(-)
 create mode 100644 drivers/power/cros_usbpd-charger.c

-- 
2.5.0



Re: Re: [PATCH] PM / devfreq: tegra: Set freq in rate callback

2016-02-22 Thread Tomeu Vizoso
On 28 January 2016 at 05:14, MyungJoo Ham <myungjoo@samsung.com> wrote:
>> Hi Thierry,
>>
>> On 21 January 2016 at 02:54, Thierry Reding <thierry.red...@gmail.com> wrote:
>> > On Thu, Jan 21, 2016 at 08:52:26AM +0100, Tomeu Vizoso wrote:
> []
>> >> Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
>> >> Reported-by: Tyler Baker <tyler.ba...@linaro.org>
> []
>> >>
>> >
>> > I had noticed it recently but hadn't got around to look into it, thanks
>> > for fixing it.
>> >
>> > Tested-by: Thierry Reding <tred...@nvidia.com>
>> > Acked-by: Thierry Reding <tred...@nvidia.com>
>>
>> I don't see this patch in -next yet, so I'm guess it hasn't been
>> applied. Any chance you could pick it up? This issue is now
>> manifesting in mainline, and causing ton of noise in the boot reports.
>>
>> Cheers,
>>
>> Tyler
>
>
> Hey, the patch appeared at the mailing list a week ago.
> Linux 4.5-rc1 appeared 3 days ago.
> The fastest possible for mainline inclusion is 4.5-rc2 or 3.
>
> You cannot simply expect the patch to be included in the maiinline that fast.

Hi MyungJoo Ham,

the problem is that linux-next has been showing that error in
multi_v7_defconfig builds since your changes got there. This is so
annoying that people have been putting their tegra124 boards offline
in their CI labs until this gets fixed in linux-next.

Regards,

Tomeu


Re: Re: [PATCH] PM / devfreq: tegra: Set freq in rate callback

2016-02-22 Thread Tomeu Vizoso
On 28 January 2016 at 05:14, MyungJoo Ham  wrote:
>> Hi Thierry,
>>
>> On 21 January 2016 at 02:54, Thierry Reding  wrote:
>> > On Thu, Jan 21, 2016 at 08:52:26AM +0100, Tomeu Vizoso wrote:
> []
>> >> Signed-off-by: Tomeu Vizoso 
>> >> Reported-by: Tyler Baker 
> []
>> >>
>> >
>> > I had noticed it recently but hadn't got around to look into it, thanks
>> > for fixing it.
>> >
>> > Tested-by: Thierry Reding 
>> > Acked-by: Thierry Reding 
>>
>> I don't see this patch in -next yet, so I'm guess it hasn't been
>> applied. Any chance you could pick it up? This issue is now
>> manifesting in mainline, and causing ton of noise in the boot reports.
>>
>> Cheers,
>>
>> Tyler
>
>
> Hey, the patch appeared at the mailing list a week ago.
> Linux 4.5-rc1 appeared 3 days ago.
> The fastest possible for mainline inclusion is 4.5-rc2 or 3.
>
> You cannot simply expect the patch to be included in the maiinline that fast.

Hi MyungJoo Ham,

the problem is that linux-next has been showing that error in
multi_v7_defconfig builds since your changes got there. This is so
annoying that people have been putting their tegra124 boards offline
in their CI labs until this gets fixed in linux-next.

Regards,

Tomeu


Re: [PATCH v2 0/8] EC-based USB Power Delivery support for Chrome machines

2016-02-21 Thread Tomeu Vizoso
On 20 February 2016 at 17:22, Pavel Machek  wrote:
> Hi!
>
>> this series contains a driver that exposes a power_supply to userspace
>> representing a port that support USB PD charging.
>
> Well, if this is meant for userspace, should it add some
> documentation, too?

Hi Pavel, in v3 I have dropped any new sysfs attributes, so everything
exposed to userspace is already documented.

Thanks,

Tomeu

> Thanks,
> Pavel
>
> --
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) 
> http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Re: [PATCH v2 0/8] EC-based USB Power Delivery support for Chrome machines

2016-02-21 Thread Tomeu Vizoso
On 20 February 2016 at 17:22, Pavel Machek  wrote:
> Hi!
>
>> this series contains a driver that exposes a power_supply to userspace
>> representing a port that support USB PD charging.
>
> Well, if this is meant for userspace, should it add some
> documentation, too?

Hi Pavel, in v3 I have dropped any new sysfs attributes, so everything
exposed to userspace is already documented.

Thanks,

Tomeu

> Thanks,
> Pavel
>
> --
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) 
> http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


[PATCH v3 1/6] mfd: cros_ec: Add MKBP event support

2016-02-17 Thread Tomeu Vizoso
From: Vic Yang <victory...@google.com>

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang <victory...@chromium.org>
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung <ble...@chromium.org>
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
Cc: Randall Spangler <rspang...@chromium.org>
Cc: Vincent Palatin <vpala...@chromium.org>
---

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.even

[PATCH v3 1/6] mfd: cros_ec: Add MKBP event support

2016-02-17 Thread Tomeu Vizoso
From: Vic Yang 

Newer revisions of the ChromeOS EC add more events besides the keyboard
ones. So handle interrupts in the MFD driver and let consumers register
for notifications for the events they might care.

To keep backward compatibility, if the EC doesn't support MKBP event, we
fall back to the old MKBP key matrix host command.

Signed-off-by: Vic Yang 
[bleung: fixup some context changes going from v3.14 to v3.18]
Signed-off-by: Benson Leung 
[tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
Signed-off-by: Tomeu Vizoso 
Cc: Randall Spangler 
Cc: Vincent Palatin 
---

Changes in v3:
- Remove duplicated prototype of cros_ec_get_host_event.

Changes in v2:
- Allocate enough for the structs in cros_ec_get_host_command_version_mask,
  not their pointers.
- Allocate msg in the stack in get_next_event and
  get_keyboard_state_event, as suggested by Gwendal.

 drivers/input/keyboard/cros_ec_keyb.c   | 135 
 drivers/mfd/cros_ec.c   |  57 +-
 drivers/platform/chrome/cros_ec_proto.c |  92 ++
 include/linux/mfd/cros_ec.h |  34 
 include/linux/mfd/cros_ec_commands.h|  34 
 5 files changed, 245 insertions(+), 107 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..b891503143dc 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,6 +45,7 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
+ * @notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
unsigned int rows;
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
+   struct notifier_block notifier;
 };
 
 
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
*ckdev,
input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
*kb_state)
-{
-   int ret = 0;
-   struct cros_ec_command *msg;
-
-   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->version = 0;
-   msg->command = EC_CMD_MKBP_STATE;
-   msg->insize = ckdev->cols;
-   msg->outsize = 0;
-
-   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
-   if (ret < 0) {
-   dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
-   goto exit;
-   }
-
-   memcpy(kb_state, msg->data, ckdev->cols);
-exit:
-   kfree(msg);
-   return ret;
-}
-
-static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
+static int cros_ec_keyb_open(struct input_dev *dev)
 {
-   struct cros_ec_keyb *ckdev = data;
-   struct cros_ec_device *ec = ckdev->ec;
-   int ret;
-   uint8_t kb_state[ckdev->cols];
-
-   if (device_may_wakeup(ec->dev))
-   pm_wakeup_event(ec->dev, 0);
-
-   ret = cros_ec_keyb_get_state(ckdev, kb_state);
-   if (ret >= 0)
-   cros_ec_keyb_process(ckdev, kb_state, ret);
-   else
-   dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
 
-   return IRQ_HANDLED;
+   return blocking_notifier_chain_register(>ec->event_notifier,
+   >notifier);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
+static void cros_ec_keyb_close(struct input_dev *dev)
 {
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
 
-   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
-   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-   "cros_ec_keyb", ckdev);
+   blocking_notifier_chain_unregister(>ec->event_notifier,
+  >notifier);
 }
 
-static void cros_ec_keyb_close(struct input_dev *dev)
+static int cros_ec_keyb_work(struct notifier_block *nb,
+unsigned long queued_during_suspend, void *_notify)
 {
-   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-   struct cros_ec_device *ec = ckdev->ec;
+   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+ notifier);
 
-   free_irq(ec->irq, ckdev);
+   if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
+   return NOTIFY_DONE;
+   /*
+* If EC is not the wake source, discard key state changes during
+* suspend.
+

[PATCH v3 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-02-17 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 << 0) /* Communicat

[PATCH v3 4/6] mfd: cros_ec: Add more definitions for PD commands

2016-02-17 Thread Tomeu Vizoso
Copy a few structs and commands from the EC firmware headers so we can
communicate with the EC regarding PD functionality.

Signed-off-by: Tomeu Vizoso 
---

Changes in v3: None
Changes in v2: None

 include/linux/mfd/cros_ec_commands.h | 324 ++-
 1 file changed, 319 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index d86526f0bd8e..4f056d2747ff 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -286,6 +286,9 @@ enum host_event_code {
/* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21,
 
+   /* PD MCU triggering host event */
+   EC_HOST_EVENT_PD_MCU = 22,
+
/*
 * The high bit of the event mask is not used as a host event code.  If
 * it reads back as set, then the entire event mask should be
@@ -2273,6 +2276,13 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
 } __packed;
 
+struct ec_params_external_power_limit_v1 {
+   uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+   uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
+} __packed;
+
+#define EC_POWER_LIMIT_NONE 0x
+
 /*/
 /* Smart battery pass-through */
 
@@ -2527,8 +2537,6 @@ struct ec_params_reboot_ec {
  */
 #define EC_CMD_VERSION0 0xdc
 
-#endif  /* !__ACPI__ */
-
 /*/
 /*
  * PD commands
@@ -2538,16 +2546,51 @@ struct ec_params_reboot_ec {
 
 /* EC to PD MCU exchange status command */
 #define EC_CMD_PD_EXCHANGE_STATUS 0x100
+#define EC_VER_PD_EXCHANGE_STATUS 2
+
+enum pd_charge_state {
+   PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */
+   PD_CHARGE_NONE,  /* No charging allowed */
+   PD_CHARGE_5V,/* 5V charging only */
+   PD_CHARGE_MAX/* Charge at max voltage */
+};
 
 /* Status of EC being sent to PD */
+#define EC_STATUS_HIBERNATING  (1 << 0)
+
 struct ec_params_pd_status {
-   int8_t batt_soc; /* battery state of charge */
+   uint8_t status;   /* EC status */
+   int8_t batt_soc;  /* battery state of charge */
+   uint8_t charge_state; /* charging state (from enum pd_charge_state) */
 } __packed;
 
 /* Status of PD being sent back to EC */
+#define PD_STATUS_HOST_EVENT  (1 << 0) /* Forward host event to AP */
+#define PD_STATUS_IN_RW   (1 << 1) /* Running RW image */
+#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */
+#define PD_STATUS_TCPC_ALERT_0(1 << 3) /* Alert active in port 0 TCPC */
+#define PD_STATUS_TCPC_ALERT_1(1 << 4) /* Alert active in port 1 TCPC */
+#define PD_STATUS_TCPC_ALERT_2(1 << 5) /* Alert active in port 2 TCPC */
+#define PD_STATUS_TCPC_ALERT_3(1 << 6) /* Alert active in port 3 TCPC */
+#define PD_STATUS_EC_INT_ACTIVE  (PD_STATUS_TCPC_ALERT_0 | \
+ PD_STATUS_TCPC_ALERT_1 | \
+ PD_STATUS_HOST_EVENT)
 struct ec_response_pd_status {
-   int8_t status;/* PD MCU status */
-   uint32_t curr_lim_ma; /* input current limit */
+   uint32_t curr_lim_ma;   /* input current limit */
+   uint16_t status;/* PD MCU status */
+   int8_t active_charge_port;  /* active charging port */
+} __packed;
+
+/* AP to PD MCU host event status command, cleared on read */
+#define EC_CMD_PD_HOST_EVENT_STATUS 0x104
+
+/* PD MCU host event status bits */
+#define PD_EVENT_UPDATE_DEVICE (1 << 0)
+#define PD_EVENT_POWER_CHANGE  (1 << 1)
+#define PD_EVENT_IDENTITY_RECEIVED (1 << 2)
+#define PD_EVENT_DATA_SWAP (1 << 3)
+struct ec_response_host_event_status {
+   uint32_t status;  /* PD MCU host event status */
 } __packed;
 
 /* Set USB type-C port role and muxes */
@@ -2559,6 +2602,7 @@ enum usb_pd_control_role {
USB_PD_CTRL_ROLE_TOGGLE_OFF = 2,
USB_PD_CTRL_ROLE_FORCE_SINK = 3,
USB_PD_CTRL_ROLE_FORCE_SOURCE = 4,
+   USB_PD_CTRL_ROLE_COUNT
 };
 
 enum usb_pd_control_mux {
@@ -2568,14 +2612,284 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_DP = 3,
USB_PD_CTRL_MUX_DOCK = 4,
USB_PD_CTRL_MUX_AUTO = 5,
+   USB_PD_CTRL_MUX_COUNT
+};
+
+enum usb_pd_control_swap {
+   USB_PD_CTRL_SWAP_NONE = 0,
+   USB_PD_CTRL_SWAP_DATA = 1,
+   USB_PD_CTRL_SWAP_POWER = 2,
+   USB_PD_CTRL_SWAP_VCONN = 3,
+   USB_PD_CTRL_SWAP_COUNT
 };
 
 struct ec_params_usb_pd_control {
uint8_t port;
uint8_t role;
uint8_t mux;
+   uint8_t swap;
+} __packed;
+
+#define PD_CTRL_RESP_ENABLED_COMMS  (1 << 0) /* Communication enabled */
+#d

[PATCH v3 2/6] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

2016-02-17 Thread Tomeu Vizoso
So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com>
---

Changes in v3: None
Changes in v2: None

 drivers/platform/chrome/cros_ec_proto.c | 14 ++
 include/linux/mfd/cros_ec.h | 18 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 00beacbf7645..c95d68dee3c9 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -472,3 +472,17 @@ 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);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg)
+{
+   int ret = cros_ec_cmd_xfer(ec_dev, msg);
+
+   if (ret < 0)
+   dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+   else if (msg->result)
+   return -EECRESULT - msg->result;
+
+   return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 1f88418a36cf..b6961c717209 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD1
 #define EC_MAX_RESPONSE_OVERHEAD   2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -250,6 +253,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+   struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.5.0



<    1   2   3   4   5   6   7   8   9   10   >