Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v2] soc: qcom: smp2p: Access APCS as mailbox client
From: Bjorn Andersson @ 2017-12-04 20:18 UTC (permalink / raw)
  To: Rob Herring
  Cc: Andy Gross, David Brown, Mark Rutland,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Arun Kumar Neelakantam
In-Reply-To: <20171201222545.hkp73cuou6aildky@rob-hp-laptop>

On Fri 01 Dec 14:25 PST 2017, Rob Herring wrote:

> On Wed, Nov 29, 2017 at 04:00:40PM -0800, Bjorn Andersson wrote:
> > Attempt to acquire the APCS IPC through the mailbox framework and fall
> > back to the old syscon based approach, to allow us to move away from
> > using the syscon.
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > ---
> > 
> > Changes since v1:
> > - Added dt binding update
> > - Specifies knows_txdone on the mailbox client
> > 
> >  .../devicetree/bindings/soc/qcom/qcom,smp2p.txt    |  8 ++++-
> >  drivers/soc/qcom/Kconfig                           |  1 +
> >  drivers/soc/qcom/smp2p.c                           | 39 ++++++++++++++++++----
> >  3 files changed, 41 insertions(+), 7 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt
> > index af9ca37221ce..a35af2dafdad 100644
> > --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt
> > +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt
> > @@ -17,9 +17,15 @@ processor ID) and a string identifier.
> >  	Value type: <prop-encoded-array>
> >  	Definition: one entry specifying the smp2p notification interrupt
> >  
> > -- qcom,ipc:
> > +- mboxes:
> >  	Usage: required
> >  	Value type: <prop-encoded-array>
> > +	Definition: reference to the associated doorbell in APCS, as described
> > +		    in mailbox/mailbox.txt
> > +
> > +- qcom,ipc:
> > +	Usage: required, unless mboxes is specified
> 
> Is this deprecated as mboxes is required, so it's never present?
> 

Right, this required property "mboxes" replaces the previously required
property "qcom,ipc". This comes from migrating the description of APCS
as a syscon to a mailbox/doorbell.

Regards,
Bjorn

> > +	Value type: <prop-encoded-array>
> >  	Definition: three entries specifying the outgoing ipc bit used for
> >  		    signaling the remote end of the smp2p edge:
> >  		    - phandle to a syscon node representing the apcs registers
--
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 2/2] of: dynamic: add overlay-allowed DT property
From: Alan Tull @ 2017-12-04 20:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Frank Rowand, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAL_Jsq+f4q=8rvxndbJNkp5KNMYRoKHs-zKOL1zwXfS0T2A3mA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Mon, Dec 4, 2017 at 2:04 PM, Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Mon, Dec 4, 2017 at 1:13 PM, Alan Tull <atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>> Allow DT nodes to be marked as valid targets for DT
>> overlays by the added "overlay-allowed" property.
>
> Why do you need a property for this? I'm not all that keen on putting
> this policy into the DT. It can change over time in the kernel. For
> example, as we define use cases that work, then we can loosen
> restrictions in the kernel.

For FPGA regions, I don't need it.  Yes, if the other patch is
accepted, I'm sure we will hear more from people who will need some
specific loosening.  I was trying to anticipate that, but I don't have
a specific need.

Alan

>
> 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 2/2] of: dynamic: add overlay-allowed DT property
From: Rob Herring @ 2017-12-04 20:04 UTC (permalink / raw)
  To: Alan Tull
  Cc: Moritz Fischer, Frank Rowand, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171204191357.3211-3-atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

On Mon, Dec 4, 2017 at 1:13 PM, Alan Tull <atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> Allow DT nodes to be marked as valid targets for DT
> overlays by the added "overlay-allowed" property.

Why do you need a property for this? I'm not all that keen on putting
this policy into the DT. It can change over time in the kernel. For
example, as we define use cases that work, then we can loosen
restrictions in the kernel.

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 v2 2/2] of: overlay: Fix cleanup order in of_overlay_apply()
From: Geert Uytterhoeven @ 2017-12-04 19:45 UTC (permalink / raw)
  To: Rob Herring
  Cc: Geert Uytterhoeven, Pantelis Antoniou, Frank Rowand, Colin King,
	Dan Carpenter, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAL_JsqJqb-01rQ6D65-r3Q1ZdF407b11BrVgnUQZPjyTW8hj8A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Rob,

On Mon, Dec 4, 2017 at 8:35 PM, Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Mon, Dec 4, 2017 at 9:47 AM, Geert Uytterhoeven
> <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org> wrote:
>> The special overlay mutex is taken first, hence it should be released
>> last in the error path.
>>
>> Move "mutex_lock(&of_mutex)" up, as suggested by Frank, as
>> free_overlay_changeset() should be called with that mutex held if any
>> non-trivial cleanup is to be done.
>
> Not holding the of_mutex for of_resolve_phandles is just wrong.
> Without it, a node and new phandle could be added via of_attach_node
> making the max phandle wrong.

After my patch it's held, so what's the problem?

> Now, with the 2 mutexes adjacent, what is the point of even having the
> of_overlay_mutex? Seems like we should just drop it.

Frank?

> I also don't think we really need to hold the mutex during post-apply
> notifiers. It also seems like some steps could be moved outside the
> mutex(es) like init_overlay_changeset().

Perhaps.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
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 v2 2/2] ARM: dts: at91: disable the nxp,se97b SMBUS timeout on the TSE-850
From: Alexandre Belloni @ 2017-12-04 19:39 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Rosin, linux-kernel, Rob Herring, Mark Rutland,
	Nicolas Ferre, Russell King, Jean Delvare, Ludovic Desroches,
	devicetree, linux-arm-kernel, linux-hwmon
In-Reply-To: <20171130211740.GA26784@roeck-us.net>

On 30/11/2017 at 13:17:40 -0800, Guenter Roeck wrote:
> > I think it's a bugfix; it fixes real problems where the application
> > misbehave due to faulty content when reading from an eeprom. I'm
> > expecting to make a new release for the hw in question RSN and these
> > are the only local patches. So, it would be nice if they made it to
> > 4.14.x before my release happens. However, it's not like it's difficult
> > to rebase the patches should that backport not happen or take too long.
> > 
> Good enough for me. I'll send it as a fix for v4.15, with Cc: stable.
> 

I have it in my fixes branch too, I'll send it to arm-soc soon.


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

^ permalink raw reply

* Re: [PATCH v2] ARM: dts: at91: add devicetree for the Axentia Nattis with Natte power
From: Alexandre Belloni @ 2017-12-04 19:38 UTC (permalink / raw)
  To: Peter Rosin
  Cc: linux-kernel, Rob Herring, Mark Rutland, Russell King,
	Nicolas Ferre, linux-arm-kernel, devicetree
In-Reply-To: <20171204135708.8234-1-peda@axentia.se>

On 04/12/2017 at 14:57:08 +0100, Peter Rosin wrote:
> The Axentia Nattis is a device designed for presenting departures for
> public transport systems. The Natte helper board provides power and
> features a battery of battery chargers.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>
> ---
> 
> This was part of a two-patch series, but the first patch in that
> series was redundant, so I dropped it (there was a dt binding
> recently added for the tfa9879 amplifier that I had not noticed).
> 
> Changes since v1:    https://lkml.org/lkml/2017/12/1/844
> - removed chip-ids from before the @-sign instead naming the nodes
>   for the function, e.g sx1502q@20 -> ioexp@20
> - added #sound-dai-cells to the amplifier node
> - switch to SPDX license tags
> 
> Cheers,
> Peter
> 
> Documentation/devicetree/bindings/arm/axentia.txt |   9 +
>  MAINTAINERS                                       |   2 +
>  arch/arm/boot/dts/Makefile                        |   1 +
>  arch/arm/boot/dts/at91-natte.dtsi                 | 244 ++++++++++++++++++++
>  arch/arm/boot/dts/at91-nattis-2-natte-2.dts       | 258 ++++++++++++++++++++++
>  5 files changed, 514 insertions(+)
>  create mode 100644 arch/arm/boot/dts/at91-natte.dtsi
>  create mode 100644 arch/arm/boot/dts/at91-nattis-2-natte-2.dts
> 
Applied, thanks.

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

^ permalink raw reply

* Re: [PATCH v2 2/2] of: overlay: Fix cleanup order in of_overlay_apply()
From: Rob Herring @ 2017-12-04 19:35 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Pantelis Antoniou, Frank Rowand, Colin King, Dan Carpenter,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1512402456-8176-3-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>

On Mon, Dec 4, 2017 at 9:47 AM, Geert Uytterhoeven
<geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org> wrote:
> The special overlay mutex is taken first, hence it should be released
> last in the error path.
>
> Move "mutex_lock(&of_mutex)" up, as suggested by Frank, as
> free_overlay_changeset() should be called with that mutex held if any
> non-trivial cleanup is to be done.

Not holding the of_mutex for of_resolve_phandles is just wrong.
Without it, a node and new phandle could be added via of_attach_node
making the max phandle wrong.

Now, with the 2 mutexes adjacent, what is the point of even having the
of_overlay_mutex? Seems like we should just drop it.

I also don't think we really need to hold the mutex during post-apply
notifiers. It also seems like some steps could be moved outside the
mutex(es) like init_overlay_changeset().

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 0/2] of: dynamic: restrict overlay by targets
From: Moritz Fischer @ 2017-12-04 19:20 UTC (permalink / raw)
  To: Moritz Fischer
  Cc: Alan Tull, Rob Herring, Frank Rowand, Pantelis Antoniou,
	devicetree, linux-kernel, linux-fpga
In-Reply-To: <20171204191849.GA17574@tyrael.ni.corp.natinst.com>

On Mon, Dec 04, 2017 at 11:18:49AM -0800, Moritz Fischer wrote:
> On Mon, Dec 04, 2017 at 01:13:55PM -0600, Alan Tull wrote:
> > Restrict which nodes are valid targets for a DT overlay.
> > 
> > Add a flag bit to struct device_node allowing nodes to be marked as
> > valid target for overlays.
> > 
> > A driver that is always intended to handle DT overlays can
> > enable overlays by calling a function for its DT node.
> > 
> > For individual nodes that need to be opened up for a specific use,
> > adding the property "overlay-allowed" enables overlays targeting
> > that node.  I'll need to document the DT property, not sure where
> > specifically.  New file bindings/overlay.txt?
> > 
> > This patchset differs from the RFC:
> > * Added a flag bit and got rid of the whitelist
> > * Renamed the functions that enable a node
> > * Added a DT property
> > 
> > Alan Tull (2):
> >   of: overlay: add flag enabling overlays and enable fpga-region
> >     overlays
> >   of: dynamic: add overlay-allowed DT property
> 
> I think [1/2] and [2/2] are backwards order. If applied like this,
> it won't work. [1/2] uses stuff that gets added in [2/2]

Ignore that, my mailclient is being funny.

Moritz
> 
> > 
> >  drivers/fpga/of-fpga-region.c |  4 ++++
> >  drivers/of/base.c             |  4 ++--
> >  drivers/of/dynamic.c          |  3 +++
> >  drivers/of/fdt.c              |  3 +++
> >  drivers/of/of_private.h       |  2 ++
> >  drivers/of/overlay.c          | 26 ++++++++++++++++++++++++++
> >  include/linux/of.h            | 19 +++++++++++++++++++
> >  7 files changed, 59 insertions(+), 2 deletions(-)
> > 
> > -- 
> > 2.7.4
> > 
> 
> Moritz

^ permalink raw reply

* Re: [PATCH 0/2] of: dynamic: restrict overlay by targets
From: Moritz Fischer @ 2017-12-04 19:18 UTC (permalink / raw)
  To: Alan Tull
  Cc: Moritz Fischer, Rob Herring, Frank Rowand, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171204191357.3211-1-atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

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

On Mon, Dec 04, 2017 at 01:13:55PM -0600, Alan Tull wrote:
> Restrict which nodes are valid targets for a DT overlay.
> 
> Add a flag bit to struct device_node allowing nodes to be marked as
> valid target for overlays.
> 
> A driver that is always intended to handle DT overlays can
> enable overlays by calling a function for its DT node.
> 
> For individual nodes that need to be opened up for a specific use,
> adding the property "overlay-allowed" enables overlays targeting
> that node.  I'll need to document the DT property, not sure where
> specifically.  New file bindings/overlay.txt?
> 
> This patchset differs from the RFC:
> * Added a flag bit and got rid of the whitelist
> * Renamed the functions that enable a node
> * Added a DT property
> 
> Alan Tull (2):
>   of: overlay: add flag enabling overlays and enable fpga-region
>     overlays
>   of: dynamic: add overlay-allowed DT property

I think [1/2] and [2/2] are backwards order. If applied like this,
it won't work. [1/2] uses stuff that gets added in [2/2]

> 
>  drivers/fpga/of-fpga-region.c |  4 ++++
>  drivers/of/base.c             |  4 ++--
>  drivers/of/dynamic.c          |  3 +++
>  drivers/of/fdt.c              |  3 +++
>  drivers/of/of_private.h       |  2 ++
>  drivers/of/overlay.c          | 26 ++++++++++++++++++++++++++
>  include/linux/of.h            | 19 +++++++++++++++++++
>  7 files changed, 59 insertions(+), 2 deletions(-)
> 
> -- 
> 2.7.4
> 

Moritz

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

^ permalink raw reply

* [PATCH 2/2] of: dynamic: add overlay-allowed DT property
From: Alan Tull @ 2017-12-04 19:13 UTC (permalink / raw)
  To: Moritz Fischer, Rob Herring, Frank Rowand, Pantelis Antoniou
  Cc: Alan Tull, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171204191357.3211-1-atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Allow DT nodes to be marked as valid targets for DT
overlays by the added "overlay-allowed" property.

Signed-off-by: Alan Tull <atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/of/base.c       | 4 ++--
 drivers/of/dynamic.c    | 3 +++
 drivers/of/fdt.c        | 3 +++
 drivers/of/of_private.h | 2 ++
 4 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 26618ba..ac6b326 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -116,8 +116,8 @@ void __init of_core_init(void)
 		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
 }
 
-static struct property *__of_find_property(const struct device_node *np,
-					   const char *name, int *lenp)
+struct property *__of_find_property(const struct device_node *np,
+				    const char *name, int *lenp)
 {
 	struct property *pp;
 
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index ab988d8..fae9b85 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -207,6 +207,9 @@ static void __of_attach_node(struct device_node *np)
 	np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
 	np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
 
+	if (__of_find_property(np, "overlay-allowed", NULL))
+		of_node_set_flag(np, OF_OVERLAY_ENABLED);
+
 	phandle = __of_get_property(np, "phandle", &sz);
 	if (!phandle)
 		phandle = __of_get_property(np, "linux,phandle", &sz);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 4675e5a..9237f30 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -323,6 +323,9 @@ static bool populate_node(const void *blob,
 			np->name = "<NULL>";
 		if (!np->type)
 			np->type = "<NULL>";
+
+		if (of_find_property(np, "overlay-allowed", NULL))
+			of_node_set_flag(np, OF_OVERLAY_ENABLED);
 	}
 
 	*pnp = np;
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 92a9a36..75fcba3 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -115,6 +115,8 @@ struct device_node *__of_find_node_by_path(struct device_node *parent,
 struct device_node *__of_find_node_by_full_path(struct device_node *node,
 						const char *path);
 
+extern struct property *__of_find_property(const struct device_node *np,
+					   const char *name, int *lenp);
 extern const void *__of_get_property(const struct device_node *np,
 				     const char *name, int *lenp);
 extern int __of_add_property(struct device_node *np, struct property *prop);
-- 
2.7.4

--
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 1/2] of: overlay: add flag enabling overlays and enable fpga-region overlays
From: Alan Tull @ 2017-12-04 19:13 UTC (permalink / raw)
  To: Moritz Fischer, Rob Herring, Frank Rowand, Pantelis Antoniou
  Cc: Alan Tull, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171204191357.3211-1-atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Add a flag to struct device_node marking the node as a valid target
for device tree overlays.  When an overlay is submitted, if any target
in the overlay is not enabled for overlays, the overlay is rejected.
Drivers that support dynamic configuration can enable/disable their
device node with:

  void of_node_overlay_enable(struct device_node *np)
  void of_node_overlay_disable(struct device_node *np)

During each FPGA region's probe, enable its node for overlays.

Signed-off-by: Alan Tull <atull-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
v1: (changes from the rfc)
    Add a flag instead of implementing a list
    rename functions for what they do, not how they're implemented
    squash with patch that enables fpga-region nodes
    add a helpful error message
---
 drivers/fpga/of-fpga-region.c |  4 ++++
 drivers/of/overlay.c          | 26 ++++++++++++++++++++++++++
 include/linux/of.h            | 19 +++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 119ff75..8633eea 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -438,6 +438,7 @@ static int of_fpga_region_probe(struct platform_device *pdev)
 		goto eprobe_mgr_put;
 
 	of_platform_populate(np, fpga_region_of_match, NULL, &region->dev);
+	of_node_overlay_enable(np);
 
 	dev_info(dev, "FPGA Region probed\n");
 
@@ -451,7 +452,10 @@ static int of_fpga_region_probe(struct platform_device *pdev)
 static int of_fpga_region_remove(struct platform_device *pdev)
 {
 	struct fpga_region *region = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 
+	of_node_overlay_disable(np);
 	fpga_region_unregister(region);
 	fpga_mgr_put(region->mgr);
 
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 53bc9e3..a9758d6 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/idr.h>
+#include <linux/spinlock.h>
 
 #include "of_private.h"
 
@@ -646,6 +647,27 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
 	kfree(ovcs);
 }
 
+static int of_overlay_check_targets(struct overlay_changeset *ovcs)
+{
+	struct device_node *target;
+	int i;
+
+	for (i = 0; i < ovcs->count; i++) {
+		target = ovcs->fragments[i].target;
+
+		if (!of_node_cmp(target->name, "__symbols__"))
+			continue;
+
+		if (!of_node_check_flag(target, OF_OVERLAY_ENABLED)) {
+			pr_err("Overlays not enabled for target %pOF\n",
+			       target);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
 /**
  * of_overlay_apply() - Create and apply an overlay changeset
  * @tree:	Expanded overlay device tree
@@ -717,6 +739,10 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id)
 	if (ret)
 		goto err_free_overlay_changeset;
 
+	ret = of_overlay_check_targets(ovcs);
+	if (ret)
+		goto err_free_overlay_changeset;
+
 	ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
 	if (ret) {
 		pr_err("overlay changeset pre-apply notify error %d\n", ret);
diff --git a/include/linux/of.h b/include/linux/of.h
index d3dea1d..16a2cae 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -147,6 +147,7 @@ extern raw_spinlock_t devtree_lock;
 #define OF_DETACHED	2 /* node has been detached from the device tree */
 #define OF_POPULATED	3 /* device already created for the node */
 #define OF_POPULATED_BUS	4 /* of_platform_populate recursed to children of this node */
+#define OF_OVERLAY_ENABLED	5 /* allow DT overlay targeting this node */
 
 #define OF_BAD_ADDR	((u64)-1)
 
@@ -1364,6 +1365,16 @@ int of_overlay_remove_all(void);
 int of_overlay_notifier_register(struct notifier_block *nb);
 int of_overlay_notifier_unregister(struct notifier_block *nb);
 
+static inline void of_node_overlay_enable(struct device_node *np)
+{
+	of_node_set_flag(np, OF_OVERLAY_ENABLED);
+}
+
+static inline void of_node_overlay_disable(struct device_node *np)
+{
+	of_node_clear_flag(np, OF_OVERLAY_ENABLED);
+}
+
 #else
 
 static inline int of_overlay_apply(struct device_node *tree, int *ovcs_id)
@@ -1391,6 +1402,14 @@ static inline int of_overlay_notifier_unregister(struct notifier_block *nb)
 	return 0;
 }
 
+static inline void of_node_overlay_enable(struct device_node *np)
+{
+}
+
+static inline void of_node_overlay_disable(struct device_node *np)
+{
+}
+
 #endif
 
 #endif /* _LINUX_OF_H */
-- 
2.7.4

--
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 0/2] of: dynamic: restrict overlay by targets
From: Alan Tull @ 2017-12-04 19:13 UTC (permalink / raw)
  To: Moritz Fischer, Rob Herring, Frank Rowand, Pantelis Antoniou
  Cc: Alan Tull, devicetree, linux-kernel, linux-fpga

Restrict which nodes are valid targets for a DT overlay.

Add a flag bit to struct device_node allowing nodes to be marked as
valid target for overlays.

A driver that is always intended to handle DT overlays can
enable overlays by calling a function for its DT node.

For individual nodes that need to be opened up for a specific use,
adding the property "overlay-allowed" enables overlays targeting
that node.  I'll need to document the DT property, not sure where
specifically.  New file bindings/overlay.txt?

This patchset differs from the RFC:
* Added a flag bit and got rid of the whitelist
* Renamed the functions that enable a node
* Added a DT property

Alan Tull (2):
  of: overlay: add flag enabling overlays and enable fpga-region
    overlays
  of: dynamic: add overlay-allowed DT property

 drivers/fpga/of-fpga-region.c |  4 ++++
 drivers/of/base.c             |  4 ++--
 drivers/of/dynamic.c          |  3 +++
 drivers/of/fdt.c              |  3 +++
 drivers/of/of_private.h       |  2 ++
 drivers/of/overlay.c          | 26 ++++++++++++++++++++++++++
 include/linux/of.h            | 19 +++++++++++++++++++
 7 files changed, 59 insertions(+), 2 deletions(-)

-- 
2.7.4

^ permalink raw reply

* Re: [PATCH 3/5] PCI: cadence: Add host driver for Cadence PCIe controller
From: Ard Biesheuvel @ 2017-12-04 18:49 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Cyrille Pitchen, Bjorn Helgaas, kishon, linux-pci, adouglas,
	Scott Telford, dgary, kgopi, eandrews, Thomas Petazzoni, sureshp,
	nsekhar, linux-kernel@vger.kernel.org, Rob Herring,
	devicetree@vger.kernel.org
In-Reply-To: <20171204182013.GA7343@red-moon>

On 4 December 2017 at 18:20, Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
> [+Ard]
>
> Hi Cyrille,
>
> On Sun, Dec 03, 2017 at 09:44:46PM +0100, Cyrille Pitchen wrote:
>
> [...]
>
>> >> +cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, int where)
>> >> +{
>> >> +     struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
>> >> +     struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
>> >> +     struct cdns_pcie *pcie = &rc->pcie;
>> >> +     unsigned int busn = bus->number;
>> >> +     u32 addr0, desc0;
>> >> +
>> >> +     if (busn < rc->bus_range->start || busn > rc->bus_range->end)
>> >> +             return NULL;
>> >
>> > It does not hurt but I wonder whether you really need this check.
>> >
>>
>> I can remove it.
>>
>> >> +     if (busn == rc->bus_range->start) {
>> >> +             if (devfn)
>> >
>> > I suspect I know why you need this check but I ask you to explain it
>> > anyway if you do not mind please.
>> >
>>
>> If I have understood correctly, Cadence team told me that only the root
>> port is available on the first bus through device 0, function 0.
>> No other device/function should connected on this bus, all other devices
>> are behind at least one PCI bridge.
>>
>> I can add a comment here to explain that.
>
> That's understood, the question is what happens if you do scan devfn != 0.
>

OK, this is similar to the Synopsys IP. Type 0 config TLPs are not
filtered by the hardware, and so if you don't filter them in software,
the device downstream of the rootport will appear 32 times.

>> >> +                     return NULL;
>> >> +
>> >> +             return pcie->reg_base + (where & 0xfff);
>> >> +     }
>> >> +
>> >> +     /* Update Output registers for AXI region 0. */
>> >> +     addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
>> >
>> > Ok, so for every config access you reprogram addr0 to reflect the
>> > correct bus|devfn ID in the PCI bus TLP corresponding to an ECAM address
>> > in CPU physical address space, is my understanding correct ?
>> >
>>
>> The idea is to able to use only a 4KB memory area at a fixed address in the
>> space allocated for the PCIe controller in the AXI bus. I guess the plan is
>> to leave more space on the AXI bus to map all other PCIe devices.
>>
>> This is just my guess. Anyway one purpose of this driver was actually to
>> perform all PCI configuration space accesses through this single 4KB memory
>> area in the AXI bus, changing the mapping dynamically to reach the relevant
>> PCI device.
>
> Thank you for explaining - that matches my understanding.
>
>> >> +             CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) |
>> >> +             CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(busn);
>> >> +     cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(0), addr0);
>> >> +
>> >> +     /* Configuration Type 0 or Type 1 access. */
>> >> +     desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
>> >> +             CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
>> >> +     /*
>> >> +      * The bus number was already set once for all in desc1 by
>> >> +      * cdns_pcie_host_init_address_translation().
>> >> +      */
>> >> +     if (busn == rc->bus_range->start + 1)
>> >> +             desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
>> >> +     else
>> >> +             desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
>> >
>> > I would like to ask you why you have to do it here and the root port
>> > does not figure it out by itself, I do not have the datasheet so I am
>> > just asking for my own information.
>>
>> PCI configuration space registers of the root port can only be read through
>> the APB bus at offset 0:
>> ->reg_base + (where & 0xfff)
>>
>> They are internal registers of the PCIe controller so no TLP on the PCIe bus.
>>
>> However to access the PCI configuration space registers of any other device,
>> the PCIe controller builds then sends a TLP on the PCIe bus using the offset
>> in the 4KB AXI area as the offset of the register in the PCI configuration
>> space:
>> ->cfg_base + (where & 0xfff)
>>
>> >
>> >> +     cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0);
>> >> +
>> >> +     return rc->cfg_base + (where & 0xfff);
>> >> +}
>> >> +
>> >> +static struct pci_ops cdns_pcie_host_ops = {
>> >> +     .map_bus        = cdns_pci_map_bus,
>> >> +     .read           = pci_generic_config_read,
>> >> +     .write          = pci_generic_config_write,
>> >> +};
>> >> +
>> >> +static const struct cdns_pcie_rc_data cdns_pcie_rc_data = {
>> >> +     .max_regions    = 32,
>> >> +     .vendor_id      = PCI_VENDOR_ID_CDNS,
>> >> +     .device_id      = 0x0200,
>> >> +     .no_bar_nbits   = 32,
>> >> +};
>> >
>> > Should (some of) these parameters be retrieved through a DT binding ?
>> >
>>
>> Indeed, maybe we get max_regions and no_bar_nbits from the DT.
>>
>> About the vendor and device IDs, I don't know which would be the best
>> choice between some dedicated DT properties or associating a custom
>> structure as above to the 'compatible' string.
>>
>> Honestly, I don't have any strong preference, please just tell me what
>> you would prefer :)
>
> I think it is best to ask DT maintainers (in CC) POV on this, they
> certainly have a more comprehensive view than mine on the subject - I
> have just noticed that _some_ data can be retrieved through DT therefore
> I raised the point - either through different compatible strings or
> some IP specific properties.
>
>> >> +static const struct of_device_id cdns_pcie_host_of_match[] = {
>> >> +     { .compatible = "cdns,cdns-pcie-host",
>> >> +       .data = &cdns_pcie_rc_data },
>> >> +
>> >> +     { },
>> >> +};
>> >> +
>> >> +static int cdns_pcie_parse_request_of_pci_ranges(struct device *dev,
>> >> +                                              struct list_head *resources,
>> >> +                                              struct resource **bus_range)
>> >> +{
>> >> +     int err, res_valid = 0;
>> >> +     struct device_node *np = dev->of_node;
>> >> +     resource_size_t iobase;
>> >> +     struct resource_entry *win, *tmp;
>> >> +
>> >> +     err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
>> >> +     if (err)
>> >> +             return err;
>> >> +
>> >> +     err = devm_request_pci_bus_resources(dev, resources);
>> >> +     if (err)
>> >> +             return err;
>> >> +
>> >> +     resource_list_for_each_entry_safe(win, tmp, resources) {
>> >> +             struct resource *res = win->res;
>> >> +
>> >> +             switch (resource_type(res)) {
>> >> +             case IORESOURCE_IO:
>> >> +                     err = pci_remap_iospace(res, iobase);
>> >> +                     if (err) {
>> >> +                             dev_warn(dev, "error %d: failed to map resource %pR\n",
>> >> +                                      err, res);
>> >> +                             resource_list_destroy_entry(win);
>> >> +                     }
>> >> +                     break;
>> >> +             case IORESOURCE_MEM:
>> >> +                     res_valid |= !(res->flags & IORESOURCE_PREFETCH);
>> >> +                     break;
>> >> +             case IORESOURCE_BUS:
>> >> +                     *bus_range = res;
>> >> +                     break;
>> >> +             }
>> >> +     }
>> >> +
>> >> +     if (res_valid)
>> >> +             return 0;
>> >> +
>> >> +     dev_err(dev, "non-prefetchable memory resource required\n");
>> >> +     return -EINVAL;
>> >
>> > Nit, I prefer you swap these two as it is done in pci-aardvark.c:
>> >
>> >         if (!res_valid) {
>> >                 dev_err(dev, "non-prefetchable memory resource required\n");
>> >                 return -EINVAL;
>> >         }
>> >
>> >         return 0;
>> >
>> > but as per previous replies this function can be factorized in
>> > core PCI code - I would not bother unless you are willing to write
>> > the patch series that does the refactoring yourself :)
>> >
>> >> +}
>> >> +
>> >> +static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
>> >> +{
>> >> +     const struct cdns_pcie_rc_data *data = rc->data;
>> >> +     struct cdns_pcie *pcie = &rc->pcie;
>> >> +     u8 pbn, sbn, subn;
>> >> +     u32 value, ctrl;
>> >> +
>> >> +     /*
>> >> +      * Set the root complex BAR configuration register:
>> >> +      * - disable both BAR0 and BAR1.
>> >> +      * - enable Prefetchable Memory Base and Limit registers in type 1
>> >> +      *   config space (64 bits).
>> >> +      * - enable IO Base and Limit registers in type 1 config
>> >> +      *   space (32 bits).
>> >> +      */
>> >> +     ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
>> >> +     value = CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
>> >> +             CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
>> >> +             CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
>> >> +             CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
>> >> +             CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
>> >> +             CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS;
>> >> +     cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
>> >> +
>> >> +     /* Set root port configuration space */
>> >> +     if (data->vendor_id != 0xffff)
>> >> +             cdns_pcie_rp_writew(pcie, PCI_VENDOR_ID, data->vendor_id);
>> >> +     if (data->device_id != 0xffff)
>> >> +             cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, data->device_id);
>> >> +
>> >> +     cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0);
>> >> +     cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0);
>> >> +     cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
>> >> +
>> >> +     pbn = rc->bus_range->start;
>> >> +     sbn = pbn + 1; /* Single root port. */
>> >> +     subn = rc->bus_range->end;
>> >> +     cdns_pcie_rp_writeb(pcie, PCI_PRIMARY_BUS, pbn);
>> >> +     cdns_pcie_rp_writeb(pcie, PCI_SECONDARY_BUS, sbn);
>> >> +     cdns_pcie_rp_writeb(pcie, PCI_SUBORDINATE_BUS, subn);
>> >
>> > Again - I do not have the datasheet for this device therefore I would
>> > kindly ask you how this works; it seems to me that what you are doing
>> > here is done through normal configuration cycles in an ECAM compliant
>> > system to program the RP PRIMARY/SECONDARY/SUBORDINATE bus - I would
>> > like to understand why this code is needed.
>> >
>>
>> I will test without those lines to test whether I can remove them.
>>
>> At first, the PCIe controller was tested by Cadence team: there was code
>> in their bootloader to initialize the hardware (building the AXI <-> PCIe
>> mappings, ...): the bootloader used to set the primary, secondary and
>> subordinate bus numbers in the root port PCI config space.
>>
>> Also there was a hardware trick to redirect accesses of the lowest
>> addresses in the AXI bus to the APB bus so the PCI configuration space of
>> the root port could have been accessed from the AXI bus too.
>>
>> The AXI <-> PCIe mapping being done by the bootloader and the root port
>> config space being accessible from the AXI bus, it was possible to use
>> the pci-host-generic driver.
>
> That's what I was getting at. Ard (CC'ed) implemented a firmware set-up
> (even though it was for a different IP but maybe it applies here) that
> allows the kernel to use the pci-host-generic driver to initialize the
> PCI controller:
>
> https://marc.info/?l=linux-pci&m=150360022626351&w=2
>
> I want to understand if there is an IP initialization sequence whereby
> this IP can be made to work in an ECAM compliant way and therefore
> reuse (most of) the pci-host-generic driver code.
>

I think the Synopsys case is probably very similar. There are some
registers that look like the config space of a root port, but in
reality, every memory access that hits a live host bridge window is
forwarded onto the link, regardless of the values of the bridge BARs.
That is why in the quoted case, we can get away with ignoring the root
port altogether, rather than jumping through hoops to make the IP
block's PCI config space registers appear at B/D/F 0/0/0, while still
having to filter type 0 config TLPs going onto the link (which is
arguably the job of the root port to begin with)

So if this IP does implement a proper root port (i.e., one where the
bridge BARs are actually taken into account, and where type 0 config
TLPs are in fact filtered), I strongly recommend mapping its config
space registers in an ECAM compliant matter, which implies no
accessors in the OS.

However, given the observation above, this IP does not appear to
filter type 0 config TLPs to devfn > 0 downstream of the root port
either.

>> However, the hardware trick won't be included in the final design since
>> Cadence now wants to perform all PCI configuration space accesses through
>> a small 4KB window at a fixed address on the AXI bus.
>
> I would like to understand what the HW "trick" (if you can disclose it)
> was, because if there is a chance to reuse the pci-host-generic driver
> for this IP I want to take it (yes it may entail some firmware set-up in
> the bootloader) - was it a HW trick or a specific IP SW configuration ?
>
>> Also, we now want all initialisations to be done by the linux driver
>> instead of the bootloader.
>
> That's a choice, I do not necessarily agree with it and I think we
> should aim for more standardization on the PCI host bridge set-up
> at firmware->kernel handover on DT platforms.
>

Well, for one, it means this IP will never be supported by ACPI, which
seems like a huge downside to me.

>> I simply moved all those initialisations from the bootloader to the linux
>> driver but actually there is a chance that I can remove the 3 writes to
>> the PCI_*_BUS registers.
>
> I asked because I do not have this IP documentation so I rely on you to
> provide the correct initialization sequence and an explanation for it,
> I think I understand now the initialization sequence a bit more but it
> would be good to get to the bottom of it.
>

^ permalink raw reply

* Applied "ASoC: spdif: Add S32_LE support for S/PDIF dummy codec drivers" to the asoc tree
From: Mark Brown @ 2017-12-04 18:48 UTC (permalink / raw)
  To: Katsuhiro Suzuki; +Cc: Mark Brown
In-Reply-To: <20171122114321.29196-2-suzuki.katsuhiro@socionext.com>

The patch

   ASoC: spdif: Add S32_LE support for S/PDIF dummy codec drivers

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From eb733366f5f7f416a7d9215a40e00d57aa193361 Mon Sep 17 00:00:00 2001
From: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Date: Wed, 22 Nov 2017 20:43:14 +0900
Subject: [PATCH] ASoC: spdif: Add S32_LE support for S/PDIF dummy codec
 drivers

AIO on UniPhier can output S/PDIF where no codec is needed.
This patch adds S32_LE support for dummy codec drivers.

If one S/PDIF controller has its own limitation, its CPU DAI driver should
set the supported format by its own circumstance, since the soc-pcm driver
will use the intersection of cpu_dai's formats and codec_dai's formats.

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/spdif_receiver.c    | 5 +++--
 sound/soc/codecs/spdif_transmitter.c | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
index 7acd05140a81..c8fd6367f6c0 100644
--- a/sound/soc/codecs/spdif_receiver.c
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -34,10 +34,11 @@ static const struct snd_soc_dapm_route dir_routes[] = {
 #define STUB_RATES	SNDRV_PCM_RATE_8000_192000
 #define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
 			SNDRV_PCM_FMTBIT_S20_3LE | \
-			SNDRV_PCM_FMTBIT_S24_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE  | \
+			SNDRV_PCM_FMTBIT_S32_LE | \
 			SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
 
-static const struct snd_soc_codec_driver soc_codec_spdif_dir = {
+static struct snd_soc_codec_driver soc_codec_spdif_dir = {
 	.component_driver = {
 		.dapm_widgets		= dir_widgets,
 		.num_dapm_widgets	= ARRAY_SIZE(dir_widgets),
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index 063a64ff82d3..037aa1d45559 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -27,7 +27,8 @@
 #define STUB_RATES	SNDRV_PCM_RATE_8000_192000
 #define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
 			SNDRV_PCM_FMTBIT_S20_3LE | \
-			SNDRV_PCM_FMTBIT_S24_LE)
+			SNDRV_PCM_FMTBIT_S24_LE  | \
+			SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dapm_widget dit_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("spdif-out"),
@@ -37,7 +38,7 @@ static const struct snd_soc_dapm_route dit_routes[] = {
 	{ "spdif-out", NULL, "Playback" },
 };
 
-static const struct snd_soc_codec_driver soc_codec_spdif_dit = {
+static struct snd_soc_codec_driver soc_codec_spdif_dit = {
 	.component_driver = {
 		.dapm_widgets		= dit_widgets,
 		.num_dapm_widgets	= ARRAY_SIZE(dit_widgets),
-- 
2.15.0

^ permalink raw reply related

* Applied "ASoC: uniphier: add DT bindings documentation for UniPhier EVEA" to the asoc tree
From: Mark Brown @ 2017-12-04 18:48 UTC (permalink / raw)
  To: Katsuhiro Suzuki
  Cc: Rob Herring, alsa-devel, Masami Hiramatsu, devicetree,
	linux-kernel, Rob Herring, Masahiro Yamada, Mark Brown,
	Jassi Brar, linux-arm-kernel
In-Reply-To: <20171122114321.29196-3-suzuki.katsuhiro@socionext.com>

The patch

   ASoC: uniphier: add DT bindings documentation for UniPhier EVEA

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From e85c8d3e25c09fd9b21ba74e14078ab4c1d977ef Mon Sep 17 00:00:00 2001
From: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Date: Wed, 22 Nov 2017 20:43:15 +0900
Subject: [PATCH] ASoC: uniphier: add DT bindings documentation for UniPhier
 EVEA

This patch adds DT binding documentation for UniPhier EVEA
that is SoC inner sound codec of UniPhier series.

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 .../devicetree/bindings/sound/uniphier,evea.txt    | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/uniphier,evea.txt

diff --git a/Documentation/devicetree/bindings/sound/uniphier,evea.txt b/Documentation/devicetree/bindings/sound/uniphier,evea.txt
new file mode 100644
index 000000000000..3f31b235f18b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/uniphier,evea.txt
@@ -0,0 +1,26 @@
+Socionext EVEA - UniPhier SoC internal codec driver
+
+Required properties:
+- compatible      : should be "socionext,uniphier-evea".
+- reg             : offset and length of the register set for the device.
+- clock-names     : should include following entries:
+                    "evea", "exiv"
+- clocks          : a list of phandle, should contain an entry for each
+                    entries in clock-names.
+- reset-names     : should include following entries:
+                    "evea", "exiv", "adamv"
+- resets          : a list of phandle, should contain reset entries of
+                    reset-names.
+- #sound-dai-cells: should be 1.
+
+Example:
+
+	codec {
+		compatible = "socionext,uniphier-evea";
+		reg = <0x57900000 0x1000>;
+		clock-names = "evea", "exiv";
+		clocks = <&sys_clk 41>, <&sys_clk 42>;
+		reset-names = "evea", "exiv", "adamv";
+		resets = <&sys_rst 41>, <&sys_rst 42>, <&adamv_rst 0>;
+		#sound-dai-cells = <1>;
+	};
-- 
2.15.0

^ permalink raw reply related

* Applied "ASoC: uniphier: add support for UniPhier EVEA codec" to the asoc tree
From: Mark Brown @ 2017-12-04 18:48 UTC (permalink / raw)
  To: Katsuhiro Suzuki; +Cc: Mark Brown
In-Reply-To: <20171122114321.29196-5-suzuki.katsuhiro@socionext.com>

The patch

   ASoC: uniphier: add support for UniPhier EVEA codec

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 3a47b1dfa2913038623cec3164adfb2448269fa6 Mon Sep 17 00:00:00 2001
From: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Date: Wed, 22 Nov 2017 20:43:17 +0900
Subject: [PATCH] ASoC: uniphier: add support for UniPhier EVEA codec

This patch adds EVEA codec driver. This codec core is in inside of
UniPhier SoC.

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/Kconfig           |   1 +
 sound/soc/Makefile          |   1 +
 sound/soc/uniphier/Kconfig  |  19 ++
 sound/soc/uniphier/Makefile |   3 +
 sound/soc/uniphier/evea.c   | 567 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 591 insertions(+)
 create mode 100644 sound/soc/uniphier/Kconfig
 create mode 100644 sound/soc/uniphier/Makefile
 create mode 100644 sound/soc/uniphier/evea.c

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index d22758165496..84c3582f3982 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -71,6 +71,7 @@ source "sound/soc/stm/Kconfig"
 source "sound/soc/sunxi/Kconfig"
 source "sound/soc/tegra/Kconfig"
 source "sound/soc/txx9/Kconfig"
+source "sound/soc/uniphier/Kconfig"
 source "sound/soc/ux500/Kconfig"
 source "sound/soc/xtensa/Kconfig"
 source "sound/soc/zte/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 5327f4d6c668..74cd1858d38b 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_SND_SOC)	+= stm/
 obj-$(CONFIG_SND_SOC)	+= sunxi/
 obj-$(CONFIG_SND_SOC)	+= tegra/
 obj-$(CONFIG_SND_SOC)	+= txx9/
+obj-$(CONFIG_SND_SOC)	+= uniphier/
 obj-$(CONFIG_SND_SOC)	+= ux500/
 obj-$(CONFIG_SND_SOC)	+= xtensa/
 obj-$(CONFIG_SND_SOC)	+= zte/
diff --git a/sound/soc/uniphier/Kconfig b/sound/soc/uniphier/Kconfig
new file mode 100644
index 000000000000..02886a457eaf
--- /dev/null
+++ b/sound/soc/uniphier/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+config SND_SOC_UNIPHIER
+	tristate "ASoC support for UniPhier"
+	depends on (ARCH_UNIPHIER || COMPILE_TEST)
+	help
+	  Say Y or M if you want to add support for the Socionext
+	  UniPhier SoC audio interfaces. You will also need to select the
+	  audio interfaces to support below.
+	  If unsure select "N".
+
+config SND_SOC_UNIPHIER_EVEA_CODEC
+	tristate "UniPhier SoC internal audio codec"
+	depends on SND_SOC_UNIPHIER
+	select REGMAP_MMIO
+	help
+	  This adds Codec driver for Socionext UniPhier LD11/20 SoC
+	  internal DAC. This driver supports Line In / Out and HeadPhone.
+	  Select Y if you use such device.
+	  If unsure select "N".
diff --git a/sound/soc/uniphier/Makefile b/sound/soc/uniphier/Makefile
new file mode 100644
index 000000000000..3be00d72f5e5
--- /dev/null
+++ b/sound/soc/uniphier/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+snd-soc-uniphier-evea-objs := evea.o
+obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o
diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c
new file mode 100644
index 000000000000..0cc9efff1d9a
--- /dev/null
+++ b/sound/soc/uniphier/evea.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Socionext UniPhier EVEA ADC/DAC codec driver.
+ *
+ * Copyright (c) 2016-2017 Socionext Inc.
+ *
+ * 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; version 2
+ * of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#define DRV_NAME        "evea"
+#define EVEA_RATES      SNDRV_PCM_RATE_48000
+#define EVEA_FORMATS    SNDRV_PCM_FMTBIT_S32_LE
+
+#define AADCPOW(n)                           (0x0078 + 0x04 * (n))
+#define   AADCPOW_AADC_POWD                   BIT(0)
+#define AHPOUTPOW                            0x0098
+#define   AHPOUTPOW_HP_ON                     BIT(4)
+#define ALINEPOW                             0x009c
+#define   ALINEPOW_LIN2_POWD                  BIT(3)
+#define   ALINEPOW_LIN1_POWD                  BIT(4)
+#define ALO1OUTPOW                           0x00a8
+#define   ALO1OUTPOW_LO1_ON                   BIT(4)
+#define ALO2OUTPOW                           0x00ac
+#define   ALO2OUTPOW_ADAC2_MUTE               BIT(0)
+#define   ALO2OUTPOW_LO2_ON                   BIT(4)
+#define AANAPOW                              0x00b8
+#define   AANAPOW_A_POWD                      BIT(4)
+#define ADACSEQ1(n)                          (0x0144 + 0x40 * (n))
+#define   ADACSEQ1_MMUTE                      BIT(1)
+#define ADACSEQ2(n)                          (0x0160 + 0x40 * (n))
+#define   ADACSEQ2_ADACIN_FIX                 BIT(0)
+#define ADAC1ODC                             0x0200
+#define   ADAC1ODC_HP_DIS_RES_MASK            GENMASK(2, 1)
+#define   ADAC1ODC_HP_DIS_RES_OFF             (0x0 << 1)
+#define   ADAC1ODC_HP_DIS_RES_ON              (0x3 << 1)
+#define   ADAC1ODC_ADAC_RAMPCLT_MASK          GENMASK(8, 7)
+#define   ADAC1ODC_ADAC_RAMPCLT_NORMAL        (0x0 << 7)
+#define   ADAC1ODC_ADAC_RAMPCLT_REDUCE        (0x1 << 7)
+
+struct evea_priv {
+	struct clk *clk, *clk_exiv;
+	struct reset_control *rst, *rst_exiv, *rst_adamv;
+	struct regmap *regmap;
+
+	int switch_lin;
+	int switch_lo;
+	int switch_hp;
+};
+
+static const struct snd_soc_dapm_widget evea_widgets[] = {
+	SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_INPUT("LIN1_LP"),
+	SND_SOC_DAPM_INPUT("LIN1_RP"),
+	SND_SOC_DAPM_INPUT("LIN2_LP"),
+	SND_SOC_DAPM_INPUT("LIN2_RP"),
+	SND_SOC_DAPM_INPUT("LIN3_LP"),
+	SND_SOC_DAPM_INPUT("LIN3_RP"),
+
+	SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_OUTPUT("HP1_L"),
+	SND_SOC_DAPM_OUTPUT("HP1_R"),
+	SND_SOC_DAPM_OUTPUT("LO2_L"),
+	SND_SOC_DAPM_OUTPUT("LO2_R"),
+};
+
+static const struct snd_soc_dapm_route evea_routes[] = {
+	{ "ADC", NULL, "LIN1_LP" },
+	{ "ADC", NULL, "LIN1_RP" },
+	{ "ADC", NULL, "LIN2_LP" },
+	{ "ADC", NULL, "LIN2_RP" },
+	{ "ADC", NULL, "LIN3_LP" },
+	{ "ADC", NULL, "LIN3_RP" },
+
+	{ "HP1_L", NULL, "DAC" },
+	{ "HP1_R", NULL, "DAC" },
+	{ "LO2_L", NULL, "DAC" },
+	{ "LO2_R", NULL, "DAC" },
+};
+
+static void evea_set_power_state_on(struct evea_priv *evea)
+{
+	struct regmap *map = evea->regmap;
+
+	regmap_update_bits(map, AANAPOW, AANAPOW_A_POWD,
+			   AANAPOW_A_POWD);
+
+	regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
+			   ADAC1ODC_HP_DIS_RES_ON);
+
+	regmap_update_bits(map, ADAC1ODC, ADAC1ODC_ADAC_RAMPCLT_MASK,
+			   ADAC1ODC_ADAC_RAMPCLT_REDUCE);
+
+	regmap_update_bits(map, ADACSEQ2(0), ADACSEQ2_ADACIN_FIX, 0);
+	regmap_update_bits(map, ADACSEQ2(1), ADACSEQ2_ADACIN_FIX, 0);
+	regmap_update_bits(map, ADACSEQ2(2), ADACSEQ2_ADACIN_FIX, 0);
+}
+
+static void evea_set_power_state_off(struct evea_priv *evea)
+{
+	struct regmap *map = evea->regmap;
+
+	regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
+			   ADAC1ODC_HP_DIS_RES_ON);
+
+	regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE,
+			   ADACSEQ1_MMUTE);
+	regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE,
+			   ADACSEQ1_MMUTE);
+	regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE,
+			   ADACSEQ1_MMUTE);
+
+	regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 0);
+	regmap_update_bits(map, ALO2OUTPOW, ALO2OUTPOW_LO2_ON, 0);
+	regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 0);
+}
+
+static int evea_update_switch_lin(struct evea_priv *evea)
+{
+	struct regmap *map = evea->regmap;
+
+	if (evea->switch_lin) {
+		regmap_update_bits(map, ALINEPOW,
+				   ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD,
+				   ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD);
+
+		regmap_update_bits(map, AADCPOW(0), AADCPOW_AADC_POWD,
+				   AADCPOW_AADC_POWD);
+		regmap_update_bits(map, AADCPOW(1), AADCPOW_AADC_POWD,
+				   AADCPOW_AADC_POWD);
+	} else {
+		regmap_update_bits(map, AADCPOW(0), AADCPOW_AADC_POWD, 0);
+		regmap_update_bits(map, AADCPOW(1), AADCPOW_AADC_POWD, 0);
+
+		regmap_update_bits(map, ALINEPOW,
+				   ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD, 0);
+	}
+
+	return 0;
+}
+
+static int evea_update_switch_lo(struct evea_priv *evea)
+{
+	struct regmap *map = evea->regmap;
+
+	if (evea->switch_lo) {
+		regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE, 0);
+		regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE, 0);
+
+		regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON,
+				   ALO1OUTPOW_LO1_ON);
+		regmap_update_bits(map, ALO2OUTPOW,
+				   ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON,
+				   ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON);
+	} else {
+		regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE,
+				   ADACSEQ1_MMUTE);
+		regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE,
+				   ADACSEQ1_MMUTE);
+
+		regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 0);
+		regmap_update_bits(map, ALO2OUTPOW,
+				   ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON,
+				   0);
+	}
+
+	return 0;
+}
+
+static int evea_update_switch_hp(struct evea_priv *evea)
+{
+	struct regmap *map = evea->regmap;
+
+	if (evea->switch_hp) {
+		regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE, 0);
+
+		regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON,
+				   AHPOUTPOW_HP_ON);
+
+		regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
+				   ADAC1ODC_HP_DIS_RES_OFF);
+	} else {
+		regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
+				   ADAC1ODC_HP_DIS_RES_ON);
+
+		regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE,
+				   ADACSEQ1_MMUTE);
+
+		regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 0);
+	}
+
+	return 0;
+}
+
+static void evea_update_switch_all(struct evea_priv *evea)
+{
+	evea_update_switch_lin(evea);
+	evea_update_switch_lo(evea);
+	evea_update_switch_hp(evea);
+}
+
+static int evea_get_switch_lin(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = evea->switch_lin;
+
+	return 0;
+}
+
+static int evea_set_switch_lin(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	if (evea->switch_lin == ucontrol->value.integer.value[0])
+		return 0;
+
+	evea->switch_lin = ucontrol->value.integer.value[0];
+
+	return evea_update_switch_lin(evea);
+}
+
+static int evea_get_switch_lo(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = evea->switch_lo;
+
+	return 0;
+}
+
+static int evea_set_switch_lo(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	if (evea->switch_lo == ucontrol->value.integer.value[0])
+		return 0;
+
+	evea->switch_lo = ucontrol->value.integer.value[0];
+
+	return evea_update_switch_lo(evea);
+}
+
+static int evea_get_switch_hp(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = evea->switch_hp;
+
+	return 0;
+}
+
+static int evea_set_switch_hp(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	if (evea->switch_hp == ucontrol->value.integer.value[0])
+		return 0;
+
+	evea->switch_hp = ucontrol->value.integer.value[0];
+
+	return evea_update_switch_hp(evea);
+}
+
+static const struct snd_kcontrol_new eva_controls[] = {
+	SOC_SINGLE_BOOL_EXT("Line Capture Switch", 0,
+			    evea_get_switch_lin, evea_set_switch_lin),
+	SOC_SINGLE_BOOL_EXT("Line Playback Switch", 0,
+			    evea_get_switch_lo, evea_set_switch_lo),
+	SOC_SINGLE_BOOL_EXT("Headphone Playback Switch", 0,
+			    evea_get_switch_hp, evea_set_switch_hp),
+};
+
+static int evea_codec_probe(struct snd_soc_codec *codec)
+{
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	evea->switch_lin = 1;
+	evea->switch_lo = 1;
+	evea->switch_hp = 1;
+
+	evea_set_power_state_on(evea);
+	evea_update_switch_all(evea);
+
+	return 0;
+}
+
+static int evea_codec_suspend(struct snd_soc_codec *codec)
+{
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+
+	evea_set_power_state_off(evea);
+
+	reset_control_assert(evea->rst_adamv);
+	reset_control_assert(evea->rst_exiv);
+	reset_control_assert(evea->rst);
+
+	clk_disable_unprepare(evea->clk_exiv);
+	clk_disable_unprepare(evea->clk);
+
+	return 0;
+}
+
+static int evea_codec_resume(struct snd_soc_codec *codec)
+{
+	struct evea_priv *evea = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = clk_prepare_enable(evea->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(evea->clk_exiv);
+	if (ret)
+		goto err_out_clock;
+
+	ret = reset_control_deassert(evea->rst);
+	if (ret)
+		goto err_out_clock_exiv;
+
+	ret = reset_control_deassert(evea->rst_exiv);
+	if (ret)
+		goto err_out_reset;
+
+	ret = reset_control_deassert(evea->rst_adamv);
+	if (ret)
+		goto err_out_reset_exiv;
+
+	evea_set_power_state_on(evea);
+	evea_update_switch_all(evea);
+
+	return 0;
+
+err_out_reset_exiv:
+	reset_control_assert(evea->rst_exiv);
+
+err_out_reset:
+	reset_control_assert(evea->rst);
+
+err_out_clock_exiv:
+	clk_disable_unprepare(evea->clk_exiv);
+
+err_out_clock:
+	clk_disable_unprepare(evea->clk);
+
+	return ret;
+}
+
+static struct snd_soc_codec_driver soc_codec_evea = {
+	.probe   = evea_codec_probe,
+	.suspend = evea_codec_suspend,
+	.resume  = evea_codec_resume,
+
+	.component_driver = {
+		.dapm_widgets = evea_widgets,
+		.num_dapm_widgets = ARRAY_SIZE(evea_widgets),
+		.dapm_routes = evea_routes,
+		.num_dapm_routes = ARRAY_SIZE(evea_routes),
+		.controls = eva_controls,
+		.num_controls = ARRAY_SIZE(eva_controls),
+	},
+};
+
+static struct snd_soc_dai_driver soc_dai_evea[] = {
+	{
+		.name     = DRV_NAME "-line1",
+		.playback = {
+			.stream_name  = "Line Out 1",
+			.formats      = EVEA_FORMATS,
+			.rates        = EVEA_RATES,
+			.channels_min = 2,
+			.channels_max = 2,
+		},
+		.capture = {
+			.stream_name  = "Line In 1",
+			.formats      = EVEA_FORMATS,
+			.rates        = EVEA_RATES,
+			.channels_min = 2,
+			.channels_max = 2,
+		},
+	},
+	{
+		.name     = DRV_NAME "-hp1",
+		.playback = {
+			.stream_name  = "Headphone 1",
+			.formats      = EVEA_FORMATS,
+			.rates        = EVEA_RATES,
+			.channels_min = 2,
+			.channels_max = 2,
+		},
+	},
+	{
+		.name     = DRV_NAME "-lo2",
+		.playback = {
+			.stream_name  = "Line Out 2",
+			.formats      = EVEA_FORMATS,
+			.rates        = EVEA_RATES,
+			.channels_min = 2,
+			.channels_max = 2,
+		},
+	},
+};
+
+static const struct regmap_config evea_regmap_config = {
+	.reg_bits      = 32,
+	.reg_stride    = 4,
+	.val_bits      = 32,
+	.max_register  = 0xffc,
+	.cache_type    = REGCACHE_NONE,
+};
+
+static int evea_probe(struct platform_device *pdev)
+{
+	struct evea_priv *evea;
+	struct resource *res;
+	void __iomem *preg;
+	int ret;
+
+	evea = devm_kzalloc(&pdev->dev, sizeof(struct evea_priv), GFP_KERNEL);
+	if (!evea)
+		return -ENOMEM;
+
+	evea->clk = devm_clk_get(&pdev->dev, "evea");
+	if (IS_ERR(evea->clk))
+		return PTR_ERR(evea->clk);
+
+	evea->clk_exiv = devm_clk_get(&pdev->dev, "exiv");
+	if (IS_ERR(evea->clk_exiv))
+		return PTR_ERR(evea->clk_exiv);
+
+	evea->rst = devm_reset_control_get_shared(&pdev->dev, "evea");
+	if (IS_ERR(evea->rst))
+		return PTR_ERR(evea->rst);
+
+	evea->rst_exiv = devm_reset_control_get_shared(&pdev->dev, "exiv");
+	if (IS_ERR(evea->rst_exiv))
+		return PTR_ERR(evea->rst_exiv);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	preg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(preg))
+		return PTR_ERR(preg);
+
+	evea->regmap = devm_regmap_init_mmio(&pdev->dev, preg,
+					     &evea_regmap_config);
+	if (IS_ERR(evea->regmap))
+		return PTR_ERR(evea->regmap);
+
+	ret = clk_prepare_enable(evea->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(evea->clk_exiv);
+	if (ret)
+		goto err_out_clock;
+
+	ret = reset_control_deassert(evea->rst);
+	if (ret)
+		goto err_out_clock_exiv;
+
+	ret = reset_control_deassert(evea->rst_exiv);
+	if (ret)
+		goto err_out_reset;
+
+	/* ADAMV will hangup if EXIV reset is asserted */
+	evea->rst_adamv = devm_reset_control_get_shared(&pdev->dev, "adamv");
+	if (IS_ERR(evea->rst_adamv)) {
+		ret = PTR_ERR(evea->rst_adamv);
+		goto err_out_reset_exiv;
+	}
+
+	ret = reset_control_deassert(evea->rst_adamv);
+	if (ret)
+		goto err_out_reset_exiv;
+
+	platform_set_drvdata(pdev, evea);
+
+	ret = snd_soc_register_codec(&pdev->dev, &soc_codec_evea,
+				     soc_dai_evea, ARRAY_SIZE(soc_dai_evea));
+	if (ret)
+		goto err_out_reset_adamv;
+
+	return 0;
+
+err_out_reset_adamv:
+	reset_control_assert(evea->rst_adamv);
+
+err_out_reset_exiv:
+	reset_control_assert(evea->rst_exiv);
+
+err_out_reset:
+	reset_control_assert(evea->rst);
+
+err_out_clock_exiv:
+	clk_disable_unprepare(evea->clk_exiv);
+
+err_out_clock:
+	clk_disable_unprepare(evea->clk);
+
+	return ret;
+}
+
+static int evea_remove(struct platform_device *pdev)
+{
+	struct evea_priv *evea = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_codec(&pdev->dev);
+
+	reset_control_assert(evea->rst_adamv);
+	reset_control_assert(evea->rst_exiv);
+	reset_control_assert(evea->rst);
+
+	clk_disable_unprepare(evea->clk_exiv);
+	clk_disable_unprepare(evea->clk);
+
+	return 0;
+}
+
+static const struct of_device_id evea_of_match[] = {
+	{ .compatible = "socionext,uniphier-evea", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, evea_of_match);
+
+static struct platform_driver evea_codec_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = of_match_ptr(evea_of_match),
+	},
+	.probe  = evea_probe,
+	.remove = evea_remove,
+};
+module_platform_driver(evea_codec_driver);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier EVEA codec driver");
+MODULE_LICENSE("GPL v2");
-- 
2.15.0

^ permalink raw reply related

* Applied "MAINTAINERS: add entries for UniPhier ASoC sound drivers" to the asoc tree
From: Mark Brown @ 2017-12-04 18:48 UTC (permalink / raw)
  To: Katsuhiro Suzuki; +Cc: Mark Brown
In-Reply-To: <20171122114321.29196-8-suzuki.katsuhiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>

The patch

   MAINTAINERS: add entries for UniPhier ASoC sound drivers

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 576f8f46e7c923f830dfa61924ad547447399b05 Mon Sep 17 00:00:00 2001
From: Katsuhiro Suzuki <suzuki.katsuhiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>
Date: Wed, 22 Nov 2017 20:43:20 +0900
Subject: [PATCH] MAINTAINERS: add entries for UniPhier ASoC sound drivers

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52fd76..55ae8ea8722a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12581,6 +12581,12 @@ F:	include/media/soc*
 F:	drivers/media/i2c/soc_camera/
 F:	drivers/media/platform/soc_camera/
 
+SOCIONEXT UNIPHIER SOUND DRIVER
+M:	Katsuhiro Suzuki <suzuki.katsuhiro-uWyLwvC0a2jby3iVrkZq2A@public.gmane.org>
+L:	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org (moderated for non-subscribers)
+S:	Maintained
+F:	sound/soc/uniphier/
+
 SOEKRIS NET48XX LED SUPPORT
 M:	Chris Boot <bootc-1Slo4GeK4H1eoWH0uzbU5w@public.gmane.org>
 S:	Maintained
-- 
2.15.0

--
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 v7 2/2] leds: lm3692x: Introduce LM3692x dual string driver
From: Dan Murphy @ 2017-12-04 18:41 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	rpurdie-Fm38FmjxZ/leoWH0uzbU5w,
	jacek.anaszewski-Re5JQEeQqe8AvxtiuMwx3w, pavel-+ZI9xUNit7I
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-leds-u79uwXL29TY76Z2rM5mHXA, Dan Murphy
In-Reply-To: <20171204184107.682-1-dmurphy-l0cyMroinI0@public.gmane.org>

Introducing the LM3692x Dual-String white LED driver.

Data sheet is located
http://www.ti.com/lit/ds/snvsa29/snvsa29.pdf

Signed-off-by: Dan Murphy <dmurphy-l0cyMroinI0@public.gmane.org>
---

v7 - Reverted back to creating the LED label within the driver -
https://patchwork.kernel.org/patch/10087473/

v6 - Use new LED API to compose LED label as opposed to creating it. -
https://patchwork.kernel.org/patch/10085565/
v5 - Added OF dependency in Kconfig, added extra fault flag read to ensure that
if a fault exists and it is not a artifact, fixed LED class label to be derived
from either the DT child "label" node or create a label based on 
parent_node_name:led color:trigger, removed ifdef for CONFIG_OF and removed
of_match_ptr - https://patchwork.kernel.org/patch/10081073/
v4 - Converted to devm led class register, changed MODULE_LICENSE to GPL v2, 
set the led name based on child node name or label entry, removed fault and
returned read_buf for fault checking, added mutex_destroy to remove function,
and removed LED_FULL - https://patchwork.kernel.org/patch/10060109/
v3 - Add missing Makefile and Kconfig from v1 and v2 - https://patchwork.kernel.org/patch/10060075/
v2 - Added data sheet link, fixed linuxdoc format, returned on failure in init
routine, return on fault_check failure, updated brightness calculation and
fixed capitalization issue - https://patchwork.kernel.org/patch/10056675/

 drivers/leds/Kconfig        |   7 +
 drivers/leds/Makefile       |   1 +
 drivers/leds/leds-lm3692x.c | 393 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 401 insertions(+)
 create mode 100644 drivers/leds/leds-lm3692x.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 318a28fd58fe..1d215b39cefd 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -137,6 +137,13 @@ config LEDS_LM3642
 	  converter plus 1.5A constant current driver for a high-current
 	  white LED.
 
+config LEDS_LM3692X
+	tristate "LED support for LM3692x Chips"
+	depends on LEDS_CLASS && I2C && OF
+	select REGMAP_I2C
+	help
+	  This option enables support for the TI LM3692x family
+	  of white LED string drivers used for backlighting.
 
 config LEDS_LOCOMO
 	tristate "LED Support for Locomo device"
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a2a6b5a4f86d..987884a5b9a5 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_LEDS_PM8058)		+= leds-pm8058.o
 obj-$(CONFIG_LEDS_MLXCPLD)		+= leds-mlxcpld.o
 obj-$(CONFIG_LEDS_NIC78BX)		+= leds-nic78bx.o
 obj-$(CONFIG_LEDS_MT6323)		+= leds-mt6323.o
+obj-$(CONFIG_LEDS_LM3692X)		+= leds-lm3692x.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
new file mode 100644
index 000000000000..e18f12009612
--- /dev/null
+++ b/drivers/leds/leds-lm3692x.c
@@ -0,0 +1,393 @@
+/*
+ * TI lm3692x LED Driver
+ *
+ * Copyright (C) 2017 Texas Instruments
+ *
+ * Author: Dan Murphy <dmurphy-l0cyMroinI0@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * Data sheet is located
+ * http://www.ti.com/lit/ds/snvsa29/snvsa29.pdf
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/slab.h>
+#include <uapi/linux/uleds.h>
+
+#define LM3692X_REV		0x0
+#define LM3692X_RESET		0x1
+#define LM3692X_EN		0x10
+#define LM3692X_BRT_CTRL	0x11
+#define LM3692X_PWM_CTRL	0x12
+#define LM3692X_BOOST_CTRL	0x13
+#define LM3692X_AUTO_FREQ_HI	0x15
+#define LM3692X_AUTO_FREQ_LO	0x16
+#define LM3692X_BL_ADJ_THRESH	0x17
+#define LM3692X_BRT_LSB		0x18
+#define LM3692X_BRT_MSB		0x19
+#define LM3692X_FAULT_CTRL	0x1e
+#define LM3692X_FAULT_FLAGS	0x1f
+
+#define LM3692X_SW_RESET	BIT(0)
+#define LM3692X_DEVICE_EN	BIT(0)
+#define LM3692X_LED1_EN		BIT(1)
+#define LM3692X_LED2_EN		BIT(2)
+
+/* Brightness Control Bits */
+#define LM3692X_BL_ADJ_POL	BIT(0)
+#define LM3692X_RAMP_RATE_125us	0x00
+#define LM3692X_RAMP_RATE_250us	BIT(1)
+#define LM3692X_RAMP_RATE_500us BIT(2)
+#define LM3692X_RAMP_RATE_1ms	(BIT(1) | BIT(2))
+#define LM3692X_RAMP_RATE_2ms	BIT(3)
+#define LM3692X_RAMP_RATE_4ms	(BIT(3) | BIT(1))
+#define LM3692X_RAMP_RATE_8ms	(BIT(2) | BIT(3))
+#define LM3692X_RAMP_RATE_16ms	(BIT(1) | BIT(2) | BIT(3))
+#define LM3692X_RAMP_EN		BIT(4)
+#define LM3692X_BRHT_MODE_REG	0x00
+#define LM3692X_BRHT_MODE_PWM	BIT(5)
+#define LM3692X_BRHT_MODE_MULTI_RAMP BIT(6)
+#define LM3692X_BRHT_MODE_RAMP_MULTI (BIT(5) | BIT(6))
+#define LM3692X_MAP_MODE_EXP	BIT(7)
+
+/* PWM Register Bits */
+#define LM3692X_PWM_FILTER_100	BIT(0)
+#define LM3692X_PWM_FILTER_150	BIT(1)
+#define LM3692X_PWM_FILTER_200	(BIT(0) | BIT(1))
+#define LM3692X_PWM_HYSTER_1LSB BIT(2)
+#define LM3692X_PWM_HYSTER_2LSB	BIT(3)
+#define LM3692X_PWM_HYSTER_3LSB (BIT(3) | BIT(2))
+#define LM3692X_PWM_HYSTER_4LSB BIT(4)
+#define LM3692X_PWM_HYSTER_5LSB (BIT(4) | BIT(2))
+#define LM3692X_PWM_HYSTER_6LSB (BIT(4) | BIT(3))
+#define LM3692X_PWM_POLARITY	BIT(5)
+#define LM3692X_PWM_SAMP_4MHZ	BIT(6)
+#define LM3692X_PWM_SAMP_24MHZ	BIT(7)
+
+/* Boost Control Bits */
+#define LM3692X_OCP_PROT_1A	BIT(0)
+#define LM3692X_OCP_PROT_1_25A	BIT(1)
+#define LM3692X_OCP_PROT_1_5A	(BIT(0) | BIT(1))
+#define LM3692X_OVP_21V		BIT(2)
+#define LM3692X_OVP_25V		BIT(3)
+#define LM3692X_OVP_29V		(BIT(2) | BIT(3))
+#define LM3692X_MIN_IND_22UH	BIT(4)
+#define LM3692X_BOOST_SW_1MHZ	BIT(5)
+#define LM3692X_BOOST_SW_NO_SHIFT	BIT(6)
+
+/* Fault Control Bits */
+#define LM3692X_FAULT_CTRL_OVP BIT(0)
+#define LM3692X_FAULT_CTRL_OCP BIT(1)
+#define LM3692X_FAULT_CTRL_TSD BIT(2)
+#define LM3692X_FAULT_CTRL_OPEN BIT(3)
+
+/* Fault Flag Bits */
+#define LM3692X_FAULT_FLAG_OVP BIT(0)
+#define LM3692X_FAULT_FLAG_OCP BIT(1)
+#define LM3692X_FAULT_FLAG_TSD BIT(2)
+#define LM3692X_FAULT_FLAG_SHRT BIT(3)
+#define LM3692X_FAULT_FLAG_OPEN BIT(4)
+
+/**
+ * struct lm3692x_led -
+ * @lock - Lock for reading/writing the device
+ * @client - Pointer to the I2C client
+ * @led_dev - LED class device pointer
+ * @regmap - Devices register map
+ * @enable_gpio - VDDIO/EN gpio to enable communication interface
+ * @regulator - LED supply regulator pointer
+ * @label - LED label
+ */
+struct lm3692x_led {
+	struct mutex lock;
+	struct i2c_client *client;
+	struct led_classdev led_dev;
+	struct regmap *regmap;
+	struct gpio_desc *enable_gpio;
+	struct regulator *regulator;
+	char label[LED_MAX_NAME_SIZE];
+};
+
+static const struct reg_default lm3692x_reg_defs[] = {
+	{LM3692X_EN, 0xf},
+	{LM3692X_BRT_CTRL, 0x61},
+	{LM3692X_PWM_CTRL, 0x73},
+	{LM3692X_BOOST_CTRL, 0x6f},
+	{LM3692X_AUTO_FREQ_HI, 0x0},
+	{LM3692X_AUTO_FREQ_LO, 0x0},
+	{LM3692X_BL_ADJ_THRESH, 0x0},
+	{LM3692X_BRT_LSB, 0x7},
+	{LM3692X_BRT_MSB, 0xff},
+	{LM3692X_FAULT_CTRL, 0x7},
+};
+
+static const struct regmap_config lm3692x_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = LM3692X_FAULT_FLAGS,
+	.reg_defaults = lm3692x_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(lm3692x_reg_defs),
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int lm3692x_fault_check(struct lm3692x_led *led)
+{
+	int ret;
+	unsigned int read_buf;
+
+	ret = regmap_read(led->regmap, LM3692X_FAULT_FLAGS, &read_buf);
+	if (ret)
+		return ret;
+
+	if (read_buf)
+		dev_err(&led->client->dev, "Detected a fault 0x%X\n", read_buf);
+
+	/* The first read may clear the fault.  Check again to see if the fault
+	 * still exits and return that value.
+	 */
+	regmap_read(led->regmap, LM3692X_FAULT_FLAGS, &read_buf);
+	if (read_buf)
+		dev_err(&led->client->dev, "Second read of fault flags 0x%X\n",
+			read_buf);
+
+	return read_buf;
+}
+
+static int lm3692x_brightness_set(struct led_classdev *led_cdev,
+				enum led_brightness brt_val)
+{
+	struct lm3692x_led *led =
+			container_of(led_cdev, struct lm3692x_led, led_dev);
+	int ret;
+	int led_brightness_lsb = (brt_val >> 5);
+
+	mutex_lock(&led->lock);
+
+	ret = lm3692x_fault_check(led);
+	if (ret) {
+		dev_err(&led->client->dev, "Cannot read/clear faults\n");
+		goto out;
+	}
+
+	ret = regmap_write(led->regmap, LM3692X_BRT_MSB, brt_val);
+	if (ret) {
+		dev_err(&led->client->dev, "Cannot write MSB\n");
+		goto out;
+	}
+
+	ret = regmap_write(led->regmap, LM3692X_BRT_LSB, led_brightness_lsb);
+	if (ret) {
+		dev_err(&led->client->dev, "Cannot write LSB\n");
+		goto out;
+	}
+out:
+	mutex_unlock(&led->lock);
+	return ret;
+}
+
+static int lm3692x_init(struct lm3692x_led *led)
+{
+	int ret;
+
+	if (led->regulator) {
+		ret = regulator_enable(led->regulator);
+		if (ret) {
+			dev_err(&led->client->dev,
+				"Failed to enable regulator\n");
+			return ret;
+		}
+	}
+
+	if (led->enable_gpio)
+		gpiod_direction_output(led->enable_gpio, 1);
+
+	ret = lm3692x_fault_check(led);
+	if (ret) {
+		dev_err(&led->client->dev, "Cannot read/clear faults\n");
+		goto out;
+	}
+
+	ret = regmap_write(led->regmap, LM3692X_BRT_CTRL, 0x00);
+	if (ret)
+		goto out;
+
+	/*
+	 * For glitch free operation, the following data should
+	 * only be written while device enable bit is 0
+	 * per Section 7.5.14 of the data sheet
+	 */
+	ret = regmap_write(led->regmap, LM3692X_PWM_CTRL,
+		LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(led->regmap, LM3692X_BOOST_CTRL,
+			LM3692X_BRHT_MODE_RAMP_MULTI |
+			LM3692X_BL_ADJ_POL |
+			LM3692X_RAMP_RATE_250us);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(led->regmap, LM3692X_AUTO_FREQ_HI, 0x00);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(led->regmap, LM3692X_AUTO_FREQ_LO, 0x00);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(led->regmap, LM3692X_BL_ADJ_THRESH, 0x00);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(led->regmap, LM3692X_BRT_CTRL,
+			LM3692X_BL_ADJ_POL | LM3692X_PWM_HYSTER_4LSB);
+	if (ret)
+		goto out;
+
+	return ret;
+out:
+	dev_err(&led->client->dev, "Fail writing initialization values\n");
+
+	if (led->enable_gpio)
+		gpiod_direction_output(led->enable_gpio, 0);
+
+	if (led->regulator) {
+		ret = regulator_disable(led->regulator);
+		if (ret)
+			dev_err(&led->client->dev,
+				"Failed to disable regulator\n");
+	}
+
+	return ret;
+}
+
+static int lm3692x_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct lm3692x_led *led;
+	struct device_node *np = client->dev.of_node;
+	struct device_node *child_node;
+	const char *name;
+
+	led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	for_each_available_child_of_node(np, child_node) {
+		led->led_dev.default_trigger = of_get_property(child_node,
+						    "linux,default-trigger",
+						    NULL);
+
+		ret = of_property_read_string(child_node, "label", &name);
+		if (!ret)
+		    snprintf(led->label, sizeof(led->label), "%s:%s",
+					np->name, name);
+		else
+		    snprintf(led->label, sizeof(led->label),
+			     "%s::backlight_cluster", np->name);
+	};
+
+	led->enable_gpio = devm_gpiod_get_optional(&client->dev,
+						   "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(led->enable_gpio)) {
+		ret = PTR_ERR(led->enable_gpio);
+		dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret);
+		return ret;
+	}
+
+	led->regulator = devm_regulator_get(&client->dev, "vled");
+	if (IS_ERR(led->regulator))
+		led->regulator = NULL;
+
+	led->client = client;
+	led->led_dev.name = led->label;
+	led->led_dev.brightness_set_blocking = lm3692x_brightness_set;
+
+	mutex_init(&led->lock);
+
+	i2c_set_clientdata(client, led);
+
+	led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config);
+	if (IS_ERR(led->regmap)) {
+		ret = PTR_ERR(led->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = lm3692x_init(led);
+	if (ret)
+		return ret;
+
+	ret = devm_led_classdev_register(&client->dev, &led->led_dev);
+	if (ret) {
+		dev_err(&client->dev, "led register err: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lm3692x_remove(struct i2c_client *client)
+{
+	struct lm3692x_led *led = i2c_get_clientdata(client);
+	int ret;
+
+	if (led->enable_gpio)
+		gpiod_direction_output(led->enable_gpio, 0);
+
+	if (led->regulator) {
+		ret = regulator_disable(led->regulator);
+		if (ret)
+			dev_err(&led->client->dev,
+				"Failed to disable regulator\n");
+	}
+
+	mutex_destroy(&led->lock);
+
+	return 0;
+}
+
+static const struct i2c_device_id lm3692x_id[] = {
+	{ "lm36922", 0 },
+	{ "lm36923", 1 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lm3692x_id);
+
+static const struct of_device_id of_lm3692x_leds_match[] = {
+	{ .compatible = "ti,lm36922", },
+	{ .compatible = "ti,lm36923", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_lm3692x_leds_match);
+
+static struct i2c_driver lm3692x_driver = {
+	.driver = {
+		.name	= "lm3692x",
+		.of_match_table = of_lm3692x_leds_match,
+	},
+	.probe		= lm3692x_probe,
+	.remove		= lm3692x_remove,
+	.id_table	= lm3692x_id,
+};
+module_i2c_driver(lm3692x_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LM3692X LED driver");
+MODULE_AUTHOR("Dan Murphy <dmurphy-l0cyMroinI0@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.15.0.124.g7668cbc60

--
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 v7 1/2] dt: bindings: lm3692x: Add bindings for lm3692x LED driver
From: Dan Murphy @ 2017-12-04 18:41 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	rpurdie-Fm38FmjxZ/leoWH0uzbU5w,
	jacek.anaszewski-Re5JQEeQqe8AvxtiuMwx3w, pavel-+ZI9xUNit7I
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-leds-u79uwXL29TY76Z2rM5mHXA, Dan Murphy

This adds the devicetree bindings for the LM3692x
I2C LED string driver.

Acked-by: Pavel Machek <pavel-+ZI9xUNit7I@public.gmane.org>
Signed-off-by: Dan Murphy <dmurphy-l0cyMroinI0@public.gmane.org>
---

v7 - No changes - https://patchwork.kernel.org/patch/10087475/
v6 - No changes -https://patchwork.kernel.org/patch/10085567/
v5 - No Changes - https://patchwork.kernel.org/patch/10081071/
v4 - Fix example node, added trigger entry, removed ambiguous x for compatible and
added common.txt pointer for label - https://patchwork.kernel.org/patch/10060107
v3 - No changes
v2 - No changes - https://patchwork.kernel.org/patch/10056677/

 .../devicetree/bindings/leds/leds-lm3692x.txt      | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-lm3692x.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
new file mode 100644
index 000000000000..c259cde2226f
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
@@ -0,0 +1,39 @@
+* Texas Instruments - LM3692x Highly Efficient White LED Driver
+
+The LM3692x is an ultra-compact, highly efficient,
+white-LED driver designed for LCD display backlighting.
+
+The main difference between the LM36922 and LM36923 is the number of
+LED strings it supports.  The LM36922 supports two strings while the LM36923
+supports three strings.
+
+Required properties:
+	- compatible:
+		"ti,lm36922"
+		"ti,lm36923"
+	- reg :  I2C slave address
+
+Optional properties:
+	- label : see Documentation/devicetree/bindings/leds/common.txt
+	- enable-gpios : gpio pin to enable/disable the device.
+	- vled-supply : LED supply
+	- linux,default-trigger : (optional)
+	   see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+
+lm3692x@36 {
+	compatible = "ti,lm3692x";
+	reg = <0x36>;
+
+	enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+	vled-supply = <&vbatt>;
+
+	backlight: backlight@0 {
+		label = "backlight_cluster";
+		linux,default-trigger = "backlight";
+	};
+}
+
+For more product information please see the link below:
+http://www.ti.com/lit/ds/snvsa29/snvsa29.pdf
-- 
2.15.0.124.g7668cbc60

--
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 5/8] ASoC: uniphier: add support for UniPhier AIO driver
From: Mark Brown @ 2017-12-04 18:39 UTC (permalink / raw)
  To: Katsuhiro Suzuki
  Cc: devicetree, alsa-devel, Masami Hiramatsu, Masahiro Yamada,
	linux-kernel, Jassi Brar, Rob Herring, linux-arm-kernel
In-Reply-To: <20171122114321.29196-6-suzuki.katsuhiro@socionext.com>


[-- Attachment #1.1: Type: text/plain, Size: 3925 bytes --]

On Wed, Nov 22, 2017 at 08:43:18PM +0900, Katsuhiro Suzuki wrote:

>  sound/soc/uniphier/Makefile      |   4 +
>  sound/soc/uniphier/aio-core.c    | 368 +++++++++++++++++++++
>  sound/soc/uniphier/aio-dma.c     | 266 +++++++++++++++
>  sound/soc/uniphier/aio-regctrl.c | 699 +++++++++++++++++++++++++++++++++++++++
>  sound/soc/uniphier/aio-regctrl.h | 495 +++++++++++++++++++++++++++
>  sound/soc/uniphier/aio.h         | 261 +++++++++++++++

Please split this up more, it looks like there's at least two or three
drivers in here and it winds up being quite large.  There's at least a
DMA and a DAI driver.  Looking through this my overall impression is
that this is a fairly large and complex audio subsystem with some DSP
and routing capacity which is being handled in a board specific fashion
rather than generically but it's kind of hard to tell as there's not
much description of what's going on so I'm needing to reverse engineer
things from the driver.

The code itself looks fairly clean, it's mainly a case of trying to
figure out if it's doing what it's supposed to with the limited
documentation.

> +int uniphier_aio_hw_params(struct snd_pcm_substream *substream,
> +			   struct snd_pcm_hw_params *params,
> +			   struct snd_soc_dai *dai)
> +{
> +	struct uniphier_aio *aio = uniphier_priv(dai);
> +	struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
> +
> +	sub->params = *params;
> +	sub->setting = 1;

So we don't validate the params at all?

> +	uniphier_aio_port_reset(sub);
> +	uniphier_aio_srcport_reset(sub);

Is there a mux in the SoC here?

> +static const struct of_device_id uniphier_aio_of_match[] = {
> +#ifdef CONFIG_SND_SOC_UNIPHIER_LD11
> +	{
> +		.compatible = "socionext,uniphier-ld11-aio",
> +		.data = &uniphier_aio_ld11_spec,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld20-aio",
> +		.data = &uniphier_aio_ld20_spec,
> +	},
> +#endif /* CONFIG_SND_SOC_UNIPHIER_LD11 */

Why is there an ifdef here?  There's no other conditional code in here,
it seems pointless.

> +		for (j = 0; j < ARRAY_SIZE(aio->sub); j++) {
> +			struct uniphier_aio_sub *sub = &aio->sub[j];
> +
> +			if (!sub->running)
> +				continue;
> +
> +			spin_lock(&sub->spin);
> +			uniphier_aio_rb_sync(sub);
> +			uniphier_aio_rb_clear_int(sub);
> +			spin_unlock(&sub->spin);

It's not 100% obvious what this does...  a comment might help.

> +int uniphier_aio_chip_init(struct uniphier_aio_chip *chip)
> +{
> +	struct regmap *r = chip->regmap;
> +
> +	regmap_update_bits(r, A2APLLCTR0,
> +			   A2APLLCTR0_APLLXPOW_MASK,
> +			   A2APLLCTR0_APLLXPOW_PWON);
> +
> +	regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLL_MASK,
> +			   A2APLLCTR1_APLLF2_33MHZ | A2APLLCTR1_APLLA2_33MHZ |
> +			   A2APLLCTR1_APLLF1_36MHZ | A2APLLCTR1_APLLA1_36MHZ);
> +
> +	regmap_update_bits(r, A2EXMCLKSEL0,
> +			   A2EXMCLKSEL0_EXMCLK_MASK,
> +			   A2EXMCLKSEL0_EXMCLK_OUTPUT);
> +
> +	regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
> +			   A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
> +			   A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
> +			   A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
> +			   A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);

This definitely looks like there's some clocking and audio routing
within the SoC which should be exposed to userspace, or at the very
least machine driver configuration rather than being hard coded.

> +	switch (pc) {
> +	case IEC61937_PC_AC3:
> +		repet = OPORTMXREPET_STRLENGTH_AC3 |
> +			OPORTMXREPET_PMLENGTH_AC3;
> +		pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
> +		break;
> +	case IEC61937_PC_MPA:
> +		repet = OPORTMXREPET_STRLENGTH_MPA |
> +			OPORTMXREPET_PMLENGTH_MPA;
> +		pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
> +		break;
> +	case IEC61937_PC_MP3:
> +		repet = OPORTMXREPET_STRLENGTH_MP3 |
> +			OPORTMXREPET_PMLENGTH_MP3;
> +		pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
> +		break;

This looks awfully like compressed audio support...  should there be
integration with the compressed audio API/

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

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Re: [PATCH 4/8] ASoC: uniphier: add support for UniPhier EVEA codec
From: Mark Brown @ 2017-12-04 18:20 UTC (permalink / raw)
  To: Katsuhiro Suzuki
  Cc: devicetree, alsa-devel, Masami Hiramatsu, Masahiro Yamada,
	linux-kernel, Jassi Brar, Rob Herring, linux-arm-kernel
In-Reply-To: <20171122114321.29196-5-suzuki.katsuhiro@socionext.com>


[-- Attachment #1.1: Type: text/plain, Size: 494 bytes --]

On Wed, Nov 22, 2017 at 08:43:17PM +0900, Katsuhiro Suzuki wrote:

> +++ b/sound/soc/uniphier/evea.c
> @@ -0,0 +1,567 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Socionext UniPhier EVEA ADC/DAC codec driver.
> + *
> + * Copyright (c) 2016-2017 Socionext Inc.

Make the entire comment a C++ comment, don't mix and match like this -
it's ugly.  Otherwise this looks good so I'll apply it, please send a
followup patch fixing this (and I guess the same thing will apply to
other files).

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

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Re: [PATCH 3/5] PCI: cadence: Add host driver for Cadence PCIe controller
From: Lorenzo Pieralisi @ 2017-12-04 18:20 UTC (permalink / raw)
  To: Cyrille Pitchen
  Cc: bhelgaas, kishon, linux-pci, adouglas, stelford, dgary, kgopi,
	eandrews, thomas.petazzoni, sureshp, nsekhar, linux-kernel, robh,
	devicetree, ard.biesheuvel
In-Reply-To: <f870ad14-0bd5-9d7b-78f2-1e7f663d1127@free-electrons.com>

[+Ard]

Hi Cyrille,

On Sun, Dec 03, 2017 at 09:44:46PM +0100, Cyrille Pitchen wrote:

[...]

> >> +cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, int where)
> >> +{
> >> +     struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
> >> +     struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
> >> +     struct cdns_pcie *pcie = &rc->pcie;
> >> +     unsigned int busn = bus->number;
> >> +     u32 addr0, desc0;
> >> +
> >> +     if (busn < rc->bus_range->start || busn > rc->bus_range->end)
> >> +             return NULL;
> > 
> > It does not hurt but I wonder whether you really need this check.
> >
> 
> I can remove it.
>  
> >> +     if (busn == rc->bus_range->start) {
> >> +             if (devfn)
> > 
> > I suspect I know why you need this check but I ask you to explain it
> > anyway if you do not mind please.
> >
> 
> If I have understood correctly, Cadence team told me that only the root
> port is available on the first bus through device 0, function 0.
> No other device/function should connected on this bus, all other devices
> are behind at least one PCI bridge.
> 
> I can add a comment here to explain that.

That's understood, the question is what happens if you do scan devfn != 0.

> >> +                     return NULL;
> >> +
> >> +             return pcie->reg_base + (where & 0xfff);
> >> +     }
> >> +
> >> +     /* Update Output registers for AXI region 0. */
> >> +     addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
> > 
> > Ok, so for every config access you reprogram addr0 to reflect the
> > correct bus|devfn ID in the PCI bus TLP corresponding to an ECAM address
> > in CPU physical address space, is my understanding correct ?
> >
> 
> The idea is to able to use only a 4KB memory area at a fixed address in the
> space allocated for the PCIe controller in the AXI bus. I guess the plan is
> to leave more space on the AXI bus to map all other PCIe devices.
> 
> This is just my guess. Anyway one purpose of this driver was actually to
> perform all PCI configuration space accesses through this single 4KB memory
> area in the AXI bus, changing the mapping dynamically to reach the relevant
> PCI device. 

Thank you for explaining - that matches my understanding.

> >> +             CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) |
> >> +             CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(busn);
> >> +     cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(0), addr0);
> >> +
> >> +     /* Configuration Type 0 or Type 1 access. */
> >> +     desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
> >> +             CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
> >> +     /*
> >> +      * The bus number was already set once for all in desc1 by
> >> +      * cdns_pcie_host_init_address_translation().
> >> +      */
> >> +     if (busn == rc->bus_range->start + 1)
> >> +             desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
> >> +     else
> >> +             desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
> > 
> > I would like to ask you why you have to do it here and the root port
> > does not figure it out by itself, I do not have the datasheet so I am
> > just asking for my own information.
> 
> PCI configuration space registers of the root port can only be read through
> the APB bus at offset 0:
> ->reg_base + (where & 0xfff)
> 
> They are internal registers of the PCIe controller so no TLP on the PCIe bus.
> 
> However to access the PCI configuration space registers of any other device,
> the PCIe controller builds then sends a TLP on the PCIe bus using the offset
> in the 4KB AXI area as the offset of the register in the PCI configuration
> space:
> ->cfg_base + (where & 0xfff)
> 
> > 
> >> +     cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0);
> >> +
> >> +     return rc->cfg_base + (where & 0xfff);
> >> +}
> >> +
> >> +static struct pci_ops cdns_pcie_host_ops = {
> >> +     .map_bus        = cdns_pci_map_bus,
> >> +     .read           = pci_generic_config_read,
> >> +     .write          = pci_generic_config_write,
> >> +};
> >> +
> >> +static const struct cdns_pcie_rc_data cdns_pcie_rc_data = {
> >> +     .max_regions    = 32,
> >> +     .vendor_id      = PCI_VENDOR_ID_CDNS,
> >> +     .device_id      = 0x0200,
> >> +     .no_bar_nbits   = 32,
> >> +};
> > 
> > Should (some of) these parameters be retrieved through a DT binding ?
> >
> 
> Indeed, maybe we get max_regions and no_bar_nbits from the DT.
> 
> About the vendor and device IDs, I don't know which would be the best
> choice between some dedicated DT properties or associating a custom
> structure as above to the 'compatible' string.
> 
> Honestly, I don't have any strong preference, please just tell me what
> you would prefer :)

I think it is best to ask DT maintainers (in CC) POV on this, they
certainly have a more comprehensive view than mine on the subject - I
have just noticed that _some_ data can be retrieved through DT therefore
I raised the point - either through different compatible strings or
some IP specific properties.

> >> +static const struct of_device_id cdns_pcie_host_of_match[] = {
> >> +     { .compatible = "cdns,cdns-pcie-host",
> >> +       .data = &cdns_pcie_rc_data },
> >> +
> >> +     { },
> >> +};
> >> +
> >> +static int cdns_pcie_parse_request_of_pci_ranges(struct device *dev,
> >> +                                              struct list_head *resources,
> >> +                                              struct resource **bus_range)
> >> +{
> >> +     int err, res_valid = 0;
> >> +     struct device_node *np = dev->of_node;
> >> +     resource_size_t iobase;
> >> +     struct resource_entry *win, *tmp;
> >> +
> >> +     err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
> >> +     if (err)
> >> +             return err;
> >> +
> >> +     err = devm_request_pci_bus_resources(dev, resources);
> >> +     if (err)
> >> +             return err;
> >> +
> >> +     resource_list_for_each_entry_safe(win, tmp, resources) {
> >> +             struct resource *res = win->res;
> >> +
> >> +             switch (resource_type(res)) {
> >> +             case IORESOURCE_IO:
> >> +                     err = pci_remap_iospace(res, iobase);
> >> +                     if (err) {
> >> +                             dev_warn(dev, "error %d: failed to map resource %pR\n",
> >> +                                      err, res);
> >> +                             resource_list_destroy_entry(win);
> >> +                     }
> >> +                     break;
> >> +             case IORESOURCE_MEM:
> >> +                     res_valid |= !(res->flags & IORESOURCE_PREFETCH);
> >> +                     break;
> >> +             case IORESOURCE_BUS:
> >> +                     *bus_range = res;
> >> +                     break;
> >> +             }
> >> +     }
> >> +
> >> +     if (res_valid)
> >> +             return 0;
> >> +
> >> +     dev_err(dev, "non-prefetchable memory resource required\n");
> >> +     return -EINVAL;
> > 
> > Nit, I prefer you swap these two as it is done in pci-aardvark.c:
> > 
> >         if (!res_valid) {
> >                 dev_err(dev, "non-prefetchable memory resource required\n");
> >                 return -EINVAL;
> >         }
> > 
> >         return 0;
> > 
> > but as per previous replies this function can be factorized in
> > core PCI code - I would not bother unless you are willing to write
> > the patch series that does the refactoring yourself :)
> > 
> >> +}
> >> +
> >> +static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
> >> +{
> >> +     const struct cdns_pcie_rc_data *data = rc->data;
> >> +     struct cdns_pcie *pcie = &rc->pcie;
> >> +     u8 pbn, sbn, subn;
> >> +     u32 value, ctrl;
> >> +
> >> +     /*
> >> +      * Set the root complex BAR configuration register:
> >> +      * - disable both BAR0 and BAR1.
> >> +      * - enable Prefetchable Memory Base and Limit registers in type 1
> >> +      *   config space (64 bits).
> >> +      * - enable IO Base and Limit registers in type 1 config
> >> +      *   space (32 bits).
> >> +      */
> >> +     ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
> >> +     value = CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
> >> +             CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
> >> +             CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
> >> +             CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
> >> +             CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
> >> +             CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS;
> >> +     cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
> >> +
> >> +     /* Set root port configuration space */
> >> +     if (data->vendor_id != 0xffff)
> >> +             cdns_pcie_rp_writew(pcie, PCI_VENDOR_ID, data->vendor_id);
> >> +     if (data->device_id != 0xffff)
> >> +             cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, data->device_id);
> >> +
> >> +     cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0);
> >> +     cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0);
> >> +     cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
> >> +
> >> +     pbn = rc->bus_range->start;
> >> +     sbn = pbn + 1; /* Single root port. */
> >> +     subn = rc->bus_range->end;
> >> +     cdns_pcie_rp_writeb(pcie, PCI_PRIMARY_BUS, pbn);
> >> +     cdns_pcie_rp_writeb(pcie, PCI_SECONDARY_BUS, sbn);
> >> +     cdns_pcie_rp_writeb(pcie, PCI_SUBORDINATE_BUS, subn);
> > 
> > Again - I do not have the datasheet for this device therefore I would
> > kindly ask you how this works; it seems to me that what you are doing
> > here is done through normal configuration cycles in an ECAM compliant
> > system to program the RP PRIMARY/SECONDARY/SUBORDINATE bus - I would
> > like to understand why this code is needed.
> >
> 
> I will test without those lines to test whether I can remove them.
> 
> At first, the PCIe controller was tested by Cadence team: there was code
> in their bootloader to initialize the hardware (building the AXI <-> PCIe
> mappings, ...): the bootloader used to set the primary, secondary and
> subordinate bus numbers in the root port PCI config space.
> 
> Also there was a hardware trick to redirect accesses of the lowest
> addresses in the AXI bus to the APB bus so the PCI configuration space of
> the root port could have been accessed from the AXI bus too.
> 
> The AXI <-> PCIe mapping being done by the bootloader and the root port
> config space being accessible from the AXI bus, it was possible to use
> the pci-host-generic driver.

That's what I was getting at. Ard (CC'ed) implemented a firmware set-up
(even though it was for a different IP but maybe it applies here) that
allows the kernel to use the pci-host-generic driver to initialize the
PCI controller:

https://marc.info/?l=linux-pci&m=150360022626351&w=2

I want to understand if there is an IP initialization sequence whereby
this IP can be made to work in an ECAM compliant way and therefore
reuse (most of) the pci-host-generic driver code.

> However, the hardware trick won't be included in the final design since
> Cadence now wants to perform all PCI configuration space accesses through
> a small 4KB window at a fixed address on the AXI bus.

I would like to understand what the HW "trick" (if you can disclose it)
was, because if there is a chance to reuse the pci-host-generic driver
for this IP I want to take it (yes it may entail some firmware set-up in
the bootloader) - was it a HW trick or a specific IP SW configuration ?

> Also, we now want all initialisations to be done by the linux driver
> instead of the bootloader.

That's a choice, I do not necessarily agree with it and I think we
should aim for more standardization on the PCI host bridge set-up
at firmware->kernel handover on DT platforms.

> I simply moved all those initialisations from the bootloader to the linux
> driver but actually there is a chance that I can remove the 3 writes to
> the PCI_*_BUS registers.

I asked because I do not have this IP documentation so I rely on you to
provide the correct initialization sequence and an explanation for it,
I think I understand now the initialization sequence a bit more but it
would be good to get to the bottom of it.

Thank you,
Lorenzo

^ permalink raw reply

* Re: [PATCH net-next 1/2 v6] net: ethernet: Add DT bindings for the Gemini ethernet
From: Hans Ulli Kroll @ 2017-12-04 18:06 UTC (permalink / raw)
  To: Linus Walleij
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David S . Miller,
	Michał Mirosław, Janos Laube, Paulius Zaleckas,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Hans Ulli Kroll, Florian Fainelli,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Tobias Waldvogel
In-Reply-To: <20171202110640.5284-1-linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 900 bytes --]

Hi Linus

On Sat, 2 Dec 2017, Linus Walleij wrote:

> This adds the device tree bindings for the Gemini ethernet
> controller. It is pretty straight-forward, using standard
> bindings and modelling the two child ports as child devices
> under the parent ethernet controller device.
> 
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: Tobias Waldvogel <tobias.waldvogel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Michał Mirosław <mirq-linux-CoA6ZxLDdyEEUmgCuDUIdw@public.gmane.org>
> Signed-off-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  .../bindings/net/cortina,gemini-ethernet.txt       | 92 ++++++++++++++++++++++
>  1 file changed, 92 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt
>

Acked-by: Hans Ulli Kroll <ulli.kroll-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

^ permalink raw reply

* Re: [PATCH V5 4/7] OF: properties: Implement get_match_data() callback
From: Sinan Kaya @ 2017-12-04 18:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: open list:DMA GENERIC OFFLOAD ENGINE SUBSYSTEM, Timur Tabi,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-arm-msm,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Frank Rowand, open list
In-Reply-To: <CAL_JsqJ+fMqrt6Tk8h6v1fSkrBg+GcMxSXK9XCcz3nmYgyguuQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 12/4/2017 11:23 AM, Rob Herring wrote:
> On Fri, Dec 1, 2017 at 10:27 PM, Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
>> Now that we have a get_match_data() callback as part of the firmware node,
>> implement the OF specific piece for it.
>>
>> Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> ---
>>  drivers/of/property.c | 17 +++++++++++++++++
>>  1 file changed, 17 insertions(+)
>>
..

>>
>> +void *of_fwnode_get_match_data(const struct fwnode_handle *fwnode,
>> +                              const struct device_driver *drv)
>> +{
>> +       const struct device_node *node = to_of_node(fwnode);
>> +       const struct of_device_id *match;
>> +
>> +       if (!node)
>> +               return NULL;
> 
> of_match_node checks this.

I see a check for the matches argument but not for the node argument.
Am I missing something?

> 
>> +
>> +       match = of_match_node(drv->of_match_table, node);
>> +       if (!match)
>> +               return NULL;
>> +
>> +       return (void *)match->data;
> 
> Don't need a cast here.

I can fix this.

> 
> of_device_get_match_data() already does most of this, but getting a
> device ptr from fwnode_handle may not be possible?

I couldn't figure out how to do that. Do you have a suggestion?
I have been looking for examples with no luck.

> 
> Rob
> 


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
--
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 v6 01/10] arm64: dts: rockchip: Enable edp disaplay on kevin
From: Heiko Stuebner @ 2017-12-04 17:59 UTC (permalink / raw)
  To: Jeffy Chen
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	briannorris-F7+t8E8rja9g9hUCZPvPmw,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw, dianders-F7+t8E8rja9g9hUCZPvPmw,
	tfiga-F7+t8E8rja9g9hUCZPvPmw, Matthias Kaehlcke, Arnd Bergmann,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Yao,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Will Deacon,
	Mark Rutland, Caesar Wang, Catalin Marinas
In-Reply-To: <20171019034812.13768-2-jeffy.chen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

Am Donnerstag, 19. Oktober 2017, 11:48:03 CET schrieb Jeffy Chen:
> Add edp panel and enable related nodes on kevin.
> 
> Signed-off-by: Jeffy Chen <jeffy.chen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> Reviewed-by: Mark Yao <mark.yao-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

applied for 4.16 with Enric's Tested-tag and after also
seeing a bit of output on the edp.


Thanks
Heiko
--
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


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