Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v1 4/4] ARM: dts: Enable interrupt support for cygnus crmu gpio driver
From: Florian Fainelli @ 2016-11-16 20:50 UTC (permalink / raw)
  To: Jonathan Richardson, Jassi Brar
  Cc: Rob Herring, Mark Rutland, Ray Jui, Scott Branden, Jon Mason,
	Russell King, Vikram Prakash, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	BCM Kernel Feedback
In-Reply-To: <1476817238-1226-5-git-send-email-jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

On 10/18/2016 12:00 PM, Jonathan Richardson wrote:
> The M0 processor handles interrupts for the always-on CRMU GPIO
> controller. Setting the CRMU GPIO driver with the mailbox controller as
> the interrupt parent allows the mailbox controller to forward interrupts
> from the M0 to the GPIO driver for processing.
> 
> Reviewed-by: Jonathan Richardson <jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Tested-by: Jonathan Richardson <jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Vikram Prakash <vikram.prakash-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Shreesha Rajashekar <shreesha.rajashekar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Ray Jui <ray.jui-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Scott Branden <scott.branden-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Jonathan Richardson <jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

Applied, thanks
-- 
Florian
--
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 v1 3/3] ARM: dts: Add node for Broadcom OTP controller driver
From: Florian Fainelli @ 2016-11-16 20:51 UTC (permalink / raw)
  To: Jonathan Richardson, Srinivas Kandagatla, Maxime Ripard
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Rob Herring,
	Scott Branden, Ray Jui,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
	Jonathan Richardson, Scott Branden, Oza Pawandeep
In-Reply-To: <1477336324-10543-4-git-send-email-jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

On 10/24/2016 12:12 PM, Jonathan Richardson wrote:
> From: Jonathan Richardson <jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> 
> Reviewed-by: Ray Jui <ray.jui-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Tested-by: Jonathan Richardson <jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Scott Branden <scott.branden-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Oza Pawandeep <oza-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Jonathan Richardson <jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

Applied, thanks
-- 
Florian
--
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 devicetree/next] ARM: BCM5301X: Add DT for TP-LINK Archer C9 V1
From: Florian Fainelli @ 2016-11-16 20:52 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Rob Herring, Mark Rutland, Russell King, Hauke Mehrtens,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rafał Miłecki
In-Reply-To: <20161113101209.22185-1-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On 11/13/2016 02:12 AM, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>
> 
> It's BCM4709A0 based device with 16 MiB flash, 128 MiB of RAM and two
> PCIe based on-PCB BCM4360 chipsets.
> 
> Signed-off-by: Rafał Miłecki <rafal-g1n6cQUeyibVItvQsEIGlw@public.gmane.org>

Applied, thanks!
-- 
Florian
--
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 1/1] ARM: dts: enable GPIO-b for Broadcom NSP
From: Florian Fainelli @ 2016-11-16 20:52 UTC (permalink / raw)
  To: Yendapally Reddy Dhananjaya Reddy, Rob Herring, Mark Rutland,
	Russell King, Ray Jui, Scott Branden, Jon Mason
  Cc: bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479130219-25639-1-git-send-email-yendapally.reddy-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

On 11/14/2016 05:30 AM, Yendapally Reddy Dhananjaya Reddy wrote:
> This enables the GPIO-b support for Broadcom NSP SoC
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

Applied, thanks
-- 
Florian
--
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: [upstream-release] [PATCH 1/2] drivers: usb: phy: Add qoriq usb 3.0 phy driver support
From: Scott Wood @ 2016-11-16 21:07 UTC (permalink / raw)
  To: Sriram Dash, linux-kernel@vger.kernel.org,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
  Cc: mark.rutland@arm.com, felipe.balbi@linux.intel.com,
	mathias.nyman@intel.com, catalin.marinas@arm.com,
	will.deacon@arm.com, kishon@ti.com, robh+dt@kernel.org,
	stern@rowland.harvard.edu, Suresh Gupta,
	gregkh@linuxfoundation.org, pku.leo@gmail.com
In-Reply-To: <DB5PR0401MB1925E935B4E7F5D1D1E521D5F5BE0@DB5PR0401MB1925.eurprd04.prod.outlook.com>

On 11/16/2016 05:33 AM, Sriram Dash wrote:
>> From: Scott Wood
>> On 11/15/2016 06:39 AM, Sriram Dash wrote:
>>>> From: Scott Wood
>>>> On 11/13/2016 11:27 PM, Sriram Dash wrote:
>>>>> diff --git
>>>>> a/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>>>> b/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>>>> new file mode 100644
>>>>> index 0000000..d934c80
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/phy/phy-qoriq-usb3.txt
>>>>> @@ -0,0 +1,36 @@
>>>>> +Driver for Freescale USB 3.0 PHY
>>>>> +
>>>>> +Required properties:
>>>>> +
>>>>> +- compatible :	fsl,qoriq-usb3-phy
>>>>
>>>
>>> Hi Scott,
>>>
>>>> This is a very vague compatible.  Are there versioning registers
>>>> within this register block?
>>>>
>>>
>>> There are versioning registers for the phy (1.0 and 1.1). But the
>>> current erratum
>>> A008751 does not require the mentioning of the version numbers. Was
>>> planning to take care of the versioning when there is code diversity
>>> on the basis of the version number.
>>
>> That is not how device tree bindings work.  The describe the hardware, not the
>> driver.
>>
>> That said, is the block version sufficient to tell whether a given chip has this
>> erratum? If so, you don't need a special property for the erratum.  If not, what is
>> different about the PHY that is not described by the versioning?

Can you find out the answer to this?

>> In any case, it would be nice to mention the version register and its offset in the
>> binding, just so that it becomes part of the definition of this compatible string, and
>> if we come out with some QorIQ chip with a
>> USB3 PHY that is totally different and doesn't have that version register, it'll be
>> clear that it needs a different compatible.
>>
> 
> Okay. Will include version number in the next rev for Documentation and dt.

I'm not asking you to put the version number in the dt if it can be read
from a register.  I'm asking you to have the binding describe the
version register, as part of the definition of what "fsl,qoriq-usb3-phy"
means.

>>> The only reason for __raw_writel is to make the code faster.
>>
>> Does that really matter here?
>>
>>> However, shall I use writel(with both barriers and byte swap) instead
>>
>> Yes, if the registers are little-endian on all chips.
>>
> 
> The endianness is not same for all Socs. But for most Socs, it is big-endian.
> Is "iowrite32be" better instead? 

Then the device tree node needs to say what endian it is, and you need
to choose the appropriate accessor at runtime.

But is it really big endian for most or even any SoCs?  This hardware
isn't present on our PPC chips, right (I checked a couple of the most
recent PPC RMs and it shows USB 2.0 only)?  So it'd just be the few ARM
chips that made almost everything big endian, and even there the couple
RMs I checked (ls1021a and ls1043a) have these registers described as
little-endian.

>>> and then make appropriate changes in the value 32'h27672B2A?
>>
>> Not sure what you mean here.
>>
>>> In my knowledge, there are more than 5 errata in pipeline,
>>
>> Then please get all of these errata described in the device tree ASAP (unless their
>> presence can be reliably inferred from the block version, as discussed above).
>>
> 
> Yes. We will push the errata asap.

My point is that the device tree node should be complete when you submit
it.  Don't wait for the implementation of a workaround to advertise the
existence of an erratum in the device tree.

-Scott

^ permalink raw reply

* Re: [PATCH v5 1/7] drm: sunxi: Add a basic DRM driver for Allwinner DE2
From: Maxime Ripard @ 2016-11-16 21:33 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Dave Airlie, Liam Girdwood, Mark Brown, Rob Herring,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20161108153752.a17440e784f2e3993c79ee69-GANU6spQydw@public.gmane.org>

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

On Tue, Nov 08, 2016 at 03:37:52PM +0100, Jean-Francois Moine wrote:
> On Mon, 7 Nov 2016 23:37:41 +0100
> Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> 
> > Hi,
> > 
> > On Fri, Oct 28, 2016 at 07:34:20PM +0200, Jean-Francois Moine wrote:
> > > On Fri, 28 Oct 2016 00:03:16 +0200
> > > Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> 	[snip]
> > > > > > We've been calling them bus and mod.
> > > > > 
> > > > > I can understand "bus" (which is better than "apb"), but why "mod"?
> > > > 
> > > > Allwinner has been calling the clocks that are supposed to generate
> > > > the external signals (depending on where you were looking) module or
> > > > mod clocks (which is also why we have mod in the clock
> > > > compatibles). The module 1 clocks being used for the audio and the
> > > > module 0 for the rest (SPI, MMC, NAND, display, etc.)
> > > 
> > > I did not find any 'module' in the H3 documentation.
> > > So, is it really a good name?
> > 
> > It's true that they use it less nowadays, but they still do,
> > ie. https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/drivers/clk/sunxi/clk-sun8iw7.c#L513
> 
> There is a 'mod' suffix, but it is used for the bus gates only, not for
> the main clocks.
> 
> > And we have to remain consistent anyway.
> 
> I don't see any consistency in the H3 DT:
> - the bus gates are named "ahb" and apb"

We've been inconsistent in the past, hence why it would be great to
have bus instead.

> - the (main) clocks are named "mmc", "usb0_phy" and "ir"
> There is no "bus" nor "mod".

Look into the other devices, for other SoCs. Pointing out that we've
been bad in the past doesn't mean that we can't improve.

> > > > > > > +
> > > > > > > +- resets: phandle to the reset of the device
> > > > > > > +
> > > > > > > +- ports: phandle's to the LCD ports
> > > > > > 
> > > > > > Please use the OF graph.
> > > > > 
> > > > > These ports are references to the graph of nodes. See
> > > > > 	http://www.kernelhub.org/?msg=911825&p=2
> > > > 
> > > > In an OF-graph, your phandle to the LCD controller would be replaced
> > > > by an output endpoint.
> > > 
> > > This is the DE controller. There is no endpoint link at this level.
> > 
> > The display engine definitely has an endpoint: the TCON.
> 
> Not at all. The video chain is simply
> 	CRTC (TCON) -> connector (HDMI/LCD/DAC/..)
> The DE is an ancillary device which handles the planes.

And what does it do exactly with those planes? It outputs it to the
TCON.

> > > The Device Engine just handles the planes of the LCDs, but, indeed,
> > > the LCDs must know about the DE and the DE must know about the LCDs.
> > > There are 2 ways to realize this knowledge in the DT:
> > > 1) either the DE has one or two phandle's to the LCDs,
> > > 2) or the LCDs have a phandle to the DE.
> > > 
> > > I chose the 1st way, the DE ports pointing to the endpoint of the LCDs
> > > which is part of the video link (OF-graph LCD <-> connector).
> > > It would be possible to have phandles to the LCDs themselves, but this
> > > asks for more code.
> > > 
> > > The second way is also possible, but it also complexifies a bit the
> > > exchanges DE <-> LCD.
> > 
> > I'm still not sure how it would complexify anything, and why you can't
> > use the display graph to model the relation between the display engine
> > and the TCON (and why you want to use a generic property that refers
> > to the of-graph while it really isn't).
> 
> Complexification:
> 1- my solution:
>   At startup time, the DE device is the DRM device.

How do you deal with SoCs with multiple display engines then?

> It has to know the devices entering in the video chains.
>   The CRTCs (LCD/TCON) are found by
> 	ports[i] -> parent
>   The connectors are found by
> 	ports[i] -> endpoint -> remote_endpoint -> parent
> 2- with ports pointing to the LCDs:
>   The CRTCs (LCD/TCON) are simply
> 	ports[i]
>   The connectors are found by
> 	loop on all ports of ports[i]
> 		ports[i][j] -> endpoint -> remote_endpoint -> parent
> 3- with a phandle to the DE in the LCDs:

What do you mean with LCD? Panels? Why would panels have a phandle to
the display engine?

>   The DE cannot be the DRM device because there is no information about
>   the video devices in the DT. Then, the DRM devices are the LCDs.
>   These LCDs must give their indices to the DE. So, the DE must implement
>   some callback function to accept a LCD definition, and there must be
>   a list of DEs in the driver to make the association DE <-> LCD[i]
>   Some more problem may be raised if a user wants to have the same frame
>   buffer on the 2 LCDs of a DE.

I have no idea what you're talking about, sorry.

> Anyway, my solution is already used in the IMX Soc.
> See 'display-subsystem' in arch/arm/boot/dts/imx6q.dtsi for an example.

Pointing out random example in the tree doesn't make a compelling
argument.

> > > > > > > +void de2_disable_vblank(struct drm_device *drm, unsigned crtc)
> > > > > > > +{
> > > > > > > +	struct priv *priv = drm->dev_private;
> > > > > > > +	struct lcd *lcd = priv->lcds[crtc];
> > > > > > > +
> > > > > > > +	tcon_write(lcd->mmio, gint0,
> > > > > > > +			 tcon_read(lcd->mmio, gint0) &
> > > > > > > +					~TCON_GINT0_TCON1_Vb_Int_En);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/* panel functions */
> > > > > > 
> > > > > > Panel functions? In the CRTC driver?
> > > > > 
> > > > > Yes, dumb panel.
> > > > 
> > > > What do you mean by that? Using a Parallel/RGB interface?
> > > 
> > > Sorry, I though this was a well-known name. The 'dump panel' was used
> > > in the documentation of my previous ARM machine as the video frame sent
> > > to the HDMI controller. 'video_frame' is OK for you?
> > 
> > If it's the frame sent to the encoder, then it would be the CRTC by
> > DRM's nomenclature.
> 
> The CRTC is a software entity. The frame buffer is a hardware entity.

Why are you about framebuffer now, this is nowhere in that
discussion. Any way, the framebuffer is also what is put in a plane,
so there's a name collision here, and you'll probably want to change
it.

Judging by the previous discussion, this should really be called
encoder if it encodes the frames on a bus format, or CRTC if it
composes the planes.

> > > > > > > +static const struct {
> > > > > > > +	char chan;
> > > > > > > +	char layer;
> > > > > > > +	char pipe;
> > > > > > > +} plane2layer[DE2_N_PLANES] = {
> > > > > > > +	[DE2_PRIMARY_PLANE] =	{0, 0, 0},
> > > > > > > +	[DE2_CURSOR_PLANE] =	{1, 0, 1},
> > > > > > > +	[DE2_VI_PLANE] =	{0, 1, 0},
> > > > > > > +};
> 	[snip]
> > > > > > 
> > > > > > Comments?
> > > > > 
> > > > > This
> > > > > 	primary plane is channel 0 (VI), layer 0, pipe 0
> > > > > 	cursor plane is channel 1 (UI), layer 0, pipe 1
> > > > > 	overlay plane is channel 0 (VI), layer 1, pipe 0
> > > > > or the full explanation:
> > > > >     Constraints:
> > > > > 	The VI channels can do RGB or YUV, while UI channels can do RGB
> > > > > 	only.
> > > > > 	The LCD 0 has 1 VI channel and 4 UI channels, while
> > > > > 	LCD 1 has only 1 VI channel and 1 UI channel.
> > > > > 	The cursor must go to a channel bigger than the primary channel,
> > > > > 	otherwise it is not transparent.
> > > > >     First try:
> > > > > 	Letting the primary plane (usually RGB) in the 2nd channel (UI),
> > > > > 	as this is done in the legacy driver, asks for the cursor to go
> > > > > 	to the next channel (UI), but this one does not exist in LCD1.
> > > > >     Retained layout:
> > > > > 	So, we must use only 2 channels for the same behaviour on LCD0
> > > > > 	(H3) and LCD1 (A83T)
> > > > > 	The retained combination is:
> > > > > 		- primary plane in the first channel (VI),
> > > > > 		- cursor plane inthe 2nd channel (UI), and
> > > > > 		- overlay plane in the 1st channel (VI).
> > > > > 
> > > > > 	Note that there could be 3 overlay planes (a channel has 4
> > > > > 	layers), but I am not sure that the A83T or the H3 could
> > > > > 	support 3 simultaneous video streams...
> > > > 
> > > > Do you know if the pipe works in the old display engine?
> > > > 
> > > > Especially about the two-steps composition that wouldn't allow you to
> > > > have alpha on all the planes?
> > > > 
> > > > If it is similar, I think hardcoding the pipe number is pretty bad,
> > > > because that would restrict the combination of planes and formats,
> > > > while some other might have worked.
> > > 
> > > From what I understood about the DE2, the pipes just define the priority
> > > of the overlay channels (one pipe for one channel).
> > > With the cursor constraint, there must be at least 2 channels in
> > > order (primary, cursor). Then, with these 2 channels/pipes, there can be
> > > 6 so-called overlay planes (3 RGB/YUV and 3 RGB only).
> > > Enabling the pipes 2 and 3 (LCD 0 only) would offer 8 more planes, but
> > > RGB only. Then, it might be useful to have dynamic pipes.
> > 
> > That's very valuable (and definitely should go into a comment),
> > thanks!
> > 
> > I still believe that's it should be into a (simple at first)
> > atomic_check. That would be easier to extend and quite easy to
> > document and get simply by looking at the code.
> 
> Sorry for I don't understand what you mean.

You can check all the constraints you exposed above in atomic_check
instead of hardcoding it.

> > > > > > > +static int __init de2_drm_init(void)
> > > > > > > +{
> > > > > > > +	int ret;
> > > > > > > +
> > > > > > > +/* uncomment to activate the drm traces at startup time */
> > > > > > > +/*	drm_debug = DRM_UT_CORE | DRM_UT_DRIVER | DRM_UT_KMS |
> > > > > > > +			DRM_UT_PRIME | DRM_UT_ATOMIC; */
> > > > > > 
> > > > > > That's useless.
> > > > > 
> > > > > Right, but it seems that some people don't know how to debug a DRM
> > > > > driver. This is only a reminder.
> > > > > 
> > > > > > > +	DRM_DEBUG_DRIVER("\n");
> > > > > > > +
> > > > > > > +	ret = platform_driver_register(&de2_lcd_platform_driver);
> > > > > > > +	if (ret < 0)
> > > > > > > +		return ret;
> > > > > > > +
> > > > > > > +	ret = platform_driver_register(&de2_drm_platform_driver);
> > > > > > > +	if (ret < 0)
> > > > > > > +		platform_driver_unregister(&de2_lcd_platform_driver);
> > > > > > > +
> > > > > > > +	return ret;
> > > > > > > +}
> > > > > > 
> > > > > > And that really shouldn't be done that way.
> > > > > 
> > > > > May you explain?
> > > > 
> > > > This goes against the whole idea of the device and driver
> > > > model. Drivers should only register themselves, device should be
> > > > created by buses (or by using some external components if the bus
> > > > can't: DT, ACPI, etc.). If there's a match, you get probed.
> > > > 
> > > > A driver that creates its own device just to probe itself violates
> > > > that.
> > > 
> > > In this function (module init), there is no driver yet.
> > > The module contains 2 drivers: the DE (planes) and the LCD (CRTC),
> > > and there is no macro to handle such modules.
> > 
> > Ah, yes, my bad. I thought you were registering a device and a
> > driver. Still this is a very unusual pattern. Why do you need to split
> > the two? Can't you just merge them?
> 
> The DE and the LCDs are different devices on different drivers.
> A DE must be only one device because it has to handle concurent
> accesses from its 2 LCDs. Then 2 drivers.

If it's different drivers, why are they in the same module?

> But only one module. Why? Because there cannot be double direction
> calls from one module to an other one, and, in our case, for example,
> - the DRM (DE) device must call vblank functions which are handled in
>   the CRTC (TCON) device, and
> - the CRTC device must call DE initialization functions at startup time.

I'm sorry, but that doesn't make any sense. The crtc device should
take care of the CRTC functions. Your DRM CRTC and encoders can
definitely be shared across different devices, you can have a look at
how we're doing it for sun4i.

We basically have 3 drivers to create most of the display pipeline:
  - One for the DRM device
  - One for the display engine
  - One for the TCON

Once they have all loaded and registered in the component framework,
their bind callback is called, and it's when the DRM entities are
created using exported functions to manipulate what needs to be setup.

It's definitely doable, it just takes some effort.

> > > > > > > +int de2_plane_init(struct drm_device *drm, struct lcd *lcd)
> > > > > > > +{
> > > > > > > +	int ret, possible_crtcs = 1 << lcd->crtc_idx;
> > > > > > > +
> > > > > > > +	ret = de2_one_plane_init(drm, &lcd->planes[DE2_PRIMARY_PLANE],
> > > > > > > +				DRM_PLANE_TYPE_PRIMARY, possible_crtcs,
> > > > > > > +				ui_formats, ARRAY_SIZE(ui_formats));
> > > > > > > +	if (ret >= 0)
> > > > > > > +		ret = de2_one_plane_init(drm, &lcd->planes[DE2_CURSOR_PLANE],
> > > > > > > +				DRM_PLANE_TYPE_CURSOR, possible_crtcs,
> > > > > > > +				ui_formats, ARRAY_SIZE(ui_formats));
> > > > > > 
> > > > > > Nothing looks really special about that cursor plane. Any reasion not
> > > > > > to make it an overlay?
> > > > > 
> > > > > As explained above (channel/layer/pipe plane definitions), the cursor
> > > > > cannot go in a channel lower or equal to the one of the primary plane.
> > > > > Then, it must be known and, so, have an explicit plane.
> > > > 
> > > > If you were to make it a plane, you could use atomic_check to check
> > > > this and make sure this doesn't happen. And you would gain a generic
> > > > plane that can be used for other purposes if needed.
> > > 
> > > The function drm_crtc_init_with_planes() offers a cursor plane for free.
> > > On the other side, having 6 overlay planes is more than the SoCs can
> > > support.
> > 
> > It's not really for free, it costs you a generic plane that could
> > definitely be used for something else and cannot anymore because
> > they've been hardcoded to a cursor.
> > 
> > And having a camera, the VPU or even an application directly output
> > directly into one of these planes seems a much better use of a generic
> > plane than a cursor.
> 
> Looking at the harder case (A83T), there may be 8 planes on 2 channels.
> Using a primary plane and the cursor,
> 	8 planes - primary plane - cursor plane = 6 planes
> 6 planes are available.
> If I count correctly, in your example:
> 	one camera + one VPU + one application = 3 planes
> 3 planes are used.
> So, 3 planes are still available.
> 
> On the other side, removing the cursor would just let one more plane.
> Do we really need this one? In other words, I'd be pleased to know how
> you run 7 applications doing video overlay.

You can use those planes to do composition too, with each application
having one or more plane. Android uses that.

There's no argument to have a cursor plane, really. Even regular
graphic stack like X can use a regular overlay to have its cursor on
it. It doesn't *remove* anything, it just allows to use the plane for
what it was supposed to be used for.

Maxime

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

^ permalink raw reply

* Re: [PATCH 3/3] ARM64: dts: meson-gxbb: add the USB reset also to the second USB PHY
From: Kevin Hilman @ 2016-11-16 21:35 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kishon-l0cyMroinI0,
	carlo-KA+7E9HrN00dnm+yROfE0A, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161112131305.26088-4-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> writes:

> When the USB PHY driver was introduced the reset framework did not
> have support for triggering a reset pulse for shared resets. On GXBB
> however there is only one reset line for both PHYs (meaning we have a
> shared reset line). With the latest changes to the reset framework and
> the corresponding updates to the phy-meson8b-usb2 driver we can now pass
> the reset to the second PHY as well.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Applied.

Thanks,

Kevin
--
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 V8 0/6] thermal: bcm2835: add thermal driver
From: Eric Anholt @ 2016-11-16 21:57 UTC (permalink / raw)
  To: Zhang Rui, kernel-TqfNSX0MhmxHKSADF0wUEw, Eduardo Valentin,
	Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren, Lee Jones,
	Russell King, Florian Fainelli, Catalin Marinas, Will Deacon,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1479214212.2224.24.camel-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

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

Zhang Rui <rui.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> writes:

> On Fri, 2016-11-11 at 09:01 -0800, Eric Anholt wrote:
>> kernel-TqfNSX0MhmxHKSADF0wUEw@public.gmane.org writes:
>> 
>> > 
>> > From: Martin Sperl <kernel-TqfNSX0MhmxHKSADF0wUEw@public.gmane.org>
>> Since Eduardo seems to be AFK, I've pulled this series to my -next
>> branches.
> I will take the thermal soc patches this time if we still don't have
> response from Eduardo by the end of this week.
>
> For this patches set, will you queue them up or do you prefer to go via
> thermal tree?

I was queuing up the entire series (including the driver) through the
SOC trees.

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

^ permalink raw reply

* [PATCH v2 0/4] usb: dwc2: Add AHB burst configuration
From: John Youn @ 2016-11-16 23:47 UTC (permalink / raw)
  To: John Youn, Felipe Balbi, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland
  Cc: Christian Lamparter, Stefan Wahren

This series adds a binding for AHB burst, reads it in, and configures
the controller for the specified burst type.

Tested on HAPS platform with DWC_hsotg IP version 3.30a.

v2:
* Don't remove the bcm2835 ahbcfg param and document why.


John Youn (4):
  usb: dwc2: Document the AHB burst value for bcm2835
  usb: dwc2: Add binding for AHB burst
  usb: dwc2: Use the ahb_burst param
  usb: dwc2: pci: Add AHB burst property for HAPS

 Documentation/devicetree/bindings/usb/dwc2.txt |  2 +
 drivers/usb/dwc2/core.h                        |  9 ++++
 drivers/usb/dwc2/gadget.c                      |  2 +-
 drivers/usb/dwc2/hcd.c                         |  8 ++-
 drivers/usb/dwc2/params.c                      | 73 ++++++++++++++++++++++----
 drivers/usb/dwc2/pci.c                         |  1 +
 6 files changed, 79 insertions(+), 16 deletions(-)

-- 
2.10.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

* [PATCH v2 2/4] usb: dwc2: Add binding for AHB burst
From: John Youn @ 2016-11-16 23:47 UTC (permalink / raw)
  To: John Youn, Felipe Balbi, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland
  Cc: Christian Lamparter, Stefan Wahren
In-Reply-To: <cover.1479339900.git.johnyoun-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>

Add the "snps,ahb-burst" binding and read it in.

This property controls which burst type to perform on the AHB bus as a
master in internal DMA mode. This overrides the legacy param value,
which we need to keep around for now since several platforms use it.

Some platforms may see better or worse performance based on this
value. The HAPS platform is one example where all INCRx have worse
performance than INCR.

Other platforms (such as the Canyonlands board) report that the default
value causes system hangs.

Signed-off-by: John Youn <johnyoun-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
Cc: Christian Lamparter <chunkeey-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 Documentation/devicetree/bindings/usb/dwc2.txt |  2 +
 drivers/usb/dwc2/core.h                        |  9 +++++
 drivers/usb/dwc2/params.c                      | 56 ++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
index 6c7c2bce..9e7b4b4 100644
--- a/Documentation/devicetree/bindings/usb/dwc2.txt
+++ b/Documentation/devicetree/bindings/usb/dwc2.txt
@@ -26,6 +26,8 @@ Optional properties:
 Refer to phy/phy-bindings.txt for generic phy consumer properties
 - dr_mode: shall be one of "host", "peripheral" and "otg"
   Refer to usb/generic.txt
+- snps,ahb-burst: specifies the ahb burst length. Valid arguments are:
+  "SINGLE", "INCR", "INCR4", "INCR8", "INCR16". Defaults to "INCR4".
 - g-rx-fifo-size: size of rx fifo size in gadget mode.
 - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
 - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 9548d3e..75c238c 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -430,6 +430,12 @@ enum dwc2_ep0_state {
  *			needed.
  *			0 - No (default)
  *			1 - Yes
+ * @ahb_burst:          Specifies the AHB burst.
+ *                       0 - Single
+ *                       1 - INCR
+ *                       3 - INCR4 (default)
+ *                       5 - INCR8
+ *                       7 - INCR16
  * @g_dma:              Enables gadget dma usage (default: autodetect).
  * @g_dma_desc:         Enables gadget descriptor DMA (default: autodetect).
  * @g_rx_fifo_size:	The periodic rx fifo size for the device, in
@@ -507,6 +513,9 @@ struct dwc2_core_params {
 	 * properties and cannot be set directly in this structure.
 	 */
 
+	/* Global parameters */
+	u8 ahb_burst;
+
 	/* Host parameters */
 	bool host_dma;
 
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index d44b31c..8bc2745 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -1098,6 +1098,60 @@ static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
 	}
 }
 
+static const char *const ahb_bursts[] = {
+	[GAHBCFG_HBSTLEN_SINGLE]	= "SINGLE",
+	[GAHBCFG_HBSTLEN_INCR]		= "INCR",
+	[GAHBCFG_HBSTLEN_INCR4]		= "INCR4",
+	[GAHBCFG_HBSTLEN_INCR8]		= "INCR8",
+	[GAHBCFG_HBSTLEN_INCR16]	= "INCR16",
+};
+
+static int dwc2_get_property_ahb_burst(struct dwc2_hsotg *hsotg)
+{
+	const char *str = NULL;
+	int burst;
+	int ret;
+
+	ret = device_property_read_string(hsotg->dev,
+					  "snps,ahb-burst", &str);
+	if (ret < 0)
+		return ret;
+
+	burst = match_string(ahb_bursts,
+			     ARRAY_SIZE(ahb_bursts), str);
+	if (burst < 0) {
+		dev_err(hsotg->dev,
+			"Invalid parameter '%s' for ahb-burst\n", str);
+	}
+
+	return burst;
+}
+
+static void dwc2_set_ahb_burst(struct dwc2_hsotg *hsotg)
+{
+	struct dwc2_core_params *p = &hsotg->params;
+	int burst;
+	int ret;
+
+	/* Default burst value */
+	burst = GAHBCFG_HBSTLEN_INCR4;
+
+	/* Get the legacy param value, if set. */
+	if (p->ahbcfg != -1) {
+		burst = (p->ahbcfg & GAHBCFG_HBSTLEN_MASK) >>
+			GAHBCFG_HBSTLEN_SHIFT;
+	}
+
+	/* Override it from devicetree, if set. */
+	ret = dwc2_get_property_ahb_burst(hsotg);
+	if (ret >= 0)
+		burst = ret;
+
+	/* Set the parameter */
+	p->ahb_burst = (u8)burst;
+	dev_dbg(hsotg->dev, "Setting ahb-burst to %d\n", burst);
+}
+
 static void dwc2_set_gadget_dma(struct dwc2_hsotg *hsotg)
 {
 	struct dwc2_hw_params *hw = &hsotg->hw_params;
@@ -1178,6 +1232,8 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
 	dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl);
 	dwc2_set_param_hibernation(hsotg, params->hibernation);
 
+	dwc2_set_ahb_burst(hsotg);
+
 	/*
 	 * Set devicetree-only parameters. These parameters do not
 	 * take any values from @params.
-- 
2.10.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

* [RFC PATCH 0/7] mux controller astraction and iio/i2c muxes
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA

Hi!

This is work in progress, I'm asking for early feedback.

I have a piece of hardware that is using the same 3 GPIO pins
to control four 8-way muxes. Three of them control ADC lines
to an ADS1015 chip with an iio driver, and the last one
controls the SDA line of an i2c bus. We have some deployed
code to handle this, but you do not want to see it or ever
hear about it. I'm not sure why I even mention it. Anyway,
the situation has nagged me to no end for quite some time.

So, after first getting more intimate with the i2c muxing code
and later discovering the drivers/iio/inkern.c file and
writing a couple of drivers making use of it, I came up with
what I think is an acceptable solution; add a generic mux
controller driver that is shared between all instances, and
combine that with an iio mux driver and a new generic i2c mux
driver. The new i2c mux I called "simple" since it is only
hooking the i2c muxing and the new mux controller (much like
the alsa simple card driver does for ASoC).

My initial (private) version didn't add "mux" as a new bus,
but I couldn't get decent type-checking and nice devicetree
integration with that. It does however feel a bit rich to
add a new bus for something as small as mux controllers?

One thing that I would like to do, but don't see a solution
for, is to move the mux control code that is present in
various drivers in drivers/i2c/muxes to this new minimalistic
muxing subsystem, thus converting all present i2c muxes (but
perhaps not gates and arbitrators) to be i2c-mux-simple muxes.

I'm using an rwsem to lock a mux, but that isn't really a
perfect fit. Is there a better locking primitive that I don't
know about that fits better? I had a mutex at one point, but
that didn't allow any concurrent accesses at all. At least
the rwsem allows concurrent access as long as all users
agree on the mux state, but I suspect that the rwsem will
degrade to the mutex situation pretty quickly if there is
any contention.

Also, the "mux" name feels a bit ambitious, there are many muxes
in the world, and this tiny bit of code is probably not good
enough to be a nice fit for all...

This is all very fresh code and only lightly tested, but it
feels very promising! Now, go ahead and rip this to pieces...

Cheers,
Peter

Peter Rosin (7):
  dt-bindings: document devicetree bindings for mux-gpio
  misc: minimal mux subsystem and gpio-based mux controller
  iio: inkern: api for manipulating ext_info of iio channels
  dt-bindings: iio: iio-mux: document iio-mux bindings
  iio: multiplexer: new iio category and iio-mux driver
  dt-bindings: i2c: i2c-mux-simple: document i2c-mux-simple bindings
  i2c: i2c-mux-simple: new driver

 .../devicetree/bindings/i2c/i2c-mux-simple.txt     |  91 ++++++
 .../bindings/iio/multiplexer/iio-mux.txt           |  59 ++++
 .../devicetree/bindings/misc/mux-gpio.txt          |  76 +++++
 drivers/i2c/muxes/Kconfig                          |  12 +
 drivers/i2c/muxes/Makefile                         |   1 +
 drivers/i2c/muxes/i2c-mux-simple.c                 | 172 +++++++++++
 drivers/iio/Kconfig                                |   1 +
 drivers/iio/Makefile                               |   1 +
 drivers/iio/inkern.c                               |  40 +++
 drivers/iio/multiplexer/Kconfig                    |  17 ++
 drivers/iio/multiplexer/Makefile                   |   6 +
 drivers/iio/multiplexer/iio-mux.c                  | 313 +++++++++++++++++++++
 drivers/misc/Kconfig                               |   6 +
 drivers/misc/Makefile                              |   2 +
 drivers/misc/mux-core.c                            | 285 +++++++++++++++++++
 drivers/misc/mux-gpio.c                            | 105 +++++++
 include/linux/iio/consumer.h                       |   5 +
 include/linux/mux.h                                |  54 ++++
 18 files changed, 1246 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt
 create mode 100644 Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
 create mode 100644 Documentation/devicetree/bindings/misc/mux-gpio.txt
 create mode 100644 drivers/i2c/muxes/i2c-mux-simple.c
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c
 create mode 100644 drivers/misc/mux-core.c
 create mode 100644 drivers/misc/mux-gpio.c
 create mode 100644 include/linux/mux.h

-- 
2.1.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

* [RFC PATCH 1/7] dt-bindings: document devicetree bindings for mux-gpio
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c, devicetree, linux-iio
In-Reply-To: <1479340111-1259-1-git-send-email-peda@axentia.se>

---
 .../devicetree/bindings/misc/mux-gpio.txt          | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/mux-gpio.txt

diff --git a/Documentation/devicetree/bindings/misc/mux-gpio.txt b/Documentation/devicetree/bindings/misc/mux-gpio.txt
new file mode 100644
index 000000000000..8c1745ecd4ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/mux-gpio.txt
@@ -0,0 +1,76 @@
+GPIO-based multiplexer controller bindings
+
+Define what GPIO pins are used to control a multiplexer. Or several
+multiplexers, if the same pins control more than one multiplexer.
+
+Required properties:
+- compatible : "mux-gpio"
+- mux-gpios : list of gpios used to control the multiplexer, least
+	      significant bit first.
+
+Example:
+	control_mux: control-adc-mux {
+		compatible = "mux-gpio";
+
+		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
+			    <&pioA 1 GPIO_ACTIVE_HIGH>;
+	};
+
+	adc-mux {
+		compatible = "iio-mux";
+		io-channels = <&adc 0>;
+		io-channel-names = "parent";
+
+		control-muxes = <&control_mux>;
+		control-mux-names = "mux";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sync-1@0 {
+			reg = <0>;
+		};
+
+		in@1 {
+			reg = <1>;
+		};
+
+		out@2 {
+			reg = <2>;
+		};
+
+		sync-2@3 {
+			reg = <3>;
+		};
+	};
+
+	i2c-mux {
+		compatible = "i2c-mux-simple,mux-locked";
+		i2c-parent = <&i2c1>;
+
+		control-muxes = <&control_mux>;
+		control-mux-names = "mux";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			ssd1307: oled@3c {
+				/* ... */
+			};
+		};
+
+		i2c@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pca9555: pca9555@20 {
+				/* ... */
+			};
+		};
+	};
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 2/7] misc: minimal mux subsystem and gpio-based mux controller
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479340111-1259-1-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

When both the iio subsystem and the i2c subsystem wants to update
the same mux, there needs to be some coordination. Invent a new
minimal "mux" subsystem that handles this.

Add a single backend driver for this new subsystem that can
control gpio based multiplexers.
---
 drivers/misc/Kconfig    |   6 +
 drivers/misc/Makefile   |   2 +
 drivers/misc/mux-core.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/misc/mux-gpio.c | 105 ++++++++++++++++++
 include/linux/mux.h     |  54 +++++++++
 5 files changed, 452 insertions(+)
 create mode 100644 drivers/misc/mux-core.c
 create mode 100644 drivers/misc/mux-gpio.c
 create mode 100644 include/linux/mux.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 64971baf11fa..9e119bb78d82 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -766,6 +766,12 @@ config PANEL_BOOT_MESSAGE
 	  An empty message will only clear the display at driver init time. Any other
 	  printf()-formatted message is valid with newline and escape codes.
 
+config MUX_GPIO
+	tristate "GPIO-controlled MUX controller"
+	depends on OF
+	help
+	  GPIO-controlled MUX controller
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 31983366090a..92b547bcbac1 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,6 +53,8 @@ obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
 obj-$(CONFIG_PANEL)             += panel.o
+obj-$(CONFIG_MUX_GPIO)          += mux-core.o
+obj-$(CONFIG_MUX_GPIO)          += mux-gpio.o
 
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o
diff --git a/drivers/misc/mux-core.c b/drivers/misc/mux-core.c
new file mode 100644
index 000000000000..d7c7b667d1a4
--- /dev/null
+++ b/drivers/misc/mux-core.c
@@ -0,0 +1,285 @@
+/*
+ * Multiplexer subsystem
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "mux-core: " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/mux.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+static struct bus_type mux_bus_type = {
+	.name = "mux",
+};
+
+static int __init mux_init(void)
+{
+	return bus_register(&mux_bus_type);
+}
+
+static void __exit mux_exit(void)
+{
+	bus_unregister(&mux_bus_type);
+}
+
+static DEFINE_IDA(mux_ida);
+
+static void mux_control_release(struct device *dev)
+{
+	struct mux_control *mux = to_mux_control(dev);
+
+	ida_simple_remove(&mux_ida, mux->id);
+	kfree(mux);
+}
+
+static struct device_type mux_control_type = {
+	.name = "mux-control",
+	.release = mux_control_release,
+};
+
+/*
+ * Allocate a mux-control, plus an extra memory area for private use
+ * by the caller.
+ */
+struct mux_control *mux_control_alloc(size_t sizeof_priv)
+{
+	struct mux_control *mux;
+
+	mux = kzalloc(sizeof(*mux) + sizeof_priv, GFP_KERNEL);
+	if (!mux)
+		return NULL;
+
+	mux->dev.bus = &mux_bus_type;
+	mux->dev.type = &mux_control_type;
+	device_initialize(&mux->dev);
+	dev_set_drvdata(&mux->dev, mux);
+
+	init_rwsem(&mux->lock);
+	mux->priv = mux + 1;
+
+	mux->id = ida_simple_get(&mux_ida, 0, 0, GFP_KERNEL);
+	if (mux->id < 0) {
+		pr_err("mux-controlX failed to get device id\n");
+		kfree(mux);
+		return NULL;
+	}
+	dev_set_name(&mux->dev, "mux:control%d", mux->id);
+
+	return mux;
+}
+EXPORT_SYMBOL_GPL(mux_control_alloc);
+
+/*
+ * Register the mux-control, thus readying it for use.
+ */
+int mux_control_register(struct mux_control *mux)
+{
+	/* If the calling driver did not initialize of_node, do it here */
+	if (!mux->dev.of_node && mux->dev.parent)
+		mux->dev.of_node = mux->dev.parent->of_node;
+
+	return device_add(&mux->dev);
+}
+EXPORT_SYMBOL_GPL(mux_control_register);
+
+/*
+ * Take the mux-control off-line.
+ */
+void mux_control_unregister(struct mux_control *mux)
+{
+	device_del(&mux->dev);
+}
+EXPORT_SYMBOL_GPL(mux_control_unregister);
+
+/*
+ * Put away the mux-control for good.
+ */
+void mux_control_put(struct mux_control *mux)
+{
+	if (!mux)
+		return;
+	put_device(&mux->dev);
+}
+EXPORT_SYMBOL_GPL(mux_control_free);
+
+/*
+ * Select the given multiplexer channel. Call mux_control_deselect()
+ * when the operation is complete on the multiplexer channel, and the
+ * multiplexer is free for others to use.
+ */
+int mux_control_select(struct mux_control *mux, int reg)
+{
+	int ret;
+
+	if (down_read_trylock(&mux->lock)) {
+		if (mux->cache == reg)
+			return 0;
+
+		/* Sigh, the mux needs updating... */
+		up_read(&mux->lock);
+	}
+
+	/* ...or it's just contended. */
+	down_write(&mux->lock);
+
+	if (mux->cache == reg) {
+		/*
+		 * Hmmm, someone else changed the mux to my liking.
+		 * That makes me wonder how long I waited for nothing...
+		 */
+		downgrade_write(&mux->lock);
+		return 0;
+	}
+
+	ret = mux->ops->set(mux, reg);
+	if (ret < 0) {
+		up_write(&mux->lock);
+		return ret;
+	}
+
+	mux->cache = reg;
+	downgrade_write(&mux->lock);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(mux_control_select);
+
+/*
+ * Deselect the previously selected multiplexer channel.
+ */
+int mux_control_deselect(struct mux_control *mux)
+{
+	if (mux->do_idle && mux->cache != mux->idle_state) {
+		mux->ops->set(mux, mux->idle_state);
+		mux->cache = mux->idle_state;
+	}
+
+	up_read(&mux->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mux_control_deselect);
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static struct mux_control *of_find_mux_by_node(struct device_node *np)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&mux_bus_type, NULL, np, of_dev_node_match);
+
+	return dev ? to_mux_control(dev) : NULL;
+}
+
+static struct mux_control *of_mux_control_get(struct device_node *np, int index)
+{
+	struct device_node *mux_np;
+	struct mux_control *mux;
+
+	mux_np = of_parse_phandle(np, "control-muxes", index);
+	if (!mux_np)
+		return NULL;
+
+	mux = of_find_mux_by_node(mux_np);
+	of_node_put(mux_np);
+
+	return mux;
+}
+
+/*
+ * Get a named mux.
+ */
+struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
+{
+	struct device_node *np = dev->of_node;
+	struct mux_control *mux;
+	int index;
+
+	index = of_property_match_string(np, "control-mux-names", mux_name);
+	if (index < 0) {
+		dev_err(dev, "failed to get control-mux %s:%s(%i)\n",
+			np->full_name, mux_name ?: "", index);
+		return ERR_PTR(index);
+	}
+
+	mux = of_mux_control_get(np, index);
+	if (!mux)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return mux;
+}
+EXPORT_SYMBOL_GPL(mux_control_get);
+
+static void devm_mux_control_free(struct device *dev, void *res)
+{
+	struct mux_control *mux = *(struct mux_control **)res;
+
+	mux_control_put(mux);
+}
+
+/*
+ * Get a named mux, with resource management.
+ */
+struct mux_control *devm_mux_control_get(struct device *dev,
+					 const char *mux_name)
+{
+	struct mux_control **ptr, *mux;
+
+	ptr = devres_alloc(devm_mux_control_free, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	mux = mux_control_get(dev, mux_name);
+	if (IS_ERR(mux)) {
+		devres_free(ptr);
+		return mux;
+	}
+
+	*ptr = mux;
+	devres_add(dev, ptr);
+
+	return mux;
+}
+EXPORT_SYMBOL_GPL(devm_mux_control_get);
+
+static int devm_mux_control_match(struct device *dev, void *res, void *data)
+{
+	struct mux_control **r = res;
+
+	if (!r || !*r) {
+		WARN_ON(!r || !*r);
+		return 0;
+	}
+
+	return *r == data;
+}
+
+/*
+ * Resource-managed version mux_control_put.
+ */
+void devm_mux_control_put(struct device *dev, struct mux_control *mux)
+{
+	WARN_ON(devres_release(dev, devm_mux_control_free,
+			       devm_mux_control_match, mux));
+}
+EXPORT_SYMBOL_GPL(devm_mux_control_put);
+
+subsys_initcall(mux_init);
+module_exit(mux_exit);
+
+MODULE_AUTHOR("Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org");
+MODULE_DESCRIPTION("MUX subsystem");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mux-gpio.c b/drivers/misc/mux-gpio.c
new file mode 100644
index 000000000000..5fa59a0c49cf
--- /dev/null
+++ b/drivers/misc/mux-gpio.c
@@ -0,0 +1,105 @@
+/*
+ * GPIO-controlled multiplexer driver
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/mux.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+struct mux_gpio {
+	struct gpio_descs *gpios;
+};
+
+static int mux_gpio_set(struct mux_control *mux, int val)
+{
+	struct mux_gpio *mux_gpio = mux->priv;
+	int i;
+
+	for (i = 0; i < mux_gpio->gpios->ndescs; i++)
+		gpiod_set_value_cansleep(mux_gpio->gpios->desc[i],
+					 val & (1 << i));
+
+	return 0;
+}
+
+static const struct mux_control_ops mux_gpio_ops = {
+	.set = mux_gpio_set,
+};
+
+static const struct of_device_id mux_gpio_dt_ids[] = {
+	{ .compatible = "mux-gpio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
+
+static int mux_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+	struct mux_control *mux;
+	struct mux_gpio *mux_gpio;
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	mux = mux_control_alloc(sizeof(*mux_gpio));
+	if (!mux)
+		return -ENOMEM;
+	mux_gpio = mux->priv;
+	mux->dev.parent = dev;
+	mux->ops = &mux_gpio_ops;
+
+	platform_set_drvdata(pdev, mux);
+
+	mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
+	if (IS_ERR(mux_gpio->gpios)) {
+		if (PTR_ERR(mux_gpio->gpios) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get gpios\n");
+		mux_control_put(mux);
+		return PTR_ERR(mux_gpio->gpios);
+	}
+
+	ret = mux_control_register(mux);
+	if (ret < 0) {
+		dev_err(dev, "failed to register mux_control\n");
+		mux_control_put(mux);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int mux_gpio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mux_control *mux = to_mux_control(dev);
+
+	mux_control_unregister(mux);
+	mux_control_put(mux);
+	return 0;
+}
+
+static struct platform_driver mux_gpio_driver = {
+	.driver = {
+		.name = "mux-gpio",
+		.of_match_table	= of_match_ptr(mux_gpio_dt_ids),
+	},
+	.probe = mux_gpio_probe,
+	.remove = mux_gpio_remove,
+};
+module_platform_driver(mux_gpio_driver);
+
+MODULE_AUTHOR("Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org");
+MODULE_DESCRIPTION("GPIO-controlled multiplexer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mux.h b/include/linux/mux.h
new file mode 100644
index 000000000000..6513ffe749bb
--- /dev/null
+++ b/include/linux/mux.h
@@ -0,0 +1,54 @@
+/*
+ * mux.h - definitions for the multiplexer interface
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_MUX_H
+#define _LINUX_MUX_H
+
+#include <linux/device.h>
+#include <linux/rwsem.h>
+
+struct mux_control;
+
+struct mux_control_ops {
+	int (*set)(struct mux_control *mux, int reg);
+};
+
+struct mux_control {
+	struct rw_semaphore lock; /* protects the state of the mux */
+
+	struct device dev;
+	int id;
+
+	int cache;
+	bool do_idle;
+	int idle_state;
+
+	const struct mux_control_ops *ops;
+
+	void *priv;
+};
+
+#define to_mux_control(x) container_of((x), struct mux_control, dev)
+
+struct mux_control *mux_control_alloc(size_t sizeof_priv);
+int mux_control_register(struct mux_control *mux);
+void mux_control_unregister(struct mux_control *mux);
+void mux_control_put(struct mux_control *mux);
+
+int mux_control_select(struct mux_control *mux, int reg);
+int mux_control_deselect(struct mux_control *mux);
+
+struct mux_control *mux_control_get(struct device *dev,
+				    const char *mux_name);
+struct mux_control *devm_mux_control_get(struct device *dev,
+					 const char *mux_name);
+void devm_mux_control_put(struct device *dev, struct mux_control *mux);
+
+#endif /* _LINUX_MUX_H */
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 3/7] iio: inkern: api for manipulating ext_info of iio channels
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479340111-1259-1-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

Extend the inkern api with functions for reading and writing ext_info
of iio channels.
---
 drivers/iio/inkern.c         | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/iio/consumer.h |  5 +++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index cfca17ba2535..5348735281ee 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -850,3 +850,43 @@ int iio_write_channel_raw(struct iio_channel *chan, int val)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+
+int iio_read_channel_ext_info(struct iio_channel *chan,
+			      const char *attr, char *buf)
+{
+	const struct iio_chan_spec_ext_info *ext_info;
+
+	if (!chan->channel->ext_info)
+		return -EINVAL;
+
+	for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+		if (strcmp(attr, ext_info->name))
+			continue;
+
+		return ext_info->read(chan->indio_dev, ext_info->private,
+				      chan->channel, buf);
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+
+int iio_write_channel_ext_info(struct iio_channel *chan,
+			       const char *attr, const char *buf, size_t len)
+{
+	const struct iio_chan_spec_ext_info *ext_info;
+
+	if (!chan->channel->ext_info)
+		return -EINVAL;
+
+	for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
+		if (strcmp(attr, ext_info->name))
+			continue;
+
+		return ext_info->write(chan->indio_dev, ext_info->private,
+				       chan->channel, buf, len);
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 9a4f336d8b4a..3859981cea0a 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -299,4 +299,9 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
 	int *processed, unsigned int scale);
 
+int iio_read_channel_ext_info(struct iio_channel *chan,
+			      const char *attr, char *buf);
+int iio_write_channel_ext_info(struct iio_channel *chan,
+			       const char *attr, const char *buf, size_t len);
+
 #endif
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 4/7] dt-bindings: iio: iio-mux: document iio-mux bindings
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479340111-1259-1-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

---
 .../bindings/iio/multiplexer/iio-mux.txt           | 59 ++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt

diff --git a/Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt b/Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
new file mode 100644
index 000000000000..2f5c7fc35a42
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
@@ -0,0 +1,59 @@
+IIO multiplexer bindings
+
+If a multiplexer is used to select when hardware signal is fed to
+e.g. an ADC channel, these bindings describe that situation.
+
+Required properties:
+- compatible : "iio-mux"
+- io-channels : Channel node of the parent channel that has multiplexed
+		input.
+- io-channel-names : Should be "parent".
+- control-muxes : Node of the multiplexer that controls the input signal.
+- control-mux-names : Should be "mux".
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Required properties for iio-mux child nodes:
+- reg : The multiplexer number.
+
+Optional properties for iio-mux child nodes:
+- iio-ext-info : Array of string pairs, the first item in each pair is the
+		 iio ext_info attribute name, and the second item in each
+		 pair is the iio ext_info value for that attribute. The
+		 mux will write these ext_info values to the corresponding
+		 ext_info attributes on every multiplexer switch.
+
+Example:
+	control_adc_mux: control-adc-mux {
+		compatible = "mux-gpio";
+
+		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
+			    <&pioA 1 GPIO_ACTIVE_HIGH>;
+	};
+
+	adc-mux {
+		compatible = "iio-mux";
+		io-channels = <&adc 0>;
+		io-channel-names = "parent";
+
+		control-muxes = <&control_adc_mux>;
+		control-mux-names = "mux";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sync@0 {
+			reg = <0>;
+			iio-ext-info = "invert", "1";
+		};
+
+		in@1 {
+			reg = <1>;
+			iio-ext-info = "invert", "1";
+		};
+
+		system-regulator@2 {
+			reg = <2>;
+			iio-ext-info = "invert", "0";
+		};
+	};
-- 
2.1.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

* [RFC PATCH 5/7] iio: multiplexer: new iio category and iio-mux driver
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c, devicetree, linux-iio
In-Reply-To: <1479340111-1259-1-git-send-email-peda@axentia.se>

When a multiplexer changes how an iio device behaves (for example
by feeding different signals to an ADC), this driver can be used
create one virtual iio channel for each multiplexer state.

Depends on the generic multiplexer driver.
---
 drivers/iio/Kconfig               |   1 +
 drivers/iio/Makefile              |   1 +
 drivers/iio/multiplexer/Kconfig   |  17 +++
 drivers/iio/multiplexer/Makefile  |   6 +
 drivers/iio/multiplexer/iio-mux.c | 313 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 338 insertions(+)
 create mode 100644 drivers/iio/multiplexer/Kconfig
 create mode 100644 drivers/iio/multiplexer/Makefile
 create mode 100644 drivers/iio/multiplexer/iio-mux.c

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 6743b18194fb..dcb541d0d70e 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -82,6 +82,7 @@ source "drivers/iio/humidity/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
+source "drivers/iio/multiplexer/Kconfig"
 source "drivers/iio/orientation/Kconfig"
 if IIO_TRIGGER
    source "drivers/iio/trigger/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 87e4c4369e2f..f9879c29cf6f 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -27,6 +27,7 @@ obj-y += humidity/
 obj-y += imu/
 obj-y += light/
 obj-y += magnetometer/
+obj-y += multiplexer/
 obj-y += orientation/
 obj-y += potentiometer/
 obj-y += pressure/
diff --git a/drivers/iio/multiplexer/Kconfig b/drivers/iio/multiplexer/Kconfig
new file mode 100644
index 000000000000..31cbe4509366
--- /dev/null
+++ b/drivers/iio/multiplexer/Kconfig
@@ -0,0 +1,17 @@
+#
+# Multiplexer drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Multiplexers"
+
+config IIO_MUX
+	tristate "IIO multiplexer driver"
+	depends on OF && MUX_GPIO
+	help
+	  Say yes here to build support for the IIO multiplexer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iio-mux.
+
+endmenu
diff --git a/drivers/iio/multiplexer/Makefile b/drivers/iio/multiplexer/Makefile
new file mode 100644
index 000000000000..68be3c4abd07
--- /dev/null
+++ b/drivers/iio/multiplexer/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O multiplexer drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_MUX) += iio-mux.o
diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c
new file mode 100644
index 000000000000..6f6644fb9342
--- /dev/null
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -0,0 +1,313 @@
+/*
+ * IIO multiplexer driver
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <peda@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mux.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct mux_child {
+	u32 reg;
+
+	const char **ext_info;
+	int num_ext_info;
+};
+
+struct mux {
+	u32 cache;
+	struct mux_control *control;
+	struct iio_channel *parent;
+	struct iio_dev *indio_dev;
+	struct iio_chan_spec *c;
+	struct mux_child *child;
+};
+
+static int iio_mux_select(struct mux *mux, int idx)
+{
+	struct mux_child *child = &mux->child[idx];
+	int ret;
+	int i;
+
+	ret = mux_control_select(mux->control, child->reg);
+	if (ret < 0)
+		return ret;
+
+	if (mux->cache == child->reg)
+		return 0;
+
+	for (i = 0; i < child->num_ext_info - 1; i += 2) {
+		const char *value = child->ext_info[i + 1];
+
+		ret = iio_write_channel_ext_info(mux->parent,
+						 child->ext_info[i],
+						 value, strlen(value));
+		if (ret < 0) {
+			mux_control_deselect(mux->control);
+			return ret;
+		}
+	}
+	mux->cache = child->reg;
+
+	return 0;
+}
+
+static void iio_mux_deselect(struct mux *mux)
+{
+	mux_control_deselect(mux->control);
+}
+
+static int mux_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int *val, int *val2, long mask)
+{
+	struct mux *mux = iio_priv(indio_dev);
+	int idx = chan - mux->c;
+	int ret;
+
+	ret = iio_mux_select(mux, idx);
+	if (ret < 0)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = iio_read_channel_raw(mux->parent, val);
+		break;
+
+	case IIO_CHAN_INFO_SCALE:
+		ret = iio_read_channel_scale(mux->parent, val, val2);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	iio_mux_deselect(mux);
+
+	return ret;
+}
+
+static int mux_read_avail(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  const int **vals, int *type, int *length,
+			  long mask)
+{
+	struct mux *mux = iio_priv(indio_dev);
+	int idx = chan - mux->c;
+	int ret;
+
+	ret = iio_mux_select(mux, idx);
+	if (ret < 0)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		*type = IIO_VAL_INT;
+		ret = iio_read_avail_channel_raw(mux->parent, vals, length);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	iio_mux_deselect(mux);
+
+	return ret;
+}
+
+static int mux_write_raw(struct iio_dev *indio_dev,
+			 struct iio_chan_spec const *chan,
+			 int val, int val2, long mask)
+{
+	struct mux *mux = iio_priv(indio_dev);
+	int idx = chan - mux->c;
+	int ret;
+
+	ret = iio_mux_select(mux, idx);
+	if (ret < 0)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = iio_write_channel_raw(mux->parent, val);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	iio_mux_deselect(mux);
+
+	return ret;
+}
+
+static const struct iio_info mux_info = {
+	.read_raw = mux_read_raw,
+	.read_avail = mux_read_avail,
+	.write_raw = mux_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int mux_configure_channel(struct device *dev, struct mux *mux,
+				 struct device_node *child_np, int idx)
+{
+	struct mux_child *child = &mux->child[idx];
+	struct iio_chan_spec *c = &mux->c[idx];
+	const struct iio_chan_spec *pc = mux->parent->channel;
+	int i;
+	int ret;
+
+	c->indexed = 1;
+	c->channel = idx;
+	c->output = pc->output;
+	c->datasheet_name = child_np->name;
+
+	ret = iio_get_channel_type(mux->parent, &c->type);
+	if (ret < 0) {
+		dev_err(dev, "failed to get parent channel type\n");
+		return ret;
+	}
+
+	if (iio_channel_has_info(pc, IIO_CHAN_INFO_RAW))
+		c->info_mask_separate |= BIT(IIO_CHAN_INFO_RAW);
+	if (iio_channel_has_info(pc, IIO_CHAN_INFO_SCALE))
+		c->info_mask_separate |= BIT(IIO_CHAN_INFO_SCALE);
+
+	if (iio_channel_has_available(pc, IIO_CHAN_INFO_RAW))
+		c->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW);
+
+	ret = of_property_read_u32(child_np, "reg", &child->reg);
+	if (ret < 0) {
+		dev_err(dev, "no reg property for node '%s'\n", child_np->name);
+		return ret;
+	}
+
+	for (i = 0; i < idx; ++i) {
+		if (mux->child[i].reg == child->reg) {
+			dev_err(dev, "double use of reg %d\n", child->reg);
+			return -EINVAL;
+		}
+	}
+
+	ret = of_property_read_string_array(child_np, "iio-ext-info", NULL, 0);
+	if (ret <= 0)
+		return 0;
+
+	child->ext_info = devm_kzalloc(dev, sizeof(*child->ext_info) * ret,
+				       GFP_KERNEL);
+	if (!child->ext_info)
+		return -ENOMEM;
+
+	child->num_ext_info = ret;
+	ret = of_property_read_string_array(child_np, "iio-ext-info",
+					    child->ext_info,
+					    child->num_ext_info);
+	if (ret != child->num_ext_info)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child_np;
+	struct iio_dev *indio_dev;
+	struct mux *mux;
+	int children;
+	int sizeof_priv;
+	int idx;
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	children = of_get_child_count(np);
+	if (children <= 0) {
+		dev_err(dev, "not even a single child\n");
+		return -EINVAL;
+	}
+
+	sizeof_priv = sizeof(*mux);
+	sizeof_priv += sizeof(*mux->child) * children;
+	sizeof_priv += sizeof(*mux->c) * children;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof_priv);
+	if (!indio_dev)
+		return -ENOMEM;
+
+	mux = iio_priv(indio_dev);
+	mux->child = (struct mux_child *)(mux + 1);
+	mux->c = (struct iio_chan_spec *)(mux->child + children);
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	mux->parent = devm_iio_channel_get(dev, "parent");
+	if (IS_ERR(mux->parent)) {
+		if (PTR_ERR(mux->parent) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get parent channel\n");
+		return PTR_ERR(mux->parent);
+	}
+
+	indio_dev->name = dev_name(dev);
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &mux_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = mux->c;
+	indio_dev->num_channels = children;
+
+	idx = 0;
+	for_each_child_of_node(np, child_np) {
+		ret = mux_configure_channel(dev, mux, child_np, idx);
+		if (ret < 0)
+			return ret;
+		idx++;
+	}
+
+	mux->control = devm_mux_control_get(dev, "mux");
+	if (IS_ERR(mux->control)) {
+		if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get control-mux\n");
+		return PTR_ERR(mux->control);
+	}
+
+	ret = devm_iio_device_register(dev, indio_dev);
+	if (ret) {
+		dev_err(dev, "failed to register iio device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id mux_match[] = {
+	{ .compatible = "iio-mux" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_match);
+
+static struct platform_driver mux_driver = {
+	.probe = mux_probe,
+	.driver = {
+		.name = "iio-mux",
+		.of_match_table = mux_match,
+	},
+};
+module_platform_driver(mux_driver);
+
+MODULE_DESCRIPTION("IIO multiplexer driver");
+MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
+MODULE_LICENSE("GPL v2");
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 6/7] dt-bindings: i2c: i2c-mux-simple: document i2c-mux-simple bindings
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479340111-1259-1-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

---
 .../devicetree/bindings/i2c/i2c-mux-simple.txt     | 91 ++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt
new file mode 100644
index 000000000000..fec1ab39ad64
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-simple.txt
@@ -0,0 +1,91 @@
+Simple I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses GPIOs to
+route the I2C signals.
+
+                                  .-----.  .-----.
+                                  | dev |  | dev |
+    .------------.                '-----'  '-----'
+    | SoC        |                   |        |
+    |            |          .--------+--------'
+    |   .------. |  .------+    child bus A, on MUX value set to 0
+    |   | I2C  |-|--| Mux  |
+    |   '------' |  '--+---+    child bus B, on MUX value set to 1
+    |   .------. |     |    '----------+--------+--------.
+    |   | MUX- | |     |               |        |        |
+    |   | Ctrl |-|-----+            .-----.  .-----.  .-----.
+    |   '------' |                  | dev |  | dev |  | dev |
+    '------------'                  '-----'  '-----'  '-----'
+
+Required properties:
+- compatible: i2c-mux-simple,mux-locked or i2c-mux-simple,parent-locked
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- control-muxes : Node of the multiplexer that controls "Mux".
+- control-mux-names : Should be "mux".
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
+
+Optional properties:
+- idle-state: value to set the muxer to when idle. When no value is
+  given, it defaults to the last value used.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the relevant node's reg property will be fed to the mux controller.
+
+If an idle state is defined, using the idle-state (optional) property,
+whenever an access is not being made to a device on a child bus, the
+mux controller will be set according to the idle value.
+
+If an idle state is not defined, the most recently used value will be
+left programmed into hardware whenever no access is being made to a
+device on a child bus.
+
+Example:
+	control_i2c_mux: control-i2c-mux {
+		compatible = "mux-gpio";
+
+		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
+			    <&pioA 1 GPIO_ACTIVE_HIGH>;
+	};
+
+	i2c-mux {
+		compatible = "i2c-mux-simple,mux-locked";
+		i2c-parent = <&i2c1>;
+
+		control-muxes = <&control_i2c_mux>;
+		control-mux-names = "mux";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			ssd1307: oled@3c {
+				compatible = "solomon,ssd1307fb-i2c";
+				reg = <0x3c>;
+				pwms = <&pwm 4 3000>;
+				reset-gpios = <&gpio2 7 1>;
+				reset-active-low;
+			};
+		};
+
+		i2c@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pca9555: pca9555@20 {
+				compatible = "nxp,pca9555";
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x20>;
+			};
+		};
+	};
-- 
2.1.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

* [RFC PATCH 7/7] i2c: i2c-mux-simple: new driver
From: Peter Rosin @ 2016-11-16 23:48 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Peter Rosin, Wolfram Sang, Rob Herring, Mark Rutland,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Arnd Bergmann, Greg Kroah-Hartman,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479340111-1259-1-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

This is a generic simple i2c mux that uses the generic multiplexer
subsystem to do the muxing.

The user can select if the mux is to be mux-locked and parent-locked
as described in Documentation/i2c/i2c-topology.
---
 drivers/i2c/muxes/Kconfig          |  12 +++
 drivers/i2c/muxes/Makefile         |   1 +
 drivers/i2c/muxes/i2c-mux-simple.c | 172 +++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-simple.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index e280c8ecc0b5..45e80ad2d4ab 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -72,6 +72,18 @@ config I2C_MUX_REG
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mux-reg.
 
+config I2C_MUX_SIMPLE
+	tristate "Simple I2C multiplexer"
+	depends on OF
+	help
+	  If you say yes to this option, support will be included for a
+	  simple generic I2C multiplexer. This driver provides access to
+	  I2C busses connected through a MUX, which is controlled
+	  by a generic MUX controller.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mux-simple.
+
 config I2C_DEMUX_PINCTRL
 	tristate "pinctrl-based I2C demultiplexer"
 	depends on PINCTRL && OF
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 7c267c29b191..eea1fb9e6466 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
 obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
 obj-$(CONFIG_I2C_MUX_REG)	+= i2c-mux-reg.o
+obj-$(CONFIG_I2C_MUX_SIMPLE)	+= i2c-mux-simple.o
 
 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/drivers/i2c/muxes/i2c-mux-simple.c b/drivers/i2c/muxes/i2c-mux-simple.c
new file mode 100644
index 000000000000..308ecbf9d66c
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-simple.c
@@ -0,0 +1,172 @@
+/*
+ * Generic simple I2C multiplexer
+ *
+ * Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/module.h>
+#include <linux/mux.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+struct mux {
+	struct mux_control *control;
+
+	int parent;
+	int n_values;
+	u32 *values;
+};
+
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct mux *mux = i2c_mux_priv(muxc);
+
+	return mux_control_select(mux->control, chan);
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct mux *mux = i2c_mux_priv(muxc);
+
+	return mux_control_deselect(mux->control);
+}
+
+static int i2c_mux_probe_dt(struct mux *mux,
+			    struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct device_node *adapter_np, *child;
+	struct i2c_adapter *adapter;
+	int i = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
+	if (!adapter_np) {
+		dev_err(dev, "Cannot parse i2c-parent\n");
+		return -ENODEV;
+	}
+	adapter = of_find_i2c_adapter_by_node(adapter_np);
+	of_node_put(adapter_np);
+	if (!adapter)
+		return -EPROBE_DEFER;
+
+	mux->parent = i2c_adapter_id(adapter);
+	put_device(&adapter->dev);
+
+	mux->control = devm_mux_control_get(dev, "mux");
+	if (IS_ERR(mux->control)) {
+		if (PTR_ERR(mux->control) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get control-mux\n");
+		return PTR_ERR(mux->control);
+	}
+
+	mux->n_values = of_get_child_count(np);
+
+	mux->values = devm_kzalloc(dev,
+				   sizeof(*mux->values) * mux->n_values,
+				   GFP_KERNEL);
+	if (!mux->values)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		of_property_read_u32(child, "reg", mux->values + i);
+		i++;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id i2c_mux_of_match[] = {
+	{ .compatible = "i2c-mux-simple,parent-locked",
+	  .data = (void *)0, },
+	{ .compatible = "i2c-mux-simple,mux-locked",
+	  .data = (void *)1, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_of_match);
+
+static int i2c_mux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *match;
+	struct i2c_mux_core *muxc;
+	struct mux *mux;
+	struct i2c_adapter *parent;
+	int i, ret;
+
+	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return -ENOMEM;
+
+	ret = i2c_mux_probe_dt(mux, dev);
+	if (ret < 0)
+		return ret;
+
+	parent = i2c_get_adapter(mux->parent);
+	if (!parent)
+		return -EPROBE_DEFER;
+
+	muxc = i2c_mux_alloc(parent, dev, mux->n_values, 0, 0,
+			     i2c_mux_select, i2c_mux_deselect);
+	if (!muxc) {
+		ret = -ENOMEM;
+		goto alloc_failed;
+	}
+	muxc->priv = mux;
+
+	platform_set_drvdata(pdev, muxc);
+
+	match = of_match_device(of_match_ptr(i2c_mux_of_match), dev);
+	if (match)
+		muxc->mux_locked = !!of_device_get_match_data(dev);
+
+	for (i = 0; i < mux->n_values; i++) {
+		ret = i2c_mux_add_adapter(muxc, 0, mux->values[i], 0);
+		if (ret)
+			goto add_adapter_failed;
+	}
+
+	dev_info(dev, "%d port mux on %s adapter\n",
+		 mux->n_values, parent->name);
+
+	return 0;
+
+add_adapter_failed:
+	i2c_mux_del_adapters(muxc);
+alloc_failed:
+	i2c_put_adapter(parent);
+
+	return ret;
+}
+
+static int i2c_mux_remove(struct platform_device *pdev)
+{
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+
+	i2c_mux_del_adapters(muxc);
+	i2c_put_adapter(muxc->parent);
+
+	return 0;
+}
+
+static struct platform_driver i2c_mux_driver = {
+	.probe	= i2c_mux_probe,
+	.remove	= i2c_mux_remove,
+	.driver	= {
+		.name	= "i2c-mux-simple",
+		.of_match_table = i2c_mux_of_match,
+	},
+};
+module_platform_driver(i2c_mux_driver);
+
+MODULE_DESCRIPTION("Simple I2C multiplexer driver");
+MODULE_AUTHOR("Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH v5] pwm: add pwm driver for HiSilicon BVT SOCs
From: Vladimir Zapolskiy @ 2016-11-16 23:55 UTC (permalink / raw)
  To: Jian Yuan, thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
  Cc: linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuejiancheng-C8/M+/jPZTeaMJb+Lgu22Q,
	kevin.lixu-C8/M+/jPZTeaMJb+Lgu22Q,
	jalen.hsu-C8/M+/jPZTeaMJb+Lgu22Q
In-Reply-To: <1479289833-232200-1-git-send-email-yuanjian12-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>

On 11/16/2016 11:50 AM, Jian Yuan wrote:
> From: yuanjian <yuanjian12-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>
> Add PWM driver for the PWM controller found on HiSilicon BVT SOCs, like Hi3519V100, Hi3516CV300, etc.
> The PWM controller is primarily in charge of controlling P-Iris lens.
>
> Reviewed-by: Jiancheng Xue <xuejiancheng-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> Signed-off-by: Jian Yuan <yuanjian12-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> ---
> Change Log:
> v5:
> remove the generic compatible string "hisilicon, hibvt-pwm".
> v4:
> Add #pwm-cells in the bindings document.
> v3:
> fixed issues pointed by thierry.
> Add PWM compatible string for Hi3519V100.
> Implement .apply() function which support atomic, instead of .enable()/.disable()/.config().
> v2:
> The number of PWMs is change to be probeable based on the compatible string.
>
>  .../devicetree/bindings/pwm/pwm-hibvt.txt          |  22 ++
>  drivers/pwm/Kconfig                                |   9 +
>  drivers/pwm/Makefile                               |   1 +
>  drivers/pwm/pwm-hibvt.c                            | 269 +++++++++++++++++++++
>  4 files changed, 301 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-hibvt.txt
>  create mode 100644 drivers/pwm/pwm-hibvt.c
>
> diff --git a/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt b/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt
> new file mode 100644
> index 0000000..fe63950
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt
> @@ -0,0 +1,22 @@
> +Hisilicon PWM controller
> +
> +Required properties:
> +-compatible: should contain one SoC specific compatible string
> + The SoC specific strings supported including:
> +	"hisilicon,hi3516cv300-pwm"
> +	"hisilicon,hi3519v100-pwm"
> +- reg: physical base address and length of the controller's registers.
> +- clocks: phandle and clock specifier of the PWM reference clock.
> +- resets: phandle and reset specifier for the PWM controller reset.
> +- #pwm-cells: Should be 2. See pwm.txt in this directory for a description of

Since the controller has separate polarity control register, and
the driver handles polarity settings, please test/change #pwm-cells
set to 3. It is better to do it right now before someone wants
to change number of cells in future and support polarity specified
in DTB.

> +  the cells format.
> +
> +Example:
> +	pwm: pwm@12130000 {
> +

Remove empty line above.

> +		compatible = "hisilicon,hi3516cv300-pwm";
> +		reg = <0x12130000 0x10000>;
> +		clocks = <&crg_ctrl HI3516CV300_PWM_CLK>;
> +		resets = <&crg_ctrl 0x38 0>;
> +		#pwm-cells = <2>;

After tesing #pwm-cells = <3> don't forget to updated this line.

> +	};

--
With best wishes,
Vladimir
--
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 v8 00/16] mmc: sdhci-msm: Add clk-rates, DDR, HS400 support
From: Jeremy McNicoll @ 2016-11-17  0:08 UTC (permalink / raw)
  To: Ritesh Harjani, ulf.hansson, linux-mmc, adrian.hunter, sboyd,
	andy.gross
  Cc: shawn.lin, devicetree, linux-clk, david.brown, linux-arm-msm,
	georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
	asutoshd, david.griego, stummala, venkatg, rnayak, pramod.gurav,
	jeremymc
In-Reply-To: <1479312052-22396-1-git-send-email-riteshh@codeaurora.org>

On 2016-11-16 8:00 AM, Ritesh Harjani wrote:
> Hi,
>
> This is v8 version of the patch series which adds support for MSM8996.
> Adds HS400 driver support as well.
> These are tested on internal msm8996 & db410c HW.
>
> Changes from v7 -> v8 :-
> 1. Added patch 005 to add dt bindings for xo_clock.
> 2. Added patch 009 to factor out sdhci_enable_clock as discussed on v7 series.
> 2.a. Modified patch 010 by making use of sdhci_enable_clock.
> 2.b. Addressed Stephen's comment on patch 010 to call clk_set_rate unconditionally.
> 3. Addressed Stephen comments to remove unncessary one line comments, braces and other
> minor comments.
> 4. Added changes from Jeremy in patch 002 for gcc-msm8994 as well for sdcc clk_rcg2_floor_ops.
> minor comments.
>
> v7 series was verified on msm8994 target by Jeremy McNicoll.


v7 was verified on my Nexus 5X (msm8992).

-jeremy


^ permalink raw reply

* Re: [PATCH v8 05/16] dt-bindings: sdhci-msm: Add xo_clock property
From: Ritesh Harjani @ 2016-11-17  0:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: ulf.hansson, linux-mmc, adrian.hunter, andy.gross, shawn.lin,
	devicetree, linux-clk, david.brown, linux-arm-msm, georgi.djakov,
	alex.lemberg, mateusz.nowak, Yuliy.Izrailov, asutoshd,
	david.griego, stummala, venkatg, rnayak, pramod.gurav, jeremymc
In-Reply-To: <20161116191335.GH25626@codeaurora.org>

Hi,

On 11/17/2016 12:43 AM, Stephen Boyd wrote:
> On 11/16, Ritesh Harjani wrote:
>> Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
>> ---
>>  Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>> index 485483a..243c9f0 100644
>> --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>> +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
>> @@ -17,6 +17,7 @@ Required properties:
>>  	"iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required)
>>  	"core"	- SDC MMC clock (MCLK) (required)
>>  	"bus"	- SDCC bus voter clock (optional)
>> +	"xo_clock" - TCXO clock (optional)
>
> I'd prefer we just call it "xo". We usually leave out _clk or
> _clock from clock names because it's redundant.
Ok. I will send patch 004(DT), 005(DT-documentation), 006(driver) & 
012(DT conflicts) again. Since these will be affected with above change.

>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v8 04/16] ARM: dts: Add xo to sdhc clock node on qcom platforms
From: Ritesh Harjani @ 2016-11-17  0:43 UTC (permalink / raw)
  To: ulf.hansson, linux-mmc, adrian.hunter, sboyd, andy.gross
  Cc: shawn.lin, devicetree, linux-clk, david.brown, linux-arm-msm,
	georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
	asutoshd, david.griego, stummala, venkatg, rnayak, pramod.gurav,
	jeremymc, Ritesh Harjani
In-Reply-To: <1479312052-22396-5-git-send-email-riteshh@codeaurora.org>

Add xo entry to sdhc clock node on all qcom platforms.

Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
 arch/arm/boot/dts/qcom-apq8084.dtsi   | 16 ++++++++++------
 arch/arm/boot/dts/qcom-msm8974.dtsi   | 16 ++++++++++------
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 10 ++++++----
 arch/arm64/boot/dts/qcom/msm8996.dtsi |  9 +++++----
 4 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index 39eb7a4..f756cbb 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -182,13 +182,13 @@
 	};
 
 	clocks {
-		xo_board {
+		xo_board: xo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <19200000>;
 		};
 
-		sleep_clk {
+		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
@@ -416,8 +416,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 123 0>, <0 138 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC1_APPS_CLK>,
+				 <&gcc GCC_SDCC1_AHB_CLK>,
+				 <&xo_board 0>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
@@ -427,8 +429,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 125 0>, <0 221 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC2_APPS_CLK>,
+				 <&gcc GCC_SDCC2_AHB_CLK>,
+				 <&xo_board 0>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index d210947..6333415 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -220,13 +220,13 @@
 	};
 
 	clocks {
-		xo_board {
+		xo_board: xo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <19200000>;
 		};
 
-		sleep_clk {
+		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
@@ -558,8 +558,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 123 0>, <0 138 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC1_APPS_CLK>,
+				 <&gcc GCC_SDCC1_AHB_CLK>,
+				 <&xo_board 0>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
@@ -569,8 +571,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 125 0>, <0 221 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC2_APPS_CLK>,
+				 <&gcc GCC_SDCC2_AHB_CLK>,
+				 <&xo_board 0>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 466ca57..7bce1b3 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -512,8 +512,9 @@
 			interrupts = <0 123 0>, <0 138 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
 			clocks = <&gcc GCC_SDCC1_APPS_CLK>,
-				 <&gcc GCC_SDCC1_AHB_CLK>;
-			clock-names = "core", "iface";
+				 <&gcc GCC_SDCC1_AHB_CLK>,
+				 <&xo_board 0>;
+			clock-names = "core", "iface", "xo";
 			bus-width = <8>;
 			non-removable;
 			status = "disabled";
@@ -527,8 +528,9 @@
 			interrupts = <0 125 0>, <0 221 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
 			clocks = <&gcc GCC_SDCC2_APPS_CLK>,
-				 <&gcc GCC_SDCC2_AHB_CLK>;
-			clock-names = "core", "iface";
+				 <&gcc GCC_SDCC2_AHB_CLK>,
+				 <&xo_board 0>;
+			clock-names = "core", "iface", "xo";
 			bus-width = <4>;
 			status = "disabled";
 		};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 338f82a..86bfc2d 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -192,14 +192,14 @@
 	};
 
 	clocks {
-		xo_board {
+		xo_board: xo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <19200000>;
 			clock-output-names = "xo_board";
 		};
 
-		sleep_clk {
+		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32764>;
@@ -347,9 +347,10 @@
 			 interrupts = <0 125 0>, <0 221 0>;
 			 interrupt-names = "hc_irq", "pwr_irq";
 
-			 clock-names = "iface", "core";
+			 clock-names = "iface", "core", "xo";
 			 clocks = <&gcc GCC_SDCC2_AHB_CLK>,
-			 <&gcc GCC_SDCC2_APPS_CLK>;
+			 <&gcc GCC_SDCC2_APPS_CLK>,
+			 <&xo_board 0>;
 			 bus-width = <4>;
 		 };
 
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.


^ permalink raw reply related

* [PATCH v8 05/16] dt-bindings: sdhci-msm: Add xo property
From: Ritesh Harjani @ 2016-11-17  0:47 UTC (permalink / raw)
  To: ulf.hansson, linux-mmc, adrian.hunter, sboyd, andy.gross
  Cc: shawn.lin, devicetree, linux-clk, david.brown, linux-arm-msm,
	georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
	asutoshd, david.griego, stummala, venkatg, rnayak, pramod.gurav,
	jeremymc, Ritesh Harjani
In-Reply-To: <20161116191335.GH25626@codeaurora.org>

Add "xo" property which is tcxo clock.

Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 485483a..4e61086 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -17,6 +17,7 @@ Required properties:
 	"iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required)
 	"core"	- SDC MMC clock (MCLK) (required)
 	"bus"	- SDCC bus voter clock (optional)
+	"xo" - TCXO clock (optional)
 
 Example:
 
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.


^ permalink raw reply related

* [PATCH v8 06/16] mmc: sdhci-msm: Update DLL reset sequence
From: Ritesh Harjani @ 2016-11-17  0:50 UTC (permalink / raw)
  To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, andy.gross-QSEj5FYQhm4dnm+yROfE0A
  Cc: shawn.lin-TNX95d0MmH7DzftRWevZcw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	david.brown-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
	mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
	Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
	asutoshd-sgV2jX0FEOL9JmXXK+q4OQ,
	david.griego-QSEj5FYQhm4dnm+yROfE0A,
	stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	pramod.gurav-QSEj5FYQhm4dnm+yROfE0A,
	jeremymc-H+wXaHxf7aLQT0dZR+AlfA, Ritesh Harjani
In-Reply-To: <1479312052-22396-7-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

From: Venkat Gopalakrishnan <venkatg-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

SDCC core with minor version >= 0x42 introduced new 14lpp
DLL. This has additional requirements in the reset sequence
for DLL tuning. Make necessary changes as needed.

Without this patch we see below errors on such SDHC controllers
	sdhci_msm 7464900.sdhci: mmc0: DLL failed to LOCK
	mmc0: tuning execution failed: -110

Signed-off-by: Venkat Gopalakrishnan <venkatg-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Ritesh Harjani <riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Acked-by: Adrian Hunter <adrian.hunter-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/mmc/host/sdhci-msm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2dcbeb0..fc093b8 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -59,6 +59,10 @@
 #define CORE_DLL_CONFIG		0x100
 #define CORE_DLL_STATUS		0x108
 
+#define CORE_DLL_CONFIG_2	0x1b4
+#define CORE_FLL_CYCLE_CNT	BIT(18)
+#define CORE_DLL_CLOCK_DISABLE	BIT(21)
+
 #define CORE_VENDOR_SPEC	0x10c
 #define CORE_CLK_PWRSAVE	BIT(1)
 
@@ -77,7 +81,9 @@ struct sdhci_msm_host {
 	struct clk *clk;	/* main SD/MMC bus clock */
 	struct clk *pclk;	/* SDHC peripheral bus clock */
 	struct clk *bus_clk;	/* SDHC bus voter clock */
+	struct clk *xo_clk;	/* TCXO clk needed for FLL feature of cm_dll*/
 	struct mmc_host *mmc;
+	bool use_14lpp_dll_reset;
 };
 
 /* Platform specific tuning */
@@ -305,6 +311,8 @@ static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
 static int msm_init_cm_dll(struct sdhci_host *host)
 {
 	struct mmc_host *mmc = host->mmc;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	int wait_cnt = 50;
 	unsigned long flags;
 	u32 config;
@@ -320,6 +328,16 @@ static int msm_init_cm_dll(struct sdhci_host *host)
 	config &= ~CORE_CLK_PWRSAVE;
 	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
 
+	if (msm_host->use_14lpp_dll_reset) {
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+		config &= ~CORE_CK_OUT_EN;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config |= CORE_DLL_CLOCK_DISABLE;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+	}
+
 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
 	config |= CORE_DLL_RST;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
@@ -329,6 +347,28 @@ static int msm_init_cm_dll(struct sdhci_host *host)
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 	msm_cm_dll_set_freq(host);
 
+	if (msm_host->use_14lpp_dll_reset &&
+	    !IS_ERR_OR_NULL(msm_host->xo_clk)) {
+		u32 mclk_freq = 0;
+
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config &= CORE_FLL_CYCLE_CNT;
+		if (config)
+			mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8),
+					clk_get_rate(msm_host->xo_clk));
+		else
+			mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4),
+					clk_get_rate(msm_host->xo_clk));
+
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config &= ~(0xFF << 10);
+		config |= mclk_freq << 10;
+
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+		/* wait for 5us before enabling DLL clock */
+		udelay(5);
+	}
+
 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
 	config &= ~CORE_DLL_RST;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
@@ -337,6 +377,13 @@ static int msm_init_cm_dll(struct sdhci_host *host)
 	config &= ~CORE_DLL_PDN;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 
+	if (msm_host->use_14lpp_dll_reset) {
+		msm_cm_dll_set_freq(host);
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config &= ~CORE_DLL_CLOCK_DISABLE;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+	}
+
 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
 	config |= CORE_DLL_EN;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
@@ -590,6 +637,16 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 		goto pclk_disable;
 	}
 
+	/*
+	 * xo clock is needed for FLL feature of cm_dll.
+	 * In case if xo clock is not mentioned in DT, warn and proceed.
+	 */
+	msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(msm_host->xo_clk)) {
+		ret = PTR_ERR(msm_host->xo_clk);
+		dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret);
+	}
+
 	/* Vote for maximum clock rate for maximum performance */
 	ret = clk_set_rate(msm_host->clk, INT_MAX);
 	if (ret)
@@ -635,6 +692,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
 		core_version, core_major, core_minor);
 
+	if (core_major == 1 && core_minor >= 0x42)
+		msm_host->use_14lpp_dll_reset = true;
+
 	/*
 	 * Support for some capabilities is not advertised by newer
 	 * controller versions and must be explicitly enabled.
-- 
The Qualcomm Innovation Center, Inc. is a member of 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 related

* [PATCH v8 12/16] arm64: dts: qcom: msm8916: Add ddr support to sdhc1
From: Ritesh Harjani @ 2016-11-17  0:52 UTC (permalink / raw)
  To: ulf.hansson, linux-mmc, adrian.hunter, sboyd, andy.gross
  Cc: shawn.lin, devicetree, linux-clk, david.brown, linux-arm-msm,
	georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
	asutoshd, david.griego, stummala, venkatg, rnayak, pramod.gurav,
	jeremymc, Ritesh Harjani
In-Reply-To: <1479312052-22396-13-git-send-email-riteshh@codeaurora.org>

This adds mmc-ddr-1_8v support to DT for sdhc1 of msm8916.

Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 7bce1b3..1be5cd4 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -515,6 +515,7 @@
 				 <&gcc GCC_SDCC1_AHB_CLK>,
 				 <&xo_board 0>;
 			clock-names = "core", "iface", "xo";
+			mmc-ddr-1_8v;
 			bus-width = <8>;
 			non-removable;
 			status = "disabled";
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project.


^ permalink raw reply related


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