Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH 1/5] m68k/io: Add missing ioremap define guards, fix typo
From: Geert Uytterhoeven @ 2018-07-09  9:30 UTC (permalink / raw)
  To: Greg Ungerer, Dmitry Torokhov, Helge Deller
  Cc: linux-m68k, netdev, linux-input, linux-kernel, Geert Uytterhoeven
In-Reply-To: <20180709093040.23597-1-geert@linux-m68k.org>

  - Add missing define guard for ioremap_wt(),
  - Move ARCH_HAS_IOREMAP_WT from <asm/io_mm.h> to <asm/kmap.h>, as it
    is applicable to Coldfire with MMU, too,
  - Fix typo s/ioremap_fillcache/ioremap_fullcache/,
  - Add define guard for iounmap() for consistency with other
    architectures.

Fixes: 9746882f547d2f00 ("m68k: group io mapping definitions and functions")
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
v2:
  - Move ARCH_HAS_IOREMAP_WT to fix "ioremap_wt redefined" warnings with
    m5475evb defconfig.
---
 arch/m68k/include/asm/io_mm.h | 2 --
 arch/m68k/include/asm/kmap.h  | 6 +++++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index fe485f4f5fac4d92..7e518303786c2d65 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -21,8 +21,6 @@
 
 #ifdef __KERNEL__
 
-#define ARCH_HAS_IOREMAP_WT
-
 #include <linux/compiler.h>
 #include <asm/raw_io.h>
 #include <asm/virtconvert.h>
diff --git a/arch/m68k/include/asm/kmap.h b/arch/m68k/include/asm/kmap.h
index 84b8333db8ad1987..608e12f058a7cd7d 100644
--- a/arch/m68k/include/asm/kmap.h
+++ b/arch/m68k/include/asm/kmap.h
@@ -4,6 +4,8 @@
 
 #ifdef CONFIG_MMU
 
+#define ARCH_HAS_IOREMAP_WT
+
 /* Values for nocacheflag and cmode */
 #define IOMAP_FULL_CACHING		0
 #define IOMAP_NOCACHE_SER		1
@@ -16,6 +18,7 @@
  */
 extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
 			       int cacheflag);
+#define iounmap iounmap
 extern void iounmap(void __iomem *addr);
 extern void __iounmap(void *addr, unsigned long size);
 
@@ -33,13 +36,14 @@ static inline void __iomem *ioremap_nocache(unsigned long physaddr,
 }
 
 #define ioremap_uc ioremap_nocache
+#define ioremap_wt ioremap_wt
 static inline void __iomem *ioremap_wt(unsigned long physaddr,
 				       unsigned long size)
 {
 	return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
 }
 
-#define ioremap_fillcache ioremap_fullcache
+#define ioremap_fullcache ioremap_fullcache
 static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
 					      unsigned long size)
 {
-- 
2.17.1

^ permalink raw reply related

* [PATCH 0/5] m68k: IO Fixes and Cleanups
From: Geert Uytterhoeven @ 2018-07-09  9:30 UTC (permalink / raw)
  To: Greg Ungerer, Dmitry Torokhov, Helge Deller
  Cc: linux-m68k, netdev, linux-input, linux-kernel, Geert Uytterhoeven

	Hi all,

This patch series contains fixes and cleanups for I/O accessors on m68k
platforms (with MMU).

The first patch contains small fixes without any dependencies.
Patches 2 and 3 make small adjustments to drivers that are dependencies
for further cleanup.
Patch 4 and 5 complete the cleanup.

Changes compared to v1:
  - Move ARCH_HAS_IOREMAP_WT to fix "ioremap_wt redefined" warnings with
    m5475evb defconfig,
  - Add Acked-by.

Given the dependencies, I think it's easiest if the respective
maintainers would provide their Acked-by, so all patches can go in
through the m68k tree.

Thanks!

Geert Uytterhoeven (5):
  m68k/io: Add missing ioremap define guards, fix typo
  net: mac8390: Use standard memcpy_{from,to}io()
  Input: hilkbd - Add casts to HP9000/300 I/O accessors
  m68k/io: Move mem*io define guards to <asm/kmap.h>
  m68k/io: Switch mmu variant to <asm-generic/io.h>

 arch/m68k/include/asm/io.h          |  7 +++++
 arch/m68k/include/asm/io_mm.h       | 42 +++--------------------------
 arch/m68k/include/asm/io_no.h       | 12 ---------
 arch/m68k/include/asm/kmap.h        |  9 ++++++-
 drivers/input/keyboard/hilkbd.c     |  4 +--
 drivers/net/ethernet/8390/mac8390.c | 20 +++++++-------
 6 files changed, 30 insertions(+), 64 deletions(-)

-- 
2.17.1

Gr{oetje,eeting}s,

						Geert

^ permalink raw reply

* Re: [PATCH v6 2/4] resource: Use list_head to link sibling resource
From: Baoquan He @ 2018-07-09  3:04 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Nicolas Pitre, brijesh.singh-5C7GfCeVMHo, Tom Lendacky,
	David Airlie, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w, Max Filippov,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/, Frank Rowand,
	Thomas Gleixner, Lorenzo Pieralisi, Stephen Hemminger,
	kbuild test robot, linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	Patrik Jakobsson, linux-input, Gustavo Padovan, Borislav Petkov,
	Dave Young, Eric Biederman, devicetree, Haiyang Zhang,
	Maarten Lankhorst, Josh Triplett
In-Reply-To: <CAHp75VcjGQutVtZ90C0huUGCY6yj8H0Wo0tMdrbLmLsRQ+x4XQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 07/08/18 at 08:48pm, Andy Shevchenko wrote:
> On Sun, Jul 8, 2018 at 5:59 AM, Baoquan He <bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > On 07/05/18 at 01:00am, kbuild test robot wrote:
> 
> > However, I didn't find below branch. And tried to open it in web
> > broswer, also failed.
> 
> While this is kinda valid point...
> 
> > Could you help have a look at this?
> 
> ...isn't obvious that you didn't change the file mentioned in a report?
> Just take latest linux-next and you will see.

Yes, it's clear to me. Just want to use the way to cross compile them on
ia64 and mips, hope I can find out all missed places on these ARCHes.
Now I think I can apply patches on linux-next, and use the config
attached to compile. Thanks.

> 
> 
> >> All error/warnings (new ones prefixed by >>):
> >>
> >> >> arch/mips/pci/pci-rc32434.c:57:11: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> >>      .child = &rc32434_res_pci_mem2
> >>               ^
> >>    arch/mips/pci/pci-rc32434.c:57:11: note: (near initialization for 'rc32434_res_pci_mem1.child.next')
> >> >> arch/mips/pci/pci-rc32434.c:51:47: warning: missing braces around initializer [-Wmissing-braces]
> >>     static struct resource rc32434_res_pci_mem1 = {
> >>                                                   ^
> >>    arch/mips/pci/pci-rc32434.c:60:47: warning: missing braces around initializer [-Wmissing-braces]
> >>     static struct resource rc32434_res_pci_mem2 = {
> >>                                                   ^
> >>    cc1: some warnings being treated as errors
> >>
> >> vim +57 arch/mips/pci/pci-rc32434.c
> >>
> >> 73b4390f Ralf Baechle 2008-07-16  50
> >> 73b4390f Ralf Baechle 2008-07-16 @51  static struct resource rc32434_res_pci_mem1 = {
> >> 73b4390f Ralf Baechle 2008-07-16  52          .name = "PCI MEM1",
> >> 73b4390f Ralf Baechle 2008-07-16  53          .start = 0x50000000,
> >> 73b4390f Ralf Baechle 2008-07-16  54          .end = 0x5FFFFFFF,
> >> 73b4390f Ralf Baechle 2008-07-16  55          .flags = IORESOURCE_MEM,
> >> 73b4390f Ralf Baechle 2008-07-16  56          .sibling = NULL,
> >> 73b4390f Ralf Baechle 2008-07-16 @57          .child = &rc32434_res_pci_mem2
> >> 73b4390f Ralf Baechle 2008-07-16  58  };
> >> 73b4390f Ralf Baechle 2008-07-16  59
> >>
> >> :::::: The code at line 57 was first introduced by commit
> >> :::::: 73b4390fb23456964201abda79f1210fe337d01a [MIPS] Routerboard 532: Support for base system
> >>
> >> :::::: TO: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
> >> :::::: CC: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
> >>
> >> ---
> >> 0-DAY kernel test infrastructure                Open Source Technology Center
> >> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
> >
> >
> 
> 
> 
> -- 
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply

* Re: [PATCH v6 2/4] resource: Use list_head to link sibling resource
From: Andy Shevchenko @ 2018-07-08 17:48 UTC (permalink / raw)
  To: Baoquan He
  Cc: Nicolas Pitre, brijesh.singh, Tom Lendacky, David Airlie,
	linux-pci, richard.weiyang, Keith Busch, Max Filippov, baiyaowei,
	Frank Rowand, Thomas Gleixner, Lorenzo Pieralisi,
	Stephen Hemminger, linux-nvdimm, Patrik Jakobsson, linux-input,
	Gustavo Padovan, Borislav Petkov, Dave Young, Vivek Goyal,
	Eric Biederman, devicetree, Haiyang Zhang, Maarten Lankhorst
In-Reply-To: <20180708025946.GI3047@MiWiFi-R3L-srv>

On Sun, Jul 8, 2018 at 5:59 AM, Baoquan He <bhe@redhat.com> wrote:
> On 07/05/18 at 01:00am, kbuild test robot wrote:

> However, I didn't find below branch. And tried to open it in web
> broswer, also failed.

While this is kinda valid point...

> Could you help have a look at this?

...isn't obvious that you didn't change the file mentioned in a report?
Just take latest linux-next and you will see.


>> All error/warnings (new ones prefixed by >>):
>>
>> >> arch/mips/pci/pci-rc32434.c:57:11: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
>>      .child = &rc32434_res_pci_mem2
>>               ^
>>    arch/mips/pci/pci-rc32434.c:57:11: note: (near initialization for 'rc32434_res_pci_mem1.child.next')
>> >> arch/mips/pci/pci-rc32434.c:51:47: warning: missing braces around initializer [-Wmissing-braces]
>>     static struct resource rc32434_res_pci_mem1 = {
>>                                                   ^
>>    arch/mips/pci/pci-rc32434.c:60:47: warning: missing braces around initializer [-Wmissing-braces]
>>     static struct resource rc32434_res_pci_mem2 = {
>>                                                   ^
>>    cc1: some warnings being treated as errors
>>
>> vim +57 arch/mips/pci/pci-rc32434.c
>>
>> 73b4390f Ralf Baechle 2008-07-16  50
>> 73b4390f Ralf Baechle 2008-07-16 @51  static struct resource rc32434_res_pci_mem1 = {
>> 73b4390f Ralf Baechle 2008-07-16  52          .name = "PCI MEM1",
>> 73b4390f Ralf Baechle 2008-07-16  53          .start = 0x50000000,
>> 73b4390f Ralf Baechle 2008-07-16  54          .end = 0x5FFFFFFF,
>> 73b4390f Ralf Baechle 2008-07-16  55          .flags = IORESOURCE_MEM,
>> 73b4390f Ralf Baechle 2008-07-16  56          .sibling = NULL,
>> 73b4390f Ralf Baechle 2008-07-16 @57          .child = &rc32434_res_pci_mem2
>> 73b4390f Ralf Baechle 2008-07-16  58  };
>> 73b4390f Ralf Baechle 2008-07-16  59
>>
>> :::::: The code at line 57 was first introduced by commit
>> :::::: 73b4390fb23456964201abda79f1210fe337d01a [MIPS] Routerboard 532: Support for base system
>>
>> :::::: TO: Ralf Baechle <ralf@linux-mips.org>
>> :::::: CC: Ralf Baechle <ralf@linux-mips.org>
>>
>> ---
>> 0-DAY kernel test infrastructure                Open Source Technology Center
>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>
>



-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH v6 2/4] resource: Use list_head to link sibling resource
From: Baoquan He @ 2018-07-08  2:59 UTC (permalink / raw)
  To: kbuild test robot
  Cc: nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, brijesh.singh-5C7GfCeVMHo,
	thomas.lendacky-5C7GfCeVMHo, airlied-cv59FeDIM0c,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w,
	jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	frowand.list-Re5JQEeQqe8AvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	lorenzo.pieralisi-5wv7dgnIgG8, sthemmin-0li6OtcxBFHby3iVrkZq2A,
	linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	patrik.r.jakobsson-Re5JQEeQqe8AvxtiuMwx3w,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	gustavo-THi1TnShQwVAfugRpC6u6w, bp-l3A5Bk7waGM,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA, ebiederm-aS9lmoZGLiVWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	haiyangz-0li6OtcxBFHby3iVrkZq2A,
	maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA,
	josh-iaAMLnmF4UmaiuxdJuQwMA, jglisse-H+wXaHxf7aLQT0dZR+AlfA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, yinghai-DgEjT+Ai2ygdnm+yROfE0A,
	jonathan.derrick-ral2JQCrhuEAvxtiuMwx3w,
	chris-YvXeqwSYzG2sTnJN9+BGXg, monstr-pSz03upnqPeHXe+LvDLADg,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-kernel
In-Reply-To: <201807042347.hfDcKxmG%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Hi,

On 07/05/18 at 01:00am, kbuild test robot wrote:
> Hi Baoquan,
> 
> I love your patch! Yet something to improve:
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.18-rc3 next-20180704]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

Thanks for telling. 

I cloned 0day-ci/linut to my local pc.
https://github.com/0day-ci/linux.git

However, I didn't find below branch. And tried to open it in web
broswer, also failed.


> url:    https://github.com/0day-ci/linux/commits/Baoquan-He/resource-Use-list_head-to-link-sibling-resource/20180704-121402
> config: mips-rb532_defconfig (attached as .config)
> compiler: mipsel-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.2.0 make.cross ARCH=mips 

I did find a old one which is for the old version 5 post.

[bhe@linux]$ git remote -v
0day-ci	https://github.com/0day-ci/linux.git (fetch)
0day-ci	https://github.com/0day-ci/linux.git (push)
[bhe@dhcp-128-28 linux]$ git branch -a| grep Baoquan| grep resource
  remotes/0day-ci/Baoquan-He/resource-Use-list_head-to-link-sibling-resource/20180612-113600

Could you help have a look at this?

Thanks
Baoquan

> 
> All error/warnings (new ones prefixed by >>):
> 
> >> arch/mips/pci/pci-rc32434.c:57:11: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
>      .child = &rc32434_res_pci_mem2
>               ^
>    arch/mips/pci/pci-rc32434.c:57:11: note: (near initialization for 'rc32434_res_pci_mem1.child.next')
> >> arch/mips/pci/pci-rc32434.c:51:47: warning: missing braces around initializer [-Wmissing-braces]
>     static struct resource rc32434_res_pci_mem1 = {
>                                                   ^
>    arch/mips/pci/pci-rc32434.c:60:47: warning: missing braces around initializer [-Wmissing-braces]
>     static struct resource rc32434_res_pci_mem2 = {
>                                                   ^
>    cc1: some warnings being treated as errors
> 
> vim +57 arch/mips/pci/pci-rc32434.c
> 
> 73b4390f Ralf Baechle 2008-07-16  50  
> 73b4390f Ralf Baechle 2008-07-16 @51  static struct resource rc32434_res_pci_mem1 = {
> 73b4390f Ralf Baechle 2008-07-16  52  	.name = "PCI MEM1",
> 73b4390f Ralf Baechle 2008-07-16  53  	.start = 0x50000000,
> 73b4390f Ralf Baechle 2008-07-16  54  	.end = 0x5FFFFFFF,
> 73b4390f Ralf Baechle 2008-07-16  55  	.flags = IORESOURCE_MEM,
> 73b4390f Ralf Baechle 2008-07-16  56  	.sibling = NULL,
> 73b4390f Ralf Baechle 2008-07-16 @57  	.child = &rc32434_res_pci_mem2
> 73b4390f Ralf Baechle 2008-07-16  58  };
> 73b4390f Ralf Baechle 2008-07-16  59  
> 
> :::::: The code at line 57 was first introduced by commit
> :::::: 73b4390fb23456964201abda79f1210fe337d01a [MIPS] Routerboard 532: Support for base system
> 
> :::::: TO: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
> :::::: CC: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply

* [PATCH] Input: synaptics - Lenovo ThinkPad T25 and T480 devices should use RMI
From: kitsunyan @ 2018-07-07  5:19 UTC (permalink / raw)
  Cc: kitsunyan, Dmitry Torokhov, Benjamin Tissoires, linux-input,
	linux-kernel

The touchpads on both T25 and T480 are accessible over SMBUS/RMI.

Signed-off-by: kitsunyan <kitsunyan@inbox.ru>
---
 drivers/input/mouse/synaptics.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 55d33500d55e..be934a082424 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -175,7 +175,9 @@ static const char * const smbus_pnp_ids[] = {
 	"LEN0071", /* T480 */
 	"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
 	"LEN0073", /* X1 Carbon G5 (Elantech) */
+	"LEN008e", /* T25 */
 	"LEN0092", /* X1 Carbon 6 */
+	"LEN0093", /* T480 */
 	"LEN0096", /* X280 */
 	"LEN0097", /* X280 -> ALPS trackpoint */
 	"LEN200f", /* T450s */
-- 
2.18.0

^ permalink raw reply related

* [PATCH] drivers: input: Add SPDX-License-Identifier
From: Christian Thoms @ 2018-07-06 12:11 UTC (permalink / raw)
  To: dmitry.torokhov, rydberg, linux-input, linux-kernel
  Cc: Christian Thoms, linux-kernel, Sebastian Hillert

Add the SPDX-License-Identifier marked by checkpatch.pl

Signed-off-by: Christian Thoms <christian.thoms93@gmail.com>
Signed-off-by: Sebastian Hillert <sebastian.hillert1@gmail.com>
---
 drivers/input/apm-power.c     | 6 +-----
 drivers/input/evbug.c         | 6 +-----
 drivers/input/evdev.c         | 5 +----
 drivers/input/ff-core.c       | 6 +-----
 drivers/input/ff-memless.c    | 6 +-----
 drivers/input/input-compat.c  | 5 +----
 drivers/input/input-leds.c    | 5 +----
 drivers/input/input-mt.c      | 5 +----
 drivers/input/input-polldev.c | 7 ++-----
 drivers/input/input.c         | 7 +------
 drivers/input/joydev.c        | 6 +-----
 drivers/input/matrix-keymap.c | 5 +----
 drivers/input/mousedev.c      | 5 +----
 drivers/input/sparse-keymap.c | 5 +----
 14 files changed, 15 insertions(+), 64 deletions(-)

diff --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c
index 650177a..dd413df 100644
--- a/drivers/input/apm-power.c
+++ b/drivers/input/apm-power.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  Input Power Event -> APM Bridge
  *
  *  Copyright (c) 2007 Richard Purdie
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- *
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index cd4e667..337c0ff 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
@@ -7,11 +8,6 @@
  */
 
 /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c81c79d..b8456e6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Event char devices, giving access to raw input device events.
  *
  * Copyright (c) 1999-2002 Vojtech Pavlik
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 66a46c8..3086166 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Force feedback support for Linux input subsystem
  *
@@ -6,11 +7,6 @@
  */
 
 /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 2743ed46..f25377d 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Force feedback support for memoryless devices
  *
@@ -6,11 +7,6 @@
  */
 
 /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
diff --git a/drivers/input/input-compat.c b/drivers/input/input-compat.c
index fda8d6d..435e9d1e 100644
--- a/drivers/input/input-compat.c
+++ b/drivers/input/input-compat.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * 32bit compatibility wrappers for the input subsystem.
  *
  * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
  */
 
 #include <linux/export.h>
diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c
index 99cc784..82b5ded 100644
--- a/drivers/input/input-leds.c
+++ b/drivers/input/input-leds.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * LED support for the input layer
  *
  * Copyright 2010-2015 Samuel Thibault <samuel.thibault@ens-lyon.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index cf30523..1c38816b 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Input Multitouch Library
  *
  * Copyright (c) 2008-2010 Henrik Rydberg
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
  */
 
 #include <linux/input/mt.h>
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 78df5a7..13d4219 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic implementation of a polled input device
-
- * Copyright (c) 2007 Dmitry Torokhov
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
+ * Copyright (c) 2007 Dmitry Torokhov
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 6365c19..de7bc24 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * The input core
  *
  * Copyright (c) 1999-2002 Vojtech Pavlik
  */
 
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
 #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
 
 #include <linux/init.h>
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 4c1e427..cb63628 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Joystick device driver for the input driver suite.
  *
  * Copyright (c) 1999-2002 Vojtech Pavlik
  * Copyright (c) 1999 Colin Van Dyke
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index 8b3a575..c2cc853 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Helpers for matrix keyboard bindings
  *
@@ -6,10 +7,6 @@
  * Author:
  *	Olof Johansson <olof@lixom.net>
  *
- * 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
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index e082280..6c61108 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Input driver to ExplorerPS/2 device driver module.
  *
  * Copyright (c) 1999-2002 Vojtech Pavlik
  * Copyright (c) 2004      Dmitry Torokhov
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
index 0cad5e7..54ec9a0 100644
--- a/drivers/input/sparse-keymap.c
+++ b/drivers/input/sparse-keymap.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic support for sparse keymaps
  *
@@ -7,10 +8,6 @@
  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
  */
 
 #include <linux/input.h>
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v10 1/2] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Lee Jones @ 2018-07-06 10:56 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: Enric Balletbo Serra, Michael Turquette, Rob Herring, sboyd,
	Mark Rutland, Liam Girdwood, Mark Brown, Matti Vaittinen,
	Arnd Bergmann, Dmitry Torokhov, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <20180706102312.GB11209@localhost.localdomain>

On Fri, 06 Jul 2018, Matti Vaittinen wrote:

> On Fri, Jul 06, 2018 at 07:09:13AM +0100, Lee Jones wrote:
> 
> [snip]
> '
> > page trying to find your response was a little painful.  TIA.
> 
> Acronyms can be confusing for non native english speakers like me.
> Luckily we have the internet =)
> 
> https://www.acronymfinder.com/Slang/TIA.html
> 
> From these options I would go for:
> "This Is Awkward" or "That Is Alright" - depending on my mood =] Or
> maybe it was "Today I Ate"?

Ha, fair point.

In this instance it means, "thanks in advance". :)

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v10 1/2] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Matti Vaittinen @ 2018-07-06 10:23 UTC (permalink / raw)
  To: Lee Jones
  Cc: Enric Balletbo Serra, Michael Turquette, Rob Herring, sboyd,
	Mark Rutland, Liam Girdwood, Mark Brown, Matti Vaittinen,
	Arnd Bergmann, Dmitry Torokhov, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <20180706060913.GU496@dell>

On Fri, Jul 06, 2018 at 07:09:13AM +0100, Lee Jones wrote:

[snip]
'
> page trying to find your response was a little painful.  TIA.

Acronyms can be confusing for non native english speakers like me.
Luckily we have the internet =)

https://www.acronymfinder.com/Slang/TIA.html

>From these options I would go for:
"This Is Awkward" or "That Is Alright" - depending on my mood =] Or
maybe it was "Today I Ate"?

--Matti

^ permalink raw reply

* Re: [PATCH v7 1/4] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Matti Vaittinen @ 2018-07-06  7:49 UTC (permalink / raw)
  To: Lee Jones
  Cc: Dmitry Torokhov, Enric Balletbo Serra, Michael Turquette, sboyd,
	Rob Herring, Mark Rutland, Liam Girdwood, Mark Brown,
	Matti Vaittinen, Arnd Bergmann, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <20180706070559.GW496@dell>

On Fri, Jul 06, 2018 at 08:05:59AM +0100, Lee Jones wrote:
> On Thu, 05 Jul 2018, Dmitry Torokhov wrote:
> 
> > On July 5, 2018 12:56:50 AM PDT, Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> wrote:
> > >On Wed, Jul 04, 2018 at 06:57:39PM +0200, Enric Balletbo Serra wrote:
> > >> Missatge de Dmitry Torokhov <dmitry.torokhov@gmail.com> del dia dc.,
> > >4
> > >> de jul. 2018 a les 17:10:
> > >> >
> > >> > Hi Enric,
> > >> >
> > >> > On Tue, Jun 26, 2018 at 11:06:33AM +0200, Enric Balletbo Serra
> > >wrote:
> > >> > > > +static struct mfd_cell bd71837_mfd_cells[] = {
> > >> > > > +       {
> > >> > > > +               .name = "bd71837-clk",
> > >> > > > +       }, {
> > >> > > > +               .name = "bd718xx-pwrkey",
> > >> > > > +               .resources = &irqs[0],
> > >> > > > +               .num_resources = ARRAY_SIZE(irqs),
> > >> > > > +       }, {
> > >> > > > +               .name = "bd71837-pmic",
> > >> > > > +       },
> > >> > > nit: no comma at the end
> > >> >
> > >> > Actually, trailing comma is preferred on structures/arrays without
> > >> > sentinels, because if one needs to add a new entry/new member, then
> > >in
> > >> > the diff there will have only one new line added, instead of one
> > >line
> > >> > being changed (adding now necessary comma) and one added.
> > >> >
> > >> 
> > >> Many thanks for sharing your knowledge! That looks to me a good
> > >> reason.
> > >
> > >So in this specific ecample leaving the comma does not help. The
> > >opening
> > >brace for new array element would be added to same line where the comma
> > >is, right?
> > 
> > Ah, yes,  you are right. We usually have either:
> > 
> >         { /* element 1 */ },
> >         { / *element 2 */ },
> >         ...
> > 
> > or:
> > 
> >         {
> >                 /* element 1 */
> >         },
> >         {
> >                 /* element 2 */
> >         },
> > 
> > but I do not think that it is codified in the CodingStyle.
> 
> FWIW, my *strong* preference for single line entries in the
> aforementioned single line format.  Then Dmitry's explanation rings
> true.

The reasoning given by Dmitry makes perfect sense. And to my eyes:
	{
		/* element 1 */
	},
	{
		/* element 2 */
 	},

actually looks better than:
> 	{
		/* element 1 */
	}, {
		/* element 2 */
 	},

So if first one is not enforced in order to minimize almost empty lines
- then I will try to be using the latter in the future. (In such cases
  where element consists of more than one value).

Thanks for this little lesson =)

Br,
	Matti Vaittinen

^ permalink raw reply

* Re: [PATCH v7 1/4] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Lee Jones @ 2018-07-06  7:05 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Matti Vaittinen, Enric Balletbo Serra, Michael Turquette, sboyd,
	Rob Herring, Mark Rutland, Liam Girdwood, Mark Brown,
	Matti Vaittinen, Arnd Bergmann, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <31712EE3-4FA5-4A52-8F84-0EDC1AEEF868@gmail.com>

On Thu, 05 Jul 2018, Dmitry Torokhov wrote:

> On July 5, 2018 12:56:50 AM PDT, Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> wrote:
> >On Wed, Jul 04, 2018 at 06:57:39PM +0200, Enric Balletbo Serra wrote:
> >> Missatge de Dmitry Torokhov <dmitry.torokhov@gmail.com> del dia dc.,
> >4
> >> de jul. 2018 a les 17:10:
> >> >
> >> > Hi Enric,
> >> >
> >> > On Tue, Jun 26, 2018 at 11:06:33AM +0200, Enric Balletbo Serra
> >wrote:
> >> > > Hi Matti,
> >> > >
> >> > > Thanks for the patch, a few comments below, some are feedback I
> >> > > received when I sent some patches to this subsystem.
> >> > >
> >> > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> >del
> >> > > dia dt., 19 de juny 2018 a les 12:57:
> >> > > > +};
> >> > > > +
> >> > > > +/* bd71837 multi function cells */
> >> > > > +static struct mfd_cell bd71837_mfd_cells[] = {
> >> > > > +       {
> >> > > > +               .name = "bd71837-clk",
> >> > > > +       }, {
> >> > > > +               .name = "bd718xx-pwrkey",
> >> > > > +               .resources = &irqs[0],
> >> > > > +               .num_resources = ARRAY_SIZE(irqs),
> >> > > > +       }, {
> >> > > > +               .name = "bd71837-pmic",
> >> > > > +       },
> >> > > nit: no comma at the end
> >> >
> >> > Actually, trailing comma is preferred on structures/arrays without
> >> > sentinels, because if one needs to add a new entry/new member, then
> >in
> >> > the diff there will have only one new line added, instead of one
> >line
> >> > being changed (adding now necessary comma) and one added.
> >> >
> >> 
> >> Many thanks for sharing your knowledge! That looks to me a good
> >> reason.
> >
> >So in this specific ecample leaving the comma does not help. The
> >opening
> >brace for new array element would be added to same line where the comma
> >is, right?
> 
> Ah, yes,  you are right. We usually have either:
> 
>         { /* element 1 */ },
>         { / *element 2 */ },
>         ...
> 
> or:
> 
>         {
>                 /* element 1 */
>         },
>         {
>                 /* element 2 */
>         },
> 
> but I do not think that it is codified in the CodingStyle.

FWIW, my *strong* preference for single line entries in the
aforementioned single line format.  Then Dmitry's explanation rings
true.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v7 1/4] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Dmitry Torokhov @ 2018-07-06  6:38 UTC (permalink / raw)
  To: Matti Vaittinen, Enric Balletbo Serra
  Cc: Michael Turquette, sboyd, Rob Herring, Mark Rutland, Lee Jones,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Arnd Bergmann,
	Sebastian Reichel, chenjh, Andrey Smirnov, Linus Walleij,
	Kate Stewart, Heiko Stübner, Greg Kroah-Hartman, linux-clk,
	devicetree@vger.kernel.org, linux-kernel, linux-input
In-Reply-To: <20180705075650.GA7683@localhost.localdomain>

On July 5, 2018 12:56:50 AM PDT, Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> wrote:
>On Wed, Jul 04, 2018 at 06:57:39PM +0200, Enric Balletbo Serra wrote:
>> Missatge de Dmitry Torokhov <dmitry.torokhov@gmail.com> del dia dc.,
>4
>> de jul. 2018 a les 17:10:
>> >
>> > Hi Enric,
>> >
>> > On Tue, Jun 26, 2018 at 11:06:33AM +0200, Enric Balletbo Serra
>wrote:
>> > > Hi Matti,
>> > >
>> > > Thanks for the patch, a few comments below, some are feedback I
>> > > received when I sent some patches to this subsystem.
>> > >
>> > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
>del
>> > > dia dt., 19 de juny 2018 a les 12:57:
>> > > > +};
>> > > > +
>> > > > +/* bd71837 multi function cells */
>> > > > +static struct mfd_cell bd71837_mfd_cells[] = {
>> > > > +       {
>> > > > +               .name = "bd71837-clk",
>> > > > +       }, {
>> > > > +               .name = "bd718xx-pwrkey",
>> > > > +               .resources = &irqs[0],
>> > > > +               .num_resources = ARRAY_SIZE(irqs),
>> > > > +       }, {
>> > > > +               .name = "bd71837-pmic",
>> > > > +       },
>> > > nit: no comma at the end
>> >
>> > Actually, trailing comma is preferred on structures/arrays without
>> > sentinels, because if one needs to add a new entry/new member, then
>in
>> > the diff there will have only one new line added, instead of one
>line
>> > being changed (adding now necessary comma) and one added.
>> >
>> 
>> Many thanks for sharing your knowledge! That looks to me a good
>> reason.
>
>So in this specific ecample leaving the comma does not help. The
>opening
>brace for new array element would be added to same line where the comma
>is, right?

Ah, yes,  you are right. We usually have either:

        { /* element 1 */ },
        { / *element 2 */ },
        ...

or:

        {
                /* element 1 */
        },
        {
                /* element 2 */
        },

but I do not think that it is codified in the CodingStyle.


Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v10 1/2] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Lee Jones @ 2018-07-06  6:09 UTC (permalink / raw)
  To: Enric Balletbo Serra
  Cc: matti.vaittinen, Michael Turquette, Rob Herring, sboyd,
	Mark Rutland, Liam Girdwood, Mark Brown, Matti Vaittinen,
	Arnd Bergmann, Dmitry Torokhov, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <CAFqH_53DbfFTRt2xST6RXg_qu0+LayXjQL2y024We1LHGB3yQA@mail.gmail.com>

On Thu, 05 Jul 2018, Enric Balletbo Serra wrote:

> Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> dia dj., 5 de jul. 2018 a les 16:32:
> >
> > ROHM BD71837 PMIC MFD driver providing interrupts and support
> > for three subsystems:
> > - clk
> > - Regulators
> > - input/power-key
> >
> > Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> > ---
> >  drivers/mfd/Kconfig              |  13 ++
> >  drivers/mfd/Makefile             |   1 +
> >  drivers/mfd/rohm-bd718x7.c       | 198 +++++++++++++++++++++++
> >  include/linux/mfd/rohm-bd718x7.h | 333 +++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 545 insertions(+)
> >  create mode 100644 drivers/mfd/rohm-bd718x7.c
> >  create mode 100644 include/linux/mfd/rohm-bd718x7.h

[snipping ~550 lines of code]

> The main changes I requested are done so I think you can maintain my
> reviewed-by.
> 
> Reviewed-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>

Thanks for your review, it's much appreciated.

In future would you mind trimming your mails back to only include
relevant sections please?  Going through ~550 lines of code page by
page trying to find your response was a little painful.  TIA.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v10 2/2] mfd: bd71837: Devicetree bindings for ROHM BD71837 PMIC
From: Rob Herring @ 2018-07-05 20:39 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: mturquette, sboyd, mark.rutland, lee.jones, lgirdwood, broonie,
	mazziesaccount, arnd, dmitry.torokhov, sre, chenjh,
	andrew.smirnov, linus.walleij, kstewart, heiko, gregkh, eballetbo,
	linux-clk, devicetree, linux-kernel, linux-input, mikko.mutanen,
	heikki.haikola
In-Reply-To: <8ef84806b7152a4da2bffa0456052e98f4c6e1c6.1530800707.git.matti.vaittinen@fi.rohmeurope.com>

On Thu, Jul 05, 2018 at 05:32:58PM +0300, Matti Vaittinen wrote:
> Document devicetree bindings for ROHM BD71837 PMIC MFD.
> 
> Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> ---
>  .../devicetree/bindings/mfd/rohm,bd71837-pmic.txt  | 62 ++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* Re: [PATCH] Patch enabling Fn function keys for Laptop Asus G730 (keyboard 0x1869)
From: jan @ 2018-07-05 19:02 UTC (permalink / raw)
  To: Jiri Kosina, vereecke.jan; +Cc: linux-kernel, linux-input, benjamin.tissoires
In-Reply-To: <nycvar.YFH.7.76.1806251519190.6203@cbobk.fhfr.pm>

On 25/06/2018 15:20, Jiri Kosina wrote:
> On Thu, 14 Jun 2018, vereecke.jan@skynet.be wrote:
>
>> Attached is a patch enabling (most of) the Fn function keys for the Asus ROG
>> Strix GL730 Laptop. The keyboard identifies as a USB device 0x1869.
>>
>> This patch enables:
>>      volume/mute keys, ROG key, rew/play/ff,
>>      monitor and keyboard brightness keys,
>>      Touchpad toggle key,
>>      Calculator key
>>
>> 'Touchpad on/off' Key returns keycode 33, which is mapped to the 'p' key.
>> 'Display on/off' returns keycode 253, which is mapped in X11 to NoSymbol
>> 'Airplane Key' returns keycode 255, which is mapped in X11 to NoSymbol
>>
>> The following keys are not activated yet:
>>         Microphone Mute key, Fan key, Display Switch key
> Thanks a lot for the patch.
>
>> This patch is against the 4.17-rc7 kernel, for the x86 architecture
> This usually doesn't go to the changelog, it'd be unnecessary polution of
> the set-in-stone git changelog.
>
>> diffstat for this patch is:
>>   hid-asus.c   |    2 ++
>>   hid-ids.h    |    1 +
>>   hid-quirks.c |    1 +
>>   3 files changed, 4 insertions(+)
>>
>> To apply the patch, in the root of the kernel tree use:
>> patch -p1 < AsusGL703-Keyboard-Fn-keys.patch
> Neither does any of this.
>
> What is OTOH missing is your signoff.
>
> Could you please fix these up and resubmit (ideally with Subject: line
> also tailored to fit the subsystem customs, IOW something like "HID: asus:
> add support for ....").
>
> Thanks,
>
Thanks for your reply. However, I am confused. Pleas bear with me as 
this is the very first time that I submit a patch and I followed some 
guidance that I found on the internet (obviously not the correct one).

I suppose I just need to delete the parts of the email where you write 
"this doesn't go in the changelog".

I am not sure what my signoff should contain. Could you point me to a 
correct guide for this ?

Thanks.

^ permalink raw reply

* Re: [PATCH 8/8] watchdog: stpmu1: add stpmu1 watchdog driver
From: Guenter Roeck @ 2018-07-05 18:48 UTC (permalink / raw)
  To: Pascal PAILLET-LME, dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
In-Reply-To: <1530803657-17684-9-git-send-email-p.paillet@st.com>

On 07/05/2018 08:14 AM, Pascal PAILLET-LME wrote:
> From: pascal paillet <p.paillet@st.com>
> 
> The stpmu1 PMIC embeds a watchdog which is disabled by default. As soon
> as the watchdog is started, it must be refreshed periodically otherwise
> the PMIC goes off.
> 
> Signed-off-by: pascal paillet <p.paillet@st.com>
> ---
>   drivers/watchdog/Kconfig      |  12 +++
>   drivers/watchdog/Makefile     |   1 +
>   drivers/watchdog/stpmu1_wdt.c | 177 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 190 insertions(+)
>   create mode 100644 drivers/watchdog/stpmu1_wdt.c
> 
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 9af07fd..2155f4d 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -796,6 +796,18 @@ config STM32_WATCHDOG
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called stm32_iwdg.
>   
> +config STPMU1_WATCHDOG
> +	tristate "STPMU1 PMIC watchdog support"
> +	depends on MFD_STPMU1
> +	select WATCHDOG_CORE
> +	help
> +	  Say Y here to include watchdog support embedded into STPMU1 PMIC.
> +	  If the watchdog timer expires, stpmu1 shut-down all its power
> +	  supplies.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called spmu1_wdt.
> +
>   config UNIPHIER_WATCHDOG
>   	tristate "UniPhier watchdog support"
>   	depends on ARCH_UNIPHIER || COMPILE_TEST
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 1d3c6b0..c9eba94 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -216,3 +216,4 @@ obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o
>   obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
>   obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
>   obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
> +obj-$(CONFIG_STPMU1_WATCHDOG) += stpmu1_wdt.o
> diff --git a/drivers/watchdog/stpmu1_wdt.c b/drivers/watchdog/stpmu1_wdt.c
> new file mode 100644
> index 0000000..57e0afa
> --- /dev/null
> +++ b/drivers/watchdog/stpmu1_wdt.c
> @@ -0,0 +1,177 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
> + * Author: Philippe Peurichard <philippe.peurichard@st.com>,
> + * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/mfd/stpmu1.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/reboot.h>
> +#include <linux/slab.h>
> +#include <linux/watchdog.h>
> +
> +/* WATCHDOG CONTROL REGISTER bit */
> +#define WDT_START		BIT(0)
> +#define WDT_PING		BIT(1)
> +#define WDT_START_MASK		BIT(0)
> +#define WDT_PING_MASK		BIT(1)
> +
> +#define PMIC_WDT_MIN_TIMEOUT 1
> +#define PMIC_WDT_MAX_TIMEOUT 256
> +
> +struct stpmu1_wdt {
> +	struct stpmu1_dev *pmic;
> +	struct watchdog_device wdtdev;
> +	struct notifier_block restart_handler;
> +};
> +
> +static int pmic_wdt_start(struct watchdog_device *wdd)
> +{
> +	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> +	return regmap_update_bits(wdt->pmic->regmap,
> +				  WCHDG_CR, WDT_START_MASK, WDT_START);
> +}
> +
> +static int pmic_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> +	return regmap_update_bits(wdt->pmic->regmap,
> +				  WCHDG_CR, WDT_START_MASK, ~WDT_START);
> +}
> +
> +static int pmic_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
> +	int ret;
> +
> +	return regmap_update_bits(wdt->pmic->regmap,
> +				  WCHDG_CR, WDT_PING_MASK, WDT_PING);
> +	return ret;
> +}
> +
> +static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
> +				unsigned int timeout)
> +{
> +	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
> +	int ret;
> +
> +	ret = regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout);
> +	if (ret)
> +		dev_err(wdt->pmic->dev,
> +			"Failed to set watchdog timeout (err = %d)\n", ret);
> +	else
> +		wdd->timeout = PMIC_WDT_MAX_TIMEOUT;

First the requested timeout is set, then the caller is notified
that the timeout was set to the maximum possible value ? That doesn't
make sense. If that is really intentional, I would expect a detailed
explanation, and I would expect that the value written into the chip
register matches the value reported back to the user.

> +
> +	return ret;
> +}
> +
> +static int pmic_wdt_restart_handler(struct notifier_block *this,
> +				    unsigned long mode, void *cmd)
> +{
> +	struct stpmu1_wdt *wdt = container_of(this,
> +						   struct stpmu1_wdt,
> +						   restart_handler);
> +
> +	dev_info(wdt->pmic->dev,
> +		 "PMIC Watchdog Elapsed (timeout %d), shutdown of PMIC initiated\n",
> +		 wdt->wdtdev.timeout);
> +

Register a restart handler just to issue a message ? That is quite pointless.
A restart handler is supposed to restart the system. Besides, the message
is highly misleading; there is no reason to believe that it will be called
after the watchdog expired.

This function should restart the system. If it doesn't, drop it.

> +	return NOTIFY_DONE;
> +}
> +
> +static const struct watchdog_info pmic_watchdog_info = {
> +	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
> +	.identity = "STPMU1 PMIC Watchdog",
> +};
> +
> +static const struct watchdog_ops pmic_watchdog_ops = {
> +	.owner = THIS_MODULE,
> +	.start = pmic_wdt_start,
> +	.stop = pmic_wdt_stop,
> +	.ping = pmic_wdt_ping,
> +	.set_timeout = pmic_wdt_set_timeout,
> +};
> +
> +static int pmic_wdt_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct stpmu1_dev *pmic;
> +	struct stpmu1_wdt *wdt;
> +
> +	if (!pdev->dev.parent)
> +		return -EINVAL;
> +
> +	pmic = dev_get_drvdata(pdev->dev.parent);
> +	if (!pmic)
> +		return -EINVAL;
> +
> +	wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmu1_wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	wdt->pmic = pmic;
> +
> +	wdt->wdtdev.info = &pmic_watchdog_info;
> +	wdt->wdtdev.ops = &pmic_watchdog_ops;
> +	wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
> +	wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
> +	wdt->wdtdev.timeout = PMIC_WDT_MAX_TIMEOUT;

256 seconds default timeout ? Unusual, just making sure that this is what you want.

> +
> +	wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
> +
> +	watchdog_set_drvdata(&wdt->wdtdev, wdt);
> +	dev_set_drvdata(&pdev->dev, wdt);
> +
> +	ret = watchdog_register_device(&wdt->wdtdev);
> +	if (ret)
> +		return ret;
> +
> +	wdt->restart_handler.notifier_call = pmic_wdt_restart_handler;
> +	wdt->restart_handler.priority = 128;
> +	ret = register_restart_handler(&wdt->restart_handler);

Why is the restart handler provided by the watchdog core not sufficient ?


> +	if (ret) {
> +		dev_err(wdt->pmic->dev, "failed to register restart handler\n");
> +		return ret;
> +	}
> +
> +	dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");

The only reasons not to use the devm_ function to register the watchdog
are the restart handler, which 1) doesn't do anything and 2) should use
the watchdog core, and this debug message. I would suggest to use the
devm_ function to register the watchdog instead.

> +	return 0;
> +}
> +
> +static int pmic_wdt_remove(struct platform_device *pdev)
> +{
> +	struct stpmu1_wdt *wdt = dev_get_drvdata(&pdev->dev);
> +
> +	unregister_restart_handler(&wdt->restart_handler);
> +	watchdog_unregister_device(&wdt->wdtdev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id of_pmic_wdt_match[] = {
> +	{ .compatible = "st,stpmu1-wdt" },
> +	{ },
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
> +
> +static struct platform_driver stpmu1_wdt_driver = {
> +	.probe = pmic_wdt_probe,
> +	.remove = pmic_wdt_remove,
> +	.driver = {
> +		.name = "stpmu1-wdt",
> +		.of_match_table = of_pmic_wdt_match,
> +	},
> +};
> +module_platform_driver(stpmu1_wdt_driver);
> +
> +MODULE_AUTHOR("philippe.peurichard@st.com>");
> +MODULE_DESCRIPTION("Watchdog driver for STPMU1 device");
> +MODULE_LICENSE("GPL");
> 

^ permalink raw reply

* Re: [PATCH 4/8] regulator: stpmu1: add stpmu1 regulator driver
From: Mark Brown @ 2018-07-05 16:48 UTC (permalink / raw)
  To: Pascal PAILLET-LME
  Cc: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
In-Reply-To: <1530803657-17684-5-git-send-email-p.paillet@st.com>

[-- Attachment #1: Type: text/plain, Size: 5543 bytes --]

On Thu, Jul 05, 2018 at 03:14:23PM +0000, Pascal PAILLET-LME wrote:

>  obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
>  obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
>  obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
> +obj-$(CONFIG_PROTECTION_CONSUMER) += protection-consumer.o
>  
>  obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o
>  obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o

Looks like this got included by mistake...

> --- /dev/null
> +++ b/drivers/regulator/stpmu1_regulator.c
> @@ -0,0 +1,919 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved

All rights reserved and GPL :)

Please also make the entire comment a C++ one so the block looks more
intentional.

> +static unsigned int stpmu1_map_mode(unsigned int mode)
> +{
> +	return mode == REGULATOR_MODE_STANDBY ?
> +		REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
> +}

This looks confused - what's going on here?  Normally a map_mode()
operation would be translating values in DT but this translates
everything that isn't standby into normal which suggests there's an
error checking problem.

> +static int stpmu1_ldo3_list_voltage(struct regulator_dev *rdev,
> +				    unsigned int sel)
> +{
> +	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
> +
> +	if (sel == 0)
> +		return regulator_list_voltage_linear_range(rdev, 1);
> +
> +	if (sel < 31)
> +		return regulator_list_voltage_linear_range(rdev, sel);
> +
> +	if (sel == 31)
> +		return stpmu1_get_voltage_regmap(regul->voltage_ref_reg) / 2;
> +
> +	return -EINVAL;
> +}

The only thing that's going on here that's odd and that couldn't be
represented with a helper is selector 31 which looks to be some sort of
divided bypass mode - can you explain what this represents in hardware
terms please?

> +static int stpmu1_ldo3_get_voltage(struct regulator_dev *rdev)
> +{
> +	int sel = regulator_get_voltage_sel_regmap(rdev);
> +
> +	if (sel < 0)
> +		return -EINVAL;
> +
> +	return stpmu1_ldo3_list_voltage(rdev, (unsigned int)sel);
> +}

This is just the standard core behaviour, no need for this.

> +static int stpmu1_fixed_regul_get_voltage(struct regulator_dev *rdev)
> +{
> +	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
> +	int id = rdev_get_id(rdev);
> +
> +	/* VREF_DDR voltage is equal to Buck2/2 */
> +	if (id == STPMU1_VREF_DDR)
> +		return stpmu1_get_voltage_regmap(regul->voltage_ref_reg) / 2;
> +
> +	/* For all other case , rely on fixed value defined by Hw settings */
> +	return regul->cfg->desc.fixed_uV;
> +}

It'd be better to just use a separate set of operations for the DDR
regulator rather than have a conditional here, less code and makes it
clearer that this one is a special case.

> +static void update_regulator_constraints(int index,
> +					 struct regulator_init_data *init_data)
> +{
> +	struct stpmu1_regulator_cfg *cfg = &stpmu1_regulator_cfgs[index];
> +	struct regulator_desc *desc = &cfg->desc;
> +
> +	init_data->constraints.valid_ops_mask |=
> +		cfg->valid_ops_mask;
> +	init_data->constraints.valid_modes_mask |=
> +		cfg->valid_modes_mask;

Drivers should never be modifying their constraints, this is a no no.

> +	/*
> +	 * if all constraints are not specified in DT , ensure Hw
> +	 * constraints are met
> +	 */
> +	if (desc->n_voltages > 1) {

Drivers shouldn't be doing this either.  The API will not allow any
modifications of hardware state without constraints so unless the
bootloader is leaving things in a broken state we should be fine.

> +	if (!init_data->constraints.ramp_delay)
> +		init_data->constraints.ramp_delay = PMIC_RAMP_SLOPE_UV_PER_US;
> +
> +	if (!init_data->constraints.enable_time)
> +		init_data->constraints.enable_time = PMIC_ENABLE_TIME_US;

If these are hard constraints we know from the chip design they should
be being set in the descriptor.  The constraints are there to override
if either they're board dependent or the board needs something longer
than the chip default.

> +	/* LDO3 and VREF_DDR can use buck2 as reference voltage */
> +	if (regul->regul_id == STPMU1_LDO3 ||
> +	    regul->regul_id == STPMU1_VREF_DDR) {
> +		if (!buck2) {
> +			dev_err(&pdev->dev,
> +				"Error in PMIC regulator settings: Buck2 is not defined prior to LDO3 or VREF_DDR regulators\n"
> +				);
> +			return ERR_PTR(-EINVAL);
> +		}
> +		regul->voltage_ref_reg = buck2;
> +	}

Can or do?  Usually this would be hooked up in the DT (with the
regulator specifying a supply name in the desc).

> +	np = pdev->dev.of_node;
> +	if (!np) {
> +		dev_err(&pdev->dev, "regulators node not found\n");
> +		return -EINVAL;
> +	}
> +

May as well let the driver probe?

> +	/* Register all defined (from DT) regulators to Regulator Framework */
> +	for (i = 0; i < ARRAY_SIZE(stpmu1_regulator_cfgs); i++) {
> +		/* Parse DT & find regulators to register */
> +		init_data = stpmu1_regulators_matches[i].init_data;

You should register everything that's physically there unconditionally,
there's no harm in having a regulator registered that's not used and it
might be useful for debugging purposes.

> +static const struct of_device_id of_pmic_regulator_match[] = {
> +	{ .compatible = "st,stpmu1-regulators" },
> +	{ },
> +};

This is part of a MFD for a single chip, why do we need a specific
compatible string here rather than just enumerating from the base
registration of the device?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH 7/8] dt-bindings: watchdog: document stpmu1 pmic watchdog
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

The stpmu1 PMIC embeds a watchdog which is disabled by default.
In case of watchdog, the PMIC goes off.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 Documentation/devicetree/bindings/watchdog/st,stpmu1-wdt.txt | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/st,stpmu1-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/st,stpmu1-wdt.txt b/Documentation/devicetree/bindings/watchdog/st,stpmu1-wdt.txt
new file mode 100644
index 0000000..b558b3c
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/st,stpmu1-wdt.txt
@@ -0,0 +1,11 @@
+STMicroelectronics STPMU1 Watchdog
+
+Required properties:
+
+- compatible : should be "st,stpmu1-wdt"
+
+Example:
+
+watchdog {
+	compatible = "st,stpmu1-wdt";
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 8/8] watchdog: stpmu1: add stpmu1 watchdog driver
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

The stpmu1 PMIC embeds a watchdog which is disabled by default. As soon
as the watchdog is started, it must be refreshed periodically otherwise
the PMIC goes off.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 drivers/watchdog/Kconfig      |  12 +++
 drivers/watchdog/Makefile     |   1 +
 drivers/watchdog/stpmu1_wdt.c | 177 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 190 insertions(+)
 create mode 100644 drivers/watchdog/stpmu1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9af07fd..2155f4d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -796,6 +796,18 @@ config STM32_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called stm32_iwdg.
 
+config STPMU1_WATCHDOG
+	tristate "STPMU1 PMIC watchdog support"
+	depends on MFD_STPMU1
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include watchdog support embedded into STPMU1 PMIC.
+	  If the watchdog timer expires, stpmu1 shut-down all its power
+	  supplies.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called spmu1_wdt.
+
 config UNIPHIER_WATCHDOG
 	tristate "UniPhier watchdog support"
 	depends on ARCH_UNIPHIER || COMPILE_TEST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 1d3c6b0..c9eba94 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -216,3 +216,4 @@ obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
 obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
 obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
+obj-$(CONFIG_STPMU1_WATCHDOG) += stpmu1_wdt.o
diff --git a/drivers/watchdog/stpmu1_wdt.c b/drivers/watchdog/stpmu1_wdt.c
new file mode 100644
index 0000000..57e0afa
--- /dev/null
+++ b/drivers/watchdog/stpmu1_wdt.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/stpmu1.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/watchdog.h>
+
+/* WATCHDOG CONTROL REGISTER bit */
+#define WDT_START		BIT(0)
+#define WDT_PING		BIT(1)
+#define WDT_START_MASK		BIT(0)
+#define WDT_PING_MASK		BIT(1)
+
+#define PMIC_WDT_MIN_TIMEOUT 1
+#define PMIC_WDT_MAX_TIMEOUT 256
+
+struct stpmu1_wdt {
+	struct stpmu1_dev *pmic;
+	struct watchdog_device wdtdev;
+	struct notifier_block restart_handler;
+};
+
+static int pmic_wdt_start(struct watchdog_device *wdd)
+{
+	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	return regmap_update_bits(wdt->pmic->regmap,
+				  WCHDG_CR, WDT_START_MASK, WDT_START);
+}
+
+static int pmic_wdt_stop(struct watchdog_device *wdd)
+{
+	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	return regmap_update_bits(wdt->pmic->regmap,
+				  WCHDG_CR, WDT_START_MASK, ~WDT_START);
+}
+
+static int pmic_wdt_ping(struct watchdog_device *wdd)
+{
+	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
+	int ret;
+
+	return regmap_update_bits(wdt->pmic->regmap,
+				  WCHDG_CR, WDT_PING_MASK, WDT_PING);
+	return ret;
+}
+
+static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
+				unsigned int timeout)
+{
+	struct stpmu1_wdt *wdt = watchdog_get_drvdata(wdd);
+	int ret;
+
+	ret = regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout);
+	if (ret)
+		dev_err(wdt->pmic->dev,
+			"Failed to set watchdog timeout (err = %d)\n", ret);
+	else
+		wdd->timeout = PMIC_WDT_MAX_TIMEOUT;
+
+	return ret;
+}
+
+static int pmic_wdt_restart_handler(struct notifier_block *this,
+				    unsigned long mode, void *cmd)
+{
+	struct stpmu1_wdt *wdt = container_of(this,
+						   struct stpmu1_wdt,
+						   restart_handler);
+
+	dev_info(wdt->pmic->dev,
+		 "PMIC Watchdog Elapsed (timeout %d), shutdown of PMIC initiated\n",
+		 wdt->wdtdev.timeout);
+
+	return NOTIFY_DONE;
+}
+
+static const struct watchdog_info pmic_watchdog_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.identity = "STPMU1 PMIC Watchdog",
+};
+
+static const struct watchdog_ops pmic_watchdog_ops = {
+	.owner = THIS_MODULE,
+	.start = pmic_wdt_start,
+	.stop = pmic_wdt_stop,
+	.ping = pmic_wdt_ping,
+	.set_timeout = pmic_wdt_set_timeout,
+};
+
+static int pmic_wdt_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct stpmu1_dev *pmic;
+	struct stpmu1_wdt *wdt;
+
+	if (!pdev->dev.parent)
+		return -EINVAL;
+
+	pmic = dev_get_drvdata(pdev->dev.parent);
+	if (!pmic)
+		return -EINVAL;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmu1_wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	wdt->pmic = pmic;
+
+	wdt->wdtdev.info = &pmic_watchdog_info;
+	wdt->wdtdev.ops = &pmic_watchdog_ops;
+	wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
+	wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
+	wdt->wdtdev.timeout = PMIC_WDT_MAX_TIMEOUT;
+
+	wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
+
+	watchdog_set_drvdata(&wdt->wdtdev, wdt);
+	dev_set_drvdata(&pdev->dev, wdt);
+
+	ret = watchdog_register_device(&wdt->wdtdev);
+	if (ret)
+		return ret;
+
+	wdt->restart_handler.notifier_call = pmic_wdt_restart_handler;
+	wdt->restart_handler.priority = 128;
+	ret = register_restart_handler(&wdt->restart_handler);
+	if (ret) {
+		dev_err(wdt->pmic->dev, "failed to register restart handler\n");
+		return ret;
+	}
+
+	dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
+	return 0;
+}
+
+static int pmic_wdt_remove(struct platform_device *pdev)
+{
+	struct stpmu1_wdt *wdt = dev_get_drvdata(&pdev->dev);
+
+	unregister_restart_handler(&wdt->restart_handler);
+	watchdog_unregister_device(&wdt->wdtdev);
+
+	return 0;
+}
+
+static const struct of_device_id of_pmic_wdt_match[] = {
+	{ .compatible = "st,stpmu1-wdt" },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
+
+static struct platform_driver stpmu1_wdt_driver = {
+	.probe = pmic_wdt_probe,
+	.remove = pmic_wdt_remove,
+	.driver = {
+		.name = "stpmu1-wdt",
+		.of_match_table = of_pmic_wdt_match,
+	},
+};
+module_platform_driver(stpmu1_wdt_driver);
+
+MODULE_AUTHOR("philippe.peurichard@st.com>");
+MODULE_DESCRIPTION("Watchdog driver for STPMU1 device");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related

* [PATCH 5/8] dt-bindings: input: document stpmu1 pmic onkey
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

The stpmu1 pmic is able to manage an onkey button. It can be configured
to shut-down the power supplies on a long key-press with an adjustable
duration.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 .../devicetree/bindings/input/st,stpmu1-onkey.txt  | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/st,stpmu1-onkey.txt

diff --git a/Documentation/devicetree/bindings/input/st,stpmu1-onkey.txt b/Documentation/devicetree/bindings/input/st,stpmu1-onkey.txt
new file mode 100644
index 0000000..cc42b7f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/st,stpmu1-onkey.txt
@@ -0,0 +1,31 @@
+STMicroelectronics STPMU1 Onkey
+
+Required properties:
+
+- compatible = "st,stpmu1-onkey";
+- interrupt-parent: phandle to the parent interrupt controller
+- interrupts: interrupt line to use
+- interrupt-names = "onkey-falling", "onkey-rising"
+	onkey-falling: happens when onkey is pressed; IT_PONKEY_F of pmic
+	onkey-rising: happens when onkey is released; IT_PONKEY_R of pmic
+
+Optional properties:
+
+- st,onkey-pwroff-enabled: power off on long key-press
+- st,onkey-long-press-seconds: long key-press duration from 1 to 16s
+  (default 16s)
+- st,onkey-clear-cc-flag: onkey is able power on after an
+  over-current shutdown event.
+- st,onkey-pu-inactive: onkey pull up is not active
+
+Example:
+
+onkey {
+	compatible = "st,stpmu1-onkey";
+	interrupt-parent = <&pmic>;
+	interrupts = <7 0>,<6 1>;
+	interrupt-names = "onkey-falling", "onkey-rising";
+	status = "okay";
+	st,onkey-pwroff-enabled;
+	st,onkey-long-press-seconds = <10>;
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 6/8] input: stpmu1: add stpmu1 onkey driver
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

The stpmu1 pmic is able to manage an onkey button. This driver exposes
the stpmu1 onkey as an input device. It can also be configured to
shut-down the power supplies on a long key-press with an adjustable
duration.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 drivers/input/misc/Kconfig        |  11 ++
 drivers/input/misc/Makefile       |   2 +
 drivers/input/misc/stpmu1_onkey.c | 321 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/input/misc/stpmu1_onkey.c

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index c25606e..d020971 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -841,4 +841,15 @@ config INPUT_RAVE_SP_PWRBUTTON
 	  To compile this driver as a module, choose M here: the
 	  module will be called rave-sp-pwrbutton.
 
+config INPUT_STPMU1_ONKEY
+	tristate "STPMU1 PMIC Onkey support"
+	depends on MFD_STPMU1
+	help
+	  Say Y to enable support of onkey embedded into STPMU1 PMIC. onkey
+	  can be used to wakeup from low power modes and force a shut-down on
+	  long press.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called stpmu1_onkey.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 72cde28..cc60dc1 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
 obj-$(CONFIG_INPUT_SIRFSOC_ONKEY)	+= sirfsoc-onkey.o
 obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY)	+= soc_button_array.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
+obj-$(CONFIG_INPUT_STPMU1_ONKEY)  	+= stpmu1_onkey.o
 obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON)	+= tps65218-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o
@@ -80,3 +81,4 @@ obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
 obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR)	+= ideapad_slidebar.o
+
diff --git a/drivers/input/misc/stpmu1_onkey.c b/drivers/input/misc/stpmu1_onkey.c
new file mode 100644
index 0000000..084a31f
--- /dev/null
+++ b/drivers/input/misc/stpmu1_onkey.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/stpmu1.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/**
+ * struct stpmu1_onkey - OnKey data
+ * @pmic:		pointer to STPMU1 PMIC device
+ * @input_dev:		pointer to input device
+ * @irq_falling:	irq that we are hooked on to
+ * @irq_rising:		irq that we are hooked on to
+ */
+struct stpmu1_onkey {
+	struct stpmu1_dev *pmic;
+	struct input_dev *input_dev;
+	int irq_falling;
+	int irq_rising;
+};
+
+/**
+ * struct pmic_onkey_config - configuration of pmic PONKEYn
+ * @turnoff_enabled:		value to enable turnoff condition
+ * @cc_flag_clear:		value to clear CC flag in case of PowerOff
+ * trigger by longkey press
+ * @onkey_pullup_val:		value of PONKEY PullUp (active or inactive)
+ * @long_press_time_val:	value for long press h/w shutdown event
+ */
+struct pmic_onkey_config {
+	bool turnoff_enabled;
+	bool cc_flag_clear;
+	u8 onkey_pullup_val;
+	u8 long_press_time_val;
+};
+
+/**
+ * onkey_falling_irq() - button press isr
+ * @irq:		irq
+ * @pmic_onkey:		onkey device
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
+{
+	struct stpmu1_onkey *onkey = ponkey;
+	struct input_dev *input_dev = onkey->input_dev;
+
+	input_report_key(input_dev, KEY_POWER, 1);
+	pm_wakeup_event(input_dev->dev.parent, 0);
+	input_sync(input_dev);
+
+	dev_dbg(&input_dev->dev, "Pwr Onkey Falling Interrupt received\n");
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * onkey_rising_irq() - button released isr
+ * @irq:		irq
+ * @pmic_onkey:		onkey device
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
+{
+	struct stpmu1_onkey *onkey = ponkey;
+	struct input_dev *input_dev = onkey->input_dev;
+
+	input_report_key(input_dev, KEY_POWER, 0);
+	pm_wakeup_event(input_dev->dev.parent, 0);
+	input_sync(input_dev);
+
+	dev_dbg(&input_dev->dev, "Pwr Onkey Rising Interrupt received\n");
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * stpmu1_onkey_dt_params() - device tree parameter parser
+ * @pdev:	platform device for the PONKEY
+ * @onkey:	pointer to onkey driver data
+ * @config:	configuration params to be filled up
+ */
+static int stpmu1_onkey_dt_params(struct platform_device *pdev,
+				  struct stpmu1_onkey *onkey,
+				  struct pmic_onkey_config *config)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np;
+	u32 val;
+
+	np = dev->of_node;
+	if (!np)
+		return -EINVAL;
+
+	onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
+	if (onkey->irq_falling < 0) {
+		dev_err(dev, "failed: request IRQ onkey-falling %d",
+			onkey->irq_falling);
+		return onkey->irq_falling;
+	}
+
+	onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
+	if (onkey->irq_rising < 0) {
+		dev_err(dev, "failed: request IRQ onkey-rising %d",
+			onkey->irq_rising);
+		return onkey->irq_rising;
+	}
+
+	if (!of_property_read_u32(np, "st,onkey-long-press-seconds", &val)) {
+		if (val >= 1 && val <= 16) {
+			config->long_press_time_val = (16 - val);
+		} else {
+			dev_warn(dev,
+				 "Invalid range of long key pressed timer %d (<16)\n\r",
+				 val);
+		}
+	}
+	if (of_get_property(np, "st,onkey-pwroff-enabled", NULL))
+		config->turnoff_enabled = true;
+
+	if (of_get_property(np, "st,onkey-clear-cc-flag", NULL))
+		config->cc_flag_clear = true;
+
+	if (of_get_property(np, "st,onkey-pu-inactive", NULL))
+		config->onkey_pullup_val = PONKEY_PU_ACTIVE;
+
+	dev_dbg(dev, "onkey-switch-off duration=%d seconds\n",
+		config->long_press_time_val);
+
+	return 0;
+}
+
+/**
+ * stpmu1_onkey_probe() - probe
+ * @pdev:	platform device for the PONKEY
+ *
+ * Return: 0 for successful probe else appropriate error
+ */
+static int stpmu1_onkey_probe(struct platform_device *pdev)
+{
+	struct stpmu1_dev *pmic = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	struct input_dev *input_dev;
+	struct stpmu1_onkey *onkey;
+	struct pmic_onkey_config config;
+	unsigned int val = 0;
+	int ret;
+
+	onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+	if (!onkey)
+		return -ENOMEM;
+
+	memset(&config, 0, sizeof(struct pmic_onkey_config));
+	ret = stpmu1_onkey_dt_params(pdev, onkey, &config);
+	if (ret < 0)
+		goto err;
+
+	input_dev = devm_input_allocate_device(dev);
+	if (!input_dev) {
+		dev_err(dev, "Can't allocate Pwr Onkey Input Device\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	input_dev->name = "pmic_onkey";
+	input_dev->phys = "pmic_onkey/input0";
+	input_dev->dev.parent = dev;
+
+	input_set_capability(input_dev, EV_KEY, KEY_POWER);
+
+	/* Setup Power Onkey Hardware parameters (long key press)*/
+	val = (config.long_press_time_val & PONKEY_TURNOFF_TIMER_MASK);
+	if (config.turnoff_enabled)
+		val |= PONKEY_PWR_OFF;
+	if (config.cc_flag_clear)
+		val |= PONKEY_CC_FLAG_CLEAR;
+	ret = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR,
+				 PONKEY_TURNOFF_MASK, val);
+	if (ret) {
+		dev_err(dev, "LONG_PRESS_KEY_UPDATE failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = regmap_update_bits(pmic->regmap, PADS_PULL_CR,
+				 PONKEY_PU_ACTIVE,
+				 config.onkey_pullup_val);
+
+	if (ret) {
+		dev_err(dev, "ONKEY Pads configuration failed: %d\n", ret);
+		goto err;
+	}
+
+	onkey->pmic = pmic;
+	onkey->input_dev = input_dev;
+
+	ret = devm_request_threaded_irq(dev, onkey->irq_falling, NULL,
+					onkey_falling_irq,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					dev_name(dev), onkey);
+	if (ret) {
+		dev_err(dev, "Can't get IRQ for Onkey Falling edge: %d\n", ret);
+		goto err;
+	}
+
+	ret = devm_request_threaded_irq(dev, onkey->irq_rising, NULL,
+					onkey_rising_irq,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					dev_name(dev), onkey);
+	if (ret) {
+		dev_err(dev, "Can't get IRQ for Onkey Rising edge: %d\n", ret);
+		goto err;
+	}
+
+	ret = input_register_device(input_dev);
+	if (ret) {
+		dev_err(dev, "Can't register power button: %d\n", ret);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, onkey);
+	device_init_wakeup(dev, true);
+
+	dev_dbg(dev, "PMIC Pwr Onkey driver probed\n");
+
+err:
+	return ret;
+}
+
+/**
+ * stpmu1_onkey_remove() - Cleanup on removal
+ * @pdev:	platform device for the button
+ *
+ * Return: 0
+ */
+static int stpmu1_onkey_remove(struct platform_device *pdev)
+{
+	struct stpmu1_onkey *onkey = platform_get_drvdata(pdev);
+
+	input_unregister_device(onkey->input_dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+/**
+ * pmic_onkey_suspend() - suspend handler
+ * @dev:	power button device
+ *
+ * Cancel all pending work items for the power button, setup irq for wakeup
+ *
+ * Return: 0
+ */
+static int __maybe_unused stpmu1_onkey_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct stpmu1_onkey *onkey = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(dev)) {
+		enable_irq_wake(onkey->irq_falling);
+		enable_irq_wake(onkey->irq_rising);
+	}
+	return 0;
+}
+
+/**
+ * pmic_onkey_resume() - resume handler
+ * @dev:	power button device
+ *
+ * Just disable the wakeup capability of irq here.
+ *
+ * Return: 0
+ */
+static int __maybe_unused stpmu1_onkey_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct stpmu1_onkey *onkey = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(dev)) {
+		disable_irq_wake(onkey->irq_falling);
+		disable_irq_wake(onkey->irq_rising);
+	}
+	return 0;
+}
+
+#endif
+
+static SIMPLE_DEV_PM_OPS(stpmu1_onkey_pm,
+			 stpmu1_onkey_suspend,
+			 stpmu1_onkey_resume);
+
+static const struct of_device_id of_stpmu1_onkey_match[] = {
+	{ .compatible = "st,stpmu1-onkey" },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, of_stpmu1_onkey_match);
+
+static struct platform_driver stpmu1_onkey_driver = {
+	.probe	= stpmu1_onkey_probe,
+	.remove	= stpmu1_onkey_remove,
+	.driver	= {
+		.name	= "stpmu1_onkey",
+		.of_match_table = of_match_ptr(of_stpmu1_onkey_match),
+		.pm	= &stpmu1_onkey_pm,
+	},
+};
+module_platform_driver(stpmu1_onkey_driver);
+
+MODULE_DESCRIPTION("Onkey driver for STPMU1");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("philippe.peurichard@st.com>");
-- 
1.9.1

^ permalink raw reply related

* [PATCH 4/8] regulator: stpmu1: add stpmu1 regulator driver
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

The stpmu1 PMIC embeds several regulators and witches with
different capabilities.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 drivers/regulator/Kconfig            |  12 +
 drivers/regulator/Makefile           |   2 +
 drivers/regulator/stpmu1_regulator.c | 919 +++++++++++++++++++++++++++++++++++
 3 files changed, 933 insertions(+)
 create mode 100644 drivers/regulator/stpmu1_regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 5dbccf5..0b508f5 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -804,6 +804,18 @@ config REGULATOR_TI_ABB
 	  on TI SoCs may be unstable without enabling this as it provides
 	  device specific optimized bias to allow/optimize functionality.
 
+config REGULATOR_STPMU1
+	tristate "ST Microelectronics STPMU1 PMIC Regulators"
+	depends on MFD_STPMU1
+	help
+	  This driver supports ST Microelectronics STPMU1 PMIC voltage
+	  regulators and switches. The STPMU1 regulators supply power to
+	  an application processor as well as to external system
+	  peripherals such as DDR, Flash memories and system devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called stpmu1_regulator.
+
 config REGULATOR_STW481X_VMMC
 	bool "ST Microelectronics STW481X VMMC regulator"
 	depends on MFD_STW481X || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index bd818ce..3d572ae 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_OF) += of_regulator.o
 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
+obj-$(CONFIG_PROTECTION_CONSUMER) += protection-consumer.o
 
 obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o
 obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o
@@ -100,6 +101,7 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
 obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
 obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
+obj-$(CONFIG_REGULATOR_STPMU1) += stpmu1_regulator.o
 obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
 obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
 obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
diff --git a/drivers/regulator/stpmu1_regulator.c b/drivers/regulator/stpmu1_regulator.c
new file mode 100644
index 0000000..aed778b
--- /dev/null
+++ b/drivers/regulator/stpmu1_regulator.c
@@ -0,0 +1,919 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/stpmu1.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+/**
+ * stpmu1 regulator description
+ * @desc: regulator framework description
+ * @valid_modes_mask: modes supported by the regulator
+ * @valid_ops_mask: ops supported by the regulator
+ * @pull_down_reg: pull down register address
+ * @mask_reset_reg: mask reset register address
+ * @mask_reset_mask: mask rank and mask reset register mask
+ * @icc_reg: icc register address
+ * @icc_mask: icc register mask
+ */
+struct stpmu1_regulator_cfg {
+	struct regulator_desc desc;
+
+	unsigned int valid_modes_mask;
+	unsigned int valid_ops_mask;
+	u8 mask_reset_reg;
+	u8 mask_reset_mask;
+	u8 icc_reg;
+	u8 icc_mask;
+};
+
+/**
+ * stpmu1 regulator data: this structure is used as driver data
+ * @regul_id: regulator id
+ * @reg_node: DT node of regulator (unused on non-DT platforms)
+ * @cfg: stpmu specific regulator description
+ * @voltage_ref_reg: Special case for Vref DDR & LDO3 for which voltage
+ * depends on Buck2
+ * @mask_reset: mask_reset bit value
+ * @irq_curlim: current limit interrupt number
+ * @regmap: point to parent regmap structure
+ */
+struct stpmu1_regulator {
+	unsigned int regul_id;
+	struct device_node *reg_node;
+	struct stpmu1_regulator_cfg *cfg;
+	struct regulator_dev *voltage_ref_reg;
+	u8 mask_reset;
+	int irq_curlim;
+	struct regmap *regmap;
+};
+
+/**
+ * struct stpmu1_device_data - contains all regulators data
+ * @regulator_table : contains all the regulators
+ * @num_regulators: number of regulators used
+ */
+struct stpmu1_device_data {
+	struct stpmu1_regulator *regulator_table;
+	int num_regulators;
+};
+
+static int stpmu1_set_mode(struct regulator_dev *rdev, unsigned int mode);
+static unsigned int stpmu1_get_mode(struct regulator_dev *rdev);
+static int stpmu1_set_icc(struct regulator_dev *rdev);
+static int stpmu1_set_bypass(struct regulator_dev *rdev, bool enable);
+static int stpmu1_regulator_parse_dt(void *driver_data);
+static unsigned int stpmu1_regulator_get_max_volt(struct regulator_desc *desc);
+static unsigned int stpmu1_map_mode(unsigned int mode);
+static int stpmu1_ldo3_list_voltage(struct regulator_dev *rdev,
+				    unsigned int sel);
+static int stpmu1_ldo3_get_voltage(struct regulator_dev *rdev);
+static int stpmu1_fixed_regul_get_voltage(struct regulator_dev *rdev);
+
+enum {
+	STPMU1_BUCK1 = 0,
+	STPMU1_BUCK2 = 1,
+	STPMU1_BUCK3 = 2,
+	STPMU1_BUCK4 = 3,
+	STPMU1_LDO1 = 4,
+	STPMU1_LDO2 = 5,
+	STPMU1_LDO3 = 6,
+	STPMU1_LDO4 = 7,
+	STPMU1_LDO5 = 8,
+	STPMU1_LDO6 = 9,
+	STPMU1_VREF_DDR = 10,
+	STPMU1_BOOST = 11,
+	STPMU1_VBUS_OTG = 12,
+	STPMU1_SW_OUT = 13,
+};
+
+/*
+ * PMIC Ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * or enable
+ * is 3.6mV/uS +/-60%  -> 2.25mV/uS worst case
+ */
+#define PMIC_RAMP_SLOPE_UV_PER_US 2250
+/* Enable time is 5000V/2250mV/uS */
+#define PMIC_ENABLE_TIME_US 2200
+
+struct regulator_linear_range buck1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000),
+	REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0),
+};
+
+struct regulator_linear_range buck2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
+	REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
+	REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
+	REGULATOR_LINEAR_RANGE(1150000, 22, 23, 0),
+	REGULATOR_LINEAR_RANGE(1200000, 24, 25, 0),
+	REGULATOR_LINEAR_RANGE(1250000, 26, 27, 0),
+	REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
+	REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
+	REGULATOR_LINEAR_RANGE(1400000, 32, 33, 0),
+	REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
+	REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
+};
+
+struct regulator_linear_range buck3_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
+	REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
+	REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
+	REGULATOR_LINEAR_RANGE(1300000, 28, 31, 0),
+	REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0),
+	REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
+
+};
+
+struct regulator_linear_range buck4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
+	REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
+	REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
+	REGULATOR_LINEAR_RANGE(1400000, 32, 33, 0),
+	REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
+	REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000),
+	REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
+
+};
+
+struct regulator_linear_range ldo1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+	REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+	REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+
+};
+
+struct regulator_linear_range ldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+	REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+	REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
+
+};
+
+struct regulator_linear_range ldo3_ranges[] = {
+	/* Special case to allow range to cover lowest value of Buck2/2 */
+	REGULATOR_LINEAR_RANGE(500000, 0, 0, 0),
+	REGULATOR_LINEAR_RANGE(1700000, 1, 7, 0),
+	REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+	/* index 31 is special case when LDO3 is in mode DDR */
+	REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+};
+
+struct regulator_linear_range ldo5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+	REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
+	REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
+};
+
+struct regulator_linear_range ldo6_ranges[] = {
+	REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
+	REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+};
+
+static struct regulator_ops stpmu1_ldo_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.set_pull_down = regulator_set_pull_down_regmap,
+	.set_over_current_protection = stpmu1_set_icc,
+};
+
+static struct regulator_ops stpmu1_ldo3_ops = {
+	.list_voltage = stpmu1_ldo3_list_voltage,
+	.map_voltage = regulator_map_voltage_iterate,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.get_voltage = stpmu1_ldo3_get_voltage,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.set_pull_down = regulator_set_pull_down_regmap,
+	.get_bypass = regulator_get_bypass_regmap,
+	.set_bypass = stpmu1_set_bypass,
+	.set_over_current_protection = stpmu1_set_icc,
+};
+
+static struct regulator_ops stpmu1_ldo4_fixed_regul_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.set_pull_down = regulator_set_pull_down_regmap,
+	.set_over_current_protection = stpmu1_set_icc,
+};
+
+static struct regulator_ops stpmu1_buck_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.set_pull_down = regulator_set_pull_down_regmap,
+	.set_mode = stpmu1_set_mode,
+	.get_mode = stpmu1_get_mode,
+	.set_over_current_protection = stpmu1_set_icc,
+};
+
+static struct regulator_ops stpmu1_fixed_regul_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.get_voltage = stpmu1_fixed_regul_get_voltage,
+	.set_pull_down = regulator_set_pull_down_regmap,
+};
+
+static struct regulator_ops stpmu1_switch_regul_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.get_voltage = stpmu1_fixed_regul_get_voltage,
+	.set_over_current_protection = stpmu1_set_icc,
+};
+
+#define REG_LDO(ids, base) { \
+	.name = #ids, \
+	.id = STPMU1_##ids, \
+	.n_voltages = 32, \
+	.ops = &stpmu1_ldo_ops, \
+	.linear_ranges = base ## _ranges, \
+	.n_linear_ranges = ARRAY_SIZE(base ## _ranges), \
+	.type = REGULATOR_VOLTAGE, \
+	.owner = THIS_MODULE, \
+	.vsel_reg = ids##_ACTIVE_CR, \
+	.vsel_mask = LDO_VOLTAGE_MASK, \
+	.enable_reg = ids##_ACTIVE_CR, \
+	.enable_mask = LDO_ENABLE_MASK, \
+	.enable_val = 1, \
+	.disable_val = 0, \
+	.pull_down_reg = ids##_PULL_DOWN_REG, \
+	.pull_down_mask = ids##_PULL_DOWN_MASK, \
+	.supply_name = #base, \
+}
+
+#define REG_LDO3(ids) { \
+	.name = #ids, \
+	.id = STPMU1_##ids, \
+	.n_voltages = 32, \
+	.ops = &stpmu1_ldo3_ops, \
+	.linear_ranges = ldo3_ranges, \
+	.n_linear_ranges = ARRAY_SIZE(ldo3_ranges), \
+	.type = REGULATOR_VOLTAGE, \
+	.owner = THIS_MODULE, \
+	.vsel_reg = LDO3_ACTIVE_CR, \
+	.vsel_mask = LDO_VOLTAGE_MASK, \
+	.enable_reg = LDO3_ACTIVE_CR, \
+	.enable_mask = LDO_ENABLE_MASK, \
+	.enable_val = 1, \
+	.disable_val = 0, \
+	.bypass_reg = LDO3_ACTIVE_CR, \
+	.bypass_mask = LDO_BYPASS_MASK, \
+	.bypass_val_on = LDO_BYPASS_MASK, \
+	.bypass_val_off = 0, \
+	.pull_down_reg = ids##_PULL_DOWN_REG, \
+	.pull_down_mask = ids##_PULL_DOWN_MASK, \
+	.supply_name = "ldo3", \
+}
+
+#define REG_LDO4(ids) { \
+	.name = #ids, \
+	.id = STPMU1_##ids, \
+	.n_voltages = 1, \
+	.ops = &stpmu1_ldo4_fixed_regul_ops, \
+	.type = REGULATOR_VOLTAGE, \
+	.owner = THIS_MODULE, \
+	.min_uV = 3300000, \
+	.fixed_uV = 3300000, \
+	.enable_reg = LDO4_ACTIVE_CR, \
+	.enable_mask = LDO_ENABLE_MASK, \
+	.enable_val = 1, \
+	.disable_val = 0, \
+	.pull_down_reg = ids##_PULL_DOWN_REG, \
+	.pull_down_mask = ids##_PULL_DOWN_MASK, \
+	.supply_name = "ldo4", \
+}
+
+#define REG_BUCK(ids, base) { \
+	.name = #ids, \
+	.id = STPMU1_##ids, \
+	.ops = &stpmu1_buck_ops, \
+	.n_voltages = 64, \
+	.linear_ranges = base ## _ranges, \
+	.n_linear_ranges = ARRAY_SIZE(base ## _ranges), \
+	.type = REGULATOR_VOLTAGE, \
+	.owner = THIS_MODULE, \
+	.vsel_reg = ids##_ACTIVE_CR, \
+	.vsel_mask = BUCK_VOLTAGE_MASK, \
+	.enable_reg = ids##_ACTIVE_CR, \
+	.enable_mask = BUCK_ENABLE_MASK, \
+	.enable_val = 1, \
+	.disable_val = 0, \
+	.of_map_mode = stpmu1_map_mode, \
+	.pull_down_reg = ids##_PULL_DOWN_REG, \
+	.pull_down_mask = ids##_PULL_DOWN_MASK, \
+	.supply_name = #base, \
+}
+
+#define REG_VREF_DDR(ids, reg) { \
+	.name = #ids, \
+	.id = STPMU1_##ids, \
+	.n_voltages = 1, \
+	.ops = &stpmu1_fixed_regul_ops, \
+	.type = REGULATOR_VOLTAGE, \
+	.owner = THIS_MODULE, \
+	.min_uV = 0, \
+	.fixed_uV = 5000000, \
+	.enable_reg = (reg), \
+	.enable_mask = BUCK_ENABLE_MASK, \
+	.enable_val = 1, \
+	.disable_val = 0, \
+	.of_map_mode = stpmu1_map_mode, \
+	.pull_down_reg = ids##_PULL_DOWN_REG, \
+	.pull_down_mask = ids##_PULL_DOWN_MASK, \
+	.supply_name = NULL, \
+}
+
+#define REG_SWITCH(ids, base, reg, mask, val) { \
+	.name = #ids, \
+	.id = STPMU1_##ids, \
+	.n_voltages = 1, \
+	.ops = &stpmu1_switch_regul_ops, \
+	.type = REGULATOR_VOLTAGE, \
+	.owner = THIS_MODULE, \
+	.min_uV = 0, \
+	.fixed_uV = 5000000, \
+	.enable_reg = (reg), \
+	.enable_mask = (mask), \
+	.enable_val = (val), \
+	.disable_val = 0, \
+	.of_map_mode = stpmu1_map_mode, \
+	.supply_name = #base, \
+}
+
+struct stpmu1_regulator_cfg stpmu1_regulator_cfgs[] = {
+	[STPMU1_BUCK1] = {
+		.desc = REG_BUCK(BUCK1, buck1),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				    REGULATOR_MODE_STANDBY,
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(0),
+		.mask_reset_reg = BUCKS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(0),
+	},
+	[STPMU1_BUCK2] = {
+		.desc = REG_BUCK(BUCK2, buck2),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				    REGULATOR_MODE_STANDBY,
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(1),
+		.mask_reset_reg = BUCKS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(1),
+	},
+	[STPMU1_BUCK3] = {
+		.desc = REG_BUCK(BUCK3, buck3),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				    REGULATOR_MODE_STANDBY,
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(2),
+		.mask_reset_reg = BUCKS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(2),
+	},
+	[STPMU1_BUCK4] = {
+		.desc = REG_BUCK(BUCK4, buck4),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				    REGULATOR_MODE_STANDBY,
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(3),
+		.mask_reset_reg = BUCKS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(3),
+	},
+	[STPMU1_LDO1] = {
+		.desc = REG_LDO(LDO1, ldo1),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.icc_reg = LDOS_ICCTO_CR,
+		.icc_mask = BIT(0),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(0),
+	},
+	[STPMU1_LDO2] = {
+		.desc = REG_LDO(LDO2, ldo2),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.icc_reg = LDOS_ICCTO_CR,
+		.icc_mask = BIT(1),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(1),
+	},
+	[STPMU1_LDO3] = {
+		.desc = REG_LDO3(LDO3),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_BYPASS,
+		.icc_reg = LDOS_ICCTO_CR,
+		.icc_mask = BIT(2),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(2),
+	},
+	[STPMU1_LDO4] = {
+		.desc = REG_LDO4(LDO4),
+		.icc_reg = LDOS_ICCTO_CR,
+		.icc_mask = BIT(3),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(3),
+	},
+	[STPMU1_LDO5] = {
+		.desc = REG_LDO(LDO5, ldo5),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.icc_reg = LDOS_ICCTO_CR,
+		.icc_mask = BIT(4),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(4),
+	},
+	[STPMU1_LDO6] = {
+		.desc = REG_LDO(LDO6, ldo6),
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.icc_reg = LDOS_ICCTO_CR,
+		.icc_mask = BIT(5),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(5),
+	},
+	[STPMU1_VREF_DDR] = {
+		.desc = REG_VREF_DDR(VREF_DDR, VREF_DDR_ACTIVE_CR),
+		.mask_reset_reg = LDOS_MASK_RESET_CR,
+		.mask_reset_mask = BIT(6),
+	},
+	[STPMU1_BOOST] = {
+		.desc = REG_SWITCH(BOOST, boost, BST_SW_CR,
+				   BOOST_ENABLED,
+				   BOOST_ENABLED),
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(6),
+	},
+	[STPMU1_VBUS_OTG] = {
+		.desc = REG_SWITCH(VBUS_OTG, pwr_sw1, BST_SW_CR,
+				   USBSW_OTG_SWITCH_ENABLED,
+				   USBSW_OTG_SWITCH_ENABLED),
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(4),
+	},
+	[STPMU1_SW_OUT] = {
+		.desc = REG_SWITCH(SW_OUT, pwr_sw2, BST_SW_CR,
+				   SWIN_SWOUT_ENABLED,
+				   SWIN_SWOUT_ENABLED),
+		.icc_reg = BUCKS_ICCTO_CR,
+		.icc_mask = BIT(5),
+	},
+};
+
+#define GET_MINIMUM_VOLTAGE(_regulator_desc_ptr) \
+	((_regulator_desc_ptr)->linear_ranges[0].min_uV)
+
+static unsigned int stpmu1_map_mode(unsigned int mode)
+{
+	return mode == REGULATOR_MODE_STANDBY ?
+		REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
+}
+
+static unsigned int stpmu1_regulator_get_max_volt(struct regulator_desc *desc)
+{
+	const struct regulator_linear_range *last_range =
+		&desc->linear_ranges[desc->n_linear_ranges - 1];
+
+	unsigned int max_voltage =
+		last_range->min_uV +
+		(last_range->max_sel - last_range->min_sel + 1)
+		* last_range->uV_step;
+
+	return max_voltage;
+}
+
+static int stpmu1_get_voltage_regmap(struct regulator_dev *rdev)
+{
+	int selector = 0;
+
+	if (!rdev)
+		return -EINVAL;
+	selector = regulator_get_voltage_sel_regmap(rdev);
+	return regulator_list_voltage_linear_range(rdev, selector);
+}
+
+static int stpmu1_ldo3_list_voltage(struct regulator_dev *rdev,
+				    unsigned int sel)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+
+	if (sel == 0)
+		return regulator_list_voltage_linear_range(rdev, 1);
+
+	if (sel < 31)
+		return regulator_list_voltage_linear_range(rdev, sel);
+
+	if (sel == 31)
+		return stpmu1_get_voltage_regmap(regul->voltage_ref_reg) / 2;
+
+	return -EINVAL;
+}
+
+static int stpmu1_ldo3_get_voltage(struct regulator_dev *rdev)
+{
+	int sel = regulator_get_voltage_sel_regmap(rdev);
+
+	if (sel < 0)
+		return -EINVAL;
+
+	return stpmu1_ldo3_list_voltage(rdev, (unsigned int)sel);
+}
+
+static int stpmu1_fixed_regul_get_voltage(struct regulator_dev *rdev)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+
+	/* VREF_DDR voltage is equal to Buck2/2 */
+	if (id == STPMU1_VREF_DDR)
+		return stpmu1_get_voltage_regmap(regul->voltage_ref_reg) / 2;
+
+	/* For all other case , rely on fixed value defined by Hw settings */
+	return regul->cfg->desc.fixed_uV;
+}
+
+static int stpmu1_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+	unsigned int hplp;
+
+	/* The low power mode will be set for NORMAL/RUN registers */
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+		hplp = 0;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		hplp = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return  regmap_update_bits(regul->regmap, regul->cfg->desc.enable_reg,
+				   BUCK_HPLP_ENABLE_MASK,
+				   hplp << BUCK_HPLP_SHIFT);
+}
+
+static unsigned int stpmu1_get_mode(struct regulator_dev *rdev)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(regul->regmap, regul->cfg->desc.enable_reg, &val);
+	if (ret < 0)
+		return ret;
+
+	val &= BUCK_HPLP_ENABLE_MASK;
+	val >>= BUCK_HPLP_SHIFT;
+
+	return val ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
+}
+
+static int stpmu1_set_icc(struct regulator_dev *rdev)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+
+	/* enable switch off in case of over current */
+	return regmap_update_bits(regul->regmap, regul->cfg->icc_reg,
+				  regul->cfg->icc_mask, regul->cfg->icc_mask);
+}
+
+static int stpmu1_set_bypass(struct regulator_dev *rdev, bool enable)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+	int ret;
+	unsigned int val;
+
+	if (enable)
+		val = regul->cfg->desc.bypass_val_on;
+	else
+		val = regul->cfg->desc.bypass_val_off;
+
+	ret = regmap_update_bits(regul->regmap, regul->cfg->desc.bypass_reg,
+				 regul->cfg->desc.bypass_mask, val);
+
+	return ret;
+}
+
+static irqreturn_t stpmu1_curlim_irq_handler(int irq, void *data)
+{
+	struct regulator_dev *rdev = (struct regulator_dev *)data;
+
+	mutex_lock(&rdev->mutex);
+
+	/* Send an overcurrent notification */
+	regulator_notifier_call_chain(rdev,
+				      REGULATOR_EVENT_OVER_CURRENT,
+				      NULL);
+
+	mutex_unlock(&rdev->mutex);
+
+	return IRQ_HANDLED;
+}
+
+static int stpmu1_regulator_init(struct platform_device *pdev,
+				 struct regulator_dev *rdev)
+{
+	struct stpmu1_regulator *regul = rdev_get_drvdata(rdev);
+	int ret = 0;
+
+	/* set mask reset */
+	if (regul->mask_reset && regul->cfg->mask_reset_reg != 0) {
+		ret = regmap_update_bits(regul->regmap,
+					 regul->cfg->mask_reset_reg,
+					 regul->cfg->mask_reset_mask,
+					 regul->cfg->mask_reset_mask);
+		if (ret) {
+			dev_err(&pdev->dev, "set mask reset failed\n");
+			return ret;
+		}
+	}
+
+	/* setup an irq handler for over-current detection */
+	if (regul->irq_curlim >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+						regul->irq_curlim, NULL,
+						stpmu1_curlim_irq_handler,
+						IRQF_ONESHOT | IRQF_SHARED,
+						pdev->name, rdev);
+		if (ret) {
+			dev_err(&pdev->dev, "Request IRQ failed\n");
+			return ret;
+		}
+	}
+	return 0;
+}
+
+#define MATCH(_name, _id) \
+	[STPMU1_##_id] = { \
+		.name = #_name, \
+		.desc = &stpmu1_regulator_cfgs[STPMU1_##_id].desc, \
+	}
+
+static struct of_regulator_match stpmu1_regulators_matches[] = {
+	MATCH(buck1, BUCK1),
+	MATCH(buck2, BUCK2),
+	MATCH(buck3, BUCK3),
+	MATCH(buck4, BUCK4),
+	MATCH(ldo1, LDO1),
+	MATCH(ldo2, LDO2),
+	MATCH(ldo3, LDO3),
+	MATCH(ldo4, LDO4),
+	MATCH(ldo5, LDO5),
+	MATCH(ldo6, LDO6),
+	MATCH(vref_ddr, VREF_DDR),
+	MATCH(boost, BOOST),
+	MATCH(pwr_sw1, VBUS_OTG),
+	MATCH(pwr_sw2, SW_OUT),
+};
+
+static inline struct device_node *match_of_node(struct platform_device *pdev,
+						int index)
+{
+	if (!stpmu1_regulators_matches[index].of_node)
+		dev_info(&pdev->dev,
+			 "DT node not found for regulator %i\n\r", index);
+
+	return stpmu1_regulators_matches[index].of_node;
+}
+
+static int stpmu1_regulator_parse_dt(void *driver_data)
+{
+	struct stpmu1_regulator *regul =
+		(struct stpmu1_regulator *)driver_data;
+
+	if (!regul)
+		return -EINVAL;
+
+	if (of_get_property(regul->reg_node, "st,mask_reset", NULL))
+		regul->mask_reset = 1;
+
+	regul->irq_curlim = of_irq_get(regul->reg_node, 0);
+
+	return 0;
+}
+
+static void update_regulator_constraints(int index,
+					 struct regulator_init_data *init_data)
+{
+	struct stpmu1_regulator_cfg *cfg = &stpmu1_regulator_cfgs[index];
+	struct regulator_desc *desc = &cfg->desc;
+
+	init_data->constraints.valid_ops_mask |=
+		cfg->valid_ops_mask;
+	init_data->constraints.valid_modes_mask |=
+		cfg->valid_modes_mask;
+
+	/*
+	 * if all constraints are not specified in DT , ensure Hw
+	 * constraints are met
+	 */
+	if (desc->n_voltages > 1) {
+		if (!init_data->constraints.min_uV)
+			init_data->constraints.min_uV =
+				GET_MINIMUM_VOLTAGE(desc);
+		if (!init_data->constraints.max_uV)
+			init_data->constraints.max_uV =
+			stpmu1_regulator_get_max_volt(desc);
+	}
+
+	if (!init_data->constraints.ramp_delay)
+		init_data->constraints.ramp_delay = PMIC_RAMP_SLOPE_UV_PER_US;
+
+	if (!init_data->constraints.enable_time)
+		init_data->constraints.enable_time = PMIC_ENABLE_TIME_US;
+}
+
+static struct
+regulator_dev *stpmu1_regulator_register(struct platform_device *pdev, int id,
+					 struct regulator_init_data *init_data,
+					 struct stpmu1_regulator *regul,
+					 struct regulator_dev *buck2)
+{
+	struct stpmu1_dev *pmic_dev = dev_get_drvdata(pdev->dev.parent);
+	struct regulator_dev *rdev;
+	struct regulator_config config = {};
+
+	config.dev = &pdev->dev;
+	config.init_data = init_data;
+	config.of_node = match_of_node(pdev, id);
+	config.regmap = pmic_dev->regmap;
+	config.driver_data = regul;
+
+	regul->regul_id = id;
+	regul->reg_node = config.of_node;
+	regul->cfg = &stpmu1_regulator_cfgs[id];
+	regul->regmap = pmic_dev->regmap;
+
+	/* LDO3 and VREF_DDR can use buck2 as reference voltage */
+	if (regul->regul_id == STPMU1_LDO3 ||
+	    regul->regul_id == STPMU1_VREF_DDR) {
+		if (!buck2) {
+			dev_err(&pdev->dev,
+				"Error in PMIC regulator settings: Buck2 is not defined prior to LDO3 or VREF_DDR regulators\n"
+				);
+			return ERR_PTR(-EINVAL);
+		}
+		regul->voltage_ref_reg = buck2;
+	}
+
+	rdev = devm_regulator_register(&pdev->dev, &regul->cfg->desc, &config);
+	if (IS_ERR(rdev)) {
+		dev_err(&pdev->dev, "failed to register %s regulator\n",
+			regul->cfg->desc.name);
+	}
+
+	return rdev;
+}
+
+static int stpmu1_regulator_probe(struct platform_device *pdev)
+{
+	struct stpmu1_dev *pmic_dev = dev_get_drvdata(pdev->dev.parent);
+	struct stpmu1_device_data *ddata;
+	struct regulator_dev *rdev;
+	struct stpmu1_regulator *regul;
+	struct regulator_init_data *init_data;
+	struct device_node *np;
+	int i, ret;
+	struct regulator_dev *buck2_rdev = NULL;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(struct stpmu1_device_data),
+			     GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+
+	/* disable icc for all reguls */
+	ret = regmap_update_bits(pmic_dev->regmap, BUCKS_ICCTO_CR,
+				 BUCKS_ICCTO_CR_REG_MASK, 0);
+	if (ret == 0)
+		ret = regmap_update_bits(pmic_dev->regmap, LDOS_ICCTO_CR,
+					 LDOS_ICCTO_CR_REG_MASK, 0);
+	/* reset pulldown value */
+	if (ret == 0)
+		ret = regmap_update_bits(pmic_dev->regmap, BUCKS_PD_CR,
+					 BUCKS_PD_CR_REG_MASK, 0);
+	if (ret == 0)
+		ret = regmap_update_bits(pmic_dev->regmap, LDO14_PD_CR,
+					 LDO1234_PULL_DOWN_REGISTER_MASK, 0);
+	if (ret == 0)
+		ret = regmap_update_bits(pmic_dev->regmap, LDO56_VREF_PD_CR,
+					 LDO56_VREF_PD_CR_REG_MASK, 0);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to update stpmu1 register %d\n", ret);
+		return ret;
+	}
+
+	np = pdev->dev.of_node;
+	if (!np) {
+		dev_err(&pdev->dev, "regulators node not found\n");
+		return -EINVAL;
+	}
+
+	ret = of_regulator_match(&pdev->dev, np,
+				 stpmu1_regulators_matches,
+				 ARRAY_SIZE(stpmu1_regulators_matches));
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Error in PMIC regulator device tree node");
+		return ret;
+	}
+	ddata->num_regulators = ret;
+
+	dev_dbg(&pdev->dev, "%d regulator(s) found in DT\n",
+		ddata->num_regulators);
+
+	regul = devm_kzalloc(&pdev->dev, ddata->num_regulators *
+			     sizeof(struct stpmu1_regulator),
+			     GFP_KERNEL);
+	if (!regul)
+		return -ENOMEM;
+
+	ddata->regulator_table = regul;
+
+	/* Register all defined (from DT) regulators to Regulator Framework */
+	for (i = 0; i < ARRAY_SIZE(stpmu1_regulator_cfgs); i++) {
+		/* Parse DT & find regulators to register */
+		init_data = stpmu1_regulators_matches[i].init_data;
+		if (init_data) {
+			init_data->regulator_init = &stpmu1_regulator_parse_dt;
+
+			update_regulator_constraints(i, init_data);
+
+			rdev = stpmu1_regulator_register(pdev, i, init_data,
+							 regul, buck2_rdev);
+			if (IS_ERR(rdev))
+				return PTR_ERR(rdev);
+
+			ret = stpmu1_regulator_init(pdev, rdev);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"failed to initialize regulator %d\n",
+					ret);
+				return ret;
+			}
+
+			if (regul->regul_id == STPMU1_BUCK2)
+				buck2_rdev = rdev;
+
+			regul++;
+		}
+	}
+
+	dev_dbg(&pdev->dev, "stpmu1_regulator driver probed\n");
+
+	return 0;
+}
+
+static const struct of_device_id of_pmic_regulator_match[] = {
+	{ .compatible = "st,stpmu1-regulators" },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, of_pmic_regulator_match);
+
+static struct platform_driver stpmu1_regulator_driver = {
+	.driver = {
+		.name = "stpmu1-regulator",
+		.of_match_table = of_match_ptr(of_pmic_regulator_match),
+	},
+	.probe = stpmu1_regulator_probe,
+};
+
+module_platform_driver(stpmu1_regulator_driver);
+
+MODULE_DESCRIPTION("STPMU1 PMIC voltage regulator driver");
+MODULE_AUTHOR("<philippe.peurichard@st.com>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/8] dt-bindings: regulator: document stpmu1 pmic regulators
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

The STPMU1 regulators supply power to the application processor as well as
to the external system peripherals such as DDR, Flash memories and system
devices.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 .../bindings/regulator/st,stpmu1-regulator.txt     | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/st,stpmu1-regulator.txt

diff --git a/Documentation/devicetree/bindings/regulator/st,stpmu1-regulator.txt b/Documentation/devicetree/bindings/regulator/st,stpmu1-regulator.txt
new file mode 100644
index 0000000..888e759
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/st,stpmu1-regulator.txt
@@ -0,0 +1,72 @@
+STMicroelectronics STPMU1 Voltage regulators
+
+Regulator Nodes are optional depending on needs.
+
+Available Regulators in STPMU1 device are:
+  - buck1 for Buck BUCK1
+  - buck2 for Buck BUCK2
+  - buck3 for Buck BUCK3
+  - buck4 for Buck BUCK4
+  - ldo1 for LDO LDO1
+  - ldo2 for LDO LDO2
+  - ldo3 for LDO LDO3
+  - ldo4 for LDO LDO4
+  - ldo5 for LDO LDO5
+  - ldo6 for LDO LDO6
+  - vref_ddr for LDO Vref DDR
+  - boost for Buck BOOST
+  - pwr_sw1 for VBUS_OTG switch
+  - pwr_sw2 for SW_OUT switch
+
+Switches are fixed voltage regulators with only enable/disable capability.
+
+Optional properties:
+- st,mask_reset: stay on during Reset for particular regulator
+- regulator-pull-down: enable high pull down
+  if not specified light pull down is used
+- regulator-over-current-protection:
+    if set, all regulators are switched off in case of over-current detection
+    on this regulator,
+    if not set, the driver only send an over-current event.
+- interrupt-parent: phandle to the parent interrupt controller
+- interrupts: index of current limit detection interrupt
+- <regulator>-supply: phandle to the parent supply/regulator node
+	each regulator supply can be described except vref_ddr.
+
+Example:
+regulators {
+	compatible = "st,stpmu1-regulators";
+
+	ldo6-supply = <&v3v3>;
+
+	vdd_core: regulator@0 {
+		regulator-compatible = "buck1";
+		regulator-name = "vdd_core";
+		interrupts = <IT_CURLIM_BUCK1 0>;
+		interrupt-parent = <&pmic>;
+		st,mask_reset;
+		regulator-pull-down;
+		st,pulldown_config = <2>;
+		regulator-min-microvolt = <700000>;
+		regulator-max-microvolt = <1200000>;
+	};
+
+	v3v3: buck4 {
+		regulator-compatible = "buck4";
+		regulator-name = "v3v3";
+		interrupts = <IT_CURLIM_BUCK4 0>;
+		interrupt-parent = <&mypmic>;
+
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	v1v8: ldo6 {
+		regulator-compatible = "ldo6";
+		regulator-name = "v1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-over-current-protection;
+	};
+
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/8] dt-bindings: mfd: document stpmu1 pmic
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

stpmu1 is a pmic from STMicroelectronics. The stpmu1 integrates 10
regulators and 3 switches with various capabilities.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 .../devicetree/bindings/mfd/st,stpmu1.txt          | 138 +++++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/st,stpmu1.txt

diff --git a/Documentation/devicetree/bindings/mfd/st,stpmu1.txt b/Documentation/devicetree/bindings/mfd/st,stpmu1.txt
new file mode 100644
index 0000000..53bdab4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/st,stpmu1.txt
@@ -0,0 +1,138 @@
+* STMicroelectronics STPMU1 Power Management IC
+
+Required parent device properties:
+- compatible: "st,stpmu1"
+- reg: the I2C slave address for the stpmu1 chip
+- interrupts-extended: interrupt lines to use: second irq is for wakeup.
+- #interrupt-cells: should be 2.
+- interrupt-controller: describes the STPMU1 as an interrupt
+  controller (has its own domain). interrupt number are the following:
+	/* Interrupt Register 1 (0x50 for latch) */
+	IT_SWOUT_R=0
+	IT_SWOUT_F=1
+	IT_VBUS_OTG_R=2
+	IT_VBUS_OTG_F=3
+	IT_WAKEUP_R=4
+	IT_WAKEUP_F=5
+	IT_PONKEY_R=6
+	IT_PONKEY_F=7
+	/* Interrupt Register 2 (0x51 for latch) */
+	IT_OVP_BOOST=8
+	IT_OCP_BOOST=9
+	IT_OCP_SWOUT=10
+	IT_OCP_OTG=11
+	IT_CURLIM_BUCK4=12
+	IT_CURLIM_BUCK3=13
+	IT_CURLIM_BUCK2=14
+	IT_CURLIM_BUCK1=15
+	/* Interrupt Register 3 (0x52 for latch) */
+	IT_SHORT_SWOUT=16
+	IT_SHORT_SWOTG=17
+	IT_CURLIM_LDO6=18
+	IT_CURLIM_LDO5=19
+	IT_CURLIM_LDO4=20
+	IT_CURLIM_LDO3=21
+	IT_CURLIM_LDO2=22
+	IT_CURLIM_LDO1=23
+	/* Interrupt Register 3 (0x52 for latch) */
+	IT_SWIN_R=24
+	IT_SWIN_F=25
+	IT_RESERVED_1=26
+	IT_RESERVED_2=27
+	IT_VINLOW_R=28
+	IT_VINLOW_F=29
+	IT_TWARN_R=30
+	IT_TWARN_F=31
+
+Optional parent device properties:
+- st,main_control_register:
+	-bit 1: Power cycling will be performed on turn OFF condition
+	-bit 2: PWRCTRL is functional
+	-bit 3: PWRCTRL active high
+- st,pads_pull_register:
+	-bit 1: WAKEUP pull down is not active
+	-bit 2: PWRCTRL pull up is active
+	-bit 3: PWRCTRL pull down is active
+	-bit 4: WAKEUP detector is disabled
+- st,vin_control_register:
+	-bit 0: VINLOW monitoring is enabled
+	-bit [1...3]: VINLOW rising threshold
+		000 VINOK_f + 50mV
+		001 VINOK_f + 100mV
+		010 VINOK_f + 150mV
+		011 VINOK_f + 200mV
+		100 VINOK_f + 250mV
+		101 VINOK_f + 300mV
+		110 VINOK_f + 350mV
+		111 VINOK_f + 400mV
+	-bit [4...5]: VINLOW hyst
+		00 100mV
+		01 200mV
+		10 300mV
+		11 400mV
+	-bit 6: SW_OUT detector is disabled
+	-bit 7: SW_IN detector is enabled.
+- st,usb_control_register:
+	-bit 3: SW_OUT current limit
+		0: 600mA
+		1: 1.1A
+	-bit 4: VBUS_OTG discharge is enabled
+	-bit 5: SW_OUT discharge is enabled
+	-bit 6: VBUS_OTG detection is enabled
+	-bit 7: BOOST_OVP is disabled
+
+
+stpmu1 consists is a varied group of sub-devices:
+
+Device			 Description
+------			------------
+stpmu1-onkey		: On key
+stpmu1-regulators	: Regulators
+stpmu1-wdt		: Watchdog
+
+each sub-device bindings is be described in associated driver
+documentation section.
+
+Example:
+
+pmic: stpmu1@33 {
+	compatible = "st,stpmu1";
+	reg = <0x33>;
+	interrupts = <0 2>;
+	interrupts-extended = <&intc GIC_SPI 149 IRQ_TYPE_NONE>,
+			      <&exti 55 1>;
+	st,version_status = <0x10>;
+	st,main_control_register=<0x0c>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+	onkey {
+		compatible = "st,stpmu1-onkey";
+		interrupt-parent = <&pmic>;
+		interrupts = <7 0>,<6 1>;
+		st,onkey-pwroff-enabled;
+		st,onkey-press-seconds = <10>;
+	};
+
+	watchdog {
+		compatible = "st,stpmu1-wdt";
+	};
+
+	regulators {
+		compatible = "st,stpmu1-regulators";
+
+		vdd_core: regulator@0 {
+			regulator-compatible = "buck1";
+			regulator-name = "vdd_core";
+			regulator-boot-on;
+			regulator-min-microvolt = <700000>;
+			regulator-max-microvolt = <1200000>;
+		};
+		vdd: regulator@1 {
+			regulator-compatible = "buck3";
+			regulator-name = "vdd";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
+			regulator-pull-down;
+		};
+	};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/8] mfd: stpmu1: add stpmu1 pmic driver
From: Pascal PAILLET-LME @ 2018-07-05 15:14 UTC (permalink / raw)
  To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
	mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
	broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
	linux-input@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
	benjamin.gaignard@linaro.org
  Cc: Pascal PAILLET-LME
In-Reply-To: <1530803657-17684-1-git-send-email-p.paillet@st.com>

From: pascal paillet <p.paillet@st.com>

stpmu1 is a pmic from STMicroelectronics. The stpmu1 integrates 10
regulators and 3 switches with various capabilities.

Signed-off-by: pascal paillet <p.paillet@st.com>
---
 drivers/mfd/Kconfig                 |  14 ++
 drivers/mfd/Makefile                |   1 +
 drivers/mfd/stpmu1.c                | 490 ++++++++++++++++++++++++++++++++++++
 include/dt-bindings/mfd/st,stpmu1.h |  46 ++++
 include/linux/mfd/stpmu1.h          | 220 ++++++++++++++++
 5 files changed, 771 insertions(+)
 create mode 100644 drivers/mfd/stpmu1.c
 create mode 100644 include/dt-bindings/mfd/st,stpmu1.h
 create mode 100644 include/linux/mfd/stpmu1.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b860eb5..e15140b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1812,6 +1812,20 @@ config MFD_STM32_TIMERS
 	  for PWM and IIO Timer. This driver allow to share the
 	  registers between the others drivers.
 
+config MFD_STPMU1
+	tristate "Support for STPMU1 PMIC"
+	depends on (I2C=y && OF)
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	select MFD_CORE
+	help
+	  Support for ST Microelectronics STPMU1 PMIC. Stpmu1 mfd driver is
+	  the core driver for stpmu1 component that mainly handles interrupts.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called stpmu1.
+
+
 menu "Multimedia Capabilities Port drivers"
 	depends on ARCH_SA1100
 
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e9fd20d..f1c4be1 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -220,6 +220,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI)	+= intel_soc_pmic_chtdc_ti.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR)	+= altera-a10sr.o
+obj-$(CONFIG_MFD_STPMU1)	+= stpmu1.o
 obj-$(CONFIG_MFD_SUN4I_GPADC)	+= sun4i-gpadc.o
 
 obj-$(CONFIG_MFD_STM32_LPTIMER)	+= stm32-lptimer.o
diff --git a/drivers/mfd/stpmu1.c b/drivers/mfd/stpmu1.c
new file mode 100644
index 0000000..a284a3e
--- /dev/null
+++ b/drivers/mfd/stpmu1.c
@@ -0,0 +1,490 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/stpmu1.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/regmap.h>
+#include <dt-bindings/mfd/st,stpmu1.h>
+
+static bool stpmu1_reg_readable(struct device *dev, unsigned int reg);
+static bool stpmu1_reg_writeable(struct device *dev, unsigned int reg);
+static bool stpmu1_reg_volatile(struct device *dev, unsigned int reg);
+
+const struct regmap_config stpmu1_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = PMIC_MAX_REGISTER_ADDRESS,
+	.readable_reg = stpmu1_reg_readable,
+	.writeable_reg = stpmu1_reg_writeable,
+	.volatile_reg = stpmu1_reg_volatile,
+};
+
+#define FILL_IRQS(_index) \
+	[(_index)] = { \
+		.reg_offset = ((_index) >> 3), \
+		.mask = (1 << (_index % 8)), \
+	}
+
+static const struct regmap_irq stpmu1_irqs[] = {
+	FILL_IRQS(IT_PONKEY_F),
+	FILL_IRQS(IT_PONKEY_R),
+	FILL_IRQS(IT_WAKEUP_F),
+	FILL_IRQS(IT_WAKEUP_R),
+	FILL_IRQS(IT_VBUS_OTG_F),
+	FILL_IRQS(IT_VBUS_OTG_R),
+	FILL_IRQS(IT_SWOUT_F),
+	FILL_IRQS(IT_SWOUT_R),
+
+	FILL_IRQS(IT_CURLIM_BUCK1),
+	FILL_IRQS(IT_CURLIM_BUCK2),
+	FILL_IRQS(IT_CURLIM_BUCK3),
+	FILL_IRQS(IT_CURLIM_BUCK4),
+	FILL_IRQS(IT_OCP_OTG),
+	FILL_IRQS(IT_OCP_SWOUT),
+	FILL_IRQS(IT_OCP_BOOST),
+	FILL_IRQS(IT_OVP_BOOST),
+
+	FILL_IRQS(IT_CURLIM_LDO1),
+	FILL_IRQS(IT_CURLIM_LDO2),
+	FILL_IRQS(IT_CURLIM_LDO3),
+	FILL_IRQS(IT_CURLIM_LDO4),
+	FILL_IRQS(IT_CURLIM_LDO5),
+	FILL_IRQS(IT_CURLIM_LDO6),
+	FILL_IRQS(IT_SHORT_SWOTG),
+	FILL_IRQS(IT_SHORT_SWOUT),
+
+	FILL_IRQS(IT_TWARN_F),
+	FILL_IRQS(IT_TWARN_R),
+	FILL_IRQS(IT_VINLOW_F),
+	FILL_IRQS(IT_VINLOW_R),
+	FILL_IRQS(IT_SWIN_F),
+	FILL_IRQS(IT_SWIN_R),
+};
+
+static const struct regmap_irq_chip stpmu1_regmap_irq_chip = {
+	.name = "pmic_irq",
+	.status_base = INT_PENDING_R1,
+	.mask_base = INT_CLEAR_MASK_R1,
+	.unmask_base = INT_SET_MASK_R1,
+	.ack_base = INT_CLEAR_R1,
+	.num_regs = STPMU1_PMIC_NUM_IRQ_REGS,
+	.irqs = stpmu1_irqs,
+	.num_irqs = ARRAY_SIZE(stpmu1_irqs),
+};
+
+static bool stpmu1_reg_readable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TURN_ON_SR:
+	case TURN_OFF_SR:
+	case ICC_LDO_TURN_OFF_SR:
+	case ICC_BUCK_TURN_OFF_SR:
+	case RREQ_STATE_SR:
+	case VERSION_SR:
+	case SWOFF_PWRCTRL_CR:
+	case PADS_PULL_CR:
+	case BUCKS_PD_CR:
+	case LDO14_PD_CR:
+	case LDO56_VREF_PD_CR:
+	case VBUS_DET_VIN_CR:
+	case PKEY_TURNOFF_CR:
+	case BUCKS_MASK_RANK_CR:
+	case BUCKS_MASK_RESET_CR:
+	case LDOS_MASK_RANK_CR:
+	case LDOS_MASK_RESET_CR:
+	case WCHDG_CR:
+	case WCHDG_TIMER_CR:
+	case BUCKS_ICCTO_CR:
+	case LDOS_ICCTO_CR:
+	case BUCK1_ACTIVE_CR:
+	case BUCK2_ACTIVE_CR:
+	case BUCK3_ACTIVE_CR:
+	case BUCK4_ACTIVE_CR:
+	case VREF_DDR_ACTIVE_CR:
+	case LDO1_ACTIVE_CR:
+	case LDO2_ACTIVE_CR:
+	case LDO3_ACTIVE_CR:
+	case LDO4_ACTIVE_CR:
+	case LDO5_ACTIVE_CR:
+	case LDO6_ACTIVE_CR:
+	case BUCK1_STDBY_CR:
+	case BUCK2_STDBY_CR:
+	case BUCK3_STDBY_CR:
+	case BUCK4_STDBY_CR:
+	case VREF_DDR_STDBY_CR:
+	case LDO1_STDBY_CR:
+	case LDO2_STDBY_CR:
+	case LDO3_STDBY_CR:
+	case LDO4_STDBY_CR:
+	case LDO5_STDBY_CR:
+	case LDO6_STDBY_CR:
+	case BST_SW_CR:
+	case INT_PENDING_R1:
+	case INT_PENDING_R2:
+	case INT_PENDING_R3:
+	case INT_PENDING_R4:
+	case INT_DBG_LATCH_R1:
+	case INT_DBG_LATCH_R2:
+	case INT_DBG_LATCH_R3:
+	case INT_DBG_LATCH_R4:
+	case INT_CLEAR_R1:
+	case INT_CLEAR_R2:
+	case INT_CLEAR_R3:
+	case INT_CLEAR_R4:
+	case INT_MASK_R1:
+	case INT_MASK_R2:
+	case INT_MASK_R3:
+	case INT_MASK_R4:
+	case INT_SET_MASK_R1:
+	case INT_SET_MASK_R2:
+	case INT_SET_MASK_R3:
+	case INT_SET_MASK_R4:
+	case INT_CLEAR_MASK_R1:
+	case INT_CLEAR_MASK_R2:
+	case INT_CLEAR_MASK_R3:
+	case INT_CLEAR_MASK_R4:
+	case INT_SRC_R1:
+	case INT_SRC_R2:
+	case INT_SRC_R3:
+	case INT_SRC_R4:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool stpmu1_reg_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case SWOFF_PWRCTRL_CR:
+	case PADS_PULL_CR:
+	case BUCKS_PD_CR:
+	case LDO14_PD_CR:
+	case LDO56_VREF_PD_CR:
+	case VBUS_DET_VIN_CR:
+	case PKEY_TURNOFF_CR:
+	case BUCKS_MASK_RANK_CR:
+	case BUCKS_MASK_RESET_CR:
+	case LDOS_MASK_RANK_CR:
+	case LDOS_MASK_RESET_CR:
+	case WCHDG_CR:
+	case WCHDG_TIMER_CR:
+	case BUCKS_ICCTO_CR:
+	case LDOS_ICCTO_CR:
+	case BUCK1_ACTIVE_CR:
+	case BUCK2_ACTIVE_CR:
+	case BUCK3_ACTIVE_CR:
+	case BUCK4_ACTIVE_CR:
+	case VREF_DDR_ACTIVE_CR:
+	case LDO1_ACTIVE_CR:
+	case LDO2_ACTIVE_CR:
+	case LDO3_ACTIVE_CR:
+	case LDO4_ACTIVE_CR:
+	case LDO5_ACTIVE_CR:
+	case LDO6_ACTIVE_CR:
+	case BUCK1_STDBY_CR:
+	case BUCK2_STDBY_CR:
+	case BUCK3_STDBY_CR:
+	case BUCK4_STDBY_CR:
+	case VREF_DDR_STDBY_CR:
+	case LDO1_STDBY_CR:
+	case LDO2_STDBY_CR:
+	case LDO3_STDBY_CR:
+	case LDO4_STDBY_CR:
+	case LDO5_STDBY_CR:
+	case LDO6_STDBY_CR:
+	case BST_SW_CR:
+	case INT_DBG_LATCH_R1:
+	case INT_DBG_LATCH_R2:
+	case INT_DBG_LATCH_R3:
+	case INT_DBG_LATCH_R4:
+	case INT_CLEAR_R1:
+	case INT_CLEAR_R2:
+	case INT_CLEAR_R3:
+	case INT_CLEAR_R4:
+	case INT_SET_MASK_R1:
+	case INT_SET_MASK_R2:
+	case INT_SET_MASK_R3:
+	case INT_SET_MASK_R4:
+	case INT_CLEAR_MASK_R1:
+	case INT_CLEAR_MASK_R2:
+	case INT_CLEAR_MASK_R3:
+	case INT_CLEAR_MASK_R4:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool stpmu1_reg_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TURN_ON_SR:
+	case TURN_OFF_SR:
+	case ICC_LDO_TURN_OFF_SR:
+	case ICC_BUCK_TURN_OFF_SR:
+	case RREQ_STATE_SR:
+	case INT_PENDING_R1:
+	case INT_PENDING_R2:
+	case INT_PENDING_R3:
+	case INT_PENDING_R4:
+	case INT_SRC_R1:
+	case INT_SRC_R2:
+	case INT_SRC_R3:
+	case INT_SRC_R4:
+	case WCHDG_CR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int stpmu1_configure_from_dt(struct stpmu1_dev *pmic_dev)
+{
+	struct device_node *np = pmic_dev->np;
+	u32 reg = 0;
+	int ret = 0;
+	int irq;
+
+	irq = of_irq_get(np, 0);
+	if (irq <= 0) {
+		dev_err(pmic_dev->dev,
+			"Failed to get irq config: %d\n", irq);
+		return irq ? irq : -ENODEV;
+	}
+	pmic_dev->irq = irq;
+
+	irq = of_irq_get(np, 1);
+	if (irq <= 0) {
+		dev_err(pmic_dev->dev,
+			"Failed to get irq_wake config: %d\n", irq);
+		return irq ? irq : -ENODEV;
+	}
+	pmic_dev->irq_wake = irq;
+
+	device_init_wakeup(pmic_dev->dev, true);
+	ret = dev_pm_set_dedicated_wake_irq(pmic_dev->dev, pmic_dev->irq_wake);
+	if (ret)
+		dev_warn(pmic_dev->dev, "failed to set up wakeup irq");
+
+	if (!of_property_read_u32(np, "st,main_control_register", &reg)) {
+		ret = regmap_update_bits(pmic_dev->regmap,
+					 SWOFF_PWRCTRL_CR,
+					 PWRCTRL_POLARITY_HIGH |
+					 PWRCTRL_PIN_VALID |
+					 RESTART_REQUEST_ENABLED,
+					 reg);
+		if (ret) {
+			dev_err(pmic_dev->dev,
+				"Failed to update main control register: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	if (!of_property_read_u32(np, "st,pads_pull_register", &reg)) {
+		ret = regmap_update_bits(pmic_dev->regmap,
+					 PADS_PULL_CR,
+					 WAKEUP_DETECTOR_DISABLED |
+					 PWRCTRL_PD_ACTIVE |
+					 PWRCTRL_PU_ACTIVE |
+					 WAKEUP_PD_ACTIVE,
+					 reg);
+		if (ret) {
+			dev_err(pmic_dev->dev,
+				"Failed to update pads control register: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	if (!of_property_read_u32(np, "st,vin_control_register", &reg)) {
+		ret = regmap_update_bits(pmic_dev->regmap,
+					 VBUS_DET_VIN_CR,
+					 VINLOW_CTRL_REG_MASK,
+					 reg);
+		if (ret) {
+			dev_err(pmic_dev->dev,
+				"Failed to update vin control register: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	if (!of_property_read_u32(np, "st,usb_control_register", &reg)) {
+		ret = regmap_update_bits(pmic_dev->regmap, BST_SW_CR,
+					 BOOST_OVP_DISABLED |
+					 VBUS_OTG_DETECTION_DISABLED |
+					 SW_OUT_DISCHARGE |
+					 VBUS_OTG_DISCHARGE |
+					 OCP_LIMIT_HIGH,
+					 reg);
+		if (ret) {
+			dev_err(pmic_dev->dev,
+				"Failed to update usb control register: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int stpmu1_device_init(struct stpmu1_dev *pmic_dev)
+{
+	int ret;
+	unsigned int val;
+
+	pmic_dev->regmap =
+	    devm_regmap_init_i2c(pmic_dev->i2c, &stpmu1_regmap_config);
+
+	if (IS_ERR(pmic_dev->regmap)) {
+		ret = PTR_ERR(pmic_dev->regmap);
+		dev_err(pmic_dev->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = stpmu1_configure_from_dt(pmic_dev);
+	if (ret < 0) {
+		dev_err(pmic_dev->dev,
+			"Unable to configure PMIC from Device Tree: %d\n", ret);
+		return ret;
+	}
+
+	/* Read Version ID */
+	ret = regmap_read(pmic_dev->regmap, VERSION_SR, &val);
+	if (ret < 0) {
+		dev_err(pmic_dev->dev, "Unable to read pmic version\n");
+		return ret;
+	}
+	dev_dbg(pmic_dev->dev, "PMIC Chip Version: 0x%x\n", val);
+
+	/* Initialize PMIC IRQ Chip & IRQ domains associated */
+	ret = devm_regmap_add_irq_chip(pmic_dev->dev, pmic_dev->regmap,
+				       pmic_dev->irq,
+				       IRQF_ONESHOT | IRQF_SHARED,
+				       0, &stpmu1_regmap_irq_chip,
+				       &pmic_dev->irq_data);
+	if (ret < 0) {
+		dev_err(pmic_dev->dev, "IRQ Chip registration failed: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id stpmu1_dt_match[] = {
+	{.compatible = "st,stpmu1"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, stpmu1_dt_match);
+
+static int stpmu1_remove(struct i2c_client *i2c)
+{
+	struct stpmu1_dev *pmic_dev = i2c_get_clientdata(i2c);
+
+	of_platform_depopulate(pmic_dev->dev);
+
+	return 0;
+}
+
+static int stpmu1_probe(struct i2c_client *i2c,
+			const struct i2c_device_id *id)
+{
+	struct stpmu1_dev *pmic;
+	struct device *dev = &i2c->dev;
+	int ret = 0;
+
+	pmic = devm_kzalloc(dev, sizeof(struct stpmu1_dev), GFP_KERNEL);
+	if (!pmic)
+		return -ENOMEM;
+
+	pmic->np = dev->of_node;
+
+	dev_set_drvdata(dev, pmic);
+	pmic->dev = dev;
+	pmic->i2c = i2c;
+
+	ret = stpmu1_device_init(pmic);
+	if (ret < 0)
+		goto err;
+
+	ret = of_platform_populate(pmic->np, NULL, NULL, pmic->dev);
+
+	dev_dbg(dev, "stpmu1 driver probed\n");
+err:
+	return ret;
+}
+
+static const struct i2c_device_id stpmu1_id[] = {
+	{"stpmu1", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, stpmu1_id);
+
+#ifdef CONFIG_PM_SLEEP
+static int stpmu1_suspend(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct stpmu1_dev *pmic_dev = i2c_get_clientdata(i2c);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(pmic_dev->irq_wake);
+
+	disable_irq(pmic_dev->irq);
+	return 0;
+}
+
+static int stpmu1_resume(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct stpmu1_dev *pmic_dev = i2c_get_clientdata(i2c);
+
+	regcache_sync(pmic_dev->regmap);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(pmic_dev->irq_wake);
+
+	enable_irq(pmic_dev->irq);
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stpmu1_pm, stpmu1_suspend, stpmu1_resume);
+
+static struct i2c_driver stpmu1_driver = {
+	.driver = {
+		   .name = "stpmu1",
+		   .owner = THIS_MODULE,
+		   .pm = &stpmu1_pm,
+		   .of_match_table = of_match_ptr(stpmu1_dt_match),
+		   },
+	.probe = stpmu1_probe,
+	.remove = stpmu1_remove,
+	.id_table = stpmu1_id,
+};
+
+module_i2c_driver(stpmu1_driver);
+
+MODULE_DESCRIPTION("STPMU1 PMIC I2C Client");
+MODULE_AUTHOR("<philippe.peurichard@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/mfd/st,stpmu1.h b/include/dt-bindings/mfd/st,stpmu1.h
new file mode 100644
index 0000000..2d3bdf1
--- /dev/null
+++ b/include/dt-bindings/mfd/st,stpmu1.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#ifndef __DT_BINDINGS_STPMU1_H__
+#define __DT_BINDINGS_STPMU1_H__
+
+/* IRQ definitions */
+#define IT_PONKEY_F 0
+#define IT_PONKEY_R 1
+#define IT_WAKEUP_F 2
+#define IT_WAKEUP_R 3
+#define IT_VBUS_OTG_F 4
+#define IT_VBUS_OTG_R 5
+#define IT_SWOUT_F 6
+#define IT_SWOUT_R 7
+
+#define IT_CURLIM_BUCK1 8
+#define IT_CURLIM_BUCK2 9
+#define IT_CURLIM_BUCK3 10
+#define IT_CURLIM_BUCK4 11
+#define IT_OCP_OTG 12
+#define IT_OCP_SWOUT 13
+#define IT_OCP_BOOST 14
+#define IT_OVP_BOOST 15
+
+#define IT_CURLIM_LDO1 16
+#define IT_CURLIM_LDO2 17
+#define IT_CURLIM_LDO3 18
+#define IT_CURLIM_LDO4 19
+#define IT_CURLIM_LDO5 20
+#define IT_CURLIM_LDO6 21
+#define IT_SHORT_SWOTG 22
+#define IT_SHORT_SWOUT 23
+
+#define IT_TWARN_F 24
+#define IT_TWARN_R 25
+#define IT_VINLOW_F 26
+#define IT_VINLOW_R 27
+#define IT_SWIN_F 30
+#define IT_SWIN_R 31
+
+#endif /* __DT_BINDINGS_STPMU1_H__ */
diff --git a/include/linux/mfd/stpmu1.h b/include/linux/mfd/stpmu1.h
new file mode 100644
index 0000000..05fd029
--- /dev/null
+++ b/include/linux/mfd/stpmu1.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#ifndef __LINUX_MFD_STPMU1_H
+#define __LINUX_MFD_STPMU1_H
+
+#define TURN_ON_SR		0x1
+#define TURN_OFF_SR		0x2
+#define ICC_LDO_TURN_OFF_SR	0x3
+#define ICC_BUCK_TURN_OFF_SR	0x4
+#define RREQ_STATE_SR		0x5
+#define VERSION_SR		0x6
+
+#define SWOFF_PWRCTRL_CR	0x10
+#define PADS_PULL_CR		0x11
+#define BUCKS_PD_CR		0x12
+#define LDO14_PD_CR		0x13
+#define LDO56_VREF_PD_CR	0x14
+#define VBUS_DET_VIN_CR		0x15
+#define PKEY_TURNOFF_CR		0x16
+#define BUCKS_MASK_RANK_CR	0x17
+#define BUCKS_MASK_RESET_CR	0x18
+#define LDOS_MASK_RANK_CR	0x19
+#define LDOS_MASK_RESET_CR	0x1A
+#define WCHDG_CR		0x1B
+#define WCHDG_TIMER_CR		0x1C
+#define BUCKS_ICCTO_CR		0x1D
+#define LDOS_ICCTO_CR		0x1E
+
+#define BUCK1_ACTIVE_CR		0x20
+#define BUCK2_ACTIVE_CR		0x21
+#define BUCK3_ACTIVE_CR		0x22
+#define BUCK4_ACTIVE_CR		0x23
+#define VREF_DDR_ACTIVE_CR	0x24
+#define LDO1_ACTIVE_CR		0x25
+#define LDO2_ACTIVE_CR		0x26
+#define LDO3_ACTIVE_CR		0x27
+#define LDO4_ACTIVE_CR		0x28
+#define LDO5_ACTIVE_CR		0x29
+#define LDO6_ACTIVE_CR		0x2A
+
+#define BUCK1_STDBY_CR		0x30
+#define BUCK2_STDBY_CR		0x31
+#define BUCK3_STDBY_CR		0x32
+#define BUCK4_STDBY_CR		0x33
+#define VREF_DDR_STDBY_CR	0x34
+#define LDO1_STDBY_CR		0x35
+#define LDO2_STDBY_CR		0x36
+#define LDO3_STDBY_CR		0x37
+#define LDO4_STDBY_CR		0x38
+#define LDO5_STDBY_CR		0x39
+#define LDO6_STDBY_CR		0x3A
+
+#define BST_SW_CR		0x40
+
+#define INT_PENDING_R1		0x50
+#define INT_PENDING_R2		0x51
+#define INT_PENDING_R3		0x52
+#define INT_PENDING_R4		0x53
+
+#define INT_DBG_LATCH_R1	0x60
+#define INT_DBG_LATCH_R2	0x61
+#define INT_DBG_LATCH_R3	0x62
+#define INT_DBG_LATCH_R4	0x63
+
+#define INT_CLEAR_R1		0x70
+#define INT_CLEAR_R2		0x71
+#define INT_CLEAR_R3		0x72
+#define INT_CLEAR_R4		0x73
+
+#define INT_MASK_R1		0x80
+#define INT_MASK_R2		0x81
+#define INT_MASK_R3		0x82
+#define INT_MASK_R4		0x83
+
+#define INT_SET_MASK_R1		0x90
+#define INT_SET_MASK_R2		0x91
+#define INT_SET_MASK_R3		0x92
+#define INT_SET_MASK_R4		0x93
+
+#define INT_CLEAR_MASK_R1	0xA0
+#define INT_CLEAR_MASK_R2	0xA1
+#define INT_CLEAR_MASK_R3	0xA2
+#define INT_CLEAR_MASK_R4	0xA3
+
+#define INT_SRC_R1		0xB0
+#define INT_SRC_R2		0xB1
+#define INT_SRC_R3		0xB2
+#define INT_SRC_R4		0xB3
+
+#define PMIC_MAX_REGISTER_ADDRESS INT_SRC_R4
+
+#define STPMU1_PMIC_NUM_IRQ_REGS 4
+
+#define TURN_OFF_SR_ICC_EVENT	0x08
+
+#define LDO_VOLTAGE_MASK		GENMASK(6, 2)
+#define BUCK_VOLTAGE_MASK		GENMASK(7, 2)
+#define LDO_BUCK_VOLTAGE_SHIFT		2
+
+#define LDO_ENABLE_MASK			BIT(0)
+#define BUCK_ENABLE_MASK		BIT(0)
+
+#define BUCK_HPLP_ENABLE_MASK		BIT(1)
+#define BUCK_HPLP_SHIFT			1
+
+#define STDBY_ENABLE_MASK  BIT(0)
+
+#define BUCKS_PD_CR_REG_MASK	GENMASK(7, 0)
+#define BUCK_MASK_RANK_REGISTER_MASK	GENMASK(3, 0)
+#define BUCK_MASK_RESET_REGISTER_MASK	GENMASK(3, 0)
+#define LDO1234_PULL_DOWN_REGISTER_MASK	GENMASK(7, 0)
+#define LDO56_VREF_PD_CR_REG_MASK	GENMASK(5, 0)
+#define LDO_MASK_RANK_REGISTER_MASK	GENMASK(5, 0)
+#define LDO_MASK_RESET_REGISTER_MASK	GENMASK(5, 0)
+
+#define BUCK1_PULL_DOWN_REG		BUCKS_PD_CR
+#define BUCK1_PULL_DOWN_MASK		BIT(0)
+#define BUCK2_PULL_DOWN_REG		BUCKS_PD_CR
+#define BUCK2_PULL_DOWN_MASK		BIT(2)
+#define BUCK3_PULL_DOWN_REG		BUCKS_PD_CR
+#define BUCK3_PULL_DOWN_MASK		BIT(4)
+#define BUCK4_PULL_DOWN_REG		BUCKS_PD_CR
+#define BUCK4_PULL_DOWN_MASK		BIT(6)
+
+#define LDO1_PULL_DOWN_REG		LDO14_PD_CR
+#define LDO1_PULL_DOWN_MASK		BIT(0)
+#define LDO2_PULL_DOWN_REG		LDO14_PD_CR
+#define LDO2_PULL_DOWN_MASK		BIT(2)
+#define LDO3_PULL_DOWN_REG		LDO14_PD_CR
+#define LDO3_PULL_DOWN_MASK		BIT(4)
+#define LDO4_PULL_DOWN_REG		LDO14_PD_CR
+#define LDO4_PULL_DOWN_MASK		BIT(6)
+#define LDO5_PULL_DOWN_REG		LDO56_VREF_PD_CR
+#define LDO5_PULL_DOWN_MASK		BIT(0)
+#define LDO6_PULL_DOWN_REG		LDO56_VREF_PD_CR
+#define LDO6_PULL_DOWN_MASK		BIT(2)
+#define VREF_DDR_PULL_DOWN_REG		LDO56_VREF_PD_CR
+#define VREF_DDR_PULL_DOWN_MASK		BIT(4)
+
+#define BUCKS_ICCTO_CR_REG_MASK	GENMASK(6, 0)
+#define LDOS_ICCTO_CR_REG_MASK	GENMASK(5, 0)
+
+#define LDO_BYPASS_MASK			BIT(7)
+
+/* Main PMIC Control Register
+ * SWOFF_PWRCTRL_CR
+ * Address : 0x10
+ */
+#define ICC_EVENT_ENABLED		BIT(4)
+#define PWRCTRL_POLARITY_HIGH		BIT(3)
+#define PWRCTRL_PIN_VALID		BIT(2)
+#define RESTART_REQUEST_ENABLED		BIT(1)
+#define SOFTWARE_SWITCH_OFF_ENABLED	BIT(0)
+
+/* Main PMIC PADS Control Register
+ * PADS_PULL_CR
+ * Address : 0x11
+ */
+#define WAKEUP_DETECTOR_DISABLED	BIT(4)
+#define PWRCTRL_PD_ACTIVE		BIT(3)
+#define PWRCTRL_PU_ACTIVE		BIT(2)
+#define WAKEUP_PD_ACTIVE		BIT(1)
+#define PONKEY_PU_ACTIVE		BIT(0)
+
+/* Main PMIC VINLOW Control Register
+ * VBUS_DET_VIN_CRC DMSC
+ * Address : 0x15
+ */
+#define SWIN_DETECTOR_ENABLED		BIT(7)
+#define SWOUT_DETECTOR_ENABLED		BIT(6)
+#define VINLOW_ENABLED			BIT(0)
+#define VINLOW_CTRL_REG_MASK		GENMASK(7, 0)
+
+/* USB Control Register
+ * Address : 0x40
+ */
+#define BOOST_OVP_DISABLED		BIT(7)
+#define VBUS_OTG_DETECTION_DISABLED	BIT(6)
+#define SW_OUT_DISCHARGE		BIT(5)
+#define VBUS_OTG_DISCHARGE		BIT(4)
+#define OCP_LIMIT_HIGH			BIT(3)
+#define SWIN_SWOUT_ENABLED		BIT(2)
+#define USBSW_OTG_SWITCH_ENABLED	BIT(1)
+#define BOOST_ENABLED			BIT(0)
+
+/* PKEY_TURNOFF_CR
+ * Address : 0x16
+ */
+#define PONKEY_PWR_OFF			BIT(7)
+#define PONKEY_CC_FLAG_CLEAR		BIT(6)
+#define PONKEY_TURNOFF_TIMER_MASK	GENMASK(3, 0)
+#define PONKEY_TURNOFF_MASK		GENMASK(7, 0)
+
+/*
+ * struct stpmu1_dev - stpmu1 master device for sub-drivers
+ * @dev: master device of the chip (can be used to access platform data)
+ * @i2c: i2c client private data for regulator
+ * @np: device DT node pointer
+ * @irq_base: base IRQ numbers
+ * @irq: generic IRQ number
+ * @irq_wake: wakeup IRQ number
+ * @regmap_irq_chip_data: irq chip data
+ */
+struct stpmu1_dev {
+	struct device *dev;
+	struct i2c_client *i2c;
+	struct regmap *regmap;
+	struct device_node *np;
+	unsigned int irq_base;
+	int irq;
+	int irq_wake;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+#endif /*  __LINUX_MFD_STPMU1_H */
-- 
1.9.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox