* Re: [PATCH v3 1/3] dma: Support multiple interleaved frames with non-contiguous memory
From: Srikanth Thokala @ 2014-02-18 17:46 UTC (permalink / raw)
To: Jassi Brar
Cc: Srikanth Thokala, Williams, Dan J, Koul, Vinod, michal.simek,
Grant Likely, robh+dt, devicetree, Levente Kurusa,
Lars-Peter Clausen, lkml, dmaengine, Andy Shevchenko,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAJe_ZhdOmu3k9gbPdQzPteyzwsMA8OzWHdhHnXudbF=X7JMhVQ@mail.gmail.com>
On Tue, Feb 18, 2014 at 10:20 PM, Jassi Brar <jaswinder.singh@linaro.org> wrote:
> On 18 February 2014 16:58, Srikanth Thokala <sthokal@xilinx.com> wrote:
>> On Mon, Feb 17, 2014 at 3:27 PM, Jassi Brar <jaswinder.singh@linaro.org> wrote:
>>> On 15 February 2014 17:30, Srikanth Thokala <sthokal@xilinx.com> wrote:
>>>> The current implementation of interleaved DMA API support multiple
>>>> frames only when the memory is contiguous by incrementing src_start/
>>>> dst_start members of interleaved template.
>>>>
>>>> But, when the memory is non-contiguous it will restrict slave device
>>>> to not submit multiple frames in a batch. This patch handles this
>>>> issue by allowing the slave device to send array of interleaved dma
>>>> templates each having a different memory location.
>>>>
>>> How fragmented could be memory in your case? Is it inefficient to
>>> submit separate transfers for each segment/frame?
>>> It will help if you could give a typical example (chunk size and gap
>>> in bytes) of what you worry about.
>>
>> With scatter-gather engine feature in the hardware, submitting separate
>> transfers for each frame look inefficient. As an example, our DMA engine
>> supports up to 16 video frames, with each frame (a typical video frame
>> size) being contiguous in memory but frames are scattered into different
>> locations. We could not definitely submit frame by frame as it would be
>> software overhead (HW interrupting for each frame) resulting in video lags.
>>
> IIUIC, it is 30fps and one dma interrupt per frame ... it doesn't seem
> inefficient at all. Even poor-latency audio would generate a higher
> interrupt-rate. So the "inefficiency concern" doesn't seem valid to
> me.
>
> Not to mean we shouldn't strive to reduce the interrupt-rate further.
> Another option is to emulate the ring-buffer scheme of ALSA.... which
> should be possible since for a session of video playback the frame
> buffers' locations wouldn't change.
>
> Yet another option is to use the full potential of the
> interleaved-xfer api as such. It seems you confuse a 'video frame'
> with the interleaved-xfer api's 'frame'. They are different.
>
> Assuming your one video frame is F bytes long and Gk is the gap in
> bytes between end of frame [k] and start of frame [k+1] and Gi != Gj
> for i!=j
> In the context of interleaved-xfer api, you have just 1 Frame of 16
> chunks. Each chunk is Fbytes and the inter-chunk-gap(ICG) is Gk where
> 0<=k<15
> So for your use-case .....
> dma_interleaved_template.numf = 1 /* just 1 frame */
> dma_interleaved_template.frame_size = 16 /* containing 16 chunks */
> ...... //other parameters
>
> You have 3 options to choose from and all should work just as fine.
> Otherwise please state your problem in real numbers (video-frames'
> size, count & gap in bytes).
Initially I interpreted interleaved template the same. But, Lars corrected me
in the subsequent discussion and let me put it here briefly,
In the interleaved template, each frame represents a line of size denoted by
chunk.size and the stride by icg. 'numf' represent number of frames i.e.
number of lines.
In video frame context,
chunk.size -> hsize
chunk.icg -> stride
numf -> vsize
and frame_size is always 1 as it will have only one chunk in a line.
So, the API would not allow to pass multiple frames and we came up with a
resolution to pass an array of interleaved template structs to handle this.
Srikanth
>
> -Jassi
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* Re: [PATCH v2 2/3] usb: chipidea: msm: Add device tree support
From: Sergei Shtylyov @ 2014-02-18 17:53 UTC (permalink / raw)
To: Ivan T. Ivanov, Peter Chen, Grant Likely, Rob Herring
Cc: Greg Kroah-Hartman, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392729681-21022-3-git-send-email-iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
Hello.
On 02/18/2014 04:21 PM, Ivan T. Ivanov wrote:
> From: "Ivan T. Ivanov" <iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
> Allows controller to be specified via device tree.
> Pass PHY phandle specified in DT to core driver.
> Signed-off-by: Ivan T. Ivanov <iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 23 ++++++++++++++++++++++-
> 1 file changed, 22 insertions(+), 1 deletion(-)
You also need to describe the binding you're creating in
Documentation/devicetree/bindings/usb/<file>.txt.
WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Jason Cooper @ 2014-02-18 17:56 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Arnd Bergmann,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Grant Likely, Jason Gunthorpe,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Laura Abbott,
Kees Cook, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Rob Herring, Kumar Gala
In-Reply-To: <CAMuHMdW7S=o4oHVsNtYo0i_giB5cgWhygo-GgSaA1Kur6m3vng-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Mon, Feb 17, 2014 at 10:07:50PM +0100, Geert Uytterhoeven wrote:
> On Mon, Feb 17, 2014 at 7:23 PM, Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org> wrote:
> >> Could we use a faster hash function that scans the entire device tree and
> >> then just feed the output of that into add_device_randomness? We probably
> >> can't expect that there is a lot of entropy in the DT blob, so the
> >> result wouldn't be all that different in terms of quality of the random
> >> seed.
> >
> > I think it would be easier to identify the few attributes that differ
> > from board to board (mac address, serial number, etc), and differ from
> > boot to boot (random-seed, timestamp) and just extract and feed those
> > in.
>
> Isn't identifying those (mostly) a manual process?
> Calculating a fast hash is fully automatic.
The list would be pretty short, and once created wouldn't likely change
too often. But it really depends on the 'fast hash'. if the two
methods have comparable speed, I'd definitely prefer the hash. Easier
to maintain.
thx,
Jason.
--
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/2] mfd: palmas: support IRQ inversion at the board level
From: Lee Jones @ 2014-02-18 18:01 UTC (permalink / raw)
To: Stephen Warren
Cc: Samuel Ortiz, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, J Keerthy, Ian Lartey,
Stefan Agner, josephl-DDmLM1+adcrQT0dZR+AlfA,
ldewangan-DDmLM1+adcrQT0dZR+AlfA, Stephen Warren
In-Reply-To: <53039B6D.8080004-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
> >> From: Stephen Warren <swarren-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >>
> >> Some boards or SoCs have an inverter between the PMIC IRQ output pin and
> >> the IRQ controller input signal.
> >>
> >> The IRQ specifier in DT is meant to represent the IRQ flags at the input
> >> to the IRQ controller.
> >>
> >> The Palmas HW's IRQ output has configurable polarity. The driver
> >> currently selects the output polarity by querying the input polarity at
> >> the IRQ controller. This works fine if the IRQ signal is routed directly
> >> from the PMIC to the IRQ controller with no intervening logic. However,
> >> if the signal is inverted between the two, this automatic polarity
> >> selection gets the wrong answer.
> >>
> >> Add an additional optional DT and platform data parameter which indicates
> >> that such an inversion occurs. If this option is enabled, the Palmas
> >> driver will configure its IRQ output to the opposite polarity of the IRQ
> >> controller's input.
> >>
> >> An alternative would have been to add a new non-optional DT parameter to
> >> indicate the exact desired output polarity. However, this would have been
> >> an incompatible change to the DT binding.
> >>
> >> Signed-off-by: Stephen Warren <swarren-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >> ---
> >> If this patch could be applied to its own branch (w/ signed tag) in the
> >> MFD tree, that would great; then I can pull patch 1/2 into the Tegra tree
> >> so that I can apply patch 2/2 to the Tegra tree. Thanks.
> >> ---
> >> Documentation/devicetree/bindings/mfd/palmas.txt | 6 ++++++
> >> drivers/mfd/palmas.c | 4 ++++
> >> include/linux/mfd/palmas.h | 1 +
> >> 3 files changed, 11 insertions(+)
> >
> > For the core changes:
> > Acked-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> Thanks. Since you ack'd this and are an MFD maintainer, was that an
> indication that I should take this patch through the Tegra tree?
No, it was an indication that we still require more Acks. :)
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH] of_mdio: fix phy interrupt passing
From: Sergei Shtylyov @ 2014-02-18 18:06 UTC (permalink / raw)
To: Grant Likely, Ben Dooks
Cc: linux-kernel, devicetree, linux-kernel, netdev, linux-sh
In-Reply-To: <20140218170202.424D7C40517@trevor.secretlab.ca>
Hello.
On 02/18/2014 08:02 PM, Grant Likely wrote:
>>> On Mon, 17 Feb 2014 16:29:40 +0000, Ben Dooks <ben.dooks@codethink.co.uk> wrote:
>>>> The of_mdiobus_register_phy() is not setting phy->irq this causing
>>>> some drivers to incorrectly assume that the PHY does not have an
>>>> IRQ associated with it or install an interrupt handler for the
>>>> PHY.
>>>> Simplify the code setting irq and set the phy->irq at the same
>>>> time so that the case if mdio->irq is not NULL is easier to read.
>>>> This fixes the issue:
>>>> net eth0: attached PHY 1 (IRQ -1) to driver Micrel KSZ8041RNLI
>>>> to the correct:
>>>> net eth0: attached PHY 1 (IRQ 416) to driver Micrel KSZ8041RNLI
>>>> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
>>>> ---
>>>> drivers/of/of_mdio.c | 12 ++++++------
>>>> 1 file changed, 6 insertions(+), 6 deletions(-)
>>>> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
>>>> index 875b7b6..7b3e7b0 100644
>>>> --- a/drivers/of/of_mdio.c
>>>> +++ b/drivers/of/of_mdio.c
>>>> @@ -44,7 +44,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
>>>> {
>>>> struct phy_device *phy;
>>>> bool is_c45;
>>>> - int rc, prev_irq;
>>>> + int rc;
>>>> u32 max_speed = 0;
>>>>
>>>> is_c45 = of_device_is_compatible(child,
>>>> @@ -55,11 +55,11 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
>>>> return 1;
>>>>
>>>> if (mdio->irq) {
>>>> - prev_irq = mdio->irq[addr];
>>>> - mdio->irq[addr] =
>>>> - irq_of_parse_and_map(child, 0);
>>>> - if (!mdio->irq[addr])
>>>> - mdio->irq[addr] = prev_irq;
>>> I cannot for the life for me remeber why the code was structured that
>>> way. Your change is better.
>>>> + rc = irq_of_parse_and_map(child, 0);
>>>> + if (rc > 0) {
>>>> + mdio->irq[addr] = rc;
>>>> + phy->irq = rc;
>>>> + }
>>>> }
>>> The outer if is merely protecting against no irq array being allocated
>>> for the bus. Would not the following be better:
>>> rc = irq_of_parse_and_map(child, 0);
>>> if (rc > 0) {
>>> phy->irq = rc;
>>> if (mdio->irq)
>>> mdio->irq[addr] = rc;
>>> }
>> Thanks, that makes sense, although we've both failed to work
>> out if mdio->irq is set, and rc <= 0 case, so:
>> rc = irq_of_parse_and_map(child, 0);
>> if (rc > 0) {
>> phy->irq = rc;
>> if (mdio->irq)
>> mdio->irq[addr] = rc;
>> } else {
>> if (mdio->irq)
>> phy->irq = mdio->irq[addr];
>> }
> Is this actually a valid thing to do? I think the only time mdio->irq[]
> is non-zero is when it is set to PHY_POLL. Is it valid to set phy->irq
> to PHY_POLL? I didn't think it was.
It is valid, AFAIK.
> g.
>> --
>> Ben Dooks http://www.codethink.co.uk/
>> Senior Engineer Codethink - Providing Genius
WBR, Sergei
^ permalink raw reply
* Re: [PATCH v4 1/7] Documentation: Add device tree bindings for Freescale i.MX GPC
From: Arnd Bergmann @ 2014-02-18 18:10 UTC (permalink / raw)
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Philipp Zabel, Shawn Guo, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
Rob Herring
In-Reply-To: <1392737687-25003-2-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
On Tuesday 18 February 2014 16:34:41 Philipp Zabel wrote:
> +
> +Example of a device that is part of a power domain:
> +
> + vpu: vpu@02040000 {
> + reg = <0x02040000 0x3c000>;
> + /* ... */
> + fsl,power-domain = <&pd_pu>;
> + /* ... */
> + };
> +
I'm really not too happy about platforms starting to add random
bindings for power domains. Unfortunately I didn't catch exynos
doing this first, but I don't want to see another platform like
that.
Can we please come up with a proper generic power domain binding
first and then add platform specific users?
Arnd
--
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: devicetree repository separation/migration
From: Jason Cooper @ 2014-02-18 18:18 UTC (permalink / raw)
To: Sascha Hauer
Cc: Grant Likely, Rob Herring, Ian Campbell, pawel.moll-5wv7dgnIgG8,
mark.rutland-5wv7dgnIgG8, galak-sgV2jX0FEOL9JmXXK+q4OQ,
rob-VoJi6FS/r0vR7s880joybQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
devicetree-spec-u79uwXL29TY76Z2rM5mHXA,
devicetree-compiler-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20140218155750.GS17250-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
On Tue, Feb 18, 2014 at 04:57:50PM +0100, Sascha Hauer wrote:
> On Mon, Feb 17, 2014 at 01:05:44PM -0500, Jason Cooper wrote:
...
> > - Is the Linux development workflow ready for devicetree to move out
> > of the Linux Kernel?
>
> I hope so since keeping the devicetrees in sync with the kernel is a
> pain for all external users.
Well, I haven't heard any screams yet. I suspect people are waiting for
details on the exact form it would take before complaining...
> > - How do we envision projects will use it? git submodule? reference
> > a version tag? (this is primarily targeted at bootloaders that need
> > to compile in a dtb or subset of a dtb into the bootloader)
>
> I would prefer to use it as a submodule.
ok. I've often thought that was the right solution for several things
(dtc.git inside the kernel tree), but no one ever seemed to speak of it
or bring it up. Kinda like leprosy.
It does add an extra step to build process for new users. Although that
could be handled in the Makefile.
> I'll likely need some barebox specific additions to the devicetrees.
> Right now our idea is to leave the provided devicetrees untouched and
> instead of compiling the board dts files directly we create
> <boardname>-barebox.dts files which include the original board files.
> That would allow us to provide additional information to barebox
> without having to carry patches for the devicetrees.
So the resulting <boardname>-barebox.dtb is compiled into the barebox
binary? Is the dtb passed to the kernel independently upgradeable?
Why not post binding/dts patches for 'barebox,...' attributes that you
need?
> > Other thoughts I may have missed?
>
> It will be interesting to see which rules should apply for merging new
> bindings. I know that devicetrees should be OS agnostic, but sometimes
> they are modelled after how Linux currently works. What happens when the
> *BSD guys have different ideas how a good binding looks like? How will
> such conflicts be resolved?
That's more a question for Grant. I assume we'll all put on our big-boy
pants and pick the best technical solution based on their merits. :)
thx,
Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree-spec" 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: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Jason Gunthorpe @ 2014-02-18 18:19 UTC (permalink / raw)
To: Grant Likely
Cc: Jason Cooper, Arnd Bergmann, keescook, devicetree, Laura Abbott,
linux-kernel, Rob Herring, Kumar Gala, linux-arm-kernel
In-Reply-To: <20140217155419.682F7C401D4@trevor.secretlab.ca>
On Mon, Feb 17, 2014 at 03:54:19PM +0000, Grant Likely wrote:
> I applied a patch that did exactly that (109b623629), and then reverted
> it (b920ecc82) shortly thereafter because add_device_randomness() is
> a rather slow function and FDTs can get large. I'd like to see someone
> do a reasonable analysis on the cost of using an FDT for randomness
> before I reapply a patch doing something similar. An awful lot of the
> FDT data is not very random, but there are certainly portions of it that
> are appropriate for the random pool.
I read through the original thread from Tim Bird and FWIW I agree with
the assessment that passing the FDT through MD5 first is a good
approach.
Thinking into the future, I'd expect to see similar variable data in
DT on servers as we see in DMI, including:
- Vendor serial number for the HW, manufacturing date, model number,
and HW UUID
- Serial numbers and vendor part numbers for DIMMS
- MAC addresses for all the ethernet
- OEM specific data
At worst a 'choosen/linux,no-dt-random = 1' value in the DT to disable
it would solve the problem for those in embedded that care about
microseconds during booting.
Regards,
Jason
^ permalink raw reply
* Re: [PATCH v2 2/3] usb: chipidea: msm: Add device tree support
From: Sergei Shtylyov @ 2014-02-18 18:31 UTC (permalink / raw)
To: Ivan T. Ivanov
Cc: Peter Chen, Grant Likely, Rob Herring, Greg Kroah-Hartman,
linux-usb, linux-kernel, devicetree, linux-arm-msm
In-Reply-To: <1392743648.17130.17.camel@iivanov-dev>
On 02/18/2014 08:14 PM, Ivan T. Ivanov wrote:
>>> From: "Ivan T. Ivanov" <iivanov@mm-sol.com>
>>> Allows controller to be specified via device tree.
>>> Pass PHY phandle specified in DT to core driver.
>>> Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>
>>> ---
>>> drivers/usb/chipidea/ci_hdrc_msm.c | 23 ++++++++++++++++++++++-
>>> 1 file changed, 22 insertions(+), 1 deletion(-)
>> You also need to describe the binding you're creating in
>> Documentation/devicetree/bindings/usb/<file>.txt.
> Did you check "[PATCH v2 1/3]"?
Did you send it to 'linux-usb'? I just didn't get the patch.
(Typically, the bindings are described in the same patch the DT support is
added to the driver bu YMMV, of course.)
> Regards,
> Ivan
WBR, Sergei
^ permalink raw reply
* Re: [PATCH v3 7/7] devicetree: bindings: Document PM8921/8058 PMICs
From: Stephen Boyd @ 2014-02-18 18:44 UTC (permalink / raw)
To: Lee Jones
Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel,
devicetree
In-Reply-To: <20140213110619.GI32508@lee--X1>
On 02/13/14 03:06, Lee Jones wrote:
>> These match the #defines in that file. I'd like to be explicit
>> about the numbers to prevent people from thinking they have to
>> use #defines and to match what other irq controllers have done
>> (gic, atmel-aic, etc.)
> I believe people _do_ have to use the #defines? Is there a good reason
> for you not wanting to use them?
>
No, there isn't any requirement to use #defines in DT.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: [PATCH v5 1/6] spmi: Linux driver framework for SPMI
From: Josh Cartwright @ 2014-02-18 18:56 UTC (permalink / raw)
To: Felipe Balbi
Cc: Mark Rutland, devicetree, Pawel Moll, Ian Campbell,
Greg Kroah-Hartman, Gilad Avidov, linux-kernel, Kenneth Heitke,
Rob Herring, Michael Bohan, linux-arm-msm, Kumar Gala,
Sagar Dharia, linux-arm-kernel
In-Reply-To: <20140215234748.GA26494@saruman.home>
On Sat, Feb 15, 2014 at 05:47:48PM -0600, Felipe Balbi wrote:
> On Mon, Feb 03, 2014 at 05:05:33PM -0600, Josh Cartwright wrote:
> > +#ifdef CONFIG_PM_RUNTIME
> > +static int spmi_runtime_suspend(struct device *dev)
> > +{
> > + struct spmi_device *sdev = to_spmi_device(dev);
> > + int err;
> > +
> > + err = pm_generic_runtime_suspend(dev);
> > + if (err)
> > + return err;
> > +
> > + return spmi_command_sleep(sdev);
>
> shouldn't this too calls be swapped ? I mean, some pm_runtime
> implementations could be gating clocks at the driver's
> ->runtime_suspend() callback.
Perhaps. I had added the explicit SLEEP/WAKEUP commands to
suspend()/resume(), but now I'm thinking issuing these commands should
not be the responsibility of the core, since the semantics of the
SLEEP/ACTIVE state aren't well defined in general (each
implementation/slave defines what, if anything, these states mean).
Fortunately, there are no users yet, so this is a painless change. :)
Thanks for taking a look.
Josh
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: [PATCH v3 1/3] dma: Support multiple interleaved frames with non-contiguous memory
From: Jassi Brar @ 2014-02-18 19:03 UTC (permalink / raw)
To: Srikanth Thokala
Cc: Williams, Dan J, Koul, Vinod, michal.simek, Grant Likely, robh+dt,
devicetree, Levente Kurusa, Lars-Peter Clausen, lkml, dmaengine,
Andy Shevchenko, linux-arm-kernel@lists.infradead.org
In-Reply-To: <CA+mB=1K43MDZj0Rx3q=ETQMaFsG1j7TXsH6v-7a26JdtqTJkbw@mail.gmail.com>
On 18 February 2014 23:16, Srikanth Thokala <sthokal@xilinx.com> wrote:
> On Tue, Feb 18, 2014 at 10:20 PM, Jassi Brar <jaswinder.singh@linaro.org> wrote:
>> On 18 February 2014 16:58, Srikanth Thokala <sthokal@xilinx.com> wrote:
>>> On Mon, Feb 17, 2014 at 3:27 PM, Jassi Brar <jaswinder.singh@linaro.org> wrote:
>>>> On 15 February 2014 17:30, Srikanth Thokala <sthokal@xilinx.com> wrote:
>>>>> The current implementation of interleaved DMA API support multiple
>>>>> frames only when the memory is contiguous by incrementing src_start/
>>>>> dst_start members of interleaved template.
>>>>>
>>>>> But, when the memory is non-contiguous it will restrict slave device
>>>>> to not submit multiple frames in a batch. This patch handles this
>>>>> issue by allowing the slave device to send array of interleaved dma
>>>>> templates each having a different memory location.
>>>>>
>>>> How fragmented could be memory in your case? Is it inefficient to
>>>> submit separate transfers for each segment/frame?
>>>> It will help if you could give a typical example (chunk size and gap
>>>> in bytes) of what you worry about.
>>>
>>> With scatter-gather engine feature in the hardware, submitting separate
>>> transfers for each frame look inefficient. As an example, our DMA engine
>>> supports up to 16 video frames, with each frame (a typical video frame
>>> size) being contiguous in memory but frames are scattered into different
>>> locations. We could not definitely submit frame by frame as it would be
>>> software overhead (HW interrupting for each frame) resulting in video lags.
>>>
>> IIUIC, it is 30fps and one dma interrupt per frame ... it doesn't seem
>> inefficient at all. Even poor-latency audio would generate a higher
>> interrupt-rate. So the "inefficiency concern" doesn't seem valid to
>> me.
>>
>> Not to mean we shouldn't strive to reduce the interrupt-rate further.
>> Another option is to emulate the ring-buffer scheme of ALSA.... which
>> should be possible since for a session of video playback the frame
>> buffers' locations wouldn't change.
>>
>> Yet another option is to use the full potential of the
>> interleaved-xfer api as such. It seems you confuse a 'video frame'
>> with the interleaved-xfer api's 'frame'. They are different.
>>
>> Assuming your one video frame is F bytes long and Gk is the gap in
>> bytes between end of frame [k] and start of frame [k+1] and Gi != Gj
>> for i!=j
>> In the context of interleaved-xfer api, you have just 1 Frame of 16
>> chunks. Each chunk is Fbytes and the inter-chunk-gap(ICG) is Gk where
>> 0<=k<15
>> So for your use-case .....
>> dma_interleaved_template.numf = 1 /* just 1 frame */
>> dma_interleaved_template.frame_size = 16 /* containing 16 chunks */
>> ...... //other parameters
>>
>> You have 3 options to choose from and all should work just as fine.
>> Otherwise please state your problem in real numbers (video-frames'
>> size, count & gap in bytes).
>
> Initially I interpreted interleaved template the same. But, Lars corrected me
> in the subsequent discussion and let me put it here briefly,
>
> In the interleaved template, each frame represents a line of size denoted by
> chunk.size and the stride by icg. 'numf' represent number of frames i.e.
> number of lines.
>
> In video frame context,
> chunk.size -> hsize
> chunk.icg -> stride
> numf -> vsize
> and frame_size is always 1 as it will have only one chunk in a line.
>
But you said in your last post
"with each frame (a typical video frame size) being contiguous in memory"
... which is not true from what you write above. Anyways, my first 2
suggestions still hold.
> So, the API would not allow to pass multiple frames and we came up with a
> resolution to pass an array of interleaved template structs to handle this.
>
Yeah the API doesn't allow such xfers that don't fall into any
'regular expression' of a transfer and also because no controller
natively supports such xfers -- your controller will break your
request up into 16 transfers and program them individually, right?
BTW if you insist you could still express the 16 video frames as 1
interleaved-xfer frame with frame_size = (vsize + 1) * 16 ;)
Again, I would suggest you implement ring-buffer type scheme. Say
prepare 16 interleaved xfer templates and queue them. Upon each
xfer-done callback (i.e frame rendered), update the data and queue it
back. It might be much simpler for your actual case. At 30fps, 33ms to
queue a dma request should _not_ result in any frame-drop.
-Jassi
^ permalink raw reply
* Re: [PATCH v2 1/3] usb: chipidea: msm: Add device tree binding information
From: Josh Cartwright @ 2014-02-18 19:07 UTC (permalink / raw)
To: Ivan T. Ivanov
Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Rob Landley, Greg Kroah-Hartman, David Brown, devicetree,
linux-doc, linux-kernel, linux-arm-msm
In-Reply-To: <1392744420.17130.24.camel@iivanov-dev>
On Tue, Feb 18, 2014 at 07:27:00PM +0200, Ivan T. Ivanov wrote:
> On Tue, 2014-02-18 at 10:13 -0600, Josh Cartwright wrote:
> > On Tue, Feb 18, 2014 at 03:21:19PM +0200, Ivan T. Ivanov wrote:
> > > .../devicetree/bindings/usb/msm-hsusb.txt | 17 +++++++++++++++++
> >
> > Is this really the appropriate place to document this? It seems like
> > this binding doc should be merged with the i.MX ci13xxx binding in a
> > common ci13xxx doc.
> >
>
> This driver is a "glue" layer driver which control Qualcomm
> specific logic around Chipidea IP core. It is supposed to
> hold "non standard" Chipidea properties, but I suppose that
> ci-hdrc-qcom.txt will be better name and will be similar to
> i.MX chosen name.
>
> What do you think?
Sounds like an improvement to me.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: devicetree repository separation/migration
From: Stephen Warren @ 2014-02-18 19:09 UTC (permalink / raw)
To: Jason Cooper, Sascha Hauer
Cc: Grant Likely, Rob Herring, Ian Campbell, pawel.moll-5wv7dgnIgG8,
mark.rutland-5wv7dgnIgG8, galak-sgV2jX0FEOL9JmXXK+q4OQ,
rob-VoJi6FS/r0vR7s880joybQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
devicetree-spec-u79uwXL29TY76Z2rM5mHXA,
devicetree-compiler-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20140218181854.GB7862-u4khhh1J0LxI1Ri9qeTfzeTW4wlIGRCZ@public.gmane.org>
On 02/18/2014 11:18 AM, Jason Cooper wrote:
> On Tue, Feb 18, 2014 at 04:57:50PM +0100, Sascha Hauer wrote:
>> On Mon, Feb 17, 2014 at 01:05:44PM -0500, Jason Cooper wrote:
> ...
>>> - Is the Linux development workflow ready for devicetree to move out
>>> of the Linux Kernel?
>>
>> I hope so since keeping the devicetrees in sync with the kernel is a
>> pain for all external users.
>
> Well, I haven't heard any screams yet. I suspect people are waiting for
> details on the exact form it would take before complaining...
>
>>> - How do we envision projects will use it? git submodule? reference
>>> a version tag? (this is primarily targeted at bootloaders that need
>>> to compile in a dtb or subset of a dtb into the bootloader)
>>
>> I would prefer to use it as a submodule.
>
> ok. I've often thought that was the right solution for several things
> (dtc.git inside the kernel tree), but no one ever seemed to speak of it
> or bring it up. Kinda like leprosy.
>
> It does add an extra step to build process for new users. Although that
> could be handled in the Makefile.
My limited experience of git submodules implies that comparing them to
Leprosy isn't a bad comparison:-)
If they are separated out, I'd vastly prefer they simply be a standalone
project completed divorced from the kernel. Playing games with git
submodules to try and make it easier seems more likely to actually make
this more complicated.
--
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: devicetree repository separation/migration
From: Jason Cooper @ 2014-02-18 19:22 UTC (permalink / raw)
To: Stephen Warren
Cc: Sascha Hauer, Grant Likely, Rob Herring, Ian Campbell,
pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
devicetree-spec-u79uwXL29TY76Z2rM5mHXA,
devicetree-compiler-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <5303AFDC.9010908-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
On Tue, Feb 18, 2014 at 12:09:16PM -0700, Stephen Warren wrote:
> On 02/18/2014 11:18 AM, Jason Cooper wrote:
> > On Tue, Feb 18, 2014 at 04:57:50PM +0100, Sascha Hauer wrote:
> >> On Mon, Feb 17, 2014 at 01:05:44PM -0500, Jason Cooper wrote:
> > ...
> >>> - Is the Linux development workflow ready for devicetree to move out
> >>> of the Linux Kernel?
> >>
> >> I hope so since keeping the devicetrees in sync with the kernel is a
> >> pain for all external users.
> >
> > Well, I haven't heard any screams yet. I suspect people are waiting for
> > details on the exact form it would take before complaining...
> >
> >>> - How do we envision projects will use it? git submodule? reference
> >>> a version tag? (this is primarily targeted at bootloaders that need
> >>> to compile in a dtb or subset of a dtb into the bootloader)
> >>
> >> I would prefer to use it as a submodule.
> >
> > ok. I've often thought that was the right solution for several things
> > (dtc.git inside the kernel tree), but no one ever seemed to speak of it
> > or bring it up. Kinda like leprosy.
> >
> > It does add an extra step to build process for new users. Although that
> > could be handled in the Makefile.
>
> My limited experience of git submodules implies that comparing them to
> Leprosy isn't a bad comparison:-)
>
> If they are separated out, I'd vastly prefer they simply be a standalone
> project completed divorced from the kernel.
Yes, I probably wasn't clear. The devicetree repo _would_ be it's own
repo divorced from all other projects, including the kernel.
How projects wish to integrate the tree in order to produce the dtbs is
the question at hand. The outcome of the discussion may have an effect
on how we structure the tree. eg Makefile's and such.
> Playing games with git submodules to try and make it easier seems more
> likely to actually make this more complicated.
I've played around with them a bit, and I think they are most similar to
round-abouts. It looks like chaos. But as long as people follow a few
simple rules, it works out fine.
>From the devicetree pov, though, it would just be maintaining the
makefile(s) to be amenable to that scenario.
thx,
Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree-spec" 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: devicetree repository separation/migration
From: Olof Johansson @ 2014-02-18 19:47 UTC (permalink / raw)
To: Jason Cooper
Cc: Sascha Hauer, Grant Likely, Rob Herring, Ian Campbell, Pawel Moll,
Mark Rutland, Kumar Gala, Rob Landley,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-spec-u79uwXL29TY76Z2rM5mHXA,
devicetree-compiler-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20140218181854.GB7862-u4khhh1J0LxI1Ri9qeTfzeTW4wlIGRCZ@public.gmane.org>
On Tue, Feb 18, 2014 at 10:18 AM, Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org> wrote:
> On Tue, Feb 18, 2014 at 04:57:50PM +0100, Sascha Hauer wrote:
>> On Mon, Feb 17, 2014 at 01:05:44PM -0500, Jason Cooper wrote:
> ...
>> > - Is the Linux development workflow ready for devicetree to move out
>> > of the Linux Kernel?
>>
>> I hope so since keeping the devicetrees in sync with the kernel is a
>> pain for all external users.
>
> Well, I haven't heard any screams yet. I suspect people are waiting for
> details on the exact form it would take before complaining...
I'M SCREAMING NOW. :-)
Honestly though, I think we need to do this carefully. Even though we
don't like it, there are still lots of bindings in flux and
cross-dependencies between two independent repos will be a major pain.
I think we have two options:
1. Bring out everything in the current kernel repo to a separate one,
but do it my mirroring over. Changes go into the kernel repo first and
then comes over to this one, but other projects can mirror the
standalone repo without downloading a whole kernel tree.
2. Remove the kernel contents and move it over to the new repo. This
should be done independently for each platform, and the maintainers
get to decide if, when and how they do it. Some platforms are ready
for it (some have been for a long time), others are not. And it's up
to the maintainer, since they are the ones we will yell at when they
make our life miserable by adding cross-dependencies with an external
repo. Breakage due to the move is something we should have to put up
with, etc.
>> I'll likely need some barebox specific additions to the devicetrees.
>> Right now our idea is to leave the provided devicetrees untouched and
>> instead of compiling the board dts files directly we create
>> <boardname>-barebox.dts files which include the original board files.
>> That would allow us to provide additional information to barebox
>> without having to carry patches for the devicetrees.
>
> So the resulting <boardname>-barebox.dtb is compiled into the barebox
> binary? Is the dtb passed to the kernel independently upgradeable?
>
> Why not post binding/dts patches for 'barebox,...' attributes that you
> need?
+1. These should ideally be posted and reviewed too -- maybe they make
sense to share between barebox and other firmware stacks, for example.
>
>> > Other thoughts I may have missed?
>>
>> It will be interesting to see which rules should apply for merging new
>> bindings. I know that devicetrees should be OS agnostic, but sometimes
>> they are modelled after how Linux currently works. What happens when the
>> *BSD guys have different ideas how a good binding looks like? How will
>> such conflicts be resolved?
>
> That's more a question for Grant. I assume we'll all put on our big-boy
> pants and pick the best technical solution based on their merits. :)
A good binding focuses on describing hardware, so as long as we keep
our focus on that instead of how a specific implementation of a driver
will use it, I think we can avoid at least some of the potential
conflicts.
-Olof
--
To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" 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] dt: platform driver: Fill the resources before probe and defer if needed
From: Greg KH @ 2014-02-18 20:22 UTC (permalink / raw)
To: Jean-Jacques Hiblot
Cc: grant.likely, robh+dt, linux-kernel, devicetree, gregory.clement,
linux-arm-kernel
In-Reply-To: <1392285429-9325-1-git-send-email-jjhiblot@traphandler.com>
On Thu, Feb 13, 2014 at 10:57:09AM +0100, Jean-Jacques Hiblot wrote:
> The goal of this patch is to allow drivers to be probed even if at the time of
> the DT parsing some of their ressources are not available yet.
>
> In the current situation, the resource of a platform device are filled from the
> DT at the time the device is created (of_device_alloc()). The drawbackof this
> is that a device sitting close to the top of the DT (ahb for example) but
> depending on ressources that are initialized later (IRQ domain dynamically
> created for example) will fail to probe because the ressources don't exist
> at this time.
>
> This patch fills the resource structure only before the device is probed and
> will defer the probe if the resource are not available yet.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/base/platform.c | 6 ++++
> drivers/of/platform.c | 71 +++++++++++++++++++++++++++++----------------
> include/linux/of_platform.h | 10 +++++++
> 3 files changed, 62 insertions(+), 25 deletions(-)
I need some others to ack this before I can take it...
^ permalink raw reply
* Re: [PATCH v4 0/2] Introduce AEMIF driver for Davinci/Keystone archs
From: Greg KH @ 2014-02-18 20:27 UTC (permalink / raw)
To: Santosh Shilimkar
Cc: Ivan Khoronzhuk, rob-VoJi6FS/r0vR7s880joybQ,
linux-lFZ/pmaqli7XmaaqVzeoHQ,
galak-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, pawel.moll-5wv7dgnIgG8,
mark.rutland-5wv7dgnIgG8, rob.herring-bsGFqQB8/DxBDgjK7y7TUQ,
swarren-3lzwWm7+Weoh9ZMKESR00Q,
ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
grygorii.strashko-l0cyMroinI0, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
nsekhar-l0cyMroinI0
In-Reply-To: <53037113.3090105-l0cyMroinI0@public.gmane.org>
On Tue, Feb 18, 2014 at 09:41:23AM -0500, Santosh Shilimkar wrote:
> Greg,
>
> On Wednesday 05 February 2014 02:46 PM, Ivan Khoronzhuk wrote:
> > These patches introduce Async External Memory Interface (EMIF16/AEMIF)
> > controller driver for Davinci/Keystone archs.
> >
> > For more informations see documentation:
> > Davinci DM646x - http://www.ti.com/lit/ug/sprueq7c/sprueq7c.pdf
> > OMAP-L138 - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf
> > Kestone - http://www.ti.com/lit/ug/sprugz3a/sprugz3a.pdf
> >
> Can you please have a look at the series ? It has been on the list for
> sometime and all the outstanding comments are addressed so far. If
> you are ok with it, I would like to get these queued up for 3.15
> via your tree.
Why my tree? Am I the drivers/memory/ maintainer?
/me digs in git...
Ah, it looks like I might be...
Ok, let me go review this.
greg k-h
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2] of_mdio: fix phy interrupt passing
From: Sergei Shtylyov @ 2014-02-18 20:29 UTC (permalink / raw)
To: Ben Dooks, grant.likely
Cc: linux-kernel, devicetree, linux-kernel, netdev, linux-sh
In-Reply-To: <1392725818-558-1-git-send-email-ben.dooks@codethink.co.uk>
Hello.
On 02/18/2014 03:16 PM, Ben Dooks wrote:
> The of_mdiobus_register_phy() is not setting phy->irq thus causing
> some drivers to incorrectly assume that the PHY does not have an
> IRQ associated with it. Not only do some drivers report no IRQ
> they do not install an interrupt handler for the PHY.
> Simplify the code setting irq and set the phy->irq at the same
> time so that we cover the following issues, which should cover
> all the cases the code will find:
> - Set phy->irq if node has irq property and mdio->irq is NULL
> - Set phy->irq if node has no irq and mdio->irq is not NULL
> - Leave phy->irq as PHY_POLL default if none of the above
> This fixes the issue:
> net eth0: attached PHY 1 (IRQ -1) to driver Micrel KSZ8041RNLI
> to the correct:
> net eth0: attached PHY 1 (IRQ 416) to driver Micrel KSZ8041RNLI
> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
[...]
> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
> index 875b7b6..46d95fc 100644
> --- a/drivers/of/of_mdio.c
> +++ b/drivers/of/of_mdio.c
[...]
> @@ -54,12 +54,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
> if (!phy || IS_ERR(phy))
> return 1;
>
> - if (mdio->irq) {
> - prev_irq = mdio->irq[addr];
> - mdio->irq[addr] =
> - irq_of_parse_and_map(child, 0);
> - if (!mdio->irq[addr])
> - mdio->irq[addr] = prev_irq;
> + rc = irq_of_parse_and_map(child, 0);
> + if (rc > 0) {
> + phy->irq = rc;
> + if (mdio->irq)
> + mdio->irq[addr] = rc;
> + } else {
> + if (mdio->irq)
> + phy->irq = mdio->irq[addr];
I have now looked thru the of_mdio.c code and the code it calls.
This case seems to be cared about by phy_device_create() called earlier
via get_phy_device() call just above this hunk; in any case the value will be
PHY_POLL. I don't think this branch is needed at all.
WBR, Sergei
^ permalink raw reply
* Re: [PATCH v4 1/2] memory: ti-aemif: introduce AEMIF driver
From: Greg KH @ 2014-02-18 20:30 UTC (permalink / raw)
To: Ivan Khoronzhuk
Cc: santosh.shilimkar, rob, linux, galak, devicetree, pawel.moll,
mark.rutland, rob.herring, swarren, ijc+devicetree, linux-kernel,
linux-arm-kernel, linux-mtd, grygorii.strashko, dwmw2, nsekhar,
[initial author] Murali Karicheri
In-Reply-To: <1391629574-18955-2-git-send-email-ivan.khoronzhuk@ti.com>
On Wed, Feb 05, 2014 at 09:46:13PM +0200, Ivan Khoronzhuk wrote:
> Add new AEMIF driver for EMIF16 Texas Instruments controller.
> The EMIF16 module is intended to provide a glue-less interface to
> a variety of asynchronous memory devices like ASRA M, NOR and NAND
> memory. A total of 256M bytes of any of these memories can be
> accessed at any given time via 4 chip selects with 64M byte access
> per chip select.
>
> Synchronous memories such as DDR1 SD RAM, SDR SDRAM and Mobile SDR
> are not supported.
>
> This controller is used on SoCs like Davinci, Keysone2
>
> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com
> Signed-off-by: [initial author] Murali Karicheri <m-karicheri2@ti.com>
What's this [] stuff?
If Murali wrote this, that name needs to be in a "From:" line in the
patch to properly attribute it, and drop the [] here.
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
> ---
> drivers/memory/Kconfig | 11 ++
> drivers/memory/Makefile | 1 +
> drivers/memory/ti-aemif.c | 429 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 441 insertions(+)
> create mode 100644 drivers/memory/ti-aemif.c
>
> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> index 29a11db..7bc3982 100644
> --- a/drivers/memory/Kconfig
> +++ b/drivers/memory/Kconfig
> @@ -7,6 +7,17 @@ menuconfig MEMORY
>
> if MEMORY
>
> +config TI_AEMIF
> + tristate "Texas Instruments AEMIF driver"
> + depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
> + help
> + This driver is for the AEMIF module available in Texas Instruments
> + SoCs. AEMIF stands for Asynchronous External Memory Interface and
> + is intended to provide a glue-less interface to a variety of
> + asynchronuous memory devices like ASRAM, NOR and NAND memory. A total
> + of 256M bytes of any of these memories can be accessed at a given
> + time via four chip selects with 64M byte access per chip select.
> +
> config TI_EMIF
> tristate "Texas Instruments EMIF driver"
> depends on ARCH_OMAP2PLUS
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index 969d923..d4e150c 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -5,6 +5,7 @@
> ifeq ($(CONFIG_DDR),y)
> obj-$(CONFIG_OF) += of_memory.o
> endif
> +obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
> obj-$(CONFIG_TI_EMIF) += emif.o
> obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
> obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
> diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
> new file mode 100644
> index 0000000..8d15d87
> --- /dev/null
> +++ b/drivers/memory/ti-aemif.c
> @@ -0,0 +1,429 @@
> +/*
> + * TI AEMIF driver
> + *
> + * Copyright (C) 2010 - 2013 Texas Instruments Incorporated. http://www.ti.com/
> + *
> + * Authors:
> + * Murali Karicheri <m-karicheri2@ti.com>
> + * Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
> + *
> + * 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/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +
> +#define TA_SHIFT 2
> +#define RHOLD_SHIFT 4
> +#define RSTROBE_SHIFT 7
> +#define RSETUP_SHIFT 13
> +#define WHOLD_SHIFT 17
> +#define WSTROBE_SHIFT 20
> +#define WSETUP_SHIFT 26
> +#define EW_SHIFT 30
> +#define SS_SHIFT 31
> +
> +#define TA(x) ((x) << TA_SHIFT)
> +#define RHOLD(x) ((x) << RHOLD_SHIFT)
> +#define RSTROBE(x) ((x) << RSTROBE_SHIFT)
> +#define RSETUP(x) ((x) << RSETUP_SHIFT)
> +#define WHOLD(x) ((x) << WHOLD_SHIFT)
> +#define WSTROBE(x) ((x) << WSTROBE_SHIFT)
> +#define WSETUP(x) ((x) << WSETUP_SHIFT)
> +#define EW(x) ((x) << EW_SHIFT)
> +#define SS(x) ((x) << SS_SHIFT)
> +
> +#define ASIZE_MAX 0x1
> +#define TA_MAX 0x3
> +#define RHOLD_MAX 0x7
> +#define RSTROBE_MAX 0x3f
> +#define RSETUP_MAX 0xf
> +#define WHOLD_MAX 0x7
> +#define WSTROBE_MAX 0x3f
> +#define WSETUP_MAX 0xf
> +#define EW_MAX 0x1
> +#define SS_MAX 0x1
> +#define NUM_CS 4
> +
> +#define TA_VAL(x) (((x) & TA(TA_MAX)) >> TA_SHIFT)
> +#define RHOLD_VAL(x) (((x) & RHOLD(RHOLD_MAX)) >> RHOLD_SHIFT)
> +#define RSTROBE_VAL(x) (((x) & RSTROBE(RSTROBE_MAX)) >> RSTROBE_SHIFT)
> +#define RSETUP_VAL(x) (((x) & RSETUP(RSETUP_MAX)) >> RSETUP_SHIFT)
> +#define WHOLD_VAL(x) (((x) & WHOLD(WHOLD_MAX)) >> WHOLD_SHIFT)
> +#define WSTROBE_VAL(x) (((x) & WSTROBE(WSTROBE_MAX)) >> WSTROBE_SHIFT)
> +#define WSETUP_VAL(x) (((x) & WSETUP(WSETUP_MAX)) >> WSETUP_SHIFT)
> +#define EW_VAL(x) (((x) & EW(EW_MAX)) >> EW_SHIFT)
> +#define SS_VAL(x) (((x) & SS(SS_MAX)) >> SS_SHIFT)
> +
> +#define NRCSR_OFFSET 0x00
> +#define AWCCR_OFFSET 0x04
> +#define A1CR_OFFSET 0x10
> +
> +#define ACR_ASIZE_MASK 0x3
> +#define ACR_EW_MASK BIT(30)
> +#define ACR_SS_MASK BIT(31)
> +#define ASIZE_16BIT 1
> +
> +#define CONFIG_MASK (TA(TA_MAX) | \
> + RHOLD(RHOLD_MAX) | \
> + RSTROBE(RSTROBE_MAX) | \
> + RSETUP(RSETUP_MAX) | \
> + WHOLD(WHOLD_MAX) | \
> + WSTROBE(WSTROBE_MAX) | \
> + WSETUP(WSETUP_MAX) | \
> + EW(EW_MAX) | SS(SS_MAX) | \
> + ASIZE_MAX)
> +
> +#define DRV_NAME "ti-aemif"
What's wrong with KBUILD_MODNAME?
> +static int aemif_probe(struct platform_device *pdev)
> +{
> + int ret = -ENODEV, i;
Extra spaces?
Split this into two lines?
> + struct resource *res;
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct device_node *child_np;
> + struct aemif_device *aemif;
> +
> + if (np == NULL)
> + return 0;
> +
> + aemif = devm_kzalloc(dev, sizeof(*aemif), GFP_KERNEL);
> + if (!aemif) {
> + dev_err(dev, "cannot allocate memory for aemif\n");
Not needed, you'll get a message from kzalloc about this.
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(pdev, aemif);
> +
> + aemif->clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(aemif->clk)) {
> + dev_err(dev, "cannot get clock 'aemif'\n");
> + return PTR_ERR(aemif->clk);
No freeing memory?
> + }
> +
> + clk_prepare_enable(aemif->clk);
> + aemif->clk_rate = clk_get_rate(aemif->clk) / MSEC_PER_SEC;
> +
> + if (of_device_is_compatible(np, "ti,da850-aemif"))
> + aemif->cs_offset = 2;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + aemif->base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(aemif->base)) {
> + ret = PTR_ERR(aemif->base);
> + goto error;
> + }
> +
> + /*
> + * For every controller device node, there is a cs device node that
> + * describe the bus configuration parameters. This functions iterate
> + * over these nodes and update the cs data array.
> + */
> + for_each_available_child_of_node(np, child_np) {
> + ret = of_aemif_parse_abus_config(pdev, child_np);
> + if (ret < 0)
> + goto error;
> + }
> +
> + for (i = 0; i < aemif->num_cs; i++) {
> + ret = aemif_config_abus(pdev, i);
> + if (ret < 0) {
> + dev_err(dev, "Error configuring chip select %d\n",
> + aemif->cs_data[i].cs);
> + goto error;
> + }
> + }
> +
> + /*
> + * Create a child devices explicitly from here to
> + * guarantee that the child will be probed after the AEMIF timing
> + * parameters are set.
> + */
> + for_each_available_child_of_node(np, child_np) {
> + ret = of_platform_populate(child_np, NULL, NULL, dev);
> + if (ret < 0)
> + goto error;
> + }
> +
> + return 0;
> +error:
> + clk_disable_unprepare(aemif->clk);
> + return ret;
No freeing memory?
> +}
> +
> +static int aemif_remove(struct platform_device *pdev)
> +{
> + struct aemif_device *aemif = platform_get_drvdata(pdev);
> + clk_disable_unprepare(aemif->clk);
Extra line needed.
> + return 0;
> +}
thanks,
greg k-h
^ permalink raw reply
* [RFC PATCH 0/6] PM: introduce voltage domain abstraction
From: Nishanth Menon @ 2014-02-18 20:32 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, MyungJoo Ham, Mark Brown,
Mike Turquette
Cc: devicetree, linux-doc, linux-kernel, cpufreq, linux-pm,
linux-arm-kernel, linux-omap, Nishanth Menon
Hi,
On many SoCs such as OMAP, hardware blocks are isolated into voltage
domains allowing for individual tweaks for optimal power-performance
tradeoffs. Frameworks such as cpufreq, devfreq provide a top level
control of these hardware blocks. Most SoCs have different knobs to
fine tune the voltages. They may supply multiple supplies to various
voltage planes on the same voltage domains.
Regulator framework provides us a with an appropriate representation
of consumer model, however, we lack the abstraction necessary to
isolate the necessary sequencing for a specific voltage domain.
There has been few attempts previously taken such as [3] [4],
this series is a further development of of Mike's series[1] where
cpufreq-cpu0 driver was first targetted with clk notifiers. While I do
understand the concerns Mike has in [2], this could be a base on which
further work may be done.
In a nutshell, this (for cpufreq-cpu0 as an example):
maintains the legacy definitions used by cpufreq/devfreq such as:
&cpu0 {
cpu0-supply = <®ulator_x>;
};
on other SoCs where this might turn out to be a more detailed
implementation,
&cpu0 {
cpu0-voltdm = <&voltdm_x>;
};
To enure this is split off from clk framework, I chose
drivers/power/voltdm as the location for the new files, I'd love to
hear opinions and suggestions on the approach.
The series is based on 3.14-rc3 and is available here:
https://github.com/nmenon/linux-2.6-playground/commits/push/voltdm-notifier-rfc
A testing branch for Beagle-XM (OMAP3630 as testbed):
https://github.com/nmenon/linux-2.6-playground/commits/testing/beagle-xm-voltdm-notifier-rfc
Log: http://slexy.org/view/s20TgkN7kf
NOTE: TI platforms potentially need further development, however, this
forms the basis of the development.
Mike Turquette (2):
PM / Voltagedomain: Add generic clk notifier handler for regulator
based dynamic voltage scaling
cpufreq: cpufreq-cpu0: use clk rate-change notifiers
Nishanth Menon (4):
PM / Voltagedomain: introduce voltage domain driver support
devicetree: bindings: add documentation for voltagedomain
PM / Voltagedomain: introduce basic voltage domain support for OMAP
devicetree: bindings: voltagedomain: add bindings for OMAP compatible
SoCs
.../bindings/power/voltdm/voltage_domain.txt | 65 +++
.../bindings/power/voltdm/voltdm_omap.txt | 24 +
drivers/cpufreq/Kconfig | 1 +
drivers/cpufreq/cpufreq-cpu0.c | 140 ++----
drivers/power/Kconfig | 1 +
drivers/power/Makefile | 1 +
drivers/power/voltdm/Kconfig | 19 +
drivers/power/voltdm/Makefile | 6 +
drivers/power/voltdm/core.c | 508 ++++++++++++++++++++
drivers/power/voltdm/voltage_domain_private.h | 86 ++++
drivers/power/voltdm/voltdm_omap.c | 287 +++++++++++
include/linux/pm_voltage_domain.h | 47 ++
12 files changed, 1086 insertions(+), 99 deletions(-)
create mode 100644 Documentation/devicetree/bindings/power/voltdm/voltage_domain.txt
create mode 100644 Documentation/devicetree/bindings/power/voltdm/voltdm_omap.txt
create mode 100644 drivers/power/voltdm/Kconfig
create mode 100644 drivers/power/voltdm/Makefile
create mode 100644 drivers/power/voltdm/core.c
create mode 100644 drivers/power/voltdm/voltage_domain_private.h
create mode 100644 drivers/power/voltdm/voltdm_omap.c
create mode 100644 include/linux/pm_voltage_domain.h
[1] https://lkml.org/lkml/2013/7/7/110 (original RFC)
[2] http://marc.info/?l=linux-arm-kernel&m=137947787621572&w=2 (runtime pm should enable regulator)
[3] http://marc.info/?t=136603111700006&r=1&w=2
[4] http://git.omapzoom.org/?p=kernel/omap.git;a=blob;f=arch/arm/mach-omap2/dvfs.c;hb=p-linux-omap-3.4
--
1.7.9.5
^ permalink raw reply
* [RFC PATCH 1/6] PM / Voltagedomain: Add generic clk notifier handler for regulator based dynamic voltage scaling
From: Nishanth Menon @ 2014-02-18 20:32 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, MyungJoo Ham, Mark Brown,
Mike Turquette
Cc: devicetree, linux-doc, linux-kernel, cpufreq, linux-pm,
linux-arm-kernel, linux-omap, Nishanth Menon
In-Reply-To: <1392755543-28335-1-git-send-email-nm@ti.com>
From: Mike Turquette <mturquette@linaro.org>
This patch provides helper functions for drivers that wish to scale
voltage through the clock rate-change notifiers. The approach taken
is that the user-driver(cpufreq/devfreq) do not care about the
details of the OPP table, nor does it care about handling the voltage
regulator directly.
By using the clk notifier flags, we are able to sequence the operations
in the right order. The current logic is heavily influenced by
implementation done in cpufreq-cpu0.
[nm@ti.com: Fixes in logic, and broken out from clk to allow building
a generic voltagedomain solution independent of cpufreq]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
---
drivers/power/Kconfig | 1 +
drivers/power/Makefile | 1 +
drivers/power/voltdm/Kconfig | 7 ++
drivers/power/voltdm/Makefile | 2 +
drivers/power/voltdm/core.c | 195 +++++++++++++++++++++++++++++++++++++
include/linux/pm_voltage_domain.h | 47 +++++++++
6 files changed, 253 insertions(+)
create mode 100644 drivers/power/voltdm/Kconfig
create mode 100644 drivers/power/voltdm/Makefile
create mode 100644 drivers/power/voltdm/core.c
create mode 100644 include/linux/pm_voltage_domain.h
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index ba69751..5c4fe16 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -394,3 +394,4 @@ source "drivers/power/reset/Kconfig"
endif # POWER_SUPPLY
source "drivers/power/avs/Kconfig"
+source "drivers/power/voltdm/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ee54a3e..3d47072 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
obj-$(CONFIG_POWER_RESET) += reset/
+obj-$(CONFIG_VOLTAGE_DOMAIN) += voltdm/
diff --git a/drivers/power/voltdm/Kconfig b/drivers/power/voltdm/Kconfig
new file mode 100644
index 0000000..c5353bd
--- /dev/null
+++ b/drivers/power/voltdm/Kconfig
@@ -0,0 +1,7 @@
+config VOLTAGE_DOMAIN
+ bool
+ depends on COMMON_CLK && OF && PM_OPP
+ default y if COMMON_CLK
+ ---help---
+ Core voltage domain framework using common clock framework's
+ notifier mechanism.
diff --git a/drivers/power/voltdm/Makefile b/drivers/power/voltdm/Makefile
new file mode 100644
index 0000000..3fa4408
--- /dev/null
+++ b/drivers/power/voltdm/Makefile
@@ -0,0 +1,2 @@
+# Generic voltage domain
+obj-$(CONFIG_VOLTAGE_DOMAIN) += core.o
diff --git a/drivers/power/voltdm/core.c b/drivers/power/voltdm/core.c
new file mode 100644
index 0000000..d0ed27e
--- /dev/null
+++ b/drivers/power/voltdm/core.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2013 Linaro Ltd <mturquette@linaro.org>
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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.
+ *
+ * Helper functions for registering clock rate-change notifier handlers
+ * that scale voltage when a clock changes its output frequency.
+ */
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/pm_opp.h>
+#include <linux/pm_voltage_domain.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+/**
+ * struct volt_scale_data - Internal structure to maintain notifier information
+ * @dev: device on behalf of which we register the notifier
+ * @clk: clk on which we registered the notifier
+ * @reg: regulator if any which is used for scaling voltage
+ * @tol: voltage tolerance in %
+ * @nb: notifier block pointer
+ */
+struct volt_scale_data {
+ struct device *dev;
+ struct clk *clk;
+ struct regulator *reg;
+ int tol;
+ struct notifier_block nb;
+};
+
+#define to_volt_scale_data(_nb) container_of(_nb, \
+ struct volt_scale_data, nb)
+
+static int clk_volt_notifier_handler(struct notifier_block *nb,
+ unsigned long flags, void *data)
+{
+ struct clk_notifier_data *cnd = data;
+ struct volt_scale_data *vsd = to_volt_scale_data(nb);
+ int ret, volt, tol;
+ struct dev_pm_opp *opp;
+ unsigned long old_rate = cnd->old_rate;
+ unsigned long new_rate = cnd->new_rate;
+
+ if ((new_rate < old_rate && flags == PRE_RATE_CHANGE) ||
+ (new_rate > old_rate && flags == POST_RATE_CHANGE))
+ return NOTIFY_OK;
+
+ rcu_read_lock();
+ if (flags != ABORT_RATE_CHANGE)
+ opp = dev_pm_opp_find_freq_ceil(vsd->dev, &new_rate);
+ else
+ opp = dev_pm_opp_find_freq_ceil(vsd->dev, &old_rate);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ dev_err(vsd->dev, "%s: Failed to find OPP for %lu\n",
+ __func__, new_rate);
+ return notifier_from_errno(PTR_ERR(opp));
+ }
+
+ volt = dev_pm_opp_get_voltage(opp);
+ rcu_read_unlock();
+
+ tol = volt * vsd->tol / 100;
+
+ dev_dbg(vsd->dev, "%s: %lu -> %lu, V=%d, tol=%d, clk_flag=%lu\n",
+ __func__, old_rate, new_rate, volt, tol, flags);
+
+ ret = regulator_set_voltage_tol(vsd->reg, volt, tol);
+ if (ret) {
+ dev_err(vsd->dev,
+ "%s: Failed to scale voltage(%u): %d\n", __func__,
+ volt, ret);
+ return notifier_from_errno(ret);
+ }
+
+ return NOTIFY_OK;
+}
+
+/**
+ * of_pm_voltdm_notifier_register() - register voltage domain notifier
+ * @dev: device for which to register notifier for
+ * @np: node pointer of the device for which we register
+ * @clk: clk pointer around which the notifier is expected to trigger
+ * @supply: default regulator supply name(regulator id string)
+ * @voltage_latency: returns the latency for the voltage domain
+ *
+ * Return: notifier block which is registered with the common clock framework's
+ * notifier for the clk node requested.
+ */
+struct notifier_block *of_pm_voltdm_notifier_register(struct device *dev,
+ struct device_node *np,
+ struct clk *clk,
+ const char *supply,
+ int *voltage_latency)
+{
+ struct volt_scale_data *vsd;
+ struct dev_pm_opp *opp;
+ unsigned long min, max, freq;
+ int ret;
+
+ vsd = kzalloc(sizeof(*vsd), GFP_KERNEL);
+ if (!vsd)
+ return ERR_PTR(-ENOMEM);
+
+ vsd->dev = dev;
+ vsd->clk = clk;
+ vsd->nb.notifier_call = clk_volt_notifier_handler;
+ vsd->reg = regulator_get_optional(dev, supply);
+ ret = 0;
+ if (IS_ERR(vsd->reg))
+ ret = PTR_ERR(vsd->reg);
+ /* regulator is not mandatory */
+ if (ret != -EPROBE_DEFER) {
+ dev_warn(dev, "%s: Failed to get %s regulator:%d\n",
+ __func__, supply, ret);
+ ret = 0;
+ goto err_free_vsd;
+ }
+ /* For devices that are not ready.... */
+ if (ret)
+ goto err_free_vsd;
+
+ rcu_read_lock();
+ freq = 0;
+ opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+ if (IS_ERR(opp))
+ goto err_bad_opp;
+ min = dev_pm_opp_get_voltage(opp);
+
+ freq = ULONG_MAX;
+ opp = dev_pm_opp_find_freq_floor(dev, &freq);
+ if (IS_ERR(opp))
+ goto err_bad_opp;
+ max = dev_pm_opp_get_voltage(opp);
+ rcu_read_unlock();
+
+ *voltage_latency = regulator_set_voltage_time(vsd->reg, min, max);
+ if (*voltage_latency < 0) {
+ dev_warn(dev,
+ "%s: Fail calculating voltage latency[%ld<->%ld]:%d\n",
+ __func__, min, max, *voltage_latency);
+ }
+
+ of_property_read_u32(np, "voltage-tolerance", &vsd->tol);
+
+ ret = clk_notifier_register(clk, &vsd->nb);
+
+ if (ret) {
+ dev_err(dev, "%s: Failed to Register Notifier, %d\n", __func__,
+ ret);
+ goto err_free_reg;
+ }
+
+ return &vsd->nb;
+
+err_bad_opp:
+ rcu_read_unlock();
+ ret = PTR_ERR(opp);
+ dev_err(dev, "%s: failed to get OPP, %d\n", __func__, ret);
+
+err_free_reg:
+ regulator_put(vsd->reg);
+
+err_free_vsd:
+ kfree(vsd);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(of_pm_voltdm_notifier_register);
+
+/**
+ * of_pm_voltdm_notifier_unregister() - unregister notifier for volt domain
+ * @nb: notifier block returned by of_pm_voltdm_notifier_register
+ */
+void of_pm_voltdm_notifier_unregister(struct notifier_block *nb)
+{
+ struct volt_scale_data *vsd;
+ struct clk *clk;
+
+ /* if caller send us back error value */
+ if (IS_ERR(nb))
+ return;
+
+ vsd = to_volt_scale_data(nb);
+ clk = vsd->clk;
+ clk_notifier_unregister(clk, nb);
+ if (!IS_ERR(vsd->reg))
+ regulator_put(vsd->reg);
+
+ kfree(vsd);
+}
+EXPORT_SYMBOL_GPL(of_pm_voltdm_notifier_unregister);
diff --git a/include/linux/pm_voltage_domain.h b/include/linux/pm_voltage_domain.h
new file mode 100644
index 0000000..1ee7343
--- /dev/null
+++ b/include/linux/pm_voltage_domain.h
@@ -0,0 +1,47 @@
+/*
+ * Voltage Domain header for users of voltage domain interface
+ *
+ * Copyright (C) 2013 Linaro Ltd <mturquette@linaro.org>
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PM_VOLTAGE_DOMAIN__
+#define __PM_VOLTAGE_DOMAIN__
+
+#include <linux/clk.h>
+
+#if defined(CONFIG_VOLTAGE_DOMAIN)
+struct notifier_block *of_pm_voltdm_notifier_register(struct device *dev,
+ struct device_node *np,
+ struct clk *clk,
+ const char *supply,
+ int *voltage_latency);
+void of_pm_voltdm_notifier_unregister(struct notifier_block *nb);
+
+#else
+static inline struct notifier_block *of_pm_voltdm_notifier_register(
+ struct device *dev,
+ struct device_node *np,
+ struct clk *clk,
+ const char *supply,
+ int *voltage_latency);
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline void of_pm_voltdm_notifier_unregister(struct notifier_block *nb)
+{
+}
+
+#endif /* VOLTAGE_DOMAIN */
+
+#endif /* __PM_VOLTAGE_DOMAIN__ */
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 2/6] cpufreq: cpufreq-cpu0: use clk rate-change notifiers
From: Nishanth Menon @ 2014-02-18 20:32 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, MyungJoo Ham, Mark Brown,
Mike Turquette
Cc: devicetree, linux-doc, linux-kernel, cpufreq, linux-pm,
linux-arm-kernel, linux-omap, Nishanth Menon
In-Reply-To: <1392755543-28335-1-git-send-email-nm@ti.com>
From: Mike Turquette <mturquette@linaro.org>
Removes directly handling of OPP tables and voltage regulators by
calling of_clk_cpufreq_notifier_handler, introduced by commit "clk:
cpufreq helper for voltage scaling".
In the future this can help consolidate code found across similar
CPUfreq drivers.
[nm@ti.com: updates to keep the OPP logic still in cpufreq-cpu0 -
optimization to generalize that for cpufreq is to be done in a later
series]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
---
drivers/cpufreq/Kconfig | 1 +
drivers/cpufreq/cpufreq-cpu0.c | 140 ++++++++++++----------------------------
2 files changed, 42 insertions(+), 99 deletions(-)
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 4b029c0..70b07ab 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -187,6 +187,7 @@ config GENERIC_CPUFREQ_CPU0
tristate "Generic CPU0 cpufreq driver"
depends on HAVE_CLK && REGULATOR && OF && THERMAL && CPU_THERMAL
select PM_OPP
+ select VOLTAGE_DOMAIN
help
This adds a generic cpufreq driver for CPU0 frequency management.
It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 0c12ffc..32719d3 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -21,23 +21,20 @@
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
+#include <linux/pm_voltage_domain.h>
#include <linux/slab.h>
#include <linux/thermal.h>
static unsigned int transition_latency;
-static unsigned int voltage_tolerance; /* in percentage */
static struct device *cpu_dev;
static struct clk *cpu_clk;
-static struct regulator *cpu_reg;
static struct cpufreq_frequency_table *freq_table;
static struct thermal_cooling_device *cdev;
+static struct notifier_block *clk_nb;
static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
{
- struct dev_pm_opp *opp;
- unsigned long volt = 0, volt_old = 0, tol = 0;
unsigned int old_freq, new_freq;
long freq_Hz, freq_exact;
int ret;
@@ -50,50 +47,14 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
new_freq = freq_Hz / 1000;
old_freq = clk_get_rate(cpu_clk) / 1000;
- if (!IS_ERR(cpu_reg)) {
- rcu_read_lock();
- opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
- if (IS_ERR(opp)) {
- rcu_read_unlock();
- pr_err("failed to find OPP for %ld\n", freq_Hz);
- return PTR_ERR(opp);
- }
- volt = dev_pm_opp_get_voltage(opp);
- rcu_read_unlock();
- tol = volt * voltage_tolerance / 100;
- volt_old = regulator_get_voltage(cpu_reg);
- }
-
- pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
- old_freq / 1000, volt_old ? volt_old / 1000 : -1,
- new_freq / 1000, volt ? volt / 1000 : -1);
-
- /* scaling up? scale voltage before frequency */
- if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
- ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
- if (ret) {
- pr_err("failed to scale voltage up: %d\n", ret);
- return ret;
- }
- }
+ pr_debug("%u MHz --> %u MHz\n", old_freq / 1000, new_freq / 1000);
ret = clk_set_rate(cpu_clk, freq_exact);
if (ret) {
pr_err("failed to set clock rate: %d\n", ret);
- if (!IS_ERR(cpu_reg))
- regulator_set_voltage_tol(cpu_reg, volt_old, tol);
return ret;
}
- /* scaling down? scale voltage after frequency */
- if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
- ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
- if (ret) {
- pr_err("failed to scale voltage down: %d\n", ret);
- clk_set_rate(cpu_clk, old_freq * 1000);
- }
- }
-
return ret;
}
@@ -117,33 +78,24 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
static int cpu0_cpufreq_probe(struct platform_device *pdev)
{
struct device_node *np;
+ unsigned int voltage_latency;
int ret;
- cpu_dev = get_cpu_device(0);
if (!cpu_dev) {
- pr_err("failed to get cpu0 device\n");
- return -ENODEV;
- }
-
- np = of_node_get(cpu_dev->of_node);
- if (!np) {
- pr_err("failed to find cpu0 node\n");
- return -ENOENT;
- }
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ pr_err("failed to get cpu0 device\n");
+ return -ENODEV;
+ }
- cpu_reg = devm_regulator_get_optional(cpu_dev, "cpu0");
- if (IS_ERR(cpu_reg)) {
- /*
- * If cpu0 regulator supply node is present, but regulator is
- * not yet registered, we should try defering probe.
- */
- if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
- dev_err(cpu_dev, "cpu0 regulator not ready, retry\n");
- ret = -EPROBE_DEFER;
- goto out_put_node;
+ np = of_node_get(cpu_dev->of_node);
+ ret = of_init_opp_table(cpu_dev);
+ if (ret) {
+ pr_err("failed to init OPP table: %d\n", ret);
+ return ret;
}
- pr_warn("failed to get cpu0 regulator: %ld\n",
- PTR_ERR(cpu_reg));
+ } else {
+ np = of_node_get(cpu_dev->of_node);
}
cpu_clk = devm_clk_get(cpu_dev, NULL);
@@ -153,11 +105,8 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
goto out_put_node;
}
- ret = of_init_opp_table(cpu_dev);
- if (ret) {
- pr_err("failed to init OPP table: %d\n", ret);
- goto out_put_node;
- }
+ if (of_property_read_u32(np, "clock-latency", &transition_latency))
+ transition_latency = CPUFREQ_ETERNAL;
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
if (ret) {
@@ -165,40 +114,30 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
goto out_put_node;
}
- of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
-
- if (of_property_read_u32(np, "clock-latency", &transition_latency))
- transition_latency = CPUFREQ_ETERNAL;
-
- if (!IS_ERR(cpu_reg)) {
- struct dev_pm_opp *opp;
- unsigned long min_uV, max_uV;
- int i;
-
- /*
- * OPP is maintained in order of increasing frequency, and
- * freq_table initialised from OPP is therefore sorted in the
- * same order.
- */
- for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
- ;
- rcu_read_lock();
- opp = dev_pm_opp_find_freq_exact(cpu_dev,
- freq_table[0].frequency * 1000, true);
- min_uV = dev_pm_opp_get_voltage(opp);
- opp = dev_pm_opp_find_freq_exact(cpu_dev,
- freq_table[i-1].frequency * 1000, true);
- max_uV = dev_pm_opp_get_voltage(opp);
- rcu_read_unlock();
- ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
- if (ret > 0)
- transition_latency += ret * 1000;
+ clk_nb = of_pm_voltdm_notifier_register(cpu_dev, np, cpu_clk, "cpu0",
+ &voltage_latency);
+
+ if (IS_ERR(clk_nb)) {
+ ret = PTR_ERR(clk_nb);
+ /* defer probe if regulator is not yet registered */
+ if (ret == -EPROBE_DEFER) {
+ dev_err(cpu_dev,
+ "cpu0 clock notifier not ready, retry\n");
+ } else {
+ dev_err(cpu_dev,
+ "Failed to register cpu0 clock notifier: %d\n",
+ ret);
+ }
+ goto out_freq_table_free;
}
+ if (voltage_latency > 0)
+ transition_latency += voltage_latency;
+
ret = cpufreq_register_driver(&cpu0_cpufreq_driver);
if (ret) {
pr_err("failed register driver: %d\n", ret);
- goto out_free_table;
+ goto out_notifier_unregister;
}
/*
@@ -215,7 +154,9 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
of_node_put(np);
return 0;
-out_free_table:
+out_notifier_unregister:
+ of_pm_voltdm_notifier_unregister(clk_nb);
+out_freq_table_free:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_put_node:
of_node_put(np);
@@ -226,6 +167,7 @@ static int cpu0_cpufreq_remove(struct platform_device *pdev)
{
cpufreq_cooling_unregister(cdev);
cpufreq_unregister_driver(&cpu0_cpufreq_driver);
+ of_pm_voltdm_notifier_unregister(clk_nb);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
return 0;
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 3/6] PM / Voltagedomain: introduce voltage domain driver support
From: Nishanth Menon @ 2014-02-18 20:32 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, MyungJoo Ham, Mark Brown,
Mike Turquette
Cc: devicetree, linux-doc, linux-kernel, cpufreq, linux-pm,
linux-arm-kernel, linux-omap, Nishanth Menon
In-Reply-To: <1392755543-28335-1-git-send-email-nm@ti.com>
Many SoCs have basic concepts of voltage rails supplying a specific
SoC device. These voltage rails may be as simple as a single regulator
or complex to be three or more regulators that are transitioned in
tandem with respect to clock changes. In some cases, they may tend
to use custom frameworks to do the actual voltage transition OR use
hardware modules that takes hints about the required configuration and
does optimized voltage transitions.
The current regulator model provides the basic building blocks for the
transitions, however SoC drivers specific to each of these devices, be
it cpufreq/devfreq have to replicate the logic for functionality.
To simply the logic, we can hence introduce a layer that takes care
of the mundane transition logic, registration mechanisms to provide
the "user drivers" such as cpufreq/devfreq a generic interface, whose
details are abstracted by the device tree description for the SoC on
which the driver operates on.
This allows us opportunity to make generic cpufreq / devfreq drivers
which may deal with a single clock, however the actual voltage change
mechanism can be customized specific to SoC without impact to the
generic driver.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
drivers/power/voltdm/Kconfig | 5 +
drivers/power/voltdm/Makefile | 3 +
drivers/power/voltdm/core.c | 347 +++++++++++++++++++++++--
drivers/power/voltdm/voltage_domain_private.h | 86 ++++++
4 files changed, 424 insertions(+), 17 deletions(-)
create mode 100644 drivers/power/voltdm/voltage_domain_private.h
diff --git a/drivers/power/voltdm/Kconfig b/drivers/power/voltdm/Kconfig
index c5353bd..270fdab 100644
--- a/drivers/power/voltdm/Kconfig
+++ b/drivers/power/voltdm/Kconfig
@@ -5,3 +5,8 @@ config VOLTAGE_DOMAIN
---help---
Core voltage domain framework using common clock framework's
notifier mechanism.
+
+menu "Voltage Domain Framework Drivers"
+ depends on VOLTAGE_DOMAIN
+
+endmenu
diff --git a/drivers/power/voltdm/Makefile b/drivers/power/voltdm/Makefile
index 3fa4408..fd32040 100644
--- a/drivers/power/voltdm/Makefile
+++ b/drivers/power/voltdm/Makefile
@@ -1,2 +1,5 @@
# Generic voltage domain
obj-$(CONFIG_VOLTAGE_DOMAIN) += core.o
+
+# Hardware specific voltage domain
+# please keep this section sorted lexicographically by file/directory path name
diff --git a/drivers/power/voltdm/core.c b/drivers/power/voltdm/core.c
index d0ed27e..69f6e81 100644
--- a/drivers/power/voltdm/core.c
+++ b/drivers/power/voltdm/core.c
@@ -10,12 +10,32 @@
* that scale voltage when a clock changes its output frequency.
*/
#include <linux/device.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/pm_voltage_domain.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include "voltage_domain_private.h"
+
+/**
+ * struct pm_voltdm_dev - internal representation of voltage domain devices
+ * @desc: voltage domain description
+ * @dev: voltage domain device
+ * @list: list to remaining voltage domain devices
+ * @lock: mutex to control data structure modifications and serialize ops
+ * @notifier_list: list of notifiers registered for this device
+ */
+struct pm_voltdm_dev {
+ const struct pm_voltdm_desc *desc;
+ struct device *dev;
+ struct list_head list;
+ /* list lock */
+ struct mutex lock;
+ struct list_head notifier_list;
+};
+
/**
* struct volt_scale_data - Internal structure to maintain notifier information
* @dev: device on behalf of which we register the notifier
@@ -23,6 +43,9 @@
* @reg: regulator if any which is used for scaling voltage
* @tol: voltage tolerance in %
* @nb: notifier block pointer
+ * @list: list head for the notifier
+ * @vdev: pointer to voltage domain device for this notifier
+ * @voltdm_data: voltdm driver specific data
*/
struct volt_scale_data {
struct device *dev;
@@ -30,23 +53,208 @@ struct volt_scale_data {
struct regulator *reg;
int tol;
struct notifier_block nb;
+ struct list_head list;
+
+ struct pm_voltdm_dev *vdev;
+ void *voltdm_data;
};
#define to_volt_scale_data(_nb) container_of(_nb, \
struct volt_scale_data, nb)
+static DEFINE_MUTEX(pm_voltdm_list_lock);
+static LIST_HEAD(pm_voltdm_list);
+
+static inline bool voltmd_skip_check(struct pm_voltdm_dev *vdev)
+{
+ bool ret = false;
+
+ if (vdev) {
+ const struct pm_voltdm_desc *desc;
+
+ if (IS_ERR(vdev))
+ return false;
+
+ mutex_lock(&vdev->lock);
+ desc = vdev->desc;
+
+ if (desc->flags & VOLTAGE_DOMAIN_FLAG_NOTIFY_ALL)
+ ret = true;
+ mutex_unlock(&vdev->lock);
+ }
+
+ return ret;
+}
+
+static inline int voltmd_scale_voltage(struct volt_scale_data *vsd,
+ unsigned long flags, int volt, int tol)
+{
+ int ret;
+ struct pm_voltdm_dev *vdev = vsd->vdev;
+
+ if (vdev) {
+ const struct pm_voltdm_ops *ops;
+
+ if (IS_ERR(vdev))
+ return PTR_ERR(vdev);
+
+ mutex_lock(&vdev->lock);
+ ops = vdev->desc->ops;
+
+ ret = ops->voltdm_do_transition(vdev->dev,
+ vsd->voltdm_data,
+ flags, volt, tol);
+ mutex_unlock(&vdev->lock);
+ } else {
+ ret = regulator_set_voltage_tol(vsd->reg, volt, tol);
+ }
+
+ return ret;
+}
+
+static struct pm_voltdm_dev *voltdm_parse_of(struct device_node *np,
+ const char *supply,
+ struct of_phandle_args *args)
+{
+ char prop_name[32]; /* 32 is max size of property name */
+ bool found = false;
+ struct device_node *voltdm_np;
+ struct pm_voltdm_dev *vdev = NULL;
+ int ret;
+
+ snprintf(prop_name, sizeof(prop_name), "%s-voltdm", supply);
+ voltdm_np = of_parse_phandle(np, prop_name, 0);
+ if (voltdm_np) {
+ ret = of_parse_phandle_with_args(np, prop_name, "#voltdm-cells",
+ 0, args);
+ if (ret)
+ return ERR_PTR(ret);
+
+ mutex_lock(&pm_voltdm_list_lock);
+ list_for_each_entry(vdev, &pm_voltdm_list, list)
+ if (vdev->dev->parent && voltdm_np == vdev->dev->of_node) {
+ found = true;
+ break;
+ }
+ mutex_unlock(&pm_voltdm_list_lock);
+
+ /* if node is present and not ready, then defer */
+ if (!found)
+ return ERR_PTR(-EPROBE_DEFER);
+ } else {
+ return NULL;
+ }
+
+ return vdev;
+}
+
+static int voltdm_get(struct volt_scale_data *vsd, struct device_node *np,
+ const char *supply, struct of_phandle_args *args,
+ bool *skip_reg)
+{
+ struct pm_voltdm_dev *vdev = vsd->vdev;
+ struct device *dev = vsd->dev;
+ int ret = 0;
+
+ if (vdev) {
+ const struct pm_voltdm_ops *ops;
+ if (IS_ERR(vdev))
+ return PTR_ERR(vdev);
+
+ mutex_lock(&vdev->lock);
+ if (!try_module_get(vdev->dev->driver->owner)) {
+ ret = -ENODEV;
+ } else {
+ ops = vdev->desc->ops;
+ if (ops->voltdm_get)
+ ret = ops->voltdm_get(vdev->dev, dev, np,
+ args, supply,
+ &vsd->voltdm_data);
+ if (ret)
+ module_put(vdev->dev->driver->owner);
+ }
+ if (!ret)
+ list_add(&vsd->list, &vdev->notifier_list);
+
+ mutex_unlock(&vdev->lock);
+ } else {
+ vsd->reg = regulator_get_optional(dev, supply);
+ if (IS_ERR(vsd->reg))
+ ret = PTR_ERR(vsd->reg);
+ /* Regulator is not mandatory */
+ if (ret != -EPROBE_DEFER) {
+ ret = 0;
+ *skip_reg = false;
+ dev_dbg(dev, "%s: Failed to get %s regulator:%d\n",
+ __func__, supply, ret);
+ }
+ }
+
+ return ret;
+}
+
+static void voltdm_put(struct volt_scale_data *vsd)
+{
+ struct pm_voltdm_dev *vdev = vsd->vdev;
+
+ if (vdev) {
+ const struct pm_voltdm_ops *ops;
+
+ if (IS_ERR(vdev))
+ return;
+
+ mutex_lock(&vdev->lock);
+ ops = vdev->desc->ops;
+ if (ops->voltdm_put)
+ ops->voltdm_put(vdev->dev, vsd->dev, vsd->voltdm_data);
+ list_del(&vsd->list);
+ module_put(vdev->dev->driver->owner);
+ mutex_unlock(&vdev->lock);
+ } else {
+ if (!IS_ERR(vsd->reg))
+ regulator_put(vsd->reg);
+ }
+}
+
+static int voltdm_get_latency(struct volt_scale_data *vsd, int min, int max)
+{
+ struct pm_voltdm_dev *vdev = vsd->vdev;
+ const struct pm_voltdm_ops *ops;
+ int ret;
+
+ if (!vdev)
+ return regulator_set_voltage_time(vsd->reg, min, max);
+
+ if (IS_ERR(vdev))
+ return PTR_ERR(vdev);
+
+ mutex_lock(&vdev->lock);
+ ops = vdev->desc->ops;
+
+ if (!ops->voltdm_latency)
+ ret = -ENXIO;
+ else
+ ret = ops->voltdm_latency(vdev->dev, vsd->voltdm_data,
+ min, max);
+ mutex_unlock(&vdev->lock);
+
+ return ret;
+}
+
static int clk_volt_notifier_handler(struct notifier_block *nb,
unsigned long flags, void *data)
{
struct clk_notifier_data *cnd = data;
struct volt_scale_data *vsd = to_volt_scale_data(nb);
+ struct pm_voltdm_dev *vdev = vsd->vdev;
int ret, volt, tol;
struct dev_pm_opp *opp;
unsigned long old_rate = cnd->old_rate;
unsigned long new_rate = cnd->new_rate;
- if ((new_rate < old_rate && flags == PRE_RATE_CHANGE) ||
- (new_rate > old_rate && flags == POST_RATE_CHANGE))
+ if (!voltmd_skip_check(vdev) &&
+ ((new_rate < old_rate && flags == PRE_RATE_CHANGE) ||
+ (new_rate > old_rate && flags == POST_RATE_CHANGE)))
return NOTIFY_OK;
rcu_read_lock();
@@ -69,7 +277,7 @@ static int clk_volt_notifier_handler(struct notifier_block *nb,
dev_dbg(vsd->dev, "%s: %lu -> %lu, V=%d, tol=%d, clk_flag=%lu\n",
__func__, old_rate, new_rate, volt, tol, flags);
- ret = regulator_set_voltage_tol(vsd->reg, volt, tol);
+ ret = voltmd_scale_voltage(vsd, flags, volt, tol);
if (ret) {
dev_err(vsd->dev,
"%s: Failed to scale voltage(%u): %d\n", __func__,
@@ -101,6 +309,14 @@ struct notifier_block *of_pm_voltdm_notifier_register(struct device *dev,
struct dev_pm_opp *opp;
unsigned long min, max, freq;
int ret;
+ struct of_phandle_args voltdm_args = {NULL};
+ struct pm_voltdm_dev *vdev = NULL;
+ bool skip_reg = false;
+
+ /* First look for voltdm of node */
+ vdev = voltdm_parse_of(np, supply, &voltdm_args);
+ if (IS_ERR(vdev))
+ return (struct notifier_block *)vdev;
vsd = kzalloc(sizeof(*vsd), GFP_KERNEL);
if (!vsd)
@@ -109,19 +325,16 @@ struct notifier_block *of_pm_voltdm_notifier_register(struct device *dev,
vsd->dev = dev;
vsd->clk = clk;
vsd->nb.notifier_call = clk_volt_notifier_handler;
- vsd->reg = regulator_get_optional(dev, supply);
- ret = 0;
- if (IS_ERR(vsd->reg))
- ret = PTR_ERR(vsd->reg);
- /* regulator is not mandatory */
- if (ret != -EPROBE_DEFER) {
- dev_warn(dev, "%s: Failed to get %s regulator:%d\n",
+ vsd->vdev = vdev;
+ ret = voltdm_get(vsd, np, supply, &voltdm_args, &skip_reg);
+
+ if (ret) {
+ dev_warn(dev, "%s: Failed to get %s regulator/voltdm: %d\n",
__func__, supply, ret);
- ret = 0;
goto err_free_vsd;
}
- /* For devices that are not ready.... */
- if (ret)
+ /* if not mandatory... */
+ if (skip_reg)
goto err_free_vsd;
rcu_read_lock();
@@ -138,7 +351,7 @@ struct notifier_block *of_pm_voltdm_notifier_register(struct device *dev,
max = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
- *voltage_latency = regulator_set_voltage_time(vsd->reg, min, max);
+ *voltage_latency = voltdm_get_latency(vsd, min, max);
if (*voltage_latency < 0) {
dev_warn(dev,
"%s: Fail calculating voltage latency[%ld<->%ld]:%d\n",
@@ -163,7 +376,7 @@ err_bad_opp:
dev_err(dev, "%s: failed to get OPP, %d\n", __func__, ret);
err_free_reg:
- regulator_put(vsd->reg);
+ voltdm_put(vsd);
err_free_vsd:
kfree(vsd);
@@ -187,9 +400,109 @@ void of_pm_voltdm_notifier_unregister(struct notifier_block *nb)
vsd = to_volt_scale_data(nb);
clk = vsd->clk;
clk_notifier_unregister(clk, nb);
- if (!IS_ERR(vsd->reg))
- regulator_put(vsd->reg);
+ voltdm_put(vsd);
kfree(vsd);
}
EXPORT_SYMBOL_GPL(of_pm_voltdm_notifier_unregister);
+
+static void devm_voltdm_release(struct device *dev, void *res)
+{
+ struct pm_voltdm_dev *vdev = *(struct pm_voltdm_dev **)res;
+ struct volt_scale_data *vsd;
+
+ mutex_lock(&pm_voltdm_list_lock);
+ mutex_lock(&vdev->lock);
+ list_for_each_entry(vsd, &vdev->notifier_list, list) {
+ dev_warn(dev, "%s: pending notifier from device %s!\n",
+ __func__, dev_name(vsd->dev));
+ vsd->vdev = ERR_PTR(-EINVAL);
+ }
+ mutex_unlock(&vdev->lock);
+
+ list_del(&vdev->list);
+ mutex_unlock(&pm_voltdm_list_lock);
+
+ kfree(vdev);
+}
+
+/**
+ * devm_voltdm_register - Resource managed voltage domain registration
+ * @dev: pointer to the device representing the voltage domain
+ * @desc: voltage domain descriptor
+ *
+ * Called by voltage domain drivers to register a voltagedomain. Returns a
+ * valid pointer to struct pm_voltdm_dev on success or an ERR_PTR() on
+ * error. The voltagedomain will automatically be released when the device
+ * is unbound.
+ */
+struct pm_voltdm_dev *devm_voltdm_register(struct device *dev,
+ const struct pm_voltdm_desc *desc)
+{
+ struct pm_voltdm_dev **ptr, *vdev;
+
+ if (!dev || !desc)
+ return ERR_PTR(-EINVAL);
+
+ if (!desc->ops)
+ return ERR_PTR(-EINVAL);
+
+ /* Mandatory to have notify transition */
+ if (!desc->ops->voltdm_do_transition) {
+ dev_err(dev, "%s: Bad desc -do_transition missing\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev)
+ return ERR_PTR(-ENOMEM);
+
+ ptr = devres_alloc(devm_voltdm_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr) {
+ kfree(vdev);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ vdev->desc = desc;
+ vdev->dev = dev;
+ mutex_init(&vdev->lock);
+ INIT_LIST_HEAD(&vdev->notifier_list);
+ mutex_lock(&pm_voltdm_list_lock);
+ list_add(&vdev->list, &pm_voltdm_list);
+ mutex_unlock(&pm_voltdm_list_lock);
+
+ *ptr = vdev;
+ devres_add(dev, ptr);
+
+ return vdev;
+}
+EXPORT_SYMBOL_GPL(devm_voltdm_register);
+
+static int devm_vdev_match(struct device *dev, void *res, void *data)
+{
+ struct pm_voltdm_dev **r = res;
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+ return *r == data;
+}
+
+/**
+ * devm_voltdm_unregister - Resource managed voltagedomain unregister
+ * @vdev: voltage domain device returned by devm_voltdm_register()
+ *
+ * Unregister a voltdm registered with devm_voltdm_register().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_voltdm_unregister(struct pm_voltdm_dev *vdev)
+{
+ int rc;
+ struct device *dev = vdev->dev;
+
+ rc = devres_release(dev, devm_voltdm_release, devm_vdev_match, vdev);
+ if (rc != 0)
+ WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_voltdm_unregister);
diff --git a/drivers/power/voltdm/voltage_domain_private.h b/drivers/power/voltdm/voltage_domain_private.h
new file mode 100644
index 0000000..e63c2b1
--- /dev/null
+++ b/drivers/power/voltdm/voltage_domain_private.h
@@ -0,0 +1,86 @@
+/*
+ * Voltage Domain private header for voltage domain drivers
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Nishanth Menon
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PM_VOLTAGE_DOMAIN_PRIVATE__
+#define __PM_VOLTAGE_DOMAIN_PRIVATE__
+
+#include <linux/pm_voltage_domain.h>
+
+struct pm_voltdm_dev;
+
+/**
+ * struct pm_voltdm_ops - Operations functions for voltage domain
+ * @voltdm_get: (optional) invoked when notifier is to be registered.
+ * @voltdm_put: (optional) invoked when notifier is unregistered.
+ * @voltdm_latency: (optional) compute and provide voltage domain
+ * transition latency.
+ * @voltdm_do_transition: (mandatory) callback for notification
+ *
+ * np_args - is arguments to the node phandle - useful when specific voltage
+ * domain is refered to using indices.
+ * voltdm_data - is the voltage domain driver specific data corresponding to
+ * driver information per registration (may point to domain driver specific
+ * data including reference to index. This is always provided back to the
+ * driver at various follow on operations.
+ * clk_notifier_flags - follows the standard clk notification flags
+ */
+struct pm_voltdm_ops {
+ int (*voltdm_get)(struct device *voltdm_dev,
+ struct device *request_dev,
+ struct device_node *np,
+ struct of_phandle_args *np_args,
+ const char *supply,
+ void **voltdm_data);
+ int (*voltdm_latency)(struct device *voltdm_dev, void *voltdm_data,
+ unsigned long min_uv, unsigned long max_uv);
+ int (*voltdm_do_transition)(struct device *voltdm_dev,
+ void *voltdm_data,
+ unsigned long clk_notifier_flags,
+ int uv, int tol_uv);
+ void (*voltdm_put)(struct device *voltdm_dev,
+ struct device *request_dev,
+ void *voltdm_data);
+};
+
+#define VOLTAGE_DOMAIN_FLAG_NOTIFY_ALL (0x1 << 0)
+
+/**
+ * struct pm_voltdm_desc - Descriptor for the voltage domain
+ * @ops: operations for the voltage domain
+ * @flags: flags controlling the various operations
+ */
+struct pm_voltdm_desc {
+ const struct pm_voltdm_ops *ops;
+ u16 flags;
+};
+
+#if defined(CONFIG_VOLTAGE_DOMAIN)
+struct pm_voltdm_dev *devm_voltdm_register(struct device *dev,
+ const struct pm_voltdm_desc *desc);
+void devm_voltdm_unregister(struct pm_voltdm_dev *vdev);
+#else
+static inline struct pm_voltdm_dev *devm_voltdm_register(struct device *dev,
+ const struct pm_voltdm_desc *desc)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline void devm_voltdm_unregister(struct pm_voltdm_dev *vdev)
+{
+}
+#endif /* VOLTAGE_DOMAIN */
+
+#endif /* __PM_VOLTAGE_DOMAIN_PRIVATE__ */
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 4/6] devicetree: bindings: add documentation for voltagedomain
From: Nishanth Menon @ 2014-02-18 20:32 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, MyungJoo Ham, Mark Brown,
Mike Turquette
Cc: Nishanth Menon, devicetree, linux-pm, linux-doc, linux-kernel,
cpufreq, linux-omap, linux-arm-kernel
In-Reply-To: <1392755543-28335-1-git-send-email-nm@ti.com>
Add documentation for voltage domain binding format. Specific
voltage domains will have bindings corresponding to them.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
.../bindings/power/voltdm/voltage_domain.txt | 65 ++++++++++++++++++++
1 file changed, 65 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/voltdm/voltage_domain.txt
diff --git a/Documentation/devicetree/bindings/power/voltdm/voltage_domain.txt b/Documentation/devicetree/bindings/power/voltdm/voltage_domain.txt
new file mode 100644
index 0000000..da48a19
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/voltdm/voltage_domain.txt
@@ -0,0 +1,65 @@
+Specifying Voltage Domain information for devices
+=================================================
+
+1. Specifying a voltage domain.
+
+SoCs may have multiple voltage domains under which various clocks operate.
+
+Mandatory Properties:
+- #voltdm-cells - indicates if there are specifiers needed to reference the
+ voltage domain
+
+Optional Properties:
+- voltage-tolerance: Specify the voltage tolerance in percentage
+
+2. Voltage domain consumer
+consumer nodes can be reference using the below binding:
+- <name>-voltdm: phandle to the voltage domain node.
+
+Examples:
+
+A. Voltage Domain controlling multiple regulator
+voltage_domain_mpu: voltdm@1 {
+ compatible = "xyz";
+ #voltdm-cells = <0>;
+ vdd-supply = <&vcc>;
+ vbb-supply = <&abb_mpu>;
+ ...
+};
+
+voltage_domain_gpu: voltdm@2 {
+ compatible = "xyz";
+ #voltdm-cells = <0>;
+ vdd-supply = <&dcdc2>;
+ vbb-supply = <&abb_gpu>;
+ ...
+};
+...
+&cpu0 {
+ cpu0-voltdm = <&voltage_domain_mpu>;
+ voltage-tolerance = <1>;
+};
+
+&gpu {
+ gpu-voltdm = <&voltage_domain_gpu>;
+};
+
+B. Indexed voltage domain device
+
+#define SOC_XYZ_VOLTAGE_DOMAIN_MPU 0
+#define SOC_XYZ_VOLTAGE_DOMAIN_GFX 1
+
+voltage_domain_socx: voltdm@1 {
+ compatible = "abc";
+ #voltdm-cells = <1>;
+ ...
+};
+...
+&cpu0 {
+ cpu0-voltdm = <&voltage_domain_socx SOC_XYZ_VOLTAGE_DOMAIN_MPU>;
+ voltage-tolerance = <1>;
+};
+
+&gpu {
+ gpu-voltdm = <&voltage_domain_socx SOC_XYZ_VOLTAGE_DOMAIN_GFX>;
+};
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox