* [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency support
From: Rajendra Nayak @ 2011-02-11 5:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1102102209080.21991@utopia.booyaka.com>
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Friday, February 11, 2011 10:44 AM
> To: Rajendra Nayak
> Cc: linux-omap at vger.kernel.org; Kevin Hilman; Benoit Cousson;
linux-arm-kernel at lists.infradead.org
> Subject: RE: [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency
support
>
> Hi Rajendra
>
> On Fri, 11 Feb 2011, Rajendra Nayak wrote:
>
> > Failing silently is going to make it more difficult to identify and
fix.
> > Maybe a WARN in else?
> >
> > if (cd->clkdm) {
> > ...
> > } else
> > WARN()
>
> I was thinking it might be nice to put it right next to the
> _clkdm_lookup()s in clkdm_init(), since the _clkdm_lookup is what is
> actually failing. Then we could do a
>
> if (!cd->clkdm)
> continue;
>
> in the SoC-specific *_all_wkdep/sleepdep* code, just to keep the system
> from crashing...
>
> Does that sound okay to you?
Yep, that sounds better.
Thanks,
Rajendra
>
>
> - Paul
^ permalink raw reply
* [PATCH 2/2] Add Snapper9260 rtc wakeup interrupt pin
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-02-11 5:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297395844-21162-2-git-send-email-ryan@bluewatersys.com>
On 16:44 Fri 11 Feb , Ryan Mallon wrote:
>
> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
> ---
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Best Regards,
J.
^ permalink raw reply
* [PATCH 1/2] AT91: Use macros for gpio_to_irq/irq_to_gpio
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-02-11 5:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297395844-21162-1-git-send-email-ryan@bluewatersys.com>
On 16:44 Fri 11 Feb , Ryan Mallon wrote:
> Replace the static inline functions for gpio_to_irq/irq_to_gpio so that they
> can be used in static initialisers.
>
> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
> ---
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Best Regards,
J.
^ permalink raw reply
* [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency support
From: Paul Walmsley @ 2011-02-11 5:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <74b7dfbe67e19da4358f7df0bc4dd8f1@mail.gmail.com>
Hi Rajendra
On Fri, 11 Feb 2011, Rajendra Nayak wrote:
> Failing silently is going to make it more difficult to identify and fix.
> Maybe a WARN in else?
>
> if (cd->clkdm) {
> ...
> } else
> WARN()
I was thinking it might be nice to put it right next to the
_clkdm_lookup()s in clkdm_init(), since the _clkdm_lookup is what is
actually failing. Then we could do a
if (!cd->clkdm)
continue;
in the SoC-specific *_all_wkdep/sleepdep* code, just to keep the system
from crashing...
Does that sound okay to you?
- Paul
^ permalink raw reply
* [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency support
From: Rajendra Nayak @ 2011-02-11 5:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1102102135220.21991@utopia.booyaka.com>
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Friday, February 11, 2011 10:08 AM
> To: Rajendra Nayak
> Cc: linux-omap at vger.kernel.org; Kevin Hilman; Benoit Cousson;
linux-arm-kernel at lists.infradead.org
> Subject: RE: [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency
support
>
> On Fri, 11 Feb 2011, Rajendra Nayak wrote:
>
> > My initial version actually did have a check for cd->clkdm_name
instead
> > of cd->clkdm, and then I ran into aborts when a clkdm, though
belonging
> > to the right chip version, failed lookup (in clkdm_init) and left the
> > cd->clkdm pointer NULL. This however was due to the fact that the
> > clkdm_name populated was'nt matching the actual name,
>
> So those aborts were due to clockdomain or clockdomain dependency data
> that had errors that caused it not to have referential integrity?
Yes, I specifically found it when my script updates were actually
generating some non-matching (and hence wrong) clkdm_names.
The aborts actually helped me fix it...
>
> > Would it make sense to add an additional check here to avoid
> > an abort in case of mismatches in clkdm_name populated and
> > lookup's failing in clkdm_init?
> >
> > Something like...
> >
> > If (cd->clkdm) {
> > |= 1 << cd->clkdm->dep_bit;
> > atomic_set(&cd->wkdep_usecount, 0);
> > }
>
> That is going to fail silently. If I'm understanding the problem
> that you're referring to correctly, it seems to me that in these
> circumstances, we want to fail loudly. Especially now that all that
data
> is supposed to be autogenerated. It is a symptom of a more profound
> problem that the end user should never see, no?
... so you are right. Failing silently is going to make it more difficult
to identify and fix. Maybe a WARN in else?
if (cd->clkdm) {
...
} else
WARN()
>
>
> - Paul
^ permalink raw reply
* [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency support
From: Paul Walmsley @ 2011-02-11 4:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3754d10e94217aa81846aa1d41fe0a9d@mail.gmail.com>
On Fri, 11 Feb 2011, Rajendra Nayak wrote:
> My initial version actually did have a check for cd->clkdm_name instead
> of cd->clkdm, and then I ran into aborts when a clkdm, though belonging
> to the right chip version, failed lookup (in clkdm_init) and left the
> cd->clkdm pointer NULL. This however was due to the fact that the
> clkdm_name populated was'nt matching the actual name,
So those aborts were due to clockdomain or clockdomain dependency data
that had errors that caused it not to have referential integrity?
> Would it make sense to add an additional check here to avoid
> an abort in case of mismatches in clkdm_name populated and
> lookup's failing in clkdm_init?
>
> Something like...
>
> If (cd->clkdm) {
> |= 1 << cd->clkdm->dep_bit;
> atomic_set(&cd->wkdep_usecount, 0);
> }
That is going to fail silently. If I'm understanding the problem
that you're referring to correctly, it seems to me that in these
circumstances, we want to fail loudly. Especially now that all that data
is supposed to be autogenerated. It is a symptom of a more profound
problem that the end user should never see, no?
- Paul
^ permalink raw reply
* [PATCH v2 2/5] OMAP: clockdomain: Arch specific funcs to handle deps
From: Rajendra Nayak @ 2011-02-11 4:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1102101908540.21991@utopia.booyaka.com>
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Friday, February 11, 2011 7:40 AM
> To: Rajendra Nayak
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
khilman at ti.com; b-cousson at ti.com
> Subject: Re: [PATCH v2 2/5] OMAP: clockdomain: Arch specific funcs to
handle deps
>
>
> One other minor change; also modified the wkdep_src/sleepdep_src clkdm
> resolve loops in clkdm_init() to avoid re-resolving clockdomains that
have
> already been looked up. Updated patch follows.
Thanks, looks good.
>
>
> - Paul
>
>
> From 22e63ae70ee061de0171c99ee336957b5e9a11ea Mon Sep 17 00:00:00 2001
> From: Rajendra Nayak <rnayak@ti.com>
> Date: Tue, 8 Feb 2011 14:25:34 -0700
> Subject: [PATCH] OMAP: clockdomain: Arch specific funcs to handle deps
>
> Define the following architecture specific funtions for omap2/3
> .clkdm_add_wkdep
> .clkdm_del_wkdep
> .clkdm_read_wkdep
> .clkdm_clear_all_wkdeps
> .clkdm_add_sleepdep
> .clkdm_del_sleepdep
> .clkdm_read_sleepdep
> .clkdm_clear_all_sleepdeps
>
> Convert the platform-independent framework to call these functions.
> With this also move the clkdm lookups for all wkdep_srcs and
> sleepdep_srcs at clkdm_init.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> [paul at pwsan.com: fixed loop termination conditions in
omap*_clkdm_clear_all_*();
> thanks to Kevin Hilman for finding and helping fix those bugs; also
> avoid re-resolving clockdomains during init]
> Cc: Kevin Hilman <khilman@ti.com>
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> ---
> arch/arm/mach-omap2/Makefile | 2 +
> arch/arm/mach-omap2/clockdomain.c | 164
+++++++++++----------
> arch/arm/mach-omap2/clockdomain.h | 6 +-
> arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 126
+++++++++++++++++
> arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c | 9 +-
> arch/arm/mach-omap2/io.c | 6 +-
> 6 files changed, 229 insertions(+), 84 deletions(-)
> create mode 100644 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 1c0c2b0..6b2824d 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -102,8 +102,10 @@ obj-$(CONFIG_ARCH_OMAP4) +=
$(powerdomain-common) \
>
> # PRCM clockdomain control
> obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \
> + clockdomain2xxx_3xxx.o \
> clockdomains2xxx_3xxx_data.o
> obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \
> + clockdomain2xxx_3xxx.o \
> clockdomains2xxx_3xxx_data.o
> obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \
> clockdomains44xx_data.o
> diff --git a/arch/arm/mach-omap2/clockdomain.c
b/arch/arm/mach-omap2/clockdomain.c
> index f70b06a..ee73927 100644
> --- a/arch/arm/mach-omap2/clockdomain.c
> +++ b/arch/arm/mach-omap2/clockdomain.c
> @@ -308,6 +308,7 @@ void clkdm_init(struct clockdomain **clkdms,
> struct clockdomain **c = NULL;
> struct clockdomain *clkdm;
> struct clkdm_autodep *autodep = NULL;
> + struct clkdm_dep *cd;
>
> if (!custom_funcs)
> WARN(1, "No custom clkdm functions registered\n");
> @@ -333,7 +334,22 @@ void clkdm_init(struct clockdomain **clkdms,
> else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
> omap2_clkdm_deny_idle(clkdm);
>
> + for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
> + if (!omap_chip_is(cd->omap_chip))
> + continue;
> + if (cd->clkdm)
> + continue;
> + cd->clkdm = _clkdm_lookup(cd->clkdm_name);
> + }
> clkdm_clear_all_wkdeps(clkdm);
> +
> + for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name;
cd++) {
> + if (!omap_chip_is(cd->omap_chip))
> + continue;
> + if (cd->clkdm)
> + continue;
> + cd->clkdm = _clkdm_lookup(cd->clkdm_name);
> + }
> clkdm_clear_all_sleepdeps(clkdm);
> }
> }
> @@ -430,6 +446,7 @@ struct powerdomain *clkdm_get_pwrdm(struct
clockdomain *clkdm)
> int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain
*clkdm2)
> {
> struct clkdm_dep *cd;
> + int ret = 0;
>
> if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
> pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
> @@ -441,21 +458,26 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> return -EINVAL;
>
> cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
> - if (IS_ERR(cd)) {
> + if (IS_ERR(cd))
> + ret = PTR_ERR(cd);
> +
> + if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
> + ret = -EINVAL;
> +
> + if (ret) {
> pr_debug("clockdomain: hardware cannot set/clear wake up
of "
> "%s when %s wakes up\n", clkdm1->name,
clkdm2->name);
> - return PTR_ERR(cd);
> + return ret;
> }
>
> if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
> pr_debug("clockdomain: hardware will wake up %s when %s
wakes "
> "up\n", clkdm1->name, clkdm2->name);
>
> - omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
> - clkdm1->pwrdm.ptr->prcm_offs,
PM_WKDEP);
> + ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
> }
>
> - return 0;
> + return ret;
> }
>
> /**
> @@ -471,6 +493,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain
*clkdm2)
> {
> struct clkdm_dep *cd;
> + int ret = 0;
>
> if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
> pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
> @@ -482,21 +505,26 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> return -EINVAL;
>
> cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
> - if (IS_ERR(cd)) {
> + if (IS_ERR(cd))
> + ret = PTR_ERR(cd);
> +
> + if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
> + ret = -EINVAL;
> +
> + if (ret) {
> pr_debug("clockdomain: hardware cannot set/clear wake up
of "
> "%s when %s wakes up\n", clkdm1->name,
clkdm2->name);
> - return PTR_ERR(cd);
> + return ret;
> }
>
> if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
> pr_debug("clockdomain: hardware will no longer wake up %s
"
> "after %s wakes up\n", clkdm1->name,
clkdm2->name);
>
> - omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
> - clkdm1->pwrdm.ptr->prcm_offs,
PM_WKDEP);
> + ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
> }
>
> - return 0;
> + return ret;
> }
>
> /**
> @@ -516,6 +544,7 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain
*clkdm2)
> {
> struct clkdm_dep *cd;
> + int ret = 0;
>
> if (!clkdm1 || !clkdm2)
> return -EINVAL;
> @@ -527,15 +556,20 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> }
>
> cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
> - if (IS_ERR(cd)) {
> + if (IS_ERR(cd))
> + ret = PTR_ERR(cd);
> +
> + if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
> + ret = -EINVAL;
> +
> + if (ret) {
> pr_debug("clockdomain: hardware cannot set/clear wake up
of "
> "%s when %s wakes up\n", clkdm1->name,
clkdm2->name);
> - return PTR_ERR(cd);
> + return ret;
> }
>
> /* XXX It's faster to return the atomic wkdep_usecount */
> - return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
PM_WKDEP,
> - (1 << clkdm2->dep_bit));
> + return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
> }
>
> /**
> @@ -550,9 +584,6 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> */
> int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
> {
> - struct clkdm_dep *cd;
> - u32 mask = 0;
> -
> if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
> pr_err("clockdomain: %s: %s: not yet implemented\n",
> clkdm->name, __func__);
> @@ -562,21 +593,10 @@ int clkdm_clear_all_wkdeps(struct clockdomain
*clkdm)
> if (!clkdm)
> return -EINVAL;
>
> - for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
> - if (!omap_chip_is(cd->omap_chip))
> - continue;
> -
> - if (!cd->clkdm && cd->clkdm_name)
> - cd->clkdm = _clkdm_lookup(cd->clkdm_name);
> -
> - /* PRM accesses are slow, so minimize them */
> - mask |= 1 << cd->clkdm->dep_bit;
> - atomic_set(&cd->wkdep_usecount, 0);
> - }
> -
> - omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
PM_WKDEP);
> + if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
> + return -EINVAL;
>
> - return 0;
> + return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
> }
>
> /**
> @@ -594,31 +614,33 @@ int clkdm_clear_all_wkdeps(struct clockdomain
*clkdm)
> int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain
*clkdm2)
> {
> struct clkdm_dep *cd;
> -
> - if (!cpu_is_omap34xx())
> - return -EINVAL;
> + int ret = 0;
>
> if (!clkdm1 || !clkdm2)
> return -EINVAL;
>
> cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
> - if (IS_ERR(cd)) {
> + if (IS_ERR(cd))
> + ret = PTR_ERR(cd);
> +
> + if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
> + ret = -EINVAL;
> +
> + if (ret) {
> pr_debug("clockdomain: hardware cannot set/clear sleep "
> "dependency affecting %s from %s\n",
clkdm1->name,
> clkdm2->name);
> - return PTR_ERR(cd);
> + return ret;
> }
>
> if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
> pr_debug("clockdomain: will prevent %s from sleeping if %s
"
> "is active\n", clkdm1->name, clkdm2->name);
>
> - omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
> - clkdm1->pwrdm.ptr->prcm_offs,
> - OMAP3430_CM_SLEEPDEP);
> + ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
> }
>
> - return 0;
> + return ret;
> }
>
> /**
> @@ -636,19 +658,23 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain
*clkdm2)
> {
> struct clkdm_dep *cd;
> -
> - if (!cpu_is_omap34xx())
> - return -EINVAL;
> + int ret = 0;
>
> if (!clkdm1 || !clkdm2)
> return -EINVAL;
>
> cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
> - if (IS_ERR(cd)) {
> + if (IS_ERR(cd))
> + ret = PTR_ERR(cd);
> +
> + if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
> + ret = -EINVAL;
> +
> + if (ret) {
> pr_debug("clockdomain: hardware cannot set/clear sleep "
> "dependency affecting %s from %s\n",
clkdm1->name,
> clkdm2->name);
> - return PTR_ERR(cd);
> + return ret;
> }
>
> if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
> @@ -656,12 +682,10 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> "sleeping if %s is active\n", clkdm1->name,
> clkdm2->name);
>
> - omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
> - clkdm1->pwrdm.ptr->prcm_offs,
> - OMAP3430_CM_SLEEPDEP);
> + ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
> }
>
> - return 0;
> + return ret;
> }
>
> /**
> @@ -683,25 +707,27 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1,
struct clockdomain *clkdm2)
> int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain
*clkdm2)
> {
> struct clkdm_dep *cd;
> -
> - if (!cpu_is_omap34xx())
> - return -EINVAL;
> + int ret = 0;
>
> if (!clkdm1 || !clkdm2)
> return -EINVAL;
>
> cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
> - if (IS_ERR(cd)) {
> + if (IS_ERR(cd))
> + ret = PTR_ERR(cd);
> +
> + if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
> + ret = -EINVAL;
> +
> + if (ret) {
> pr_debug("clockdomain: hardware cannot set/clear sleep "
> "dependency affecting %s from %s\n",
clkdm1->name,
> clkdm2->name);
> - return PTR_ERR(cd);
> + return ret;
> }
>
> /* XXX It's faster to return the atomic sleepdep_usecount */
> - return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
> - OMAP3430_CM_SLEEPDEP,
> - (1 << clkdm2->dep_bit));
> + return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
> }
>
> /**
> @@ -716,31 +742,13 @@ int clkdm_read_sleepdep(struct clockdomain
*clkdm1, struct clockdomain *clkdm2)
> */
> int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
> {
> - struct clkdm_dep *cd;
> - u32 mask = 0;
> -
> - if (!cpu_is_omap34xx())
> - return -EINVAL;
> -
> if (!clkdm)
> return -EINVAL;
>
> - for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
> - if (!omap_chip_is(cd->omap_chip))
> - continue;
> -
> - if (!cd->clkdm && cd->clkdm_name)
> - cd->clkdm = _clkdm_lookup(cd->clkdm_name);
> -
> - /* PRM accesses are slow, so minimize them */
> - mask |= 1 << cd->clkdm->dep_bit;
> - atomic_set(&cd->sleepdep_usecount, 0);
> - }
> -
> - omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
> - OMAP3430_CM_SLEEPDEP);
> + if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
> + return -EINVAL;
>
> - return 0;
> + return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
> }
>
> /**
> diff --git a/arch/arm/mach-omap2/clockdomain.h
b/arch/arm/mach-omap2/clockdomain.h
> index 71ad265..90b6d6a 100644
> --- a/arch/arm/mach-omap2/clockdomain.h
> +++ b/arch/arm/mach-omap2/clockdomain.h
> @@ -176,7 +176,11 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm);
> int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
> int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk
*clk);
>
> -extern void __init omap2_clockdomains_init(void);
> +extern void __init omap2xxx_clockdomains_init(void);
> +extern void __init omap3xxx_clockdomains_init(void);
> extern void __init omap44xx_clockdomains_init(void);
>
> +extern struct clkdm_ops omap2_clkdm_operations;
> +extern struct clkdm_ops omap3_clkdm_operations;
> +
> #endif
> diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
> new file mode 100644
> index 0000000..38dd903
> --- /dev/null
> +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
> @@ -0,0 +1,126 @@
> +/*
> + * OMAP2 and OMAP3 clockdomain control
> + *
> + * Copyright (C) 2008-2010 Texas Instruments, Inc.
> + * Copyright (C) 2008-2010 Nokia Corporation
> + *
> + * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
> + * Rajendra Nayak <rnayak@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/types.h>
> +#include <plat/prcm.h>
> +#include "prm.h"
> +#include "prm2xxx_3xxx.h"
> +#include "cm.h"
> +#include "cm2xxx_3xxx.h"
> +#include "cm-regbits-24xx.h"
> +#include "cm-regbits-34xx.h"
> +#include "clockdomain.h"
> +
> +static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
> + struct clockdomain
*clkdm2)
> +{
> + omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
> + clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
> + return 0;
> +}
> +
> +static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
> + struct clockdomain
*clkdm2)
> +{
> + omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
> + clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
> + return 0;
> +}
> +
> +static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
> + struct clockdomain
*clkdm2)
> +{
> + return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
> + PM_WKDEP, (1 << clkdm2->dep_bit));
> +}
> +
> +static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
> +{
> + struct clkdm_dep *cd;
> + u32 mask = 0;
> +
> + for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
> + if (!omap_chip_is(cd->omap_chip))
> + continue;
> +
> + /* PRM accesses are slow, so minimize them */
> + mask |= 1 << cd->clkdm->dep_bit;
> + atomic_set(&cd->wkdep_usecount, 0);
> + }
> +
> + omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
> + PM_WKDEP);
> + return 0;
> +}
> +
> +static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
> + struct clockdomain
*clkdm2)
> +{
> + omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
> + clkdm1->pwrdm.ptr->prcm_offs,
> + OMAP3430_CM_SLEEPDEP);
> + return 0;
> +}
> +
> +static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
> + struct clockdomain
*clkdm2)
> +{
> + omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
> + clkdm1->pwrdm.ptr->prcm_offs,
> + OMAP3430_CM_SLEEPDEP);
> + return 0;
> +}
> +
> +static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
> + struct clockdomain
*clkdm2)
> +{
> + return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
> + OMAP3430_CM_SLEEPDEP, (1 <<
clkdm2->dep_bit));
> +}
> +
> +static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
> +{
> + struct clkdm_dep *cd;
> + u32 mask = 0;
> +
> + for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
> + if (!omap_chip_is(cd->omap_chip))
> + continue;
> +
> + /* PRM accesses are slow, so minimize them */
> + mask |= 1 << cd->clkdm->dep_bit;
> + atomic_set(&cd->sleepdep_usecount, 0);
> + }
> + omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
> + OMAP3430_CM_SLEEPDEP);
> + return 0;
> +}
> +
> +struct clkdm_ops omap2_clkdm_operations = {
> + .clkdm_add_wkdep = omap2_clkdm_add_wkdep,
> + .clkdm_del_wkdep = omap2_clkdm_del_wkdep,
> + .clkdm_read_wkdep = omap2_clkdm_read_wkdep,
> + .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
> +};
> +
> +struct clkdm_ops omap3_clkdm_operations = {
> + .clkdm_add_wkdep = omap2_clkdm_add_wkdep,
> + .clkdm_del_wkdep = omap2_clkdm_del_wkdep,
> + .clkdm_read_wkdep = omap2_clkdm_read_wkdep,
> + .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
> + .clkdm_add_sleepdep = omap3_clkdm_add_sleepdep,
> + .clkdm_del_sleepdep = omap3_clkdm_del_sleepdep,
> + .clkdm_read_sleepdep = omap3_clkdm_read_sleepdep,
> + .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps,
> +};
> diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
b/arch/arm/mach-
> omap2/clockdomains2xxx_3xxx_data.c
> index 8cab07a..f85de72 100644
> --- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
> +++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
> @@ -854,7 +854,12 @@ static struct clockdomain *clockdomains_omap2[]
__initdata = {
> NULL,
> };
>
> -void __init omap2_clockdomains_init(void)
> +void __init omap2xxx_clockdomains_init(void)
> {
> - clkdm_init(clockdomains_omap2, clkdm_autodeps, NULL);
> + clkdm_init(clockdomains_omap2, clkdm_autodeps,
&omap2_clkdm_operations);
> +}
> +
> +void __init omap3xxx_clockdomains_init(void)
> +{
> + clkdm_init(clockdomains_omap2, clkdm_autodeps,
&omap3_clkdm_operations);
> }
> diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
> index c203204..89cbba2 100644
> --- a/arch/arm/mach-omap2/io.c
> +++ b/arch/arm/mach-omap2/io.c
> @@ -337,15 +337,15 @@ void __init omap2_init_common_infrastructure(void)
>
> if (cpu_is_omap242x()) {
> omap2xxx_powerdomains_init();
> - omap2_clockdomains_init();
> + omap2xxx_clockdomains_init();
> omap2420_hwmod_init();
> } else if (cpu_is_omap243x()) {
> omap2xxx_powerdomains_init();
> - omap2_clockdomains_init();
> + omap2xxx_clockdomains_init();
> omap2430_hwmod_init();
> } else if (cpu_is_omap34xx()) {
> omap3xxx_powerdomains_init();
> - omap2_clockdomains_init();
> + omap3xxx_clockdomains_init();
> omap3xxx_hwmod_init();
> } else if (cpu_is_omap44xx()) {
> omap44xx_powerdomains_init();
> --
> 1.7.2.3
^ permalink raw reply
* [PATCH] picoxcell_crypto: add support for the picoxcell crypto engines
From: Kim Phillips @ 2011-02-11 4:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297180576-11581-1-git-send-email-jamie@jamieiles.com>
On Tue, 8 Feb 2011 15:56:16 +0000
Jamie Iles <jamie@jamieiles.com> wrote:
> Picochip picoXcell devices have two crypto engines, one targeted
> at IPSEC offload and the other at WCDMA layer 2 ciphering.
>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> ---
nice driver ;). Have a couple of comments though.
> + help
> + This option enables support for the hardware offload engines in the
> + Picochip picoXcell SoC devices. Select this for IPSEC ESP offload
> + and for 3gpp Layer 2 ciphering support.
it'd be nice to mention what name the module will have.
> +#define SPACC_CRYPTO_AES_MAX_KEY_LEN 32
> +#define SPACC_CRYPTO_AES_IV_LEN 16
> +#define SPACC_CRYPTO_DES_IV_LEN 8
these are identical to algorithm-generic symbolic constants
AES_MAX_KEY_SIZE, [AD]ES_BLOCK_SIZE - why not use them instead?
> +struct spacc_generic_ctx;
this declaration isn't used prior to its definition, so it's not needed.
> +/* DDT format. This must match the hardware DDT format exactly. */
> +struct spacc_ddt {
> + u32 p, len;
type-consistency: p should be a dma_addr_t
> + /* AEAD specifc bits. */
specific
> +static inline struct spacc_ablk_ctx *
> +to_spacc_ablk_ctx(struct spacc_generic_ctx *ctx)
> +{
> + return ctx ? container_of(ctx, struct spacc_ablk_ctx, generic) : NULL;
> +}
> +
> +static inline struct spacc_aead_ctx *
> +to_spacc_aead_ctx(struct spacc_generic_ctx *ctx)
> +{
> + return ctx ? container_of(ctx, struct spacc_aead_ctx, generic) : NULL;
> +}
these aren't being used anywhere.
> +static inline struct spacc_alg *to_spacc_alg(struct crypto_alg *alg);
define it here - forward declarations should only be necessary when
dealing with circular dependencies.
> +/*
> + * Take a crypto request and scatterlists for the data and turn them into DDTs
> + * for passing to the crypto engines. This also DMA maps the data so that the
> + * crypto engines can DMA to/from them.
> + */
> +static struct spacc_ddt *spacc_sg_to_ddt(struct spacc_engine *engine,
> + struct scatterlist *payload,
> + unsigned nbytes,
> + enum dma_data_direction dir,
> + dma_addr_t *ddt_phys)
> +{
> + unsigned nents, mapped_ents;
> + struct scatterlist *cur;
> + struct spacc_ddt *ddt;
> + int i;
> +
> + nents = sg_count(payload, nbytes);
> + mapped_ents = dma_map_sg(engine->dev, payload, nents, dir);
> +
> + if (mapped_ents + 1 > MAX_DDT_LEN) {
> + dma_unmap_sg(engine->dev, payload, nents, dir);
> + return NULL;
> + }
> +
> + ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, ddt_phys);
> + if (ddt) {
> + for_each_sg(payload, cur, mapped_ents, i) {
> + ddt[i].p = sg_dma_address(cur);
> + ddt[i].len = sg_dma_len(cur);
> + }
> +
> + ddt[mapped_ents].p = 0;
> + ddt[mapped_ents].len = 0;
> + } else {
> + dma_unmap_sg(engine->dev, payload, nents, dir);
> + ddt = NULL;
> + }
> +
> + return ddt;
> +}
easier to read would be:
if (mapped_ents + 1 > MAX_DDT_LEN)
goto out;
ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, ddt_phys);
if (!ddt)
goto out;
for_each_sg(payload, cur, mapped_ents, i) {
ddt[i].p = sg_dma_address(cur);
ddt[i].len = sg_dma_len(cur);
}
ddt[mapped_ents].p = 0;
ddt[mapped_ents].len = 0;
return ddt;
out:
dma_unmap_sg(engine->dev, payload, nents, dir);
return NULL;
}
even more so by moving ddt_set() above it, and then using ddt_set() to
assign the p, len pairs.
> +static inline void ddt_set(struct spacc_ddt *ddt, unsigned long phys,
phys should be dma_addr_t
> +static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
> +{
> + struct aead_request *areq = container_of(req->req, struct aead_request,
> + base);
> + struct spacc_alg *alg = to_spacc_alg(req->req->tfm->__crt_alg);
> + struct spacc_engine *engine = req->engine;
> + struct spacc_ddt *src_ddt, *dst_ddt;
> + unsigned ivsize = alg->alg.cra_aead.ivsize;
no need to go through all those hoops to get to the ivsize - use helper
fns crypto_aead_reqtfm() and crypto_aead_ivsize(), as is done at the
callsite, or just pass it in from there.
> +static int spacc_aead_des_setkey(struct crypto_aead *aead, const u8 *key,
> + unsigned int len)
> +{
> + struct crypto_tfm *tfm = crypto_aead_tfm(aead);
> + struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
> + int err = 0;
> + u32 tmp[DES_EXPKEY_WORDS];
> +
> + err = des_ekey(tmp, key);
> + if (unlikely(!err) &&
might want to change the name of the variable err here to something
like ret or is_weak so as to not mislead the reader.
> + (crypto_aead_get_flags(aead)) & CRYPTO_TFM_REQ_WEAK_KEY) {
> + tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
> + return -EINVAL;
> + }
> + err = 0;
> +
> + memcpy(ctx->cipher_key, key, len);
> + ctx->cipher_key_len = len;
> +
> + return err;
actually, it doesn't look like this fn needs a return variable
at all.
> +/* Set the key for the AES block cipher component of the AEAD transform. */
> +static int spacc_aead_aes_setkey(struct crypto_aead *aead, const u8 *key,
> + unsigned int len)
> +{
> + struct crypto_tfm *tfm = crypto_aead_tfm(aead);
> + struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
> + int err;
> +
> + /*
> + * IPSec engine only supports 128 and 256 bit AES keys. If we get a
> + * request for any other size (192 bits) then we need to do a software
> + * fallback.
> + */
> + if (!(16 == len || 32 == len)) {
if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256)
> + /*
> + * Set the fallback transform to use the same request flags as
> + * the hardware transform.
> + */
> + ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
> + ctx->sw_cipher->base.crt_flags |=
> + (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
parens not needed.
> + err = crypto_aead_setkey(ctx->sw_cipher, key, len);
> + } else {
> + memcpy(ctx->cipher_key, key, len);
> + ctx->cipher_key_len = len;
> + err = 0;
> + }
> +
> + return err;
return crypto_aead_setkey(ctx->sw_cipher, key, len);
}
memcpy(ctx->cipher_key, key, len);
ctx->cipher_key_len = len;
return 0;
> +static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
> + unsigned int keylen)
> +{
> + struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
> + struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
> + struct rtattr *rta = (void *)key;
> + struct crypto_authenc_key_param *param;
> + unsigned int authkeylen, enckeylen;
> + int err = -EINVAL;
> +
> + if (!RTA_OK(rta, keylen))
> + goto badkey;
> +
> + if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
> + goto badkey;
> +
> + if (RTA_PAYLOAD(rta) < sizeof(*param))
> + goto badkey;
I'm not sure, but it should be safe to remove the above three checks -
they cause a false badkey failure if the keys aren't within an rtattr
struct, which, e.g., something like testmgr.c wouldn't do.
> + param = RTA_DATA(rta);
> + enckeylen = be32_to_cpu(param->enckeylen);
> +
> + key += RTA_ALIGN(rta->rta_len);
> + keylen -= RTA_ALIGN(rta->rta_len);
actually, I doubt crypto drivers should be including rtnetlink.h at
all...but it's probably ok for now - talitos still does :)
> + if ((spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
> + SPA_CTRL_CIPH_ALG_AES &&
> + !(16 == ctx->cipher_key_len || 32 == ctx->cipher_key_len))
as above, please use symbolic equivalents
> +static void spacc_aead_complete(struct spacc_req *req)
> +{
> + spacc_aead_free_ddts(req);
> +
> + if (req->req->complete)
> + req->req->complete(req->req, req->result);
when is there not a completion function?
> + /* Set the source and destination DDT pointers. */
> + writel((u32)req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
> + writel((u32)req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
cast necessary?
> + ctrl = spacc_alg->ctrl_default;
> + ctrl |= ((req->ctx_id << SPA_CTRL_CTX_IDX) |
> + (1 << SPA_CTRL_ICV_APPEND) |
> + (req->is_encrypt ? (1 << SPA_CTRL_ENCRYPT_IDX) : 0) |
> + (req->is_encrypt ? (1 << SPA_CTRL_AAD_COPY) : 0));
> + if (!req->is_encrypt)
> + ctrl |= (1 << SPA_CTRL_KEY_EXP);
ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
(1 << SPA_CTRL_ICV_APPEND);
if (req->is_encrypt)
ctrl |= (1 << SPA_CTRL_ENCRYPT_IDX) | (1 << SPA_CTRL_AAD_COPY);
else
ctrl |= (1 << SPA_CTRL_KEY_EXP);
> +static int spacc_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
> + unsigned int len)
> +{
> + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
> + struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
> + int err;
> + u32 tmp[DES_EXPKEY_WORDS];
> +
> + if (len > SPACC_CRYPTO_AES_MAX_KEY_LEN) {
AES left overs in a DES setkey
> +static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
> + unsigned int len)
> +{
> + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
> + struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
> + int err = 0;
> +
> + if (len > SPACC_CRYPTO_AES_MAX_KEY_LEN) {
> + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
> + return -EINVAL;
> + }
> +
> + /*
> + * IPSec engine only supports 128 and 256 bit AES keys. If we get a
> + * request for any other size (192 bits) then we need to do a software
> + * fallback.
> + */
> + if (!(16 == len || 32 == len) && ctx->sw_cipher) {
symbolic constants
> + /*
> + * Set the fallback transform to use the same request flags as
> + * the hardware transform.
> + */
> + ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
> + ctx->sw_cipher->base.crt_flags |=
> + (cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK);
parens not necessary
> +static int spacc_ablk_need_fallback(struct spacc_req *req)
> +{
> + struct spacc_ablk_ctx *ctx;
> + struct crypto_tfm *tfm = req->req->tfm;
> + struct crypto_alg *alg = req->req->tfm->__crt_alg;
> + struct spacc_alg *spacc_alg = to_spacc_alg(alg);
> +
> + ctx = crypto_tfm_ctx(tfm);
> +
> + return (spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
> + SPA_CTRL_CIPH_ALG_AES &&
> + !(16 == ctx->key_len || 32 == ctx->key_len);
symbolic constants
> +static ssize_t spacc_stat_irq_thresh_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t len)
> +{
> + struct spacc_engine *engine = spacc_dev_to_engine(dev);
> + unsigned thresh = simple_strtoul(buf, NULL, 0);
consider using strict_strtoul (checkpatch)
> +static struct spacc_alg ipsec_engine_algs[] = {
> + {
> + .ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC,
> + .key_offs = 0,
> + .iv_offs = SPACC_CRYPTO_AES_MAX_KEY_LEN,
> + .alg = {
> + .cra_name = "cbc(aes)",
> + .cra_driver_name = "cbc-aes-picoxcell",
> + .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
> + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
> + CRYPTO_ALG_ASYNC |
> + CRYPTO_ALG_NEED_FALLBACK,
> + .cra_blocksize = 16,
symbolic constant, here and throughout the rest of this section.
Thanks,
Kim
^ permalink raw reply
* [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency support
From: Rajendra Nayak @ 2011-02-11 4:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1102101905160.21991@utopia.booyaka.com>
Hi Kevin/Paul,
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Friday, February 11, 2011 7:36 AM
> To: Rajendra Nayak
> Cc: linux-omap at vger.kernel.org; khilman at ti.com; b-cousson at ti.com;
linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency
support
>
> Hi
>
> On Mon, 7 Feb 2011, Rajendra Nayak wrote:
>
> > Add OMAP4 platform specific implementation to support clkdm
> > wkup and sleep dependencies a.k.a static dependencies.
> >
> > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>
> This patch had a similar bug to the OMAP2/3 variants; updated patch
> follows -
Thanks for fixing this. I have one comment below...
>
>
> - Paul
>
> From: Rajendra Nayak <rnayak@ti.com>
> Date: Thu, 10 Feb 2011 18:58:04 -0700
> Subject: [PATCH] OMAP4: clockdomain: Add wkup/sleep dependency support
>
> Add OMAP4 platform specific implementation to support clkdm
> wkup and sleep dependencies a.k.a static dependencies.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> [paul at pwsan.com: removed comment about PRM; zero-prefixed STATICDEP
> register offset; fixed loop termination condition in
> omap4_clkdm_clear_all_wkup_sleep_deps(); thanks to Kevin Hilman for
finding
> and helping fix this bug]
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> ---
> arch/arm/mach-omap2/clockdomain44xx.c | 58
+++++++++++++++++++++++++++++++++
> arch/arm/mach-omap2/cm44xx.h | 1 +
> 2 files changed, 59 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/clockdomain44xx.c
b/arch/arm/mach-omap2/clockdomain44xx.c
> index c0ccc47..e6fd8da 100644
> --- a/arch/arm/mach-omap2/clockdomain44xx.c
> +++ b/arch/arm/mach-omap2/clockdomain44xx.c
> @@ -12,8 +12,58 @@
> * published by the Free Software Foundation.
> */
>
> +#include <linux/kernel.h>
> #include "clockdomain.h"
> #include "cminst44xx.h"
> +#include "cm44xx.h"
> +
> +static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
> + struct clockdomain *clkdm2)
> +{
> + omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
> + clkdm1->prcm_partition,
> + clkdm1->cm_inst,
clkdm1->clkdm_offs +
> + OMAP4_CM_STATICDEP);
> + return 0;
> +}
> +
> +static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
> + struct clockdomain *clkdm2)
> +{
> + omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
> + clkdm1->prcm_partition,
> + clkdm1->cm_inst,
clkdm1->clkdm_offs +
> + OMAP4_CM_STATICDEP);
> + return 0;
> +}
> +
> +static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
> + struct clockdomain *clkdm2)
> +{
> + return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
> + clkdm1->cm_inst,
clkdm1->clkdm_offs +
> + OMAP4_CM_STATICDEP,
> + (1 << clkdm2->dep_bit));
> +}
> +
> +static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain
*clkdm)
> +{
> + struct clkdm_dep *cd;
> + u32 mask = 0;
> +
> + for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
My initial version actually did have a check for cd->clkdm_name instead
of cd->clkdm, and then I ran into aborts when a clkdm, though
belonging to the right chip version, failed lookup (in clkdm_init) and
left
the cd->clkdm pointer NULL. This however was due to the fact that the
clkdm_name populated was'nt matching the actual name, but that got
me thinking if its better to look for populated pointers instead of names.
I however seemed to have missed the point that there also could be a
cd->clkdm populated as NULL for non supported CHIP rev's.
> + if (!omap_chip_is(cd->omap_chip))
> + continue;
> +
Would it make sense to add an additional check here to avoid
an abort in case of mismatches in clkdm_name populated and
lookup's failing in clkdm_init?
Something like...
If (cd->clkdm) {
|= 1 << cd->clkdm->dep_bit;
atomic_set(&cd->wkdep_usecount, 0);
}
Regards
Rajendra
> + mask |= 1 << cd->clkdm->dep_bit;
> + atomic_set(&cd->wkdep_usecount, 0);
> + }
> +
> + omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
> + clkdm->cm_inst, clkdm->clkdm_offs
+
> + OMAP4_CM_STATICDEP);
> + return 0;
> +}
>
> static int omap4_clkdm_sleep(struct clockdomain *clkdm)
> {
> @@ -68,6 +118,14 @@ static int omap4_clkdm_clk_disable(struct
clockdomain *clkdm)
> }
>
> struct clkdm_ops omap4_clkdm_operations = {
> + .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep,
> + .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
> + .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep,
> + .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps,
> + .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep,
> + .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep,
> + .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep,
> + .clkdm_clear_all_sleepdeps =
omap4_clkdm_clear_all_wkup_sleep_deps,
> .clkdm_sleep = omap4_clkdm_sleep,
> .clkdm_wakeup = omap4_clkdm_wakeup,
> .clkdm_allow_idle = omap4_clkdm_allow_idle,
> diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
> index 48fc3f4..0b87ec8 100644
> --- a/arch/arm/mach-omap2/cm44xx.h
> +++ b/arch/arm/mach-omap2/cm44xx.h
> @@ -21,6 +21,7 @@
> #include "cm.h"
>
> #define OMAP4_CM_CLKSTCTRL 0x0000
> +#define OMAP4_CM_STATICDEP 0x0004
>
> /* Function prototypes */
> # ifndef __ASSEMBLER__
> --
> 1.7.2.3
^ permalink raw reply
* [PATCH 2/2] Add Snapper9260 rtc wakeup interrupt pin
From: Ryan Mallon @ 2011-02-11 3:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297395844-21162-1-git-send-email-ryan@bluewatersys.com>
Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
arch/arm/mach-at91/board-snapper9260.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 0a99b3c..17f7d9b 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -153,6 +153,7 @@ static struct i2c_board_info __initdata snapper9260_i2c_devices[] = {
{
/* RTC */
I2C_BOARD_INFO("isl1208", 0x6f),
+ .irq = gpio_to_irq(AT91_PIN_PA31),
},
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/2] AT91: Use macros for gpio_to_irq/irq_to_gpio
From: Ryan Mallon @ 2011-02-11 3:44 UTC (permalink / raw)
To: linux-arm-kernel
Replace the static inline functions for gpio_to_irq/irq_to_gpio so that they
can be used in static initialisers.
Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
arch/arm/mach-at91/include/mach/gpio.h | 11 ++---------
1 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index bfdd8ab..ddeb645 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -220,15 +220,8 @@ extern void at91_gpio_resume(void);
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
-static inline int gpio_to_irq(unsigned gpio)
-{
- return gpio;
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
- return irq;
-}
+#define gpio_to_irq(gpio) (gpio)
+#define irq_to_gpio(irq) (irq)
#endif /* __ASSEMBLY__ */
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/2] ARM: tegra: add TrimSlice board
From: Colin Cross @ 2011-02-11 2:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c61e1816027e51acfb5bda1e498225a4da37d92d.1297063443.git.mike@compulab.co.il>
On Mon, Feb 7, 2011 at 12:10 AM, Mike Rapoport <mike@compulab.co.il> wrote:
> Add basic support for CompuLab TrimSlice platform
>
> Signed-off-by: Mike Rapoport <mike@compulab.co.il>
> ---
> ?arch/arm/mach-tegra/Kconfig ? ? ? ? ? ? ? ? ?| ? ?6 +
> ?arch/arm/mach-tegra/Makefile ? ? ? ? ? ? ? ? | ? ?3 +
> ?arch/arm/mach-tegra/board-trimslice-pinmux.c | ?145 ++++++++++++++++++++++++++
> ?arch/arm/mach-tegra/board-trimslice.c ? ? ? ?| ?104 ++++++++++++++++++
> ?arch/arm/mach-tegra/board-trimslice.h ? ? ? ?| ? 22 ++++
> ?5 files changed, 280 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/arm/mach-tegra/board-trimslice-pinmux.c
> ?create mode 100644 arch/arm/mach-tegra/board-trimslice.c
> ?create mode 100644 arch/arm/mach-tegra/board-trimslice.h
>
> diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
> index acd9552..f0fda77 100644
> --- a/arch/arm/mach-tegra/Kconfig
> +++ b/arch/arm/mach-tegra/Kconfig
> @@ -27,6 +27,12 @@ config MACH_HARMONY
> ? ? ? ?help
> ? ? ? ? ?Support for nVidia Harmony development platform
>
> +config MACH_TRIMSLICE
> + ? ? ? bool "TrimSlice board"
> + ? ? ? select TEGRA_PCI
> + ? ? ? help
> + ? ? ? ? Support for CompuLab TrimSlice platform
> +
> ?choice
> ? ? ? ? prompt "Low-level debug console UART"
> ? ? ? ? default TEGRA_DEBUG_UART_NONE
> diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
> index cdbc68e..0e1844b 100644
> --- a/arch/arm/mach-tegra/Makefile
> +++ b/arch/arm/mach-tegra/Makefile
> @@ -19,3 +19,6 @@ obj-$(CONFIG_TEGRA_PCI) ? ? ? ? ? ? ? ? ? ? ? += pcie.o
> ?obj-${CONFIG_MACH_HARMONY} ? ? ? ? ? ? ?+= board-harmony.o
> ?obj-${CONFIG_MACH_HARMONY} ? ? ? ? ? ? ?+= board-harmony-pinmux.o
> ?obj-${CONFIG_MACH_HARMONY} ? ? ? ? ? ? ?+= board-harmony-pcie.o
> +
> +obj-${CONFIG_MACH_TRIMSLICE} ? ? ? ? ? ?+= board-trimslice.o
> +obj-${CONFIG_MACH_TRIMSLICE} ? ? ? ? ? ?+= board-trimslice-pinmux.o
> diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
> new file mode 100644
> index 0000000..6d4fc9f
> --- /dev/null
> +++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
> @@ -0,0 +1,145 @@
> +/*
> + * arch/arm/mach-tegra/board-trimslice-pinmux.c
> + *
> + * Copyright (C) 2011 CompuLab, Ltd.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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/init.h>
> +#include <mach/pinmux.h>
> +
> +#include "board-trimslice.h"
> +
> +static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
> + ? ? ? {TEGRA_PINGROUP_ATA, ? TEGRA_MUX_IDE, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_ATB, ? TEGRA_MUX_SDIO4, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_ATC, ? TEGRA_MUX_NAND, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_ATD, ? TEGRA_MUX_GMI, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_ATE, ? TEGRA_MUX_GMI, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, ? ? TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_CRTP, ?TEGRA_MUX_CRT, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_CSUS, ?TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DAP1, ?TEGRA_MUX_DAP1, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_DAP2, ?TEGRA_MUX_DAP2, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DAP3, ?TEGRA_MUX_DAP3, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_DAP4, ?TEGRA_MUX_DAP4, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DDC, ? TEGRA_MUX_I2C2, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_DTA, ? TEGRA_MUX_VI, ? ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DTB, ? TEGRA_MUX_VI, ? ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DTC, ? TEGRA_MUX_VI, ? ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DTD, ? TEGRA_MUX_VI, ? ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DTE, ? TEGRA_MUX_VI, ? ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_DTF, ? TEGRA_MUX_I2C3, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_GMA, ? TEGRA_MUX_SDIO4, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_GMB, ? TEGRA_MUX_NAND, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_GMC, ? TEGRA_MUX_SFLASH, ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_GMD, ? TEGRA_MUX_SFLASH, ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_GME, ? TEGRA_MUX_GMI, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_GPU, ? TEGRA_MUX_UARTA, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_GPU7, ?TEGRA_MUX_RTCK, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_GPV, ? TEGRA_MUX_PCIE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_I2CP, ?TEGRA_MUX_I2C, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_IRRX, ?TEGRA_MUX_UARTB, ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_IRTX, ?TEGRA_MUX_UARTB, ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_KBCA, ?TEGRA_MUX_KBC, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_KBCB, ?TEGRA_MUX_KBC, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_KBCC, ?TEGRA_MUX_KBC, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_KBCD, ?TEGRA_MUX_KBC, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_KBCE, ?TEGRA_MUX_KBC, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_KBCF, ?TEGRA_MUX_KBC, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LCSN, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LD0, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD1, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD2, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD3, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD4, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD5, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD6, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD7, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD8, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD9, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD10, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD11, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD12, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD13, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD14, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD15, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD16, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LD17, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LDC, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LDI, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LHP0, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LHP1, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LHP2, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LHS, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LM0, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LM1, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LPP, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LPW0, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LPW1, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LPW2, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LSC0, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LSC1, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LSCK, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LSDA, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LSDI, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LSPI, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LVP0, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_LVP1, ?TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_LVS, ? TEGRA_MUX_DISPLAYA, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_OWC, ? TEGRA_MUX_RSVD2, ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_PMC, ? TEGRA_MUX_PWR_ON, ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_PTA, ? TEGRA_MUX_RSVD3, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_RM, ? ?TEGRA_MUX_I2C, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SDB, ? TEGRA_MUX_PWM, ? ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SDC, ? TEGRA_MUX_PWM, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SDD, ? TEGRA_MUX_PWM, ? ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SLXA, ?TEGRA_MUX_PCIE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SLXC, ?TEGRA_MUX_SDIO3, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SLXD, ?TEGRA_MUX_SDIO3, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SLXK, ?TEGRA_MUX_PCIE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_SPDI, ?TEGRA_MUX_SPDIF, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPDO, ?TEGRA_MUX_SPDIF, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIA, ?TEGRA_MUX_SPI2, ? ? ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIB, ?TEGRA_MUX_SPI2, ? ? ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIC, ?TEGRA_MUX_SPI2, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPID, ?TEGRA_MUX_SPI1, ? ? ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIE, ?TEGRA_MUX_SPI1, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIF, ?TEGRA_MUX_SPI1, ? ? ? ? ?TEGRA_PUPD_PULL_DOWN, ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIG, ?TEGRA_MUX_SPI2_ALT, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_SPIH, ?TEGRA_MUX_SPI2_ALT, ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UAA, ? TEGRA_MUX_ULPI, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UAB, ? TEGRA_MUX_ULPI, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UAC, ? TEGRA_MUX_RSVD2, ? ? ? ? TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UAD, ? TEGRA_MUX_IRDA, ? ? ? ? ?TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UCA, ? TEGRA_MUX_UARTC, ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UCB, ? TEGRA_MUX_UARTC, ? ? ? ? TEGRA_PUPD_PULL_UP, ? ? TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_UDA, ? TEGRA_MUX_ULPI, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_TRISTATE},
> + ? ? ? {TEGRA_PINGROUP_CK32, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_DDRC, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_PMCA, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_PMCB, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_PMCC, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_PMCD, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_PMCE, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_XM2C, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> + ? ? ? {TEGRA_PINGROUP_XM2D, ?TEGRA_MUX_NONE, ? ? ? ? ?TEGRA_PUPD_NORMAL, ? ? ?TEGRA_TRI_NORMAL},
> +};
> +
> +void __init trimslice_pinmux_init(void)
> +{
> + ? ? ? tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
> +}
> diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
> new file mode 100644
> index 0000000..ef233b2
> --- /dev/null
> +++ b/arch/arm/mach-tegra/board-trimslice.c
> @@ -0,0 +1,104 @@
> +/*
> + * arch/arm/mach-tegra/board-trimslice.c
> + *
> + * Copyright (C) 2011 CompuLab, Ltd.
> + * Author: Mike Rapoport <mike@compulab.co.il>
> + *
> + * Based on board-harmony.c
> + * Copyright (C) 2010 Google, Inc.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/serial_8250.h>
> +#include <linux/io.h>
> +
> +#include <asm/mach-types.h>
> +#include <asm/mach/arch.h>
> +#include <asm/setup.h>
> +
> +#include <mach/iomap.h>
> +
> +#include "board.h"
> +#include "clock.h"
> +
> +#include "board-trimslice.h"
> +
> +static struct plat_serial8250_port debug_uart_platform_data[] = {
> + ? ? ? {
> + ? ? ? ? ? ? ? .membase ? ? ? ?= IO_ADDRESS(TEGRA_UARTA_BASE),
> + ? ? ? ? ? ? ? .mapbase ? ? ? ?= TEGRA_UARTA_BASE,
> + ? ? ? ? ? ? ? .irq ? ? ? ? ? ?= INT_UARTA,
> + ? ? ? ? ? ? ? .flags ? ? ? ? ?= UPF_BOOT_AUTOCONF,
> + ? ? ? ? ? ? ? .iotype ? ? ? ? = UPIO_MEM,
> + ? ? ? ? ? ? ? .regshift ? ? ? = 2,
> + ? ? ? ? ? ? ? .uartclk ? ? ? ?= 216000000,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .flags ? ? ? ? ?= 0
> + ? ? ? }
> +};
> +
> +static struct platform_device debug_uart = {
> + ? ? ? .name ? = "serial8250",
> + ? ? ? .id ? ? = PLAT8250_DEV_PLATFORM,
> + ? ? ? .dev ? ?= {
> + ? ? ? ? ? ? ? .platform_data ?= debug_uart_platform_data,
> + ? ? ? },
> +};
> +
> +static struct platform_device *trimslice_devices[] __initdata = {
> + ? ? ? &debug_uart,
> +};
> +
> +static void __init tegra_trimslice_fixup(struct machine_desc *desc,
> + ? ? ? struct tag *tags, char **cmdline, struct meminfo *mi)
> +{
> + ? ? ? mi->nr_banks = 2;
> + ? ? ? mi->bank[0].start = PHYS_OFFSET;
> + ? ? ? mi->bank[0].size = 448 * SZ_1M;
> + ? ? ? mi->bank[1].start = SZ_512M;
> + ? ? ? mi->bank[1].size = SZ_512M;
> +}
> +
> +static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
> + ? ? ? /* name ? ? ? ? parent ? ? ? ? ?rate ? ? ? ? ? ?enabled */
> + ? ? ? { "uarta", ? ? ?"pll_p", ? ? ? ?216000000, ? ? ?true },
> + ? ? ? { NULL, ? ? ? ? NULL, ? ? ? ? ? 0, ? ? ? ? ? ? ?0},
> +};
> +
> +static int __init tegra_trimslice_pci_init(void)
> +{
> + ? ? ? return tegra_pcie_init(true, true);
> +}
> +subsys_initcall(tegra_trimslice_pci_init);
> +
> +static void __init tegra_trimslice_init(void)
> +{
> + ? ? ? tegra_common_init();
> +
> + ? ? ? tegra_clk_init_from_table(trimslice_clk_init_table);
> +
> + ? ? ? trimslice_pinmux_init();
> +
> + ? ? ? platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
> +}
> +
> +MACHINE_START(TRIMSLICE, "trimslice")
> + ? ? ? .boot_params ? ?= 0x00000100,
> + ? ? ? .fixup ? ? ? ? ?= tegra_trimslice_fixup,
> + ? ? ? .init_irq ? ? ? = tegra_init_irq,
> + ? ? ? .init_machine ? = tegra_trimslice_init,
> + ? ? ? .map_io ? ? ? ? = tegra_map_common_io,
> + ? ? ? .timer ? ? ? ? ?= &tegra_timer,
> +MACHINE_END
> diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h
> new file mode 100644
> index 0000000..16ec0f0
> --- /dev/null
> +++ b/arch/arm/mach-tegra/board-trimslice.h
> @@ -0,0 +1,22 @@
> +/*
> + * arch/arm/mach-tegra/board-trimslice.h
> + *
> + * Copyright (C) 2011 CompuLab, Ltd.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * 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 _MACH_TEGRA_BOARD_TRIMSLICE_H
> +#define _MACH_TEGRA_BOARD_TRIMSLICE_H
> +
> +void trimslice_pinmux_init(void);
> +
> +#endif
> --
> 1.7.3.1
Ack, the machine type is merged so I'll put this in for-next. Do you
want it enabled in tegra_defconfig?
^ permalink raw reply
* [PATCH] mx31: add support for the bugbase 1.3 from buglabs
From: Fabio Estevam @ 2011-02-11 2:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297372554-19527-1-git-send-email-GNUtoo@no-log.org>
Hi Denis,
On Thu, Feb 10, 2011 at 7:15 PM, Denis 'GNUtoo' Carikli
<GNUtoo@no-log.org> wrote:
> This work was based on bug-linux-2.6.30.patch that can be found
> ?in buglabs's svn here:
> ?svn://bugcamp.net/bug/branches/izzy/experimental
>
> Note that the hardware schematics and documentations can be obtained
> ?here: http://www.bugcommunity.com/wiki/index.php/BUGbase
>
> Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
> ---
> ?arch/arm/mach-mx3/Kconfig ? ? ? ? ? ?| ? ?9 +++
> ?arch/arm/mach-mx3/Makefile ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-mx3/mach-mx31bugbase.c | ? 97 ++++++++++++++++++++++++++++++++++
> ?3 files changed, 107 insertions(+), 0 deletions(-)
Please add an entry for this board at
arch/arm/plat-mxc/include/mach/uncompress.h
Regards,
Fabio Estevam
^ permalink raw reply
* [PATCH v2 2/5] OMAP: clockdomain: Arch specific funcs to handle deps
From: Paul Walmsley @ 2011-02-11 2:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1102101840200.21991@utopia.booyaka.com>
One other minor change; also modified the wkdep_src/sleepdep_src clkdm
resolve loops in clkdm_init() to avoid re-resolving clockdomains that have
already been looked up. Updated patch follows.
- Paul
^ permalink raw reply
* [PATCH 3/3] OMAP4: clockdomain: Add wkup/sleep dependency support
From: Paul Walmsley @ 2011-02-11 2:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297084631-27474-4-git-send-email-rnayak@ti.com>
Hi
On Mon, 7 Feb 2011, Rajendra Nayak wrote:
> Add OMAP4 platform specific implementation to support clkdm
> wkup and sleep dependencies a.k.a static dependencies.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
This patch had a similar bug to the OMAP2/3 variants; updated patch
follows -
- Paul
From: Rajendra Nayak <rnayak@ti.com>
Date: Thu, 10 Feb 2011 18:58:04 -0700
Subject: [PATCH] OMAP4: clockdomain: Add wkup/sleep dependency support
Add OMAP4 platform specific implementation to support clkdm
wkup and sleep dependencies a.k.a static dependencies.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[paul at pwsan.com: removed comment about PRM; zero-prefixed STATICDEP
register offset; fixed loop termination condition in
omap4_clkdm_clear_all_wkup_sleep_deps(); thanks to Kevin Hilman for finding
and helping fix this bug]
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/clockdomain44xx.c | 58 +++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/cm44xx.h | 1 +
2 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index c0ccc47..e6fd8da 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -12,8 +12,58 @@
* published by the Free Software Foundation.
*/
+#include <linux/kernel.h>
#include "clockdomain.h"
#include "cminst44xx.h"
+#include "cm44xx.h"
+
+static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
+ clkdm1->prcm_partition,
+ clkdm1->cm_inst, clkdm1->clkdm_offs +
+ OMAP4_CM_STATICDEP);
+ return 0;
+}
+
+static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
+ clkdm1->prcm_partition,
+ clkdm1->cm_inst, clkdm1->clkdm_offs +
+ OMAP4_CM_STATICDEP);
+ return 0;
+}
+
+static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
+ clkdm1->cm_inst, clkdm1->clkdm_offs +
+ OMAP4_CM_STATICDEP,
+ (1 << clkdm2->dep_bit));
+}
+
+static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
+{
+ struct clkdm_dep *cd;
+ u32 mask = 0;
+
+ for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+ if (!omap_chip_is(cd->omap_chip))
+ continue;
+
+ mask |= 1 << cd->clkdm->dep_bit;
+ atomic_set(&cd->wkdep_usecount, 0);
+ }
+
+ omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
+ clkdm->cm_inst, clkdm->clkdm_offs +
+ OMAP4_CM_STATICDEP);
+ return 0;
+}
static int omap4_clkdm_sleep(struct clockdomain *clkdm)
{
@@ -68,6 +118,14 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
}
struct clkdm_ops omap4_clkdm_operations = {
+ .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep,
+ .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
+ .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep,
+ .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps,
+ .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep,
+ .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep,
+ .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep,
+ .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps,
.clkdm_sleep = omap4_clkdm_sleep,
.clkdm_wakeup = omap4_clkdm_wakeup,
.clkdm_allow_idle = omap4_clkdm_allow_idle,
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 48fc3f4..0b87ec8 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -21,6 +21,7 @@
#include "cm.h"
#define OMAP4_CM_CLKSTCTRL 0x0000
+#define OMAP4_CM_STATICDEP 0x0004
/* Function prototypes */
# ifndef __ASSEMBLER__
--
1.7.2.3
^ permalink raw reply related
* [PATCH v2 2/5] OMAP: clockdomain: Arch specific funcs to handle deps
From: Paul Walmsley @ 2011-02-11 2:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1295956308-23860-3-git-send-email-rnayak@ti.com>
Hi
Kevin caught a couple of bugs in this code during his testing that were
unmasked by "[PATCH] OMAP2/3: PM: remove unnecessary wakeup/sleep
dependency clear":
http://www.spinics.net/lists/arm-kernel/msg112417.html
Symptoms here:
http://www.spinics.net/lists/arm-kernel/msg113991.html
On Tue, 25 Jan 2011, Rajendra Nayak wrote:
+static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+ struct clkdm_dep *cd;
+ u32 mask = 0;
+
+ for (cd = clkdm->wkdep_srcs; cd && cd->clkdm; cd++) {
cd->clkdm should be cd->clkdm_name; otherwise, any wkdep_src that does not
apply to the current chip will terminate the loop early (since cd->clkdm
will be NULL in that case)
> +static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
> +{
> + struct clkdm_dep *cd;
> + u32 mask = 0;
> +
> + for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm; cd++) {
Same thing here.
Updated patch follows,
- Paul
From: Rajendra Nayak <rnayak@ti.com>
Date: Tue, 8 Feb 2011 14:25:34 -0700
Subject: [PATCH] OMAP: clockdomain: Arch specific funcs to handle deps
Define the following architecture specific funtions for omap2/3
.clkdm_add_wkdep
.clkdm_del_wkdep
.clkdm_read_wkdep
.clkdm_clear_all_wkdeps
.clkdm_add_sleepdep
.clkdm_del_sleepdep
.clkdm_read_sleepdep
.clkdm_clear_all_sleepdeps
Convert the platform-independent framework to call these functions.
With this also move the clkdm lookups for all wkdep_srcs and
sleepdep_srcs at clkdm_init.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[paul at pwsan.com: fixed loop termination conditions in omap*_clkdm_clear_all_*();
thanks to Kevin Hilman for finding and helping fix those bugs]
Cc: Kevin Hilman <khilman@ti.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/Makefile | 2 +
arch/arm/mach-omap2/clockdomain.c | 160 +++++++++++-----------
arch/arm/mach-omap2/clockdomain.h | 6 +-
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 126 +++++++++++++++++
arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c | 9 +-
arch/arm/mach-omap2/io.c | 6 +-
6 files changed, 225 insertions(+), 84 deletions(-)
create mode 100644 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 1c0c2b0..6b2824d 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -102,8 +102,10 @@ obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common) \
# PRCM clockdomain control
obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \
+ clockdomain2xxx_3xxx.o \
clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \
+ clockdomain2xxx_3xxx.o \
clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \
clockdomains44xx_data.o
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index f70b06a..99005a7 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -308,6 +308,7 @@ void clkdm_init(struct clockdomain **clkdms,
struct clockdomain **c = NULL;
struct clockdomain *clkdm;
struct clkdm_autodep *autodep = NULL;
+ struct clkdm_dep *cd;
if (!custom_funcs)
WARN(1, "No custom clkdm functions registered\n");
@@ -333,7 +334,18 @@ void clkdm_init(struct clockdomain **clkdms,
else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
omap2_clkdm_deny_idle(clkdm);
+ for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+ if (!omap_chip_is(cd->omap_chip))
+ continue;
+ cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+ }
clkdm_clear_all_wkdeps(clkdm);
+
+ for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+ if (!omap_chip_is(cd->omap_chip))
+ continue;
+ cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+ }
clkdm_clear_all_sleepdeps(clkdm);
}
}
@@ -430,6 +442,7 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
{
struct clkdm_dep *cd;
+ int ret = 0;
if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
@@ -441,21 +454,26 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
return -EINVAL;
cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
- if (IS_ERR(cd)) {
+ if (IS_ERR(cd))
+ ret = PTR_ERR(cd);
+
+ if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
+ ret = -EINVAL;
+
+ if (ret) {
pr_debug("clockdomain: hardware cannot set/clear wake up of "
"%s when %s wakes up\n", clkdm1->name, clkdm2->name);
- return PTR_ERR(cd);
+ return ret;
}
if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
pr_debug("clockdomain: hardware will wake up %s when %s wakes "
"up\n", clkdm1->name, clkdm2->name);
- omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
- clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+ ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
}
- return 0;
+ return ret;
}
/**
@@ -471,6 +489,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
{
struct clkdm_dep *cd;
+ int ret = 0;
if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
@@ -482,21 +501,26 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
return -EINVAL;
cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
- if (IS_ERR(cd)) {
+ if (IS_ERR(cd))
+ ret = PTR_ERR(cd);
+
+ if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
+ ret = -EINVAL;
+
+ if (ret) {
pr_debug("clockdomain: hardware cannot set/clear wake up of "
"%s when %s wakes up\n", clkdm1->name, clkdm2->name);
- return PTR_ERR(cd);
+ return ret;
}
if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
pr_debug("clockdomain: hardware will no longer wake up %s "
"after %s wakes up\n", clkdm1->name, clkdm2->name);
- omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
- clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+ ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
}
- return 0;
+ return ret;
}
/**
@@ -516,6 +540,7 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
{
struct clkdm_dep *cd;
+ int ret = 0;
if (!clkdm1 || !clkdm2)
return -EINVAL;
@@ -527,15 +552,20 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
}
cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
- if (IS_ERR(cd)) {
+ if (IS_ERR(cd))
+ ret = PTR_ERR(cd);
+
+ if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
+ ret = -EINVAL;
+
+ if (ret) {
pr_debug("clockdomain: hardware cannot set/clear wake up of "
"%s when %s wakes up\n", clkdm1->name, clkdm2->name);
- return PTR_ERR(cd);
+ return ret;
}
/* XXX It's faster to return the atomic wkdep_usecount */
- return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
- (1 << clkdm2->dep_bit));
+ return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
}
/**
@@ -550,9 +580,6 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
*/
int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
{
- struct clkdm_dep *cd;
- u32 mask = 0;
-
if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
pr_err("clockdomain: %s: %s: not yet implemented\n",
clkdm->name, __func__);
@@ -562,21 +589,10 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
if (!clkdm)
return -EINVAL;
- for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
-
- if (!cd->clkdm && cd->clkdm_name)
- cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
- /* PRM accesses are slow, so minimize them */
- mask |= 1 << cd->clkdm->dep_bit;
- atomic_set(&cd->wkdep_usecount, 0);
- }
-
- omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+ if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
+ return -EINVAL;
- return 0;
+ return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
}
/**
@@ -594,31 +610,33 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
{
struct clkdm_dep *cd;
-
- if (!cpu_is_omap34xx())
- return -EINVAL;
+ int ret = 0;
if (!clkdm1 || !clkdm2)
return -EINVAL;
cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
- if (IS_ERR(cd)) {
+ if (IS_ERR(cd))
+ ret = PTR_ERR(cd);
+
+ if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
+ ret = -EINVAL;
+
+ if (ret) {
pr_debug("clockdomain: hardware cannot set/clear sleep "
"dependency affecting %s from %s\n", clkdm1->name,
clkdm2->name);
- return PTR_ERR(cd);
+ return ret;
}
if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
pr_debug("clockdomain: will prevent %s from sleeping if %s "
"is active\n", clkdm1->name, clkdm2->name);
- omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
- clkdm1->pwrdm.ptr->prcm_offs,
- OMAP3430_CM_SLEEPDEP);
+ ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
}
- return 0;
+ return ret;
}
/**
@@ -636,19 +654,23 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
{
struct clkdm_dep *cd;
-
- if (!cpu_is_omap34xx())
- return -EINVAL;
+ int ret = 0;
if (!clkdm1 || !clkdm2)
return -EINVAL;
cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
- if (IS_ERR(cd)) {
+ if (IS_ERR(cd))
+ ret = PTR_ERR(cd);
+
+ if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
+ ret = -EINVAL;
+
+ if (ret) {
pr_debug("clockdomain: hardware cannot set/clear sleep "
"dependency affecting %s from %s\n", clkdm1->name,
clkdm2->name);
- return PTR_ERR(cd);
+ return ret;
}
if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
@@ -656,12 +678,10 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
"sleeping if %s is active\n", clkdm1->name,
clkdm2->name);
- omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
- clkdm1->pwrdm.ptr->prcm_offs,
- OMAP3430_CM_SLEEPDEP);
+ ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
}
- return 0;
+ return ret;
}
/**
@@ -683,25 +703,27 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
{
struct clkdm_dep *cd;
-
- if (!cpu_is_omap34xx())
- return -EINVAL;
+ int ret = 0;
if (!clkdm1 || !clkdm2)
return -EINVAL;
cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
- if (IS_ERR(cd)) {
+ if (IS_ERR(cd))
+ ret = PTR_ERR(cd);
+
+ if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
+ ret = -EINVAL;
+
+ if (ret) {
pr_debug("clockdomain: hardware cannot set/clear sleep "
"dependency affecting %s from %s\n", clkdm1->name,
clkdm2->name);
- return PTR_ERR(cd);
+ return ret;
}
/* XXX It's faster to return the atomic sleepdep_usecount */
- return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
- OMAP3430_CM_SLEEPDEP,
- (1 << clkdm2->dep_bit));
+ return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
}
/**
@@ -716,31 +738,13 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
*/
int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
{
- struct clkdm_dep *cd;
- u32 mask = 0;
-
- if (!cpu_is_omap34xx())
- return -EINVAL;
-
if (!clkdm)
return -EINVAL;
- for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
-
- if (!cd->clkdm && cd->clkdm_name)
- cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
- /* PRM accesses are slow, so minimize them */
- mask |= 1 << cd->clkdm->dep_bit;
- atomic_set(&cd->sleepdep_usecount, 0);
- }
-
- omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
- OMAP3430_CM_SLEEPDEP);
+ if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
+ return -EINVAL;
- return 0;
+ return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
}
/**
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 71ad265..90b6d6a 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -176,7 +176,11 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm);
int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
-extern void __init omap2_clockdomains_init(void);
+extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap3xxx_clockdomains_init(void);
extern void __init omap44xx_clockdomains_init(void);
+extern struct clkdm_ops omap2_clkdm_operations;
+extern struct clkdm_ops omap3_clkdm_operations;
+
#endif
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
new file mode 100644
index 0000000..38dd903
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -0,0 +1,126 @@
+/*
+ * OMAP2 and OMAP3 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <plat/prcm.h>
+#include "prm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cm-regbits-34xx.h"
+#include "clockdomain.h"
+
+static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+ clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+ return 0;
+}
+
+static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+ clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+ return 0;
+}
+
+static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+ PM_WKDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+ struct clkdm_dep *cd;
+ u32 mask = 0;
+
+ for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+ if (!omap_chip_is(cd->omap_chip))
+ continue;
+
+ /* PRM accesses are slow, so minimize them */
+ mask |= 1 << cd->clkdm->dep_bit;
+ atomic_set(&cd->wkdep_usecount, 0);
+ }
+
+ omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+ PM_WKDEP);
+ return 0;
+}
+
+static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+ clkdm1->pwrdm.ptr->prcm_offs,
+ OMAP3430_CM_SLEEPDEP);
+ return 0;
+}
+
+static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+ clkdm1->pwrdm.ptr->prcm_offs,
+ OMAP3430_CM_SLEEPDEP);
+ return 0;
+}
+
+static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
+ struct clockdomain *clkdm2)
+{
+ return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+ OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+ struct clkdm_dep *cd;
+ u32 mask = 0;
+
+ for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+ if (!omap_chip_is(cd->omap_chip))
+ continue;
+
+ /* PRM accesses are slow, so minimize them */
+ mask |= 1 << cd->clkdm->dep_bit;
+ atomic_set(&cd->sleepdep_usecount, 0);
+ }
+ omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+ OMAP3430_CM_SLEEPDEP);
+ return 0;
+}
+
+struct clkdm_ops omap2_clkdm_operations = {
+ .clkdm_add_wkdep = omap2_clkdm_add_wkdep,
+ .clkdm_del_wkdep = omap2_clkdm_del_wkdep,
+ .clkdm_read_wkdep = omap2_clkdm_read_wkdep,
+ .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
+};
+
+struct clkdm_ops omap3_clkdm_operations = {
+ .clkdm_add_wkdep = omap2_clkdm_add_wkdep,
+ .clkdm_del_wkdep = omap2_clkdm_del_wkdep,
+ .clkdm_read_wkdep = omap2_clkdm_read_wkdep,
+ .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
+ .clkdm_add_sleepdep = omap3_clkdm_add_sleepdep,
+ .clkdm_del_sleepdep = omap3_clkdm_del_sleepdep,
+ .clkdm_read_sleepdep = omap3_clkdm_read_sleepdep,
+ .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps,
+};
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
index 8cab07a..f85de72 100644
--- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -854,7 +854,12 @@ static struct clockdomain *clockdomains_omap2[] __initdata = {
NULL,
};
-void __init omap2_clockdomains_init(void)
+void __init omap2xxx_clockdomains_init(void)
{
- clkdm_init(clockdomains_omap2, clkdm_autodeps, NULL);
+ clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
+}
+
+void __init omap3xxx_clockdomains_init(void)
+{
+ clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index c203204..89cbba2 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -337,15 +337,15 @@ void __init omap2_init_common_infrastructure(void)
if (cpu_is_omap242x()) {
omap2xxx_powerdomains_init();
- omap2_clockdomains_init();
+ omap2xxx_clockdomains_init();
omap2420_hwmod_init();
} else if (cpu_is_omap243x()) {
omap2xxx_powerdomains_init();
- omap2_clockdomains_init();
+ omap2xxx_clockdomains_init();
omap2430_hwmod_init();
} else if (cpu_is_omap34xx()) {
omap3xxx_powerdomains_init();
- omap2_clockdomains_init();
+ omap3xxx_clockdomains_init();
omap3xxx_hwmod_init();
} else if (cpu_is_omap44xx()) {
omap44xx_powerdomains_init();
--
1.7.2.3
^ permalink raw reply related
* [GIT PULL] Samsung fixes for 2.6.38-rc5
From: Kukjin Kim @ 2011-02-11 1:56 UTC (permalink / raw)
To: linux-arm-kernel
Hi Linus,
Please pull Samsung fixes from:
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
s5p-fixes-for-linus
These things are for small fix on 2.6.38-rc5.
If any problems, please let me know.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
The following changes since commit 100b33c8bd8a3235fd0b7948338d6cbb3db3c63d:
Linux 2.6.38-rc4 (2011-02-07 16:03:17 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
s5p-fixes-for-linus
Kukjin Kim (1):
ARM: S5PV310: Cleanup System MMU
Mark Brown (1):
ARM: SAMSUNG: Ensure struct sys_device is declared in plat/pm.h
Thomas Abraham (1):
ARM: S5PV310: Add support System MMU on SMDKV310
arch/arm/mach-s5pv310/Kconfig | 1 +
arch/arm/mach-s5pv310/include/mach/map.h | 2 --
arch/arm/mach-s5pv310/include/mach/sysmmu.h | 5 ++++-
arch/arm/plat-s5p/Kconfig | 24 ++++++++----------------
arch/arm/plat-s5p/Makefile | 2 +-
arch/arm/plat-s5p/include/plat/sysmmu.h | 23 -----------------------
arch/arm/plat-s5p/sysmmu.c | 4 +---
arch/arm/plat-samsung/include/plat/pm.h | 2 ++
8 files changed, 17 insertions(+), 46 deletions(-)
^ permalink raw reply
* [PATCH v4 10/15] ARM: tegra: iomap: Add missing devices, fix use of SZ_8, SZ_64
From: Colin Cross @ 2011-02-11 1:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <74CDBE0F657A3D45AFBB94109FB122FF0310F60414@HQMAIL01.nvidia.com>
On Thu, Feb 10, 2011 at 8:45 AM, Stephen Warren <swarren@nvidia.com> wrote:
> Colin Cross wrote at Wednesday, February 09, 2011 11:43 PM:
>>
>> From: Gary King <gking@nvidia.com>
>>
>> Adds gart, hdmi, avp, host1x, and pwm controllers to mach/iomap.h
>> There is no SZ_8 or SZ_64, replace them with constants
>
> Can't we add those SZ_* constants?
Sure, you already added SZ_64, and nothing depends on the SZ_8 defines
right now, so I'll drop that part of the change and send a patch that
completes the SZ_* defines.
^ permalink raw reply
* [PATCH] OMAP2/3: PM: remove unnecessary wakeup/sleep dependency clear
From: Paul Walmsley @ 2011-02-11 1:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1102101617200.21991@utopia.booyaka.com>
On Thu, 10 Feb 2011, Paul Walmsley wrote:
> On Thu, 10 Feb 2011, Kevin Hilman wrote:
>
> > While testing, I found out this patch breaks suspend/resume and idle on
> > at least 34xx.
> >
> > A first suspend/resume works fine, but on subsequent ones SGX
> > powerdomain does not hit retention (and thus CORE powerdomain does not
> > either....
>
> ...
>
> > Simply adding back the above 5 lines (the SGX ones) gets things working
> > again, which suggests something isn't quite right with SGX, but I
> > haven't found the exact reason yet.
>
> Thanks for the report, I will take a look.
Kevin and I did some debugging on this. It turns out that there is a bug
in the recent clockdomain abstraction code in the git.pwsan.com
integration branch that caused the underlying problem. Will follow up
with comments on the threads of the original patches.
Kevin is planning to keep the patch under discussion in this thread in
his 2.6.39 queue...
- Paul
^ permalink raw reply
* [PATCH] arm: update gitignore file
From: rklein at nvidia.com @ 2011-02-11 1:26 UTC (permalink / raw)
To: linux-arm-kernel
From: Rhyland Klein <rklein@nvidia.com>
Updating the .gitignore file to ignore 3 files that are always created in
manual builds to cleanup git status results.
Signed-off-by: Rhyland Klein <rklein@nvidia.com>
---
arch/arm/boot/compressed/.gitignore | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index ab204db..c52a6dd 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1,3 +1,6 @@
font.c
piggy.gz
vmlinux.lds
+lib1funcs.S
+piggy.gzip
+vmlinux
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/7] mmc: mxs-mmc: add mmc host driver for i.MX23/28
From: Shawn Guo @ 2011-02-11 0:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201102042126.52701.arnd@arndb.de>
Hi Arnd,
Sorry for the late response. It really took me some time to address
your comments, especially about using mmc core completion to save
the one in the driver.
On Fri, Feb 04, 2011 at 09:26:52PM +0100, Arnd Bergmann wrote:
> On Saturday 05 February 2011 03:18:41 Shawn Guo wrote:
> > This adds the mmc host driver for Freescale MXS-based SoC i.MX23/28.
> > The driver calls into mxs-dma via generic dmaengine api for both pio
> > and data transfer.
>
> Hi Shawn,
>
> The driver looks good coding-style wise, but it's my impression that
> you do some thing less efficient or more complex than necessary. To
> be more specific:
Thanks for the review and comments.
>
> > +struct mxs_mmc_host {
>
> It seems you have a number of members in this struct that only
> add confusion but are not actually needed, so just get rid of
> them:
>
> > + struct device *dev;
>
> mmc_host->parent ?
>
OK. Will replace all host->dev with mmc_dev(host->mmc) to save it.
> > + struct resource *res;
> > + struct resource *dma_res;
> > + struct clk *clk;
>
> are visible in the parent.
>
It seems this is a generally used approach, seen in mxcmmc and pxamci.
> > + unsigned int version;
>
> unused
>
#define ssp_is_old() (host->version < SSP_VERSION_LATEST)
> > + struct mmc_command *cmd;
>
> mrq->cmd ?
>
Generally used approach again.
> > + struct mmc_data *data;
>
> unused
>
Will be used in v2.
> > + unsigned present:1;
>
> Your card detection by polling through this variable is
> really bad for power management. Is there really no interrupt
> that gets triggered when installing or removing a card?
>
Good point. Will try to use interrupt.
> Also, please try to avoid bit fields. 'bool' variables are
> fine for flags.
>
> > + unsigned int dma_dir;
>
> not needed, a local variable would be just fine.
>
Will be needed in v2.
> > + struct mxs_dma_data dma_data;
>
> Why do you need host specific DMA structures? Please stick to
> the generic dma-engine API if possible.
>
I'm sticking to the generic dmaengine api. The mxs dma hardware
has separate irq line for every single dma channel, which needs to
be told by client driver.
> > + struct completion done;
>
> The mmc layer already comes with a generic completion that you
> can and should use, mainly for performance reasons. Adding your
> own completion forces every single request to go through an
> additional context switch, compared to just returning from
> the request function when you have scheduled the command, and
> calling mmc_request_done from the interrupt handler.
>
I'm rewriting some amount of codes to address it.
> > + u32 status;
>
> Won't be needed any more when you complete the requests at
> interrupt time.
>
Yes.
> > +#define SSP_PIO_NUM 3
> > +static u32 ssp_pio_words[SSP_PIO_NUM];
>
> I don't think this is safe: This is a global variable, so if you have
> multiple controllers, they would access the same data. Why not integrate
> it into the host data structure?
>
Sounds sane.
> > +
> > +static void mxs_mmc_reset(struct mxs_mmc_host *host)
> > +{
> > + u32 ctrl0, ctrl1;
> > +
> > + mxs_reset_block(host->base);
> > +
> > + ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
> > + ctrl1 = BF_SSP(0x3, SSP_CTRL1_SSP_MODE) |
> > + BF_SSP(0x7, SSP_CTRL1_WORD_LENGTH) |
> > + BM_SSP_CTRL1_DMA_ENABLE |
> > + BM_SSP_CTRL1_POLARITY |
> > + BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
> > + BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
> > + BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
> > + BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
> > + BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
> > +
> > + __raw_writel(BF_SSP(0xffff, SSP_TIMING_TIMEOUT) |
> > + BF_SSP(2, SSP_TIMING_CLOCK_DIVIDE) |
> > + BF_SSP(0, SSP_TIMING_CLOCK_RATE),
> > + host->base + HW_SSP_TIMING);
>
> Please use proper MMIO accessors like writel() and readl() that
> are known to be safe here. The __raw_ variants are not really
> meant for device drivers, which can lead to very subtle bugs.
>
OK. __mxs_clrl/setl will also be replaced by writel with set/clr
register offset, so that code looks more consistent.
> > +static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
> > +{
> > + struct mxs_mmc_host *host = dev_id;
> > + u32 stat;
> > +
> > + stat = __raw_readl(host->base + HW_SSP_CTRL1);
> > + __mxs_clrl(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1);
> > +
> > + if (host->cmd && (stat & MXS_MMC_ERR_BITS))
> > + host->status = __raw_readl(host->base + HW_SSP_STATUS);
> > +
> > + if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
> > + mmc_signal_sdio_irq(host->mmc);
> > +
> > + return IRQ_HANDLED;
> > +}
>
> You use spin_lock_irqsave in mxs_mmc_enable_sdio_irq, but don't
> actually use the spinlock in the interrupt handler. This means
> that either your interrupt handler is broken because it doesn't
> lock, or that you don't actually need the _irqsave part.
>
I do not understand this one. I'm seeing mxcmmc and pxamci use
spin_lock_irqsave/irqrestore in the similar way.
> > +static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> > +{
> > + struct mxs_mmc_host *host = mmc_priv(mmc);
> > +
> > + BUG_ON(host->mrq != NULL);
> > +
> > + host->mrq = mrq;
> > + mxs_mmc_start_cmd(host, mrq->cmd);
> > +
> > + if (mrq->data && mrq->data->stop) {
> > + dev_dbg(host->dev, "Stop opcode is %u\n",
> > + mrq->data->stop->opcode);
> > + mxs_mmc_start_cmd(host, mrq->data->stop);
> > + }
> > +
> > + host->mrq = NULL;
> > + mmc_request_done(mmc, mrq);
> > +}
>
> As mentioned above, the mmc_request_done() shouldn't really be needed here,
> it's more efficient to do it in the interrupt handler.
>
OK.
Regards,
Shawn
^ permalink raw reply
* [PATCH v2 5/5] ARM: omap3: Thumb-2 compatibility for sleep34xx.S
From: Kevin Hilman @ 2011-02-11 0:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87d3mzh6vq.fsf@ti.com>
Kevin Hilman <khilman@ti.com> writes:
> Dave Martin <dave.martin@linaro.org> writes:
>
>> * Use BSYM() to get the correct Thumb branch address
>> for adr <Rd>, <label>
>>
>> * Fix an out-of-range ADR when building for ARM
>>
>> * Correctly call es3_sdrc_fix as Thumb when copied to SRAM.
>>
>> * Remove deprecated/undefined PC-relative stores
>>
>> * Add the required ENDPROC() directive for each ENTRY().
>>
>> * .align before data words
>>
>> Signed-off-by: Dave Martin <dave.martin@linaro.org>
>
> I'm attempting to test this series with OMAP PM, but some changes here
> don't compile for me.
>
> My toolchain is: gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50)
>
> First, I merged your arm/omap-thumb2+merged branch with my pm branch
> from git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git
Sorry for the confusion, this patch should've been in reply to your v4
version, since I merged with your 'arm/omap-thumb2+merged' branch from
today.
Kevin
^ permalink raw reply
* [patch 47/75] arm: tegra: Remove unused function which fiddles with irq_desc
From: Colin Cross @ 2011-02-10 23:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110210223258.848294582@linutronix.de>
On Thu, Feb 10, 2011 at 3:37 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> These functions are unused and in the way of cleanups in the core
> code. If you have special requirements vs. irqs and PM then please
> talk to me. Access to the generic core internals is going away.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Colin Cross <ccross@android.com>
> Cc: linux-tegra at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> ?arch/arm/mach-tegra/gpio.c | ? 63 ---------------------------------------------
> ?arch/arm/mach-tegra/irq.c ?| ? 58 -----------------------------------------
> ?2 files changed, 121 deletions(-)
>
> Index: linux-2.6-tip/arch/arm/mach-tegra/gpio.c
> ===================================================================
> --- linux-2.6-tip.orig/arch/arm/mach-tegra/gpio.c
> +++ linux-2.6-tip/arch/arm/mach-tegra/gpio.c
> @@ -253,69 +253,6 @@ static void tegra_gpio_irq_handler(unsig
> ?}
>
> ?#ifdef CONFIG_PM
> -void tegra_gpio_resume(void)
> -{
> - ? ? ? unsigned long flags;
> - ? ? ? int b, p, i;
> -
> - ? ? ? local_irq_save(flags);
> -
> - ? ? ? for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
> - ? ? ? ? ? ? ? struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
> -
> - ? ? ? ? ? ? ? for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
> - ? ? ? ? ? ? ? ? ? ? ? unsigned int gpio = (b<<5) | (p<<3);
> - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->out[p], GPIO_OUT(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->oe[p], GPIO_OE(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
> - ? ? ? ? ? ? ? }
> - ? ? ? }
> -
> - ? ? ? local_irq_restore(flags);
> -
> - ? ? ? for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
> - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i);
> - ? ? ? ? ? ? ? if (!desc || (desc->status & IRQ_WAKEUP))
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? enable_irq(i);
> - ? ? ? }
> -}
> -
> -void tegra_gpio_suspend(void)
> -{
> - ? ? ? unsigned long flags;
> - ? ? ? int b, p, i;
> -
> - ? ? ? for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
> - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i);
> - ? ? ? ? ? ? ? if (!desc)
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? if (desc->status & IRQ_WAKEUP) {
> - ? ? ? ? ? ? ? ? ? ? ? int gpio = i - INT_GPIO_BASE;
> - ? ? ? ? ? ? ? ? ? ? ? pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? disable_irq(i);
> - ? ? ? }
> -
> - ? ? ? local_irq_save(flags);
> - ? ? ? for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
> - ? ? ? ? ? ? ? struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
> -
> - ? ? ? ? ? ? ? for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
> - ? ? ? ? ? ? ? ? ? ? ? unsigned int gpio = (b<<5) | (p<<3);
> - ? ? ? ? ? ? ? ? ? ? ? bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? bank->out[p] = __raw_readl(GPIO_OUT(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? bank->oe[p] = __raw_readl(GPIO_OE(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
> - ? ? ? ? ? ? ? ? ? ? ? bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
> - ? ? ? ? ? ? ? }
> - ? ? ? }
> - ? ? ? local_irq_restore(flags);
> -}
> -
> ?static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
> ?{
> ? ? ? ?struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
> Index: linux-2.6-tip/arch/arm/mach-tegra/irq.c
> ===================================================================
> --- linux-2.6-tip.orig/arch/arm/mach-tegra/irq.c
> +++ linux-2.6-tip/arch/arm/mach-tegra/irq.c
> @@ -111,61 +111,3 @@ void __init tegra_init_irq(void)
> ? ? ? ? ? ? ? ?set_irq_flags(i, IRQF_VALID);
> ? ? ? ?}
> ?}
> -
> -#ifdef CONFIG_PM
> -static u32 cop_ier[PPI_NR];
> -static u32 cpu_ier[PPI_NR];
> -static u32 cpu_iep[PPI_NR];
> -
> -void tegra_irq_suspend(void)
> -{
> - ? ? ? unsigned long flags;
> - ? ? ? int i;
> -
> - ? ? ? for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
> - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i);
> - ? ? ? ? ? ? ? if (!desc)
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? if (desc->status & IRQ_WAKEUP) {
> - ? ? ? ? ? ? ? ? ? ? ? pr_debug("irq %d is wakeup\n", i);
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? disable_irq(i);
> - ? ? ? }
> -
> - ? ? ? local_irq_save(flags);
> - ? ? ? for (i = 0; i < PPI_NR; i++) {
> - ? ? ? ? ? ? ? void __iomem *ictlr = ictlr_to_virt(i);
> - ? ? ? ? ? ? ? cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
> - ? ? ? ? ? ? ? cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
> - ? ? ? ? ? ? ? cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
> - ? ? ? ? ? ? ? writel(~0, ictlr + ICTLR_COP_IER_CLR);
> - ? ? ? }
> - ? ? ? local_irq_restore(flags);
> -}
> -
> -void tegra_irq_resume(void)
> -{
> - ? ? ? unsigned long flags;
> - ? ? ? int i;
> -
> - ? ? ? local_irq_save(flags);
> - ? ? ? for (i = 0; i < PPI_NR; i++) {
> - ? ? ? ? ? ? ? void __iomem *ictlr = ictlr_to_virt(i);
> - ? ? ? ? ? ? ? writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
> - ? ? ? ? ? ? ? writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
> - ? ? ? ? ? ? ? writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
> - ? ? ? ? ? ? ? writel(0, ictlr + ICTLR_COP_IEP_CLASS);
> - ? ? ? ? ? ? ? writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
> - ? ? ? ? ? ? ? writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
> - ? ? ? }
> - ? ? ? local_irq_restore(flags);
> -
> - ? ? ? for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
> - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i);
> - ? ? ? ? ? ? ? if (!desc || (desc->status & IRQ_WAKEUP))
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? enable_irq(i);
> - ? ? ? }
> -}
> -#endif
>
>
>
Acked-by: Colin Cross <ccross@android.com>
These functions are clearly incorrectly accessing IRQ internals. I
have replacements that have been posted for review that properly track
the wakeup state using set_wake, but they are held up on some
unrelated PM changes.
^ permalink raw reply
* [PATCH] msm: gpiomux: decentralize and modularize gpiomux init.
From: Rohit Vaswani @ 2011-02-10 23:45 UTC (permalink / raw)
To: linux-arm-kernel
Reorganize gpiomux initialization as follows:
- remove the global static gpiomux configuration table;
- remove the universal initcall from gpiomux.c;
- add a public function, msm_gpiomux_init, which installs
a provided gpiomux config table and runs the code
previously run by the universal init.
- Add initcalls in each of the board-specific gpiomux files.
This decentralization of gpiomux init improves its flexibility
by allowing board-specific runtime code to select and/or
assemble the correct gpiomux-config table and send it to the
gpiomux framework for initialization. Rather than having a single
static array which must meet all needs.
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
---
arch/arm/mach-msm/board-msm7x27.c | 17 ++++++++-
arch/arm/mach-msm/board-msm7x30.c | 51 ++++++++++++++++++--------
arch/arm/mach-msm/board-msm8x60.c | 15 +++++++-
arch/arm/mach-msm/board-qsd8x50.c | 33 ++++++++++++++----
arch/arm/mach-msm/gpiomux-v1.h | 10 +-----
arch/arm/mach-msm/gpiomux-v2.h | 4 +--
arch/arm/mach-msm/gpiomux.c | 70
+++++++++++++++++++++++++++++--------
arch/arm/mach-msm/gpiomux.h | 30 ++++++++++-----
8 files changed, 167 insertions(+), 63 deletions(-)
diff --git a/arch/arm/mach-msm/board-msm7x27.c
b/arch/arm/mach-msm/board-msm7x27.c
index 16d7580..64f29f6 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -75,6 +75,19 @@ static struct platform_device *devices[] __initdata = {
extern struct sys_timer msm_timer;
+static int __init gpiomux_init(void)
+{
+ int rc;
+
+ rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ if (rc) {
+ printk(KERN_ERR "msm_gpiomux_init failed - %n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static void __init msm7x2x_init_irq(void)
{
msm_init_irq();
@@ -85,6 +98,8 @@ static void __init msm7x2x_init(void)
if (socinfo_init() < 0)
BUG();
+ gpiomux_init();
+
if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) {
smc91x_resources[0].start = 0x98000300;
smc91x_resources[0].end = 0x980003ff;
diff --git a/arch/arm/mach-msm/board-msm7x30.c
b/arch/arm/mach-msm/board-msm7x30.c
index dc9fac1..7b4c414 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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
@@ -39,6 +39,9 @@
#include "gpiomux.h"
#include "proc_comm.h"
+#define UART2_SUSPENDED (GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |\
+ GPIOMUX_FUNC_2 | GPIOMUX_VALID)
+
extern struct sys_timer msm_timer;
static int hsusb_phy_init_seq[] = {
@@ -53,25 +56,23 @@ static struct msm_otg_platform_data msm_otg_pdata = {
.otg_control = OTG_PHY_CONTROL,
};
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
- [49] = { /* UART2 RFR */
- .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
- GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+struct msm_gpiomux_config msm7x30_uart2_configs[] __initdata = {
+ {
+ .gpio = 49, /* UART2 RFR */
+ .suspended = UART2_SUSPENDED,
},
- [50] = { /* UART2 CTS */
- .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
- GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ {
+ .gpio = 50, /* UART2 CTS */
+ .suspended = UART2_SUSPENDED,
},
- [51] = { /* UART2 RX */
- .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
- GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ {
+ .gpio = 51, /* UART2 RX */
+ .suspended = UART2_SUSPENDED,
},
- [52] = { /* UART2 TX */
- .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
- GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ {
+ .gpio = 52, /* UART2 TX */
+ .suspended = UART2_SUSPENDED,
},
-#endif
};
static struct platform_device *devices[] __initdata = {
@@ -84,6 +85,22 @@ static struct platform_device *devices[] __initdata = {
&msm_device_hsusb_host,
};
+static int __init gpiomux_init(void)
+{
+ int rc;
+
+ rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ if (rc) {
+ printk(KERN_ERR "msm_gpiomux_init failed - %d\n", rc);
+ return rc;
+ }
+
+ msm_gpiomux_install(msm7x30_uart2_configs,
+ ARRAY_SIZE(msm7x30_uart2_configs));
+ return 0;
+
+}
+
static void __init msm7x30_init_irq(void)
{
msm_init_irq();
@@ -95,6 +112,8 @@ static void __init msm7x30_init(void)
msm_device_hsusb.dev.parent = &msm_device_otg.dev;
msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
+ gpiomux_init();
+
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-msm/board-msm8x60.c
b/arch/arm/mach-msm/board-msm8x60.c
index 6c0b868..a3a28f0 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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
@@ -29,8 +29,18 @@
#include <mach/msm_iomap.h>
#include "gpiomux.h"
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {};
+static int __init gpiomux_init(void)
+{
+ int rc;
+
+ rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ if (rc) {
+ printk(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
+ return rc;
+ }
+ return 0;
+}
static void __init msm8x60_map_io(void)
{
@@ -65,6 +75,7 @@ static void __init msm8x60_init_irq(void)
static void __init msm8x60_init(void)
{
+ gpiomux_init();
}
MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
diff --git a/arch/arm/mach-msm/board-qsd8x50.c
b/arch/arm/mach-msm/board-qsd8x50.c
index b63b7c4..33ab1fe 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -38,16 +38,19 @@
#include "devices.h"
#include "gpiomux.h"
+#define UART3_SUSPENDED (GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |\
+ GPIOMUX_FUNC_1 | GPIOMUX_VALID)
+
extern struct sys_timer msm_timer;
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
- [86] = { /* UART3 RX */
- .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
- GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+struct msm_gpiomux_config qsd8x50_uart3_configs[] __initdata = {
+ {
+ .gpio = 86, /* UART3 RX */
+ .suspended = UART3_SUSPENDED,
},
- [87] = { /* UART3 TX */
- .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
- GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+ {
+ .gpio = 87, /* UART3 TX */
+ .suspended = UART3_SUSPENDED,
},
};
@@ -169,6 +172,21 @@ static struct msm_mmc_platform_data
qsd8x50_sdc1_data = {
.gpio_data = &sdc1_gpio,
};
+static int __init gpiomux_init(void)
+{
+ int rc;
+
+ rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ if (rc) {
+ printk(KERN_ERR "msm_gpiomux_init failed - %d\n", rc);
+ return rc;
+ }
+
+ msm_gpiomux_install(qsd8x50_uart3_configs,
+ ARRAY_SIZE(qsd8x50_uart3_configs));
+ return 0;
+}
+
static void __init qsd8x50_init_mmc(void)
{
if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa())
@@ -202,6 +220,7 @@ static void __init qsd8x50_init(void)
msm_device_otg.dev.platform_data = &msm_otg_pdata;
msm_device_hsusb.dev.parent = &msm_device_otg.dev;
msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
+ gpiomux_init();
platform_add_devices(devices, ARRAY_SIZE(devices));
qsd8x50_init_mmc();
}
diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h
index 71d86fe..4d545f7 100644
--- a/arch/arm/mach-msm/gpiomux-v1.h
+++ b/arch/arm/mach-msm/gpiomux-v1.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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
@@ -17,14 +17,6 @@
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
-#if defined(CONFIG_ARCH_MSM7X30)
-#define GPIOMUX_NGPIOS 182
-#elif defined(CONFIG_ARCH_QSD8X50)
-#define GPIOMUX_NGPIOS 165
-#else
-#define GPIOMUX_NGPIOS 133
-#endif
-
typedef u32 gpiomux_config_t;
enum {
diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h
index 3bf10e7..2840de9 100644
--- a/arch/arm/mach-msm/gpiomux-v2.h
+++ b/arch/arm/mach-msm/gpiomux-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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
@@ -17,8 +17,6 @@
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
-#define GPIOMUX_NGPIOS 173
-
typedef u16 gpiomux_config_t;
enum {
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 53af21a..b4a6fd6 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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
@@ -15,20 +15,31 @@
* 02110-1301, USA.
*/
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/spinlock.h>
#include "gpiomux.h"
+struct msm_gpiomux_rec {
+ gpiomux_config_t active;
+ gpiomux_config_t suspended;
+ int ref;
+};
static DEFINE_SPINLOCK(gpiomux_lock);
+static struct msm_gpiomux_rec *msm_gpiomux_recs;
+static unsigned msm_gpiomux_ngpio;
int msm_gpiomux_write(unsigned gpio,
gpiomux_config_t active,
gpiomux_config_t suspended)
{
- struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ struct msm_gpiomux_rec *cfg = msm_gpiomux_recs + gpio;
unsigned long irq_flags;
gpiomux_config_t setting;
- if (gpio >= GPIOMUX_NGPIOS)
+ if (!msm_gpiomux_recs)
+ return -EFAULT;
+
+ if (gpio >= msm_gpiomux_ngpio)
return -EINVAL;
spin_lock_irqsave(&gpiomux_lock, irq_flags);
@@ -50,10 +61,13 @@ EXPORT_SYMBOL(msm_gpiomux_write);
int msm_gpiomux_get(unsigned gpio)
{
- struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ struct msm_gpiomux_rec *cfg = msm_gpiomux_recs + gpio;
unsigned long irq_flags;
- if (gpio >= GPIOMUX_NGPIOS)
+ if (!msm_gpiomux_recs)
+ return -EFAULT;
+
+ if (gpio >= msm_gpiomux_ngpio)
return -EINVAL;
spin_lock_irqsave(&gpiomux_lock, irq_flags);
@@ -66,10 +80,13 @@ EXPORT_SYMBOL(msm_gpiomux_get);
int msm_gpiomux_put(unsigned gpio)
{
- struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ struct msm_gpiomux_rec *cfg = msm_gpiomux_recs + gpio;
unsigned long irq_flags;
- if (gpio >= GPIOMUX_NGPIOS)
+ if (!msm_gpiomux_recs)
+ return -EFAULT;
+
+ if (gpio >= msm_gpiomux_ngpio)
return -EINVAL;
spin_lock_irqsave(&gpiomux_lock, irq_flags);
@@ -81,16 +98,39 @@ int msm_gpiomux_put(unsigned gpio)
}
EXPORT_SYMBOL(msm_gpiomux_put);
-static int __init gpiomux_init(void)
+int msm_gpiomux_init(size_t ngpio)
+{
+ if (!ngpio)
+ return -EINVAL;
+
+ if (msm_gpiomux_recs)
+ return -EPERM;
+
+ msm_gpiomux_recs = kzalloc(sizeof(struct msm_gpiomux_rec) * ngpio,
+ GFP_KERNEL);
+ if (!msm_gpiomux_recs)
+ return -ENOMEM;
+
+ msm_gpiomux_ngpio = ngpio;
+
+ return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_init);
+
+void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned
nconfigs)
{
unsigned n;
+ int rc;
+
+ if (!msm_gpiomux_recs)
+ return;
- for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
- msm_gpiomux_configs[n].ref = 0;
- if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
- continue;
- __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
+ for (n = 0; n < nconfigs; ++n) {
+ rc = msm_gpiomux_write(configs[n].gpio,
+ configs[n].active,
+ configs[n].suspended);
+ if (rc)
+ pr_err("%s: write failure: %d\n", __func__, rc);
}
- return 0;
}
-postcore_initcall(gpiomux_init);
+EXPORT_SYMBOL(msm_gpiomux_install);
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
index b178d9c..cc2e58a 100644
--- a/arch/arm/mach-msm/gpiomux.h
+++ b/arch/arm/mach-msm/gpiomux.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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
@@ -37,17 +37,16 @@
* Available settings differ by target; see the gpiomux header
* specific to your target arch for available configurations.
*
+ * @gpio: The index number of the gpio being described.
* @active: The configuration to be installed when the line is
* active, or its reference count is > 0.
* @suspended: The configuration to be installed when the line
* is suspended, or its reference count is 0.
- * @ref: The reference count of the line. For internal use of
- * the gpiomux framework only.
*/
struct msm_gpiomux_config {
+ unsigned gpio;
gpiomux_config_t active;
gpiomux_config_t suspended;
- unsigned ref;
};
/**
@@ -63,13 +62,16 @@ enum {
#ifdef CONFIG_MSM_GPIOMUX
-/* Each architecture must provide its own instance of this table.
- * To avoid having gpiomux manage any given gpio, one or both of
- * the entries can avoid setting GPIOMUX_VALID - the absence
- * of that flag will prevent the configuration from being applied
- * during state transitions.
+/* Before using gpiomux, initialize the subsystem by telling it how many
+ * gpios are going to be managed. Calling any other gpiomux functions
before
+ * msm_gpiomux_init is unsupported.
*/
-extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
+int msm_gpiomux_init(size_t ngpio);
+
+/* Install a block of gpiomux configurations in gpiomux. This is
functionally
+ * identical to calling msm_gpiomux_write many times.
+ */
+void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned
nconfigs);
/* Increment a gpio's reference count, possibly activating the line. */
int __must_check msm_gpiomux_get(unsigned gpio);
@@ -94,6 +96,14 @@ int msm_gpiomux_write(unsigned gpio,
*/
void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
#else
+static inline int msm_gpiomux_init(size_t ngpio)
+{
+ return -ENOSYS;
+}
+
+static inline void
+msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned
nconfigs) {}
+
static inline int __must_check msm_gpiomux_get(unsigned gpio)
{
return -ENOSYS;
--
1.7.3.3
Thanks,
Rohit Vaswani
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [patch 47/75] arm: tegra: Remove unused function which fiddles with irq_desc
From: Thomas Gleixner @ 2011-02-10 23:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110210222908.661199947@linutronix.de>
An embedded and charset-unspecified text was scrubbed...
Name: arm-tegra.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110210/f5bcbf8a/attachment.ksh>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox