Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH] dt-binding: soc: qcom: smd: Add label property
From: Rob Herring @ 2016-10-26 22:08 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Andy Gross, David Brown, Mark Rutland, linux-arm-msm, linux-soc,
	devicetree, linux-kernel
In-Reply-To: <1476931090-1616-1-git-send-email-bjorn.andersson@linaro.org>

On Wed, Oct 19, 2016 at 07:38:10PM -0700, Bjorn Andersson wrote:
> The label property can be used to specify a name of the edge, for
> consistent naming purposes.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt | 7 +++++++
>  1 file changed, 7 insertions(+)

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

^ permalink raw reply

* RE: [PATCH 1/6] dt/bindings: adjust bindings for Layerscape SCFG MSI
From: Leo Li @ 2016-10-26 22:09 UTC (permalink / raw)
  To: Mark Rutland, M.H. Lian
  Cc: devicetree@vger.kernel.org, Marc Zyngier, Stuart Yoder,
	linux-kernel@vger.kernel.org, Scott Wood, Mingkai Hu, Shawn Guo,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20161026103101.GC19965@leverpostej>



> -----Original Message-----
> From: Mark Rutland [mailto:mark.rutland@arm.com]
> Sent: Wednesday, October 26, 2016 5:31 AM
> To: M.H. Lian <minghuan.lian@nxp.com>
> Cc: linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org; Marc Zyngier <marc.zyngier@arm.com>; Stuart
> Yoder <stuart.yoder@nxp.com>; Leo Li <leoyang.li@nxp.com>; Scott Wood
> <scott.wood@nxp.com>; Shawn Guo <shawnguo@kernel.org>; Mingkai Hu
> <mingkai.hu@nxp.com>
> Subject: Re: [PATCH 1/6] dt/bindings: adjust bindings for Layerscape SCFG MSI
> 
> On Tue, Oct 25, 2016 at 08:35:40PM +0800, Minghuan Lian wrote:
> > 1. The different version of a SoC may have different MSI
> > implementation. But compatible "fsl,<soc-name>-msi" can not describe
> > the SoC version.
> 
> Surely, "fsl,<soc-name>-<rev>-msi" can describe this?
> 
> If the hardware differs, it needs a new compatible string.
> 
> If there's some configuration value that varies across revisions (e.g.
> number of slots), you can add a proeprty to describe that explciitly.
> 
> > The MSI driver will use SoC match interface to get SoC type and
> > version instead of compatible string. So all MSI node can use the
> > common compatible "fsl,ls-scfg-msi" and the original compatible is
> > unnecessary.
> >
> > 2. Layerscape SoCs may have one or several MSI controllers.
> > In order to increase MSI interrupt number of a PCIe, the patch moves
> > all MSI node into the parent node "msi-controller". So a PCIe can
> > request MSI from all the MSI controllers.
> 
> This is not necessary, and does not represent a real block of hardware.
> So NAK for this approach.
> 
> The msi-parent property can contain a list of MSI controllers. See the examples
> in Documentation/devicetree/bindings/interrupt-controller/msi.txt.
> Likewise, the msi-map property can map to a number of MSI controllers.
> 
> If the core code can only consider one at a time, then that's an issue to be
> addressed in core code, not one to be bodged around in bindings.
> 
> >
> > Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> > ---
> >  .../interrupt-controller/fsl,ls-scfg-msi.txt       | 57 +++++++++++++++++++---
> >  1 file changed, 49 insertions(+), 8 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-m
> > si.txt
> > b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-m
> > si.txt
> > index 9e38949..29f95fd 100644
> > ---
> > a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-m
> > si.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-sc
> > +++ fg-msi.txt
> > @@ -1,18 +1,28 @@
> >  * Freescale Layerscape SCFG PCIe MSI controller
> >
> > +Layerscape SoCs may have one or multiple MSI controllers.
> > +Each MSI controller must be showed as a child node.
> > +
> >  Required properties:
> >
> > -- compatible: should be "fsl,<soc-name>-msi" to identify
> > -	      Layerscape PCIe MSI controller block such as:
> > -              "fsl,1s1021a-msi"
> > -              "fsl,1s1043a-msi"
> > +- compatible: should be "fsl,ls-scfg-msi"
> 
> This breaks old DTBs, and throws away information which you describe above as
> valuable. So another NAK for that.

I agree with you that we should maintain the backward compatibility.  But on the other hand, I just found that there is a silly typo in the original binding that "ls" is wrongly spelled as "1s" and they look too close to be noticed in previous patch reviews.  :(  The driver and all the DTSes used the binding with the typo which covered up the problem.  So even if we want to keep the "fsl,<soc-name>-msi" binding, we probably want to fix the typo, right?  And that breaks the backward compatibility too.

Regards,
Leo

^ permalink raw reply

* Re: [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Rob Herring @ 2016-10-26 22:13 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Maxime Ripard, David Airlie, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20161020034344.14154-2-wens-jdAy2FN1RRM@public.gmane.org>

On Thu, Oct 20, 2016 at 11:43:37AM +0800, Chen-Yu Tsai wrote:
> Some rgb-to-vga bridges have an enable GPIO, either directly tied to
> an enable pin on the bridge IC, or indirectly controlling a power
> switch.
> 
> Add support for it.
> 
> Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
> ---
>  .../bindings/display/bridge/dumb-vga-dac.txt       |  2 ++
>  drivers/gpu/drm/bridge/dumb-vga-dac.c              | 28 ++++++++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> index 003bc246a270..d3484822bf77 100644
> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> @@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
>  - Video port 0 for RGB input
>  - Video port 1 for VGA output
>  
> +Optional properties:
> +- enable-gpios: GPIO pin to enable or disable the bridge

This should also define the active state.

> +static void dumb_vga_enable(struct drm_bridge *bridge)
> +{
> +	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +
> +	if (vga->enable_gpio)
> +		gpiod_set_value_cansleep(vga->enable_gpio, 1);

So the driver should allow either active high or low.

> +}
> +
> +static void dumb_vga_disable(struct drm_bridge *bridge)
> +{
> +	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +
> +	if (vga->enable_gpio)
> +		gpiod_set_value_cansleep(vga->enable_gpio, 0);
> +}
> +

^ permalink raw reply

* Re: [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Maxime Ripard @ 2016-10-26 22:17 UTC (permalink / raw)
  To: Rob Herring
  Cc: Chen-Yu Tsai, David Airlie, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20161026221346.tdpmbrwca4jehch2@rob-hp-laptop>

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

Hi Rob,

On Wed, Oct 26, 2016 at 05:13:46PM -0500, Rob Herring wrote:
> On Thu, Oct 20, 2016 at 11:43:37AM +0800, Chen-Yu Tsai wrote:
> > Some rgb-to-vga bridges have an enable GPIO, either directly tied to
> > an enable pin on the bridge IC, or indirectly controlling a power
> > switch.
> > 
> > Add support for it.
> > 
> > Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
> > ---
> >  .../bindings/display/bridge/dumb-vga-dac.txt       |  2 ++
> >  drivers/gpu/drm/bridge/dumb-vga-dac.c              | 28 ++++++++++++++++++++++
> >  2 files changed, 30 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> > index 003bc246a270..d3484822bf77 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> > +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> > @@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
> >  - Video port 0 for RGB input
> >  - Video port 1 for VGA output
> >  
> > +Optional properties:
> > +- enable-gpios: GPIO pin to enable or disable the bridge
> 
> This should also define the active state.
> 
> > +static void dumb_vga_enable(struct drm_bridge *bridge)
> > +{
> > +	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> > +
> > +	if (vga->enable_gpio)
> > +		gpiod_set_value_cansleep(vga->enable_gpio, 1);
> 
> So the driver should allow either active high or low.

You mean like having a enable-active-high property? Isn't that
redundant with the GPIO flags?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH 1/2] of, numa: Add function to disable of_node_to_nid().
From: Robert Richter @ 2016-10-26 22:21 UTC (permalink / raw)
  To: David Daney
  Cc: devicetree, David Daney, Catalin Marinas, Will Deacon,
	linux-kernel, Gilbert Netzer, Rob Herring, Hanjun Guo,
	Ganapatrao Kulkarni, Frank Rowand, linux-arm-kernel, Mel Gorman,
	linux-mm
In-Reply-To: <5810E112.3070908@caviumnetworks.com>

There has been some significant rework around
__alloc_pages_nodemask(), adding Mel and linux-mm.

-Robert

On 26.10.16 10:00:02, David Daney wrote:
> On 10/26/2016 06:43 AM, Robert Richter wrote:
> >On 25.10.16 14:31:00, David Daney wrote:
> >>From: David Daney <david.daney@cavium.com>
> >>
> >>On arm64 NUMA kernels we can pass "numa=off" on the command line to
> >>disable NUMA.  A side effect of this is that kmalloc_node() calls to
> >>non-zero nodes will crash the system with an OOPS:
> >>
> >>[    0.000000] [<fffffc00081bba84>] __alloc_pages_nodemask+0xa4/0xe68
> >>[    0.000000] [<fffffc00082163a8>] new_slab+0xd0/0x57c
> >>[    0.000000] [<fffffc000821879c>] ___slab_alloc+0x2e4/0x514
> >>[    0.000000] [<fffffc000823882c>] __slab_alloc+0x48/0x58
> >>[    0.000000] [<fffffc00082195a0>] __kmalloc_node+0xd0/0x2e0
> >>[    0.000000] [<fffffc00081119b8>] __irq_domain_add+0x7c/0x164
> >>[    0.000000] [<fffffc0008b75d30>] its_probe+0x784/0x81c
> >>[    0.000000] [<fffffc0008b75e10>] its_init+0x48/0x1b0
> >>.
> >>.
> >>.
> >>
> >>This is caused by code like this in kernel/irq/irqdomain.c
> >>
> >>     domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
> >>                   GFP_KERNEL, of_node_to_nid(of_node));
> >>
> >>When NUMA is disabled, the concept of a node is really undefined, so
> >>of_node_to_nid() should unconditionally return NUMA_NO_NODE.
> >>
> >>Add __of_force_no_numa() to allow of_node_to_nid() to be forced to
> >>return NUMA_NO_NODE.
> >>
> >>The follow on patch will call this new function from the arm64 numa
> >>code.
> >
> >Didn't that work before?
> 
> I am fairly certain that it used to work.
> 
> >numa=off just maps all mem to node 0.
> 
> Yes, that is the current behavior.
> 
> >If mem
> >allocation is requested for another node it should just fall back to a
> >node with mem (node 0 then).
> 
> This is the root of the problem.  The ITS code is allocating memory. It
> calls of_node_to_nid() to determine which node it resides on.  The answer in
> the failing case is node-1.  Since we have mapped all the memory to node-0
> the  __kmalloc_node(..., 1) call fails with the OOPS shown.
> 
> It could be that __kmalloc_node() used to allocate memory on a node other
> than the requested node if the request couldn't be met.  But in v4.8 and
> later it produces that OOPS.
> 
> If you pass a node containing free memory or NUMA_NO_NODE to
> __kmalloc_node(), the allocation succeeds.
> 
> When we first did these patches, I advocated removing the numa=off feature,
> and requiring people to install usable firmware on their systems.  That was
> rejected on the grounds that not everybody has the ability to change their
> firmware and we would like to allow NUMA kernels to run on systems with
> defective firmware by supplying this command line parameter.  Now that I
> have seen requests from the wild for this, I think it is a good idea to
> allow numa=off to be used to work around this bad firmware.
> 
> The change in this patch set is fairly small, and seems to get the job done.
> An alternative would be to change __kmalloc_node() to ignore the node
> parameter if the request cannot be made, but I assume that there were good
> reasons to have the current behavior, so that would be a much more
> complicated change to make.
> 
> 
> 
> >I suspect there is something wrong with
> >the page initialization, see:
> >
> >  http://www.spinics.net/lists/arm-kernel/msg535191.html
> >  https://bugzilla.redhat.com/show_bug.cgi?id=1387793
> >
> >What is the complete oops?
> >
> >So I think k*alloc_node() must be able to handle requests to
> >non-existing nodes. Otherwise your fix is incomplete, assume a failed
> >of_numa_init() causing a dummy init but still some devices reporting a
> >node.
> 
> .
> .
> .
> EFI stub: Booting Linux Kernel...
> EFI stub: Using DTB from configuration table
> EFI stub: Exiting boot services and installing virtual address map...
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 4.8.0-rc8-dd (ddaney@localhost.localdomain)
> (gcc version 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) ) #29 SMP Tue Sep 27
> 15:50:35 PDT 2016
> [    0.000000] Boot CPU: AArch64 Processor [431f0a10]
> [    0.000000] NUMA turned off
> [    0.000000] earlycon: pl11 at MMIO 0x000087e024000000 (options '')
> [    0.000000] bootconsole [pl11] enabled
> [    0.000000] efi: Getting EFI parameters from FDT:
> [    0.000000] efi: EFI v2.40 by Cavium Thunder cn88xx EFI
> jenkins_weekly_build_40-0-ga1f880f Sep 13 2016 17:05:35
> [    0.000000] efi:  ACPI=0xfffff000  ACPI 2.0=0xfffff014  SMBIOS
> 3.0=0x10ffafcf000
> [    0.000000] cma: Reserved 512 MiB at 0x00000000c0000000
> [    0.000000] NUMA disabled
> [    0.000000] NUMA: Faking a node at [mem
> 0x0000000000000000-0x0000010fffffffff]
> [    0.000000] NUMA: Adding memblock [0x1400000 - 0xfffdffff] on node 0
> [    0.000000] NUMA: Adding memblock [0xfffe0000 - 0xffffffff] on node 0
> [    0.000000] NUMA: Adding memblock [0x100000000 - 0xfffffffff] on node 0
> [    0.000000] NUMA: Adding memblock [0x10000400000 - 0x10ffa38ffff] on node
> 0
> [    0.000000] NUMA: Adding memblock [0x10ffa390000 - 0x10ffa41ffff] on node
> 0
> [    0.000000] NUMA: Adding memblock [0x10ffa420000 - 0x10ffaeaffff] on node
> 0
> [    0.000000] NUMA: Adding memblock [0x10ffaeb0000 - 0x10ffaffffff] on node
> 0
> [    0.000000] NUMA: Adding memblock [0x10ffb000000 - 0x10ffffaffff] on node
> 0
> [    0.000000] NUMA: Adding memblock [0x10ffffb0000 - 0x10fffffffff] on node
> 0
> [    0.000000] NUMA: Initmem setup node 0 [mem 0x01400000-0x10fffffffff]
> [    0.000000] NUMA: NODE_DATA [mem 0x10ffffae480-0x10ffffaff7f]
> [    0.000000] Zone ranges:
> [    0.000000]   DMA      [mem 0x0000000001400000-0x00000000ffffffff]
> [    0.000000]   Normal   [mem 0x0000000100000000-0x0000010fffffffff]
> [    0.000000] Movable zone start for each node
> [    0.000000] Early memory node ranges
> [    0.000000]   node   0: [mem 0x0000000001400000-0x00000000fffdffff]
> [    0.000000]   node   0: [mem 0x00000000fffe0000-0x00000000ffffffff]
> [    0.000000]   node   0: [mem 0x0000000100000000-0x0000000fffffffff]
> [    0.000000]   node   0: [mem 0x0000010000400000-0x0000010ffa38ffff]
> [    0.000000]   node   0: [mem 0x0000010ffa390000-0x0000010ffa41ffff]
> [    0.000000]   node   0: [mem 0x0000010ffa420000-0x0000010ffaeaffff]
> [    0.000000]   node   0: [mem 0x0000010ffaeb0000-0x0000010ffaffffff]
> [    0.000000]   node   0: [mem 0x0000010ffb000000-0x0000010ffffaffff]
> [    0.000000]   node   0: [mem 0x0000010ffffb0000-0x0000010fffffffff]
> [    0.000000] Initmem setup node 0 [mem
> 0x0000000001400000-0x0000010fffffffff]
> [    0.000000] psci: probing for conduit method from DT.
> [    0.000000] psci: PSCIv0.2 detected in firmware.
> [    0.000000] psci: Using standard PSCI v0.2 function IDs
> [    0.000000] psci: Trusted OS resident on physical CPU 0x0
> [    0.000000] percpu: Embedded 3 pages/cpu @ffffff0ff6900000 s116736 r8192
> d71680 u196608
> [    0.000000] Detected VIPT I-cache on CPU0
> [    0.000000] CPU features: enabling workaround for Cavium erratum 27456
> [    0.000000] Built 1 zonelists in Node order, mobility grouping on. Total
> pages: 2094720
> [    0.000000] Policy zone: Normal
> [    0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-4.8.0-rc8-dd
> root=/dev/mapper/rhel-root ro crashkernel=auto rd.lvm.lv=rhel/root
> rd.lvm.lv=rhel/swap LANG=en_US.UTF-8 numa=off console=ttyAMA0,115200n8
> earlycon=pl011,0x87e024000000
> [    0.000000] log_buf_len individual max cpu contribution: 4096 bytes
> [    0.000000] log_buf_len total cpu_extra contributions: 389120 bytes
> [    0.000000] log_buf_len min size: 524288 bytes
> [    0.000000] log_buf_len: 1048576 bytes
> [    0.000000] early log buf free: 519176(99%)
> [    0.000000] PID hash table entries: 4096 (order: -1, 32768 bytes)
> [    0.000000] software IO TLB [mem 0xfbfd0000-0xfffd0000] (64MB) mapped at
> [fffffe00fbfd0000-fffffe00fffcffff]
> [    0.000000] Memory: 133391936K/134193152K available (7356K kernel code,
> 1359K rwdata, 3392K rodata, 1216K init, 6799K bss, 276928K reserved, 524288K
> cma-reserved)
> [    0.000000] Virtual kernel memory layout:
> [    0.000000]     modules : 0xfffffc0000000000 - 0xfffffc0008000000   (
> 128 MB)
> [    0.000000]     vmalloc : 0xfffffc0008000000 - 0xfffffdff5fff0000   (
> 2045 GB)
> [    0.000000]       .text : 0xfffffc0008080000 - 0xfffffc00087b0000   (
> 7360 KB)
> [    0.000000]     .rodata : 0xfffffc00087b0000 - 0xfffffc0008b10000   (
> 3456 KB)
> [    0.000000]       .init : 0xfffffc0008b10000 - 0xfffffc0008c40000   (
> 1216 KB)
> [    0.000000]       .data : 0xfffffc0008c40000 - 0xfffffc0008d93e00   (
> 1360 KB)
> [    0.000000]        .bss : 0xfffffc0008d93e00 - 0xfffffc0009437d48   (
> 6800 KB)
> [    0.000000]     fixed   : 0xfffffdff7e7d0000 - 0xfffffdff7ec00000   (
> 4288 KB)
> [    0.000000]     PCI I/O : 0xfffffdff7ee00000 - 0xfffffdff7fe00000   (
> 16 MB)
> [    0.000000]     vmemmap : 0xfffffdff80000000 - 0xfffffe0000000000   (
> 2 GB maximum)
> [    0.000000]               0xfffffdff80005000 - 0xfffffdffc4000000   (
> 1087 MB actual)
> [    0.000000]     memory  : 0xfffffe0001400000 - 0xffffff1000000000
> (1114092 MB)
> [    0.000000] SLUB: HWalign=128, Order=0-3, MinObjects=0, CPUs=96, Nodes=1
> [    0.000000] Hierarchical RCU implementation.
> [    0.000000] 	Build-time adjustment of leaf fanout to 64.
> [    0.000000] 	RCU restricting CPUs from NR_CPUS=4096 to nr_cpu_ids=96.
> [    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=96
> [    0.000000] NR_IRQS:64 nr_irqs:64 0
> [    0.000000] GICv3: GIC: Using split EOI/Deactivate mode
> [    0.000000] ITS: /interrupt-controller@801000000000/gic-its@801000020000
> [    0.000000] ITS@0x0000801000020000: allocated 2097152 Devices
> @10001000000 (flat, esz 8, psz 64K, shr 1)
> [    0.000000] ITS: /interrupt-controller@801000000000/gic-its@901000020000
> [    0.000000] ITS@0x0000901000020000: allocated 2097152 Devices
> @10002000000 (flat, esz 8, psz 64K, shr 1)
> [    0.000000] Unable to handle kernel NULL pointer dereference at virtual
> address 00001680
> [    0.000000] pgd = fffffc0009470000
> [    0.000000] [00001680] *pgd=0000010ffff90003, *pud=0000010ffff90003,
> *pmd=0000010ffff90003, *pte=0000000000000000
> [    0.000000] Internal error: Oops: 96000006 [#1] SMP
> [    0.000000] Modules linked in:
> [    0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.8.0-rc8-dd #29
> [    0.000000] Hardware name: Cavium ThunderX CN88XX board (DT)
> [    0.000000] task: fffffc0008c71c80 task.stack: fffffc0008c40000
> [    0.000000] PC is at __alloc_pages_nodemask+0xa4/0xe68
> [    0.000000] LR is at __alloc_pages_nodemask+0x38/0xe68
> [    0.000000] pc : [<fffffc00081c8950>] lr : [<fffffc00081c88e4>] pstate:
> 600000c5
> [    0.000000] sp : fffffc0008c43880
> [    0.000000] x29: fffffc0008c43880 x28: ffffff000041fc00
> [    0.000000] x27: 0000000000201200 x26: 0000000000000000
> [    0.000000] x25: 0000000000000001 x24: 0000000000001680
> [    0.000000] x23: 0000000000201200 x22: fffffc0008c439c8
> [    0.000000] x21: fffffc0008c63000 x20: 0000000000201200
> [    0.000000] x19: 0000000000000000 x18: 0000000000000070
> [    0.000000] x17: 0000000000000008 x16: 0000000000000000
> [    0.000000] x15: 0000000000000000 x14: 2820303030303030
> [    0.000000] x13: 3230303031402073 x12: 6563697665442032
> [    0.000000] x11: 0000000000000020 x10: fffffc0009334000
> [    0.000000] x9 : 0000000001bfff3f x8 : 7f7f7f7f7f7f7f7f
> [    0.000000] x7 : 0000000001210111 x6 : fffffdffc00010a0
> [    0.000000] x5 : 0000000000000000 x4 : 0000000000000000
> [    0.000000] x3 : 0000000000000000 x2 : 0000000000000000
> [    0.000000] x1 : 0000000000000000 x0 : fffffc0008c63bb0
> [    0.000000]
> [    0.000000] Process swapper/0 (pid: 0, stack limit = 0xfffffc0008c40020)
> [    0.000000] Stack: (0xfffffc0008c43880 to 0xfffffc0008c44000)
> [    0.000000] 3880: fffffc0008c439f0 fffffc000821fa70 ffffff000041fc00
> 0000000000000200
> [    0.000000] 38a0: fffffc0008115374 0000000000000000 0000000000000000
> 0000000000000001
> [    0.000000] 38c0: 0000000000000000 0000000000000000 0000000000201200
> ffffff000041fc00
> [    0.000000] 38e0: fffffc0008c43960 fffffc000810bc20 fffffc0008c43960
> fffffc0008c43960
> [    0.000000] 3900: fffffc0008c43930 00000000ffffffd0 fffffc0008c43960
> fffffc0008c43960
> [    0.000000] 3920: fffffc0008c43930 00000000ffffffd0 fffffc0008c43970
> fffffc0008221658
> [    0.000000] 3940: 7f7f7f7f7f7f7f7f 0000000000000002 0101010101010101
> 0000000000000020
> [    0.000000] 3960: fffffc0008c43a70 fffffc0008221c04 0000000000000001
> 00000000024080c0
> [    0.000000] 3980: fffffc0008115374 fffffc0008bf8648 0000000000001000
> 0000000000000000
> [    0.000000] 39a0: ffffff000041fc00 0000000000000001 ffffff0ff691e840
> ffffff000041fc00
> [    0.000000] 39c0: ffffff0ff691e840 0000000000001680 0000000000000000
> 0000000000000000
> [    0.000000] 39e0: 0000000100000000 0000000000000000 fffffc0008c43a70
> fffffc0008221e24
> [    0.000000] 3a00: 0000000000000001 00000000024080c0 fffffc0008115374
> fffffc0008bf8648
> [    0.000000] 3a20: 0000000000001000 0000000000000000 0000000000000000
> 0000000000000001
> [    0.000000] 3a40: ffffff0ff691e840 ffffff000041fc00 fffffc000928a1e8
> 024080c000000006
> [    0.000000] 3a60: fffffc0008ca6a38 000000000000005c fffffc0008c43b90
> fffffc0008239498
> [    0.000000] 3a80: 00000000000000c0 ffffff000041fc00 ffffff0000424f00
> 0000000000000070
> [    0.000000] 3aa0: 0000000000000001 fffffc0008115374 ffffff000041fc00
> fffffc00093f1000
> [    0.000000] 3ac0: ffffff0002000000 ffffff0000433000 fffffc0008c43bd0
> fffffc0008a308f0
> [    0.000000] 3ae0: 0000000000010000 0000020000000000 0000000000000000
> 0000000000000001
> [    0.000000] 3b00: fffffc0008c43b30 fffffc000861f07c fffffc000941efc0
> 00000000000000c0
> [    0.000000] 3b20: ffffff0ffff44e60 00000000000000c0 fffffc0008c43b70
> fffffc000861f234
> [    0.000000] 3b40: ffffff0ffff44e60 0000000000000004 ffffff0ffff44e60
> fffffc0008c43c70
> [    0.000000] 3b60: 0000000000000000 fffffc0008a74460 fffffc0008c43ba0
> fffffc000861f3fc
> [    0.000000] 3b80: fffffc0008c43ba0 fffffc00083ca55c fffffc0008c43bd0
> fffffc0008222c20
> [    0.000000] 3ba0: ffffff000041fc00 00000000024080c0 ffffff0ff691e840
> fffffc0008115374
> [    0.000000] 3bc0: 0000000000000001 00000000024080c0 fffffc0008c43c20
> fffffc0008115374
> [    0.000000] 3be0: 0000000000000070 ffffff0ffff44e80 ffffff0ffff44e60
> 0000000000000000
> [    0.000000] 3c00: fffffc0008849a18 ffffffffffffffff 0000000000000000
> ffffff0000433000
> [    0.000000] 3c20: fffffc0008c43c80 fffffc0008b461dc ffffff0000424e80
> 2800000000000000
> [    0.000000] 3c40: 0000000000010000 0000020000000000 0000000000000000
> 0000000000000400
> [    0.000000] 3c60: 0000000000000400 ffffff00004330f8 0000000000000001
> ffffff0ffffabe00
> [    0.000000] 3c80: fffffc0008c43dc0 fffffc0008b462bc fffffc0008d33488
> fffffc0008d33000
> [    0.000000] 3ca0: ffffff0ffff44e60 fffffc0008c6c840 ffffff0000424b00
> ffffff0000424880
> [    0.000000] 3cc0: 0000000000000002 0000000000000000 0000000001bae074
> 0000000001f1001c
> [    0.000000] 3ce0: 0000000000000000 fffffc0008a30890 ffffff0000424b00
> fffffc0008849940
> [    0.000000] 3d00: ffffff0000433020 fffffc0008a308f0 ffffff0000433008
> ffffff0ffff44e60
> [    0.000000] 3d20: fffffc000ac00000 0000000000000008 0000000000000001
> 8107000000000000
> [    0.000000] 3d40: 00000000000000c0 0000000001000000 00000008fff44e60
> 0000010002000000
> [    0.000000] 3d60: 0000000000000100 81070000000000ff fffffc0008c43dc0
> 0000000008b462cc
> [    0.000000] 3d80: 0000901000020000 000090100021ffff ffffff0ffff44f08
> 0000000000000200
> [    0.000000] 3da0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [    0.000000] 3dc0: fffffc0008c43e10 fffffc0008b4543c fffffc0008c6c828
> fffffc0008d32000
> [    0.000000] 3de0: fffffc0008c6c000 ffffff0ffff44470 fffffc0008849000
> ffffff0000424880
> [    0.000000] 3e00: fffffc0008c43e10 fffffc0008b45420 fffffc0008c43e60
> fffffc0008b456bc
> [    0.000000] 3e20: 0000000000000002 0000000000000003 0000000000000030
> ffffff0000424880
> [    0.000000] 3e40: ffffff0ffff44470 0000000000000000 0000000000000018
> fffffc0008000000
> [    0.000000] 3e60: fffffc0008c43f00 fffffc0008b5aec8 ffffff0000424700
> fffffc0008c43f60
> [    0.000000] 3e80: fffffc0008c43f60 0000000000000000 fffffc0008c43f70
> fffffc0008d92000
> [    0.000000] 3ea0: fffffc0008a734e0 fffffc0008a734b8 fffffc0008c43f00
> 0000000208b5ae3c
> [    0.000000] 3ec0: 0000000000000000 00009010805fffff ffffff0ffff44518
> 0000000000000200
> [    0.000000] 3ee0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [    0.000000] 3f00: fffffc0008c43f80 fffffc0008b43f9c fffffc0008c60000
> fffffc0008b66628
> [    0.000000] 3f20: fffffc0008b66628 fffffc0008dc0000 fffffc0008c60000
> ffffff0ffffac580
> [    0.000000] 3f40: 0000000002840000 0000000002870000 0000000000000020
> 0000000000000000
> [    0.000000] 3f60: fffffc0008c43f60 fffffc0008c43f60 fffffc0008c43f70
> fffffc0008c43f70
> [    0.000000] 3f80: fffffc0008c43f90 fffffc0008b12d60 fffffc0008c43fa0
> fffffc0008b10a3c
> [    0.000000] 3fa0: 0000000000000000 fffffc0008b101c4 0000010ff7a35218
> 0000000000000e12
> [    0.000000] 3fc0: 0000000021200000 0000000030d00980 0000000000000000
> 0000000001400000
> [    0.000000] 3fe0: 0000000000000000 fffffc0008b66628 0000000000000000
> 0000000000000000
> [    0.000000] Call trace:
> [    0.000000] Exception stack(0xfffffc0008c436b0 to 0xfffffc0008c437e0)
> [    0.000000] 36a0:                                   0000000000000000
> 0000040000000000
> [    0.000000] 36c0: fffffc0008c43880 fffffc00081c8950 ffffff0ffffaf180
> 0000000000000003
> [    0.000000] 36e0: fffffc0008c63000 00000000ffffffff 0000000000000001
> 0000000000000000
> [    0.000000] 3700: fffffc0008c43720 fffffc00081e25cc 0000000000000000
> 0000000001bfff3f
> [    0.000000] 3720: fffffc0008c43750 fffffc00081c8454 0000000000000012
> 0000000000000000
> [    0.000000] 3740: fffffffffffffff8 0000000000000012 fffffc0008c63bb0
> 0000000000000000
> [    0.000000] 3760: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [    0.000000] 3780: fffffdffc00010a0 0000000001210111 7f7f7f7f7f7f7f7f
> 0000000001bfff3f
> [    0.000000] 37a0: fffffc0009334000 0000000000000020 6563697665442032
> 3230303031402073
> [    0.000000] 37c0: 2820303030303030 0000000000000000 0000000000000000
> 0000000000000008
> [    0.000000] [<fffffc00081c8950>] __alloc_pages_nodemask+0xa4/0xe68
> [    0.000000] [<fffffc000821fa70>] new_slab+0xd0/0x564
> [    0.000000] [<fffffc0008221e24>] ___slab_alloc+0x2e4/0x514
> [    0.000000] [<fffffc0008239498>] __slab_alloc+0x48/0x58
> [    0.000000] [<fffffc0008222c20>] __kmalloc_node+0xd0/0x2dc
> [    0.000000] [<fffffc0008115374>] __irq_domain_add+0x7c/0x164
> [    0.000000] [<fffffc0008b461dc>] its_probe+0x784/0x81c
> [    0.000000] [<fffffc0008b462bc>] its_init+0x48/0x1b0
> [    0.000000] [<fffffc0008b4543c>] gic_init_bases+0x228/0x360
> [    0.000000] [<fffffc0008b456bc>] gic_of_init+0x148/0x1cc
> [    0.000000] [<fffffc0008b5aec8>] of_irq_init+0x184/0x298
> [    0.000000] [<fffffc0008b43f9c>] irqchip_init+0x14/0x38
> [    0.000000] [<fffffc0008b12d60>] init_IRQ+0xc/0x30
> [    0.000000] [<fffffc0008b10a3c>] start_kernel+0x240/0x3b8
> [    0.000000] [<fffffc0008b101c4>] __primary_switched+0x30/0x6c
> [    0.000000] Code: 912ec2a0 b9403809 0a0902fb 37b007db (f9400300)
> [    0.000000] ---[ end trace 0000000000000000 ]---
> [    0.000000] Kernel panic - not syncing: Fatal exception
> [    0.000000] ---[ end Kernel panic - not syncing: Fatal exception
> 
> 
> Same thing on v4.8.x and v4.9-rc?
> 
> 
> 
> 
> >
> >-Robert
> >
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH V4 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Rob Herring @ 2016-10-26 22:25 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, devicetree, lorenzo.pieralisi, benh, minyard, arnd,
	catalin.marinas, gabriele.paoloni, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, zourongrong, linux-serial,
	linux-pci, bhelgaas, liviu.dudau, kantyzc, zhichang.yuan02,
	linux-arm-kernel
In-Reply-To: <1476954940-242159-3-git-send-email-yuanzhichang@hisilicon.com>

On Thu, Oct 20, 2016 at 05:15:39PM +0800, zhichang.yuan wrote:
> Currently if the range property is not specified of_translate_one
> returns an error. There are some special devices that work on a
> range of I/O ports where it's is not correct to specify a range
> property as the cpu addresses are used by special accessors.
> Here we add a new exception in of_translate_one to return
> the cpu address if the range property is not there. The exception
> checks if the parent bus is ISA and if the special accessors are
> defined.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/include/asm/io.h |  7 +++++++
>  arch/arm64/kernel/extio.c   | 24 +++++++++++++++++++++++
>  drivers/of/address.c        | 47 +++++++++++++++++++++++++++++++++++++++++++--
>  drivers/pci/pci.c           |  6 +++---
>  include/linux/of_address.h  | 17 ++++++++++++++++
>  5 files changed, 96 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 136735d..e480199 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -175,6 +175,13 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define outsl outsl
>  
>  DECLARE_EXTIO(l, u32)
> +
> +
> +#define indirect_io_ison indirect_io_ison
> +extern int indirect_io_ison(void);
> +
> +#define chk_indirect_range chk_indirect_range
> +extern int chk_indirect_range(u64 taddr);
>  #endif
>  
>  
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> index 80cafd5..55df8dc 100644
> --- a/arch/arm64/kernel/extio.c
> +++ b/arch/arm64/kernel/extio.c
> @@ -19,6 +19,30 @@
>  
>  struct extio_ops *arm64_extio_ops;
>  
> +/**
> + * indirect_io_ison - check whether indirectIO can work well. This function only call
> + *		before the target I/O address was obtained.
> + *
> + * Returns 1 when indirectIO can work.
> + */
> +int indirect_io_ison()
> +{
> +	return arm64_extio_ops ? 1 : 0;
> +}
> +
> +/**
> + * check_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int chk_indirect_range(u64 taddr)
> +{
> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
> +		return 0;
> +
> +	return 1;
> +}
>  
>  BUILD_EXTIO(b, u8)
>  
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..0bee822 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -479,6 +479,39 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> +
> +/*
> + * Check whether the current device being translating use indirectIO.
> + *
> + * return 1 if the check is past, or 0 represents fail checking.
> + */
> +static int of_isa_indirect_io(struct device_node *parent,

Make the return bool.

> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_ison())

indirect_io_is_enabled() would be a bit more readable.

> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +
> +	return chk_indirect_range(*presult);
> +}
> +
>  static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
> @@ -532,7 +565,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
>  
> - finish:
> +finish:

This hunk is unrelated. Drop it.

>  	of_dump_addr("parent translation for:", addr, pna);
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
>  
> @@ -595,6 +628,15 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_info("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);

This should be debugging.

> +			break;
> +		}
>  
>  		/* Get new parent bus and counts */
>  		pbus = of_match_bus(parent);
> @@ -688,8 +730,9 @@ static int __of_address_to_resource(struct device_node *dev,
>  	if (taddr == OF_BAD_ADDR)
>  		return -EINVAL;
>  	memset(r, 0, sizeof(struct resource));
> -	if (flags & IORESOURCE_IO) {
> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>  		unsigned long port;
> +
>  		port = pci_address_to_pio(taddr);
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index ba34907..1a08511 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3263,7 +3263,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  
>  #ifdef PCI_IOBASE
>  	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>  
>  	/* check if the range hasn't been previously recorded */
>  	spin_lock(&io_range_lock);
> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
>  
>  #ifdef PCI_IOBASE
>  	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>  
>  	if (pio > IO_SPACE_LIMIT)
>  		return address;
> @@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
>  {
>  #ifdef PCI_IOBASE
>  	struct io_range *res;
> -	resource_size_t offset = 0;
> +	resource_size_t offset = PCIBIOS_MIN_IO;
>  	unsigned long addr = -1;
>  
>  	spin_lock(&io_range_lock);
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 3786473..0ba7e21 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -24,6 +24,23 @@ struct of_pci_range {
>  #define for_each_of_pci_range(parser, range) \
>  	for (; of_pci_range_parser_one(parser, range);)
>  
> +
> +#ifndef indirect_io_ison
> +#define indirect_io_ison indirect_io_ison
> +static inline int indirect_io_ison(void)
> +{
> +	return 0;
> +}
> +#endif
> +
> +#ifndef chk_indirect_range
> +#define chk_indirect_range chk_indirect_range
> +static inline int chk_indirect_range(u64 taddr)
> +{
> +	return 0;
> +}
> +#endif
> +
>  /* Translate a DMA address from device space to CPU space */
>  extern u64 of_translate_dma_address(struct device_node *dev,
>  				    const __be32 *in_addr);
> -- 
> 1.9.1
> 

^ permalink raw reply

* Re: [PATCH V4 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Rob Herring @ 2016-10-26 22:27 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, devicetree, lorenzo.pieralisi, benh, minyard, arnd,
	catalin.marinas, gabriele.paoloni, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, zourongrong, linux-serial,
	linux-pci, bhelgaas, liviu.dudau, kantyzc, zhichang.yuan02,
	linux-arm-kernel
In-Reply-To: <1476954940-242159-4-git-send-email-yuanzhichang@hisilicon.com>

On Thu, Oct 20, 2016 at 05:15:40PM +0800, zhichang.yuan wrote:
> On Hip06, the accesses to LPC peripherals work in an indirect way. A
> corresponding LPC driver configure some registers in LPC master at first, then
> the real accesses on LPC slave devices are finished by the LPC master, which
> is transparent to LPC driver.
> This patch implement the relevant driver for Hip06 LPC. Cooperating with
> indirect-IO, ipmi messages is in service without any changes on ipmi driver.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  .../arm/hisilicon/hisilicon-low-pin-count.txt      |  31 ++
>  MAINTAINERS                                        |   8 +
>  drivers/bus/Kconfig                                |   8 +
>  drivers/bus/Makefile                               |   1 +
>  drivers/bus/hisi_lpc.c                             | 501 +++++++++++++++++++++
>  5 files changed, 549 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
>  create mode 100644 drivers/bus/hisi_lpc.c
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..e681419
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> +  Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"

This should be an SoC specific compatible string.

> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set for this device is mapped.
> +
> +Note:
> +  The node name before '@' must be "isa" to represent the binding stick to the
> +  ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> +	compatible = "hisilicom,low-pin-count";
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> +	ipmi0: bt@e4 {
> +		compatible = "ipmi-bt";
> +		device_type = "ipmi";
> +		reg = <0x01 0xe4 0x04>;
> +		status = "disabled";
> +	};
> +};

^ permalink raw reply

* Re: [RFC v2 2/2] mmc: sdhci: Ignore capability register when it comes to speeds and use DT binding instead when sdhci-cap-speed-modes-broken is set.
From: Zach Brown @ 2016-10-26 22:28 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: ulf.hansson, robh+dt, mark.rutland, linux-mmc, devicetree,
	linux-kernel
In-Reply-To: <d65f018e-b20e-9e87-fc07-eb2fb4b5079e@intel.com>

On Tue, Oct 25, 2016 at 02:30:25PM +0300, Adrian Hunter wrote:
> On 24/10/16 18:48, Zach Brown wrote:
> > On Mon, Oct 24, 2016 at 10:34:46AM +0300, Adrian Hunter wrote:
> >> On 22/10/16 00:35, Zach Brown wrote:
> >>> When the sdhci-cap-speed-modes-broken DT property is set, the driver
> >>> will ignore the bits of the capability registers that correspond to
> >>> speed modes.
> >>>
> >>> Signed-off-by: Zach Brown <zach.brown@ni.com>
> >>> ---
> >>>  drivers/mmc/host/sdhci.c | 10 ++++++++++
> >>>  1 file changed, 10 insertions(+)
> >>>
> >>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >>> index 1e25b01..59c62d3 100644
> >>> --- a/drivers/mmc/host/sdhci.c
> >>> +++ b/drivers/mmc/host/sdhci.c
> >>> @@ -22,6 +22,7 @@
> >>>  #include <linux/scatterlist.h>
> >>>  #include <linux/regulator/consumer.h>
> >>>  #include <linux/pm_runtime.h>
> >>> +#include <linux/of.h>
> >>>
> >>>  #include <linux/leds.h>
> >>>
> >>> @@ -3013,10 +3014,19 @@ void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1)
> >>>
> >>>  	host->caps = caps ? *caps : sdhci_readl(host, SDHCI_CAPABILITIES);
> >>>
> >>> +	if (of_property_read_bool(mmc_dev(host->mmc)->of_node,
> >>> +				  "sdhci-cap-speed-modes-broken"))
> >>
> >> It rather begs the question: if you are going to do something sdhci
> >> specific, why not just read the whole of the caps register from DT?
> >>
> > 
> > Throwing out the whole of the caps register seems like overkill. Also
> 
> What about 2 values: one for the 64-bit caps register and one for a 64-bit
> mask of bits to override.  That way you can select which bits to override
> and what to override them to.
> 

I like this idea. I sent a RFC of it. 

> > there are some things set by the caps that are not available in the DT.
> > For example, SDHCI_CAN_64BIT is set by the cap register and is used in
> > sdhci_setup_host to set host->flags SDHCI_USE_64_BIT_DMA.
> 
> Not sure what you mean.
> 

Your suggestion addresses my concern. So it's not an issue. 

^ permalink raw reply

* Re: [PATCH V2 07/10] Input: da9061: onkey driver
From: Dmitry Torokhov @ 2016-10-26 22:50 UTC (permalink / raw)
  To: Steve Twiss
  Cc: LINUX-INPUT, LINUX-KERNEL, DEVICETREE, Eduardo Valentin,
	Guenter Roeck, LINUX-PM, LINUX-WATCHDOG, Lee Jones, Liam Girdwood,
	Mark Brown, Mark Rutland, Rob Herring, Support Opensource,
	Wim Van Sebroeck, Zhang Rui
In-Reply-To: <29f73d4d4718cc5848c0414ea60f865ef39bd2cf.1477501000.git.stwiss.opensource@diasemi.com>

On Wed, Oct 26, 2016 at 05:56:39PM +0100, Steve Twiss wrote:
> From: Steve Twiss <stwiss.opensource@diasemi.com>
> 
> Copyright header is updated to add DA9061 in its description and the module
> description macro is extended to include DA9061.
> 
> Minor change to the code, alters dev_dbg() statements to report a generic
> "PMIC" instead of DA9063. This device driver is compatible with DA9061,
> DA9062 and DA9063.
> 
> Kconfig is updated to reflect support for DA9061/62/63.
> 
> Signed-off-by: Steve Twiss <stwiss.opensource@diasemi.com>

Applied, thank you.

> 
> ---
> This patch applies against linux-next and v4.8
> 
> v1 -> v2
>  - Patch renamed from [PATCH V1 03/10] to [PATCH V2 07/10] -- these
>    changes were made to fix checkpatch warnings caused by the patch
>    set dependency order
>  - Revert changes for DA9061 specific compatible changes.
> 
> Dmitry,
> 
> Alterations made in accordance with previous e-mail thread on the use of
> compatible strings: https://lkml.org/lkml/2016/10/7/641
> Now assuming the use of a fallback compatible string in the DT.
> compatible = "dlg,da9061-onkey", "dlg,da9062-onkey";
> 
> Regards,
> Steve Twiss, Dialog Semiconductor Ltd.
> 
> 
>  drivers/input/misc/Kconfig        | 7 ++++---
>  drivers/input/misc/da9063_onkey.c | 8 ++++----
>  2 files changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index efb0ca8..57cc9c2 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -613,11 +613,12 @@ config INPUT_DA9055_ONKEY
>  	  will be called da9055_onkey.
>  
>  config INPUT_DA9063_ONKEY
> -	tristate "Dialog DA9062/63 OnKey"
> +	tristate "Dialog DA9063/62/61 OnKey"
>  	depends on MFD_DA9063 || MFD_DA9062
>  	help
> -	  Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
> -	  as an input device capable of reporting the power button status.
> +	  Support the ONKEY of Dialog DA9063, DA9062 and DA9061 Power
> +	  Management ICs as an input device capable of reporting the
> +	  power button status.
>  
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called da9063_onkey.
> diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
> index bb863e0..dff6fe5 100644
> --- a/drivers/input/misc/da9063_onkey.c
> +++ b/drivers/input/misc/da9063_onkey.c
> @@ -1,5 +1,5 @@
>  /*
> - * OnKey device driver for DA9063 and DA9062 PMICs
> + * OnKey device driver for DA9063, DA9062 and DA9061 PMICs
>   * Copyright (C) 2015  Dialog Semiconductor Ltd.
>   *
>   * This program is free software; you can redistribute it and/or
> @@ -149,13 +149,13 @@ static void da9063_poll_on(struct work_struct *work)
>  			 * and then send shutdown command
>  			 */
>  			dev_dbg(&onkey->input->dev,
> -				"Sending SHUTDOWN to DA9063 ...\n");
> +				"Sending SHUTDOWN to PMIC ...\n");
>  			error = regmap_write(onkey->regmap,
>  					     config->onkey_shutdown,
>  					     config->onkey_shutdown_mask);
>  			if (error)
>  				dev_err(&onkey->input->dev,
> -					"Cannot SHUTDOWN DA9063: %d\n",
> +					"Cannot SHUTDOWN PMIC: %d\n",
>  					error);
>  		}
>  	}
> @@ -300,6 +300,6 @@ static struct platform_driver da9063_onkey_driver = {
>  module_platform_driver(da9063_onkey_driver);
>  
>  MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
> -MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
> +MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061");
>  MODULE_LICENSE("GPL");
>  MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
> -- 
> end-of-patch for PATCH V2
> 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH 3/4] Input: goodix - Tweak configuration to use passed in touchscreen resolution
From: Rob Herring @ 2016-10-26 23:10 UTC (permalink / raw)
  To: Franklin S Cooper Jr
  Cc: dmitry.torokhov, hadess, octavian.purdila, irina.tirdea, merker,
	linux-input, devicetree, linux-kernel, nsekhar, nm
In-Reply-To: <20161020195917.20051-4-fcooper@ti.com>

On Thu, Oct 20, 2016 at 02:59:16PM -0500, Franklin S Cooper Jr wrote:
> Some goodix touchscreen controllers aren't programed properly to match the
> display panel it is used on. Although the defaults may largely work it is
> also likely that the screen resolution will be incorrect. Therefore,
> add support to allow via DT for the touchscreen resolution to be set and
> reprogram the controller to use this updated resolution.
> 
> Signed-off-by: Franklin S Cooper Jr <fcooper@ti.com>
> ---
>  .../bindings/input/touchscreen/goodix.txt          |  2 ++

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

>  drivers/input/touchscreen/goodix.c                 | 26 +++++++++++++++++++++-
>  2 files changed, 27 insertions(+), 1 deletion(-)

^ permalink raw reply

* Re: [PATCH 4/4] Input: goodix - Support interchanging x and y coordinates in hardware
From: Rob Herring @ 2016-10-26 23:18 UTC (permalink / raw)
  To: Franklin S Cooper Jr
  Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	hadess-0MeiytkfxGOsTnJN9+BGXg,
	octavian.purdila-ral2JQCrhuEAvxtiuMwx3w,
	irina.tirdea-ral2JQCrhuEAvxtiuMwx3w,
	merker-8fiUuRrzOP0dnm+yROfE0A, linux-input-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, nsekhar-l0cyMroinI0,
	nm-l0cyMroinI0
In-Reply-To: <20161020195917.20051-5-fcooper-l0cyMroinI0@public.gmane.org>

On Thu, Oct 20, 2016 at 02:59:17PM -0500, Franklin S Cooper Jr wrote:
> On systems with a fixed display/touchscreen orientation it is important to
> pass in the "correct" x and y coordinates based on the orientation.
> Currently, to support landscape and portrait touchscreen-swapped-x-y
> simply does the following:
> 
> Assuming touchscreen is as follows:
> X: 1280 Y:800 programmed in touchscreen controller and also interchange
> bit cleared. Assuming ts mounted in portrait mode.
> 
> 1280 (X)
> ------
> |    |
> |    | 800 (Y)
> |    |
> |    |
> ------
> 
> 800 (Y)
> ------
> |    |
> |    | 1280 (X)
> |    |
> |    |
> ------
> 
> However, the above isn't really what we want especially in distros that
> assumes a fixed orientation. In this case what we really want is to
> interchange the x and y coordinates so the Y coordinate can return a max
> value of 1280 and X can return a max value of 800.
> 
> 800 (X)
> ------
> |    |
> |    | 1280 (Y)
> |    |
> |    |
> ------
> 
> Since the driver is limited to the value reported by the touchscreen
> controller this issue can't be fixed purely in the driver. Therefore,
> add a new DT property that supports interchanging X and Y coordinates
> internally within the hardware.

I'm not sure I follow why existing properties don't cover this.

> 
> Signed-off-by: Franklin S Cooper Jr <fcooper-l0cyMroinI0@public.gmane.org>
> ---
>  .../devicetree/bindings/input/touchscreen/goodix.txt        |  2 ++
>  drivers/input/touchscreen/goodix.c                          | 13 +++++++++++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt
> index ebc7cb7..b8be2ab 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt
> +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt
> @@ -25,6 +25,8 @@ Optional properties:
>   - touchscreen-inverted-y  : Y axis is inverted (boolean)
>   - touchscreen-swapped-x-y : X and Y axis are swapped (boolean)
>                               (swapping is done after inverting the axis)
> + - touchscreen-inter-x-y   : X and Y maximum values programmed in the device
> +                             are interchanged internally in hardware. (boolean)

Minimally this should be vendor specific and have a vendor prefix I 
think.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 2/3] dt-bindings: mtd: add DT binding for s3c2410 flash controller
From: Rob Herring @ 2016-10-26 23:19 UTC (permalink / raw)
  To: Sergio Prado
  Cc: kgene, krzk, javier, linux, linux, boris.brezillon, richard,
	dwmw2, computersforpeace, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-mtd, mark.rutland, devicetree
In-Reply-To: <1476999766-32526-3-git-send-email-sergio.prado@e-labworks.com>

On Thu, Oct 20, 2016 at 07:42:45PM -0200, Sergio Prado wrote:
> Adds the device tree bindings description for Samsung S3C2410 and
> compatible NAND flash controller.
> 
> Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>
> ---
>  .../devicetree/bindings/mtd/samsung-s3c2410.txt    | 56 ++++++++++++++++++++++
>  1 file changed, 56 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt

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

^ permalink raw reply

* [PATCH V2] pinctrl: qcom: Add msm8994 pinctrl driver
From: Michael Scott @ 2016-10-26 23:32 UTC (permalink / raw)
  To: linux-gpio, linux-arm-msm, devicetree, linux-kernel
  Cc: Linus Walleij, Rob Herring, Mark Rutland, Andy Gross, David Brown,
	Bjorn Andersson, Joonwoo Park, Jeremy McNicoll, Michael Scott

Initial pinctrl driver for QCOM msm8994 platforms.

In order to continue the initial board support for QCOM msm8994/msm8992
presented in patches from Jeremy McNicoll <jeremymc@redhat.com>, let's put
a proper pinctrl driver in place.

Currently, the DT for these platforms uses the msm8x74 pinctrl driver to enable
basic UART.  Beyond the first few pins the rest are different enough to justify
it's own driver.

Note: This driver is also be used by QCOM's msm8992 platform as it's TLM block
is the same.

- Initial formatting and style was taken from the msm8x74 pinctrl driver added
  by Björn Andersson <bjorn.andersson@linaro.org>
- Data was then adjusted per QCOM MSM8994 documentation for Top Level Multiplexing
- Bindings documentation was based on qcom,msm8996-pinctrl.txt by
  Joonwoo Park <joonwoop@codeaurora.org> and then modified for msm8994 content

Signed-off-by: Michael Scott <michael.scott@linaro.org>
---

V1 -> V2: fixed missing FUNCTION(nav_pps) and removed 3 odd newlines between blsp_i2c4_groups and cci_timer0_groups

 .../bindings/pinctrl/qcom,msm8994-pinctrl.txt      |  175 +++
 drivers/pinctrl/qcom/Kconfig                       |    9 +
 drivers/pinctrl/qcom/Makefile                      |    1 +
 drivers/pinctrl/qcom/pinctrl-msm8994.c             | 1400 ++++++++++++++++++++
 4 files changed, 1585 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
 create mode 100644 drivers/pinctrl/qcom/pinctrl-msm8994.c

diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
new file mode 100644
index 0000000..e390087b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
@@ -0,0 +1,175 @@
+Qualcomm MSM8994 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8994 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,msm8994-pinctrl"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+	Usage: required
+	Value type: <string-array>
+	Definition: List of gpio pins affected by the properties specified in
+		    this subnode.
+
+		    Valid pins are:
+		      gpio0-gpio145
+		        Supports mux, bias and drive-strength
+
+		      sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk,
+		      sdc2_cmd, sdc2_data
+		        Supports bias and drive-strength
+
+- function:
+	Usage: required
+	Value type: <string>
+	Definition: Specify the alternative function to be configured for the
+		    specified pins. Functions are only valid for gpio pins.
+		    Valid values are:
+
+		    audio_ref_clk,  blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
+		    blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11,
+		    blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3,
+		    blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
+		    blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9,
+		    blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11,
+		    blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5,
+		    blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11,
+		    blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
+		    blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11,
+		    blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b,
+		    blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3,
+		    cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1,
+		    cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, gcc_gp_clk1,
+		    gcc_gp_clk2, gcc_gp_clk3, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
+		    gp1_clk, gps_tx, grfc, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, mdp_vsync,
+		    mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a, qdss_cti_trig_in_b,
+		    qdss_cti_trig_in_c, qdss_cti_trig_in_d, qdss_cti_trig_out_a,
+		    qdss_cti_trig_out_b, qdss_cti_trig_out_c, qdss_cti_trig_out_d,
+		    qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b,
+		    qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0, pci_e1, pri_mi2s,
+		    rffe1, rffe2, rffe3, rffe4, rffe5, rffe6, rffe7, sdc4, sec_mi2s, slimbus,
+		    spkr_mi2s, ter_mi2s, tsif1, tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4,
+		    gpio
+
+- bias-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull up.
+
+- output-high:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    high.
+		    Not valid for sdc pins.
+
+- output-low:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    low.
+		    Not valid for sdc pins.
+
+- drive-strength:
+	Usage: optional
+	Value type: <u32>
+	Definition: Selects the drive strength for the specified pins, in mA.
+		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+	msmgpio: pinctrl@fd510000 {
+		compatible = "qcom,msm8994-pinctrl";
+		reg = <0xfd510000 0x4000>;
+		interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		blsp1_uart2_default: blsp1_uart2_default {
+			pinmux {
+				pins = "gpio4", "gpio5";
+				function = "blsp_uart2";
+			};
+			pinconf {
+				pins = "gpio4", "gpio5";
+				drive-strength = <16>;
+				bias-disable;
+			};
+		};
+	};
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 93ef268..3ebdc01 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -79,6 +79,15 @@ config PINCTRL_MSM8916
 	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
 	  Qualcomm TLMM block found on the Qualcomm 8916 platform.
 
+config PINCTRL_MSM8994
+	tristate "Qualcomm 8994 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm TLMM block found in the Qualcomm 8994 platform. The
+	  Qualcomm 8992 platform is also supported by this driver.
+
 config PINCTRL_MSM8996
 	tristate "Qualcomm MSM8996 pin controller driver"
 	depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 8319e11..ab47764 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MSM8660)	+= pinctrl-msm8660.o
 obj-$(CONFIG_PINCTRL_MSM8960)	+= pinctrl-msm8960.o
 obj-$(CONFIG_PINCTRL_MSM8X74)	+= pinctrl-msm8x74.o
 obj-$(CONFIG_PINCTRL_MSM8916)	+= pinctrl-msm8916.o
+obj-$(CONFIG_PINCTRL_MSM8994)   += pinctrl-msm8994.o
 obj-$(CONFIG_PINCTRL_MSM8996)   += pinctrl-msm8996.o
 obj-$(CONFIG_PINCTRL_QDF2XXX)	+= pinctrl-qdf2xxx.o
 obj-$(CONFIG_PINCTRL_MDM9615)	+= pinctrl-mdm9615.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c
new file mode 100644
index 0000000..556eec8
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c
@@ -0,0 +1,1400 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname)					\
+	[MSM_MUX_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11)	\
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			MSM_MUX_gpio,			\
+			MSM_MUX_##f1,			\
+			MSM_MUX_##f2,			\
+			MSM_MUX_##f3,			\
+			MSM_MUX_##f4,			\
+			MSM_MUX_##f5,			\
+			MSM_MUX_##f6,			\
+			MSM_MUX_##f7,			\
+			MSM_MUX_##f8,			\
+			MSM_MUX_##f9,			\
+			MSM_MUX_##f10,			\
+			MSM_MUX_##f11			\
+		},					\
+		.nfuncs = 12,				\
+		.ctl_reg = 0x1000 + 0x10 * id,		\
+		.io_reg = 0x1004 + 0x10 * id,		\
+		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
+		.intr_status_reg = 0x100c + 0x10 * id,	\
+		.intr_target_reg = 0x1008 + 0x10 * id,	\
+		.mux_bit = 2,				\
+		.pull_bit = 0,				\
+		.drv_bit = 6,				\
+		.oe_bit = 9,				\
+		.in_bit = 0,				\
+		.out_bit = 1,				\
+		.intr_enable_bit = 0,			\
+		.intr_status_bit = 0,			\
+		.intr_target_bit = 5,			\
+		.intr_target_kpss_val = 4,		\
+		.intr_raw_status_bit = 4,		\
+		.intr_polarity_bit = 1,			\
+		.intr_detection_bit = 2,		\
+		.intr_detection_width = 2,		\
+	}
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
+	{						\
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_target_kpss_val = -1,		\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+static const struct pinctrl_pin_desc msm8994_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+	PINCTRL_PIN(90, "GPIO_90"),
+	PINCTRL_PIN(91, "GPIO_91"),
+	PINCTRL_PIN(92, "GPIO_92"),
+	PINCTRL_PIN(93, "GPIO_93"),
+	PINCTRL_PIN(94, "GPIO_94"),
+	PINCTRL_PIN(95, "GPIO_95"),
+	PINCTRL_PIN(96, "GPIO_96"),
+	PINCTRL_PIN(97, "GPIO_97"),
+	PINCTRL_PIN(98, "GPIO_98"),
+	PINCTRL_PIN(99, "GPIO_99"),
+	PINCTRL_PIN(100, "GPIO_100"),
+	PINCTRL_PIN(101, "GPIO_101"),
+	PINCTRL_PIN(102, "GPIO_102"),
+	PINCTRL_PIN(103, "GPIO_103"),
+	PINCTRL_PIN(104, "GPIO_104"),
+	PINCTRL_PIN(105, "GPIO_105"),
+	PINCTRL_PIN(106, "GPIO_106"),
+	PINCTRL_PIN(107, "GPIO_107"),
+	PINCTRL_PIN(108, "GPIO_108"),
+	PINCTRL_PIN(109, "GPIO_109"),
+	PINCTRL_PIN(110, "GPIO_110"),
+	PINCTRL_PIN(111, "GPIO_111"),
+	PINCTRL_PIN(112, "GPIO_112"),
+	PINCTRL_PIN(113, "GPIO_113"),
+	PINCTRL_PIN(114, "GPIO_114"),
+	PINCTRL_PIN(115, "GPIO_115"),
+	PINCTRL_PIN(116, "GPIO_116"),
+	PINCTRL_PIN(117, "GPIO_117"),
+	PINCTRL_PIN(118, "GPIO_118"),
+	PINCTRL_PIN(119, "GPIO_119"),
+	PINCTRL_PIN(120, "GPIO_120"),
+	PINCTRL_PIN(121, "GPIO_121"),
+	PINCTRL_PIN(122, "GPIO_122"),
+	PINCTRL_PIN(123, "GPIO_123"),
+	PINCTRL_PIN(124, "GPIO_124"),
+	PINCTRL_PIN(125, "GPIO_125"),
+	PINCTRL_PIN(126, "GPIO_126"),
+	PINCTRL_PIN(127, "GPIO_127"),
+	PINCTRL_PIN(128, "GPIO_128"),
+	PINCTRL_PIN(129, "GPIO_129"),
+	PINCTRL_PIN(130, "GPIO_130"),
+	PINCTRL_PIN(131, "GPIO_131"),
+	PINCTRL_PIN(132, "GPIO_132"),
+	PINCTRL_PIN(133, "GPIO_133"),
+	PINCTRL_PIN(134, "GPIO_134"),
+	PINCTRL_PIN(135, "GPIO_135"),
+	PINCTRL_PIN(136, "GPIO_136"),
+	PINCTRL_PIN(137, "GPIO_137"),
+	PINCTRL_PIN(138, "GPIO_138"),
+	PINCTRL_PIN(139, "GPIO_139"),
+	PINCTRL_PIN(140, "GPIO_140"),
+	PINCTRL_PIN(141, "GPIO_141"),
+	PINCTRL_PIN(142, "GPIO_142"),
+	PINCTRL_PIN(143, "GPIO_143"),
+	PINCTRL_PIN(144, "GPIO_144"),
+	PINCTRL_PIN(145, "GPIO_145"),
+	PINCTRL_PIN(146, "SDC1_RCLK"),
+	PINCTRL_PIN(147, "SDC1_CLK"),
+	PINCTRL_PIN(148, "SDC1_CMD"),
+	PINCTRL_PIN(149, "SDC1_DATA"),
+	PINCTRL_PIN(150, "SDC2_CLK"),
+	PINCTRL_PIN(151, "SDC2_CMD"),
+	PINCTRL_PIN(152, "SDC2_DATA"),
+	PINCTRL_PIN(153, "SDC3_CLK"),
+	PINCTRL_PIN(154, "SDC3_CMD"),
+	PINCTRL_PIN(155, "SDC3_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+	static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+
+static const unsigned int sdc1_rclk_pins[] = { 146 };
+static const unsigned int sdc1_clk_pins[] = { 147 };
+static const unsigned int sdc1_cmd_pins[] = { 148 };
+static const unsigned int sdc1_data_pins[] = { 149 };
+static const unsigned int sdc2_clk_pins[] = { 150 };
+static const unsigned int sdc2_cmd_pins[] = { 151 };
+static const unsigned int sdc2_data_pins[] = { 152 };
+static const unsigned int sdc3_clk_pins[] = { 153 };
+static const unsigned int sdc3_cmd_pins[] = { 154 };
+static const unsigned int sdc3_data_pins[] = { 155 };
+
+enum msm8994_functions {
+	MSM_MUX_audio_ref_clk,
+	MSM_MUX_blsp_i2c1,
+	MSM_MUX_blsp_i2c2,
+	MSM_MUX_blsp_i2c3,
+	MSM_MUX_blsp_i2c4,
+	MSM_MUX_blsp_i2c5,
+	MSM_MUX_blsp_i2c6,
+	MSM_MUX_blsp_i2c7,
+	MSM_MUX_blsp_i2c8,
+	MSM_MUX_blsp_i2c9,
+	MSM_MUX_blsp_i2c10,
+	MSM_MUX_blsp_i2c11,
+	MSM_MUX_blsp_i2c12,
+	MSM_MUX_blsp_spi1,
+	MSM_MUX_blsp_spi1_cs1,
+	MSM_MUX_blsp_spi1_cs2,
+	MSM_MUX_blsp_spi1_cs3,
+	MSM_MUX_blsp_spi2,
+	MSM_MUX_blsp_spi2_cs1,
+	MSM_MUX_blsp_spi2_cs2,
+	MSM_MUX_blsp_spi2_cs3,
+	MSM_MUX_blsp_spi3,
+	MSM_MUX_blsp_spi4,
+	MSM_MUX_blsp_spi5,
+	MSM_MUX_blsp_spi6,
+	MSM_MUX_blsp_spi7,
+	MSM_MUX_blsp_spi8,
+	MSM_MUX_blsp_spi9,
+	MSM_MUX_blsp_spi10,
+	MSM_MUX_blsp_spi10_cs1,
+	MSM_MUX_blsp_spi10_cs2,
+	MSM_MUX_blsp_spi10_cs3,
+	MSM_MUX_blsp_spi11,
+	MSM_MUX_blsp_spi12,
+	MSM_MUX_blsp_uart1,
+	MSM_MUX_blsp_uart2,
+	MSM_MUX_blsp_uart3,
+	MSM_MUX_blsp_uart4,
+	MSM_MUX_blsp_uart5,
+	MSM_MUX_blsp_uart6,
+	MSM_MUX_blsp_uart7,
+	MSM_MUX_blsp_uart8,
+	MSM_MUX_blsp_uart9,
+	MSM_MUX_blsp_uart10,
+	MSM_MUX_blsp_uart11,
+	MSM_MUX_blsp_uart12,
+	MSM_MUX_blsp_uim1,
+	MSM_MUX_blsp_uim2,
+	MSM_MUX_blsp_uim3,
+	MSM_MUX_blsp_uim4,
+	MSM_MUX_blsp_uim5,
+	MSM_MUX_blsp_uim6,
+	MSM_MUX_blsp_uim7,
+	MSM_MUX_blsp_uim8,
+	MSM_MUX_blsp_uim9,
+	MSM_MUX_blsp_uim10,
+	MSM_MUX_blsp_uim11,
+	MSM_MUX_blsp_uim12,
+	MSM_MUX_blsp11_i2c_scl_b,
+	MSM_MUX_blsp11_i2c_sda_b,
+	MSM_MUX_blsp11_uart_rx_b,
+	MSM_MUX_blsp11_uart_tx_b,
+	MSM_MUX_cam_mclk0,
+	MSM_MUX_cam_mclk1,
+	MSM_MUX_cam_mclk2,
+	MSM_MUX_cam_mclk3,
+	MSM_MUX_cci_async_in0,
+	MSM_MUX_cci_async_in1,
+	MSM_MUX_cci_async_in2,
+	MSM_MUX_cci_i2c0,
+	MSM_MUX_cci_i2c1,
+	MSM_MUX_cci_timer0,
+	MSM_MUX_cci_timer1,
+	MSM_MUX_cci_timer2,
+	MSM_MUX_cci_timer3,
+	MSM_MUX_cci_timer4,
+	MSM_MUX_gcc_gp_clk1,
+	MSM_MUX_gcc_gp_clk2,
+	MSM_MUX_gcc_gp_clk3,
+	MSM_MUX_gp_mn,
+	MSM_MUX_gp_pdm0,
+	MSM_MUX_gp_pdm1,
+	MSM_MUX_gp_pdm2,
+	MSM_MUX_gp0_clk,
+	MSM_MUX_gp1_clk,
+	MSM_MUX_gps_tx,
+	MSM_MUX_grfc,
+	MSM_MUX_gsm_tx,
+	MSM_MUX_hdmi_cec,
+	MSM_MUX_hdmi_ddc,
+	MSM_MUX_hdmi_hpd,
+	MSM_MUX_mdp_vsync,
+	MSM_MUX_mss_lte,
+	MSM_MUX_nav_pps,
+	MSM_MUX_nav_tsync,
+	MSM_MUX_qdss_cti_trig_in_a,
+	MSM_MUX_qdss_cti_trig_in_b,
+	MSM_MUX_qdss_cti_trig_in_c,
+	MSM_MUX_qdss_cti_trig_in_d,
+	MSM_MUX_qdss_cti_trig_out_a,
+	MSM_MUX_qdss_cti_trig_out_b,
+	MSM_MUX_qdss_cti_trig_out_c,
+	MSM_MUX_qdss_cti_trig_out_d,
+	MSM_MUX_qdss_traceclk_a,
+	MSM_MUX_qdss_traceclk_b,
+	MSM_MUX_qdss_tracectl_a,
+	MSM_MUX_qdss_tracectl_b,
+	MSM_MUX_qdss_tracedata_a,
+	MSM_MUX_qdss_tracedata_b,
+	MSM_MUX_qua_mi2s,
+	MSM_MUX_pci_e0,
+	MSM_MUX_pci_e1,
+	MSM_MUX_pri_mi2s,
+	MSM_MUX_rffe1,
+	MSM_MUX_rffe2,
+	MSM_MUX_rffe3,
+	MSM_MUX_rffe4,
+	MSM_MUX_rffe5,
+	MSM_MUX_rffe6,
+	MSM_MUX_rffe7,
+	MSM_MUX_sdc4,
+	MSM_MUX_sec_mi2s,
+	MSM_MUX_slimbus,
+	MSM_MUX_spkr_mi2s,
+	MSM_MUX_ter_mi2s,
+	MSM_MUX_tsif1,
+	MSM_MUX_tsif2,
+	MSM_MUX_uim1,
+	MSM_MUX_uim2,
+	MSM_MUX_uim3,
+	MSM_MUX_uim4,
+	MSM_MUX_uim_batt_alarm,
+	MSM_MUX_gpio,
+	MSM_MUX_NA,
+};
+
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145",
+};
+
+static const char * const blsp_spi1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3"
+};
+static const char * const blsp_uart1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3"
+};
+static const char * const blsp_uim1_groups[] = {
+	"gpio0", "gpio1"
+};
+static const char * const blsp_i2c1_groups[] = {
+	"gpio2", "gpio3"
+};
+static const char * const blsp_spi2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7"
+};
+static const char * const blsp_uart2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7"
+};
+static const char * const blsp_uim2_groups[] = {
+	"gpio4", "gpio5"
+};
+static const char * const qdss_cti_trig_out_b_groups[] = {
+	"gpio4",
+};
+static const char * const qdss_cti_trig_in_b_groups[] = {
+	"gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+	"gpio6", "gpio7"
+};
+static const char * const blsp_spi3_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11"
+};
+static const char * const blsp_uart3_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11"
+};
+static const char * const blsp_uim3_groups[] = {
+	"gpio8", "gpio9"
+};
+static const char * const blsp_spi1_cs1_groups[] = {
+	"gpio8"
+};
+static const char * const blsp_spi1_cs2_groups[] = {
+	"gpio9", "gpio11"
+};
+static const char * const mdp_vsync_groups[] = {
+	"gpio10", "gpio11", "gpio12"
+};
+static const char * const blsp_i2c3_groups[] = {
+	"gpio10", "gpio11"
+};
+static const char * const blsp_spi1_cs3_groups[] = {
+	"gpio10"
+};
+static const char * const qdss_tracedata_b_groups[] = {
+	"gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18",
+	"gpio19", "gpio21", "gpio22", "gpio23", "gpio25", "gpio26",
+	"gpio57", "gpio58", "gpio92", "gpio93",
+};
+static const char * const cam_mclk0_groups[] = {
+	"gpio13"
+};
+static const char * const cam_mclk1_groups[] = {
+	"gpio14"
+};
+static const char * const cam_mclk2_groups[] = {
+	"gpio15"
+};
+static const char * const cam_mclk3_groups[] = {
+	"gpio16"
+};
+static const char * const cci_i2c0_groups[] = {
+	"gpio17", "gpio18"
+};
+static const char * const blsp_spi4_groups[] = {
+	"gpio17", "gpio18", "gpio19", "gpio20"
+};
+static const char * const blsp_uart4_groups[] = {
+	"gpio17", "gpio18", "gpio19", "gpio20"
+};
+static const char * const blsp_uim4_groups[] = {
+	"gpio17", "gpio18"
+};
+static const char * const cci_i2c1_groups[] = {
+	"gpio19", "gpio20"
+};
+static const char * const blsp_i2c4_groups[] = {
+	"gpio19", "gpio20"
+};
+static const char * const cci_timer0_groups[] = {
+	"gpio21"
+};
+static const char * const blsp_spi5_groups[] = {
+	"gpio21", "gpio22", "gpio23", "gpio24"
+};
+static const char * const blsp_uart5_groups[] = {
+	"gpio21", "gpio22", "gpio23", "gpio24"
+};
+static const char * const blsp_uim5_groups[] = {
+	"gpio21", "gpio22"
+};
+static const char * const cci_timer1_groups[] = {
+	"gpio22"
+};
+static const char * const cci_timer2_groups[] = {
+	"gpio23"
+};
+static const char * const blsp_i2c5_groups[] = {
+	"gpio23", "gpio24"
+};
+static const char * const cci_timer3_groups[] = {
+	"gpio24"
+};
+static const char * const cci_async_in1_groups[] = {
+	"gpio24"
+};
+static const char * const cci_timer4_groups[] = {
+	"gpio25"
+};
+static const char * const cci_async_in2_groups[] = {
+	"gpio25"
+};
+static const char * const blsp_spi6_groups[] = {
+	"gpio25", "gpio26", "gpio27", "gpio28"
+};
+static const char * const blsp_uart6_groups[] = {
+	"gpio25", "gpio26", "gpio27", "gpio28"
+};
+static const char * const blsp_uim6_groups[] = {
+	"gpio25", "gpio26"
+};
+static const char * const cci_async_in0_groups[] = {
+	"gpio26"
+};
+static const char * const gp0_clk_groups[] = {
+	"gpio26"
+};
+static const char * const gp1_clk_groups[] = {
+	"gpio27", "gpio57", "gpio78"
+};
+static const char * const blsp_i2c6_groups[] = {
+	"gpio27", "gpio28"
+};
+static const char * const qdss_tracectl_a_groups[] = {
+	"gpio27",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+	"gpio28",
+};
+static const char * const gp_mn_groups[] = {
+	"gpio29"
+};
+static const char * const hdmi_cec_groups[] = {
+	"gpio31"
+};
+static const char * const hdmi_ddc_groups[] = {
+	"gpio32", "gpio33"
+};
+static const char * const hdmi_hpd_groups[] = {
+	"gpio34"
+};
+static const char * const uim3_groups[] = {
+	"gpio35", "gpio36", "gpio37", "gpio38"
+};
+static const char * const pci_e1_groups[] = {
+	"gpio35", "gpio36",
+};
+static const char * const blsp_spi7_groups[] = {
+	"gpio41", "gpio42", "gpio43", "gpio44"
+};
+static const char * const blsp_uart7_groups[] = {
+	"gpio41", "gpio42", "gpio43", "gpio44"
+};
+static const char * const blsp_uim7_groups[] = {
+	"gpio41", "gpio42"
+};
+static const char * const qdss_cti_trig_out_c_groups[] = {
+	"gpio41",
+};
+static const char * const qdss_cti_trig_in_c_groups[] = {
+	"gpio42",
+};
+static const char * const blsp_i2c7_groups[] = {
+	"gpio43", "gpio44"
+};
+static const char * const blsp_spi8_groups[] = {
+	"gpio45", "gpio46", "gpio47", "gpio48"
+};
+static const char * const blsp_uart8_groups[] = {
+	"gpio45", "gpio46", "gpio47", "gpio48"
+};
+static const char * const blsp_uim8_groups[] = {
+	"gpio45", "gpio46"
+};
+static const char * const blsp_i2c8_groups[] = {
+	"gpio47", "gpio48"
+};
+static const char * const blsp_spi10_cs1_groups[] = {
+	"gpio47", "gpio67"
+};
+static const char * const blsp_spi10_cs2_groups[] = {
+	"gpio48", "gpio68"
+};
+static const char * const uim2_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_spi9_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_uart9_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52"
+};
+static const char * const blsp_uim9_groups[] = {
+	"gpio49", "gpio50"
+};
+static const char * const blsp_i2c9_groups[] = {
+	"gpio51", "gpio52"
+};
+static const char * const pci_e0_groups[] = {
+	"gpio53", "gpio54",
+};
+static const char * const uim4_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_spi10_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_uart10_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56"
+};
+static const char * const blsp_uim10_groups[] = {
+	"gpio53", "gpio54"
+};
+static const char * const qdss_tracedata_a_groups[] = {
+	"gpio53", "gpio54", "gpio63", "gpio64", "gpio65",
+	"gpio66", "gpio67", "gpio74", "gpio75", "gpio76",
+	"gpio77", "gpio85", "gpio86", "gpio87", "gpio89",
+	"gpio90"
+};
+static const char * const gp_pdm0_groups[] = {
+	"gpio54", "gpio95"
+};
+static const char * const blsp_i2c10_groups[] = {
+	"gpio55", "gpio56"
+};
+static const char * const qdss_cti_trig_in_a_groups[] = {
+	"gpio55",
+};
+static const char * const qdss_cti_trig_out_a_groups[] = {
+	"gpio56",
+};
+static const char * const qua_mi2s_groups[] = {
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+};
+static const char * const gcc_gp_clk1_groups[] = {
+	"gpio57", "gpio78"
+};
+static const char * const gcc_gp_clk2_groups[] = {
+	"gpio58", "gpio81"
+};
+static const char * const gcc_gp_clk3_groups[] = {
+	"gpio59", "gpio82"
+};
+static const char * const blsp_spi2_cs1_groups[] = {
+	"gpio62"
+};
+static const char * const blsp_spi2_cs2_groups[] = {
+	"gpio63"
+};
+static const char * const gp_pdm2_groups[] = {
+	"gpio63", "gpio79"
+};
+static const char * const pri_mi2s_groups[] = {
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+static const char * const blsp_spi2_cs3_groups[] = {
+	"gpio66"
+};
+static const char * const spkr_mi2s_groups[] = {
+	"gpio69", "gpio70", "gpio71", "gpio72"
+};
+static const char * const audio_ref_clk_groups[] = {
+	"gpio69"
+};
+static const char * const slimbus_groups[] = {
+	"gpio70", "gpio71"
+};
+static const char * const ter_mi2s_groups[] = {
+	"gpio73", "gpio74", "gpio75", "gpio76", "gpio77"
+};
+static const char * const gp_pdm1_groups[] = {
+	"gpio74", "gpio86"
+};
+static const char * const sec_mi2s_groups[] = {
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
+};
+static const char * const blsp_spi11_groups[] = {
+	"gpio81", "gpio82", "gpio83", "gpio84"
+};
+static const char * const blsp_uart11_groups[] = {
+	"gpio81", "gpio82", "gpio83", "gpio84"
+};
+static const char * const blsp_uim11_groups[] = {
+	"gpio81", "gpio82"
+};
+static const char * const blsp_i2c11_groups[] = {
+	"gpio83", "gpio84"
+};
+static const char * const blsp_uart12_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88"
+};
+static const char * const blsp_uim12_groups[] = {
+	"gpio85", "gpio86"
+};
+static const char * const blsp_i2c12_groups[] = {
+	"gpio87", "gpio88"
+};
+static const char * const blsp_spi12_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88"
+};
+static const char * const tsif1_groups[] = {
+	"gpio89", "gpio90", "gpio91", "gpio110", "gpio111"
+};
+static const char * const blsp_spi10_cs3_groups[] = {
+	"gpio90"
+};
+static const char * const sdc4_groups[] = {
+	"gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
+};
+static const char * const qdss_traceclk_b_groups[] = {
+	"gpio91",
+};
+static const char * const tsif2_groups[] = {
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
+};
+static const char * const qdss_tracectl_b_groups[] = {
+	"gpio94",
+};
+static const char * const qdss_cti_trig_out_d_groups[] = {
+	"gpio95",
+};
+static const char * const qdss_cti_trig_in_d_groups[] = {
+	"gpio96",
+};
+static const char * const uim1_groups[] = {
+	"gpio97", "gpio98", "gpio99", "gpio100"
+};
+static const char * const uim_batt_alarm_groups[] = {
+	"gpio101"
+};
+static const char * const blsp11_uart_tx_b_groups[] = {
+	"gpio111"
+};
+static const char * const blsp11_uart_rx_b_groups[] = {
+	"gpio112"
+};
+static const char * const blsp11_i2c_sda_b_groups[] = {
+	"gpio113"
+};
+static const char * const blsp11_i2c_scl_b_groups[] = {
+	"gpio114"
+};
+static const char * const grfc_groups[] = {
+	"gpio115", "gpio116", "gpio117", "gpio118", "gpio119", "gpio120",
+	"gpio121", "gpio122", "gpio123", "gpio124", "gpio125", "gpio126",
+	"gpio127", "gpio128", "gpio129", "gpio133"
+};
+static const char * const rffe6_groups[] = {
+	"gpio115", "gpio116"
+};
+static const char * const rffe7_groups[] = {
+	"gpio117", "gpio118"
+};
+static const char * const gsm_tx_groups[] = {
+	"gpio126", "gpio131", "gpio132", "gpio133"
+};
+static const char * const nav_tsync_groups[] = {
+	"gpio127"
+};
+static const char * const nav_pps_groups[] = {
+	"gpio127"
+};
+static const char * const gps_tx_groups[] = {
+	"gpio130"
+};
+static const char * const mss_lte_groups[] = {
+	"gpio134", "gpio135"
+};
+static const char * const rffe1_groups[] = {
+	"gpio136", "gpio137"
+};
+static const char * const rffe2_groups[] = {
+	"gpio138", "gpio139"
+};
+static const char * const rffe3_groups[] = {
+	"gpio140", "gpio141"
+};
+static const char * const rffe4_groups[] = {
+	"gpio142", "gpio143"
+};
+static const char * const rffe5_groups[] = {
+	"gpio144", "gpio145"
+};
+
+static const struct msm_function msm8994_functions[] = {
+	FUNCTION(audio_ref_clk),
+	FUNCTION(blsp_i2c1),
+	FUNCTION(blsp_i2c2),
+	FUNCTION(blsp_i2c3),
+	FUNCTION(blsp_i2c4),
+	FUNCTION(blsp_i2c5),
+	FUNCTION(blsp_i2c6),
+	FUNCTION(blsp_i2c7),
+	FUNCTION(blsp_i2c8),
+	FUNCTION(blsp_i2c9),
+	FUNCTION(blsp_i2c10),
+	FUNCTION(blsp_i2c11),
+	FUNCTION(blsp_i2c12),
+	FUNCTION(blsp_spi1),
+	FUNCTION(blsp_spi1_cs1),
+	FUNCTION(blsp_spi1_cs2),
+	FUNCTION(blsp_spi1_cs3),
+	FUNCTION(blsp_spi2),
+	FUNCTION(blsp_spi2_cs1),
+	FUNCTION(blsp_spi2_cs2),
+	FUNCTION(blsp_spi2_cs3),
+	FUNCTION(blsp_spi3),
+	FUNCTION(blsp_spi4),
+	FUNCTION(blsp_spi5),
+	FUNCTION(blsp_spi6),
+	FUNCTION(blsp_spi7),
+	FUNCTION(blsp_spi8),
+	FUNCTION(blsp_spi9),
+	FUNCTION(blsp_spi10),
+	FUNCTION(blsp_spi10_cs1),
+	FUNCTION(blsp_spi10_cs2),
+	FUNCTION(blsp_spi10_cs3),
+	FUNCTION(blsp_spi11),
+	FUNCTION(blsp_spi12),
+	FUNCTION(blsp_uart1),
+	FUNCTION(blsp_uart2),
+	FUNCTION(blsp_uart3),
+	FUNCTION(blsp_uart4),
+	FUNCTION(blsp_uart5),
+	FUNCTION(blsp_uart6),
+	FUNCTION(blsp_uart7),
+	FUNCTION(blsp_uart8),
+	FUNCTION(blsp_uart9),
+	FUNCTION(blsp_uart10),
+	FUNCTION(blsp_uart11),
+	FUNCTION(blsp_uart12),
+	FUNCTION(blsp_uim1),
+	FUNCTION(blsp_uim2),
+	FUNCTION(blsp_uim3),
+	FUNCTION(blsp_uim4),
+	FUNCTION(blsp_uim5),
+	FUNCTION(blsp_uim6),
+	FUNCTION(blsp_uim7),
+	FUNCTION(blsp_uim8),
+	FUNCTION(blsp_uim9),
+	FUNCTION(blsp_uim10),
+	FUNCTION(blsp_uim11),
+	FUNCTION(blsp_uim12),
+	FUNCTION(blsp11_i2c_scl_b),
+	FUNCTION(blsp11_i2c_sda_b),
+	FUNCTION(blsp11_uart_rx_b),
+	FUNCTION(blsp11_uart_tx_b),
+	FUNCTION(cam_mclk0),
+	FUNCTION(cam_mclk1),
+	FUNCTION(cam_mclk2),
+	FUNCTION(cam_mclk3),
+	FUNCTION(cci_async_in0),
+	FUNCTION(cci_async_in1),
+	FUNCTION(cci_async_in2),
+	FUNCTION(cci_i2c0),
+	FUNCTION(cci_i2c1),
+	FUNCTION(cci_timer0),
+	FUNCTION(cci_timer1),
+	FUNCTION(cci_timer2),
+	FUNCTION(cci_timer3),
+	FUNCTION(cci_timer4),
+	FUNCTION(gcc_gp_clk1),
+	FUNCTION(gcc_gp_clk2),
+	FUNCTION(gcc_gp_clk3),
+	FUNCTION(gp_mn),
+	FUNCTION(gp_pdm0),
+	FUNCTION(gp_pdm1),
+	FUNCTION(gp_pdm2),
+	FUNCTION(gp0_clk),
+	FUNCTION(gp1_clk),
+	FUNCTION(gps_tx),
+	FUNCTION(grfc),
+	FUNCTION(gsm_tx),
+	FUNCTION(hdmi_cec),
+	FUNCTION(hdmi_ddc),
+	FUNCTION(hdmi_hpd),
+	FUNCTION(mdp_vsync),
+	FUNCTION(mss_lte),
+	FUNCTION(nav_pps),
+	FUNCTION(nav_tsync),
+	FUNCTION(qdss_cti_trig_in_a),
+	FUNCTION(qdss_cti_trig_in_b),
+	FUNCTION(qdss_cti_trig_in_c),
+	FUNCTION(qdss_cti_trig_in_d),
+	FUNCTION(qdss_cti_trig_out_a),
+	FUNCTION(qdss_cti_trig_out_b),
+	FUNCTION(qdss_cti_trig_out_c),
+	FUNCTION(qdss_cti_trig_out_d),
+	FUNCTION(qdss_traceclk_a),
+	FUNCTION(qdss_traceclk_b),
+	FUNCTION(qdss_tracectl_a),
+	FUNCTION(qdss_tracectl_b),
+	FUNCTION(qdss_tracedata_a),
+	FUNCTION(qdss_tracedata_b),
+	FUNCTION(qua_mi2s),
+	FUNCTION(pci_e0),
+	FUNCTION(pci_e1),
+	FUNCTION(pri_mi2s),
+	FUNCTION(rffe1),
+	FUNCTION(rffe2),
+	FUNCTION(rffe3),
+	FUNCTION(rffe4),
+	FUNCTION(rffe5),
+	FUNCTION(rffe6),
+	FUNCTION(rffe7),
+	FUNCTION(sdc4),
+	FUNCTION(sec_mi2s),
+	FUNCTION(slimbus),
+	FUNCTION(spkr_mi2s),
+	FUNCTION(ter_mi2s),
+	FUNCTION(tsif1),
+	FUNCTION(tsif2),
+	FUNCTION(uim_batt_alarm),
+	FUNCTION(uim1),
+	FUNCTION(uim2),
+	FUNCTION(uim3),
+	FUNCTION(uim4),
+	FUNCTION(gpio),
+};
+
+static const struct msm_pingroup msm8994_groups[] = {
+	PINGROUP(0,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(1,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(2,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(3,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(4,   blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti_trig_out_b,
+		 NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(5,   blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti_trig_in_b, NA,
+		 NA, NA, NA, NA, NA, NA),
+	PINGROUP(6,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(7,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(8,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(9,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(10,  mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3,
+		 blsp_spi1_cs3, NA, NA, NA, NA, NA, NA),
+	PINGROUP(11,  mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3,
+		 blsp_spi1_cs2, NA, NA, NA, NA, NA, NA),
+	PINGROUP(12,  mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(13,  cam_mclk0, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(14,  cam_mclk1, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(15,  cam_mclk2, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(16,  cam_mclk3, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(17,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA,
+		 qdss_tracedata_b, NA, NA, NA, NA, NA),
+	PINGROUP(18,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA,
+		 qdss_tracedata_b, NA, NA, NA, NA, NA),
+	PINGROUP(19,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA,
+		 qdss_tracedata_b, NA, NA, NA, NA, NA),
+	PINGROUP(20,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(21,  cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA,
+		 qdss_tracedata_b, NA, NA, NA, NA, NA),
+	PINGROUP(22,  cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA,
+		 qdss_tracedata_b, NA, NA, NA, NA, NA),
+	PINGROUP(23,  cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA,
+		 qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(24,  cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5,
+		 blsp_i2c5, NA, NA, NA, NA, NA, NA),
+	PINGROUP(25,  cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6,
+		 blsp_uim6, NA, NA, qdss_tracedata_b, NA, NA, NA),
+	PINGROUP(26,  cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, gp0_clk,
+		 NA, qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(27,  blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk,
+		 qdss_tracectl_a, NA, NA, NA, NA, NA, NA),
+	PINGROUP(28,  blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_a, NA,
+		 NA, NA, NA, NA, NA, NA),
+	PINGROUP(29,  gp_mn, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(30,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(31,  hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(32,  hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(33,  hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34,  hdmi_hpd, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(35,  uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(36,  uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37,  uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38,  uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(39,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(40,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(41,  blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_out_c,
+		 NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(42,  blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_in_c, NA,
+		 NA, NA, NA, NA, NA, NA),
+	PINGROUP(43,  blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(44,  blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(45,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(46,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(47,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(48,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(49,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(50,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(51,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(52,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(53,  uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, NA,
+		 NA, NA, NA, qdss_tracedata_a, NA),
+	PINGROUP(54,  uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10,
+		 gp_pdm0, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(55,  uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA,
+		 NA, NA, qdss_cti_trig_in_a, NA),
+	PINGROUP(56,  uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA,
+		 NA, qdss_cti_trig_out_a, NA, NA),
+	PINGROUP(57,  qua_mi2s, gcc_gp_clk1, NA, NA, NA, NA, qdss_tracedata_b,
+		 NA, NA, NA, NA),
+	PINGROUP(58,  qua_mi2s, gcc_gp_clk2, NA, NA, NA, NA, qdss_tracedata_b,
+		 NA, NA, NA, NA),
+	PINGROUP(59,  qua_mi2s, gcc_gp_clk3, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(60,  qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61,  qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62,  qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(63,  qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA, NA),
+	PINGROUP(64,  pri_mi2s, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA,
+		 NA, NA),
+	PINGROUP(65,  pri_mi2s, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA,
+		 NA, NA),
+	PINGROUP(66,  pri_mi2s, blsp_spi2_cs3, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA, NA, NA),
+	PINGROUP(67,  pri_mi2s, blsp_spi10_cs1, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA, NA, NA),
+	PINGROUP(68,  pri_mi2s, blsp_spi10_cs2, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(69,  spkr_mi2s, audio_ref_clk, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(70,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72,  spkr_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73,  ter_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74,  ter_mi2s, gp_pdm1, NA, NA, NA, NA, NA, qdss_tracedata_a,
+		 NA, NA, NA),
+	PINGROUP(75,  ter_mi2s, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(76,  ter_mi2s, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(77,  ter_mi2s, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(78,  sec_mi2s, gcc_gp_clk1, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(79,  sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(80,  sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11,
+		 gcc_gp_clk2, NA, NA, NA, NA, NA, NA),
+	PINGROUP(82,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11,
+		 gcc_gp_clk3, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(84,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(85,  blsp_spi12, blsp_uart12, blsp_uim12, NA, NA,
+		 qdss_tracedata_a, NA, NA, NA, NA, NA),
+	PINGROUP(86,  blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA,
+		 qdss_tracedata_a, NA, NA, NA, NA, NA),
+	PINGROUP(87,  blsp_spi12, blsp_uart12, blsp_i2c12, NA,
+		 qdss_tracedata_a, NA, NA, NA, NA, NA, NA),
+	PINGROUP(88,  blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(89,  tsif1, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(90,  tsif1, blsp_spi10_cs3, qdss_tracedata_a, NA, NA, NA, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(91,  tsif1, sdc4, NA, NA, NA, NA, qdss_traceclk_b, NA, NA, NA,
+		 NA),
+	PINGROUP(92,  tsif2, sdc4, NA, NA, qdss_tracedata_b, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(93,  tsif2, sdc4, NA, NA, NA, NA, qdss_tracedata_b, NA, NA,
+		 NA, NA),
+	PINGROUP(94,  tsif2, sdc4, NA, NA, NA, NA, qdss_tracectl_b, NA, NA, NA,
+		 NA),
+	PINGROUP(95,  tsif2, sdc4, gp_pdm0, NA, NA, NA, qdss_cti_trig_out_d,
+		 NA, NA, NA, NA),
+	PINGROUP(96,  tsif2, sdc4, qdss_cti_trig_in_d, NA, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(97,  uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(98,  uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(99,  uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(110, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(111, tsif1, blsp11_uart_tx_b, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(112, blsp11_uart_rx_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(113, blsp11_i2c_sda_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(114, blsp11_i2c_scl_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(115, grfc, rffe6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(116, grfc, rffe6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(117, grfc, rffe7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(118, grfc, rffe7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(119, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(120, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(121, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(122, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(123, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(124, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(125, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(126, grfc, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(127, grfc, nav_tsync, nav_pps, NA, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(128, NA, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(129, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(130, gps_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(131, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(132, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(133, gsm_tx, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(134, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(135, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(136, rffe1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(137, rffe1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(138, rffe2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(139, rffe2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(140, rffe3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(141, rffe3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(142, rffe4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(143, rffe4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(144, rffe5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(145, rffe5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	SDC_PINGROUP(sdc1_rclk, 0x2044, 15, 0),
+	SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6),
+	SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3),
+	SDC_PINGROUP(sdc1_data, 0x2044, 9, 0),
+	SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6),
+	SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3),
+	SDC_PINGROUP(sdc2_data, 0x2048, 9, 0),
+	SDC_PINGROUP(sdc3_clk, 0x206c, 14, 6),
+	SDC_PINGROUP(sdc3_cmd, 0x206c, 11, 3),
+	SDC_PINGROUP(sdc3_data, 0x206c, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 146
+
+static const struct msm_pinctrl_soc_data msm8994_pinctrl = {
+	.pins = msm8994_pins,
+	.npins = ARRAY_SIZE(msm8994_pins),
+	.functions = msm8994_functions,
+	.nfunctions = ARRAY_SIZE(msm8994_functions),
+	.groups = msm8994_groups,
+	.ngroups = ARRAY_SIZE(msm8994_groups),
+	.ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int msm8994_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &msm8994_pinctrl);
+}
+
+static const struct of_device_id msm8994_pinctrl_of_match[] = {
+	{ .compatible = "qcom,msm8994-pinctrl", },
+	{ },
+};
+
+static struct platform_driver msm8994_pinctrl_driver = {
+	.driver = {
+		.name = "msm8994-pinctrl",
+		.of_match_table = msm8994_pinctrl_of_match,
+	},
+	.probe = msm8994_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init msm8994_pinctrl_init(void)
+{
+	return platform_driver_register(&msm8994_pinctrl_driver);
+}
+arch_initcall(msm8994_pinctrl_init);
+
+static void __exit msm8994_pinctrl_exit(void)
+{
+	platform_driver_unregister(&msm8994_pinctrl_driver);
+}
+module_exit(msm8994_pinctrl_exit);
+
+MODULE_DESCRIPTION("Qualcomm MSM8994 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8994_pinctrl_of_match);
-- 
2.9.3

^ permalink raw reply related

* [PATCH v4 0/3] mtd: s3c2410: add device tree support
From: Sergio Prado @ 2016-10-26 23:59 UTC (permalink / raw)
  To: kgene, krzk, javier, linux, linux, boris.brezillon, richard,
	dwmw2, computersforpeace, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-mtd, robh+dt, mark.rutland, devicetree
  Cc: Sergio Prado

This series adds support for configuring Samsung's s3c2410 and
compatible flash memory controller via devicetree.

Tested on FriendlyARM mini2440, based on s3c2440 SoC.

Patch 3 depends on patch 1.

Changes since v3:
- apply the timings in the end of ->setup_data_interface so the
  timings can be changed at runtime by the MTD core.

Changes since v2:
- conditionally assign chip->setup_data_interface to
  s3c2410_nand_setup_data_interface if booting via device tree

Changes since v1:
- automate timing selection when booting with a device tree
- make s3c24XX_nand_devtype_data structs "static const"
- removing samsung,s3c6400-nand compatible since it is equivalent to
  samsung,s3c2412-nand

Changes since initial version:
- patch converted to a patch series
- read timings from nand_sdr_timings when booting with a device tree
- naming improvements in the device tree binding
  (s/nand/nand-controller/, s/_/-, s/children/child)
- dropped property samsung,ignore_unset_ecc
- remove @0 from nand device node
- checking pdev->dev.of_node instead of using ifdef CONFIG_OF_MTD
- preventing from parsing device tree properties twice
- increment the nand controller child node refcount, since we
  maintain a reference to it and its name field
- using of_device_get_match_data() instead of of_match_device()
  to make the code simpler
- remove CONFIG_MTD_NAND_S3C2410_HWECC compile option so we can
  select ECC mode using nand-ecc-mode property in the device tree

Sergio Prado (3):
  mtd: s3c2410: make ecc mode configurable via platform data
  dt-bindings: mtd: add DT binding for s3c2410 flash controller
  mtd: s3c2410: parse the device configuration from OF node

 .../devicetree/bindings/mtd/samsung-s3c2410.txt    |  56 +++++
 arch/arm/mach-s3c24xx/common-smdk.c                |   1 +
 arch/arm/mach-s3c24xx/mach-anubis.c                |   1 +
 arch/arm/mach-s3c24xx/mach-at2440evb.c             |   1 +
 arch/arm/mach-s3c24xx/mach-bast.c                  |   1 +
 arch/arm/mach-s3c24xx/mach-gta02.c                 |   1 +
 arch/arm/mach-s3c24xx/mach-jive.c                  |   1 +
 arch/arm/mach-s3c24xx/mach-mini2440.c              |   1 +
 arch/arm/mach-s3c24xx/mach-osiris.c                |   1 +
 arch/arm/mach-s3c24xx/mach-qt2410.c                |   1 +
 arch/arm/mach-s3c24xx/mach-rx1950.c                |   1 +
 arch/arm/mach-s3c24xx/mach-rx3715.c                |   1 +
 arch/arm/mach-s3c24xx/mach-vstms.c                 |   1 +
 arch/arm/mach-s3c64xx/mach-hmt.c                   |   1 +
 arch/arm/mach-s3c64xx/mach-mini6410.c              |   1 +
 arch/arm/mach-s3c64xx/mach-real6410.c              |   1 +
 drivers/mtd/nand/Kconfig                           |   9 -
 drivers/mtd/nand/s3c2410.c                         | 277 +++++++++++++++------
 include/linux/platform_data/mtd-nand-s3c2410.h     |   7 +-
 19 files changed, 278 insertions(+), 86 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt

-- 
1.9.1

^ permalink raw reply

* [PATCH v4 1/3] mtd: s3c2410: make ecc mode configurable via platform data
From: Sergio Prado @ 2016-10-26 23:59 UTC (permalink / raw)
  To: kgene, krzk, javier, linux, linux, boris.brezillon, richard,
	dwmw2, computersforpeace, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-mtd, robh+dt, mark.rutland, devicetree
  Cc: Sergio Prado
In-Reply-To: <1477526395-13103-1-git-send-email-sergio.prado@e-labworks.com>

Removing CONFIG_MTD_NAND_S3C2410_HWECC option and adding a ecc_mode
field in the drivers's platform data structure so it can be selectable
via platform data.

Also setting this field to NAND_ECC_SOFT in all boards using this
driver since none of them had CONFIG_MTD_NAND_S3C2410_HWECC enabled.

Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>
---
 arch/arm/mach-s3c24xx/common-smdk.c            |   1 +
 arch/arm/mach-s3c24xx/mach-anubis.c            |   1 +
 arch/arm/mach-s3c24xx/mach-at2440evb.c         |   1 +
 arch/arm/mach-s3c24xx/mach-bast.c              |   1 +
 arch/arm/mach-s3c24xx/mach-gta02.c             |   1 +
 arch/arm/mach-s3c24xx/mach-jive.c              |   1 +
 arch/arm/mach-s3c24xx/mach-mini2440.c          |   1 +
 arch/arm/mach-s3c24xx/mach-osiris.c            |   1 +
 arch/arm/mach-s3c24xx/mach-qt2410.c            |   1 +
 arch/arm/mach-s3c24xx/mach-rx1950.c            |   1 +
 arch/arm/mach-s3c24xx/mach-rx3715.c            |   1 +
 arch/arm/mach-s3c24xx/mach-vstms.c             |   1 +
 arch/arm/mach-s3c64xx/mach-hmt.c               |   1 +
 arch/arm/mach-s3c64xx/mach-mini6410.c          |   1 +
 arch/arm/mach-s3c64xx/mach-real6410.c          |   1 +
 drivers/mtd/nand/Kconfig                       |   9 --
 drivers/mtd/nand/s3c2410.c                     | 119 +++++++++++++------------
 include/linux/platform_data/mtd-nand-s3c2410.h |   6 +-
 18 files changed, 79 insertions(+), 70 deletions(-)

diff --git a/arch/arm/mach-s3c24xx/common-smdk.c b/arch/arm/mach-s3c24xx/common-smdk.c
index e9fbcc91c5c0..9e0bc46e90ec 100644
--- a/arch/arm/mach-s3c24xx/common-smdk.c
+++ b/arch/arm/mach-s3c24xx/common-smdk.c
@@ -171,6 +171,7 @@
 	.twrph1		= 20,
 	.nr_sets	= ARRAY_SIZE(smdk_nand_sets),
 	.sets		= smdk_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* devices we initialise */
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index d03df0df01fa..029ef1b58925 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -223,6 +223,7 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
 	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
 	.sets		= anubis_nand_sets,
 	.select_chip	= anubis_nand_select,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* IDE channels */
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index 9ae170fef2a7..7b28eb623fc1 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -114,6 +114,7 @@
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(at2440evb_nand_sets),
 	.sets		= at2440evb_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000AEP 10/100 ethernet controller */
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index ed07cf392d4b..5185036765db 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -299,6 +299,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot)
 	.nr_sets	= ARRAY_SIZE(bast_nand_sets),
 	.sets		= bast_nand_sets,
 	.select_chip	= bast_nand_select,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000 */
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index 27ae6877550f..b0ed401da3a3 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -443,6 +443,7 @@ static void gta02_udc_vbus_draw(unsigned int ma)
 	.twrph1		= 15,
 	.nr_sets	= ARRAY_SIZE(gta02_nand_sets),
 	.sets		= gta02_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index 7d99fe8f6157..895aca225952 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -232,6 +232,7 @@
 	.twrph1		= 40,
 	.sets		= jive_nand_sets,
 	.nr_sets	= ARRAY_SIZE(jive_nand_sets),
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static int __init jive_mtdset(char *options)
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index ec60bd4a1646..71af8d2fd320 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -287,6 +287,7 @@
 	.nr_sets	= ARRAY_SIZE(mini2440_nand_sets),
 	.sets		= mini2440_nand_sets,
 	.ignore_unset_ecc = 1,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000AEP 10/100 ethernet controller */
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index 2f6fdc326835..70b0eb7d3134 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -238,6 +238,7 @@ static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
 	.nr_sets	= ARRAY_SIZE(osiris_nand_sets),
 	.sets		= osiris_nand_sets,
 	.select_chip	= osiris_nand_select,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* PCMCIA control and configuration */
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 984516e8307a..868c82087403 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -284,6 +284,7 @@
 	.twrph1		= 20,
 	.nr_sets	= ARRAY_SIZE(qt2410_nand_sets),
 	.sets		= qt2410_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* UDC */
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 25a139bb9826..e86ad6a68a0b 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -611,6 +611,7 @@ static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd)
 	.twrph1 = 15,
 	.nr_sets = ARRAY_SIZE(rx1950_nand_sets),
 	.sets = rx1950_nand_sets,
+	.ecc_mode = NAND_ECC_SOFT,
 };
 
 static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index cf55196f89ca..a39fb9780dd3 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -164,6 +164,7 @@
 	.twrph1		= 15,
 	.nr_sets	= ARRAY_SIZE(rx3715_nand_sets),
 	.sets		= rx3715_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *rx3715_devices[] __initdata = {
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index b4460d5f7011..f5e6322145fa 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -117,6 +117,7 @@
 	.twrph1		= 20,
 	.nr_sets	= ARRAY_SIZE(vstms_nand_sets),
 	.sets		= vstms_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *vstms_devices[] __initdata = {
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index bc7dc1fcbf7d..59b5531f1987 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -204,6 +204,7 @@ static void hmt_bl_exit(struct device *dev)
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(hmt_nand_sets),
 	.sets		= hmt_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct gpio_led hmt_leds[] = {
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index ae999fb3fe6d..a3e3e25728b4 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -142,6 +142,7 @@
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(mini6410_nand_sets),
 	.sets		= mini6410_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = {
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 4e240ffa7ac7..d6b3ffd7704b 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -194,6 +194,7 @@
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(real6410_nand_sets),
 	.sets		= real6410_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *real6410_devices[] __initdata = {
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7b7a887b4709..9748f3580d4b 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -179,15 +179,6 @@ config MTD_NAND_S3C2410_DEBUG
 	help
 	  Enable debugging of the S3C NAND driver
 
-config MTD_NAND_S3C2410_HWECC
-	bool "Samsung S3C NAND Hardware ECC"
-	depends on MTD_NAND_S3C2410
-	help
-	  Enable the use of the controller's internal ECC generator when
-	  using NAND. Early versions of the chips have had problems with
-	  incorrect ECC generation, and if using these, the default of
-	  software ECC is preferable.
-
 config MTD_NAND_NDFC
 	tristate "NDFC NanD Flash Controller"
 	depends on 4xx
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d459c19d78de..371db0d48135 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -497,7 +497,6 @@ static int s3c2412_nand_devready(struct mtd_info *mtd)
 
 /* ECC handling functions */
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				     u_char *read_ecc, u_char *calc_ecc)
 {
@@ -649,7 +648,6 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
 	return 0;
 }
-#endif
 
 /* over-ride the standard functions for a little more speed. We can
  * use read/write block to move the data buffers to/from the controller
@@ -858,50 +856,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 	nmtd->info	   = info;
 	nmtd->set	   = set;
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
-	chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-	chip->ecc.correct   = s3c2410_nand_correct_data;
-	chip->ecc.mode	    = NAND_ECC_HW;
-	chip->ecc.strength  = 1;
-
-	switch (info->cpu_type) {
-	case TYPE_S3C2410:
-		chip->ecc.hwctl	    = s3c2410_nand_enable_hwecc;
-		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-		break;
-
-	case TYPE_S3C2412:
-		chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
-		chip->ecc.calculate = s3c2412_nand_calculate_ecc;
-		break;
-
-	case TYPE_S3C2440:
-		chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
-		chip->ecc.calculate = s3c2440_nand_calculate_ecc;
-		break;
-	}
-#else
-	chip->ecc.mode	    = NAND_ECC_SOFT;
-	chip->ecc.algo	= NAND_ECC_HAMMING;
-#endif
-
-	if (set->disable_ecc)
-		chip->ecc.mode	= NAND_ECC_NONE;
-
-	switch (chip->ecc.mode) {
-	case NAND_ECC_NONE:
-		dev_info(info->device, "NAND ECC disabled\n");
-		break;
-	case NAND_ECC_SOFT:
-		dev_info(info->device, "NAND soft ECC\n");
-		break;
-	case NAND_ECC_HW:
-		dev_info(info->device, "NAND hardware ECC\n");
-		break;
-	default:
-		dev_info(info->device, "NAND ECC UNKNOWN\n");
-		break;
-	}
+	chip->ecc.mode = info->platform->ecc_mode;
 
 	/* If you use u-boot BBT creation code, specifying this flag will
 	 * let the kernel fish out the BBT from the NAND, and also skip the
@@ -923,28 +878,72 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
  *
  * The internal state is currently limited to the ECC state information.
 */
-static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
+static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 				     struct s3c2410_nand_mtd *nmtd)
 {
 	struct nand_chip *chip = &nmtd->chip;
 
-	dev_dbg(info->device, "chip %p => page shift %d\n",
-		chip, chip->page_shift);
+	switch (chip->ecc.mode) {
 
-	if (chip->ecc.mode != NAND_ECC_HW)
-		return;
+	case NAND_ECC_NONE:
+		dev_info(info->device, "ECC disabled\n");
+		break;
+
+	case NAND_ECC_SOFT:
+		/*
+		 * This driver expects Hamming based ECC when ecc_mode is set
+		 * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
+		 * avoid adding an extra ecc_algo field to s3c2410_platform_nand.
+		 */
+		chip->ecc.algo = NAND_ECC_HAMMING;
+		dev_info(info->device, "soft ECC\n");
+		break;
+
+	case NAND_ECC_HW:
+		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+		chip->ecc.correct   = s3c2410_nand_correct_data;
+		chip->ecc.strength  = 1;
+
+		switch (info->cpu_type) {
+		case TYPE_S3C2410:
+			chip->ecc.hwctl	    = s3c2410_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+			break;
+
+		case TYPE_S3C2412:
+			chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2412_nand_calculate_ecc;
+			break;
+
+		case TYPE_S3C2440:
+			chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2440_nand_calculate_ecc;
+			break;
+		}
+
+		dev_dbg(info->device, "chip %p => page shift %d\n",
+			chip, chip->page_shift);
 
 		/* change the behaviour depending on whether we are using
 		 * the large or small page nand device */
+		if (chip->page_shift > 10) {
+			chip->ecc.size	    = 256;
+			chip->ecc.bytes	    = 3;
+		} else {
+			chip->ecc.size	    = 512;
+			chip->ecc.bytes	    = 3;
+			mtd_set_ooblayout(nand_to_mtd(chip), &s3c2410_ooblayout_ops);
+		}
 
-	if (chip->page_shift > 10) {
-		chip->ecc.size	    = 256;
-		chip->ecc.bytes	    = 3;
-	} else {
-		chip->ecc.size	    = 512;
-		chip->ecc.bytes	    = 3;
-		mtd_set_ooblayout(nand_to_mtd(chip), &s3c2410_ooblayout_ops);
+		dev_info(info->device, "hardware ECC\n");
+		break;
+
+	default:
+		dev_err(info->device, "invalid ECC mode!\n");
+		return -EINVAL;
 	}
+
+	return 0;
 }
 
 /* s3c24xx_nand_probe
@@ -1046,7 +1045,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 						 NULL);
 
 		if (nmtd->scan_res == 0) {
-			s3c2410_nand_update_chip(info, nmtd);
+			err = s3c2410_nand_update_chip(info, nmtd);
+			if (err < 0)
+				goto exit_error;
 			nand_scan_tail(mtd);
 			s3c2410_nand_add_partition(info, nmtd, sets);
 		}
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
index c55e42ee57fa..729af13d1773 100644
--- a/include/linux/platform_data/mtd-nand-s3c2410.h
+++ b/include/linux/platform_data/mtd-nand-s3c2410.h
@@ -12,9 +12,10 @@
 #ifndef __MTD_NAND_S3C2410_H
 #define __MTD_NAND_S3C2410_H
 
+#include <linux/mtd/nand.h>
+
 /**
  * struct s3c2410_nand_set - define a set of one or more nand chips
- * @disable_ecc:	Entirely disable ECC - Dangerous
  * @flash_bbt: 		Openmoko u-boot can create a Bad Block Table
  *			Setting this flag will allow the kernel to
  *			look for it at boot time and also skip the NAND
@@ -31,7 +32,6 @@
  * a warning at boot time.
  */
 struct s3c2410_nand_set {
-	unsigned int		disable_ecc:1;
 	unsigned int		flash_bbt:1;
 
 	unsigned int		options;
@@ -51,6 +51,8 @@ struct s3c2410_platform_nand {
 
 	unsigned int	ignore_unset_ecc:1;
 
+	nand_ecc_modes_t	ecc_mode;
+
 	int			nr_sets;
 	struct s3c2410_nand_set *sets;
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v4 2/3] dt-bindings: mtd: add DT binding for s3c2410 flash controller
From: Sergio Prado @ 2016-10-26 23:59 UTC (permalink / raw)
  To: kgene-DgEjT+Ai2ygdnm+yROfE0A, krzk-DgEjT+Ai2ygdnm+yROfE0A,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	linux-Y5A6D6n0/KfQXOPxS62xeg,
	boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	richard-/L3Ra7n9ekc, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergio Prado
In-Reply-To: <1477526395-13103-1-git-send-email-sergio.prado-1e4yhPs3/ABSwrhanM7KvQ@public.gmane.org>

Adds the device tree bindings description for Samsung S3C2410 and
compatible NAND flash controller.

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Krzysztof Kozlowski <krzk-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Sergio Prado <sergio.prado-1e4yhPs3/ABSwrhanM7KvQ@public.gmane.org>
---
 .../devicetree/bindings/mtd/samsung-s3c2410.txt    | 56 ++++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt

diff --git a/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt b/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
new file mode 100644
index 000000000000..0040eb8895e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
@@ -0,0 +1,56 @@
+* Samsung S3C2410 and compatible NAND flash controller
+
+Required properties:
+- compatible : The possible values are:
+	"samsung,s3c2410-nand"
+	"samsung,s3c2412-nand"
+	"samsung,s3c2440-nand"
+- reg : register's location and length.
+- #address-cells, #size-cells : see nand.txt
+- clocks : phandle to the nand controller clock
+- clock-names : must contain "nand"
+
+Optional child nodes:
+Child nodes representing the available nand chips.
+
+Optional child properties:
+- nand-ecc-mode : see nand.txt
+- nand-on-flash-bbt : see nand.txt
+
+Each child device node may optionally contain a 'partitions' sub-node,
+which further contains sub-nodes describing the flash partition mapping.
+See partition.txt for more detail.
+
+Example:
+
+nand-controller@4e000000 {
+	compatible = "samsung,s3c2440-nand";
+	reg = <0x4e000000 0x40>;
+
+	#address-cells = <1>;
+        #size-cells = <0>;
+
+	clocks = <&clocks HCLK_NAND>;
+	clock-names = "nand";
+
+	nand {
+		nand-ecc-mode = "soft";
+		nand-on-flash-bbt;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0 0x040000>;
+			};
+
+			partition@40000 {
+				label = "kernel";
+				reg = <0x040000 0x500000>;
+			};
+		};
+	};
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v4 3/3] mtd: s3c2410: parse the device configuration from OF node
From: Sergio Prado @ 2016-10-26 23:59 UTC (permalink / raw)
  To: kgene-DgEjT+Ai2ygdnm+yROfE0A, krzk-DgEjT+Ai2ygdnm+yROfE0A,
	javier-JPH+aEBZ4P+UEJcrhfAQsw, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	linux-Y5A6D6n0/KfQXOPxS62xeg,
	boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	richard-/L3Ra7n9ekc, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Sergio Prado
In-Reply-To: <1477526395-13103-1-git-send-email-sergio.prado-1e4yhPs3/ABSwrhanM7KvQ@public.gmane.org>

Allows configuring Samsung's s3c2410 memory controller using a
devicetree.

Signed-off-by: Sergio Prado <sergio.prado-1e4yhPs3/ABSwrhanM7KvQ@public.gmane.org>
---
 drivers/mtd/nand/s3c2410.c                     | 158 ++++++++++++++++++++++---
 include/linux/platform_data/mtd-nand-s3c2410.h |   1 +
 2 files changed, 143 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 371db0d48135..b13208c526f8 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -39,6 +39,8 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -185,6 +187,22 @@ struct s3c2410_nand_info {
 #endif
 };
 
+struct s3c24XX_nand_devtype_data {
+	enum s3c_cpu_type type;
+};
+
+static const struct s3c24XX_nand_devtype_data s3c2410_nand_devtype_data = {
+	.type = TYPE_S3C2410,
+};
+
+static const struct s3c24XX_nand_devtype_data s3c2412_nand_devtype_data = {
+	.type = TYPE_S3C2412,
+};
+
+static const struct s3c24XX_nand_devtype_data s3c2440_nand_devtype_data = {
+	.type = TYPE_S3C2440,
+};
+
 /* conversion functions */
 
 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
@@ -794,6 +812,30 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 	return -ENODEV;
 }
 
+static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd,
+					     const struct nand_data_interface *conf,
+					     bool check_only)
+{
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	struct s3c2410_platform_nand *pdata = info->platform;
+	const struct nand_sdr_timings *timings;
+	int tacls;
+
+	timings = nand_get_sdr_timings(conf);
+	if (IS_ERR(timings))
+		return -ENOTSUPP;
+
+	tacls = timings->tCLS_min - timings->tWP_min;
+	if (tacls < 0)
+		tacls = 0;
+
+	pdata->tacls  = DIV_ROUND_UP(tacls, 1000);
+	pdata->twrph0 = DIV_ROUND_UP(timings->tWP_min, 1000);
+	pdata->twrph1 = DIV_ROUND_UP(timings->tCLH_min, 1000);
+
+	return s3c2410_nand_setrate(info);
+}
+
 /**
  * s3c2410_nand_init_chip - initialise a single instance of an chip
  * @info: The base NAND controller the chip is on.
@@ -808,9 +850,12 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 				   struct s3c2410_nand_mtd *nmtd,
 				   struct s3c2410_nand_set *set)
 {
+	struct device_node *np = info->device->of_node;
 	struct nand_chip *chip = &nmtd->chip;
 	void __iomem *regs = info->regs;
 
+	nand_set_flash_node(chip, set->of_node);
+
 	chip->write_buf    = s3c2410_nand_write_buf;
 	chip->read_buf     = s3c2410_nand_read_buf;
 	chip->select_chip  = s3c2410_nand_select_chip;
@@ -819,6 +864,13 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 	chip->options	   = set->options;
 	chip->controller   = &info->controller;
 
+	/*
+	 * let's keep behavior unchanged for legacy boards booting via pdata and
+	 * auto-detect timings only when booting with a device tree.
+	 */
+	if (np)
+		chip->setup_data_interface = s3c2410_nand_setup_data_interface;
+
 	switch (info->cpu_type) {
 	case TYPE_S3C2410:
 		chip->IO_ADDR_W = regs + S3C2410_NFDATA;
@@ -859,12 +911,9 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 	chip->ecc.mode = info->platform->ecc_mode;
 
 	/* If you use u-boot BBT creation code, specifying this flag will
-	 * let the kernel fish out the BBT from the NAND, and also skip the
-	 * full NAND scan that can take 1/2s or so. Little things... */
-	if (set->flash_bbt) {
+	 * let the kernel fish out the BBT from the NAND */
+	if (set->flash_bbt)
 		chip->bbt_options |= NAND_BBT_USE_FLASH;
-		chip->options |= NAND_SKIP_BBTSCAN;
-	}
 }
 
 /**
@@ -943,6 +992,77 @@ static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 		return -EINVAL;
 	}
 
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->options |= NAND_SKIP_BBTSCAN;
+
+	return 0;
+}
+
+static const struct of_device_id s3c24xx_nand_dt_ids[] = {
+	{
+		.compatible = "samsung,s3c2410-nand",
+		.data = &s3c2410_nand_devtype_data,
+	}, {
+		.compatible = "samsung,s3c2412-nand", /* also compatible with s3c6400 */
+		.data = &s3c2412_nand_devtype_data,
+	}, {
+		.compatible = "samsung,s3c2440-nand",
+		.data = &s3c2440_nand_devtype_data,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_nand_dt_ids);
+
+static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
+{
+	const struct s3c24XX_nand_devtype_data *devtype_data;
+	struct s3c2410_platform_nand *pdata;
+	struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node, *child;
+	struct s3c2410_nand_set *sets;
+
+	devtype_data = of_device_get_match_data(&pdev->dev);
+	if (!devtype_data)
+		return -ENODEV;
+
+	info->cpu_type = devtype_data->type;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdev->dev.platform_data = pdata;
+
+	pdata->nr_sets = of_get_child_count(np);
+	if (!pdata->nr_sets)
+		return 0;
+
+	sets = devm_kzalloc(&pdev->dev, sizeof(*sets) * pdata->nr_sets, GFP_KERNEL);
+	if (!sets)
+		return -ENOMEM;
+
+	pdata->sets = sets;
+
+	for_each_available_child_of_node(np, child) {
+
+		sets->name = (char *)child->name;
+		sets->of_node = child;
+		sets->nr_chips = 1;
+
+		of_node_get(child);
+
+		sets++;
+	}
+
+	return 0;
+}
+
+static int s3c24xx_nand_probe_pdata(struct platform_device *pdev)
+{
+	struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
+
+	info->cpu_type = platform_get_device_id(pdev)->driver_data;
+
 	return 0;
 }
 
@@ -955,8 +1075,7 @@ static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 */
 static int s3c24xx_nand_probe(struct platform_device *pdev)
 {
-	struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
-	enum s3c_cpu_type cpu_type;
+	struct s3c2410_platform_nand *plat;
 	struct s3c2410_nand_info *info;
 	struct s3c2410_nand_mtd *nmtd;
 	struct s3c2410_nand_set *sets;
@@ -966,8 +1085,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 	int nr_sets;
 	int setno;
 
-	cpu_type = platform_get_device_id(pdev)->driver_data;
-
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (info == NULL) {
 		err = -ENOMEM;
@@ -989,6 +1106,16 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
 	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
+	if (pdev->dev.of_node)
+		err = s3c24xx_nand_probe_dt(pdev);
+	else
+		err = s3c24xx_nand_probe_pdata(pdev);
+
+	if (err)
+		goto exit_error;
+
+	plat = to_nand_plat(pdev);
+
 	/* allocate and map the resource */
 
 	/* currently we assume we have the one resource */
@@ -997,7 +1124,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
 	info->device	= &pdev->dev;
 	info->platform	= plat;
-	info->cpu_type	= cpu_type;
 
 	info->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(info->regs)) {
@@ -1007,12 +1133,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
 	dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
 
-	/* initialise the hardware */
-
-	err = s3c2410_nand_inithw(info);
-	if (err != 0)
-		goto exit_error;
-
 	sets = (plat != NULL) ? plat->sets : NULL;
 	nr_sets = (plat != NULL) ? plat->nr_sets : 1;
 
@@ -1056,6 +1176,11 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 			sets++;
 	}
 
+	/* initialise the hardware */
+	err = s3c2410_nand_inithw(info);
+	if (err != 0)
+		goto exit_error;
+
 	err = s3c2410_nand_cpufreq_register(info);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to init cpufreq support\n");
@@ -1156,6 +1281,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 	.id_table	= s3c24xx_driver_ids,
 	.driver		= {
 		.name	= "s3c24xx-nand",
+		.of_match_table = s3c24xx_nand_dt_ids,
 	},
 };
 
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
index 729af13d1773..f01659026b26 100644
--- a/include/linux/platform_data/mtd-nand-s3c2410.h
+++ b/include/linux/platform_data/mtd-nand-s3c2410.h
@@ -40,6 +40,7 @@ struct s3c2410_nand_set {
 	char			*name;
 	int			*nr_map;
 	struct mtd_partition	*partitions;
+	struct device_node	*of_node;
 };
 
 struct s3c2410_platform_nand {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH 0/6] msm8992/msm8994: Google Nexus 5X/6P initial board support
From: Jeremy McNicoll @ 2016-10-27  0:56 UTC (permalink / raw)
  To: Jeremy McNicoll, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: robh-DgEjT+Ai2ygdnm+yROfE0A, andy.gross-QSEj5FYQhm4dnm+yROfE0A,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	michael.scott-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1477394221-30963-1-git-send-email-jeremymc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On 2016-10-25 4:16 AM, Jeremy McNicoll wrote:
>
>
> Dropping RFC, as looks like its in reasonable shape for merging.
>
> V1:
>  [http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442069.html]
>
> V2:
>  [http://www.spinics.net/lists/linux-soc/msg01059.html]
>
> V3:
>  [http://www.spinics.net/lists/linux-soc/msg01089.html]
>
> V4:
>  [http://www.spinics.net/lists/linux-arm-msm/msg23849.html]
>
>
> V4->V5:
>
>   -gave each board their own respective line in Makefile, rolled into
>     this change instead of creating a new commit for just a Makefile
>     update.
>
>   -moved qcom,pmic-id to msm8992-bullhead-rev-101.dts , likewise for
> 	8994.
>
>   -minor cosmetic cleanups of board files:
> 	-removed extra braces for board
>   	-dropped the frequency table
> 	-replaced hardcoded #'s with symbolic names
> 	-removed properties not being used	
>
>   -instead of using msm8974 for basic pinctrl, now we are using
>    Micheal Scott's from here, [https://patches.linaro.org/patch/78750/]
>    All associated dts files updated accordingly.
>
>   -converted all timer,frame interrupt entries to associated symbolic
>    / macro values.  ie) GIC_SPI -> 0
>
>   -defconfig changed to enable 8994 pinctrl instead of 8974
>
>   -updated both 8992, 8994 dts so that the timer node is outside soc.
>
>
>
> Appreciate all the feedback thus far.

These changes were successfully booted on my msm8992 (Nexus 5X).
Unfortunately I don't have a Nexus 6p for testing. (donations greatly 
appreciated)

Downstream (3.10) code has been used for all of this work, but access
to the HW docs would make this work (hopefully) easier.  If you can help
with this feel free to contact me directly.

-jeremy

[..snip..]
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH V2 1/4] Documentation: pv88080: Move binding document
From: Eric Jeong @ 2016-10-27  1:03 UTC (permalink / raw)
  To: DEVICETREE, LINUX-KERNEL, Mark Rutland, Rob Herring
  Cc: Alexandre Courbot, LINUX-GPIO, Lee Jones, Liam Girdwood,
	Linus Walleij, Mark Brown, Support Opensource
In-Reply-To: <cover.1477530195.git.eric.jeong@diasemi.com>


From: Eric Jeong <eric.jeong.opensource@diasemi.com>

The change is to move pv88080 binding document 
from the regulator directory to mfd binding directory
for PV88080 PMIC MFD support.


Signed-off-by: Eric Jeong <eric.jeong.opensource@diasemi.com>

---
This patch applies against linux-next and next-20161026

Hi,

Change since PATCH V1
 - Patch separated from PATCH V1

Regards,
Eric Jeong, Dialog Semiconductor Ltd.


 Documentation/devicetree/bindings/mfd/pv88080.txt  |   63 ++++++++++++++++++++
 .../devicetree/bindings/regulator/pv88080.txt      |   62 -------------------
 2 files changed, 63 insertions(+), 62 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/pv88080.txt
 delete mode 100644 Documentation/devicetree/bindings/regulator/pv88080.txt

diff --git a/Documentation/devicetree/bindings/mfd/pv88080.txt b/Documentation/devicetree/bindings/mfd/pv88080.txt
new file mode 100644
index 0000000..7b556b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/pv88080.txt
@@ -0,0 +1,63 @@
+* Powerventure Semiconductor PV88080 PMIC
+
+Required properties:
+- compatible: Must be one of the following, depending on the
+  silicon version:
+	- "pvs,pv88080" (DEPRECATED)
+
+	- "pvs,pv88080-aa" for PV88080 AA or AB silicon
+	- "pvs,pv88080-ba" for PV88080 BA or BB silicon
+  NOTE: The use of the compatibles with no silicon version is deprecated.
+- reg: I2C slave address, usually 0x49
+- interrupts: the interrupt outputs of the controller
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name, with valid
+  values listed below. The content of each sub-node is defined by the
+  standard binding for regulators; see regulator.txt.
+  BUCK1, BUCK2, BUCK3 and HVBUCK.
+
+Optional properties:
+- Any optional property defined in regulator.txt
+  and gpio.txt for more information.
+
+Example:
+
+	pmic: pv88080@49 {
+		compatible = "pvs,pv88080-ba";
+		reg = <0x49>;
+		interrupt-parent = <&gpio>;
+		interrupts = <24 24>;
+
+		regulators {
+			BUCK1 {
+				regulator-name = "buck1";
+				regulator-min-microvolt = < 600000>;
+				regulator-max-microvolt = <1393750>;
+				regulator-min-microamp 	= < 220000>;
+				regulator-max-microamp 	= <7040000>;
+			};
+
+			BUCK2 {
+				regulator-name = "buck2";
+				regulator-min-microvolt = < 600000>;
+				regulator-max-microvolt = <1393750>;
+				regulator-min-microamp 	= <1496000>;
+				regulator-max-microamp 	= <4189000>;
+			};
+
+			BUCK3 {
+				regulator-name = "buck3";
+				regulator-min-microvolt = <1400000>;
+				regulator-max-microvolt = <2193750>;
+				regulator-min-microamp 	= <1496000>;
+				regulator-max-microamp 	= <4189000>;
+			};
+
+			HVBUCK {
+				regulator-name = "hvbuck";
+				regulator-min-microvolt = <   5000>;
+				regulator-max-microvolt = <1275000>;
+ 			};
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/regulator/pv88080.txt b/Documentation/devicetree/bindings/regulator/pv88080.txt
deleted file mode 100644
index e6e4b9c8..0000000
--- a/Documentation/devicetree/bindings/regulator/pv88080.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-* Powerventure Semiconductor PV88080 Voltage Regulator
-
-Required properties:
-- compatible: Must be one of the following, depending on the
-  silicon version:
-	- "pvs,pv88080" (DEPRECATED)
-
-	- "pvs,pv88080-aa" for PV88080 AA or AB silicon
-	- "pvs,pv88080-ba" for PV88080 BA or BB silicon
-  NOTE: The use of the compatibles with no silicon version is deprecated.
-- reg: I2C slave address, usually 0x49
-- interrupts: the interrupt outputs of the controller
-- regulators: A node that houses a sub-node for each regulator within the
-  device. Each sub-node is identified using the node's name, with valid
-  values listed below. The content of each sub-node is defined by the
-  standard binding for regulators; see regulator.txt.
-  BUCK1, BUCK2, BUCK3 and HVBUCK.
-
-Optional properties:
-- Any optional property defined in regulator.txt
-
-Example:
-
-	pmic: pv88080@49 {
-		compatible = "pvs,pv88080-ba";
-		reg = <0x49>;
-		interrupt-parent = <&gpio>;
-		interrupts = <24 24>;
-
-		regulators {
-			BUCK1 {
-				regulator-name = "buck1";
-				regulator-min-microvolt = < 600000>;
-				regulator-max-microvolt = <1393750>;
-				regulator-min-microamp 	= < 220000>;
-				regulator-max-microamp 	= <7040000>;
-			};
-
-			BUCK2 {
-				regulator-name = "buck2";
-				regulator-min-microvolt = < 600000>;
-				regulator-max-microvolt = <1393750>;
-				regulator-min-microamp 	= <1496000>;
-				regulator-max-microamp 	= <4189000>;
-			};
-
-			BUCK3 {
-				regulator-name = "buck3";
-				regulator-min-microvolt = <1400000>;
-				regulator-max-microvolt = <2193750>;
-				regulator-min-microamp 	= <1496000>;
-				regulator-max-microamp 	= <4189000>;
-			};
-
-			HVBUCK {
-				regulator-name = "hvbuck";
-				regulator-min-microvolt = <   5000>;
-				regulator-max-microvolt = <1275000>;
- 			};
-		};
-	};
-
-- 
end-of-patch for PATCH V2


^ permalink raw reply related

* [PATCH V2 2/4] mfd: pv88080: MFD core support
From: Eric Jeong @ 2016-10-27  1:03 UTC (permalink / raw)
  To: LINUX-KERNEL, Lee Jones
  Cc: Alexandre Courbot, DEVICETREE, LINUX-GPIO, Liam Girdwood,
	Linus Walleij, Mark Brown, Mark Rutland, Rob Herring,
	Support Opensource
In-Reply-To: <cover.1477530195.git.eric.jeong@diasemi.com>


From: Eric Jeong <eric.jeong.opensource@diasemi.com> 
 
This patch adds supports for PV88080 MFD core device.

It provides communication through the I2C interface.
It contains the following components:
    - Regulators
    - Configurable GPIOs
 
Kconfig and Makefile are updated to reflect support for PV88080 PMIC. 

Signed-off-by: Eric Jeong <eric.jeong.opensource@diasemi.com> 

---
This patch applies against linux-next and next-20161026 
 
Hi, 

This patch adds MFD core driver for PV88080 PMIC.
This is done as part of the existing PV88080 regulator driver by expending
the driver for GPIO function support.

Change since PATCH V1
 - Patch separated from PATCH V1

Regards,
Eric Jeong, Dialog Semiconductor Ltd.


 drivers/mfd/Kconfig         |   12 ++
 drivers/mfd/Makefile        |    2 +
 drivers/mfd/pv88080-core.c  |  270 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/pv88080-i2c.c   |   99 ++++++++++++++++
 include/linux/mfd/pv88080.h |  236 +++++++++++++++++++++++++++++++++++++
 5 files changed, 619 insertions(+)
 create mode 100644 drivers/mfd/pv88080-core.c
 create mode 100644 drivers/mfd/pv88080-i2c.c
 create mode 100644 include/linux/mfd/pv88080.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df644..d69edf4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -775,6 +775,18 @@ config MFD_PM8921_CORE
 	  Say M here if you want to include support for PM8921 chip as a module.
 	  This will build a module called "pm8921-core".
 
+config MFD_PV88080
+	bool "Powerventure Semiconductor PV88080 PMIC Support"
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	depends on I2C
+	help
+	  Say yes here for support for the Powerventure Semiconductor PV88080 PMIC.
+	  This includes the I2C driver and core APIs.
+	  Additional drivers must be enabled in order to use the functionality
+	  of the device.
+
 config MFD_QCOM_RPM
 	tristate "Qualcomm Resource Power Manager (RPM)"
 	depends on ARCH_QCOM && OF
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9834e66..6248e0b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -173,6 +173,8 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
+pv88080-objs := pv88080-core.o pv88080-i2c.o
+obj-$(CONFIG_MFD_PV88080)	+= pv88080.o
 obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
 obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
diff --git a/drivers/mfd/pv88080-core.c b/drivers/mfd/pv88080-core.c
new file mode 100644
index 0000000..b858f06
--- /dev/null
+++ b/drivers/mfd/pv88080-core.c
@@ -0,0 +1,270 @@
+/*
+ * pv88080-core.c - Device access for PV88080
+ *
+ * Copyright (C) 2016  Powerventure Semiconductor Ltd.
+ *
+ * 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
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+
+#include <linux/mfd/pv88080.h>
+
+#define	PV88080_REG_EVENT_A_OFFSET	0
+#define	PV88080_REG_EVENT_B_OFFSET	1
+#define	PV88080_REG_EVENT_C_OFFSET	2
+
+static const struct resource regulators_aa_resources[] = {
+	{
+		.name	= "regulator-irq",
+		.start  = PV88080_AA_IRQ_VDD_FLT,
+		.end	= PV88080_AA_IRQ_OVER_TEMP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static const struct resource regulators_ba_resources[] = {
+	{
+		.name	= "regulator-irq",
+		.start  = PV88080_BA_IRQ_VDD_FLT,
+		.end	= PV88080_BA_IRQ_OVER_TEMP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell pv88080_cells[] = {
+	{
+		.name = "pv88080-regulator",
+	},
+	{
+		.name = "pv88080-gpio",
+	},
+};
+
+static const struct regmap_irq pv88080_aa_irqs[] = {
+	/* PV88080 event A register for AA/AB silicon */
+	[PV88080_AA_IRQ_VDD_FLT] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_VDD_FLT,
+	},
+	[PV88080_AA_IRQ_OVER_TEMP] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_OVER_TEMP,
+	},
+	[PV88080_AA_IRQ_SEQ_RDY] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_SEQ_RDY,
+	},
+	/* PV88080 event B register for AA/AB silicon */
+	[PV88080_AA_IRQ_HVBUCK_OV] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_HVBUCK_OV,
+	},
+	[PV88080_AA_IRQ_HVBUCK_UV] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_HVBUCK_UV,
+	},
+	[PV88080_AA_IRQ_HVBUCK_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_HVBUCK_SCP,
+	},
+	[PV88080_AA_IRQ_BUCK1_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_BUCK1_SCP,
+	},
+	[PV88080_AA_IRQ_BUCK2_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_BUCK2_SCP,
+	},
+	[PV88080_AA_IRQ_BUCK3_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_BUCK3_SCP,
+	},
+	/* PV88080 event C register for AA/AB silicon */
+	[PV88080_AA_IRQ_GPIO_FLAG0] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_GPIO_FLAG0,
+	},
+	[PV88080_AA_IRQ_GPIO_FLAG1] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_GPIO_FLAG1,
+	},
+};
+
+static const struct regmap_irq pv88080_ba_irqs[] = {
+	/* PV88080 event A register for BA/BB silicon */
+	[PV88080_BA_IRQ_VDD_FLT] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_VDD_FLT,
+	},
+	[PV88080_BA_IRQ_OVER_TEMP] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_OVER_TEMP,
+	},
+	[PV88080_BA_IRQ_SEQ_RDY] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_SEQ_RDY,
+	},
+	[PV88080_BA_IRQ_EXT_OT] = {
+		.reg_offset = PV88080_REG_EVENT_A_OFFSET,
+		.mask = PV88080_M_EXT_OT,
+	},
+	/* PV88080 event B register for BA/BB silicon */
+	[PV88080_BA_IRQ_HVBUCK_OV] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_HVBUCK_OV,
+	},
+	[PV88080_BA_IRQ_HVBUCK_UV] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_HVBUCK_UV,
+	},
+	[PV88080_BA_IRQ_HVBUCK_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_HVBUCK_SCP,
+	},
+	[PV88080_BA_IRQ_BUCK1_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_BUCK1_SCP,
+	},
+	[PV88080_BA_IRQ_BUCK2_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_BUCK2_SCP,
+	},
+	[PV88080_BA_IRQ_BUCK3_SCP] = {
+		.reg_offset = PV88080_REG_EVENT_B_OFFSET,
+		.mask = PV88080_M_BUCK3_SCP,
+	},
+	/* PV88080 event C register for BA/BB silicon */
+	[PV88080_BA_IRQ_GPIO_FLAG0] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_GPIO_FLAG0,
+	},
+	[PV88080_BA_IRQ_GPIO_FLAG1] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_GPIO_FLAG1,
+	},
+	[PV88080_BA_IRQ_BUCK1_DROP_TIMEOUT] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_BUCK1_DROP_TIMEOUT,
+	},
+	[PV88080_BA_IRQ_BUCK2_DROP_TIMEOUT] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_BUCK2_DROP_TIMEOUT,
+	},
+	[PB88080_BA_IRQ_BUCK3_DROP_TIMEOUT] = {
+		.reg_offset = PV88080_REG_EVENT_C_OFFSET,
+		.mask = PV88080_M_BUCk3_DROP_TIMEOUT,
+	},
+};
+
+static struct regmap_irq_chip pv88080_irq_chip = {
+	.name = "pv88080-irq",
+	.num_regs = 3,
+	.status_base = PV88080_REG_EVENT_A,
+	.mask_base = PV88080_REG_MASK_A,
+	.ack_base = PV88080_REG_EVENT_A,
+	.init_ack_masked = true,
+};
+
+int pv88080_device_init(struct pv88080 *chip, unsigned int irq)
+{
+	struct pv88080_pdata *pdata = dev_get_platdata(chip->dev);
+	int ret;
+
+	if (pdata)
+		chip->irq_base = pdata->irq_base;
+	else
+		chip->irq_base = 0;
+	chip->irq = irq;
+
+	if (pdata && pdata->init != NULL) {
+		ret = pdata->init(chip);
+		if (ret != 0) {
+			dev_err(chip->dev, "Platform initialization failed\n");
+			return ret;
+		}
+	}
+
+	ret = regmap_write(chip->regmap, PV88080_REG_MASK_A, 0xFF);
+	if (ret < 0) {
+		dev_err(chip->dev,
+			"Failed to mask A reg: %d\n", ret);
+		return ret;
+	}
+	ret = regmap_write(chip->regmap, PV88080_REG_MASK_B, 0xFF);
+	if (ret < 0) {
+		dev_err(chip->dev,
+			"Failed to mask B reg: %d\n", ret);
+		return ret;
+	}
+	ret = regmap_write(chip->regmap, PV88080_REG_MASK_C, 0xFF);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to mask C reg: %d\n", ret);
+		return ret;
+	}
+
+	switch (chip->type) {
+	case TYPE_PV88080_AA:
+		pv88080_irq_chip.irqs = pv88080_aa_irqs;
+		pv88080_irq_chip.num_irqs = ARRAY_SIZE(pv88080_aa_irqs);
+
+		pv88080_cells[0].num_resources
+				= ARRAY_SIZE(regulators_aa_resources);
+		pv88080_cells[0].resources = regulators_aa_resources;
+		break;
+	case TYPE_PV88080_BA:
+		pv88080_irq_chip.irqs = pv88080_ba_irqs;
+		pv88080_irq_chip.num_irqs = ARRAY_SIZE(pv88080_ba_irqs);
+
+		pv88080_cells[0].num_resources
+				= ARRAY_SIZE(regulators_ba_resources);
+		pv88080_cells[0].resources = regulators_ba_resources;
+		break;
+	}
+
+	ret = regmap_add_irq_chip(chip->regmap, chip->irq,
+			IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+			chip->irq_base, &pv88080_irq_chip,
+			&chip->irq_data);
+	if (ret) {
+		dev_err(chip->dev, "Failed to reguest IRQ %d: %d\n",
+				chip->irq, ret);
+		return ret;
+	}
+
+	ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE,
+			pv88080_cells, ARRAY_SIZE(pv88080_cells),
+			NULL, chip->irq_base, NULL);
+	if (ret) {
+		dev_err(chip->dev, "Cannot add MFD cells\n");
+		regmap_del_irq_chip(chip->irq, chip->irq_data);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pv88080_device_init);
+
+int pv88080_device_exit(struct pv88080 *chip)
+{
+	mfd_remove_devices(chip->dev);
+	regmap_del_irq_chip(chip->irq, chip->irq_data);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pv88080_device_exit);
+
+MODULE_AUTHOR("Eric Jeong <eric.jeong.opensource@diasemi.com>");
+MODULE_DESCRIPTION("MFD driver for Powerventure PV88080");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/pv88080-i2c.c b/drivers/mfd/pv88080-i2c.c
new file mode 100644
index 0000000..a90cd40
--- /dev/null
+++ b/drivers/mfd/pv88080-i2c.c
@@ -0,0 +1,99 @@
+/*
+ * pv88080-i2c.c - I2C access driver for PV88080
+ *
+ * Copyright (C) 2016  Powerventure Semiconductor Ltd.
+ *
+ * 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
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/pv88080.h>
+
+static const struct regmap_config pv88080_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static const struct of_device_id pv88080_of_match_table[] = {
+	{ .compatible = "pvs,pv88080",    .data = (void *)TYPE_PV88080_AA },
+	{ .compatible = "pvs,pv88080-aa", .data = (void *)TYPE_PV88080_AA },
+	{ .compatible = "pvs,pv88080-ba", .data = (void *)TYPE_PV88080_BA },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, pv88080_of_match_table);
+
+static int pv88080_i2c_probe(struct i2c_client *client,
+				const struct i2c_device_id *ids)
+{
+	struct pv88080 *chip;
+	const struct of_device_id *match;
+
+	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	if (client->dev.of_node) {
+		match = of_match_node(pv88080_of_match_table,
+						client->dev.of_node);
+		if (!match) {
+			dev_err(&client->dev, "Failed to get of_match_node\n");
+			return -EINVAL;
+		}
+		chip->type = (unsigned long)match->data;
+	} else {
+		chip->type = ids->driver_data;
+	}
+
+	i2c_set_clientdata(client, chip);
+
+	chip->dev = &client->dev;
+	chip->regmap = devm_regmap_init_i2c(client, &pv88080_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		dev_err(chip->dev, "Failed to initialize register map\n");
+		return PTR_ERR(chip->regmap);
+	}
+
+	return pv88080_device_init(chip, client->irq);
+}
+
+static int pv88080_i2c_remove(struct i2c_client *client)
+{
+	struct pv88080 *chip = i2c_get_clientdata(client);
+
+	return pv88080_device_exit(chip);
+}
+
+static const struct i2c_device_id pv88080_i2c_id[] = {
+	{ "pv88080",	TYPE_PV88080_AA },
+	{ "pv88080-aa", TYPE_PV88080_AA },
+	{ "pv88080-ba", TYPE_PV88080_BA },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
+
+static struct i2c_driver pv88080_i2c_driver = {
+	.driver	 = {
+		.name	 = "pv88080",
+		.of_match_table = of_match_ptr(pv88080_of_match_table),
+	},
+	.probe	= pv88080_i2c_probe,
+	.remove	= pv88080_i2c_remove,
+	.id_table	 = pv88080_i2c_id,
+};
+module_i2c_driver(pv88080_i2c_driver);
+
+MODULE_AUTHOR("Eric Jeong <eric.jeong.opensource@diasemi.com>");
+MODULE_DESCRIPTION("I2C driver for Powerventure PV88080");
+MODULE_LICENSE("GPL");
+
diff --git a/include/linux/mfd/pv88080.h b/include/linux/mfd/pv88080.h
new file mode 100644
index 0000000..505ce63
--- /dev/null
+++ b/include/linux/mfd/pv88080.h
@@ -0,0 +1,236 @@
+/*
+ * pv88080.h - Declarations for PV88080.
+ * Copyright (C) 2016 Powerventure Semiconductor Ltd.
+ *
+ * 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
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PV88080_H__
+#define __PV88080_H__
+
+#include <linux/regulator/machine.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+/* System Control and Event Registers */
+#define PV88080_REG_STATUS_A			0x01
+#define PV88080_REG_EVENT_A				0x04
+#define PV88080_REG_MASK_A				0x09
+#define PV88080_REG_MASK_B				0x0A
+#define PV88080_REG_MASK_C				0x0B
+
+/* GPIO Registers - rev. AA */
+#define PV88080AA_REG_GPIO_INPUT		0x18
+#define PV88080AA_REG_GPIO_GPIO0		0x1A
+
+/* Regulator Registers - rev. AA */
+#define PV88080AA_REG_HVBUCK_CONF1		0x2D
+#define PV88080AA_REG_HVBUCK_CONF2		0x2E
+#define PV88080AA_REG_BUCK1_CONF0		0x27
+#define PV88080AA_REG_BUCK1_CONF1		0x28
+#define PV88080AA_REG_BUCK1_CONF2		0x59
+#define PV88080AA_REG_BUCK1_CONF5		0x5C
+#define PV88080AA_REG_BUCK2_CONF0		0x29
+#define PV88080AA_REG_BUCK2_CONF1		0x2A
+#define PV88080AA_REG_BUCK2_CONF2		0x61
+#define PV88080AA_REG_BUCK2_CONF5		0x64
+#define PV88080AA_REG_BUCK3_CONF0		0x2B
+#define PV88080AA_REG_BUCK3_CONF1		0x2C
+#define PV88080AA_REG_BUCK3_CONF2		0x69
+#define PV88080AA_REG_BUCK3_CONF5		0x6C
+
+/* GPIO Registers - rev. BA */
+#define PV88080BA_REG_GPIO_INPUT		0x17
+#define PV88080BA_REG_GPIO_GPIO0		0x19
+
+/* Regulator Registers - rev. BA */
+#define PV88080BA_REG_HVBUCK_CONF1		0x33
+#define PV88080BA_REG_HVBUCK_CONF2		0x34
+#define PV88080BA_REG_BUCK1_CONF0		0x2A
+#define PV88080BA_REG_BUCK1_CONF1		0x2C
+#define PV88080BA_REG_BUCK1_CONF2		0x5A
+#define PV88080BA_REG_BUCK1_CONF5		0x5D
+#define PV88080BA_REG_BUCK2_CONF0		0x2D
+#define PV88080BA_REG_BUCK2_CONF1		0x2F
+#define PV88080BA_REG_BUCK2_CONF2		0x63
+#define PV88080BA_REG_BUCK2_CONF5		0x66
+#define PV88080BA_REG_BUCK3_CONF0		0x30
+#define PV88080BA_REG_BUCK3_CONF1		0x32
+#define PV88080BA_REG_BUCK3_CONF2		0x6C
+#define PV88080BA_REG_BUCK3_CONF5		0x6F
+
+/* PV88080_REG_EVENT_A (addr=0x04) */
+#define PV88080_E_VDD_FLT				0x01
+#define PV88080_E_OVER_TEMP				0x02
+#define PV88080_E_SEQ_RDY				0x04
+#define PV88080_E_EXT_OT				0x08
+
+/* PV88080_REG_MASK_A (addr=0x09) */
+#define PV88080_M_VDD_FLT				0x01
+#define PV88080_M_OVER_TEMP				0x02
+#define PV88080_M_SEQ_RDY				0x04
+#define PV88080_M_EXT_OT				0x08
+
+/* PV88080_REG_EVENT_B (addr=0x05) */
+#define PV88080_E_HVBUCK_OV				0x01
+#define PV88080_E_HVBUCK_UV				0x02
+#define PV88080_E_HVBUCK_SCP			0x04
+#define PV88080_E_BUCK1_SCP				0x08
+#define PV88080_E_BUCK2_SCP				0x10
+#define PV88080_E_BUCK3_SCP				0x20
+
+/* PV88080_REG_MASK_B (addr=0x0A) */
+#define PV88080_M_HVBUCK_OV				0x01
+#define PV88080_M_HVBUCK_UV				0x02
+#define PV88080_M_HVBUCK_SCP			0x04
+#define PV88080_M_BUCK1_SCP				0x08
+#define PV88080_M_BUCK2_SCP				0x10
+#define PV88080_M_BUCK3_SCP				0x20
+
+/* PV88080_REG_EVENT_C (addr=0x06) */
+#define PV88080_E_GPIO_FLAG0			0x01
+#define PV88080_E_GPIO_FLAG1			0x02
+#define PV88080_E_BUCK1_DROP_TIMEOUT	0x08
+#define PV88080_E_BUCK2_DROP_TIMEOUT	0x10
+#define PV88080_E_BUCk3_DROP_TIMEOUT	0x20
+
+/* PV88080_REG_MASK_C (addr=0x0B) */
+#define PV88080_M_GPIO_FLAG0			0x01
+#define PV88080_M_GPIO_FLAG1			0x02
+#define PV88080_M_BUCK1_DROP_TIMEOUT	0x08
+#define PV88080_M_BUCK2_DROP_TIMEOUT	0x10
+#define PV88080_M_BUCk3_DROP_TIMEOUT	0x20
+
+/* PV88080xx_REG_GPIO_INPUT (addr=0x18|0x17) */
+#define PV88080_GPIO_INPUT_MASK			0x01
+
+/* PV88080xx_REG_GPIO_GPIO0 (addr=0x1A|0x19) */
+#define PV88080_GPIO_DIRECTION_MASK		0x01
+#define PV88080_GPIO_OUTPUT_MASK		0x0C
+#define PV88080_GPIO_OUTPUT_EN			0x04
+#define PV88080_GPIO_OUTPUT_DIS			0x08
+
+/* PV88080_REG_BUCK1_CONF0 (addr=0x27|0x2A) */
+#define PV88080_BUCK1_EN				0x80
+#define PV88080_VBUCK1_MASK				0x7F
+
+/* PV88080_REG_BUCK2_CONF0 (addr=0x29|0x2D) */
+#define PV88080_BUCK2_EN				0x80
+#define PV88080_VBUCK2_MASK				0x7F
+
+/* PV88080_REG_BUCK3_CONF0 (addr=0x2B|0x30) */
+#define PV88080_BUCK3_EN				0x80
+#define PV88080_VBUCK3_MASK				0x7F
+
+/* PV88080_REG_BUCK1_CONF1 (addr=0x28|0x2C) */
+#define PV88080_BUCK1_ILIM_SHIFT		2
+#define PV88080_BUCK1_ILIM_MASK			0x0C
+#define PV88080_BUCK1_MODE_MASK			0x03
+
+/* PV88080_REG_BUCK2_CONF1 (addr=0x2A|0x2F) */
+#define PV88080_BUCK2_ILIM_SHIFT		2
+#define PV88080_BUCK2_ILIM_MASK			0x0C
+#define PV88080_BUCK2_MODE_MASK			0x03
+
+/* PV88080_REG_BUCK3_CONF1 (addr=0x2C|0x32) */
+#define PV88080_BUCK3_ILIM_SHIFT		2
+#define PV88080_BUCK3_ILIM_MASK			0x0C
+#define PV88080_BUCK3_MODE_MASK			0x03
+
+#define PV88080_BUCK_MODE_SLEEP			0x00
+#define PV88080_BUCK_MODE_AUTO			0x01
+#define PV88080_BUCK_MODE_SYNC			0x02
+
+/* PV88080_REG_HVBUCK_CONF1 (addr=0x2D|0x33) */
+#define PV88080_VHVBUCK_MASK			0xFF
+
+/* PV88080_REG_HVBUCK_CONF1 (addr=0x2E|0x34) */
+#define PV88080_HVBUCK_EN				0x01
+
+/* PV88080_REG_BUCK2_CONF2 (addr=0x61|0x63) */
+/* PV88080_REG_BUCK3_CONF2 (addr=0x69|0x6C) */
+#define PV88080_BUCK_VDAC_RANGE_SHIFT	7
+#define PV88080_BUCK_VDAC_RANGE_MASK	0x01
+
+#define PV88080_BUCK_VDAC_RANGE_1		0x00
+#define PV88080_BUCK_VDAC_RANGE_2		0x01
+
+/* PV88080_REG_BUCK2_CONF5 (addr=0x64|0x66) */
+/* PV88080_REG_BUCK3_CONF5 (addr=0x6C|0x6F) */
+#define PV88080_BUCK_VRANGE_GAIN_SHIFT	0
+#define PV88080_BUCK_VRANGE_GAIN_MASK	0x01
+
+#define PV88080_BUCK_VRANGE_GAIN_1		0x00
+#define PV88080_BUCK_VRANGE_GAIN_2		0x01
+
+#define PV88080_MAX_REGULATORS			4
+
+enum pv88080_types {
+	TYPE_PV88080_AA,
+	TYPE_PV88080_BA,
+};
+
+/* Interrupts */
+enum pv88080_aa_irqs {
+	PV88080_AA_IRQ_VDD_FLT,
+	PV88080_AA_IRQ_OVER_TEMP,
+	PV88080_AA_IRQ_SEQ_RDY,
+	PV88080_AA_IRQ_HVBUCK_OV,
+	PV88080_AA_IRQ_HVBUCK_UV,
+	PV88080_AA_IRQ_HVBUCK_SCP,
+	PV88080_AA_IRQ_BUCK1_SCP,
+	PV88080_AA_IRQ_BUCK2_SCP,
+	PV88080_AA_IRQ_BUCK3_SCP,
+	PV88080_AA_IRQ_GPIO_FLAG0,
+	PV88080_AA_IRQ_GPIO_FLAG1,
+};
+
+enum pv88080_ba_irqs {
+	PV88080_BA_IRQ_VDD_FLT,
+	PV88080_BA_IRQ_OVER_TEMP,
+	PV88080_BA_IRQ_SEQ_RDY,
+	PV88080_BA_IRQ_EXT_OT,
+	PV88080_BA_IRQ_HVBUCK_OV,
+	PV88080_BA_IRQ_HVBUCK_UV,
+	PV88080_BA_IRQ_HVBUCK_SCP,
+	PV88080_BA_IRQ_BUCK1_SCP,
+	PV88080_BA_IRQ_BUCK2_SCP,
+	PV88080_BA_IRQ_BUCK3_SCP,
+	PV88080_BA_IRQ_GPIO_FLAG0,
+	PV88080_BA_IRQ_GPIO_FLAG1,
+	PV88080_BA_IRQ_BUCK1_DROP_TIMEOUT,
+	PV88080_BA_IRQ_BUCK2_DROP_TIMEOUT,
+	PB88080_BA_IRQ_BUCK3_DROP_TIMEOUT,
+};
+
+struct pv88080 {
+	struct device *dev;
+	struct regmap *regmap;
+	unsigned long type;
+
+	/* IRQ Data */
+	int irq;
+	int irq_base;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+struct pv88080_pdata {
+	int (*init)(struct pv88080 *pv88080);
+	int irq_base;
+	int gpio_base;
+	struct regulator_init_data *regulators[PV88080_MAX_REGULATORS];
+};
+
+int pv88080_device_init(struct pv88080 *chip, unsigned int irq);
+int pv88080_device_exit(struct pv88080 *chip);
+
+#endif	/* __PV88080_H__ */
+
-- 
end-of-patch for PATCH V2


^ permalink raw reply related

* [PATCH V2 3/4] regulator: pv88080: Update Regulator driver for MFD support
From: Eric Jeong @ 2016-10-27  1:03 UTC (permalink / raw)
  To: LINUX-KERNEL, Liam Girdwood, Mark Brown
  Cc: Alexandre Courbot, DEVICETREE, LINUX-GPIO, Lee Jones,
	Linus Walleij, Mark Rutland, Rob Herring, Support Opensource
In-Reply-To: <cover.1477530195.git.eric.jeong@diasemi.com>


From: Eric Jeong <eric.jeong.opensource@diasemi.com>

This change convert from using struct i2c_clinet 
to using struct platform_device for MFD structure.
And, the declaration of of_device_id and regmap_config
are also move to MFD driver.

The configuration for MASK registers is moved 
to MFD core.

Kconfig is updated to reflect support for PV88080 regulator.

Signed-off-by: Eric Jeong <eric.jeong.opensource@diasemi.com>

---
This patch applies against linux-next and next-20161026

Hi,

The existing PV88080 regulstor driver is updated to support
MFD structure by adding GPIO function.
Most of changes are related with MFD structure support.

Change since PATCH V1
 - Patch separated from PATCH V1

Regards,
Eric Jeong, Dialog Semiconductor Ltd.


 drivers/regulator/Kconfig             |    5 +-
 drivers/regulator/pv88080-regulator.c |  202 +++++++++++++--------------------
 drivers/regulator/pv88080-regulator.h |  118 -------------------
 3 files changed, 81 insertions(+), 244 deletions(-)
 delete mode 100644 drivers/regulator/pv88080-regulator.h

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7cc..217d568 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -576,9 +576,8 @@ config REGULATOR_PV88060
 	  PV88060
 
 config REGULATOR_PV88080
-	tristate "Powerventure Semiconductor PV88080 regulator"
-	depends on I2C
-	select REGMAP_I2C
+	bool "Powerventure Semiconductor PV88080 regulator"
+	depends on MFD_PV88080
 	help
 	  Say y here to support the buck convertors on PV88080
 
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 954a20e..6dfccee 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -14,8 +14,8 @@
  */
 
 #include <linux/err.h>
-#include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -25,9 +25,8 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/regulator/of_regulator.h>
-#include "pv88080-regulator.h"
 
-#define PV88080_MAX_REGULATORS	4
+#include <linux/mfd/pv88080.h>
 
 /* PV88080 REGULATOR IDs */
 enum {
@@ -38,11 +37,6 @@ enum {
 	PV88080_ID_HVBUCK,
 };
 
-enum pv88080_types {
-	TYPE_PV88080_AA,
-	TYPE_PV88080_BA,
-};
-
 struct pv88080_regulator {
 	struct regulator_desc desc;
 	/* Current limiting */
@@ -55,14 +49,6 @@ struct pv88080_regulator {
 	unsigned int conf5;
 };
 
-struct pv88080 {
-	struct device *dev;
-	struct regmap *regmap;
-	struct regulator_dev *rdev[PV88080_MAX_REGULATORS];
-	unsigned long type;
-	const struct pv88080_compatible_regmap *regmap_config;
-};
-
 struct pv88080_buck_voltage {
 	int min_uV;
 	int max_uV;
@@ -93,11 +79,14 @@ struct pv88080_compatible_regmap {
 	int hvbuck_vsel_mask;
 };
 
-static const struct regmap_config pv88080_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
+struct pv88080_regulators {
+	int	virq;
+	struct pv88080 *pv88080;
+	struct regulator_dev *rdev[PV88080_MAX_REGULATORS];
+	const struct pv88080_compatible_regmap *regmap_config;
 };
 
+
 /* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
  * Entry indexes corresponds to register values.
  */
@@ -211,16 +200,6 @@ struct pv88080_compatible_regmap {
 	.hvbuck_vsel_mask		  = PV88080_VHVBUCK_MASK,
 };
 
-#ifdef CONFIG_OF
-static const struct of_device_id pv88080_dt_ids[] = {
-	{ .compatible = "pvs,pv88080",    .data = (void *)TYPE_PV88080_AA },
-	{ .compatible = "pvs,pv88080-aa", .data = (void *)TYPE_PV88080_AA },
-	{ .compatible = "pvs,pv88080-ba", .data = (void *)TYPE_PV88080_BA },
-	{},
-};
-MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
-#endif
-
 static unsigned int pv88080_buck_get_mode(struct regulator_dev *rdev)
 {
 	struct pv88080_regulator *info = rdev_get_drvdata(rdev);
@@ -374,7 +353,8 @@ static int pv88080_get_current_limit(struct regulator_dev *rdev)
 
 static irqreturn_t pv88080_irq_handler(int irq, void *data)
 {
-	struct pv88080 *chip = data;
+	struct pv88080_regulators *regulators = data;
+	struct pv88080 *chip = regulators->pv88080;
 	int i, reg_val, err, ret = IRQ_NONE;
 
 	err = regmap_read(chip->regmap, PV88080_REG_EVENT_A, &reg_val);
@@ -383,8 +363,9 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data)
 
 	if (reg_val & PV88080_E_VDD_FLT) {
 		for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
-			if (chip->rdev[i] != NULL) {
-				regulator_notifier_call_chain(chip->rdev[i],
+			if (regulators->rdev[i] != NULL) {
+				regulator_notifier_call_chain(
+					regulators->rdev[i],
 					REGULATOR_EVENT_UNDER_VOLTAGE,
 					NULL);
 			}
@@ -400,8 +381,9 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data)
 
 	if (reg_val & PV88080_E_OVER_TEMP) {
 		for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
-			if (chip->rdev[i] != NULL) {
-				regulator_notifier_call_chain(chip->rdev[i],
+			if (regulators->rdev[i] != NULL) {
+				regulator_notifier_call_chain(
+					regulators->rdev[i],
 					REGULATOR_EVENT_OVER_TEMP,
 					NULL);
 			}
@@ -425,101 +407,67 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data)
 /*
  * I2C driver interface functions
  */
-static int pv88080_i2c_probe(struct i2c_client *i2c,
-		const struct i2c_device_id *id)
+static int pv88080_regulator_probe(struct platform_device *pdev)
 {
-	struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
-	struct pv88080 *chip;
+	struct pv88080 *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pv88080_pdata *pdata = dev_get_platdata(chip->dev);
+	struct pv88080_regulators *regulators;
 	const struct pv88080_compatible_regmap *regmap_config;
-	const struct of_device_id *match;
 	struct regulator_config config = { };
-	int i, error, ret;
+	int i, ret, irq;
 	unsigned int conf2, conf5;
 
-	chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88080), GFP_KERNEL);
-	if (!chip)
+	regulators = devm_kzalloc(&pdev->dev,
+			sizeof(struct pv88080_regulators), GFP_KERNEL);
+	if (!regulators)
 		return -ENOMEM;
 
-	chip->dev = &i2c->dev;
-	chip->regmap = devm_regmap_init_i2c(i2c, &pv88080_regmap_config);
-	if (IS_ERR(chip->regmap)) {
-		error = PTR_ERR(chip->regmap);
-		dev_err(chip->dev, "Failed to allocate register map: %d\n",
-			error);
-		return error;
-	}
+	platform_set_drvdata(pdev, regulators);
 
-	if (i2c->dev.of_node) {
-		match = of_match_node(pv88080_dt_ids, i2c->dev.of_node);
-		if (!match) {
-			dev_err(chip->dev, "Failed to get of_match_node\n");
-			return -EINVAL;
-		}
-		chip->type = (unsigned long)match->data;
-	} else {
-		chip->type = id->driver_data;
+	irq = platform_get_irq_byname(pdev, "regulator-irq");
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Failed to get IRQ.\n");
+		return irq;
 	}
 
-	i2c_set_clientdata(i2c, chip);
-
-	if (i2c->irq != 0) {
-		ret = regmap_write(chip->regmap, PV88080_REG_MASK_A, 0xFF);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to mask A reg: %d\n", ret);
-			return ret;
-		}
-		ret = regmap_write(chip->regmap, PV88080_REG_MASK_B, 0xFF);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to mask B reg: %d\n", ret);
-			return ret;
-		}
-		ret = regmap_write(chip->regmap, PV88080_REG_MASK_C, 0xFF);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to mask C reg: %d\n", ret);
-			return ret;
-		}
-
-		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
-					pv88080_irq_handler,
-					IRQF_TRIGGER_LOW|IRQF_ONESHOT,
-					"pv88080", chip);
-		if (ret != 0) {
-			dev_err(chip->dev, "Failed to request IRQ: %d\n",
-				i2c->irq);
+	regulators->virq = regmap_irq_get_virq(chip->irq_data, irq);
+	if (regulators->virq >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+				regulators->virq, NULL,
+				pv88080_irq_handler,
+				IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+				"regulator-irq", regulators);
+		if (ret) {
+			dev_err(chip->dev, "Failed to request IRQ: %d\n", irq);
 			return ret;
 		}
+	}
 
-		ret = regmap_update_bits(chip->regmap, PV88080_REG_MASK_A,
-			PV88080_M_VDD_FLT | PV88080_M_OVER_TEMP, 0);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to update mask reg: %d\n", ret);
-			return ret;
-		}
-	} else {
-		dev_warn(chip->dev, "No IRQ configured\n");
+	ret = regmap_update_bits(chip->regmap, PV88080_REG_MASK_A,
+		PV88080_M_VDD_FLT | PV88080_M_OVER_TEMP, 0);
+	if (ret < 0) {
+		dev_err(chip->dev,
+			"Failed to update mask reg: %d\n", ret);
+		return ret;
 	}
 
 	switch (chip->type) {
 	case TYPE_PV88080_AA:
-		chip->regmap_config = &pv88080_aa_regs;
+		regulators->regmap_config = &pv88080_aa_regs;
 		break;
 	case TYPE_PV88080_BA:
-		chip->regmap_config = &pv88080_ba_regs;
+		regulators->regmap_config = &pv88080_ba_regs;
 		break;
 	}
 
-	regmap_config = chip->regmap_config;
+	regmap_config = regulators->regmap_config;
 	config.dev = chip->dev;
 	config.regmap = chip->regmap;
 
 	/* Registeration for BUCK1, 2, 3 */
 	for (i = 0; i < PV88080_MAX_REGULATORS-1; i++) {
-		if (init_data)
-			config.init_data = &init_data[i];
+		if (pdata && pdata->regulators)
+			config.init_data = pdata->regulators[i];
 
 		pv88080_regulator_info[i].limit_reg
 			= regmap_config->buck_regmap[i].buck_limit_reg;
@@ -564,12 +512,12 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
 			/(pv88080_regulator_info[i].desc.uV_step) + 1;
 
 		config.driver_data = (void *)&pv88080_regulator_info[i];
-		chip->rdev[i] = devm_regulator_register(chip->dev,
+		regulators->rdev[i] = devm_regulator_register(chip->dev,
 			&pv88080_regulator_info[i].desc, &config);
-		if (IS_ERR(chip->rdev[i])) {
+		if (IS_ERR(regulators->rdev[i])) {
 			dev_err(chip->dev,
 				"Failed to register PV88080 regulator\n");
-			return PTR_ERR(chip->rdev[i]);
+			return PTR_ERR(regulators->rdev[i]);
 		}
 	}
 
@@ -583,39 +531,47 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
 		= regmap_config->hvbuck_vsel_mask;
 
 	/* Registeration for HVBUCK */
-	if (init_data)
-		config.init_data = &init_data[PV88080_ID_HVBUCK];
+	if (pdata && pdata->regulators)
+		config.init_data = pdata->regulators[PV88080_ID_HVBUCK];
 
 	config.driver_data = (void *)&pv88080_regulator_info[PV88080_ID_HVBUCK];
-	chip->rdev[PV88080_ID_HVBUCK] = devm_regulator_register(chip->dev,
+	regulators->rdev[PV88080_ID_HVBUCK] = devm_regulator_register(chip->dev,
 		&pv88080_regulator_info[PV88080_ID_HVBUCK].desc, &config);
-	if (IS_ERR(chip->rdev[PV88080_ID_HVBUCK])) {
+	if (IS_ERR(regulators->rdev[PV88080_ID_HVBUCK])) {
 		dev_err(chip->dev, "Failed to register PV88080 regulator\n");
-		return PTR_ERR(chip->rdev[PV88080_ID_HVBUCK]);
+		return PTR_ERR(regulators->rdev[PV88080_ID_HVBUCK]);
 	}
 
 	return 0;
 }
 
-static const struct i2c_device_id pv88080_i2c_id[] = {
-	{ "pv88080",    TYPE_PV88080_AA },
-	{ "pv88080-aa", TYPE_PV88080_AA },
-	{ "pv88080-ba", TYPE_PV88080_BA },
-	{},
+static const struct platform_device_id pv88080_regulator_id_table[] = {
+	{ "pv88080-regulator", },
+	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
+MODULE_DEVICE_TABLE(platform, pv88080_regulator_id_table);
 
-static struct i2c_driver pv88080_regulator_driver = {
+static struct platform_driver pv88080_regulator_driver = {
 	.driver = {
-		.name = "pv88080",
-		.of_match_table = of_match_ptr(pv88080_dt_ids),
+		.name = "pv88080-regulator",
 	},
-	.probe = pv88080_i2c_probe,
-	.id_table = pv88080_i2c_id,
+	.probe = pv88080_regulator_probe,
+	.id_table = pv88080_regulator_id_table,
 };
 
-module_i2c_driver(pv88080_regulator_driver);
+static int __init pv88080_regulator_init(void)
+{
+	return platform_driver_register(&pv88080_regulator_driver);
+}
+subsys_initcall(pv88080_regulator_init);
+
+static void __exit pv88080_regulator_exit(void)
+{
+	platform_driver_unregister(&pv88080_regulator_driver);
+}
+module_exit(pv88080_regulator_exit);
 
-MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
+MODULE_AUTHOR("Eric Jeong <eric.jeong.opensource@diasemi.com>");
 MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88080");
 MODULE_LICENSE("GPL");
+
diff --git a/drivers/regulator/pv88080-regulator.h b/drivers/regulator/pv88080-regulator.h
deleted file mode 100644
index ae25ff3..0000000
--- a/drivers/regulator/pv88080-regulator.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * pv88080-regulator.h - Regulator definitions for PV88080
- * Copyright (C) 2016 Powerventure Semiconductor Ltd.
- *
- * 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
- * GNU General Public License for more details.
- */
-
-#ifndef __PV88080_REGISTERS_H__
-#define __PV88080_REGISTERS_H__
-
-/* System Control and Event Registers */
-#define	PV88080_REG_EVENT_A				0x04
-#define	PV88080_REG_MASK_A				0x09
-#define	PV88080_REG_MASK_B				0x0A
-#define	PV88080_REG_MASK_C				0x0B
-
-/* Regulator Registers - rev. AA */
-#define PV88080AA_REG_HVBUCK_CONF1		0x2D
-#define PV88080AA_REG_HVBUCK_CONF2		0x2E
-#define	PV88080AA_REG_BUCK1_CONF0		0x27
-#define	PV88080AA_REG_BUCK1_CONF1		0x28
-#define	PV88080AA_REG_BUCK1_CONF2		0x59
-#define	PV88080AA_REG_BUCK1_CONF5		0x5C
-#define	PV88080AA_REG_BUCK2_CONF0		0x29
-#define	PV88080AA_REG_BUCK2_CONF1		0x2A
-#define	PV88080AA_REG_BUCK2_CONF2		0x61
-#define	PV88080AA_REG_BUCK2_CONF5		0x64
-#define	PV88080AA_REG_BUCK3_CONF0		0x2B
-#define	PV88080AA_REG_BUCK3_CONF1		0x2C
-#define	PV88080AA_REG_BUCK3_CONF2		0x69
-#define	PV88080AA_REG_BUCK3_CONF5		0x6C
-
-/* Regulator Registers - rev. BA */
-#define	PV88080BA_REG_HVBUCK_CONF1		0x33
-#define	PV88080BA_REG_HVBUCK_CONF2		0x34
-#define	PV88080BA_REG_BUCK1_CONF0		0x2A
-#define	PV88080BA_REG_BUCK1_CONF1		0x2C
-#define	PV88080BA_REG_BUCK1_CONF2		0x5A
-#define	PV88080BA_REG_BUCK1_CONF5		0x5D
-#define	PV88080BA_REG_BUCK2_CONF0		0x2D
-#define	PV88080BA_REG_BUCK2_CONF1		0x2F
-#define	PV88080BA_REG_BUCK2_CONF2		0x63
-#define	PV88080BA_REG_BUCK2_CONF5		0x66
-#define	PV88080BA_REG_BUCK3_CONF0		0x30
-#define	PV88080BA_REG_BUCK3_CONF1		0x32
-#define	PV88080BA_REG_BUCK3_CONF2		0x6C
-#define	PV88080BA_REG_BUCK3_CONF5		0x6F
-
-/* PV88080_REG_EVENT_A (addr=0x04) */
-#define	PV88080_E_VDD_FLT				0x01
-#define	PV88080_E_OVER_TEMP				0x02
-
-/* PV88080_REG_MASK_A (addr=0x09) */
-#define	PV88080_M_VDD_FLT				0x01
-#define	PV88080_M_OVER_TEMP				0x02
-
-/* PV88080_REG_BUCK1_CONF0 (addr=0x27|0x2A) */
-#define	PV88080_BUCK1_EN				0x80
-#define PV88080_VBUCK1_MASK				0x7F
-
-/* PV88080_REG_BUCK2_CONF0 (addr=0x29|0x2D) */
-#define	PV88080_BUCK2_EN				0x80
-#define PV88080_VBUCK2_MASK				0x7F
-
-/* PV88080_REG_BUCK3_CONF0 (addr=0x2B|0x30) */
-#define	PV88080_BUCK3_EN				0x80
-#define PV88080_VBUCK3_MASK				0x7F
-
-/* PV88080_REG_BUCK1_CONF1 (addr=0x28|0x2C) */
-#define PV88080_BUCK1_ILIM_SHIFT		2
-#define PV88080_BUCK1_ILIM_MASK			0x0C
-#define PV88080_BUCK1_MODE_MASK			0x03
-
-/* PV88080_REG_BUCK2_CONF1 (addr=0x2A|0x2F) */
-#define PV88080_BUCK2_ILIM_SHIFT		2
-#define PV88080_BUCK2_ILIM_MASK			0x0C
-#define PV88080_BUCK2_MODE_MASK			0x03
-
-/* PV88080_REG_BUCK3_CONF1 (addr=0x2C|0x32) */
-#define PV88080_BUCK3_ILIM_SHIFT		2
-#define PV88080_BUCK3_ILIM_MASK			0x0C
-#define PV88080_BUCK3_MODE_MASK			0x03
-
-#define	PV88080_BUCK_MODE_SLEEP			0x00
-#define	PV88080_BUCK_MODE_AUTO			0x01
-#define	PV88080_BUCK_MODE_SYNC			0x02
-
-/* PV88080_REG_HVBUCK_CONF1 (addr=0x2D|0x33) */
-#define PV88080_VHVBUCK_MASK			0xFF
-
-/* PV88080_REG_HVBUCK_CONF1 (addr=0x2E|0x34) */
-#define PV88080_HVBUCK_EN				0x01
-
-/* PV88080_REG_BUCK2_CONF2 (addr=0x61|0x63) */
-/* PV88080_REG_BUCK3_CONF2 (addr=0x69|0x6C) */
-#define PV88080_BUCK_VDAC_RANGE_SHIFT	7
-#define PV88080_BUCK_VDAC_RANGE_MASK	0x01
-
-#define PV88080_BUCK_VDAC_RANGE_1		0x00
-#define PV88080_BUCK_VDAC_RANGE_2		0x01
-
-/* PV88080_REG_BUCK2_CONF5 (addr=0x64|0x66) */
-/* PV88080_REG_BUCK3_CONF5 (addr=0x6C|0x6F) */
-#define PV88080_BUCK_VRANGE_GAIN_SHIFT	0
-#define PV88080_BUCK_VRANGE_GAIN_MASK	0x01
-
-#define PV88080_BUCK_VRANGE_GAIN_1		0x00
-#define PV88080_BUCK_VRANGE_GAIN_2		0x01
-
-#endif	/* __PV88080_REGISTERS_H__ */
-- 
end-of-patch for PATCH V2


^ permalink raw reply related

* [PATCH V2 4/4] gpio: pv88080: Add GPIO function support
From: Eric Jeong @ 2016-10-27  1:03 UTC (permalink / raw)
  To: Alexandre Courbot, LINUX-GPIO, LINUX-KERNEL, Linus Walleij
  Cc: DEVICETREE, Lee Jones, Liam Girdwood, Mark Brown, Mark Rutland,
	Rob Herring, Support Opensource
In-Reply-To: <cover.1477530195.git.eric.jeong@diasemi.com>


From: Eric Jeong <eric.jeong.opensource@diasemi.com>

This patch adds support for PV88080 PMIC GPIOs.
PV88080 has two configurable GPIOs.

Kconfig and Makefile are updated to reflect support
for PV88080 PMIC GPIO. 

Signed-off-by: Eric Jeong <eric.jeong.opensource@diasemi.com>

---
This patch applies against linux-next and next-20161026

Hi,

Change since PATCH V1
 - Patch separated from PATCH V1

Regards,
Eric Jeong, Dialog Semiconductor Ltd.


 drivers/gpio/Kconfig        |   11 +++
 drivers/gpio/Makefile       |    1 +
 drivers/gpio/gpio-pv88080.c |  195 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 207 insertions(+)
 create mode 100644 drivers/gpio/gpio-pv88080.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a9a1c8a..c43e89c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -949,6 +949,17 @@ config GPIO_PALMAS
 	  Select this option to enable GPIO driver for the TI PALMAS
 	  series chip family.
 
+config GPIO_PV88080
+	bool "Powerventure Semiconductor PV88080 GPIO"
+	depends on MFD_PV88080
+	help
+	  Support for GPIO pins on PV88080 PMIC.
+
+	  Say yes here to enable the GPIO driver for the PV88080 chip.
+
+	  The Powerventure PMIC chip has 2 GPIO pins that can be
+	  controlled by this driver.
+
 config GPIO_RC5T583
 	bool "RICOH RC5T583 GPIO"
 	depends on MFD_RC5T583
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8043a95..2a2311e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
 obj-$(CONFIG_GPIO_PISOSR)	+= gpio-pisosr.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_GPIO_PV88080)	+= gpio-pv88080.o
 obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RC5T583)	+= gpio-rc5t583.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
diff --git a/drivers/gpio/gpio-pv88080.c b/drivers/gpio/gpio-pv88080.c
new file mode 100644
index 0000000..0e2eb49
--- /dev/null
+++ b/drivers/gpio/gpio-pv88080.c
@@ -0,0 +1,195 @@
+/*
+ * gpio-pv88080.c - GPIO device driver for PV88080
+ * Copyright (C) 2016  Powerventure Semiconductor Ltd.
+ *
+ * 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
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/pv88080.h>
+
+#define DEFAULT_PIN_NUMBER		2
+
+#define PV88080_PORT_DIRECTION_INPUT	0
+#define PV88080_PORT_DIRECTION_OUTPUT	1
+
+struct pv88080_gpio {
+	struct pv88080 *chip;
+	struct gpio_chip gpio_chip;
+	unsigned int input_reg;
+	unsigned int gpio_base_reg;
+};
+
+static int pv88080_gpio_get_direction(struct gpio_chip *gc,
+				unsigned int offset)
+{
+	struct pv88080_gpio *priv = gpiochip_get_data(gc);
+	struct pv88080 *chip = priv->chip;
+	unsigned int reg;
+	int ret;
+
+	ret = regmap_read(chip->regmap, priv->gpio_base_reg + offset, &reg);
+	if (ret)
+		return ret;
+
+	reg = reg & PV88080_GPIO_DIRECTION_MASK;
+
+	return !reg;
+}
+
+static int pv88080_gpio_direction_input(struct gpio_chip *gc,
+				unsigned int offset)
+{
+	struct pv88080_gpio *priv = gpiochip_get_data(gc);
+	struct pv88080 *chip = priv->chip;
+	int ret;
+
+	/* Set the initial value */
+	ret = regmap_update_bits(chip->regmap, priv->gpio_base_reg + offset,
+					PV88080_GPIO_OUTPUT_MASK, 0);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(chip->regmap, priv->gpio_base_reg + offset,
+				PV88080_GPIO_DIRECTION_MASK, 0);
+}
+
+static int pv88080_gpio_direction_output(struct gpio_chip *gc,
+				unsigned int offset, int value)
+{
+	struct pv88080_gpio *priv = gpiochip_get_data(gc);
+	struct pv88080 *chip = priv->chip;
+	int ret;
+
+	ret = regmap_update_bits(chip->regmap, priv->gpio_base_reg + offset,
+			PV88080_GPIO_DIRECTION_MASK,
+			PV88080_GPIO_DIRECTION_MASK);
+
+	return ret;
+}
+
+static int pv88080_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+	struct pv88080_gpio *priv = gpiochip_get_data(gc);
+	struct pv88080 *chip = priv->chip;
+	unsigned int reg = 0, direction;
+	int ret;
+
+	ret = regmap_read(chip->regmap, priv->gpio_base_reg + offset, &reg);
+	if (ret)
+		return ret;
+
+	direction = (reg & PV88080_GPIO_DIRECTION_MASK);
+	if (direction == PV88080_PORT_DIRECTION_OUTPUT) {
+		if (reg & PV88080_GPIO_OUTPUT_EN)
+			return 1;
+		ret = 0;
+	} else {
+		ret = regmap_read(chip->regmap, priv->input_reg, &reg);
+		if (ret < 0)
+			return ret;
+		ret = (reg & (PV88080_GPIO_INPUT_MASK << offset)) >> offset;
+	}
+
+	return ret;
+}
+
+static void pv88080_gpio_set(struct gpio_chip *gc, unsigned int offset,
+				int value)
+{
+	struct pv88080_gpio *priv = gpiochip_get_data(gc);
+	struct pv88080 *chip = priv->chip;
+
+	if (value)
+		regmap_update_bits(chip->regmap, priv->gpio_base_reg + offset,
+				PV88080_GPIO_OUTPUT_MASK,
+				PV88080_GPIO_OUTPUT_EN);
+	else
+		regmap_update_bits(chip->regmap, priv->gpio_base_reg + offset,
+				PV88080_GPIO_OUTPUT_MASK,
+				PV88080_GPIO_OUTPUT_DIS);
+}
+
+static const struct gpio_chip template_gpio = {
+	.label = "pv88080-gpio",
+	.owner = THIS_MODULE,
+	.get_direction = pv88080_gpio_get_direction,
+	.direction_input = pv88080_gpio_direction_input,
+	.direction_output = pv88080_gpio_direction_output,
+	.get = pv88080_gpio_get,
+	.set = pv88080_gpio_set,
+	.base = -1,
+	.ngpio = DEFAULT_PIN_NUMBER,
+};
+
+static int pv88080_gpio_probe(struct platform_device *pdev)
+{
+	struct pv88080 *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pv88080_pdata *pdata = dev_get_platdata(chip->dev);
+	struct pv88080_gpio *priv;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev,
+			sizeof(struct pv88080_gpio), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->chip = chip;
+	priv->gpio_chip = template_gpio;
+	priv->gpio_chip.parent = chip->dev;
+	if (pdata && pdata->gpio_base)
+		priv->gpio_chip.base = pdata->gpio_base;
+
+	switch (chip->type) {
+	case TYPE_PV88080_AA:
+		priv->input_reg = PV88080AA_REG_GPIO_INPUT;
+		priv->gpio_base_reg = PV88080AA_REG_GPIO_GPIO0;
+		break;
+	case TYPE_PV88080_BA:
+		priv->input_reg = PV88080BA_REG_GPIO_INPUT;
+		priv->gpio_base_reg = PV88080BA_REG_GPIO_GPIO0;
+		break;
+	}
+
+	ret = devm_gpiochip_add_data(&pdev->dev, &priv->gpio_chip, priv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to register gpiochip\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static const struct platform_device_id pv88080_gpio_id_table[] = {
+	{ "pv88080-gpio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, pv88080_gpio_id_table);
+
+static struct platform_driver pv88080_gpio_driver = {
+	.driver = {
+		.name = "pv88080-gpio",
+	},
+	.probe = pv88080_gpio_probe,
+	.id_table = pv88080_gpio_id_table,
+};
+module_platform_driver(pv88080_gpio_driver);
+
+MODULE_AUTHOR("Eric Jeong <eric.jeong.opensource@diasemi.com>");
+MODULE_DESCRIPTION("GPIO device driver for Powerventure PV88080");
+MODULE_LICENSE("GPL");
+
-- 
end-of-patch for PATCH V2


^ permalink raw reply related

* [PATCH V2 0/4]  pv88080: PV88080 driver submission
From: Eric Jeong @ 2016-10-27  1:03 UTC (permalink / raw)
  To: Alexandre Courbot, DEVICETREE, LINUX-GPIO, LINUX-KERNEL,
	Lee Jones, Liam Girdwood, Linus Walleij, Mark Brown, Mark Rutland,
	Rob Herring
  Cc: Support Opensource

From: Eric Jeong <eric.jeong.opensource@diasemi.com>

This patch set adds support for the PV88080 PMIC.
And, this patch is done as part of the existing PV88080 Regulator
driver by expanding the driver for GPIO function support.

In this patch set the following is provided:

[PATCH V2 1/4] Move binding document
[PATCH V2 2/4] MFD core support
[PATCH V2 3/4] Update regulator driver for MFD support
[PATCH V2 4/4] Add GPIO function support

This patch applies against linux-next and next-20161026

Thank you,
Eric Jeong, Dialog Semiconductor Ltd.

Eric Jeong (4):
  Documentation: pv88080: Move binding document
  mfd: pv88080: MFD core support
  regulator: pv88080: Update Regulator driver for MFD support
  gpio: pv88080: Add GPIO function support

 Documentation/devicetree/bindings/mfd/pv88080.txt  |   63 +++++
 .../devicetree/bindings/regulator/pv88080.txt      |   62 -----
 drivers/gpio/Kconfig                               |   11 +
 drivers/gpio/Makefile                              |    1 +
 drivers/gpio/gpio-pv88080.c                        |  195 ++++++++++++++
 drivers/mfd/Kconfig                                |   12 +
 drivers/mfd/Makefile                               |    2 +
 drivers/mfd/pv88080-core.c                         |  270 ++++++++++++++++++++
 drivers/mfd/pv88080-i2c.c                          |   99 +++++++
 drivers/regulator/Kconfig                          |    5 +-
 drivers/regulator/pv88080-regulator.c              |  202 ++++++---------
 drivers/regulator/pv88080-regulator.h              |  118 ---------
 include/linux/mfd/pv88080.h                        |  236 +++++++++++++++++
 13 files changed, 970 insertions(+), 306 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/pv88080.txt
 delete mode 100644 Documentation/devicetree/bindings/regulator/pv88080.txt
 create mode 100644 drivers/gpio/gpio-pv88080.c
 create mode 100644 drivers/mfd/pv88080-core.c
 create mode 100644 drivers/mfd/pv88080-i2c.c
 delete mode 100644 drivers/regulator/pv88080-regulator.h
 create mode 100644 include/linux/mfd/pv88080.h

-- 
end-of-patch for PATCH V2

^ permalink raw reply

* Re: [PATCH V2] pinctrl: qcom: Add msm8994 pinctrl driver
From: Jeremy McNicoll @ 2016-10-27  1:09 UTC (permalink / raw)
  To: Michael Scott, linux-gpio, linux-arm-msm, devicetree,
	linux-kernel
  Cc: Linus Walleij, Rob Herring, Mark Rutland, Andy Gross, David Brown,
	Bjorn Andersson, Joonwoo Park, Jeremy McNicoll
In-Reply-To: <20161026233228.15219-1-michael.scott@linaro.org>

On 2016-10-26 4:32 PM, Michael Scott wrote:
> Initial pinctrl driver for QCOM msm8994 platforms.
>
> In order to continue the initial board support for QCOM msm8994/msm8992
> presented in patches from Jeremy McNicoll <jeremymc@redhat.com>, let's put
> a proper pinctrl driver in place.
>
> Currently, the DT for these platforms uses the msm8x74 pinctrl driver to enable
> basic UART.  Beyond the first few pins the rest are different enough to justify
> it's own driver.
>
> Note: This driver is also be used by QCOM's msm8992 platform as it's TLM block
> is the same.
>
> - Initial formatting and style was taken from the msm8x74 pinctrl driver added
>   by Björn Andersson <bjorn.andersson@linaro.org>
> - Data was then adjusted per QCOM MSM8994 documentation for Top Level Multiplexing
> - Bindings documentation was based on qcom,msm8996-pinctrl.txt by
>   Joonwoo Park <joonwoop@codeaurora.org> and then modified for msm8994 content
>
> Signed-off-by: Michael Scott <michael.scott@linaro.org>
> ---
>
> V1 -> V2: fixed missing FUNCTION(nav_pps) and removed 3 odd newlines between blsp_i2c4_groups and cci_timer0_groups
>

This version still boots fine on the msm8992 with my latest changes.


Tested-by: Jeremy McNicoll <jeremymc@redhat.com>

-jeremy

>  .../bindings/pinctrl/qcom,msm8994-pinctrl.txt      |  175 +++
>  drivers/pinctrl/qcom/Kconfig                       |    9 +
>  drivers/pinctrl/qcom/Makefile                      |    1 +
>  drivers/pinctrl/qcom/pinctrl-msm8994.c             | 1400 ++++++++++++++++++++
>  4 files changed, 1585 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
>  create mode 100644 drivers/pinctrl/qcom/pinctrl-msm8994.c
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
> new file mode 100644
> index 0000000..e390087b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
> @@ -0,0 +1,175 @@
> +Qualcomm MSM8994 TLMM block
> +
> +This binding describes the Top Level Mode Multiplexer block found in the
> +MSM8994 platform.
> +
> +- compatible:
> +	Usage: required
> +	Value type: <string>
> +	Definition: must be "qcom,msm8994-pinctrl"
> +
> +- reg:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: the base address and size of the TLMM register space.
> +
> +- interrupts:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: should specify the TLMM summary IRQ.
> +
> +- interrupt-controller:
> +	Usage: required
> +	Value type: <none>
> +	Definition: identifies this node as an interrupt controller
> +
> +- #interrupt-cells:
> +	Usage: required
> +	Value type: <u32>
> +	Definition: must be 2. Specifying the pin number and flags, as defined
> +		    in <dt-bindings/interrupt-controller/irq.h>
> +
> +- gpio-controller:
> +	Usage: required
> +	Value type: <none>
> +	Definition: identifies this node as a gpio controller
> +
> +- #gpio-cells:
> +	Usage: required
> +	Value type: <u32>
> +	Definition: must be 2. Specifying the pin number and flags, as defined
> +		    in <dt-bindings/gpio/gpio.h>
> +
> +Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
> +a general description of GPIO and interrupt bindings.
> +
> +Please refer to pinctrl-bindings.txt in this directory for details of the
> +common pinctrl bindings used by client devices, including the meaning of the
> +phrase "pin configuration node".
> +
> +The pin configuration nodes act as a container for an arbitrary number of
> +subnodes. Each of these subnodes represents some desired configuration for a
> +pin, a group, or a list of pins or groups. This configuration can include the
> +mux function to select on those pin(s)/group(s), and various pin configuration
> +parameters, such as pull-up, drive strength, etc.
> +
> +
> +PIN CONFIGURATION NODES:
> +
> +The name of each subnode is not important; all subnodes should be enumerated
> +and processed purely based on their content.
> +
> +Each subnode only affects those parameters that are explicitly listed. In
> +other words, a subnode that lists a mux function but no pin configuration
> +parameters implies no information about any pin configuration parameters.
> +Similarly, a pin subnode that describes a pullup parameter implies no
> +information about e.g. the mux function.
> +
> +
> +The following generic properties as defined in pinctrl-bindings.txt are valid
> +to specify in a pin configuration subnode:
> +
> +- pins:
> +	Usage: required
> +	Value type: <string-array>
> +	Definition: List of gpio pins affected by the properties specified in
> +		    this subnode.
> +
> +		    Valid pins are:
> +		      gpio0-gpio145
> +		        Supports mux, bias and drive-strength
> +
> +		      sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk,
> +		      sdc2_cmd, sdc2_data
> +		        Supports bias and drive-strength
> +
> +- function:
> +	Usage: required
> +	Value type: <string>
> +	Definition: Specify the alternative function to be configured for the
> +		    specified pins. Functions are only valid for gpio pins.
> +		    Valid values are:
> +
> +		    audio_ref_clk,  blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
> +		    blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11,
> +		    blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3,
> +		    blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
> +		    blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9,
> +		    blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11,
> +		    blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5,
> +		    blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11,
> +		    blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
> +		    blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11,
> +		    blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b,
> +		    blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3,
> +		    cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1,
> +		    cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, gcc_gp_clk1,
> +		    gcc_gp_clk2, gcc_gp_clk3, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
> +		    gp1_clk, gps_tx, grfc, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, mdp_vsync,
> +		    mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a, qdss_cti_trig_in_b,
> +		    qdss_cti_trig_in_c, qdss_cti_trig_in_d, qdss_cti_trig_out_a,
> +		    qdss_cti_trig_out_b, qdss_cti_trig_out_c, qdss_cti_trig_out_d,
> +		    qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b,
> +		    qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0, pci_e1, pri_mi2s,
> +		    rffe1, rffe2, rffe3, rffe4, rffe5, rffe6, rffe7, sdc4, sec_mi2s, slimbus,
> +		    spkr_mi2s, ter_mi2s, tsif1, tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4,
> +		    gpio
> +
> +- bias-disable:
> +	Usage: optional
> +	Value type: <none>
> +	Definition: The specified pins should be configued as no pull.
> +
> +- bias-pull-down:
> +	Usage: optional
> +	Value type: <none>
> +	Definition: The specified pins should be configued as pull down.
> +
> +- bias-pull-up:
> +	Usage: optional
> +	Value type: <none>
> +	Definition: The specified pins should be configued as pull up.
> +
> +- output-high:
> +	Usage: optional
> +	Value type: <none>
> +	Definition: The specified pins are configured in output mode, driven
> +		    high.
> +		    Not valid for sdc pins.
> +
> +- output-low:
> +	Usage: optional
> +	Value type: <none>
> +	Definition: The specified pins are configured in output mode, driven
> +		    low.
> +		    Not valid for sdc pins.
> +
> +- drive-strength:
> +	Usage: optional
> +	Value type: <u32>
> +	Definition: Selects the drive strength for the specified pins, in mA.
> +		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
> +
> +Example:
> +
> +	msmgpio: pinctrl@fd510000 {
> +		compatible = "qcom,msm8994-pinctrl";
> +		reg = <0xfd510000 0x4000>;
> +		interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
> +		gpio-controller;
> +		#gpio-cells = <2>;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +
> +		blsp1_uart2_default: blsp1_uart2_default {
> +			pinmux {
> +				pins = "gpio4", "gpio5";
> +				function = "blsp_uart2";
> +			};
> +			pinconf {
> +				pins = "gpio4", "gpio5";
> +				drive-strength = <16>;
> +				bias-disable;
> +			};
> +		};
> +	};
> diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
> index 93ef268..3ebdc01 100644
> --- a/drivers/pinctrl/qcom/Kconfig
> +++ b/drivers/pinctrl/qcom/Kconfig
> @@ -79,6 +79,15 @@ config PINCTRL_MSM8916
>  	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
>  	  Qualcomm TLMM block found on the Qualcomm 8916 platform.
>
> +config PINCTRL_MSM8994
> +	tristate "Qualcomm 8994 pin controller driver"
> +	depends on GPIOLIB && OF
> +	select PINCTRL_MSM
> +	help
> +	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
> +	  Qualcomm TLMM block found in the Qualcomm 8994 platform. The
> +	  Qualcomm 8992 platform is also supported by this driver.
> +
>  config PINCTRL_MSM8996
>  	tristate "Qualcomm MSM8996 pin controller driver"
>  	depends on GPIOLIB && OF
> diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
> index 8319e11..ab47764 100644
> --- a/drivers/pinctrl/qcom/Makefile
> +++ b/drivers/pinctrl/qcom/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MSM8660)	+= pinctrl-msm8660.o
>  obj-$(CONFIG_PINCTRL_MSM8960)	+= pinctrl-msm8960.o
>  obj-$(CONFIG_PINCTRL_MSM8X74)	+= pinctrl-msm8x74.o
>  obj-$(CONFIG_PINCTRL_MSM8916)	+= pinctrl-msm8916.o
> +obj-$(CONFIG_PINCTRL_MSM8994)   += pinctrl-msm8994.o
>  obj-$(CONFIG_PINCTRL_MSM8996)   += pinctrl-msm8996.o
>  obj-$(CONFIG_PINCTRL_QDF2XXX)	+= pinctrl-qdf2xxx.o
>  obj-$(CONFIG_PINCTRL_MDM9615)	+= pinctrl-mdm9615.o
> diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c
> new file mode 100644
> index 0000000..556eec8
> --- /dev/null
> +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c
> @@ -0,0 +1,1400 @@
> +/*
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +
> +#include "pinctrl-msm.h"
> +
> +#define FUNCTION(fname)					\
> +	[MSM_MUX_##fname] = {				\
> +		.name = #fname,				\
> +		.groups = fname##_groups,		\
> +		.ngroups = ARRAY_SIZE(fname##_groups),	\
> +	}
> +
> +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11)	\
> +	{						\
> +		.name = "gpio" #id,			\
> +		.pins = gpio##id##_pins,		\
> +		.npins = ARRAY_SIZE(gpio##id##_pins),	\
> +		.funcs = (int[]){			\
> +			MSM_MUX_gpio,			\
> +			MSM_MUX_##f1,			\
> +			MSM_MUX_##f2,			\
> +			MSM_MUX_##f3,			\
> +			MSM_MUX_##f4,			\
> +			MSM_MUX_##f5,			\
> +			MSM_MUX_##f6,			\
> +			MSM_MUX_##f7,			\
> +			MSM_MUX_##f8,			\
> +			MSM_MUX_##f9,			\
> +			MSM_MUX_##f10,			\
> +			MSM_MUX_##f11			\
> +		},					\
> +		.nfuncs = 12,				\
> +		.ctl_reg = 0x1000 + 0x10 * id,		\
> +		.io_reg = 0x1004 + 0x10 * id,		\
> +		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
> +		.intr_status_reg = 0x100c + 0x10 * id,	\
> +		.intr_target_reg = 0x1008 + 0x10 * id,	\
> +		.mux_bit = 2,				\
> +		.pull_bit = 0,				\
> +		.drv_bit = 6,				\
> +		.oe_bit = 9,				\
> +		.in_bit = 0,				\
> +		.out_bit = 1,				\
> +		.intr_enable_bit = 0,			\
> +		.intr_status_bit = 0,			\
> +		.intr_target_bit = 5,			\
> +		.intr_target_kpss_val = 4,		\
> +		.intr_raw_status_bit = 4,		\
> +		.intr_polarity_bit = 1,			\
> +		.intr_detection_bit = 2,		\
> +		.intr_detection_width = 2,		\
> +	}
> +
> +#define SDC_PINGROUP(pg_name, ctl, pull, drv)		\
> +	{						\
> +		.name = #pg_name,			\
> +		.pins = pg_name##_pins,			\
> +		.npins = ARRAY_SIZE(pg_name##_pins),	\
> +		.ctl_reg = ctl,				\
> +		.io_reg = 0,				\
> +		.intr_cfg_reg = 0,			\
> +		.intr_status_reg = 0,			\
> +		.intr_target_reg = 0,			\
> +		.mux_bit = -1,				\
> +		.pull_bit = pull,			\
> +		.drv_bit = drv,				\
> +		.oe_bit = -1,				\
> +		.in_bit = -1,				\
> +		.out_bit = -1,				\
> +		.intr_enable_bit = -1,			\
> +		.intr_status_bit = -1,			\
> +		.intr_target_bit = -1,			\
> +		.intr_target_kpss_val = -1,		\
> +		.intr_raw_status_bit = -1,		\
> +		.intr_polarity_bit = -1,		\
> +		.intr_detection_bit = -1,		\
> +		.intr_detection_width = -1,		\
> +	}
> +static const struct pinctrl_pin_desc msm8994_pins[] = {
> +	PINCTRL_PIN(0, "GPIO_0"),
> +	PINCTRL_PIN(1, "GPIO_1"),
> +	PINCTRL_PIN(2, "GPIO_2"),
> +	PINCTRL_PIN(3, "GPIO_3"),
> +	PINCTRL_PIN(4, "GPIO_4"),
> +	PINCTRL_PIN(5, "GPIO_5"),
> +	PINCTRL_PIN(6, "GPIO_6"),
> +	PINCTRL_PIN(7, "GPIO_7"),
> +	PINCTRL_PIN(8, "GPIO_8"),
> +	PINCTRL_PIN(9, "GPIO_9"),
> +	PINCTRL_PIN(10, "GPIO_10"),
> +	PINCTRL_PIN(11, "GPIO_11"),
> +	PINCTRL_PIN(12, "GPIO_12"),
> +	PINCTRL_PIN(13, "GPIO_13"),
> +	PINCTRL_PIN(14, "GPIO_14"),
> +	PINCTRL_PIN(15, "GPIO_15"),
> +	PINCTRL_PIN(16, "GPIO_16"),
> +	PINCTRL_PIN(17, "GPIO_17"),
> +	PINCTRL_PIN(18, "GPIO_18"),
> +	PINCTRL_PIN(19, "GPIO_19"),
> +	PINCTRL_PIN(20, "GPIO_20"),
> +	PINCTRL_PIN(21, "GPIO_21"),
> +	PINCTRL_PIN(22, "GPIO_22"),
> +	PINCTRL_PIN(23, "GPIO_23"),
> +	PINCTRL_PIN(24, "GPIO_24"),
> +	PINCTRL_PIN(25, "GPIO_25"),
> +	PINCTRL_PIN(26, "GPIO_26"),
> +	PINCTRL_PIN(27, "GPIO_27"),
> +	PINCTRL_PIN(28, "GPIO_28"),
> +	PINCTRL_PIN(29, "GPIO_29"),
> +	PINCTRL_PIN(30, "GPIO_30"),
> +	PINCTRL_PIN(31, "GPIO_31"),
> +	PINCTRL_PIN(32, "GPIO_32"),
> +	PINCTRL_PIN(33, "GPIO_33"),
> +	PINCTRL_PIN(34, "GPIO_34"),
> +	PINCTRL_PIN(35, "GPIO_35"),
> +	PINCTRL_PIN(36, "GPIO_36"),
> +	PINCTRL_PIN(37, "GPIO_37"),
> +	PINCTRL_PIN(38, "GPIO_38"),
> +	PINCTRL_PIN(39, "GPIO_39"),
> +	PINCTRL_PIN(40, "GPIO_40"),
> +	PINCTRL_PIN(41, "GPIO_41"),
> +	PINCTRL_PIN(42, "GPIO_42"),
> +	PINCTRL_PIN(43, "GPIO_43"),
> +	PINCTRL_PIN(44, "GPIO_44"),
> +	PINCTRL_PIN(45, "GPIO_45"),
> +	PINCTRL_PIN(46, "GPIO_46"),
> +	PINCTRL_PIN(47, "GPIO_47"),
> +	PINCTRL_PIN(48, "GPIO_48"),
> +	PINCTRL_PIN(49, "GPIO_49"),
> +	PINCTRL_PIN(50, "GPIO_50"),
> +	PINCTRL_PIN(51, "GPIO_51"),
> +	PINCTRL_PIN(52, "GPIO_52"),
> +	PINCTRL_PIN(53, "GPIO_53"),
> +	PINCTRL_PIN(54, "GPIO_54"),
> +	PINCTRL_PIN(55, "GPIO_55"),
> +	PINCTRL_PIN(56, "GPIO_56"),
> +	PINCTRL_PIN(57, "GPIO_57"),
> +	PINCTRL_PIN(58, "GPIO_58"),
> +	PINCTRL_PIN(59, "GPIO_59"),
> +	PINCTRL_PIN(60, "GPIO_60"),
> +	PINCTRL_PIN(61, "GPIO_61"),
> +	PINCTRL_PIN(62, "GPIO_62"),
> +	PINCTRL_PIN(63, "GPIO_63"),
> +	PINCTRL_PIN(64, "GPIO_64"),
> +	PINCTRL_PIN(65, "GPIO_65"),
> +	PINCTRL_PIN(66, "GPIO_66"),
> +	PINCTRL_PIN(67, "GPIO_67"),
> +	PINCTRL_PIN(68, "GPIO_68"),
> +	PINCTRL_PIN(69, "GPIO_69"),
> +	PINCTRL_PIN(70, "GPIO_70"),
> +	PINCTRL_PIN(71, "GPIO_71"),
> +	PINCTRL_PIN(72, "GPIO_72"),
> +	PINCTRL_PIN(73, "GPIO_73"),
> +	PINCTRL_PIN(74, "GPIO_74"),
> +	PINCTRL_PIN(75, "GPIO_75"),
> +	PINCTRL_PIN(76, "GPIO_76"),
> +	PINCTRL_PIN(77, "GPIO_77"),
> +	PINCTRL_PIN(78, "GPIO_78"),
> +	PINCTRL_PIN(79, "GPIO_79"),
> +	PINCTRL_PIN(80, "GPIO_80"),
> +	PINCTRL_PIN(81, "GPIO_81"),
> +	PINCTRL_PIN(82, "GPIO_82"),
> +	PINCTRL_PIN(83, "GPIO_83"),
> +	PINCTRL_PIN(84, "GPIO_84"),
> +	PINCTRL_PIN(85, "GPIO_85"),
> +	PINCTRL_PIN(86, "GPIO_86"),
> +	PINCTRL_PIN(87, "GPIO_87"),
> +	PINCTRL_PIN(88, "GPIO_88"),
> +	PINCTRL_PIN(89, "GPIO_89"),
> +	PINCTRL_PIN(90, "GPIO_90"),
> +	PINCTRL_PIN(91, "GPIO_91"),
> +	PINCTRL_PIN(92, "GPIO_92"),
> +	PINCTRL_PIN(93, "GPIO_93"),
> +	PINCTRL_PIN(94, "GPIO_94"),
> +	PINCTRL_PIN(95, "GPIO_95"),
> +	PINCTRL_PIN(96, "GPIO_96"),
> +	PINCTRL_PIN(97, "GPIO_97"),
> +	PINCTRL_PIN(98, "GPIO_98"),
> +	PINCTRL_PIN(99, "GPIO_99"),
> +	PINCTRL_PIN(100, "GPIO_100"),
> +	PINCTRL_PIN(101, "GPIO_101"),
> +	PINCTRL_PIN(102, "GPIO_102"),
> +	PINCTRL_PIN(103, "GPIO_103"),
> +	PINCTRL_PIN(104, "GPIO_104"),
> +	PINCTRL_PIN(105, "GPIO_105"),
> +	PINCTRL_PIN(106, "GPIO_106"),
> +	PINCTRL_PIN(107, "GPIO_107"),
> +	PINCTRL_PIN(108, "GPIO_108"),
> +	PINCTRL_PIN(109, "GPIO_109"),
> +	PINCTRL_PIN(110, "GPIO_110"),
> +	PINCTRL_PIN(111, "GPIO_111"),
> +	PINCTRL_PIN(112, "GPIO_112"),
> +	PINCTRL_PIN(113, "GPIO_113"),
> +	PINCTRL_PIN(114, "GPIO_114"),
> +	PINCTRL_PIN(115, "GPIO_115"),
> +	PINCTRL_PIN(116, "GPIO_116"),
> +	PINCTRL_PIN(117, "GPIO_117"),
> +	PINCTRL_PIN(118, "GPIO_118"),
> +	PINCTRL_PIN(119, "GPIO_119"),
> +	PINCTRL_PIN(120, "GPIO_120"),
> +	PINCTRL_PIN(121, "GPIO_121"),
> +	PINCTRL_PIN(122, "GPIO_122"),
> +	PINCTRL_PIN(123, "GPIO_123"),
> +	PINCTRL_PIN(124, "GPIO_124"),
> +	PINCTRL_PIN(125, "GPIO_125"),
> +	PINCTRL_PIN(126, "GPIO_126"),
> +	PINCTRL_PIN(127, "GPIO_127"),
> +	PINCTRL_PIN(128, "GPIO_128"),
> +	PINCTRL_PIN(129, "GPIO_129"),
> +	PINCTRL_PIN(130, "GPIO_130"),
> +	PINCTRL_PIN(131, "GPIO_131"),
> +	PINCTRL_PIN(132, "GPIO_132"),
> +	PINCTRL_PIN(133, "GPIO_133"),
> +	PINCTRL_PIN(134, "GPIO_134"),
> +	PINCTRL_PIN(135, "GPIO_135"),
> +	PINCTRL_PIN(136, "GPIO_136"),
> +	PINCTRL_PIN(137, "GPIO_137"),
> +	PINCTRL_PIN(138, "GPIO_138"),
> +	PINCTRL_PIN(139, "GPIO_139"),
> +	PINCTRL_PIN(140, "GPIO_140"),
> +	PINCTRL_PIN(141, "GPIO_141"),
> +	PINCTRL_PIN(142, "GPIO_142"),
> +	PINCTRL_PIN(143, "GPIO_143"),
> +	PINCTRL_PIN(144, "GPIO_144"),
> +	PINCTRL_PIN(145, "GPIO_145"),
> +	PINCTRL_PIN(146, "SDC1_RCLK"),
> +	PINCTRL_PIN(147, "SDC1_CLK"),
> +	PINCTRL_PIN(148, "SDC1_CMD"),
> +	PINCTRL_PIN(149, "SDC1_DATA"),
> +	PINCTRL_PIN(150, "SDC2_CLK"),
> +	PINCTRL_PIN(151, "SDC2_CMD"),
> +	PINCTRL_PIN(152, "SDC2_DATA"),
> +	PINCTRL_PIN(153, "SDC3_CLK"),
> +	PINCTRL_PIN(154, "SDC3_CMD"),
> +	PINCTRL_PIN(155, "SDC3_DATA"),
> +};
> +
> +#define DECLARE_MSM_GPIO_PINS(pin) \
> +	static const unsigned int gpio##pin##_pins[] = { pin }
> +DECLARE_MSM_GPIO_PINS(0);
> +DECLARE_MSM_GPIO_PINS(1);
> +DECLARE_MSM_GPIO_PINS(2);
> +DECLARE_MSM_GPIO_PINS(3);
> +DECLARE_MSM_GPIO_PINS(4);
> +DECLARE_MSM_GPIO_PINS(5);
> +DECLARE_MSM_GPIO_PINS(6);
> +DECLARE_MSM_GPIO_PINS(7);
> +DECLARE_MSM_GPIO_PINS(8);
> +DECLARE_MSM_GPIO_PINS(9);
> +DECLARE_MSM_GPIO_PINS(10);
> +DECLARE_MSM_GPIO_PINS(11);
> +DECLARE_MSM_GPIO_PINS(12);
> +DECLARE_MSM_GPIO_PINS(13);
> +DECLARE_MSM_GPIO_PINS(14);
> +DECLARE_MSM_GPIO_PINS(15);
> +DECLARE_MSM_GPIO_PINS(16);
> +DECLARE_MSM_GPIO_PINS(17);
> +DECLARE_MSM_GPIO_PINS(18);
> +DECLARE_MSM_GPIO_PINS(19);
> +DECLARE_MSM_GPIO_PINS(20);
> +DECLARE_MSM_GPIO_PINS(21);
> +DECLARE_MSM_GPIO_PINS(22);
> +DECLARE_MSM_GPIO_PINS(23);
> +DECLARE_MSM_GPIO_PINS(24);
> +DECLARE_MSM_GPIO_PINS(25);
> +DECLARE_MSM_GPIO_PINS(26);
> +DECLARE_MSM_GPIO_PINS(27);
> +DECLARE_MSM_GPIO_PINS(28);
> +DECLARE_MSM_GPIO_PINS(29);
> +DECLARE_MSM_GPIO_PINS(30);
> +DECLARE_MSM_GPIO_PINS(31);
> +DECLARE_MSM_GPIO_PINS(32);
> +DECLARE_MSM_GPIO_PINS(33);
> +DECLARE_MSM_GPIO_PINS(34);
> +DECLARE_MSM_GPIO_PINS(35);
> +DECLARE_MSM_GPIO_PINS(36);
> +DECLARE_MSM_GPIO_PINS(37);
> +DECLARE_MSM_GPIO_PINS(38);
> +DECLARE_MSM_GPIO_PINS(39);
> +DECLARE_MSM_GPIO_PINS(40);
> +DECLARE_MSM_GPIO_PINS(41);
> +DECLARE_MSM_GPIO_PINS(42);
> +DECLARE_MSM_GPIO_PINS(43);
> +DECLARE_MSM_GPIO_PINS(44);
> +DECLARE_MSM_GPIO_PINS(45);
> +DECLARE_MSM_GPIO_PINS(46);
> +DECLARE_MSM_GPIO_PINS(47);
> +DECLARE_MSM_GPIO_PINS(48);
> +DECLARE_MSM_GPIO_PINS(49);
> +DECLARE_MSM_GPIO_PINS(50);
> +DECLARE_MSM_GPIO_PINS(51);
> +DECLARE_MSM_GPIO_PINS(52);
> +DECLARE_MSM_GPIO_PINS(53);
> +DECLARE_MSM_GPIO_PINS(54);
> +DECLARE_MSM_GPIO_PINS(55);
> +DECLARE_MSM_GPIO_PINS(56);
> +DECLARE_MSM_GPIO_PINS(57);
> +DECLARE_MSM_GPIO_PINS(58);
> +DECLARE_MSM_GPIO_PINS(59);
> +DECLARE_MSM_GPIO_PINS(60);
> +DECLARE_MSM_GPIO_PINS(61);
> +DECLARE_MSM_GPIO_PINS(62);
> +DECLARE_MSM_GPIO_PINS(63);
> +DECLARE_MSM_GPIO_PINS(64);
> +DECLARE_MSM_GPIO_PINS(65);
> +DECLARE_MSM_GPIO_PINS(66);
> +DECLARE_MSM_GPIO_PINS(67);
> +DECLARE_MSM_GPIO_PINS(68);
> +DECLARE_MSM_GPIO_PINS(69);
> +DECLARE_MSM_GPIO_PINS(70);
> +DECLARE_MSM_GPIO_PINS(71);
> +DECLARE_MSM_GPIO_PINS(72);
> +DECLARE_MSM_GPIO_PINS(73);
> +DECLARE_MSM_GPIO_PINS(74);
> +DECLARE_MSM_GPIO_PINS(75);
> +DECLARE_MSM_GPIO_PINS(76);
> +DECLARE_MSM_GPIO_PINS(77);
> +DECLARE_MSM_GPIO_PINS(78);
> +DECLARE_MSM_GPIO_PINS(79);
> +DECLARE_MSM_GPIO_PINS(80);
> +DECLARE_MSM_GPIO_PINS(81);
> +DECLARE_MSM_GPIO_PINS(82);
> +DECLARE_MSM_GPIO_PINS(83);
> +DECLARE_MSM_GPIO_PINS(84);
> +DECLARE_MSM_GPIO_PINS(85);
> +DECLARE_MSM_GPIO_PINS(86);
> +DECLARE_MSM_GPIO_PINS(87);
> +DECLARE_MSM_GPIO_PINS(88);
> +DECLARE_MSM_GPIO_PINS(89);
> +DECLARE_MSM_GPIO_PINS(90);
> +DECLARE_MSM_GPIO_PINS(91);
> +DECLARE_MSM_GPIO_PINS(92);
> +DECLARE_MSM_GPIO_PINS(93);
> +DECLARE_MSM_GPIO_PINS(94);
> +DECLARE_MSM_GPIO_PINS(95);
> +DECLARE_MSM_GPIO_PINS(96);
> +DECLARE_MSM_GPIO_PINS(97);
> +DECLARE_MSM_GPIO_PINS(98);
> +DECLARE_MSM_GPIO_PINS(99);
> +DECLARE_MSM_GPIO_PINS(100);
> +DECLARE_MSM_GPIO_PINS(101);
> +DECLARE_MSM_GPIO_PINS(102);
> +DECLARE_MSM_GPIO_PINS(103);
> +DECLARE_MSM_GPIO_PINS(104);
> +DECLARE_MSM_GPIO_PINS(105);
> +DECLARE_MSM_GPIO_PINS(106);
> +DECLARE_MSM_GPIO_PINS(107);
> +DECLARE_MSM_GPIO_PINS(108);
> +DECLARE_MSM_GPIO_PINS(109);
> +DECLARE_MSM_GPIO_PINS(110);
> +DECLARE_MSM_GPIO_PINS(111);
> +DECLARE_MSM_GPIO_PINS(112);
> +DECLARE_MSM_GPIO_PINS(113);
> +DECLARE_MSM_GPIO_PINS(114);
> +DECLARE_MSM_GPIO_PINS(115);
> +DECLARE_MSM_GPIO_PINS(116);
> +DECLARE_MSM_GPIO_PINS(117);
> +DECLARE_MSM_GPIO_PINS(118);
> +DECLARE_MSM_GPIO_PINS(119);
> +DECLARE_MSM_GPIO_PINS(120);
> +DECLARE_MSM_GPIO_PINS(121);
> +DECLARE_MSM_GPIO_PINS(122);
> +DECLARE_MSM_GPIO_PINS(123);
> +DECLARE_MSM_GPIO_PINS(124);
> +DECLARE_MSM_GPIO_PINS(125);
> +DECLARE_MSM_GPIO_PINS(126);
> +DECLARE_MSM_GPIO_PINS(127);
> +DECLARE_MSM_GPIO_PINS(128);
> +DECLARE_MSM_GPIO_PINS(129);
> +DECLARE_MSM_GPIO_PINS(130);
> +DECLARE_MSM_GPIO_PINS(131);
> +DECLARE_MSM_GPIO_PINS(132);
> +DECLARE_MSM_GPIO_PINS(133);
> +DECLARE_MSM_GPIO_PINS(134);
> +DECLARE_MSM_GPIO_PINS(135);
> +DECLARE_MSM_GPIO_PINS(136);
> +DECLARE_MSM_GPIO_PINS(137);
> +DECLARE_MSM_GPIO_PINS(138);
> +DECLARE_MSM_GPIO_PINS(139);
> +DECLARE_MSM_GPIO_PINS(140);
> +DECLARE_MSM_GPIO_PINS(141);
> +DECLARE_MSM_GPIO_PINS(142);
> +DECLARE_MSM_GPIO_PINS(143);
> +DECLARE_MSM_GPIO_PINS(144);
> +DECLARE_MSM_GPIO_PINS(145);
> +
> +static const unsigned int sdc1_rclk_pins[] = { 146 };
> +static const unsigned int sdc1_clk_pins[] = { 147 };
> +static const unsigned int sdc1_cmd_pins[] = { 148 };
> +static const unsigned int sdc1_data_pins[] = { 149 };
> +static const unsigned int sdc2_clk_pins[] = { 150 };
> +static const unsigned int sdc2_cmd_pins[] = { 151 };
> +static const unsigned int sdc2_data_pins[] = { 152 };
> +static const unsigned int sdc3_clk_pins[] = { 153 };
> +static const unsigned int sdc3_cmd_pins[] = { 154 };
> +static const unsigned int sdc3_data_pins[] = { 155 };
> +
> +enum msm8994_functions {
> +	MSM_MUX_audio_ref_clk,
> +	MSM_MUX_blsp_i2c1,
> +	MSM_MUX_blsp_i2c2,
> +	MSM_MUX_blsp_i2c3,
> +	MSM_MUX_blsp_i2c4,
> +	MSM_MUX_blsp_i2c5,
> +	MSM_MUX_blsp_i2c6,
> +	MSM_MUX_blsp_i2c7,
> +	MSM_MUX_blsp_i2c8,
> +	MSM_MUX_blsp_i2c9,
> +	MSM_MUX_blsp_i2c10,
> +	MSM_MUX_blsp_i2c11,
> +	MSM_MUX_blsp_i2c12,
> +	MSM_MUX_blsp_spi1,
> +	MSM_MUX_blsp_spi1_cs1,
> +	MSM_MUX_blsp_spi1_cs2,
> +	MSM_MUX_blsp_spi1_cs3,
> +	MSM_MUX_blsp_spi2,
> +	MSM_MUX_blsp_spi2_cs1,
> +	MSM_MUX_blsp_spi2_cs2,
> +	MSM_MUX_blsp_spi2_cs3,
> +	MSM_MUX_blsp_spi3,
> +	MSM_MUX_blsp_spi4,
> +	MSM_MUX_blsp_spi5,
> +	MSM_MUX_blsp_spi6,
> +	MSM_MUX_blsp_spi7,
> +	MSM_MUX_blsp_spi8,
> +	MSM_MUX_blsp_spi9,
> +	MSM_MUX_blsp_spi10,
> +	MSM_MUX_blsp_spi10_cs1,
> +	MSM_MUX_blsp_spi10_cs2,
> +	MSM_MUX_blsp_spi10_cs3,
> +	MSM_MUX_blsp_spi11,
> +	MSM_MUX_blsp_spi12,
> +	MSM_MUX_blsp_uart1,
> +	MSM_MUX_blsp_uart2,
> +	MSM_MUX_blsp_uart3,
> +	MSM_MUX_blsp_uart4,
> +	MSM_MUX_blsp_uart5,
> +	MSM_MUX_blsp_uart6,
> +	MSM_MUX_blsp_uart7,
> +	MSM_MUX_blsp_uart8,
> +	MSM_MUX_blsp_uart9,
> +	MSM_MUX_blsp_uart10,
> +	MSM_MUX_blsp_uart11,
> +	MSM_MUX_blsp_uart12,
> +	MSM_MUX_blsp_uim1,
> +	MSM_MUX_blsp_uim2,
> +	MSM_MUX_blsp_uim3,
> +	MSM_MUX_blsp_uim4,
> +	MSM_MUX_blsp_uim5,
> +	MSM_MUX_blsp_uim6,
> +	MSM_MUX_blsp_uim7,
> +	MSM_MUX_blsp_uim8,
> +	MSM_MUX_blsp_uim9,
> +	MSM_MUX_blsp_uim10,
> +	MSM_MUX_blsp_uim11,
> +	MSM_MUX_blsp_uim12,
> +	MSM_MUX_blsp11_i2c_scl_b,
> +	MSM_MUX_blsp11_i2c_sda_b,
> +	MSM_MUX_blsp11_uart_rx_b,
> +	MSM_MUX_blsp11_uart_tx_b,
> +	MSM_MUX_cam_mclk0,
> +	MSM_MUX_cam_mclk1,
> +	MSM_MUX_cam_mclk2,
> +	MSM_MUX_cam_mclk3,
> +	MSM_MUX_cci_async_in0,
> +	MSM_MUX_cci_async_in1,
> +	MSM_MUX_cci_async_in2,
> +	MSM_MUX_cci_i2c0,
> +	MSM_MUX_cci_i2c1,
> +	MSM_MUX_cci_timer0,
> +	MSM_MUX_cci_timer1,
> +	MSM_MUX_cci_timer2,
> +	MSM_MUX_cci_timer3,
> +	MSM_MUX_cci_timer4,
> +	MSM_MUX_gcc_gp_clk1,
> +	MSM_MUX_gcc_gp_clk2,
> +	MSM_MUX_gcc_gp_clk3,
> +	MSM_MUX_gp_mn,
> +	MSM_MUX_gp_pdm0,
> +	MSM_MUX_gp_pdm1,
> +	MSM_MUX_gp_pdm2,
> +	MSM_MUX_gp0_clk,
> +	MSM_MUX_gp1_clk,
> +	MSM_MUX_gps_tx,
> +	MSM_MUX_grfc,
> +	MSM_MUX_gsm_tx,
> +	MSM_MUX_hdmi_cec,
> +	MSM_MUX_hdmi_ddc,
> +	MSM_MUX_hdmi_hpd,
> +	MSM_MUX_mdp_vsync,
> +	MSM_MUX_mss_lte,
> +	MSM_MUX_nav_pps,
> +	MSM_MUX_nav_tsync,
> +	MSM_MUX_qdss_cti_trig_in_a,
> +	MSM_MUX_qdss_cti_trig_in_b,
> +	MSM_MUX_qdss_cti_trig_in_c,
> +	MSM_MUX_qdss_cti_trig_in_d,
> +	MSM_MUX_qdss_cti_trig_out_a,
> +	MSM_MUX_qdss_cti_trig_out_b,
> +	MSM_MUX_qdss_cti_trig_out_c,
> +	MSM_MUX_qdss_cti_trig_out_d,
> +	MSM_MUX_qdss_traceclk_a,
> +	MSM_MUX_qdss_traceclk_b,
> +	MSM_MUX_qdss_tracectl_a,
> +	MSM_MUX_qdss_tracectl_b,
> +	MSM_MUX_qdss_tracedata_a,
> +	MSM_MUX_qdss_tracedata_b,
> +	MSM_MUX_qua_mi2s,
> +	MSM_MUX_pci_e0,
> +	MSM_MUX_pci_e1,
> +	MSM_MUX_pri_mi2s,
> +	MSM_MUX_rffe1,
> +	MSM_MUX_rffe2,
> +	MSM_MUX_rffe3,
> +	MSM_MUX_rffe4,
> +	MSM_MUX_rffe5,
> +	MSM_MUX_rffe6,
> +	MSM_MUX_rffe7,
> +	MSM_MUX_sdc4,
> +	MSM_MUX_sec_mi2s,
> +	MSM_MUX_slimbus,
> +	MSM_MUX_spkr_mi2s,
> +	MSM_MUX_ter_mi2s,
> +	MSM_MUX_tsif1,
> +	MSM_MUX_tsif2,
> +	MSM_MUX_uim1,
> +	MSM_MUX_uim2,
> +	MSM_MUX_uim3,
> +	MSM_MUX_uim4,
> +	MSM_MUX_uim_batt_alarm,
> +	MSM_MUX_gpio,
> +	MSM_MUX_NA,
> +};
> +
> +static const char * const gpio_groups[] = {
> +	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
> +	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
> +	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
> +	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
> +	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
> +	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
> +	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
> +	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
> +	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
> +	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
> +	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
> +	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
> +	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
> +	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
> +	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
> +	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
> +	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
> +	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
> +	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
> +	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
> +	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
> +	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145",
> +};
> +
> +static const char * const blsp_spi1_groups[] = {
> +	"gpio0", "gpio1", "gpio2", "gpio3"
> +};
> +static const char * const blsp_uart1_groups[] = {
> +	"gpio0", "gpio1", "gpio2", "gpio3"
> +};
> +static const char * const blsp_uim1_groups[] = {
> +	"gpio0", "gpio1"
> +};
> +static const char * const blsp_i2c1_groups[] = {
> +	"gpio2", "gpio3"
> +};
> +static const char * const blsp_spi2_groups[] = {
> +	"gpio4", "gpio5", "gpio6", "gpio7"
> +};
> +static const char * const blsp_uart2_groups[] = {
> +	"gpio4", "gpio5", "gpio6", "gpio7"
> +};
> +static const char * const blsp_uim2_groups[] = {
> +	"gpio4", "gpio5"
> +};
> +static const char * const qdss_cti_trig_out_b_groups[] = {
> +	"gpio4",
> +};
> +static const char * const qdss_cti_trig_in_b_groups[] = {
> +	"gpio5",
> +};
> +static const char * const blsp_i2c2_groups[] = {
> +	"gpio6", "gpio7"
> +};
> +static const char * const blsp_spi3_groups[] = {
> +	"gpio8", "gpio9", "gpio10", "gpio11"
> +};
> +static const char * const blsp_uart3_groups[] = {
> +	"gpio8", "gpio9", "gpio10", "gpio11"
> +};
> +static const char * const blsp_uim3_groups[] = {
> +	"gpio8", "gpio9"
> +};
> +static const char * const blsp_spi1_cs1_groups[] = {
> +	"gpio8"
> +};
> +static const char * const blsp_spi1_cs2_groups[] = {
> +	"gpio9", "gpio11"
> +};
> +static const char * const mdp_vsync_groups[] = {
> +	"gpio10", "gpio11", "gpio12"
> +};
> +static const char * const blsp_i2c3_groups[] = {
> +	"gpio10", "gpio11"
> +};
> +static const char * const blsp_spi1_cs3_groups[] = {
> +	"gpio10"
> +};
> +static const char * const qdss_tracedata_b_groups[] = {
> +	"gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18",
> +	"gpio19", "gpio21", "gpio22", "gpio23", "gpio25", "gpio26",
> +	"gpio57", "gpio58", "gpio92", "gpio93",
> +};
> +static const char * const cam_mclk0_groups[] = {
> +	"gpio13"
> +};
> +static const char * const cam_mclk1_groups[] = {
> +	"gpio14"
> +};
> +static const char * const cam_mclk2_groups[] = {
> +	"gpio15"
> +};
> +static const char * const cam_mclk3_groups[] = {
> +	"gpio16"
> +};
> +static const char * const cci_i2c0_groups[] = {
> +	"gpio17", "gpio18"
> +};
> +static const char * const blsp_spi4_groups[] = {
> +	"gpio17", "gpio18", "gpio19", "gpio20"
> +};
> +static const char * const blsp_uart4_groups[] = {
> +	"gpio17", "gpio18", "gpio19", "gpio20"
> +};
> +static const char * const blsp_uim4_groups[] = {
> +	"gpio17", "gpio18"
> +};
> +static const char * const cci_i2c1_groups[] = {
> +	"gpio19", "gpio20"
> +};
> +static const char * const blsp_i2c4_groups[] = {
> +	"gpio19", "gpio20"
> +};
> +static const char * const cci_timer0_groups[] = {
> +	"gpio21"
> +};
> +static const char * const blsp_spi5_groups[] = {
> +	"gpio21", "gpio22", "gpio23", "gpio24"
> +};
> +static const char * const blsp_uart5_groups[] = {
> +	"gpio21", "gpio22", "gpio23", "gpio24"
> +};
> +static const char * const blsp_uim5_groups[] = {
> +	"gpio21", "gpio22"
> +};
> +static const char * const cci_timer1_groups[] = {
> +	"gpio22"
> +};
> +static const char * const cci_timer2_groups[] = {
> +	"gpio23"
> +};
> +static const char * const blsp_i2c5_groups[] = {
> +	"gpio23", "gpio24"
> +};
> +static const char * const cci_timer3_groups[] = {
> +	"gpio24"
> +};
> +static const char * const cci_async_in1_groups[] = {
> +	"gpio24"
> +};
> +static const char * const cci_timer4_groups[] = {
> +	"gpio25"
> +};
> +static const char * const cci_async_in2_groups[] = {
> +	"gpio25"
> +};
> +static const char * const blsp_spi6_groups[] = {
> +	"gpio25", "gpio26", "gpio27", "gpio28"
> +};
> +static const char * const blsp_uart6_groups[] = {
> +	"gpio25", "gpio26", "gpio27", "gpio28"
> +};
> +static const char * const blsp_uim6_groups[] = {
> +	"gpio25", "gpio26"
> +};
> +static const char * const cci_async_in0_groups[] = {
> +	"gpio26"
> +};
> +static const char * const gp0_clk_groups[] = {
> +	"gpio26"
> +};
> +static const char * const gp1_clk_groups[] = {
> +	"gpio27", "gpio57", "gpio78"
> +};
> +static const char * const blsp_i2c6_groups[] = {
> +	"gpio27", "gpio28"
> +};
> +static const char * const qdss_tracectl_a_groups[] = {
> +	"gpio27",
> +};
> +static const char * const qdss_traceclk_a_groups[] = {
> +	"gpio28",
> +};
> +static const char * const gp_mn_groups[] = {
> +	"gpio29"
> +};
> +static const char * const hdmi_cec_groups[] = {
> +	"gpio31"
> +};
> +static const char * const hdmi_ddc_groups[] = {
> +	"gpio32", "gpio33"
> +};
> +static const char * const hdmi_hpd_groups[] = {
> +	"gpio34"
> +};
> +static const char * const uim3_groups[] = {
> +	"gpio35", "gpio36", "gpio37", "gpio38"
> +};
> +static const char * const pci_e1_groups[] = {
> +	"gpio35", "gpio36",
> +};
> +static const char * const blsp_spi7_groups[] = {
> +	"gpio41", "gpio42", "gpio43", "gpio44"
> +};
> +static const char * const blsp_uart7_groups[] = {
> +	"gpio41", "gpio42", "gpio43", "gpio44"
> +};
> +static const char * const blsp_uim7_groups[] = {
> +	"gpio41", "gpio42"
> +};
> +static const char * const qdss_cti_trig_out_c_groups[] = {
> +	"gpio41",
> +};
> +static const char * const qdss_cti_trig_in_c_groups[] = {
> +	"gpio42",
> +};
> +static const char * const blsp_i2c7_groups[] = {
> +	"gpio43", "gpio44"
> +};
> +static const char * const blsp_spi8_groups[] = {
> +	"gpio45", "gpio46", "gpio47", "gpio48"
> +};
> +static const char * const blsp_uart8_groups[] = {
> +	"gpio45", "gpio46", "gpio47", "gpio48"
> +};
> +static const char * const blsp_uim8_groups[] = {
> +	"gpio45", "gpio46"
> +};
> +static const char * const blsp_i2c8_groups[] = {
> +	"gpio47", "gpio48"
> +};
> +static const char * const blsp_spi10_cs1_groups[] = {
> +	"gpio47", "gpio67"
> +};
> +static const char * const blsp_spi10_cs2_groups[] = {
> +	"gpio48", "gpio68"
> +};
> +static const char * const uim2_groups[] = {
> +	"gpio49", "gpio50", "gpio51", "gpio52"
> +};
> +static const char * const blsp_spi9_groups[] = {
> +	"gpio49", "gpio50", "gpio51", "gpio52"
> +};
> +static const char * const blsp_uart9_groups[] = {
> +	"gpio49", "gpio50", "gpio51", "gpio52"
> +};
> +static const char * const blsp_uim9_groups[] = {
> +	"gpio49", "gpio50"
> +};
> +static const char * const blsp_i2c9_groups[] = {
> +	"gpio51", "gpio52"
> +};
> +static const char * const pci_e0_groups[] = {
> +	"gpio53", "gpio54",
> +};
> +static const char * const uim4_groups[] = {
> +	"gpio53", "gpio54", "gpio55", "gpio56"
> +};
> +static const char * const blsp_spi10_groups[] = {
> +	"gpio53", "gpio54", "gpio55", "gpio56"
> +};
> +static const char * const blsp_uart10_groups[] = {
> +	"gpio53", "gpio54", "gpio55", "gpio56"
> +};
> +static const char * const blsp_uim10_groups[] = {
> +	"gpio53", "gpio54"
> +};
> +static const char * const qdss_tracedata_a_groups[] = {
> +	"gpio53", "gpio54", "gpio63", "gpio64", "gpio65",
> +	"gpio66", "gpio67", "gpio74", "gpio75", "gpio76",
> +	"gpio77", "gpio85", "gpio86", "gpio87", "gpio89",
> +	"gpio90"
> +};
> +static const char * const gp_pdm0_groups[] = {
> +	"gpio54", "gpio95"
> +};
> +static const char * const blsp_i2c10_groups[] = {
> +	"gpio55", "gpio56"
> +};
> +static const char * const qdss_cti_trig_in_a_groups[] = {
> +	"gpio55",
> +};
> +static const char * const qdss_cti_trig_out_a_groups[] = {
> +	"gpio56",
> +};
> +static const char * const qua_mi2s_groups[] = {
> +	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
> +};
> +static const char * const gcc_gp_clk1_groups[] = {
> +	"gpio57", "gpio78"
> +};
> +static const char * const gcc_gp_clk2_groups[] = {
> +	"gpio58", "gpio81"
> +};
> +static const char * const gcc_gp_clk3_groups[] = {
> +	"gpio59", "gpio82"
> +};
> +static const char * const blsp_spi2_cs1_groups[] = {
> +	"gpio62"
> +};
> +static const char * const blsp_spi2_cs2_groups[] = {
> +	"gpio63"
> +};
> +static const char * const gp_pdm2_groups[] = {
> +	"gpio63", "gpio79"
> +};
> +static const char * const pri_mi2s_groups[] = {
> +	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
> +};
> +static const char * const blsp_spi2_cs3_groups[] = {
> +	"gpio66"
> +};
> +static const char * const spkr_mi2s_groups[] = {
> +	"gpio69", "gpio70", "gpio71", "gpio72"
> +};
> +static const char * const audio_ref_clk_groups[] = {
> +	"gpio69"
> +};
> +static const char * const slimbus_groups[] = {
> +	"gpio70", "gpio71"
> +};
> +static const char * const ter_mi2s_groups[] = {
> +	"gpio73", "gpio74", "gpio75", "gpio76", "gpio77"
> +};
> +static const char * const gp_pdm1_groups[] = {
> +	"gpio74", "gpio86"
> +};
> +static const char * const sec_mi2s_groups[] = {
> +	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
> +};
> +static const char * const blsp_spi11_groups[] = {
> +	"gpio81", "gpio82", "gpio83", "gpio84"
> +};
> +static const char * const blsp_uart11_groups[] = {
> +	"gpio81", "gpio82", "gpio83", "gpio84"
> +};
> +static const char * const blsp_uim11_groups[] = {
> +	"gpio81", "gpio82"
> +};
> +static const char * const blsp_i2c11_groups[] = {
> +	"gpio83", "gpio84"
> +};
> +static const char * const blsp_uart12_groups[] = {
> +	"gpio85", "gpio86", "gpio87", "gpio88"
> +};
> +static const char * const blsp_uim12_groups[] = {
> +	"gpio85", "gpio86"
> +};
> +static const char * const blsp_i2c12_groups[] = {
> +	"gpio87", "gpio88"
> +};
> +static const char * const blsp_spi12_groups[] = {
> +	"gpio85", "gpio86", "gpio87", "gpio88"
> +};
> +static const char * const tsif1_groups[] = {
> +	"gpio89", "gpio90", "gpio91", "gpio110", "gpio111"
> +};
> +static const char * const blsp_spi10_cs3_groups[] = {
> +	"gpio90"
> +};
> +static const char * const sdc4_groups[] = {
> +	"gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
> +};
> +static const char * const qdss_traceclk_b_groups[] = {
> +	"gpio91",
> +};
> +static const char * const tsif2_groups[] = {
> +	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96"
> +};
> +static const char * const qdss_tracectl_b_groups[] = {
> +	"gpio94",
> +};
> +static const char * const qdss_cti_trig_out_d_groups[] = {
> +	"gpio95",
> +};
> +static const char * const qdss_cti_trig_in_d_groups[] = {
> +	"gpio96",
> +};
> +static const char * const uim1_groups[] = {
> +	"gpio97", "gpio98", "gpio99", "gpio100"
> +};
> +static const char * const uim_batt_alarm_groups[] = {
> +	"gpio101"
> +};
> +static const char * const blsp11_uart_tx_b_groups[] = {
> +	"gpio111"
> +};
> +static const char * const blsp11_uart_rx_b_groups[] = {
> +	"gpio112"
> +};
> +static const char * const blsp11_i2c_sda_b_groups[] = {
> +	"gpio113"
> +};
> +static const char * const blsp11_i2c_scl_b_groups[] = {
> +	"gpio114"
> +};
> +static const char * const grfc_groups[] = {
> +	"gpio115", "gpio116", "gpio117", "gpio118", "gpio119", "gpio120",
> +	"gpio121", "gpio122", "gpio123", "gpio124", "gpio125", "gpio126",
> +	"gpio127", "gpio128", "gpio129", "gpio133"
> +};
> +static const char * const rffe6_groups[] = {
> +	"gpio115", "gpio116"
> +};
> +static const char * const rffe7_groups[] = {
> +	"gpio117", "gpio118"
> +};
> +static const char * const gsm_tx_groups[] = {
> +	"gpio126", "gpio131", "gpio132", "gpio133"
> +};
> +static const char * const nav_tsync_groups[] = {
> +	"gpio127"
> +};
> +static const char * const nav_pps_groups[] = {
> +	"gpio127"
> +};
> +static const char * const gps_tx_groups[] = {
> +	"gpio130"
> +};
> +static const char * const mss_lte_groups[] = {
> +	"gpio134", "gpio135"
> +};
> +static const char * const rffe1_groups[] = {
> +	"gpio136", "gpio137"
> +};
> +static const char * const rffe2_groups[] = {
> +	"gpio138", "gpio139"
> +};
> +static const char * const rffe3_groups[] = {
> +	"gpio140", "gpio141"
> +};
> +static const char * const rffe4_groups[] = {
> +	"gpio142", "gpio143"
> +};
> +static const char * const rffe5_groups[] = {
> +	"gpio144", "gpio145"
> +};
> +
> +static const struct msm_function msm8994_functions[] = {
> +	FUNCTION(audio_ref_clk),
> +	FUNCTION(blsp_i2c1),
> +	FUNCTION(blsp_i2c2),
> +	FUNCTION(blsp_i2c3),
> +	FUNCTION(blsp_i2c4),
> +	FUNCTION(blsp_i2c5),
> +	FUNCTION(blsp_i2c6),
> +	FUNCTION(blsp_i2c7),
> +	FUNCTION(blsp_i2c8),
> +	FUNCTION(blsp_i2c9),
> +	FUNCTION(blsp_i2c10),
> +	FUNCTION(blsp_i2c11),
> +	FUNCTION(blsp_i2c12),
> +	FUNCTION(blsp_spi1),
> +	FUNCTION(blsp_spi1_cs1),
> +	FUNCTION(blsp_spi1_cs2),
> +	FUNCTION(blsp_spi1_cs3),
> +	FUNCTION(blsp_spi2),
> +	FUNCTION(blsp_spi2_cs1),
> +	FUNCTION(blsp_spi2_cs2),
> +	FUNCTION(blsp_spi2_cs3),
> +	FUNCTION(blsp_spi3),
> +	FUNCTION(blsp_spi4),
> +	FUNCTION(blsp_spi5),
> +	FUNCTION(blsp_spi6),
> +	FUNCTION(blsp_spi7),
> +	FUNCTION(blsp_spi8),
> +	FUNCTION(blsp_spi9),
> +	FUNCTION(blsp_spi10),
> +	FUNCTION(blsp_spi10_cs1),
> +	FUNCTION(blsp_spi10_cs2),
> +	FUNCTION(blsp_spi10_cs3),
> +	FUNCTION(blsp_spi11),
> +	FUNCTION(blsp_spi12),
> +	FUNCTION(blsp_uart1),
> +	FUNCTION(blsp_uart2),
> +	FUNCTION(blsp_uart3),
> +	FUNCTION(blsp_uart4),
> +	FUNCTION(blsp_uart5),
> +	FUNCTION(blsp_uart6),
> +	FUNCTION(blsp_uart7),
> +	FUNCTION(blsp_uart8),
> +	FUNCTION(blsp_uart9),
> +	FUNCTION(blsp_uart10),
> +	FUNCTION(blsp_uart11),
> +	FUNCTION(blsp_uart12),
> +	FUNCTION(blsp_uim1),
> +	FUNCTION(blsp_uim2),
> +	FUNCTION(blsp_uim3),
> +	FUNCTION(blsp_uim4),
> +	FUNCTION(blsp_uim5),
> +	FUNCTION(blsp_uim6),
> +	FUNCTION(blsp_uim7),
> +	FUNCTION(blsp_uim8),
> +	FUNCTION(blsp_uim9),
> +	FUNCTION(blsp_uim10),
> +	FUNCTION(blsp_uim11),
> +	FUNCTION(blsp_uim12),
> +	FUNCTION(blsp11_i2c_scl_b),
> +	FUNCTION(blsp11_i2c_sda_b),
> +	FUNCTION(blsp11_uart_rx_b),
> +	FUNCTION(blsp11_uart_tx_b),
> +	FUNCTION(cam_mclk0),
> +	FUNCTION(cam_mclk1),
> +	FUNCTION(cam_mclk2),
> +	FUNCTION(cam_mclk3),
> +	FUNCTION(cci_async_in0),
> +	FUNCTION(cci_async_in1),
> +	FUNCTION(cci_async_in2),
> +	FUNCTION(cci_i2c0),
> +	FUNCTION(cci_i2c1),
> +	FUNCTION(cci_timer0),
> +	FUNCTION(cci_timer1),
> +	FUNCTION(cci_timer2),
> +	FUNCTION(cci_timer3),
> +	FUNCTION(cci_timer4),
> +	FUNCTION(gcc_gp_clk1),
> +	FUNCTION(gcc_gp_clk2),
> +	FUNCTION(gcc_gp_clk3),
> +	FUNCTION(gp_mn),
> +	FUNCTION(gp_pdm0),
> +	FUNCTION(gp_pdm1),
> +	FUNCTION(gp_pdm2),
> +	FUNCTION(gp0_clk),
> +	FUNCTION(gp1_clk),
> +	FUNCTION(gps_tx),
> +	FUNCTION(grfc),
> +	FUNCTION(gsm_tx),
> +	FUNCTION(hdmi_cec),
> +	FUNCTION(hdmi_ddc),
> +	FUNCTION(hdmi_hpd),
> +	FUNCTION(mdp_vsync),
> +	FUNCTION(mss_lte),
> +	FUNCTION(nav_pps),
> +	FUNCTION(nav_tsync),
> +	FUNCTION(qdss_cti_trig_in_a),
> +	FUNCTION(qdss_cti_trig_in_b),
> +	FUNCTION(qdss_cti_trig_in_c),
> +	FUNCTION(qdss_cti_trig_in_d),
> +	FUNCTION(qdss_cti_trig_out_a),
> +	FUNCTION(qdss_cti_trig_out_b),
> +	FUNCTION(qdss_cti_trig_out_c),
> +	FUNCTION(qdss_cti_trig_out_d),
> +	FUNCTION(qdss_traceclk_a),
> +	FUNCTION(qdss_traceclk_b),
> +	FUNCTION(qdss_tracectl_a),
> +	FUNCTION(qdss_tracectl_b),
> +	FUNCTION(qdss_tracedata_a),
> +	FUNCTION(qdss_tracedata_b),
> +	FUNCTION(qua_mi2s),
> +	FUNCTION(pci_e0),
> +	FUNCTION(pci_e1),
> +	FUNCTION(pri_mi2s),
> +	FUNCTION(rffe1),
> +	FUNCTION(rffe2),
> +	FUNCTION(rffe3),
> +	FUNCTION(rffe4),
> +	FUNCTION(rffe5),
> +	FUNCTION(rffe6),
> +	FUNCTION(rffe7),
> +	FUNCTION(sdc4),
> +	FUNCTION(sec_mi2s),
> +	FUNCTION(slimbus),
> +	FUNCTION(spkr_mi2s),
> +	FUNCTION(ter_mi2s),
> +	FUNCTION(tsif1),
> +	FUNCTION(tsif2),
> +	FUNCTION(uim_batt_alarm),
> +	FUNCTION(uim1),
> +	FUNCTION(uim2),
> +	FUNCTION(uim3),
> +	FUNCTION(uim4),
> +	FUNCTION(gpio),
> +};
> +
> +static const struct msm_pingroup msm8994_groups[] = {
> +	PINGROUP(0,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(1,   blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(2,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(3,   blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(4,   blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti_trig_out_b,
> +		 NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(5,   blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti_trig_in_b, NA,
> +		 NA, NA, NA, NA, NA, NA),
> +	PINGROUP(6,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(7,   blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(8,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA,
> +		 NA, NA, NA, NA, NA),
> +	PINGROUP(9,   blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA,
> +		 NA, NA, NA, NA, NA),
> +	PINGROUP(10,  mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3,
> +		 blsp_spi1_cs3, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(11,  mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3,
> +		 blsp_spi1_cs2, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(12,  mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(13,  cam_mclk0, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(14,  cam_mclk1, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(15,  cam_mclk2, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(16,  cam_mclk3, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(17,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA,
> +		 qdss_tracedata_b, NA, NA, NA, NA, NA),
> +	PINGROUP(18,  cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA,
> +		 qdss_tracedata_b, NA, NA, NA, NA, NA),
> +	PINGROUP(19,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA,
> +		 qdss_tracedata_b, NA, NA, NA, NA, NA),
> +	PINGROUP(20,  cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA,
> +		 NA, NA, NA, NA),
> +	PINGROUP(21,  cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA,
> +		 qdss_tracedata_b, NA, NA, NA, NA, NA),
> +	PINGROUP(22,  cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA,
> +		 qdss_tracedata_b, NA, NA, NA, NA, NA),
> +	PINGROUP(23,  cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA,
> +		 qdss_tracedata_b, NA, NA, NA, NA),
> +	PINGROUP(24,  cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5,
> +		 blsp_i2c5, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(25,  cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6,
> +		 blsp_uim6, NA, NA, qdss_tracedata_b, NA, NA, NA),
> +	PINGROUP(26,  cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, gp0_clk,
> +		 NA, qdss_tracedata_b, NA, NA, NA, NA),
> +	PINGROUP(27,  blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk,
> +		 qdss_tracectl_a, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(28,  blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_a, NA,
> +		 NA, NA, NA, NA, NA, NA),
> +	PINGROUP(29,  gp_mn, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(30,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(31,  hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(32,  hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(33,  hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(34,  hdmi_hpd, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(35,  uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(36,  uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(37,  uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(38,  uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(39,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(40,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(41,  blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_out_c,
> +		 NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(42,  blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_in_c, NA,
> +		 NA, NA, NA, NA, NA, NA),
> +	PINGROUP(43,  blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(44,  blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(45,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(46,  blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(47,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA,
> +		 NA, NA, NA, NA, NA),
> +	PINGROUP(48,  blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA,
> +		 NA, NA, NA, NA, NA),
> +	PINGROUP(49,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(50,  uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(51,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(52,  uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(53,  uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, NA,
> +		 NA, NA, NA, qdss_tracedata_a, NA),
> +	PINGROUP(54,  uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10,
> +		 gp_pdm0, NA, NA, NA, NA, qdss_tracedata_a),
> +	PINGROUP(55,  uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA,
> +		 NA, NA, qdss_cti_trig_in_a, NA),
> +	PINGROUP(56,  uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA,
> +		 NA, qdss_cti_trig_out_a, NA, NA),
> +	PINGROUP(57,  qua_mi2s, gcc_gp_clk1, NA, NA, NA, NA, qdss_tracedata_b,
> +		 NA, NA, NA, NA),
> +	PINGROUP(58,  qua_mi2s, gcc_gp_clk2, NA, NA, NA, NA, qdss_tracedata_b,
> +		 NA, NA, NA, NA),
> +	PINGROUP(59,  qua_mi2s, gcc_gp_clk3, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(60,  qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(61,  qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(62,  qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(63,  qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA, NA,
> +		 qdss_tracedata_a, NA, NA),
> +	PINGROUP(64,  pri_mi2s, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA,
> +		 NA, NA),
> +	PINGROUP(65,  pri_mi2s, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA,
> +		 NA, NA),
> +	PINGROUP(66,  pri_mi2s, blsp_spi2_cs3, NA, NA, NA, NA, NA,
> +		 qdss_tracedata_a, NA, NA, NA),
> +	PINGROUP(67,  pri_mi2s, blsp_spi10_cs1, NA, NA, NA, NA, NA,
> +		 qdss_tracedata_a, NA, NA, NA),
> +	PINGROUP(68,  pri_mi2s, blsp_spi10_cs2, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(69,  spkr_mi2s, audio_ref_clk, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(70,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(71,  slimbus, spkr_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(72,  spkr_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(73,  ter_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(74,  ter_mi2s, gp_pdm1, NA, NA, NA, NA, NA, qdss_tracedata_a,
> +		 NA, NA, NA),
> +	PINGROUP(75,  ter_mi2s, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(76,  ter_mi2s, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(77,  ter_mi2s, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(78,  sec_mi2s, gcc_gp_clk1, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(79,  sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(80,  sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(81,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11,
> +		 gcc_gp_clk2, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(82,  sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11,
> +		 gcc_gp_clk3, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(83,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(84,  blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(85,  blsp_spi12, blsp_uart12, blsp_uim12, NA, NA,
> +		 qdss_tracedata_a, NA, NA, NA, NA, NA),
> +	PINGROUP(86,  blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA,
> +		 qdss_tracedata_a, NA, NA, NA, NA, NA),
> +	PINGROUP(87,  blsp_spi12, blsp_uart12, blsp_i2c12, NA,
> +		 qdss_tracedata_a, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(88,  blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA, NA,
> +		 NA, NA, NA),
> +	PINGROUP(89,  tsif1, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(90,  tsif1, blsp_spi10_cs3, qdss_tracedata_a, NA, NA, NA, NA,
> +		 NA, NA, NA, NA),
> +	PINGROUP(91,  tsif1, sdc4, NA, NA, NA, NA, qdss_traceclk_b, NA, NA, NA,
> +		 NA),
> +	PINGROUP(92,  tsif2, sdc4, NA, NA, qdss_tracedata_b, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(93,  tsif2, sdc4, NA, NA, NA, NA, qdss_tracedata_b, NA, NA,
> +		 NA, NA),
> +	PINGROUP(94,  tsif2, sdc4, NA, NA, NA, NA, qdss_tracectl_b, NA, NA, NA,
> +		 NA),
> +	PINGROUP(95,  tsif2, sdc4, gp_pdm0, NA, NA, NA, qdss_cti_trig_out_d,
> +		 NA, NA, NA, NA),
> +	PINGROUP(96,  tsif2, sdc4, qdss_cti_trig_in_d, NA, NA, NA, NA, NA, NA,
> +		 NA, NA),
> +	PINGROUP(97,  uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(98,  uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(99,  uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(110, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(111, tsif1, blsp11_uart_tx_b, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(112, blsp11_uart_rx_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(113, blsp11_i2c_sda_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(114, blsp11_i2c_scl_b, NA, NA, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(115, grfc, rffe6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(116, grfc, rffe6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(117, grfc, rffe7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(118, grfc, rffe7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(119, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(120, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(121, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(122, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(123, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(124, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(125, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(126, grfc, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(127, grfc, nav_tsync, nav_pps, NA, NA, NA, NA, NA, NA, NA,
> +		 NA),
> +	PINGROUP(128, NA, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(129, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(130, gps_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(131, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(132, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(133, gsm_tx, grfc, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(134, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(135, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(136, rffe1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(137, rffe1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(138, rffe2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(139, rffe2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(140, rffe3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(141, rffe3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(142, rffe4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(143, rffe4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(144, rffe5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	PINGROUP(145, rffe5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
> +	SDC_PINGROUP(sdc1_rclk, 0x2044, 15, 0),
> +	SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6),
> +	SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3),
> +	SDC_PINGROUP(sdc1_data, 0x2044, 9, 0),
> +	SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6),
> +	SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3),
> +	SDC_PINGROUP(sdc2_data, 0x2048, 9, 0),
> +	SDC_PINGROUP(sdc3_clk, 0x206c, 14, 6),
> +	SDC_PINGROUP(sdc3_cmd, 0x206c, 11, 3),
> +	SDC_PINGROUP(sdc3_data, 0x206c, 9, 0),
> +};
> +
> +#define NUM_GPIO_PINGROUPS 146
> +
> +static const struct msm_pinctrl_soc_data msm8994_pinctrl = {
> +	.pins = msm8994_pins,
> +	.npins = ARRAY_SIZE(msm8994_pins),
> +	.functions = msm8994_functions,
> +	.nfunctions = ARRAY_SIZE(msm8994_functions),
> +	.groups = msm8994_groups,
> +	.ngroups = ARRAY_SIZE(msm8994_groups),
> +	.ngpios = NUM_GPIO_PINGROUPS,
> +};
> +
> +static int msm8994_pinctrl_probe(struct platform_device *pdev)
> +{
> +	return msm_pinctrl_probe(pdev, &msm8994_pinctrl);
> +}
> +
> +static const struct of_device_id msm8994_pinctrl_of_match[] = {
> +	{ .compatible = "qcom,msm8994-pinctrl", },
> +	{ },
> +};
> +
> +static struct platform_driver msm8994_pinctrl_driver = {
> +	.driver = {
> +		.name = "msm8994-pinctrl",
> +		.of_match_table = msm8994_pinctrl_of_match,
> +	},
> +	.probe = msm8994_pinctrl_probe,
> +	.remove = msm_pinctrl_remove,
> +};
> +
> +static int __init msm8994_pinctrl_init(void)
> +{
> +	return platform_driver_register(&msm8994_pinctrl_driver);
> +}
> +arch_initcall(msm8994_pinctrl_init);
> +
> +static void __exit msm8994_pinctrl_exit(void)
> +{
> +	platform_driver_unregister(&msm8994_pinctrl_driver);
> +}
> +module_exit(msm8994_pinctrl_exit);
> +
> +MODULE_DESCRIPTION("Qualcomm MSM8994 pinctrl driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DEVICE_TABLE(of, msm8994_pinctrl_of_match);
>


^ permalink raw reply

* Re: [PATCH 02/12] ASoC: dapm: Implement stereo mixer control support
From: Chen-Yu Tsai @ 2016-10-27  1:20 UTC (permalink / raw)
  To: Mark Brown
  Cc: Chen-Yu Tsai, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Rob Herring, Mark Rutland, Russell King, Maxime Ripard,
	Linux-ALSA, linux-arm-kernel, linux-kernel, devicetree,
	linux-sunxi
In-Reply-To: <20161026165753.GC25322-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>

On Thu, Oct 27, 2016 at 12:57 AM, Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Mon, Oct 03, 2016 at 07:07:54PM +0800, Chen-Yu Tsai wrote:
>
>> While DAPM is mono or single channel, its controls can be shared between
>> widgets, such as sharing one stereo mixer control between the left and
>> right channel widgets.
>
>> This patch introduces support for such shared mixer controls.
>
> Based on this changelog I'm really not sure what the intended semantic
> of this change is which makes it difficult to review.  What are you
> expecting these controls to look like and how are you expecting them to
> work?
>
>> -static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i)
>> +static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,
>> +                                    int nth_path)
>
> It looks like the goal is to attach more than one path to a single
> control somehow?

Correct. I'll try to expand the commit log and add an example diagram.

ChenYu

^ permalink raw reply


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