Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH RFC v7 0/6] MPC512x DMA slave s/g support, OF DMA lookup
From: Gerhard Sittig @ 2014-02-13  0:32 UTC (permalink / raw)
  To: Alexander Popov
  Cc: Dan Williams, Vinod Koul, Lars-Peter Clausen, Arnd Bergmann,
	Anatolij Gustschin, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392211508-23615-1-git-send-email-a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

For some reason you have kept the DMA maintainers, but dropped
the dmaengine ML from Cc: -- was this intentional, given that the
series is specifically about DMA and you want to get feedback?

And you may want to help DT people by not sending purely Linux
implementation related stuff to them (they already are drinking
from the firehose).  DT reviewers are foremost interested in
bindings and policy and remaining OS agnostic, and leave
mechanical .dts file updates to subsystem maintainers.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org
--
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 net-next 00/10] Support for Broadcom GENET driver
From: Florian Fainelli @ 2014-02-13  0:23 UTC (permalink / raw)
  To: netdev
  Cc: David Miller, Kevin Cernekee, devicetree@vger.kernel.org,
	Florian Fainelli
In-Reply-To: <1392178053-3143-1-git-send-email-f.fainelli@gmail.com>

2014-02-11 20:07 GMT-08:00 Florian Fainelli <f.fainelli@gmail.com>:
> Hi all,
>
> This patchset adds support for the Broadcom GENET Gigabit Ethernet MAC
> controller. This controller is found on the Broadcom BCM7xxx Set Top Box
> System-on-a-Chip.

I just found a small bug in the main driver file, and due to my
previous series touching libphy, this will not apply cleanly anymore.
I will wait for some initial feedback before doing a second respin
though.

>
> Florian Fainelli (10):
>   net: phy: add "internal" PHY mode
>   net: phy: add MoCA PHY type
>   net: phy: update port type for MoCA PHYs
>   net: phy: add Broadcom BCM7xxx internal PHY driver
>   net: bcmgenet: add driver definitions and private structure
>   net: bcmgenet: add main driver file
>   net: bcmgenet: add MDIO routines
>   net: bcmgenet: hook into the build system
>   Documentation: add Device tree bindings for Broadcom GENET
>   MAINTAINERS: add entry for the Broadcom GENET driver
>
>  .../devicetree/bindings/net/broadcom-bcmgenet.txt  |  111 +
>  MAINTAINERS                                        |    6 +
>  drivers/net/ethernet/broadcom/Kconfig              |   10 +
>  drivers/net/ethernet/broadcom/Makefile             |    1 +
>  drivers/net/ethernet/broadcom/genet/Makefile       |    2 +
>  drivers/net/ethernet/broadcom/genet/bcmgenet.c     | 2685 ++++++++++++++++++++
>  drivers/net/ethernet/broadcom/genet/bcmgenet.h     |  631 +++++
>  drivers/net/ethernet/broadcom/genet/bcmmii.c       |  483 ++++
>  drivers/net/phy/Kconfig                            |    6 +
>  drivers/net/phy/Makefile                           |    1 +
>  drivers/net/phy/bcm7xxx.c                          |  322 +++
>  drivers/net/phy/phy.c                              |    5 +-
>  drivers/of/of_net.c                                |    2 +
>  include/linux/brcmphy.h                            |    9 +
>  include/linux/phy.h                                |    5 +-
>  15 files changed, 4277 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt
>  create mode 100644 drivers/net/ethernet/broadcom/genet/Makefile
>  create mode 100644 drivers/net/ethernet/broadcom/genet/bcmgenet.c
>  create mode 100644 drivers/net/ethernet/broadcom/genet/bcmgenet.h
>  create mode 100644 drivers/net/ethernet/broadcom/genet/bcmmii.c
>  create mode 100644 drivers/net/phy/bcm7xxx.c
>
> --
> 1.8.3.2
>



-- 
Florian

^ permalink raw reply

* Re: [PATCH RFC v7 4/6] dma: mpc512x: add device tree binding document
From: Gerhard Sittig @ 2014-02-13  0:21 UTC (permalink / raw)
  To: Alexander Popov
  Cc: Dan Williams, Vinod Koul, Lars-Peter Clausen, Arnd Bergmann,
	Anatolij Gustschin, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392211508-23615-5-git-send-email-a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Wed, Feb 12, 2014 at 17:25 +0400, Alexander Popov wrote:
> 
> From: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
> 
> introduce a device tree binding document for the MPC512x DMA controller
> 
> Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
> [ a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org: turn this into a separate patch ]

As stated in the previous iteration, this one no longer is good
enough.  As time has passed, we have moved forward and learned
something.  We would not write a binding like this today.
Admittedly I went dormant (did not provide an update) since v6.

There are several issues.
- The MPC512x DMA completely lacks a binding document, so one
  should get added.
- The MPC8308 hardware is similar and can re-use the MPC512x
  binding, which should be stated.
- The Linux implementation currently has no OF based channel
  lookup support, so '#dma-cells' is "a future feature".  I guess
  the binding can and should already discuss the feature,
  regardless of whether all implementations support it.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 0/14] Xilinx axi ethernet patches
From: David Miller @ 2014-02-13  0:18 UTC (permalink / raw)
  To: michal.simek
  Cc: netdev, sthokal, devicetree, monstr, John.Linn, anirudh,
	linux-kernel, grant.likely, robh+dt, linux-arm-kernel
In-Reply-To: <cover.1392220536.git.michal.simek@xilinx.com>

From: Michal Simek <michal.simek@xilinx.com>
Date: Wed, 12 Feb 2014 16:55:34 +0100

> I have exctracted patches which I have in our
> xilinx git tree which are missing in the mainline.
> 
> The first two patches fix compilation error and
> warnings. Then 5 feature patches
> and the rest is OF cleanup and with kernel-doc
> and checkpatch problems.

You should not combine bug fix and feature patches.

Rather, you should submit bug fixes against the 'net' tree.  Then when
those bug fixes get applied and propagate to the 'net-next' tree you
can submit the feature patches and cleanups against the 'net-next'
tree.

^ permalink raw reply

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Laura Abbott @ 2014-02-13  0:06 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: devicetree, Kees Cook, linux-kernel, Rob Herring, Kumar Gala,
	Grant Likely, linux-arm-kernel
In-Reply-To: <201402121251.06280.arnd@arndb.de>

On 2/12/2014 3:51 AM, Arnd Bergmann wrote:
> On Wednesday 12 February 2014, Laura Abbott wrote:
>> This is an RFC to seed the random number pool earlier when using devicetree.
>> The big issue this is trying to solve is the fact that the stack canary for
>> ARM tends to be the same across bootups of the same device. This is because
>> the random number pools do not get initialized until after the canary has
>> been set up. The canary can be moved later, but in general there is still
>> no way to reliably get random numbers early for other features (e.g. vector
>> randomization).
>
> Implementation-wise this looks reasonable, and it obviously addresses a
> very real problem.
>
>> The goal here is to allow devices to add to the random pools via
>> add_device_randomness or some other method of their chosing at FDT time.
>> I realize that ARCH_RANDOM is already available but this didn't work because
>> 1) ARCH_RANDOM is not multi-platform compatible without added
>> infrastructure to ARM
>
> That could certainly be done, but I agree that a more generic
> approach like you did is nicer. One thing that might be useful
> would be to wire up your OF_RANDOM infrastructure as a generic
> implementation of ARCH_RANDOM, and merge your header file into
> include/asm-generic/archrandom.h, with an added way to call
> arch_get_random_long() for the devices you add.
>

I originally tried that approach but ran into some hiccups related to 
mapping for access to the HWRNG. early_ioremap would be needed to access 
hardware registers but on ARM early_ioremap does not persist across 
paging init. I couldn't come up with a sufficiently not terrible way to 
unmap the early mapping and re-map with a proper ioremap.

>> The big reason to skip ARCH_RANDOM though is that the random number generation
>> we have would be reasonable if only seeded earlier.
>
> Yes, makes sense.
>
> I also wonder if we should add a 'trivial' implementation that just
> reads a DT property full of random numbers to use as either an initial
> seed, or to feed into arch_get_random_long(). This would allow the
> boot loader to pass any entropy it has already gathered into the kernel,
> but leaves the danger that people might pass static not-so-random data
> through a precompiled dtb file ;-). If we get the boot loaders to be
> smart enough, doing only this would be a much simpler kernel implementation
> than your suggestion, but I'm not sure how far I want to trust boot loaders.
>

This was similar to an option discussed internally (passing a seed on 
the command line). Ultimately, it was concluded that relying on the 
bootloader to do this would be too much overhead vs. doing all the work 
in the kernel.

> Another possibilitiy is to mix in the any contents of a "local-mac-address"
> property into the entropy at early DT probing, which would still be
> deterministic for a given machine and should not count as entropty,
> but at least give each machine with this property a unique seed in the
> absence of any other entropy source.

Is this typically updated by the bootloader as well? I'm looking at the 
tree and most of the instances of local-mac-address I see are all zero.

>
> 	Arnd

Thanks,
Laura


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Rob Herring @ 2014-02-12 23:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Jason Cooper, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Laura Abbott, Kees Cook,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
	Kumar Gala, Grant Likely
In-Reply-To: <1882539.R1gpoLLYks@wuerfel>

On Wed, Feb 12, 2014 at 1:12 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Wednesday 12 February 2014 13:45:21 Jason Cooper wrote:
>> On Wed, Feb 12, 2014 at 07:17:41PM +0100, Arnd Bergmann wrote:
>> > On Wednesday 12 February 2014 12:45:54 Jason Cooper wrote:
>> > > I brought this up at last weeks devicetree irc meeting.  My goal is to
>> > > provide early randomness for kaslr on ARM.  Currently, my idea is modify
>> > > the init script to save an additional random seed from /dev/urandom to
>> > > /boot/random-seed.
>> > >
>> > > The bootloader would then load this file into ram, and pass the
>> > > address/size to the kernel either via dt, or commandline.  kaslr (run in
>> > > the decompressor) would consume some of this randomness, and then
>> > > random.c would consume the rest in a non-crediting initialization.
>> >
>> > I like the idea, but wouldn't it be easier to pass actual random data
>> > using DT, rather than the address/size?
>>
>> I thought about that at first, but that requires either that the
>> bootloader be upgraded to insert the data, or that userspace is
>> modifying the dtb at least twice per boot.
>>
>> I chose address/size to facilitate modifying existing/fielded devices.
>> The user could modify the dtb once, and modify the bootloader
>> environment to load X amount to Y address.  As a fallback, it could be
>> expressed on the commandline for non-DT bootloaders.
>
> Ah, so you are interested in boot loaders that can be scripted to do
> what you had in mind but cannot be scripted to add or modify a DT
> property. I hadn't considered that, but you are probably right that
> this is at least 90% of the systems you'd find in the wild today.
>
> Thinking this a bit further, I wonder if (at least upstream) u-boot
> has a way to modify DT properties in a scripted way that would allow
> the direct property. It sounds like a generally useful feature not
> just for randomness, so if that doesn't already work, maybe someone
> can implement it. In the simplest case, you'd only need to find the
> address of an existing property in the dtb and load a file to
> that location.

You would be referring to the u-boot fdt command which can read and
set properties. Of course, like all u-boot commands, that may or may
not be enabled by a vendor's u-boot. :(

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

^ permalink raw reply

* Re: [PATCH] of: Turn of_match_node into a static inline when CONFIG_OF isn't set
From: Geert Uytterhoeven @ 2014-02-12 21:54 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Josh Cartwright, Laurent Pinchart, linux-kernel@vger.kernel.org,
	devicetree@vger.kernel.org, Grant Likely, Rob Herring
In-Reply-To: <3619654.tQqiI1EfTB@wuerfel>

On Tue, Feb 11, 2014 at 9:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 11 February 2014 19:29:19 Geert Uytterhoeven wrote:
>> On Tue, Feb 11, 2014 at 7:08 PM, Josh Cartwright <joshc@codeaurora.org> wrote:
>> Ideally, all xxx_device_id look like
>>
>>     struct xxx_device_id {
>>             ... /* bus-specific ID information */
>>             kernel_ulong_t driver_data;
>>     };
>>
>> This may be formalized in some way, using a base class, but thay may
>> require reordering the fields, like:
>>
>>     struct base_device_id {
>>             kernel_ulong_t driver_data;
>>             long id[0];
>>     };
>>
>
> You can't reorder the fields because they are shared with user
> space in form of the module-init-tools.

Sure, that's part of the ABI.

But that doesn't mean we can't change the ID as stored in the platform_device.
Many drivers don't want to know the ID, only the driver_data part.
Having that in a uniform way across the different ID types would help.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Kees Cook @ 2014-02-12 21:35 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Arnd Bergmann, Laura Abbott, Grant Likely, Rob Herring, LKML,
	devicetree, linux-arm-kernel@lists.infradead.org, Kumar Gala
In-Reply-To: <20140212174554.GM27395@titan.lakedaemon.net>

On Wed, Feb 12, 2014 at 9:45 AM, Jason Cooper <jason@lakedaemon.net> wrote:
> I brought this up at last weeks devicetree irc meeting.  My goal is to
> provide early randomness for kaslr on ARM.  Currently, my idea is modify
> the init script to save an additional random seed from /dev/urandom to
> /boot/random-seed.

I'm all for a good entropy source for early boot. :)

I need to figure out what's needed for relocation support first
though, before we can really tackle kernel base-address randomization
on ARM. I haven't had a chance to look around too closely yet, but it
seems like only x86 and ppc do this currently? Has anyone looked in
detail and what would be needed on ARM for CONFIG_RELOCATABLE
behavior?

-Kees

-- 
Kees Cook
Chrome OS Security

^ permalink raw reply

* Re: [PATCH] of: give priority to the compatible match in __of_match_node()
From: Stephen N Chivers @ 2014-02-12 20:42 UTC (permalink / raw)
  To: Kevin Hao
  Cc: Chris Proctor, Arnd Bergmann, devicetree, Stephen N Chivers,
	Scott Wood, Rob Herring, Grant Likely, linuxppc-dev,
	Sebastian Hesselbarth
In-Reply-To: <1392205084-2351-1-git-send-email-haokexin@gmail.com>

Kevin Hao <haokexin@gmail.com> wrote on 02/12/2014 10:38:04 PM:

> From: Kevin Hao <haokexin@gmail.com>
> To: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Stephen
> N Chivers <schivers@csc.com.au>, Chris Proctor 
> <cproctor@csc.com.au>, Arnd Bergmann <arnd@arndb.de>, Scott Wood 
> <scottwood@freescale.com>, Grant Likely <grant.likely@linaro.org>, 
> Rob Herring <robh+dt@kernel.org>
> Date: 02/12/2014 10:38 PM
> Subject: [PATCH] of: give priority to the compatible match in 
> __of_match_node()
> 
> When the device node do have a compatible property, we definitely
> prefer the compatible match besides the type and name. Only if
> there is no such a match, we then consider the candidate which
> doesn't have compatible entry but do match the type or name with
> the device node.
> 
> This is based on a patch from Sebastian Hesselbarth.
>   http://patchwork.ozlabs.org/patch/319434/
> 
> I did some code refactoring and also fixed a bug in the original patch.
> 
> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
Tested-by: Stephen Chivers <schivers@csc.com>

Patch works for both orderings. Platform boots without problems and
I get the normal serial console.
> ---
>  drivers/of/base.c | 55 ++++++++++++++++++++++++++++++++++++
> +------------------
>  1 file changed, 37 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index ff85450d5683..9d655df458bd 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -730,32 +730,45 @@ out:
>  }
>  EXPORT_SYMBOL(of_find_node_with_property);
> 
> +static int of_match_type_or_name(const struct device_node *node,
> +            const struct of_device_id *m)
> +{
> +   int match = 1;
> +
> +   if (m->name[0])
> +      match &= node->name && !strcmp(m->name, node->name);
> +
> +   if (m->type[0])
> +      match &= node->type && !strcmp(m->type, node->type);
> +
> +   return match;
> +}
> +
>  static
>  const struct of_device_id *__of_match_node(const struct 
> of_device_id *matches,
>                    const struct device_node *node)
>  {
>     const char *cp;
>     int cplen, l;
> +   const struct of_device_id *m;
> +   int match;
> 
>     if (!matches)
>        return NULL;
> 
>     cp = __of_get_property(node, "compatible", &cplen);
> -   do {
> -      const struct of_device_id *m = matches;
> +   while (cp && (cplen > 0)) {
> +      m = matches;
> 
>        /* Check against matches with current compatible string */
>        while (m->name[0] || m->type[0] || m->compatible[0]) {
> -         int match = 1;
> -         if (m->name[0])
> -            match &= node->name
> -               && !strcmp(m->name, node->name);
> -         if (m->type[0])
> -            match &= node->type
> -               && !strcmp(m->type, node->type);
> -         if (m->compatible[0])
> -            match &= cp
> -               && !of_compat_cmp(m->compatible, cp,
> +         if (!m->compatible[0]) {
> +            m++;
> +            continue;
> +         }
> +
> +         match = of_match_type_or_name(node, m);
> +         match &= cp && !of_compat_cmp(m->compatible, cp,
>                       strlen(m->compatible));
>           if (match)
>              return m;
> @@ -763,12 +776,18 @@ const struct of_device_id *__of_match_node
> (const struct of_device_id *matches,
>        }
> 
>        /* Get node's next compatible string */ 
> -      if (cp) {
> -         l = strlen(cp) + 1;
> -         cp += l;
> -         cplen -= l;
> -      }
> -   } while (cp && (cplen > 0));
> +      l = strlen(cp) + 1;
> +      cp += l;
> +      cplen -= l;
> +   }
> +
> +   m = matches;
> +   /* Check against matches without compatible string */
> +   while (m->name[0] || m->type[0] || m->compatible[0]) {
> +      if (!m->compatible[0] && of_match_type_or_name(node, m))
> +         return m;
> +      m++;
> +   }
> 
>     return NULL;
>  }
> -- 
> 1.8.5.3
> 

^ permalink raw reply

* Re: [PATCH] export of_irq_count
From: Rob Herring @ 2014-02-12 19:56 UTC (permalink / raw)
  To: delicious quinoa
  Cc: Rob Herring, Grant Likely,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Dinh Nguyen,
	Yves Vandervennet, Alan Tull
In-Reply-To: <CANk1AXTbnBXzxf_WiQAbWKxNhm2wKVrj0O=nDcW7j27i4T3YBw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Wed, Feb 12, 2014 at 12:43 PM, delicious quinoa
<delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Wed, Feb 12, 2014 at 12:32 PM, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Wed, Feb 12, 2014 at 11:34 AM, delicious quinoa
>> <delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> From: Alan Tull <atull-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>
>>>
>>> export of_irq_count so it can be used in drivers that are built
>>> as modules.
>>
>> What drivers? Drivers generally should be using resources rather than
>> this function directly.
>
> It's for the DesignWare GPIO driver I've been upstreaming.  The
> DesignWare IP can be configured to be one irq for all the gpios or one
> irq per gpio.  I want to support both cases.  So I need to know how
> many irqs are specified in the device tree.

Okay. You should merge this as part of that then, so:

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

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

^ permalink raw reply

* [PATCH v6 5/6] spmi: document the PMIC arbiter SPMI bindings
From: Josh Cartwright @ 2014-02-12 19:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel
  Cc: linux-arm-msm, Gilad Avidov, Sagar Dharia, Michael Bohan,
	linux-arm-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, devicetree, linux-doc
In-Reply-To: <1392234267-10880-1-git-send-email-joshc@codeaurora.org>

Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
---
 .../bindings/spmi/qcom,spmi-pmic-arb.txt           | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt

diff --git a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
new file mode 100644
index 0000000..715d099
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
@@ -0,0 +1,61 @@
+Qualcomm SPMI Controller (PMIC Arbiter)
+
+The SPMI PMIC Arbiter is found on the Snapdragon 800 Series.  It is an SPMI
+controller with wrapping arbitration logic to allow for multiple on-chip
+devices to control a single SPMI master.
+
+The PMIC Arbiter can also act as an interrupt controller, providing interrupts
+to slave devices.
+
+See spmi.txt for the generic SPMI controller binding requirements for child
+nodes.
+
+See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+generic interrupt controller binding documentation.
+
+Required properties:
+- compatible : should be "qcom,spmi-pmic-arb".
+- reg-names  : must contain:
+     "core" - core registers
+     "intr" - interrupt controller registers
+     "cnfg" - configuration registers
+- reg : address + size pairs describing the PMIC arb register sets; order must
+        correspond with the order of entries in reg-names
+- #address-cells : must be set to 2
+- #size-cells : must be set to 0
+- qcom,ee : indicates the active Execution Environment identifier (0-5)
+- qcom,channel : which of the PMIC Arb provided channels to use for accesses (0-5)
+- interrupts : interrupt list for the PMIC Arb controller, must contain a
+               single interrupt entry for the peripheral interrupt
+- interrupt-names : corresponding interrupt names for the interrupts
+                    listed in the 'interrupts' property, must contain:
+     "periph_irq" - summary interrupt for PMIC peripherals
+- interrupt-controller : boolean indicator that the PMIC arbiter is an interrupt controller
+- #interrupt-cells :  must be set to 4. Interrupts are specified as a 4-tuple:
+    cell 1: slave ID for the requested interrupt (0-15)
+    cell 2: peripheral ID for requested interrupt (0-255)
+    cell 3: the requested peripheral interrupt (0-7)
+    cell 4: interrupt flags indicating level-sense information, as defined in
+            dt-bindings/interrupt-controller/irq.h
+
+Example:
+
+	spmi {
+		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
+		reg = <0xfc4cf000 0x1000>,
+		      <0xfc4cb000 0x1000>,
+		      <0xfc4ca000 0x1000>;
+
+		interrupt-names = "periph_irq";
+		interrupts = <0 190 0>;
+
+		qcom,ee = <0>;
+		qcom,channel = <0>;
+
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		interrupt-controller;
+		#interrupt-cells = <4>;
+	};
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCH v6 3/6] spmi: Add MSM PMIC Arbiter SPMI controller
From: Josh Cartwright @ 2014-02-12 19:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Grant Likely, Rob Herring
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Gilad Avidov, Sagar Dharia,
	Michael Bohan, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Kenneth Heitke, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392234267-10880-1-git-send-email-joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

From: Kenneth Heitke <kheitke-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Qualcomm's PMIC Arbiter SPMI controller functions as a bus master and
is used to communication with one or more PMIC (slave) devices on the
SPMI bus.  The PMIC Arbiter is actually a hardware wrapper around the
SPMI controller that provides concurrent and autonomous PMIC access
to various entities that need to communicate with the PMIC.

The SPMI controller hardware handles all of the SPMI bus activity (bus
arbitration, sequence start condition, transmission of frames, etc).
This software driver uses the PMIC Arbiter register interface to
initiate command sequences on the SPMI bus.  The status register is
read to determine when the command sequence has completed and whether
or not it completed successfully.

Signed-off-by: Kenneth Heitke <kheitke-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Josh Cartwright <joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 drivers/spmi/Kconfig         |  17 ++
 drivers/spmi/Makefile        |   2 +
 drivers/spmi/spmi-pmic-arb.c | 405 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 424 insertions(+)
 create mode 100644 drivers/spmi/spmi-pmic-arb.c

diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 1dbfee0..80b7901 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -7,3 +7,20 @@ menuconfig SPMI
 	  SPMI (System Power Management Interface) is a two-wire
 	  serial interface between baseband and application processors
 	  and Power Management Integrated Circuits (PMIC).
+
+if SPMI
+
+config SPMI_MSM_PMIC_ARB
+	tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
+	depends on ARM
+	depends on ARCH_MSM || COMPILE_TEST
+	default ARCH_MSM
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in SPMI PMIC Arbiter interface on Qualcomm MSM family
+	  processors.
+
+	  This is required for communicating with Qualcomm PMICs and
+	  other devices that have the SPMI interface.
+
+endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 1de1acd..fc75104 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -2,3 +2,5 @@
 # Makefile for kernel SPMI framework.
 #
 obj-$(CONFIG_SPMI)	+= spmi.o
+
+obj-$(CONFIG_SPMI_MSM_PMIC_ARB)	+= spmi-pmic-arb.o
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
new file mode 100644
index 0000000..2dd27e8
--- /dev/null
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -0,0 +1,405 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+/* PMIC Arbiter configuration registers */
+#define PMIC_ARB_VERSION		0x0000
+#define PMIC_ARB_INT_EN			0x0004
+
+/* PMIC Arbiter channel registers */
+#define PMIC_ARB_CMD(N)			(0x0800 + (0x80 * (N)))
+#define PMIC_ARB_CONFIG(N)		(0x0804 + (0x80 * (N)))
+#define PMIC_ARB_STATUS(N)		(0x0808 + (0x80 * (N)))
+#define PMIC_ARB_WDATA0(N)		(0x0810 + (0x80 * (N)))
+#define PMIC_ARB_WDATA1(N)		(0x0814 + (0x80 * (N)))
+#define PMIC_ARB_RDATA0(N)		(0x0818 + (0x80 * (N)))
+#define PMIC_ARB_RDATA1(N)		(0x081C + (0x80 * (N)))
+
+/* Interrupt Controller */
+#define SPMI_PIC_OWNER_ACC_STATUS(M, N)	(0x0000 + ((32 * (M)) + (4 * (N))))
+#define SPMI_PIC_ACC_ENABLE(N)		(0x0200 + (4 * (N)))
+#define SPMI_PIC_IRQ_STATUS(N)		(0x0600 + (4 * (N)))
+#define SPMI_PIC_IRQ_CLEAR(N)		(0x0A00 + (4 * (N)))
+
+/* Mapping Table */
+#define SPMI_MAPPING_TABLE_REG(N)	(0x0B00 + (4 * (N)))
+#define SPMI_MAPPING_BIT_INDEX(X)	(((X) >> 18) & 0xF)
+#define SPMI_MAPPING_BIT_IS_0_FLAG(X)	(((X) >> 17) & 0x1)
+#define SPMI_MAPPING_BIT_IS_0_RESULT(X)	(((X) >> 9) & 0xFF)
+#define SPMI_MAPPING_BIT_IS_1_FLAG(X)	(((X) >> 8) & 0x1)
+#define SPMI_MAPPING_BIT_IS_1_RESULT(X)	(((X) >> 0) & 0xFF)
+
+#define SPMI_MAPPING_TABLE_LEN		255
+#define SPMI_MAPPING_TABLE_TREE_DEPTH	16	/* Maximum of 16-bits */
+
+/* Ownership Table */
+#define SPMI_OWNERSHIP_TABLE_REG(N)	(0x0700 + (4 * (N)))
+#define SPMI_OWNERSHIP_PERIPH2OWNER(X)	((X) & 0x7)
+
+/* Channel Status fields */
+enum pmic_arb_chnl_status {
+	PMIC_ARB_STATUS_DONE	= (1 << 0),
+	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
+	PMIC_ARB_STATUS_DENIED	= (1 << 2),
+	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
+};
+
+/* Command register fields */
+#define PMIC_ARB_CMD_MAX_BYTE_COUNT	8
+
+/* Command Opcodes */
+enum pmic_arb_cmd_op_code {
+	PMIC_ARB_OP_EXT_WRITEL = 0,
+	PMIC_ARB_OP_EXT_READL = 1,
+	PMIC_ARB_OP_EXT_WRITE = 2,
+	PMIC_ARB_OP_RESET = 3,
+	PMIC_ARB_OP_SLEEP = 4,
+	PMIC_ARB_OP_SHUTDOWN = 5,
+	PMIC_ARB_OP_WAKEUP = 6,
+	PMIC_ARB_OP_AUTHENTICATE = 7,
+	PMIC_ARB_OP_MSTR_READ = 8,
+	PMIC_ARB_OP_MSTR_WRITE = 9,
+	PMIC_ARB_OP_EXT_READ = 13,
+	PMIC_ARB_OP_WRITE = 14,
+	PMIC_ARB_OP_READ = 15,
+	PMIC_ARB_OP_ZERO_WRITE = 16,
+};
+
+/* Maximum number of support PMIC peripherals */
+#define PMIC_ARB_MAX_PERIPHS		256
+#define PMIC_ARB_PERIPH_ID_VALID	(1 << 15)
+#define PMIC_ARB_TIMEOUT_US		100
+#define PMIC_ARB_MAX_TRANS_BYTES	(8)
+
+#define PMIC_ARB_APID_MASK		0xFF
+#define PMIC_ARB_PPID_MASK		0xFFF
+
+/* interrupt enable bit */
+#define SPMI_PIC_ACC_ENABLE_BIT		BIT(0)
+
+/**
+ * spmi_pmic_arb_dev - SPMI PMIC Arbiter object
+ *
+ * @base:		address of the PMIC Arbiter core registers.
+ * @intr:		address of the SPMI interrupt control registers.
+ * @cnfg:		address of the PMIC Arbiter configuration registers.
+ * @lock:		lock to synchronize accesses.
+ * @channel:		which channel to use for accesses.
+ */
+struct spmi_pmic_arb_dev {
+	void __iomem		*base;
+	void __iomem		*intr;
+	void __iomem		*cnfg;
+	raw_spinlock_t		lock;
+	u8			channel;
+};
+
+static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset)
+{
+	return readl_relaxed(dev->base + offset);
+}
+
+static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
+				       u32 offset, u32 val)
+{
+	writel_relaxed(val, dev->base + offset);
+}
+
+/**
+ * pa_read_data: reads pmic-arb's register and copy 1..4 bytes to buf
+ * @bc:		byte count -1. range: 0..3
+ * @reg:	register's address
+ * @buf:	output parameter, length must be bc + 1
+ */
+static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = pmic_arb_base_read(dev, reg);
+	memcpy(buf, &data, (bc & 3) + 1);
+}
+
+/**
+ * pa_write_data: write 1..4 bytes from buf to pmic-arb's register
+ * @bc:		byte-count -1. range: 0..3.
+ * @reg:	register's address.
+ * @buf:	buffer to write. length must be bc + 1.
+ */
+static void
+pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = 0;
+	memcpy(&data, buf, (bc & 3) + 1);
+	pmic_arb_base_write(dev, reg, data);
+}
+
+static int pmic_arb_wait_for_done(struct spmi_controller *ctrl)
+{
+	struct spmi_pmic_arb_dev *dev = spmi_controller_get_drvdata(ctrl);
+	u32 status = 0;
+	u32 timeout = PMIC_ARB_TIMEOUT_US;
+	u32 offset = PMIC_ARB_STATUS(dev->channel);
+
+	while (timeout--) {
+		status = pmic_arb_base_read(dev, offset);
+
+		if (status & PMIC_ARB_STATUS_DONE) {
+			if (status & PMIC_ARB_STATUS_DENIED) {
+				dev_err(&ctrl->dev,
+					"%s: transaction denied (0x%x)\n",
+					__func__, status);
+				return -EPERM;
+			}
+
+			if (status & PMIC_ARB_STATUS_FAILURE) {
+				dev_err(&ctrl->dev,
+					"%s: transaction failed (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			if (status & PMIC_ARB_STATUS_DROPPED) {
+				dev_err(&ctrl->dev,
+					"%s: transaction dropped (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			return 0;
+		}
+		udelay(1);
+	}
+
+	dev_err(&ctrl->dev,
+		"%s: timeout, status 0x%x\n",
+		__func__, status);
+	return -ETIMEDOUT;
+}
+
+/* Non-data command */
+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	/* Check for valid non-data command */
+	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
+		return -EINVAL;
+
+	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
+
+	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(ctrl);
+	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			     u16 addr, u8 *buf, size_t len)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	unsigned long flags;
+	u8 bc = len - 1;
+	u32 cmd;
+	int rc;
+
+	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
+		dev_err(&ctrl->dev,
+			"pmic-arb supports 1..%d bytes per trans, but %d requested",
+			PMIC_ARB_MAX_TRANS_BYTES, len);
+		return  -EINVAL;
+	}
+
+	/* Check the opcode */
+	if (opc >= 0x60 && opc <= 0x7F)
+		opc = PMIC_ARB_OP_READ;
+	else if (opc >= 0x20 && opc <= 0x2F)
+		opc = PMIC_ARB_OP_EXT_READ;
+	else if (opc >= 0x38 && opc <= 0x3F)
+		opc = PMIC_ARB_OP_EXT_READL;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(ctrl);
+	if (rc)
+		goto done;
+
+	pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel),
+		     min_t(u8, bc, 3));
+
+	if (bc > 3)
+		pa_read_data(pmic_arb, buf + 4,
+				PMIC_ARB_RDATA1(pmic_arb->channel), bc - 4);
+
+done:
+	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return rc;
+}
+
+static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
+			      u16 addr, const u8 *buf, size_t len)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	unsigned long flags;
+	u8 bc = len - 1;
+	u32 cmd;
+	int rc;
+
+	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
+		dev_err(&ctrl->dev,
+			"pmic-arb supports 1..%d bytes per trans, but:%d requested",
+			PMIC_ARB_MAX_TRANS_BYTES, len);
+		return  -EINVAL;
+	}
+
+	/* Check the opcode */
+	if (opc >= 0x40 && opc <= 0x5F)
+		opc = PMIC_ARB_OP_WRITE;
+	else if (opc >= 0x00 && opc <= 0x0F)
+		opc = PMIC_ARB_OP_EXT_WRITE;
+	else if (opc >= 0x30 && opc <= 0x37)
+		opc = PMIC_ARB_OP_EXT_WRITEL;
+	else if (opc >= 0x80 && opc <= 0xFF)
+		opc = PMIC_ARB_OP_ZERO_WRITE;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	/* Write data to FIFOs */
+	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
+	pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel)
+							, min_t(u8, bc, 3));
+	if (bc > 3)
+		pa_write_data(pmic_arb, buf + 4,
+				PMIC_ARB_WDATA1(pmic_arb->channel), bc - 4);
+
+	/* Start the transaction */
+	pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(ctrl);
+	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+static int spmi_pmic_arb_probe(struct platform_device *pdev)
+{
+	struct spmi_pmic_arb_dev *pa;
+	struct spmi_controller *ctrl;
+	struct resource *res;
+	u32 channel;
+	int err, i;
+
+	ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa));
+	if (!ctrl)
+		return -ENOMEM;
+
+	pa = spmi_controller_get_drvdata(ctrl);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
+	pa->base = devm_ioremap_resource(&ctrl->dev, res);
+	if (IS_ERR(pa->base)) {
+		err = PTR_ERR(pa->base);
+		goto err_put_ctrl;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
+	pa->intr = devm_ioremap_resource(&ctrl->dev, res);
+	if (IS_ERR(pa->intr)) {
+		err = PTR_ERR(pa->intr);
+		goto err_put_ctrl;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
+	pa->cnfg = devm_ioremap_resource(&ctrl->dev, res);
+	if (IS_ERR(pa->cnfg)) {
+		err = PTR_ERR(pa->cnfg);
+		goto err_put_ctrl;
+	}
+
+	err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel);
+	if (err) {
+		dev_err(&pdev->dev, "channel unspecified.\n");
+		goto err_put_ctrl;
+	}
+
+	if (channel > 5) {
+		dev_err(&pdev->dev, "invalid channel (%u) specified.\n",
+			channel);
+		goto err_put_ctrl;
+	}
+
+	pa->channel = channel;
+
+	platform_set_drvdata(pdev, ctrl);
+	raw_spin_lock_init(&pa->lock);
+
+	ctrl->cmd = pmic_arb_cmd;
+	ctrl->read_cmd = pmic_arb_read_cmd;
+	ctrl->write_cmd = pmic_arb_write_cmd;
+
+	err = spmi_controller_add(ctrl);
+	if (err)
+		goto err_put_ctrl;
+
+	dev_dbg(&ctrl->dev, "PMIC Arb Version 0x%x\n",
+		pmic_arb_base_read(pa, PMIC_ARB_VERSION));
+
+	return 0;
+
+err_put_ctrl:
+	spmi_controller_put(ctrl);
+	return err;
+}
+
+static int spmi_pmic_arb_remove(struct platform_device *pdev)
+{
+	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
+	spmi_controller_remove(ctrl);
+	spmi_controller_put(ctrl);
+	return 0;
+}
+
+static const struct of_device_id spmi_pmic_arb_match_table[] = {
+	{ .compatible = "qcom,spmi-pmic-arb", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);
+
+static struct platform_driver spmi_pmic_arb_driver = {
+	.probe		= spmi_pmic_arb_probe,
+	.remove		= spmi_pmic_arb_remove,
+	.driver		= {
+		.name	= "spmi_pmic_arb",
+		.owner	= THIS_MODULE,
+		.of_match_table = spmi_pmic_arb_match_table,
+	},
+};
+module_platform_driver(spmi_pmic_arb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:spmi_pmic_arb");
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

^ permalink raw reply related

* [PATCH v6 2/6] spmi: add generic SPMI controller binding documentation
From: Josh Cartwright @ 2014-02-12 19:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel
  Cc: linux-arm-msm, Gilad Avidov, Sagar Dharia, Michael Bohan,
	linux-arm-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Rob Landley, devicetree, linux-doc
In-Reply-To: <1392234267-10880-1-git-send-email-joshc@codeaurora.org>

Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
---
 Documentation/devicetree/bindings/spmi/spmi.txt | 41 +++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spmi/spmi.txt

diff --git a/Documentation/devicetree/bindings/spmi/spmi.txt b/Documentation/devicetree/bindings/spmi/spmi.txt
new file mode 100644
index 0000000..462a42f
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/spmi.txt
@@ -0,0 +1,41 @@
+System Power Management Interface (SPMI) Controller
+
+This document defines a generic set of bindings for use by SPMI controllers.  A
+controller is modelled in device tree as a node with zero or more child nodes,
+each representing a unique slave on the bus.
+
+Required properties:
+- #address-cells : must be set to 2
+- #size-cells : must be set to 0
+
+Child nodes:
+
+An SPMI controller node can contain zero or more child nodes representing slave
+devices on the bus.  Child 'reg' properties are specified as an address, type
+pair.  The address must be in the range 0-15 (4 bits).  The type must be one of
+SPMI_USID (0) or SPMI_GSID (1) for Unique Slave ID or Group Slave ID respectively.
+These are the identifiers "statically assigned by the system integrator", as
+per the SPMI spec.
+
+Each child node must have one and only one 'reg' entry of type SPMI_USID.
+
+#include <dt-bindings/spmi/spmi.h>
+
+	spmi@.. {
+		compatible = "...";
+		reg = <...>;
+
+		#address-cells = <2>;
+		#size-cells <0>;
+
+		child@0 {
+			compatible = "...";
+			reg = <0 SPMI_USID>;
+		};
+
+		child@7 {
+			compatible = "...";
+			reg = <7 SPMI_USID
+			       3 SPMI_GSID>;
+		};
+	};
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [PATCH v6 1/6] spmi: Linux driver framework for SPMI
From: Josh Cartwright @ 2014-02-12 19:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel
  Cc: linux-arm-msm, Gilad Avidov, Sagar Dharia, Michael Bohan,
	linux-arm-kernel, Kenneth Heitke, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
In-Reply-To: <1392234267-10880-1-git-send-email-joshc@codeaurora.org>

From: Kenneth Heitke <kheitke@codeaurora.org>

System Power Management Interface (SPMI) is a specification
developed by the MIPI (Mobile Industry Process Interface) Alliance
optimized for the real time control of Power Management ICs (PMIC).

SPMI is a two-wire serial interface that supports up to 4 master
devices and up to 16 logical slaves.

The framework supports message APIs, multiple busses (1 controller
per bus) and multiple clients/slave devices per controller.

Signed-off-by: Kenneth Heitke <kheitke@codeaurora.org>
Signed-off-by: Michael Bohan <mbohan@codeaurora.org>
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
---
 drivers/Kconfig                 |   2 +
 drivers/Makefile                |   1 +
 drivers/spmi/Kconfig            |   9 +
 drivers/spmi/Makefile           |   4 +
 drivers/spmi/spmi.c             | 609 ++++++++++++++++++++++++++++++++++++++++
 include/dt-bindings/spmi/spmi.h |  18 ++
 include/linux/mod_devicetable.h |   8 +
 include/linux/spmi.h            | 191 +++++++++++++
 8 files changed, 842 insertions(+)
 create mode 100644 drivers/spmi/Kconfig
 create mode 100644 drivers/spmi/Makefile
 create mode 100644 drivers/spmi/spmi.c
 create mode 100644 include/dt-bindings/spmi/spmi.h
 create mode 100644 include/linux/spmi.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index b3138fb..e0a4ae6 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
+source "drivers/spmi/Kconfig"
+
 source "drivers/hsi/Kconfig"
 
 source "drivers/pps/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 8e3b8b0..3d6de8b 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_ATA)		+= ata/
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
+obj-$(CONFIG_SPMI)		+= spmi/
 obj-y				+= hsi/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
new file mode 100644
index 0000000..1dbfee0
--- /dev/null
+++ b/drivers/spmi/Kconfig
@@ -0,0 +1,9 @@
+#
+# SPMI driver configuration
+#
+menuconfig SPMI
+	tristate "SPMI support"
+	help
+	  SPMI (System Power Management Interface) is a two-wire
+	  serial interface between baseband and application processors
+	  and Power Management Integrated Circuits (PMIC).
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
new file mode 100644
index 0000000..1de1acd
--- /dev/null
+++ b/drivers/spmi/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for kernel SPMI framework.
+#
+obj-$(CONFIG_SPMI)	+= spmi.o
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
new file mode 100644
index 0000000..6122c8f
--- /dev/null
+++ b/drivers/spmi/spmi.c
@@ -0,0 +1,609 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+
+#include <dt-bindings/spmi/spmi.h>
+
+static DEFINE_IDA(ctrl_ida);
+
+static void spmi_dev_release(struct device *dev)
+{
+	struct spmi_device *sdev = to_spmi_device(dev);
+	kfree(sdev);
+}
+
+static const struct device_type spmi_dev_type = {
+	.release	= spmi_dev_release,
+};
+
+static void spmi_ctrl_release(struct device *dev)
+{
+	struct spmi_controller *ctrl = to_spmi_controller(dev);
+	ida_simple_remove(&ctrl_ida, ctrl->nr);
+	kfree(ctrl);
+}
+
+static const struct device_type spmi_ctrl_type = {
+	.release	= spmi_ctrl_release,
+};
+
+#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);
+}
+
+static int spmi_runtime_resume(struct device *dev)
+{
+	struct spmi_device *sdev = to_spmi_device(dev);
+	int err;
+
+	err = spmi_command_wakeup(sdev);
+	if (err)
+		return err;
+
+	return pm_generic_runtime_resume(dev);
+}
+#endif
+
+static const struct dev_pm_ops spmi_pm_ops = {
+	SET_RUNTIME_PM_OPS(
+		spmi_runtime_suspend,
+		spmi_runtime_resume,
+		NULL
+	)
+};
+
+static int spmi_device_match(struct device *dev, struct device_driver *drv)
+{
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (drv->name)
+		return strncmp(dev_name(dev), drv->name,
+			       SPMI_NAME_SIZE) == 0;
+
+	return 0;
+}
+
+/**
+ * spmi_device_add() - add a device previously constructed via spmi_device_alloc()
+ * @sdev:	spmi_device to be added
+ */
+int spmi_device_add(struct spmi_device *sdev)
+{
+	struct spmi_controller *ctrl = sdev->ctrl;
+	int err;
+
+	dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, sdev->usid);
+
+	err = device_add(&sdev->dev);
+	if (err < 0) {
+		dev_err(&sdev->dev, "Can't add %s, status %d\n",
+			dev_name(&sdev->dev), err);
+		goto err_device_add;
+	}
+
+	dev_dbg(&sdev->dev, "device %s registered\n", dev_name(&sdev->dev));
+
+err_device_add:
+	return err;
+}
+EXPORT_SYMBOL_GPL(spmi_device_add);
+
+/**
+ * spmi_device_remove(): remove an SPMI device
+ * @sdev:	spmi_device to be removed
+ */
+void spmi_device_remove(struct spmi_device *sdev)
+{
+	device_unregister(&sdev->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_device_remove);
+
+static inline int
+spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
+{
+	if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type)
+		return -EINVAL;
+
+	return ctrl->cmd(ctrl, opcode, sid);
+}
+
+static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode,
+				u8 sid, u16 addr, u8 *buf, size_t len)
+{
+	if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type)
+		return -EINVAL;
+
+	return ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
+}
+
+static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode,
+				 u8 sid, u16 addr, const u8 *buf, size_t len)
+{
+	if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type)
+		return -EINVAL;
+
+	return ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
+}
+
+/**
+ * spmi_register_read() - register read
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (5-bit address).
+ * @buf:	buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf)
+{
+	/* 5-bit register address */
+	if (addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_read_cmd(sdev->ctrl, SPMI_CMD_READ, sdev->usid, addr,
+			     buf, 1);
+}
+EXPORT_SYMBOL_GPL(spmi_register_read);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (8-bit address).
+ * @buf:	buffer to be populated with data from the Slave.
+ * @len:	the request number of bytes to read (up to 16 bytes).
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf,
+			   size_t len)
+{
+	/* 8-bit register address, up to 16 bytes */
+	if (len == 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READ, sdev->usid, addr,
+			     buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_read);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (16-bit address).
+ * @buf:	buffer to be populated with data from the Slave.
+ * @len:	the request number of bytes to read (up to 8 bytes).
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf,
+			    size_t len)
+{
+	/* 16-bit register address, up to 8 bytes */
+	if (len == 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READL, sdev->usid, addr,
+			     buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_readl);
+
+/**
+ * spmi_register_write() - register write
+ * @sdev:	SPMI device
+ * @addr:	slave register address (5-bit address).
+ * @data:	buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data)
+{
+	/* 5-bit register address */
+	if (addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_WRITE, sdev->usid, addr,
+			      &data, 1);
+}
+EXPORT_SYMBOL_GPL(spmi_register_write);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @sdev:	SPMI device.
+ * @data:	the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+int spmi_register_zero_write(struct spmi_device *sdev, u8 data)
+{
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_ZERO_WRITE, sdev->usid, 0,
+			      &data, 1);
+}
+EXPORT_SYMBOL_GPL(spmi_register_zero_write);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (8-bit address).
+ * @buf:	buffer containing the data to be transferred to the Slave.
+ * @len:	the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, const u8 *buf,
+			    size_t len)
+{
+	/* 8-bit register address, up to 16 bytes */
+	if (len == 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITE, sdev->usid, addr,
+			      buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_write);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @sdev:	SPMI device.
+ * @addr:	slave register address (16-bit address).
+ * @buf:	buffer containing the data to be transferred to the Slave.
+ * @len:	the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, const u8 *buf,
+			     size_t len)
+{
+	/* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+	if (len == 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITEL, sdev->usid,
+			      addr, buf, len);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_writel);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @sdev:	SPMI device.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ */
+int spmi_command_reset(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_RESET, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_reset);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified SPMI device
+ * @sdev:	SPMI device.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ */
+int spmi_command_sleep(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_SLEEP, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_sleep);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified SPMI device
+ * @sdev:	SPMI device.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ */
+int spmi_command_wakeup(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_WAKEUP, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_wakeup);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified SPMI device
+ * @sdev:	SPMI device.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ */
+int spmi_command_shutdown(struct spmi_device *sdev)
+{
+	return spmi_cmd(sdev->ctrl, SPMI_CMD_SHUTDOWN, sdev->usid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_shutdown);
+
+static int spmi_drv_probe(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+	struct spmi_device *sdev = to_spmi_device(dev);
+	int err;
+
+	/* Ensure the slave is in ACTIVE state */
+	err = spmi_command_wakeup(sdev);
+	if (err)
+		goto fail_wakeup;
+
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	err = sdrv->probe(sdev);
+	if (err)
+		goto fail_probe;
+
+	return 0;
+
+fail_probe:
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+fail_wakeup:
+	return err;
+}
+
+static int spmi_drv_remove(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	pm_runtime_get_sync(dev);
+	sdrv->remove(to_spmi_device(dev));
+	pm_runtime_put_noidle(dev);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+	return 0;
+}
+
+static struct bus_type spmi_bus_type = {
+	.name		= "spmi",
+	.match		= spmi_device_match,
+	.pm		= &spmi_pm_ops,
+	.probe		= spmi_drv_probe,
+	.remove		= spmi_drv_remove,
+};
+
+/**
+ * spmi_controller_alloc() - Allocate a new SPMI device
+ * @ctrl:	associated controller
+ *
+ * Caller is responsible for either calling spmi_device_add() to add the
+ * newly allocated controller, or calling spmi_device_put() to discard it.
+ */
+struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl)
+{
+	struct spmi_device *sdev;
+
+	sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+	if (!sdev)
+		return NULL;
+
+	sdev->ctrl = ctrl;
+	device_initialize(&sdev->dev);
+	sdev->dev.parent = &ctrl->dev;
+	sdev->dev.bus = &spmi_bus_type;
+	sdev->dev.type = &spmi_dev_type;
+	return sdev;
+}
+EXPORT_SYMBOL_GPL(spmi_device_alloc);
+
+/**
+ * spmi_controller_alloc() - Allocate a new SPMI controller
+ * @parent:	parent device
+ * @size:	size of private data
+ *
+ * Caller is responsible for either calling spmi_controller_add() to add the
+ * newly allocated controller, or calling spmi_controller_put() to discard it.
+ * The allocated private data region may be accessed via
+ * spmi_controller_get_drvdata()
+ */
+struct spmi_controller *spmi_controller_alloc(struct device *parent,
+					      size_t size)
+{
+	struct spmi_controller *ctrl;
+	int id;
+
+	if (WARN_ON(!parent))
+		return NULL;
+
+	ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL);
+	if (!ctrl)
+		return NULL;
+
+	device_initialize(&ctrl->dev);
+	ctrl->dev.type = &spmi_ctrl_type;
+	ctrl->dev.bus = &spmi_bus_type;
+	ctrl->dev.parent = parent;
+	ctrl->dev.of_node = parent->of_node;
+	spmi_controller_set_drvdata(ctrl, &ctrl[1]);
+
+	id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		dev_err(parent,
+			"unable to allocate SPMI controller identifier.\n");
+		spmi_controller_put(ctrl);
+		return NULL;
+	}
+
+	ctrl->nr = id;
+	dev_set_name(&ctrl->dev, "spmi-%d", id);
+
+	dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id);
+	return ctrl;
+}
+EXPORT_SYMBOL_GPL(spmi_controller_alloc);
+
+static void of_spmi_register_devices(struct spmi_controller *ctrl)
+{
+	struct device_node *node;
+	int err;
+
+	if (!ctrl->dev.of_node)
+		return;
+
+	for_each_available_child_of_node(ctrl->dev.of_node, node) {
+		struct spmi_device *sdev;
+		u32 reg[2];
+
+		dev_dbg(&ctrl->dev, "adding child %s\n", node->full_name);
+
+		err = of_property_read_u32_array(node, "reg", reg, 2);
+		if (err) {
+			dev_err(&ctrl->dev,
+				"node %s err (%d) does not have 'reg' property\n",
+				node->full_name, err);
+			continue;
+		}
+
+		if (reg[1] != SPMI_USID) {
+			dev_err(&ctrl->dev,
+				"node %s contains unsupported 'reg' entry\n",
+				node->full_name);
+			continue;
+		}
+
+		if (reg[0] >= SPMI_MAX_SLAVE_ID) {
+			dev_err(&ctrl->dev,
+				"invalid usid on node %s\n",
+				node->full_name);
+			continue;
+		}
+
+		dev_dbg(&ctrl->dev, "read usid %02x\n", reg[0]);
+
+		sdev = spmi_device_alloc(ctrl);
+		if (!sdev)
+			continue;
+
+		sdev->dev.of_node = node;
+		sdev->usid = (u8) reg[0];
+
+		err = spmi_device_add(sdev);
+		if (err) {
+			dev_err(&sdev->dev,
+				"failure adding device. status %d\n", err);
+			spmi_device_put(sdev);
+		}
+	}
+}
+
+/**
+ * spmi_controller_add() - Add an SPMI controller
+ * @ctrl:	controller to be registered.
+ *
+ * Register a controller previously allocated via spmi_controller_alloc() with
+ * the SPMI core.
+ */
+int spmi_controller_add(struct spmi_controller *ctrl)
+{
+	int ret;
+
+	/* Can't register until after driver model init */
+	if (WARN_ON(!spmi_bus_type.p))
+		return -EAGAIN;
+
+	ret = device_add(&ctrl->dev);
+	if (ret)
+		return ret;
+
+	if (IS_ENABLED(CONFIG_OF))
+		of_spmi_register_devices(ctrl);
+
+	dev_dbg(&ctrl->dev, "spmi-%d registered: dev:%p\n",
+		ctrl->nr, &ctrl->dev);
+
+	return 0;
+};
+EXPORT_SYMBOL_GPL(spmi_controller_add);
+
+/* Remove a device associated with a controller */
+static int spmi_ctrl_remove_device(struct device *dev, void *data)
+{
+	struct spmi_device *spmidev = to_spmi_device(dev);
+	if (dev->type == &spmi_dev_type)
+		spmi_device_remove(spmidev);
+	return 0;
+}
+
+/**
+ * spmi_controller_remove(): remove an SPMI controller
+ * @ctrl:	controller to remove
+ *
+ * Remove a SPMI controller.  Caller is responsible for calling
+ * spmi_controller_put() to discard the allocated controller.
+ */
+void spmi_controller_remove(struct spmi_controller *ctrl)
+{
+	int dummy;
+
+	if (!ctrl)
+		return;
+
+	dummy = device_for_each_child(&ctrl->dev, NULL,
+				      spmi_ctrl_remove_device);
+	device_del(&ctrl->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_controller_remove);
+
+/**
+ * spmi_driver_register() - Register client driver with SPMI core
+ * @sdrv:	client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is typically called from the driver's module-init function.
+ */
+int spmi_driver_register(struct spmi_driver *sdrv)
+{
+	sdrv->driver.bus = &spmi_bus_type;
+	return driver_register(&sdrv->driver);
+}
+EXPORT_SYMBOL_GPL(spmi_driver_register);
+
+static void __exit spmi_exit(void)
+{
+	bus_unregister(&spmi_bus_type);
+}
+module_exit(spmi_exit);
+
+static int __init spmi_init(void)
+{
+	return bus_register(&spmi_bus_type);
+}
+postcore_initcall(spmi_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SPMI module");
+MODULE_ALIAS("platform:spmi");
diff --git a/include/dt-bindings/spmi/spmi.h b/include/dt-bindings/spmi/spmi.h
new file mode 100644
index 0000000..d11e1e5
--- /dev/null
+++ b/include/dt-bindings/spmi/spmi.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DT_BINDINGS_SPMI_H
+#define __DT_BINDINGS_SPMI_H
+
+#define SPMI_USID	0
+#define SPMI_GSID	1
+
+#endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 45e9214..677e474 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -432,6 +432,14 @@ struct spi_device_id {
 	kernel_ulong_t driver_data;	/* Data private to the driver */
 };
 
+#define SPMI_NAME_SIZE	32
+#define SPMI_MODULE_PREFIX "spmi:"
+
+struct spmi_device_id {
+	char name[SPMI_NAME_SIZE];
+	kernel_ulong_t driver_data;	/* Data private to the driver */
+};
+
 /* dmi */
 enum dmi_field {
 	DMI_NONE,
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
new file mode 100644
index 0000000..91f5eab
--- /dev/null
+++ b/include/linux/spmi.h
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _LINUX_SPMI_H
+#define _LINUX_SPMI_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/* Maximum slave identifier */
+#define SPMI_MAX_SLAVE_ID		16
+
+/* SPMI Commands */
+#define SPMI_CMD_EXT_WRITE		0x00
+#define SPMI_CMD_RESET			0x10
+#define SPMI_CMD_SLEEP			0x11
+#define SPMI_CMD_SHUTDOWN		0x12
+#define SPMI_CMD_WAKEUP			0x13
+#define SPMI_CMD_AUTHENTICATE		0x14
+#define SPMI_CMD_MSTR_READ		0x15
+#define SPMI_CMD_MSTR_WRITE		0x16
+#define SPMI_CMD_TRANSFER_BUS_OWNERSHIP	0x1A
+#define SPMI_CMD_DDB_MASTER_READ	0x1B
+#define SPMI_CMD_DDB_SLAVE_READ		0x1C
+#define SPMI_CMD_EXT_READ		0x20
+#define SPMI_CMD_EXT_WRITEL		0x30
+#define SPMI_CMD_EXT_READL		0x38
+#define SPMI_CMD_WRITE			0x40
+#define SPMI_CMD_READ			0x60
+#define SPMI_CMD_ZERO_WRITE		0x80
+
+/**
+ * struct spmi_device - Basic representation of an SPMI device
+ * @dev:	Driver model representation of the device.
+ * @ctrl:	SPMI controller managing the bus hosting this device.
+ * @usid:	This devices' Unique Slave IDentifier.
+ */
+struct spmi_device {
+	struct device		dev;
+	struct spmi_controller	*ctrl;
+	u8			usid;
+};
+
+static inline struct spmi_device *to_spmi_device(struct device *d)
+{
+	return container_of(d, struct spmi_device, dev);
+}
+
+static inline void *spmi_device_get_drvdata(const struct spmi_device *sdev)
+{
+	return dev_get_drvdata(&sdev->dev);
+}
+
+static inline void spmi_device_set_drvdata(struct spmi_device *sdev, void *data)
+{
+	dev_set_drvdata(&sdev->dev, data);
+}
+
+struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl);
+
+static inline void spmi_device_put(struct spmi_device *sdev)
+{
+	if (sdev)
+		put_device(&sdev->dev);
+}
+
+int spmi_device_add(struct spmi_device *sdev);
+
+void spmi_device_remove(struct spmi_device *sdev);
+
+/**
+ * struct spmi_controller - interface to the SPMI master controller
+ * @dev:	Driver model representation of the device.
+ * @nr:		board-specific number identifier for this controller/bus
+ * @cmd:	sends a non-data command sequence on the SPMI bus.
+ * @read_cmd:	sends a register read command sequence on the SPMI bus.
+ * @write_cmd:	sends a register write command sequence on the SPMI bus.
+ */
+struct spmi_controller {
+	struct device		dev;
+	unsigned int		nr;
+	int	(*cmd)(struct spmi_controller *ctrl, u8 opcode, u8 sid);
+	int	(*read_cmd)(struct spmi_controller *ctrl, u8 opcode,
+			    u8 sid, u16 addr, u8 *buf, size_t len);
+	int	(*write_cmd)(struct spmi_controller *ctrl, u8 opcode,
+			     u8 sid, u16 addr, const u8 *buf, size_t len);
+};
+
+static inline struct spmi_controller *to_spmi_controller(struct device *d)
+{
+	return container_of(d, struct spmi_controller, dev);
+}
+
+static inline
+void *spmi_controller_get_drvdata(const struct spmi_controller *ctrl)
+{
+	return dev_get_drvdata(&ctrl->dev);
+}
+
+static inline void spmi_controller_set_drvdata(struct spmi_controller *ctrl,
+					       void *data)
+{
+	dev_set_drvdata(&ctrl->dev, data);
+}
+
+struct spmi_controller *spmi_controller_alloc(struct device *parent,
+					      size_t size);
+
+/**
+ * spmi_controller_put() - decrement controller refcount
+ * @ctrl	SPMI controller.
+ */
+static inline void spmi_controller_put(struct spmi_controller *ctrl)
+{
+	if (ctrl)
+		put_device(&ctrl->dev);
+}
+
+int spmi_controller_add(struct spmi_controller *ctrl);
+void spmi_controller_remove(struct spmi_controller *ctrl);
+
+/**
+ * struct spmi_driver - SPMI slave device driver
+ * @driver:	SPMI device drivers should initialize name and owner field of
+ *		this structure.
+ * @probe:	binds this driver to a SPMI device.
+ * @remove:	unbinds this driver from the SPMI device.
+ * @shutdown:	standard shutdown callback used during powerdown/halt.
+ * @suspend:	standard suspend callback used during system suspend.
+ * @resume:	standard resume callback used during system resume.
+ *
+ * If PM runtime support is desired for a slave, a device driver can call
+ * pm_runtime_put() from their probe() routine (and a balancing
+ * pm_runtime_get() in remove()).  PM runtime support for a slave is
+ * implemented by issuing a SLEEP command to the slave on runtime_suspend(),
+ * transitioning the slave into the SLEEP state.  On runtime_resume(), a WAKEUP
+ * command is sent to the slave to bring it back to ACTIVE.
+ */
+struct spmi_driver {
+	struct device_driver driver;
+	int	(*probe)(struct spmi_device *sdev);
+	void	(*remove)(struct spmi_device *sdev);
+};
+
+static inline struct spmi_driver *to_spmi_driver(struct device_driver *d)
+{
+	return container_of(d, struct spmi_driver, driver);
+}
+
+int spmi_driver_register(struct spmi_driver *sdrv);
+
+/**
+ * spmi_driver_unregister() - unregister an SPMI client driver
+ * @sdrv:	the driver to unregister
+ */
+static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
+{
+	if (sdrv)
+		driver_unregister(&sdrv->driver);
+}
+
+#define module_spmi_driver(__spmi_driver) \
+	module_driver(__spmi_driver, spmi_driver_register, \
+			spmi_driver_unregister)
+
+int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf);
+int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf,
+			   size_t len);
+int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf,
+			    size_t len);
+int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data);
+int spmi_register_zero_write(struct spmi_device *sdev, u8 data);
+int spmi_ext_register_write(struct spmi_device *sdev, u8 addr,
+			    const u8 *buf, size_t len);
+int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr,
+			     const u8 *buf, size_t len);
+int spmi_command_reset(struct spmi_device *sdev);
+int spmi_command_sleep(struct spmi_device *sdev);
+int spmi_command_wakeup(struct spmi_device *sdev);
+int spmi_command_shutdown(struct spmi_device *sdev);
+
+#endif
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Jason Cooper @ 2014-02-12 19:43 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, devicetree, Laura Abbott, keescook,
	linux-kernel, Rob Herring, Kumar Gala, Grant Likely
In-Reply-To: <1882539.R1gpoLLYks@wuerfel>

On Wed, Feb 12, 2014 at 08:12:23PM +0100, Arnd Bergmann wrote:
> On Wednesday 12 February 2014 13:45:21 Jason Cooper wrote:
> > On Wed, Feb 12, 2014 at 07:17:41PM +0100, Arnd Bergmann wrote:
> > > On Wednesday 12 February 2014 12:45:54 Jason Cooper wrote:
> > > > I brought this up at last weeks devicetree irc meeting.  My goal is to
> > > > provide early randomness for kaslr on ARM.  Currently, my idea is modify
> > > > the init script to save an additional random seed from /dev/urandom to
> > > > /boot/random-seed.
> > > > 
> > > > The bootloader would then load this file into ram, and pass the
> > > > address/size to the kernel either via dt, or commandline.  kaslr (run in
> > > > the decompressor) would consume some of this randomness, and then
> > > > random.c would consume the rest in a non-crediting initialization.
> > > 
> > > I like the idea, but wouldn't it be easier to pass actual random data
> > > using DT, rather than the address/size?
> > 
> > I thought about that at first, but that requires either that the
> > bootloader be upgraded to insert the data, or that userspace is
> > modifying the dtb at least twice per boot.
> > 
> > I chose address/size to facilitate modifying existing/fielded devices.
> > The user could modify the dtb once, and modify the bootloader
> > environment to load X amount to Y address.  As a fallback, it could be
> > expressed on the commandline for non-DT bootloaders.
> 
> Ah, so you are interested in boot loaders that can be scripted to do
> what you had in mind but cannot be scripted to add or modify a DT
> property. I hadn't considered that, but you are probably right that
> this is at least 90% of the systems you'd find in the wild today.

Yes, exactly.

> Thinking this a bit further, I wonder if (at least upstream) u-boot
> has a way to modify DT properties in a scripted way that would allow
> the direct property. It sounds like a generally useful feature not
> just for randomness, so if that doesn't already work, maybe someone
> can implement it. In the simplest case, you'd only need to find the
> address of an existing property in the dtb and load a file to
> that location.

Like fdtget from dtc?  The thing is, this address would only need to be
setup once per board.  Hypothetically, debian's flash-kernel could set
the address in the dtb, then set it in the u-boot environment.  From
then on, only the normal initscript writing to random-seed would be
needed.

thx,

Jason.

^ permalink raw reply

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Arnd Bergmann @ 2014-02-12 19:12 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Jason Cooper, devicetree, Laura Abbott, keescook, linux-kernel,
	Rob Herring, Kumar Gala, Grant Likely
In-Reply-To: <20140212184521.GO27395@titan.lakedaemon.net>

On Wednesday 12 February 2014 13:45:21 Jason Cooper wrote:
> On Wed, Feb 12, 2014 at 07:17:41PM +0100, Arnd Bergmann wrote:
> > On Wednesday 12 February 2014 12:45:54 Jason Cooper wrote:
> > > I brought this up at last weeks devicetree irc meeting.  My goal is to
> > > provide early randomness for kaslr on ARM.  Currently, my idea is modify
> > > the init script to save an additional random seed from /dev/urandom to
> > > /boot/random-seed.
> > > 
> > > The bootloader would then load this file into ram, and pass the
> > > address/size to the kernel either via dt, or commandline.  kaslr (run in
> > > the decompressor) would consume some of this randomness, and then
> > > random.c would consume the rest in a non-crediting initialization.
> > 
> > I like the idea, but wouldn't it be easier to pass actual random data
> > using DT, rather than the address/size?
> 
> I thought about that at first, but that requires either that the
> bootloader be upgraded to insert the data, or that userspace is
> modifying the dtb at least twice per boot.
> 
> I chose address/size to facilitate modifying existing/fielded devices.
> The user could modify the dtb once, and modify the bootloader
> environment to load X amount to Y address.  As a fallback, it could be
> expressed on the commandline for non-DT bootloaders.

Ah, so you are interested in boot loaders that can be scripted to do
what you had in mind but cannot be scripted to add or modify a DT
property. I hadn't considered that, but you are probably right that
this is at least 90% of the systems you'd find in the wild today.

Thinking this a bit further, I wonder if (at least upstream) u-boot
has a way to modify DT properties in a scripted way that would allow
the direct property. It sounds like a generally useful feature not
just for randomness, so if that doesn't already work, maybe someone
can implement it. In the simplest case, you'd only need to find the
address of an existing property in the dtb and load a file to
that location.

	Arnd

^ permalink raw reply

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Jason Cooper @ 2014-02-12 18:51 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Laura Abbott,
	keescook-F7+t8E8rja9g9hUCZPvPmw, Arnd Bergmann,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Kumar Gala,
	Grant Likely, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20140212182000.GJ5554-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>

On Wed, Feb 12, 2014 at 11:20:00AM -0700, Jason Gunthorpe wrote:
> On Wed, Feb 12, 2014 at 12:45:54PM -0500, Jason Cooper wrote:
> 
> > The bootloader would then load this file into ram, and pass the
> > address/size to the kernel either via dt, or commandline.  kaslr (run in
> > the decompressor) would consume some of this randomness, and then
> > random.c would consume the rest in a non-crediting initialization.
> 
> Sure is a neat idea, but I think in general it would probably be smart
> to include the entire FDT blob in the early random pool, that way you
> get MACs and other machine unique data too.

Sure.

> From there it is a small step to encourage bootloaders to include
> boot-time-variable data in the DT like like 'boot time of day', 'cycle
> counter', 'random blob', etc.

I like it.

> Then you just need the bootloader to dump the random-seed file into a
> DT property.

Yes, see my response to Arnd re the binding.  I'm also interested in
making it easier for devices already in the field.  iow, without
upgrading the bootloader.

> Or have the bootloader fetch randomness from any HWRNG it has a driver
> for. (eg a TPM)

Depends on who you're protecting against.  I'd prefer to have that
called out as a separate blob in the DT so the kernel could decide
whether to trust it explicitly, or mix it like random.c already does
with RDRAND.

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: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Jason Cooper @ 2014-02-12 18:45 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Laura Abbott,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Kumar Gala,
	Grant Likely, keescook-F7+t8E8rja9g9hUCZPvPmw
In-Reply-To: <1571508.yGAAZ8TNH0@wuerfel>

On Wed, Feb 12, 2014 at 07:17:41PM +0100, Arnd Bergmann wrote:
> On Wednesday 12 February 2014 12:45:54 Jason Cooper wrote:
> > I brought this up at last weeks devicetree irc meeting.  My goal is to
> > provide early randomness for kaslr on ARM.  Currently, my idea is modify
> > the init script to save an additional random seed from /dev/urandom to
> > /boot/random-seed.
> > 
> > The bootloader would then load this file into ram, and pass the
> > address/size to the kernel either via dt, or commandline.  kaslr (run in
> > the decompressor) would consume some of this randomness, and then
> > random.c would consume the rest in a non-crediting initialization.
> 
> I like the idea, but wouldn't it be easier to pass actual random data
> using DT, rather than the address/size?

I thought about that at first, but that requires either that the
bootloader be upgraded to insert the data, or that userspace is
modifying the dtb at least twice per boot.

I chose address/size to facilitate modifying existing/fielded devices.
The user could modify the dtb once, and modify the bootloader
environment to load X amount to Y address.  As a fallback, it could be
expressed on the commandline for non-DT bootloaders.

So I'm not against the idea of random-seed,{start,size} and a
random-seed,blob.  I would just like the former to be available for
folks interested in the capability on existing hardware w/o upgrading
the bootloader.

> That way we could even use the same DT binding for passing randomness
> from the bootloader, whereever it may have found that.

The problem lies in defining "whereever" ;)

> If the bootloader has internet connectivity, it could even mix in
> some data from http://www.random.org/cgi-bin/randbyte?nbytes=256&format=f
> ;-)

Gah!  Arnd, you just about gave me a heart attack.  And http no less.

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] export of_irq_count
From: delicious quinoa @ 2014-02-12 18:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Rob Herring, Grant Likely,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Dinh Nguyen,
	Yves Vandervennet, Alan Tull
In-Reply-To: <CAL_JsqLT=w5wDnFBcQdeF5KgpJK76xJhH=ZYJy24CEeV2uQ2aQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Wed, Feb 12, 2014 at 12:32 PM, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Wed, Feb 12, 2014 at 11:34 AM, delicious quinoa
> <delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> From: Alan Tull <atull-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>
>>
>> export of_irq_count so it can be used in drivers that are built
>> as modules.
>
> What drivers? Drivers generally should be using resources rather than
> this function directly.

It's for the DesignWare GPIO driver I've been upstreaming.  The
DesignWare IP can be configured to be one irq for all the gpios or one
irq per gpio.  I want to support both cases.  So I need to know how
many irqs are specified in the device tree.

Alan
aka
delicious quinoa
--
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/3] mmc: add support for power-on sequencing through DT
From: Mark Brown @ 2014-02-12 18:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Ulf Hansson, mark.rutland, devicetree, Russell King - ARM Linux,
	Pawel Moll, Ian Campbell, Tomasz Figa, linux-mmc, Tomasz Figa,
	Chris Ball, robh+dt, Kumar Gala, Olof Johansson, Fabio Estevam,
	Sascha Hauer, linux-arm-kernel@lists.infradead.org
In-Reply-To: <201401281148.10670.arnd@arndb.de>

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

On Tue, Jan 28, 2014 at 11:48:10AM +0100, Arnd Bergmann wrote:

> I think there is another option, which does have its own pros and cons:
> We could move all the power handling back into the sdio function driver
> if we allow a secondary detection path using DT rather than the probing
> of the SDIO bus. Essentially you'd have to list the class/vendor/device
> ID for each function that cannot be autodetected in DT, and have the
> SDIO core pretend that it found the device just by looking at the
> device nodes, and register the struct sdio_func so it can be bound to
> the driver. The driver then does all the power handling in a device
> specific way. At some point the hardware gets registered at the 
> mmc host, and the sdio core connects the bus state to the already present
> sdio_func, possibly notifying the function driver that it has become
> usable.

> Obviously, this can only work for CAP_NONREMOVABLE devices, but those
> are exactly the ones we are worried about here. The advantage is that
> the power sequencing for a particular device can then be in device
> specific code and can have an arbitrarily complex in the driver without
> needing the mmc code to handle all possible corner cases.

I think this is going to be the most generic solution overall, it's
going to work with other buses and it's going to allow the device to
fully power itself off while running (I don't know if it's useful for SD
but that's definitely common with some other buses).

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [RFC/PATCH 0/3] Add devicetree scanning for randomness
From: Jason Cooper @ 2014-02-12 18:32 UTC (permalink / raw)
  To: Olof Johansson
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Laura Abbott,
	Kees Cook, Arnd Bergmann,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
	Kumar Gala, Grant Likely,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <CAOesGMgNkdxW4znmns10-DPc4+OTWJLyx2fcJGTgdND6pp0zUQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Wed, Feb 12, 2014 at 10:13:59AM -0800, Olof Johansson wrote:
> On Wed, Feb 12, 2014 at 9:45 AM, Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org> wrote:
> 
> > I brought this up at last weeks devicetree irc meeting.  My goal is to
> > provide early randomness for kaslr on ARM.  Currently, my idea is modify
> > the init script to save an additional random seed from /dev/urandom to
> > /boot/random-seed.
> >
> > The bootloader would then load this file into ram, and pass the
> > address/size to the kernel either via dt, or commandline.  kaslr (run in
> > the decompressor) would consume some of this randomness, and then
> > random.c would consume the rest in a non-crediting initialization.
> >
> > While not ideal, it works in absence of an HRNG, and is no worse than
> > the current situation of storing the seed in /var/lib/misc/random-seed.
> > It also doesn't require modification of the bootloaders.  Just an
> > updated kernel, and update the bootloader environment to load the
> > seed.
> 
> Hmm. There are some drawbacks with this -- it assumes you can "just
> update the bootloader environment" which in general isn't easy to do.

true, the scope of my experience is consumer grade NASs, routers and
APs.  At the very least, it's much easier than upgrading the bootloader.

Also, my pov is as a hobbyist modifying devices post-sale.  The idea is
something I could add to my existing boxes without having to upgrade the
bootloaders.

> Also, you can't assume that /boot is writable or exists on all
> embedded systems.

In systems missing this capability, they often have the ability to
update the kernel.  All that's needed is one block of flash.  Current
random-seed size is 512 bytes.  I'm not saying it's easy or desirable.
But for folks who feel it's necessary to have kaslr on embedded devices,
it would facilitate better random numbers.  "Better" meaning much harder
for an attacker to guess.

> In general, taking both runtime and system-dependend data and using
> that to see entropy is a good idea.

Of course, I wasn't arguing for one or the other.  As you said later, in
situations where you can't feed in a seed file, MAC addresses and serial
numbers are better than nothing.

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] export of_irq_count
From: Rob Herring @ 2014-02-12 18:32 UTC (permalink / raw)
  To: delicious quinoa
  Cc: Rob Herring, Grant Likely,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Dinh Nguyen,
	Yves Vandervennet, Alan Tull
In-Reply-To: <1392226444-30507-1-git-send-email-delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Wed, Feb 12, 2014 at 11:34 AM, delicious quinoa
<delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> From: Alan Tull <atull-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>
>
> export of_irq_count so it can be used in drivers that are built
> as modules.

What drivers? Drivers generally should be using resources rather than
this function directly.

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

^ permalink raw reply

* Re: [RFC 1/6] mailbox: add core framework
From: Courtney Cavin @ 2014-02-12 18:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Rob Herring, Josh Cartwright, s-anna@ti.com, Rob Herring,
	Wysocki, Rafael J, Mark Langsdorf, Tony Lindgren,
	omar.ramirez@copitl.com, Greg Kroah-Hartman, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Rob Landley,
	linux-doc@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <1765844.1kjKsO2Rzo@wuerfel>

On Tue, Feb 11, 2014 at 09:35:01AM +0100, Arnd Bergmann wrote:
> On Monday 10 February 2014 16:23:48 Courtney Cavin wrote:
> 
> > While I'm not sure the dislike of notifiers entirely justifies not using
> > them here, where they seem to make sense, I can understand that they
> > might not fully implement what we need to expose.
> 
> I think we need to look at a few more examples of things that people
> want to with the framework to come up with a good interface. It's
> possible that we end up with multiple alternative notification
> methods, but it would be good to come up with one that works well
> for everyone.
> 
> > Regarding handlers running in IRQ context: currently the API is designed
> > to do just that.  From the use-cases I've found, most message handlers
> > simply queue something to happen at a later point.  This is logical, as
> > the callback will be async, so you'll need to swap contexts or add locks
> > in your consumer anyway.
> 
> Right. You may also have some handlers that need to run with extreme
> latency constraints, so we need at least the option of getting the
> callback from hardirq context, or possibly from softirq/tasklet
> as in the dmaengine case.
> 
> > The dma engine is large and confused, so I'm not sure entirely which
> > part you are refering to.  I've looked at having async completion going
> > both ways, but what I see every time is code complication in both the
> > adapter and in the consumers in the simple use-case.  It doesn't really
> > make sense to make an API which makes things so generic that it becomes
> > hard to use.  What I tried to follow here when designing the API was
> > what I saw in the actual implementations, not what was future-proof:
> > 	- Message receive callbacks may be called from IRQ context
> > 	- Message send implementations may sleep
> 
> I can imagine cases where you want to send messages from softirq
> context, or from the same context in which you received the incoming
> mail, so it would be good to have the API flexible enough to deal
> with that. As a first step, always allowing send to sleep seems
> fine. Alternatively, we could have a 'sync' flag in the send
> API, to choose between "arrange this message to be sent out as
> soon as possible, but don't sleep" and "send this message and
> make sure it has arrived at the other end" as you do now.

Although I'm not sure there's currently a requirement for this, I can see that
this could be needed in the future.

> > What I can do is try to alleviate implementation efforts of future
> > requirements--as honestly, we can't really say exactly what they are--by
> > turning the messages into structs themselves, so at a later point flags,
> > ack callbacks, and rainbows can be added.  I can then stop using
> > notifiers, and re-invent that functionality with a mbox_ prefix.
> 
> I don't think there is a point in reimplementing notifiers under a
> different name. The question is rather how we want to deal with
> the 'multiple listener' case. If this case is the exception rather
> than the rule, I'd prefer making the callback API handle only
> single listeners and adding higher-level abstractions for the
> cases where we do need multiple listeners, but it really depends
> on what people need.

I wasn't actually planning on directly ripping-off notifiers under a new name.
Rather, as switching to message structs is probably a good idea anyway, I don't
think the notifier API properly represents that,... the void pointer is a bit
vague.  It could be that it would turn out as a wrapper around notifiers.  As
you said though, I do think this is the exception, so I'm fine with the single
callback idea, as long as Rob and Suman agree that this will be suitable for
their use-cases.

Then again, I think that the context management stuff is the exception as well,
and I think that can/should also be handled in a higher level.  Regardless, I
went ahead and drafted the async flags idea out anyway, so here's some
pseudo-code.  I also tried to shoe-horn in 'peek', and you can see how that
turns out.  Let me know if this is something like what you had in mind.

enum {
	MBOX_ASYNC	= BIT(0),
};

struct mbox_adapter_ops {
	...
	int (*put_message)(struct mbox_adapter *, struct mbox_channel *,
			const struct mbox_message *msg)
	int (*peek_message)(struct mbox_adapter *, struct mbox_channel *,
			struct mbox_message *msg)
};

struct mbox;

#define MBOX_FIFO_SIZE PAGE_SZ /* or not? */

struct mbox_channel {
	...
	unsigned long flags; /* MBOX_ASYNC, for now */
	struct mbox *consumer;
	struct kfifo_rec_ptr_1 rx_fifo;
	/**
	 * probably should be allocated only if user needs to call
	 * mbox_put_message with MBOX_ASYNC, instead of statically.
	 */
	STRUCT_KFIFO_REC_1(MBOX_FIFO_SIZE) tx_fifo;
	struct work_struct rx_work;
	struct work_struct tx_work;
}

struct mbox {
	struct mbox_channel *chan;
	struct mbox_adapter *adapter;
	void (*cb)(void *, struct mbox *, const struct mbox_message *);
	void *priv;
};

struct mbox_message {
	void *data;
	unsigned int len;
};

static void rx_work(struct work_struct *work)
{
	struct mbox_channel *chan;
	struct mbox_message msg;

	chan = container_of(work, struct mbox_channel, rx_work);
	msg.len = kfifo_out(&chan->rx_fifo, msg.data);
	chan->consumer->cb(chan->consumer, &msg);
}

/* called from adapter, typically in a IRQ handler */
int mbox_channel_notify(struct mbox_channel *chan,
		const struct mbox_message *msg)
{
	if (chan->flags & MBOX_ASYNC) {
		kfifo_in(&chan->rx_fifo, msg->data, msg->len);
		schedule_work(&chan->rx_work);
		return 0;
	}

	/*
	 * consumer may not sleep here, as they did not specify this
	 * requirement in channel flags when requesting
	 */
	return chan->consumer->cb(chan->consumer->priv, chan->consumer, msg);
}

static void tx_work(struct work_struct *work)
{
	struct mbox_channel *chan;
	struct mbox_message msg;
	char buf[PAGE_SZ]; /* should max size be specified by the adapter? */

	chan = container_of(work, struct mbox_channel, tx_work);
	msg.len = kfifo_out(&chan->tx_fifo, buf, sizeof(buf));
	msg.data = buf;

	mutex_lock(&chan->adapter->lock);
	chan->adapter->ops->put_message(chan->adapter, chan, &msg);
	mutex_unlock(&chan->adapter->lock);
}

/* called from consumer */
int mbox_put_message(struct mbox *mbox, const struct mbox_message *msg,
		unsigned long flags)
{
	int rc;

	if (flags & MBOX_ASYNC) {
		kfifo_in(&chan->tx_fifo, msg->data, msg->len);
		schedule_work(&mbox->chan->tx_work);
		return 0;
	}

	/**
	 * obviously, if not because of the lock, then because the adapter
	 * should wait for an ACK from it's controller if appropriate.
	 */
	might_sleep();

	mutex_lock(&mbox->adapter->lock);
	rc = mbox->adapter->ops->put_message(mbox->adapter, mbox->chan, msg);
	mutex_unlock(&mbox->adapter->lock);

	return rc;
}

/* called from consumer; illustrates the problem with peek */
int mbox_peek_message(struct mbox *mbox, struct mbox_message *msg)
{

	int rc;
	if (chan->flags & MBOX_ASYNC) {
		msg->len = kfifo_out_peek(&mbox->chan->rx_fifo,
				msg->data, msg->len);
		return 0;
	}

	/**
	 * It is unlikely that most adapters are able to properly implement
	 * this, so we have to allow for that.
	 */
	if (!mbox->adapter->ops->peek_message)
		return -EOPNOTSUPP;

	/**
	 * so this is where this lock makes things difficult, as this function
	 * might_sleep(), but only really because of the lock.  Either we can
	 * remove the lock and force the adapter to do its own locking
	 * spinlock-style, or we can accept the sleep here, which seems a bit
	 * stupid in a peek function.  Neither option is good.  Additionally,
	 * there's no guarantee that the adapter doesn't operate over a bus
	 * which itself might_sleep(), exacerbating the problem.
	 */
	mutex_lock(&mbox->adapter->lock);
	rc = mbox->adapter->ops->peek_message(mbox->adapter, mbox->chan, msg);
	mutex_lock(&mbox->adapter->lock);

	return rc;
}

struct mbox *mbox_request(struct device *dev, const char *con_id,
		void (*receive)(void *, struct mbox *, const struct mbox_message *),
		void *priv, unsigned long flags)
{
	struct mbox_channel *chan;
	struct mbox *mbox;
	int rc;
	...
	chan->flags = flags;
	if (flags & MBOX_ASYNC) {
		rc = kfifo_alloc(&chan->rx_fifo, MBOX_FIFO_SIZE, GFP_KERNEL);
		if (rc)
			return rc;
		INIT_WORK(&chan->rx_work, rx_work);
	}
	if (1 /* consumer plans on calling put_message with MBOX_ASYNC */) {
		INIT_KFIFO(chan->tx_fifo);
		INIT_WORK(&chan->tx_work, tx_work);
	}
	chan->consumer = mbox;
	mbox->cb = receive;
	mbox->priv = priv;
	...
	return mbox;
}

^ permalink raw reply

* Re: [PATCH v2 3/3] Documentation: mfd: Add binding document for S2MPA01
From: Mark Brown @ 2014-02-12 18:21 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Sachin Kamat,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	sbkim73-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
	lgirdwood-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	patches-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
In-Reply-To: <20140212181043.GB23630-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>

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

On Wed, Feb 12, 2014 at 06:10:43PM +0000, Mark Rutland wrote:
> On Thu, Jan 09, 2014 at 11:22:34AM +0000, Sachin Kamat wrote:

> > +Required properties:
> > +- compatible: Should be "samsung,s2mpa01-pmic".
> > +- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.

> Is the slave address not per-instance in I2C? If not why must is be 0x66?

I2C devices tend to have a very limited selection of addresses they can
support, a small number selected by pin strapping is common but a single
fixed address is also common.  Each device on the bus will have a unique
address but there may not be any selectability.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH V6 05/12] SPEAr: misc: Add binding information
From: Mark Rutland @ 2014-02-12 18:21 UTC (permalink / raw)
  To: Mohit Kumar
  Cc: arnd-r2nGTMty4D4@public.gmane.org, Pratyush Anand, Viresh Kumar,
	spear-devel-nkJGhpqTU55BDgjK7y7TUQ@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <bfddafffd103bef179fef717793bf94652742b85.1392109054.git.mohit.kumar-qxv4g6HH51o@public.gmane.org>

On Tue, Feb 11, 2014 at 09:30:01AM +0000, Mohit Kumar wrote:
> From: Pratyush Anand <pratyush.anand-qxv4g6HH51o@public.gmane.org>
> 
> SPEAr SOCs have some miscellaneous registers which are used to configure
> few properties of different peripheral controllers.
> 
> Signed-off-by: Pratyush Anand <pratyush.anand-qxv4g6HH51o@public.gmane.org>
> Cc: Mohit Kumar <mohit.kumar-qxv4g6HH51o@public.gmane.org>
> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Cc: Viresh Kumar <viresh.linux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: spear-devel-nkJGhpqTU55BDgjK7y7TUQ@public.gmane.org
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> ---
>  .../devicetree/bindings/arm/spear-misc.txt         |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/spear-misc.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/spear-misc.txt b/Documentation/devicetree/bindings/arm/spear-misc.txt
> new file mode 100644
> index 0000000..ab324e1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/spear-misc.txt
> @@ -0,0 +1,9 @@
> +SPEAr Misc configuration
> +===========================
> +SPEAr SOCs have some miscellaneous registers which are used to configure
> +few properties of different peripheral controllers.
> +
> +misc node required properties:
> +
> +- compatible Should be	"st,spear1340-misc", "syscon".
> +- reg: Address range of misc space

Is there no better name than misc?

How big is this expected to be?

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

^ permalink raw reply


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