Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
From: Felipe Contreras @ 2012-10-16  3:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CALLhW=6_0Rnp7-gNhCexUVzxam54KhoqAF6e8eiH5yo-wKBxzQ@mail.gmail.com>

Hi,

On Tue, Oct 16, 2012 at 3:29 AM, Omar Ramirez Luna <omar.luna@linaro.org> wrote:

>> After your patch, even if I don't use the camera, or the DSP, the
>> iommu devices will be enabled, and will be consuming energy *all the
>> time*. Which I don't think is what we want.
>
> Wrong, the iommu device will be enabled by pm_runtime_get_sync once
> you decide to attach with iommu_attach_device, if you do not use
> camera or the dsp, you won't turn ON the iommus.

I see, somehow I conflated the two functions.

> On probe this patch does pm_runtime_enable, however this doesn't mean
> the device is turned ON or resumed or kept ON all the time.

In fact it's the other way around; pm_runtime_enable turns off the
power (if it's ON).

>>>>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>>>>>         release_mem_region(res->start, resource_size(res));
>>>>>         iounmap(obj->regbase);
>>>>>
>>>>> -       clk_put(obj->clk);
>>>>> +       pm_runtime_disable(obj->dev);
>>>>
>>>> This will turn on the device unnecessarily, wasting power, and there's
>>>> no need for that, kfree will take care of that without resuming.
>>>
>>> Left aside the aesthetics of having balanced calls, the device will be
>>> enabled if there was a pending resume to be executed, otherwise it
>>> won't, kfree won't increment the disable_depth counter and I don't
>>> think that freeing the pointer is enough reason to ignore
>>> pm_runtime_disable.
>>
>> You are doing __pm_runtime_disable(dev, true), kfree will do
>> __pm_runtime_disable(dev, false), which is what we want. Both will
>> decrement the disable_depth.
>
> I'm quite confused here, could you please point me to the kfree snip
> that does __pm_runtime_disable(dev, false)?

Sorry, not kfree, but the device removal process:

device_del
 device_pm_remove
  pm_runtime_remove
   __pm_runtime_disable <- HERE
 bus_remove_device
  device_release_driver
   __device_release_driver
    .remove => platform_drv_remove
     .remove => omap_iommu_remove

Actually, it seems the pm is disabled _before_ omap_iommu_remove is
even called, so it's a no-op.

>> But at least you agree that there's a chance that the device will be waken up.
>
> Of course, if there is a pending resume to be executed, it must honor
> that resume request and then turn off the device before removing the
> iommu, IMHO.

Who will turn off the device afterwards?

>>>> Also, I still think that something like this is needed:
>>> ...
>>>> +static struct clk cam_fck = {
>>>> +       .name           = "cam_fck",
>>>> +       .ops            = &clkops_omap2_iclk_dflt,
>>>> +       .parent         = &l3_ick,
>>>> +       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
>>>
>>> a cam_fck name to enable the ick?
>>
>> Yeap, according to the TRM. Take a look at 12.3 Camera ISP Integration
>> Fig 12-50.
>
> What I meant is that, you are using the CM_ICLKEN to enable a clock
> named "cam_fck" which has l3_ick as a parent. And that is not
> consistent with what that register is meant to do, which is:
>
> 4.14.1.10 CAM_CM Registers
>
> CM_ICKLEN_CAM
> 0x0: CAM_L3_ICK and CAM_L4_ICLK are disabled
> 0x1: CAM_L3_ICK and CAM_L4_ICLK are enabled
>
> So, I'm complaining about the name "cam_fck", for an interface clock
> with parent l3_ick. However I don't know why on section 12.3 they
> refer to CAM_FCK to a l3_ick child clock.

Because it's also used as a functional clock.  Anyway, I don't care
much about the name of the clock, what is clear is that there's a link
missing to the l3_ick.

Cheers.

-- 
Felipe Contreras

^ permalink raw reply

* [PATCH v3 2/2] i2c: change id to let i2c-at91 work
From: Bo Shen @ 2012-10-16  3:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121015150244.GZ12801@game.jcrosoft.org>

Hi J,

On 10/15/2012 23:02, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 17:30 Mon 15 Oct     , Bo Shen wrote:
>> The i2c core driver will turn the platform device ID to busnum
>> When using platfrom device ID as -1, it means dynamically assigned
>> the busnum. When writing code, we need to make sure the busnum,
>> and call i2c_register_board_info(int busnum, ...) to register device
>> if using -1, we do not know the value of busnum
>> 	
>> In order to solve this issue, set the platform device ID as a fix number
>> Here using 0 to match the busnum used in i2c_regsiter_board_info()
>>
>> Signed-off-by: Bo Shen <voice.shen@atmel.com>
>> ---
>
> can you check when this append for the first time to schedule a patch for stable too

OK. I will resend it and add linux stable into the cc list.

Thanks.

BRs,
Bo Shen

> Best Regards,
> J.
>

^ permalink raw reply

* [PATCH V6 2/2] dmaengine: add helper function to request a slave DMA channel
From: Shawn Guo @ 2012-10-16  2:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348547701.1943.190.camel@vkoul-udesk3>

On Tue, Sep 25, 2012 at 10:05:01AM +0530, Vinod Koul wrote:
> On Mon, 2012-09-24 at 17:25 -0500, Jon Hunter wrote:
> > > For DT bindings, I think the binding itself shouldn't change based on my
> > > work but I would like these same bindings to help build the DMA engine
> > > code mappings.
> > > 
> > > Now would it make sense to NOT merge these changes for 3.7 and postpone
> > > to 3.8. I can host these patches on a topic branch and merge them when
> > > we are ready. I plan to spend some good amount of time on my work this
> > > week so we should be ready pretty soon.
> > > One these changes are merged, users can start moving to this scheme.
> > 
> > I just wanted to see how things are progressing your side. Did you
> > create a topic branch for this? If so let me know where I can find it, I
> > did not find a branch on your infradead git tree.
> > 
> > I wanted to pull in the latest patches for some testing. 
> Sorry for delay, I had everything ready, but couldn't manage to commit
> and push. I have pushed to topic/dmaengine_dt, it is pushing out now...
> 
Vinod,

Looks it seemed 3.7-rc1.  Does that mean we have to wait for 3.8, or
will it show on later -rc for 3.7?

Shawn

^ permalink raw reply

* [PATCH V6 2/2] dmaengine: add helper function to request a slave DMA channel
From: Vinod Koul @ 2012-10-16  2:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016024318.GF24393@S2101-09.ap.freescale.net>

On Tue, 2012-10-16 at 10:43 +0800, Shawn Guo wrote:
> On Tue, Sep 25, 2012 at 10:05:01AM +0530, Vinod Koul wrote:
> > On Mon, 2012-09-24 at 17:25 -0500, Jon Hunter wrote:
> > > > For DT bindings, I think the binding itself shouldn't change based on my
> > > > work but I would like these same bindings to help build the DMA engine
> > > > code mappings.
> > > > 
> > > > Now would it make sense to NOT merge these changes for 3.7 and postpone
> > > > to 3.8. I can host these patches on a topic branch and merge them when
> > > > we are ready. I plan to spend some good amount of time on my work this
> > > > week so we should be ready pretty soon.
> > > > One these changes are merged, users can start moving to this scheme.
> > > 
> > > I just wanted to see how things are progressing your side. Did you
> > > create a topic branch for this? If so let me know where I can find it, I
> > > did not find a branch on your infradead git tree.
> > > 
> > > I wanted to pull in the latest patches for some testing. 
> > Sorry for delay, I had everything ready, but couldn't manage to commit
> > and push. I have pushed to topic/dmaengine_dt, it is pushing out now...
> > 
> Vinod,
> 
> Looks it seemed 3.7-rc1.  Does that mean we have to wait for 3.8, or
> will it show on later -rc for 3.7?
Yes this will be merged once we work out the common interface, otherwise
we will end up redoing interfaces for all drivers.

-- 
~Vinod

^ permalink raw reply

* [PATCH] ARM: mxs: Add support for the Armadeus Systems APF28 module
From: Shawn Guo @ 2012-10-16  2:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350149143-9684-1-git-send-email-julien.boibessot@free.fr>

On Sat, Oct 13, 2012 at 07:25:43PM +0200, julien.boibessot at free.fr wrote:
> From: Julien Boibessot <julien.boibessot@armadeus.com>
> 
> Signed-off-by: Julien Boibessot <julien.boibessot@armadeus.com>
> Signed-off-by: Gwenhael Goavec-Merou <gwenhael.goavec-merou@armadeus.com>
> ---
>  arch/arm/boot/dts/imx28-apf28.dts |   79 +++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-mxs/mach-mxs.c      |    7 +++
>  2 files changed, 86 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/boot/dts/imx28-apf28.dts

Please add imx28-apf28.dtb target into arch/arm/boot/dts/Makefile.

> 
> diff --git a/arch/arm/boot/dts/imx28-apf28.dts b/arch/arm/boot/dts/imx28-apf28.dts
> new file mode 100644
> index 0000000..83e37c1
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx28-apf28.dts
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright 2012 Armadeus Systems - <support@armadeus.com>
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +/dts-v1/;
> +/include/ "imx28.dtsi"
> +
> +/ {
> +	model = "Armadeus Systems APF28 module";
> +	compatible = "armadeus,imx28-apf28", "fsl,imx28";
> +
> +	memory {
> +		reg = <0x40000000 0x08000000>;
> +	};
> +
> +	apb at 80000000 {
> +		apbh at 80000000 {
> +			gpmi-nand at 8000c000 {
> +				pinctrl-names = "default";
> +				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
> +				status = "okay";
> +
> +				partition at 0 {
> +					label = "u-boot";
> +					reg = <0x0 0x300000>;
> +				};

Nit: please put a new line between nodes.

> +				partition at 1 {

partition at 300000

xxx after partition@ should be the first cell of "reg" property.

Shawn

> +					label = "env";
> +					reg = <0x300000 0x80000>;
> +				};
> +				partition at 2 {
> +					label = "env2";
> +					reg = <0x380000 0x80000>;
> +				};
> +				partition at 3 {
> +					label = "dtb";
> +					reg = <0x400000 0x80000>;
> +				};
> +				partition at 4 {
> +					label = "splash";
> +					reg = <0x480000 0x80000>;
> +				};
> +				partition at 5 {
> +					label = "kernel";
> +					reg = <0x500000 0x800000>;
> +				};
> +				partition at 6 {
> +					label = "rootfs";
> +					reg = <0xd00000 0xf300000>;
> +				};
> +			};
> +		};
> +
> +		apbx at 80040000 {
> +			duart: serial at 80074000 {
> +				pinctrl-names = "default";
> +				pinctrl-0 = <&duart_pins_a>;
> +				status = "okay";
> +			};
> +		};
> +	};
> +
> +	ahb at 80080000 {
> +		mac0: ethernet at 800f0000 {
> +			phy-mode = "rmii";
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&mac0_pins_a>;
> +			phy-reset-gpios = <&gpio4 13 0>;
> +			status = "okay";
> +		};
> +	};
> +};
> diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
> index caf11db..93bc53d 100644
> --- a/arch/arm/mach-mxs/mach-mxs.c
> +++ b/arch/arm/mach-mxs/mach-mxs.c
> @@ -357,6 +357,11 @@ static void __init tx28_post_init(void)
>  	pinctrl_put(pctl);
>  }
>  
> +static void __init apf28_init(void)
> +{
> +	enable_clk_enet_out();
> +}
> +
>  static void __init mxs_machine_init(void)
>  {
>  	if (of_machine_is_compatible("fsl,imx28-evk"))
> @@ -367,6 +372,8 @@ static void __init mxs_machine_init(void)
>  		m28evk_init();
>  	else if (of_machine_is_compatible("bluegiga,apx4devkit"))
>  		apx4devkit_init();
> +	else if (of_machine_is_compatible("armadeus,imx28-apf28"))
> +		apf28_init();
>  
>  	of_platform_populate(NULL, of_default_bus_match_table,
>  			     mxs_auxdata_lookup, NULL);
> -- 
> 1.7.5.4
> 

^ permalink raw reply

* dma_alloc_coherent fails in framebuffer
From: Bob Liu @ 2012-10-16  2:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350325704.31162.16.camel@gitbox>

On Tue, Oct 16, 2012 at 2:28 AM, Tony Prisk <linux@prisktech.co.nz> wrote:
> On Mon, 2012-10-15 at 10:45 +0100, Mel Gorman wrote:
>> On Mon, Oct 15, 2012 at 09:34:55AM +1300, Tony Prisk wrote:
>> > On Sun, 2012-10-14 at 18:28 +1300, Tony Prisk wrote:
>> > > Up until 07 Oct, drivers/video/wm8505-fb.c was working fine, but on the
>> > > 11 Oct when I did another pull from linus all of a sudden
>> > > dma_alloc_coherent is failing to allocate the framebuffer any longer.
>> > >
>> > > I did a quick look back and found this:
>> > >
>> > > ARM: add coherent dma ops
>> > >
>> > > arch_is_coherent is problematic as it is a global symbol. This
>> > > doesn't work for multi-platform kernels or platforms which can support
>> > > per device coherent DMA.
>> > >
>> > > This adds arm_coherent_dma_ops to be used for devices which connected
>> > > coherently (i.e. to the ACP port on Cortex-A9 or A15). The arm_dma_ops
>> > > are modified at boot when arch_is_coherent is true.
>> > >
>> > > Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> > > Cc: Russell King <linux@arm.linux.org.uk>
>> > > Cc: Marek Szyprowski <m.szyprowski@samsung.com>
>> > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> > >
>> > >
>> > > This is the only patch lately that I could find (not that I would claim
>> > > to be any good at finding things) that is related to the problem. Could
>> > > it have caused the allocations to fail?
>> > >
>> > > Regards
>> > > Tony P
>> >
>> > Have done a bit more digging and found the cause - not Rob's patch so
>> > apologies.
>> >
>> > The cause of the regression is this patch:
>> >
>> > From f40d1e42bb988d2a26e8e111ea4c4c7bac819b7e Mon Sep 17 00:00:00 2001
>> > From: Mel Gorman <mgorman@suse.de>
>> > Date: Mon, 8 Oct 2012 16:32:36 -0700
>> > Subject: [PATCH 2/3] mm: compaction: acquire the zone->lock as late as
>> >  possible
>> >
>> > Up until then, the framebuffer allocation with dma_alloc_coherent(...)
>> > was fine. From this patch onwards, allocations fail.
>> >
>>
>> Was this found through bisection or some other means?
>>
>> There was a bug in that series that broke CMA but it was commit bb13ffeb
>> (mm: compaction: cache if a pageblock was scanned and no pages were
>> isolated) and it was fixed by 62726059 (mm: compaction: fix bit ranges
>> in {get,clear,set}_pageblock_skip()). So it should have been fixed by
>> 3.7-rc1 and probably was included by the time you pulled in October 11th
>> but bisection would be a pain. There were problems with that series during
>> development but tests were completing for other people.
>>
>> Just in case, is this still broken in 3.7-rc1?
>
> Still broken. Although the printk's might have cleared it up a bit.
>>
>> > I don't know how this patch would effect CMA allocations, but it seems
>> > to be causing the issue (or at least, it's caused an error in
>> > arch-vt8500 to become visible).
>> >
>> > Perhaps someone who understand -mm could explain the best way to
>> > troubleshoot the cause of this problem?
>> >
>>
>> If you are comfortable with ftrace, it can be used to narrow down where
>> the exact failure is occurring but if you're not comfortable with that
>> then the easiest is a bunch of printks starting in alloc_contig_range()
>> to see at what point and why it returns failure.
>>
>> It's not obvious at the moment why that patch would cause an allocation
>> problem. It's the type of patch that if it was wrong it would fail every
>> time for everyone, not just for a single driver.
>>
>
> I added some printk's to see what was happening.
>
> from arch/arm/mm/dma-mapping.c: arm_dma_alloc(..) it calls out to:
> dma_alloc_from_coherent().
>
> This returns 0, because:
> mem = dev->dma_mem
> if (!mem) return 0;
>
> and then arm_dma_alloc() falls back on __dma_alloc(..)
>
>
> I suspect the reason this fault is a bit 'weird' is because its
> effectively not using alloc_from_coherent at all, but falling back on
> __dma_alloc all the time, and sometimes it fails.
>

I think you need to declare that memory using
dma_declare_coherent_memory() before
alloc_from_coherent.

> Why it caused a problem on that particular commit I don't know - but it
> was reproducible by adding/removing it.
>
>
> Regards
> Tony P
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo at kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email at kvack.org </a>

-- 
Regards,
--Bob

^ permalink raw reply

* [PATCH 1/2] ARM: config: sort select statements alphanumerically
From: Eric Miao @ 2012-10-16  2:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121012150945.GB30339@atomide.com>

On Fri, Oct 12, 2012 at 11:09 PM, Tony Lindgren <tony@atomide.com> wrote:
> * Russell King - ARM Linux <linux@arm.linux.org.uk> [121012 07:44]:
>> On Fri, Oct 12, 2012 at 04:04:28PM +0200, Linus Walleij wrote:
>> > On Fri, Oct 12, 2012 at 3:26 PM, Russell King
>> > <rmk+kernel@arm.linux.org.uk> wrote:
>> >
>> > > As suggested by Andrew Morton:
>> > >
>> > >   This is a pet peeve of mine.  Any time there's a long list of items
>> > >   (header file inclusions, kconfig entries, array initalisers, etc) and
>> > >   someone wants to add a new item, they *always* go and stick it at the
>> > >   end of the list.
>> > >
>> > >   Guys, don't do this.  Either put the new item into a randomly-chosen
>> > >   position or, probably better, alphanumerically sort the list.
>> > >
>> > > lets sort all our select statements alphanumerically.  This commit was
>> > > created by the following perl:
>> >
>> > I applied this and tried to configure the Nomadik defconfig,
>> > and I get this, sadly:
>>
>> Yes, I've just fixed those.  Unfortunately, the patch is soo large that
>> it trips the mailing list size limit, and has to be manually approved,
>> so I'm not sure I can call on the list maintainers again today to do the
>> approval thing.
>
> After applying these two patches and manually running:
>
> $ git checkout-index -f arch/arm/mach-pxa/Kconfig
> $ git checkout-index -f arch/arm/mach-footbridge/Kconfig

Tony, why pxa and footbridge here?

>
> It builds just fine for omaps, so for omaps:
>
> Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply

* [PATCH 2/2] ARM: unwind: enable dumping stacks for SMP && ARM_UNWIND
From: Colin Cross @ 2012-10-16  2:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121012100242.GA2126@linaro.org>

On Fri, Oct 12, 2012 at 3:02 AM, Dave Martin <dave.martin@linaro.org> wrote:
> On Fri, Oct 12, 2012 at 10:08:07AM +0100, Russell King - ARM Linux wrote:
>> On Sun, Aug 26, 2012 at 03:46:56PM -0700, Colin Cross wrote:
>> > Unwinding with CONFIG_ARM_UNWIND is much more complicated than
>> > unwinding with CONFIG_FRAME_POINTER, but there are only a few points
>> > that require validation in order to avoid faults or infinite loops.
>> > Avoiding faults is easy by adding checks to verify that all accesses
>> > relative to the frame's stack pointer remain inside the stack.
>> >
>> > When CONFIG_FRAME_POINTER is not set it is possible for two frames to
>> > have the same SP, so there is no way to avoid repeated calls to
>> > unwind_frame continuing forever.
>>
>> So here you admit that this patch can cause the unwinder to loop forever,
>> which would provide no way out of that.  Why do you think this patch is
>> suitable for mainline with such a problem?
>
> With CONFIG_FRAME_POINTER we have a straightforward definition of
> progress: the sp must increase per frame, and cannot increase beyond the
> limit of the tasks stack.  We get this property from the fact that
> each frame record consumes actual space on the stack.  If we parse a
> frame record which does not both increase the sp and provide a frame
> address greater than that sp, we know that frame is garbage and we must
> stop.
>
>
> With CONFIG_ARM_UNWIND, we have no straightforward definition of
> progress.  However, sp must _normally_ still increase, because compiler-
> generated non-leaf functions must store the lr somewhere, and the
> compiler always uses the stack.  Even if lr is stashed in r4, an ABI
> compliant would then have needed to save r4 on the stack beforehand.
>
> We can assume that we will never parse a garbage unwind table because of
> the way the table lookup works (though we may parse a valid table which
> has nothing whatever to do with the code that was executing in the case
> of a corrupted stack).  So we only need to worry about what the unwind
> tables will look like for valid functions.
>
> Nonetheless, tail-call-optimised and manually-annotated functions may
> have unusual frames which don't consume any stack.  Stackless tail-
> call-optimised functions shouldn't be a problem, since their frames
> are completely missing from the backtrace and won't dump us into a loop.
> Stackless assembler functions are overwhelmingly likely to be leaf
> functions, giving us just one stackless frame.
>
>
> Would it make sense if we place some small sanity limit on the number
> of frames the unwinder will process with the same sp before giving up?

About half the callers to unwind_frame end up limiting the number of
frames they will follow before giving up, so I wasn't sure if I should
put an arbitrary limit in unwind_frame or just make sure all callers
are bounded.  Your idea of limiting same sp frames instead of total
frames sounds better.  I can send a new patch that adds a new field to
struct stackframe (which will need to be initialized everywhere, the
struct is usually on the stack) and limits the recursion.  Any
suggestion on the recursion limit?  I would never expect to see a real
situation with more than a few, but on the other hand parsing the
frames should be pretty fast so a high number (100?) shouldn't cause
any user visible effect.

^ permalink raw reply

* [PATCH 7/7] ARM: OMAP2+: PRCM: remove omap_prcm_get_reset_sources()
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

omap_prcm_get_reset_sources() is now unused; so, remove it.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/prcm.c             |   12 ------------
 arch/arm/plat-omap/include/plat/prcm.h |    1 -
 2 files changed, 13 deletions(-)

diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 0f51e03..0a2c33b 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -46,18 +46,6 @@ void __iomem *prcm_mpu_base;
 
 #define MAX_MODULE_ENABLE_WAIT		100000
 
-u32 omap_prcm_get_reset_sources(void)
-{
-	/* XXX This presumably needs modification for 34XX */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		return omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
-	if (cpu_is_omap44xx())
-		return omap2_prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_prcm_get_reset_sources);
-
 /* Resets clock rates and reboots the system. Only called from system.h */
 void omap_prcm_restart(char mode, const char *cmd)
 {
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 267f43b..a76cbd4 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -27,7 +27,6 @@
 #ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
 #define __ASM_ARM_ARCH_OMAP_PRCM_H
 
-u32 omap_prcm_get_reset_sources(void);
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);
 

^ permalink raw reply related

* [PATCH 6/7] watchdog: OMAP: use standard GETBOOTSTATUS interface; use platform_data fn ptr
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

Previously the OMAP watchdog driver used a non-standard way to report
the chip reset source via the GETBOOTSTATUS ioctl.  This patch
converts the driver to use the standard WDIOF_* flags for this
purpose.

This patch may break existing userspace code that uses the existing
non-standard data format returned by the OMAP watchdog driver's
GETBOOTSTATUS ioctl.  To fetch detailed reset source information,
userspace code will need to retrieve it directly from the CGRM or PRM
drivers when those are completed.

Previously, to fetch the reset source, the driver either read a
register outside the watchdog IP block (OMAP1), or called a function
exported directly from arch/arm/mach-omap2.  Both approaches are
broken.  This patch also converts the driver to use a platform_data
function pointer.  This approach is temporary, and is due to the lack
of drivers for the OMAP16xx+ Clock Generation and Reset Management IP
block and the OMAP2+ Power and Reset Management IP block.  Once
drivers are available for those IP blocks, the watchdog driver can be
converted to call exported drivers from those functions directly.
At that point, the platform_data function pointer can be removed.

In the short term, this patch is needed to allow the PRM code to be
removed from arch/arm/mach-omap2 (it is being moved to a driver).

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Wim Van Sebroeck <wim@iguana.be>
---
 drivers/watchdog/omap_wdt.c |   26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index f5db18db..5d33bc0 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -46,8 +46,8 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <mach/hardware.h>
-#include <plat/cpu.h>
-#include <plat/prcm.h>
+
+#include <linux/platform_data/omap-wd-timer.h>
 
 #include "omap_wdt.h"
 
@@ -202,8 +202,10 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
 static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 						unsigned long arg)
 {
+	struct omap_wd_timer_platform_data *pdata;
 	struct omap_wdt_dev *wdev;
-	int new_margin;
+	u32 rs;
+	int new_margin, bs;
 	static const struct watchdog_info ident = {
 		.identity = "OMAP Watchdog",
 		.options = WDIOF_SETTIMEOUT,
@@ -211,6 +213,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 	};
 
 	wdev = file->private_data;
+	pdata = wdev->dev->platform_data;
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
@@ -219,17 +222,12 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 	case WDIOC_GETSTATUS:
 		return put_user(0, (int __user *)arg);
 	case WDIOC_GETBOOTSTATUS:
-#ifdef CONFIG_ARCH_OMAP1
-		if (cpu_is_omap16xx())
-			return put_user(__raw_readw(ARM_SYSST),
-					(int __user *)arg);
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if (cpu_is_omap24xx())
-			return put_user(omap_prcm_get_reset_sources(),
-					(int __user *)arg);
-#endif
-		return put_user(0, (int __user *)arg);
+		if (!pdata->read_reset_sources)
+			return put_user(0, (int __user *)arg);
+		rs = pdata->read_reset_sources();
+		bs = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ?
+			WDIOF_CARDRESET : 0;
+		return put_user(bs, (int __user *)arg);
 	case WDIOC_KEEPALIVE:
 		spin_lock(&wdt_lock);
 		omap_wdt_ping(wdev);

^ permalink raw reply related

* [PATCH 5/7] ARM: OMAP2+: WDT: move init; add read_reset_sources pdata function pointer
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

The OMAP watchdog timer driver directly calls a function exported by
code in arch/arm/mach-omap2.  This is not good; it tightly couples
this driver to the mach-omap2 integration code.  Instead, add a
temporary platform_data function pointer to abstract this function
call.  A subsequent patch will convert the watchdog driver to use this
function pointer.

This patch also moves the device creation code out of
arch/arm/mach-omap2/devices.c and into arch/arm/mach-omap2/wd_timer.c.
This is another step towards the removal of
arch/arm/mach-omap2/devices.c.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Wim Van Sebroeck <wim@iguana.be>
---
 arch/arm/mach-omap1/devices.c               |   21 +++++++++++++--
 arch/arm/mach-omap2/devices.c               |   26 ------------------
 arch/arm/mach-omap2/wd_timer.c              |   33 +++++++++++++++++++++++
 include/linux/platform_data/omap-wd-timer.h |   38 +++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 29 deletions(-)
 create mode 100644 include/linux/platform_data/omap-wd-timer.h

diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index d3fec92..c3408e7 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 
+#include <linux/platform_data/omap-wd-timer.h>
+
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
@@ -439,18 +441,31 @@ static struct resource wdt_resources[] = {
 };
 
 static struct platform_device omap_wdt_device = {
-	.name	   = "omap_wdt",
-	.id	     = -1,
+	.name		= "omap_wdt",
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(wdt_resources),
 	.resource	= wdt_resources,
 };
 
 static int __init omap_init_wdt(void)
 {
+	struct omap_wd_timer_platform_data pdata;
+	int ret;
+
 	if (!cpu_is_omap16xx())
 		return -ENODEV;
 
-	return platform_device_register(&omap_wdt_device);
+	pdata.read_reset_sources = omap1_read_reset_sources;
+
+	ret = platform_device_register(&omap_wdt_device);
+	if (!ret) {
+		ret = platform_device_add_data(&omap_wdt_device, &pdata,
+					       sizeof(pdata));
+		if (ret)
+			platform_device_del(&omap_wdt_device);
+	}
+
+	return ret;
 }
 subsys_initcall(omap_init_wdt);
 #endif
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..2ab2c99 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -644,29 +644,3 @@ static int __init omap2_init_devices(void)
 	return 0;
 }
 arch_initcall(omap2_init_devices);
-
-#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-static int __init omap_init_wdt(void)
-{
-	int id = -1;
-	struct platform_device *pdev;
-	struct omap_hwmod *oh;
-	char *oh_name = "wd_timer2";
-	char *dev_name = "omap_wdt";
-
-	if (!cpu_class_is_omap2() || of_have_populated_dt())
-		return 0;
-
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-		pr_err("Could not look up wd_timer%d hwmod\n", id);
-		return -EINVAL;
-	}
-
-	pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
-	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
-				dev_name, oh->name);
-	return 0;
-}
-subsys_initcall(omap_init_wdt);
-#endif
diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
index b2f1c67..00ef54c 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -11,10 +11,14 @@
 #include <linux/io.h>
 #include <linux/err.h>
 
+#include <linux/platform_data/omap-wd-timer.h>
+
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "wd_timer.h"
 #include "common.h"
+#include "prm.h"
 
 /*
  * In order to avoid any assumptions from bootloader regarding WDT
@@ -99,3 +103,32 @@ int omap2_wd_timer_reset(struct omap_hwmod *oh)
 	return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT :
 		omap2_wd_timer_disable(oh);
 }
+
+static int __init omap_init_wdt(void)
+{
+	int id = -1;
+	struct platform_device *pdev;
+	struct omap_hwmod *oh;
+	char *oh_name = "wd_timer2";
+	char *dev_name = "omap_wdt";
+	struct omap_wd_timer_platform_data pdata;
+
+	if (!cpu_class_is_omap2())
+		return 0;
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up wd_timer%d hwmod\n", id);
+		return -EINVAL;
+	}
+
+	pdata.read_reset_sources = prm_read_reset_sources;
+
+	pdev = omap_device_build(dev_name, id, oh, &pdata,
+				 sizeof(struct omap_wd_timer_platform_data),
+				 NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
+	     dev_name, oh->name);
+	return 0;
+}
+subsys_initcall(omap_init_wdt);
diff --git a/include/linux/platform_data/omap-wd-timer.h b/include/linux/platform_data/omap-wd-timer.h
new file mode 100644
index 0000000..d75f5f8
--- /dev/null
+++ b/include/linux/platform_data/omap-wd-timer.h
@@ -0,0 +1,38 @@
+/*
+ * OMAP2+ WDTIMER-specific function prototypes
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_OMAP_WD_TIMER_H
+#define __LINUX_PLATFORM_DATA_OMAP_WD_TIMER_H
+
+#include <linux/types.h>
+
+/*
+ * Standardized OMAP reset source bits
+ *
+ * This is a subset of the ones listed in arch/arm/mach-omap2/prm.h
+ * and are the only ones needed in the watchdog driver.
+ */
+#define OMAP_MPU_WD_RST_SRC_ID_SHIFT				3
+
+/**
+ * struct omap_wd_timer_platform_data - WDTIMER integration to the host SoC
+ * @read_reset_sources - fn ptr for the SoC to indicate the last reset cause
+ *
+ * The function pointed to by @read_reset_sources must return its data
+ * in a standard format - search for RST_SRC_ID_SHIFT in
+ * arch/arm/mach-omap2
+ */
+struct omap_wd_timer_platform_data {
+	u32 (*read_reset_sources)(void);
+};
+
+#endif

^ permalink raw reply related

* [PATCH 4/7] ARM: OMAP2+: PRM: create PRM reset source API for the watchdog timer driver
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

The OMAP watchdog timer driver needs to determine what caused the SoC
to reset for its GETBOOTSTATUS ioctl.  So, define a set of standard
reset sources across OMAP SoCs.  For OMAP2xxx, 3xxx, and 4xxx SoCs,
define mappings from the SoC-specific reset source register bits to
the standardized reset source IDs.  Create SoC-specific PRM functions
that read the appropriate per-SoC register and use the mapping to
return the standardized reset bits.  Register the SoC-specific PRM
functions with the common PRM code via prm_register().  Create a
function in the common PRM code, prm_read_reset_sources(), that
calls the SoC-specific function, registered during boot.

This patch does not yet handle some SoCs, such as AM33xx.  Those SoCs
were not handled by the code this will replace.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/prm-regbits-24xx.h |    4 ++
 arch/arm/mach-omap2/prm-regbits-34xx.h |   10 ++++
 arch/arm/mach-omap2/prm.h              |   44 +++++++++++++++++
 arch/arm/mach-omap2/prm2xxx.c          |   68 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm2xxx.h          |    4 ++
 arch/arm/mach-omap2/prm2xxx_3xxx.h     |    2 +
 arch/arm/mach-omap2/prm3xxx.c          |   65 +++++++++++++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h          |    2 +
 arch/arm/mach-omap2/prm44xx.c          |   83 +++++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/prm44xx.h          |    2 +
 arch/arm/mach-omap2/prm_common.c       |   26 ++++++++++
 11 files changed, 306 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
index bd70a5a..638da6d 100644
--- a/arch/arm/mach-omap2/prm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
@@ -209,9 +209,13 @@
 
 /* RM_RSTST_WKUP specific bits */
 /* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
+#define OMAP24XX_EXTWMPU_RST_SHIFT			6
 #define OMAP24XX_EXTWMPU_RST_MASK			(1 << 6)
+#define OMAP24XX_SECU_WD_RST_SHIFT			5
 #define OMAP24XX_SECU_WD_RST_MASK			(1 << 5)
+#define OMAP24XX_MPU_WD_RST_SHIFT			4
 #define OMAP24XX_MPU_WD_RST_MASK			(1 << 4)
+#define OMAP24XX_SECU_VIOL_RST_SHIFT			3
 #define OMAP24XX_SECU_VIOL_RST_MASK			(1 << 3)
 
 /* PM_WKEN_WKUP specific bits */
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 073d4db..838b594 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -509,15 +509,25 @@
 #define OMAP3430_RSTTIME1_MASK				(0xff << 0)
 
 /* PRM_RSTST */
+#define OMAP3430_ICECRUSHER_RST_SHIFT			10
 #define OMAP3430_ICECRUSHER_RST_MASK			(1 << 10)
+#define OMAP3430_ICEPICK_RST_SHIFT			9
 #define OMAP3430_ICEPICK_RST_MASK			(1 << 9)
+#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT		8
 #define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_MASK		(1 << 8)
+#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT		7
 #define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_MASK		(1 << 7)
+#define OMAP3430_EXTERNAL_WARM_RST_SHIFT		6
 #define OMAP3430_EXTERNAL_WARM_RST_MASK			(1 << 6)
+#define OMAP3430_SECURE_WD_RST_SHIFT			5
 #define OMAP3430_SECURE_WD_RST_MASK			(1 << 5)
+#define OMAP3430_MPU_WD_RST_SHIFT			4
 #define OMAP3430_MPU_WD_RST_MASK			(1 << 4)
+#define OMAP3430_SECURITY_VIOL_RST_SHIFT		3
 #define OMAP3430_SECURITY_VIOL_RST_MASK			(1 << 3)
+#define OMAP3430_GLOBAL_SW_RST_SHIFT			1
 #define OMAP3430_GLOBAL_SW_RST_MASK			(1 << 1)
+#define OMAP3430_GLOBAL_COLD_RST_SHIFT			0
 #define OMAP3430_GLOBAL_COLD_RST_MASK			(1 << 0)
 
 /* PRM_VOLTCTRL */
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 3e51c1d..c30ab5d 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -52,16 +52,58 @@
 #define OMAP_POWERSTATE_SHIFT				0
 #define OMAP_POWERSTATE_MASK				(0x3 << 0)
 
+/*
+ * Standardized OMAP reset source bits
+ *
+ * To the extent these happen to match the hardware register bit
+ * shifts, it's purely coincidental.  Used by omap-wdt.c.
+ * OMAP_UNKNOWN_RST_SRC_ID_SHIFT is a special value, used whenever
+ * there are any bits remaining in the global PRM_RSTST register that
+ * haven't been identified, or when the PRM code for the current SoC
+ * doesn't know how to interpret the register.
+ */
+#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT			0
+#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT			1
+#define OMAP_SECU_VIOL_RST_SRC_ID_SHIFT				2
+#define OMAP_MPU_WD_RST_SRC_ID_SHIFT				3
+#define OMAP_SECU_WD_RST_SRC_ID_SHIFT				4
+#define OMAP_EXTWARM_RST_SRC_ID_SHIFT				5
+#define OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT			6
+#define OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT			7
+#define OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT			8
+#define OMAP_ICEPICK_RST_SRC_ID_SHIFT				9
+#define OMAP_ICECRUSHER_RST_SRC_ID_SHIFT			10
+#define OMAP_C2C_RST_SRC_ID_SHIFT				11
+#define OMAP_UNKNOWN_RST_SRC_ID_SHIFT				12
+
 #ifndef __ASSEMBLER__
 
 /**
+ * struct prm_reset_src_map - map register bitshifts to standard bitshifts
+ * @reg_shift: bitshift in the PRM reset source register
+ * @std_shift: bitshift equivalent in the standard reset source list
+ *
+ * The fields are signed because -1 is used as a terminator.
+ */
+struct prm_reset_src_map {
+	s8 reg_shift;
+	s8 std_shift;
+};
+
+/**
  * struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
+ * @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
  */
-struct prm_ll_data {};
+struct prm_ll_data {
+	u32 (*read_reset_sources)(void);
+};
 
 extern int prm_register(struct prm_ll_data *pld);
 extern int prm_unregister(struct prm_ll_data *pld);
 
+extern u32 prm_read_reset_sources(void);
+
 #endif
 
+
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
index d08a2b9..1fc06b0 100644
--- a/arch/arm/mach-omap2/prm2xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -28,6 +28,46 @@
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
+/*
+ * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
+ *   hardware register (which are specific to the OMAP2xxx SoCs) to
+ *   reset source ID bit shifts (which is an OMAP SoC-independent
+ *   enumeration)
+ */
+static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
+	{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+	{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+	{ -1, -1 },
+};
+
+/**
+ * omap2xxx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC.  The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap2xxx_prm_read_reset_sources(void)
+{
+	struct prm_reset_src_map *p;
+	u32 r = 0;
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
+
+	p = omap2xxx_prm_reset_src_map;
+	while (p->reg_shift >= 0 && p->std_shift >= 0) {
+		if (v & (1 << p->reg_shift))
+			r |= 1 << p->std_shift;
+		p++;
+	}
+
+	return r;
+}
+
 int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
 {
 	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
@@ -55,3 +95,31 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
 	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
 };
+
+/*
+ *
+ */
+
+static struct prm_ll_data omap2xxx_prm_ll_data = {
+	.read_reset_sources = &omap2xxx_prm_read_reset_sources,
+};
+
+static int __init omap2xxx_prm_init(void)
+{
+	if (!cpu_is_omap24xx())
+		return 0;
+
+	return prm_register(&omap2xxx_prm_ll_data);
+}
+subsys_initcall(omap2xxx_prm_init);
+
+static void __exit omap2xxx_prm_exit(void)
+{
+	if (!cpu_is_omap24xx())
+		return;
+
+	/* Should never happen */
+	WARN(prm_unregister(&omap2xxx_prm_ll_data),
+	     "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap2xxx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h
index 6d76716..1d97112 100644
--- a/arch/arm/mach-omap2/prm2xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx.h
@@ -123,6 +123,10 @@
 /* Function prototypes */
 extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
 extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
+
+extern int __init prm2xxx_init(void);
+extern int __exit prm2xxx_exit(void);
+
 #endif
 
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index 22a405a..3330b1b 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -211,7 +211,9 @@ extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
  *
  * 3430: RM_RSTST_CORE, RM_RSTST_EMU
  */
+#define OMAP_GLOBALWARM_RST_SHIFT			1
 #define OMAP_GLOBALWARM_RST_MASK			(1 << 1)
+#define OMAP_GLOBALCOLD_RST_SHIFT			0
 #define OMAP_GLOBALCOLD_RST_MASK			(1 << 0)
 
 /*
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
index b2c5fd9..e96446c 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -46,6 +46,27 @@ static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
 	.restore_irqen		= &omap3xxx_prm_restore_irqen,
 };
 
+/*
+ * omap3_prm_reset_src_map - map from bits in the PRM_RSTST hardware
+ *   register (which are specific to OMAP3xxx SoCs) to reset source ID
+ *   bit shifts (which is an OMAP SoC-independent enumeration)
+ */
+static struct prm_reset_src_map omap3xxx_prm_reset_src_map[] = {
+	{ OMAP3430_GLOBAL_COLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+	{ OMAP3430_GLOBAL_SW_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_SECURITY_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+	{ OMAP3430_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP3430_SECURE_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP3430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT,
+	  OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT,
+	  OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
+	{ OMAP3430_ICECRUSHER_RST_SHIFT, OMAP_ICECRUSHER_RST_SRC_ID_SHIFT },
+	{ -1, -1 },
+};
+
 /* PRM VP */
 
 /*
@@ -216,6 +237,30 @@ static void __init omap3xxx_prm_enable_io_wakeup(void)
 					   PM_WKEN);
 }
 
+/**
+ * omap3xxx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC.  The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap3xxx_prm_read_reset_sources(void)
+{
+	struct prm_reset_src_map *p;
+	u32 r = 0;
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
+
+	p = omap3xxx_prm_reset_src_map;
+	while (p->reg_shift >= 0 && p->std_shift >= 0) {
+		if (v & (1 << p->reg_shift))
+			r |= 1 << p->std_shift;
+		p++;
+	}
+
+	return r;
+}
+
 /* Powerdomain low-level functions */
 
 /* Applicable only for OMAP3. Not supported on OMAP2 */
@@ -319,6 +364,10 @@ struct pwrdm_ops omap3_pwrdm_operations = {
  *
  */
 
+static struct prm_ll_data omap3xxx_prm_ll_data = {
+	.read_reset_sources = &omap3xxx_prm_read_reset_sources,
+};
+
 static int __init omap3xxx_prm_init(void)
 {
 	int ret;
@@ -326,12 +375,28 @@ static int __init omap3xxx_prm_init(void)
 	if (!cpu_is_omap34xx())
 		return 0;
 
+	ret = prm_register(&omap3xxx_prm_ll_data);
+	if (ret)
+		return ret;
+
 	omap3xxx_prm_enable_io_wakeup();
 	ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
 	if (!ret)
 		irq_set_status_flags(omap_prcm_event_to_irq("io"),
 				     IRQ_NOAUTOEN);
 
+
 	return ret;
 }
 subsys_initcall(omap3xxx_prm_init);
+
+static void __exit omap3xxx_prm_exit(void)
+{
+	if (!cpu_is_omap34xx())
+		return;
+
+	/* Should never happen */
+	WARN(prm_unregister(&omap3xxx_prm_ll_data),
+	     "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap3xxx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 6821e83..a3c28a8 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -152,6 +152,8 @@ extern void omap3xxx_prm_ocp_barrier(void);
 extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
 extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
 
+extern u32 omap3xxx_prm_get_reset_sources(void);
+
 #endif /* __ASSEMBLER */
 
 
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 9231fe5..beb4502 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -1,7 +1,7 @@
 /*
  * OMAP4 PRM module functions
  *
- * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011-2012 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  * Beno?t Cousson
  * Paul Walmsley
@@ -29,6 +29,8 @@
 #include "prminst44xx.h"
 #include "powerdomain.h"
 
+/* Static data */
+
 static const struct omap_prcm_irq omap4_prcm_irqs[] = {
 	OMAP_PRCM_IRQ("wkup",   0,      0),
 	OMAP_PRCM_IRQ("io",     9,      1),
@@ -47,6 +49,33 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
 	.restore_irqen		= &omap44xx_prm_restore_irqen,
 };
 
+/*
+ * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
+ *   hardware register (which are specific to OMAP44xx SoCs) to reset
+ *   source ID bit shifts (which is an OMAP SoC-independent
+ *   enumeration)
+ */
+static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
+	{ OMAP4430_RST_GLOBAL_WARM_SW_SHIFT,
+	  OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_RST_GLOBAL_COLD_SW_SHIFT,
+	  OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+	{ OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
+	  OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+	{ OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
+	  OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
+	  OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
+	  OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
+	{ OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
+	{ -1, -1 },
+};
+
 /* PRM low-level functions */
 
 /* Read a register in a CM/PRM instance in the PRM module */
@@ -292,6 +321,31 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 
+/**
+ * omap44xx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC.  The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap44xx_prm_read_reset_sources(void)
+{
+	struct prm_reset_src_map *p;
+	u32 r = 0;
+	u32 v;
+
+	v = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+				    OMAP4_RM_RSTST);
+
+	p = omap44xx_prm_reset_src_map;
+	while (p->reg_shift >= 0 && p->std_shift >= 0) {
+		if (v & (1 << p->reg_shift))
+			r |= 1 << p->std_shift;
+		p++;
+	}
+
+	return r;
+}
+
 /* Powerdomain low-level functions */
 
 static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
@@ -554,14 +608,37 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
 };
 
+/*
+ * XXX document
+ */
+static struct prm_ll_data omap44xx_prm_ll_data = {
+	.read_reset_sources = &omap44xx_prm_read_reset_sources,
+};
 
-static int __init omap4xxx_prm_init(void)
+static int __init omap44xx_prm_init(void)
 {
+	int ret;
+
 	if (!cpu_is_omap44xx())
 		return 0;
 
+	ret = prm_register(&omap44xx_prm_ll_data);
+	if (ret)
+		return ret;
+
 	omap44xx_prm_enable_io_wakeup();
 
 	return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
 }
-subsys_initcall(omap4xxx_prm_init);
+subsys_initcall(omap44xx_prm_init);
+
+static void __exit omap44xx_prm_exit(void)
+{
+	if (!cpu_is_omap44xx())
+		return;
+
+	/* Should never happen */
+	WARN(prm_unregister(&omap44xx_prm_ll_data),
+	     "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap44xx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index ee72ae6..c8e1acc 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
 extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
 extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
 
+extern u32 omap44xx_prm_get_reset_sources(void);
+
 # endif
 
 #endif
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 8670a3c..e200e4f 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -28,6 +28,8 @@
 #include <plat/prcm.h>
 
 #include "prm2xxx_3xxx.h"
+#include "prm2xxx.h"
+#include "prm3xxx.h"
 #include "prm44xx.h"
 
 /*
@@ -327,6 +329,30 @@ err:
 }
 
 /**
+ * prm_read_reset_sources - return the sources of the SoC's last reset
+ *
+ * Return a u32 bitmask representing the reset sources that caused the
+ * SoC to reset.  The low-level per-SoC functions called by this
+ * function remap the SoC-specific reset source bits into an
+ * OMAP-common set of reset source bits, defined in
+ * arch/arm/mach-omap2/prm.h.  Returns the standardized reset source
+ * u32 bitmask from the hardware upon success, or returns (1 <<
+ * OMAP_UNKNOWN_RST_SRC_ID_SHIFT) if no low-level read_reset_sources()
+ * function was registered.
+ */
+u32 prm_read_reset_sources(void)
+{
+	u32 ret = 1 << OMAP_UNKNOWN_RST_SRC_ID_SHIFT;
+
+	if (prm_ll_data->read_reset_sources)
+		ret = prm_ll_data->read_reset_sources();
+	else
+		WARN_ONCE(1, "prm: %s: no mapping function defined for reset sources\n", __func__);
+
+	return ret;
+}
+
+/**
  * prm_register - register per-SoC low-level data with the PRM
  * @pld: low-level per-SoC OMAP PRM data & function pointers to register
  *

^ permalink raw reply related

* [PATCH 3/7] ARM: OMAP1: create read_reset_sources() function (for initial use by watchdog)
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

On OMAP1, the existing OMAP watchdog driver reads a register directly
from a non-watchdog IP block.  It also does not convert the register's
contents into the standard WDIOF_* bits expected from the
GETBOOTSTATUS ioctl().

To move towards fixing these problems, create an function in
arch/arm/mach-omap1 to return the reset source data.  A subsequent
patch will provide this function to the watchdog driver via
platform_data.

In the long term, the best approach would be to move this function
to a new OMAP1 driver that handles access to the OMAP1 Clock
Generation and Reset Management IP block.  Then no platform_data would
be needed.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap1/common.h |    2 ++
 arch/arm/mach-omap1/reset.c  |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index c2552b2..e83fd70 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -90,4 +90,6 @@ extern int ocpi_enable(void);
 static inline int ocpi_enable(void) { return 0; }
 #endif
 
+extern u32 omap1_read_reset_sources(void);
+
 #endif /* __ARCH_ARM_MACH_OMAP1_COMMON_H */
diff --git a/arch/arm/mach-omap1/reset.c b/arch/arm/mach-omap1/reset.c
index b177091..3e894fb 100644
--- a/arch/arm/mach-omap1/reset.c
+++ b/arch/arm/mach-omap1/reset.c
@@ -8,8 +8,22 @@
 
 #include <mach/hardware.h>
 
+#include "iomap.h"
 #include "common.h"
 
+/* ARM_SYSST bit shifts related to SoC reset sources */
+#define ARM_SYSST_POR_SHIFT				5
+#define ARM_SYSST_EXT_RST_SHIFT				4
+#define ARM_SYSST_ARM_WDRST_SHIFT			2
+#define ARM_SYSST_GLOB_SWRST_SHIFT			1
+
+/* Standardized reset source bits (across all OMAP SoCs) */
+#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT		0
+#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT		1
+#define OMAP_MPU_WD_RST_SRC_ID_SHIFT			3
+#define OMAP_EXTWARM_RST_SRC_ID_SHIFT			5
+
+
 void omap1_restart(char mode, const char *cmd)
 {
 	/*
@@ -23,3 +37,28 @@ void omap1_restart(char mode, const char *cmd)
 
 	omap_writew(1, ARM_RSTCT1);
 }
+
+/**
+ * omap1_read_reset_sources - return the source of the SoC's last reset
+ *
+ * Returns bits that represent the last reset source for the SoC.  The
+ * format is standardized across OMAPs for use by the OMAP watchdog.
+ */
+u32 omap1_read_reset_sources(void)
+{
+	int ret = 0;
+	u16 rs;
+
+	rs = __raw_readw(OMAP1_IO_ADDRESS(ARM_SYSST));
+
+	if (rs & (1 << ARM_SYSST_POR_SHIFT))
+		ret |= 1 << OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT;
+	if (rs & (1 << ARM_SYSST_EXT_RST_SHIFT))
+		ret |= 1 << OMAP_EXTWARM_RST_SRC_ID_SHIFT;
+	if (rs & (1 << ARM_SYSST_ARM_WDRST_SHIFT))
+		ret |= 1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT;
+	if (rs & (1 << ARM_SYSST_GLOB_SWRST_SHIFT))
+		ret |= 1 << OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT;
+
+	return ret;
+}

^ permalink raw reply related

* [PATCH 2/7] ARM: OMAP2+: CM: prepare for use of cm_ll_data function pointers
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

There are several CM operations which behave similarly across OMAP2+
SoCs, but which have slight differences in their underlying
implementations.

This patch creates the support code for this function pointer
registration process.  No function pointers are included yet, but a
subsequent patch will create these for the module IDLEST registers.

This patch allows other code to use CM-provided data and operations
without needing to know which SoC is currently in use.  A further
description of the concept is provided in the patch entitled
"ARM: OMAP2+: PRM: prepare for use of prm_ll_data function pointers".

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/Makefile    |    2 +
 arch/arm/mach-omap2/cm.h        |   12 +++++++
 arch/arm/mach-omap2/cm_common.c |   71 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-omap2/cm_common.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 3751d56..f7cf382 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -93,7 +93,7 @@ obj-$(CONFIG_ARCH_OMAP4)                += cpuidle44xx.o
 endif
 
 # PRCM
-obj-y					+= prcm.o prm_common.o
+obj-y					+= prcm.o prm_common.o cm_common.o
 obj-$(CONFIG_ARCH_OMAP2)		+= prm2xxx_3xxx.o prm2xxx.o cm2xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= prm2xxx_3xxx.o prm3xxx.o cm3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= vc3xxx_data.o vp3xxx_data.o
diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index f24e3f7..b3cee91 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -33,4 +33,16 @@
  */
 #define MAX_MODULE_DISABLE_TIME		5000
 
+# ifndef __ASSEMBLER__
+
+/**
+ * struct cm_ll_data - fn ptrs to per-SoC CM function implementations
+ */
+struct cm_ll_data {};
+
+extern int cm_register(struct cm_ll_data *cld);
+extern int cm_unregister(struct cm_ll_data *cld);
+
+# endif
+
 #endif
diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c
new file mode 100644
index 0000000..3246cef
--- /dev/null
+++ b/arch/arm/mach-omap2/cm_common.c
@@ -0,0 +1,71 @@
+/*
+ * OMAP2+ common Clock Management (CM) IP block functions
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley <paul@pwsan.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.
+ *
+ * XXX This code should eventually be moved to a CM driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "cm2xxx.h"
+#include "cm3xxx.h"
+#include "cm44xx.h"
+
+/*
+ * cm_ll_data: function pointers to SoC-specific implementations of
+ * common CM functions
+ */
+static struct cm_ll_data null_cm_ll_data;
+static struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
+
+/**
+ * cm_register - register per-SoC low-level data with the CM
+ * @cld: low-level per-SoC OMAP CM data & function pointers to register
+ *
+ * Register per-SoC low-level OMAP CM data and function pointers with
+ * the OMAP CM common interface.  The caller must keep the data
+ * pointed to by @cld valid until it calls cm_unregister() and
+ * it returns successfully.  Returns 0 upon success, -EINVAL if @cld
+ * is NULL, or -EEXIST if cm_register() has already been called
+ * without an intervening cm_unregister().
+ */
+int cm_register(struct cm_ll_data *cld)
+{
+	if (!cld)
+		return -EINVAL;
+
+	if (cm_ll_data != &null_cm_ll_data)
+		return -EEXIST;
+
+	cm_ll_data = cld;
+
+	return 0;
+}
+
+/**
+ * cm_unregister - unregister per-SoC low-level data & function pointers
+ * @cld: low-level per-SoC OMAP CM data & function pointers to unregister
+ *
+ * Unregister per-SoC low-level OMAP CM data and function pointers
+ * that were previously registered with cm_register().  The
+ * caller may not destroy any of the data pointed to by @cld until
+ * this function returns successfully.  Returns 0 upon success, or
+ * -EINVAL if @cld is NULL or if @cld does not match the struct
+ * cm_ll_data * previously registered by cm_register().
+ */
+int cm_unregister(struct cm_ll_data *cld)
+{
+	if (!cld || cm_ll_data != cld)
+		return -EINVAL;
+
+	cm_ll_data = &null_cm_ll_data;
+
+	return 0;
+}

^ permalink raw reply related

* [PATCH 1/7] ARM: OMAP2+: PRM: prepare for use of prm_ll_data function pointers
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016012448.21844.92339.stgit@dusk.lan>

There are several PRM operations which behave similarly across OMAP2+
SoCs, but which have slight differences in their underlying
implementations.  For example, to fetch the SoC's last reset sources,
different registers are read across OMAP2xxx, 3xxx, and 44xx, and
different bits are used on each SoC.  But the information returned is
so similar that a single, common interface for drivers is useful.

This patch creates the support code for this function pointer
registration process.  No function pointers are included yet, but a
subsequent patch will create one for the reset source API.

To illustrate the end goal with the above reset source example, each
per-SoC driver will use its own low-level implementation function --
e.g., prm2xxx.c would contain omap2xxx_prm_read_reset_sources().  This
function would read the appropriate register and remap the register
bits to a standard set of reset source bits.  When the prm2xxx.c
driver is loaded, it would register this function with the common PRM
driver, prm.c.  prm.c would then export a common function,
omap_prm_read_reset_sources().  Calling it would call through to the
function pointer for the currently-registered SoC PRM driver.  This
will allow other drivers to use PRM-provided data and operations
without needing to know which SoC is currently in use.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/prm.h        |   11 ++++++++
 arch/arm/mach-omap2/prm_common.c |   52 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 39d5621..3e51c1d 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -52,5 +52,16 @@
 #define OMAP_POWERSTATE_SHIFT				0
 #define OMAP_POWERSTATE_MASK				(0x3 << 0)
 
+#ifndef __ASSEMBLER__
+
+/**
+ * struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
+ */
+struct prm_ll_data {};
+
+extern int prm_register(struct prm_ll_data *pld);
+extern int prm_unregister(struct prm_ll_data *pld);
+
+#endif
 
 #endif
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 0a100d9..8670a3c 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -53,6 +53,13 @@ static struct irq_chip_generic **prcm_irq_chips;
  */
 static struct omap_prcm_irq_setup *prcm_irq_setup;
 
+/*
+ * prm_ll_data: function pointers to SoC-specific implementations of
+ * common PRM functions
+ */
+static struct prm_ll_data null_prm_ll_data;
+static struct prm_ll_data *prm_ll_data = &null_prm_ll_data;
+
 /* Private functions */
 
 /*
@@ -318,3 +325,48 @@ err:
 	omap_prcm_irq_cleanup();
 	return -ENOMEM;
 }
+
+/**
+ * prm_register - register per-SoC low-level data with the PRM
+ * @pld: low-level per-SoC OMAP PRM data & function pointers to register
+ *
+ * Register per-SoC low-level OMAP PRM data and function pointers with
+ * the OMAP PRM common interface.  The caller must keep the data
+ * pointed to by @pld valid until it calls prm_unregister() and
+ * it returns successfully.  Returns 0 upon success, -EINVAL if @pld
+ * is NULL, or -EEXIST if prm_register() has already been called
+ * without an intervening prm_unregister().
+ */
+int prm_register(struct prm_ll_data *pld)
+{
+	if (!pld)
+		return -EINVAL;
+
+	if (prm_ll_data != &null_prm_ll_data)
+		return -EEXIST;
+
+	prm_ll_data = pld;
+
+	return 0;
+}
+
+/**
+ * prm_unregister - unregister per-SoC low-level data & function pointers
+ * @pld: low-level per-SoC OMAP PRM data & function pointers to unregister
+ *
+ * Unregister per-SoC low-level OMAP PRM data and function pointers
+ * that were previously registered with prm_register().  The
+ * caller may not destroy any of the data pointed to by @pld until
+ * this function returns successfully.  Returns 0 upon success, or
+ * -EINVAL if @pld is NULL or if @pld does not match the struct
+ * prm_ll_data * previously registered by prm_register().
+ */
+int prm_unregister(struct prm_ll_data *pld)
+{
+	if (!pld || prm_ll_data != pld)
+		return -EINVAL;
+
+	prm_ll_data = &null_prm_ll_data;
+
+	return 0;
+}

^ permalink raw reply related

* [PATCH 0/7] ARM: OMAP: second set of PRM/CM/CGRM cleanup patches for 3.8
From: Paul Walmsley @ 2012-10-16  1:32 UTC (permalink / raw)
  To: linux-arm-kernel

This series removes the omap_prcm_get_reset_sources() function.  This
was exported from arch/arm/mach-omap2/prcm.c for use by the OMAP
watchdog driver to report the "boot reason".  This series reimplements
this using a platform_data function pointer for the time being, but
after the upcoming PRM/CM drivers are merged, the watchdog driver can be
patched to use an exported function from the drivers.

This series will also be used as a base for other PRM/CM cleanup during the
3.8 time frame, since it adds the prm_register() and prm_unregister() functions.
These are called by SoC-specific PRM IP block drivers to register function
pointers with the PRM subsystem.

This series changes the format of the watchdog's boot reason data to conform
with the watchdog subsystem standard (the WDIOF_* flags).  If users need
more detail than that interface provides, either the watchdog interface can
be patched, or those users can get that information from the upcoming PRM
drivers.


- Paul

---

prcm_cleanup_b_3.8
   text	   data	    bss	    dec	    hex	filename
7519295	 696796	5613996	13830087	 d307c7	vmlinux.omap2plus_defconfig.orig
7520203	 696868	5613996	13831067	 d30b9b	vmlinux.omap2plus_defconfig

Paul Walmsley (7):
      ARM: OMAP2+: PRM: prepare for use of prm_ll_data function pointers
      ARM: OMAP2+: CM: prepare for use of cm_ll_data function pointers
      ARM: OMAP1: create read_reset_sources() function (for initial use by watchdog)
      ARM: OMAP2+: PRM: create PRM reset source API for the watchdog timer driver
      ARM: OMAP2+: WDT: move init; add read_reset_sources pdata function pointer
      watchdog: OMAP: use standard GETBOOTSTATUS interface; use platform_data fn ptr
      ARM: OMAP2+: PRCM: remove omap_prcm_get_reset_sources()


 arch/arm/mach-omap1/common.h                |    2 +
 arch/arm/mach-omap1/devices.c               |   21 ++++++-
 arch/arm/mach-omap1/reset.c                 |   39 +++++++++++++
 arch/arm/mach-omap2/Makefile                |    2 -
 arch/arm/mach-omap2/cm.h                    |   12 ++++
 arch/arm/mach-omap2/cm_common.c             |   71 +++++++++++++++++++++++
 arch/arm/mach-omap2/devices.c               |   26 --------
 arch/arm/mach-omap2/prcm.c                  |   12 ----
 arch/arm/mach-omap2/prm-regbits-24xx.h      |    4 +
 arch/arm/mach-omap2/prm-regbits-34xx.h      |   10 +++
 arch/arm/mach-omap2/prm.h                   |   53 +++++++++++++++++
 arch/arm/mach-omap2/prm2xxx.c               |   68 ++++++++++++++++++++++
 arch/arm/mach-omap2/prm2xxx.h               |    4 +
 arch/arm/mach-omap2/prm2xxx_3xxx.h          |    2 +
 arch/arm/mach-omap2/prm3xxx.c               |   65 +++++++++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h               |    2 +
 arch/arm/mach-omap2/prm44xx.c               |   83 ++++++++++++++++++++++++++-
 arch/arm/mach-omap2/prm44xx.h               |    2 +
 arch/arm/mach-omap2/prm_common.c            |   78 +++++++++++++++++++++++++
 arch/arm/mach-omap2/wd_timer.c              |   33 +++++++++++
 arch/arm/plat-omap/include/plat/prcm.h      |    1 
 drivers/watchdog/omap_wdt.c                 |   26 ++++----
 include/linux/platform_data/omap-wd-timer.h |   38 ++++++++++++
 23 files changed, 594 insertions(+), 60 deletions(-)
 create mode 100644 arch/arm/mach-omap2/cm_common.c
 create mode 100644 include/linux/platform_data/omap-wd-timer.h

^ permalink raw reply

* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
From: Omar Ramirez Luna @ 2012-10-16  1:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMP44s3wTYTFgSw7r+77zb0fxMSjo1R69Zx0nyM6Hgy2h=Gggw@mail.gmail.com>

Hi Felipe,

On 12 October 2012 16:25, Felipe Contreras <felipe.contreras@gmail.com> wrote:
>>>> @@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
>>>>                 }
>>>>         }
>>>>
>>>> -       clk_enable(obj->clk);
>>>> +       pm_runtime_get_sync(obj->dev);
>>>>
>>>>         err = arch_iommu->enable(obj);
>>>>
>>>> -       clk_disable(obj->clk);
>>>
>>> The device will never go to sleep, until iommu_disable is called.
>>> clk_enable -> pm_runtime_get_sync, clk_disable pm_runtime_put.
>>
>> Which is what you want... why would you want your iommu to be disabled
>> if the client of that iommu could request a translation?
>
> That's the whole point of *dynamic* pm; _when_ the client wants to
> request a translation, _then_ the device is waken up, which is what I
> believe the code currently does.

No it doesn't, current code is working because the processor and the
iommu share the same clock, so enabling the processor is implicitly
guaranteeing that the iommu will be enabled. IMHO, there shouldn't be
such assumption that you can control both with the same clock.

So, once the remote processor is enabled, any "dynamic pm" from iommu
with current code has no effect because the clock was already enabled
for the processor.

> After your patch, even if I don't use the camera, or the DSP, the
> iommu devices will be enabled, and will be consuming energy *all the
> time*. Which I don't think is what we want.

Wrong, the iommu device will be enabled by pm_runtime_get_sync once
you decide to attach with iommu_attach_device, if you do not use
camera or the dsp, you won't turn ON the iommus.

On probe this patch does pm_runtime_enable, however this doesn't mean
the device is turned ON or resumed or kept ON all the time.

> I'm not saying I have a solution, I'm simply saying that's what's
> going to happen if I'm correct.

Ok, but that is not what happens here.

>> Remember that these iommus, sit along of other processors not on the
>> main processor side. So, this code should enable it for the other
>> processor to use, and there is no point where the processor can say
>> "I'm not using it, shut it down" or "I'm using it, turn it on" in the
>> middle of execution, other than suspend/resume and if supported,
>> autosuspend.
>
> I understand, but perhaps there should be?

Autosuspend is a feature missing and should handle the scenario where
the remote processor can sleep dynamically, this scenario should turn
off the iommu and the remote processor itself when there is no
workload but it depends on the remote processor activity not the iommu
activity.

>>>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>>>>         release_mem_region(res->start, resource_size(res));
>>>>         iounmap(obj->regbase);
>>>>
>>>> -       clk_put(obj->clk);
>>>> +       pm_runtime_disable(obj->dev);
>>>
>>> This will turn on the device unnecessarily, wasting power, and there's
>>> no need for that, kfree will take care of that without resuming.
>>
>> Left aside the aesthetics of having balanced calls, the device will be
>> enabled if there was a pending resume to be executed, otherwise it
>> won't, kfree won't increment the disable_depth counter and I don't
>> think that freeing the pointer is enough reason to ignore
>> pm_runtime_disable.
>
> You are doing __pm_runtime_disable(dev, true), kfree will do
> __pm_runtime_disable(dev, false), which is what we want. Both will
> decrement the disable_depth.

I'm quite confused here, could you please point me to the kfree snip
that does __pm_runtime_disable(dev, false)?

> But at least you agree that there's a chance that the device will be waken up.

Of course, if there is a pending resume to be executed, it must honor
that resume request and then turn off the device before removing the
iommu, IMHO.

>>> Also, I still think that something like this is needed:
>> ...
>>> +static struct clk cam_fck = {
>>> +       .name           = "cam_fck",
>>> +       .ops            = &clkops_omap2_iclk_dflt,
>>> +       .parent         = &l3_ick,
>>> +       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
>>
>> a cam_fck name to enable the ick?
>
> Yeap, according to the TRM. Take a look at 12.3 Camera ISP Integration
> Fig 12-50.

What I meant is that, you are using the CM_ICLKEN to enable a clock
named "cam_fck" which has l3_ick as a parent. And that is not
consistent with what that register is meant to do, which is:

4.14.1.10 CAM_CM Registers

CM_ICKLEN_CAM
0x0: CAM_L3_ICK and CAM_L4_ICLK are disabled
0x1: CAM_L3_ICK and CAM_L4_ICLK are enabled

So, I'm complaining about the name "cam_fck", for an interface clock
with parent l3_ick. However I don't know why on section 12.3 they
refer to CAM_FCK to a l3_ick child clock.

Cheers,

Omar

^ permalink raw reply

* [RFC 0/2] DMA-mapping & IOMMU - physically contiguous allocations
From: Inki Dae @ 2012-10-16  0:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350309832-18461-1-git-send-email-m.szyprowski@samsung.com>

2012/10/15 Marek Szyprowski <m.szyprowski@samsung.com>:
> Hello,
>
> Some devices, which have IOMMU, for some use cases might require to
> allocate a buffers for DMA which is contiguous in physical memory. Such
> use cases appears for example in DRM subsystem when one wants to improve
> performance or use secure buffer protection.
>
> I would like to ask if adding a new attribute, as proposed in this RFC
> is a good idea? I feel that it might be an attribute just for a single
> driver, but I would like to know your opinion. Should we look for other
> solution?
>

In addition, currently we have worked dma-mapping-based iommu support
for exynos drm driver with this patch set so this patch set has been
tested with iommu enabled exynos drm driver and worked fine. actually,
this feature is needed for secure mode such as TrustZone. in case of
Exynos SoC, memory region for secure mode should be physically
contiguous and also maybe OMAP but now dma-mapping framework doesn't
guarantee physically continuous memory allocation so this patch set
would make it possible.

Tested-by: Inki Dae <inki.dae@samsung.com>
Reviewed-by: Inki Dae <inki.dae@samsung.com>

Thanks,
Inki Dae

> Best regards
> --
> Marek Szyprowski
> Samsung Poland R&D Center
>
>
> Marek Szyprowski (2):
>   common: DMA-mapping: add DMA_ATTR_FORCE_CONTIGUOUS attribute
>   ARM: dma-mapping: add support for DMA_ATTR_FORCE_CONTIGUOUS attribute
>
>  Documentation/DMA-attributes.txt |    9 +++++++++
>  arch/arm/mm/dma-mapping.c        |   41 ++++++++++++++++++++++++++++++--------
>  include/linux/dma-attrs.h        |    1 +
>  3 files changed, 43 insertions(+), 8 deletions(-)
>
> --
> 1.7.9.5
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo at kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email at kvack.org </a>

^ permalink raw reply

* [PATCH 4/4] ARM: versatile: Make able to use UART ports for KGDB FIQ debugger
From: Anton Vorontsov @ 2012-10-16  0:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016003756.GA23146@lizard>

If enabled, kernel will able to enter KGDB upon serial line activity on
UART ports.

Note that even with this patch and CONFIG_KGDB_FIQ is enabled, you still
need to pass kgdb_fiq.enable=1 kernel command line option, otherwise UART
will behave in a normal way.

By default UART0 is used, but this can be changed via kgdb_fiq.uart_num
kernel command line option.

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
 arch/arm/Kconfig                   |  1 +
 arch/arm/mach-versatile/Makefile   |  1 +
 arch/arm/mach-versatile/kgdb_fiq.c | 31 +++++++++++++++++++++++++++++++
 3 files changed, 33 insertions(+)
 create mode 100644 arch/arm/mach-versatile/kgdb_fiq.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 87eb4f8..879136b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -337,6 +337,7 @@ config ARCH_VERSATILE
 	select PLAT_VERSATILE_CLCD
 	select PLAT_VERSATILE_CLOCK
 	select PLAT_VERSATILE_FPGA_IRQ
+	select ARCH_MIGHT_HAVE_KGDB_FIQ
 	help
 	  This enables support for ARM Ltd Versatile board.
 
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
index 81fa3fe..bfd761f 100644
--- a/arch/arm/mach-versatile/Makefile
+++ b/arch/arm/mach-versatile/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_ARCH_VERSATILE_PB)		+= versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)		+= versatile_ab.o
 obj-$(CONFIG_MACH_VERSATILE_DT)		+= versatile_dt.o
 obj-$(CONFIG_PCI)			+= pci.o
+obj-$(CONFIG_KGDB_FIQ)			+= kgdb_fiq.o
diff --git a/arch/arm/mach-versatile/kgdb_fiq.c b/arch/arm/mach-versatile/kgdb_fiq.c
new file mode 100644
index 0000000..3cdf71d
--- /dev/null
+++ b/arch/arm/mach-versatile/kgdb_fiq.c
@@ -0,0 +1,31 @@
+/*
+ * KGDB FIQ board support
+ *
+ * Copyright 2012 Linaro Ltd.
+ *		  Anton Vorontsov <anton.vorontsov@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/hardware/vic.h>
+
+static int kgdb_fiq;
+module_param_named(uart_num, kgdb_fiq, int, 0600);
+MODULE_PARM_DESC(uart_num, "UART<number> port to use for KGDB FIQ");
+
+static int __init kgdb_fiq_init(void)
+{
+	WARN_ON(kgdb_fiq > INT_UARTINT2 - INT_UARTINT0);
+
+	return kgdb_register_fiq(INT_UARTINT0 + kgdb_fiq,
+				 vic_fiq_select,
+				 vic_is_fiq_rised);
+}
+console_initcall(kgdb_fiq_init);
-- 
1.7.12.3

^ permalink raw reply related

* [PATCH 3/4] ARM: VIC: Add a couple of low-level FIQ management helpers
From: Anton Vorontsov @ 2012-10-16  0:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016003756.GA23146@lizard>

Just a couple of calls to manage VIC FIQ routing. We'll use them for
KGDB FIQ support on ARM Versatile machines.

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
 arch/arm/common/vic.c               | 28 ++++++++++++++++++++++++++++
 arch/arm/include/asm/hardware/vic.h |  2 ++
 2 files changed, 30 insertions(+)

diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index e0d5388..df2fc82 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -66,6 +66,34 @@ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
 
 static int vic_id;
 
+static void __iomem *vic_base(struct irq_data *d)
+{
+	return (void __iomem *)irq_data_get_irq_chip_data(d);
+}
+
+void vic_fiq_select(unsigned int irq, bool on)
+{
+	void __iomem *base = vic_base(&irq_to_desc(irq)->irq_data);
+	void __iomem *sel = base + VIC_INT_SELECT;
+	u32 msk = 1 << irq;
+	u32 val;
+
+	pr_debug("rerouting VIC vector %d to %s\n", irq, on ? "FIQ" : "IRQ");
+
+	val = readl(sel);
+	val &= ~msk;
+	if (on)
+		val |= msk;
+	writel(val, sel);
+}
+
+bool vic_is_fiq_rised(unsigned int irq)
+{
+	void __iomem *base = vic_base(&irq_to_desc(irq)->irq_data);
+
+	return readl(base + VIC_FIQ_STATUS) & (1 << irq);
+}
+
 /**
  * vic_init2 - common initialisation code
  * @base: Base of the VIC.
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index e14af1a..2728975 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -52,6 +52,8 @@ void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
 int vic_of_init(struct device_node *node, struct device_node *parent);
 void vic_handle_irq(struct pt_regs *regs);
+void vic_fiq_select(unsigned int irq, bool on);
+bool vic_is_fiq_rised(unsigned int irq);
 
 #endif /* __ASSEMBLY__ */
 #endif
-- 
1.7.12.3

^ permalink raw reply related

* [PATCH 2/4] ARM: Add KGDB/KDB FIQ debugger generic code
From: Anton Vorontsov @ 2012-10-16  0:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016003756.GA23146@lizard>

The FIQ debugger may be used to debug situations when the kernel stuck
in uninterruptable sections, e.g. the kernel infinitely loops or
deadlocked in an interrupt or with interrupts disabled.

By default KGDB FIQ is disabled in runtime, but can be enabled with
kgdb_fiq.enable=1 kernel command line option.

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
 arch/arm/Kconfig                 |  18 ++++++
 arch/arm/include/asm/kgdb.h      |   8 +++
 arch/arm/kernel/Makefile         |   1 +
 arch/arm/kernel/kgdb_fiq.c       | 124 +++++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/kgdb_fiq_entry.S |  87 +++++++++++++++++++++++++++
 5 files changed, 238 insertions(+)
 create mode 100644 arch/arm/kernel/kgdb_fiq.c
 create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 73067ef..87eb4f8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -177,6 +177,24 @@ config GENERIC_ISA_DMA
 config FIQ
 	bool
 
+config ARCH_MIGHT_HAVE_KGDB_FIQ
+	bool
+
+config KGDB_FIQ
+	bool "KGDB/KDB FIQ debugger"
+	depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL
+	select FIQ
+	help
+	  The FIQ debugger may be used to debug situations when the
+	  kernel stuck in uninterruptable sections, e.g. the kernel
+	  infinitely loops or deadlocked in an interrupt or with
+	  interrupts disabled.
+
+	  By default KGDB FIQ is disabled in runtime, but can be
+	  enabled with kgdb_fiq.enable=1 kernel command line option.
+
+	  If unsure, say N.
+
 config NEED_RET_TO_USER
 	bool
 
diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h
index 48066ce..807e547 100644
--- a/arch/arm/include/asm/kgdb.h
+++ b/arch/arm/include/asm/kgdb.h
@@ -11,6 +11,8 @@
 #define __ARM_KGDB_H__
 
 #include <linux/ptrace.h>
+#include <linux/linkage.h>
+#include <asm/exception.h>
 
 /*
  * GDB assumes that we're a user process being debugged, so
@@ -47,6 +49,12 @@ static inline void arch_kgdb_breakpoint(void)
 extern void kgdb_handle_bus_error(void);
 extern int kgdb_fault_expected;
 
+extern char kgdb_fiq_handler;
+extern char kgdb_fiq_handler_end;
+asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs);
+extern int __init kgdb_register_fiq(unsigned int mach_kgdb_fiq,
+		     void (*mach_kgdb_enable_fiq)(unsigned int irq, bool on),
+		     bool (*mach_is_kgdb_fiq)(unsigned int irq));
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5bbec7b..84ff575 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -56,6 +56,7 @@ endif
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
+obj-$(CONFIG_KGDB_FIQ)		+= kgdb_fiq_entry.o kgdb_fiq.o
 obj-$(CONFIG_ARM_UNWIND)	+= unwind.o
 obj-$(CONFIG_HAVE_TCM)		+= tcm.o
 obj-$(CONFIG_OF)		+= devtree.o
diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c
new file mode 100644
index 0000000..f3df754
--- /dev/null
+++ b/arch/arm/kernel/kgdb_fiq.c
@@ -0,0 +1,124 @@
+/*
+ * KGDB FIQ
+ *
+ * Copyright 2010 Google, Inc.
+ *		  Arve Hj?nnev?g <arve@android.com>
+ *		  Colin Cross <ccross@android.com>
+ * Copyright 2012 Linaro Ltd.
+ *		  Anton Vorontsov <anton.vorontsov@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/hardirq.h>
+#include <linux/atomic.h>
+#include <linux/kdb.h>
+#include <linux/kgdb.h>
+#include <asm/fiq.h>
+#include <asm/exception.h>
+
+static int kgdb_fiq_enabled;
+module_param_named(enable, kgdb_fiq_enabled, int, 0600);
+MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB");
+
+static unsigned int kgdb_fiq;
+static bool (*is_kgdb_fiq)(unsigned int irq);
+
+asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs)
+{
+	if (!is_kgdb_fiq(kgdb_fiq))
+		return;
+	if (!kgdb_nmi_poll_knock())
+		return;
+
+	nmi_enter();
+	kgdb_handle_exception(1, 0, 0, regs);
+	nmi_exit();
+}
+
+static struct fiq_handler kgdb_fiq_desc = {
+	.name = "kgdb",
+};
+
+static long kgdb_fiq_setup_stack(void *info)
+{
+	struct pt_regs regs;
+
+	regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) +
+			THREAD_START_SP;
+	WARN_ON(!regs.ARM_sp);
+
+	set_fiq_regs(&regs);
+	return 0;
+}
+
+static void (*kgdb_enable_fiq)(unsigned int irq, bool on);
+
+/**
+ * kgdb_fiq_enable_nmi - Manage NMI-triggered entry to KGDB
+ * @on: Flag to either enable or disable an NMI
+ *
+ * This function manages NMIs that usually cause KGDB to enter. That is, not
+ * all NMIs should be enabled or disabled, but only those that issue
+ * kgdb_handle_exception().
+ *
+ * The call counts disable requests, and thus allows to nest disables. But
+ * trying to enable already enabled NMI is an error.
+ */
+static void kgdb_fiq_enable_nmi(bool on)
+{
+	static atomic_t cnt;
+	int ret;
+
+	ret = atomic_add_return(on ? 1 : -1, &cnt);
+	if (ret > 1 && on) {
+		/*
+		 * There should be only one instance that calls this function
+		 * in "enable, disable" order. All other users must call
+		 * disable first, then enable. If not, something is wrong.
+		 */
+		WARN_ON(1);
+		return;
+	}
+
+	kgdb_enable_fiq(kgdb_fiq, ret > 0);
+}
+
+int __init kgdb_register_fiq(unsigned int mach_kgdb_fiq,
+		void (*mach_kgdb_enable_fiq)(unsigned int irq, bool on),
+		bool (*mach_is_kgdb_fiq)(unsigned int irq))
+{
+	int err;
+	int cpu;
+
+	if (!kgdb_fiq_enabled)
+		return -ENODEV;
+	if (kgdb_fiq)
+		return -EBUSY;
+
+	kgdb_fiq = mach_kgdb_fiq;
+	kgdb_enable_fiq = mach_kgdb_enable_fiq;
+	is_kgdb_fiq = mach_is_kgdb_fiq;
+
+	err = claim_fiq(&kgdb_fiq_desc);
+	if (err) {
+		pr_warn("%s: unable to claim fiq", __func__);
+		return err;
+	}
+
+	for_each_possible_cpu(cpu)
+		work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL);
+
+	set_fiq_handler(&kgdb_fiq_handler,
+			&kgdb_fiq_handler_end - &kgdb_fiq_handler);
+
+	arch_kgdb_ops.enable_nmi = kgdb_fiq_enable_nmi;
+	return 0;
+}
diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S
new file mode 100644
index 0000000..d6becca
--- /dev/null
+++ b/arch/arm/kernel/kgdb_fiq_entry.S
@@ -0,0 +1,87 @@
+/*
+ * KGDB FIQ entry
+ *
+ * Copyright 1996,1997,1998 Russell King.
+ * Copyright 2012 Linaro Ltd.
+ *		  Anton Vorontsov <anton.vorontsov@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include <asm/unwind.h>
+#include "entry-header.S"
+
+	.text
+
+@ This is needed for usr_entry/alignment_trap
+.LCcralign:
+	.long	cr_alignment
+.LCdohandle:
+	.long	kgdb_fiq_do_handle
+
+	.macro	fiq_handler
+	ldr	r1, =.LCdohandle
+	mov	r0, sp
+	adr	lr, BSYM(9997f)
+	ldr	pc, [r1]
+9997:
+	.endm
+
+	.align	5
+__fiq_svc:
+	svc_entry
+	fiq_handler
+	mov	r0, sp
+	ldmib	r0, {r1 - r14}
+	msr	cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT
+	add	r8, r0, #S_PC
+	ldr	r9, [r0, #S_PSR]
+	msr	spsr_cxsf, r9
+	ldr	r0, [r0, #S_R0]
+	ldmia	r8, {pc}^
+
+ UNWIND(.fnend		)
+ENDPROC(__fiq_svc)
+	.ltorg
+
+	.align	5
+__fiq_usr:
+	usr_entry
+	kuser_cmpxchg_check
+	fiq_handler
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user_from_irq
+ UNWIND(.fnend		)
+ENDPROC(__fiq_usr)
+	.ltorg
+
+	.global kgdb_fiq_handler
+kgdb_fiq_handler:
+
+	vector_stub	fiq, FIQ_MODE, 4
+
+	.long	__fiq_usr			@  0  (USR_26 / USR_32)
+	.long	__fiq_svc			@  1  (FIQ_26 / FIQ_32)
+	.long	__fiq_svc			@  2  (IRQ_26 / IRQ_32)
+	.long	__fiq_svc			@  3  (SVC_26 / SVC_32)
+	.long	__fiq_svc			@  4
+	.long	__fiq_svc			@  5
+	.long	__fiq_svc			@  6
+	.long	__fiq_svc			@  7
+	.long	__fiq_svc			@  8
+	.long	__fiq_svc			@  9
+	.long	__fiq_svc			@  a
+	.long	__fiq_svc			@  b
+	.long	__fiq_svc			@  c
+	.long	__fiq_svc			@  d
+	.long	__fiq_svc			@  e
+	.long	__fiq_svc			@  f
+
+	.global kgdb_fiq_handler_end
+kgdb_fiq_handler_end:
-- 
1.7.12.3

^ permalink raw reply related

* [PATCH 1/4] ARM: Move some macros from entry-armv to entry-header
From: Anton Vorontsov @ 2012-10-16  0:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016003756.GA23146@lizard>

Just move the macros into header file as we would want to use them for
KGDB FIQ entry code.

The following macros were moved:

 - svc_entry
 - usr_entry
 - kuser_cmpxchg_check
 - vector_stub

To make kuser_cmpxchg_check actually work across different files, we
also have to make kuser_cmpxchg64_fixup global.

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
 arch/arm/kernel/entry-armv.S   | 167 +---------------------------------------
 arch/arm/kernel/entry-header.S | 170 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+), 166 deletions(-)

diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0f82098..0f15368 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -136,57 +136,6 @@ common_invalid:
 	b	bad_mode
 ENDPROC(__und_invalid)
 
-/*
- * SVC mode handlers
- */
-
-#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
-#define SPFIX(code...) code
-#else
-#define SPFIX(code...)
-#endif
-
-	.macro	svc_entry, stack_hole=0
- UNWIND(.fnstart		)
- UNWIND(.save {r0 - pc}		)
-	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
-#ifdef CONFIG_THUMB2_KERNEL
- SPFIX(	str	r0, [sp]	)	@ temporarily saved
- SPFIX(	mov	r0, sp		)
- SPFIX(	tst	r0, #4		)	@ test original stack alignment
- SPFIX(	ldr	r0, [sp]	)	@ restored
-#else
- SPFIX(	tst	sp, #4		)
-#endif
- SPFIX(	subeq	sp, sp, #4	)
-	stmia	sp, {r1 - r12}
-
-	ldmia	r0, {r3 - r5}
-	add	r7, sp, #S_SP - 4	@ here for interlock avoidance
-	mov	r6, #-1			@  ""  ""      ""       ""
-	add	r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
- SPFIX(	addeq	r2, r2, #4	)
-	str	r3, [sp, #-4]!		@ save the "real" r0 copied
-					@ from the exception stack
-
-	mov	r3, lr
-
-	@
-	@ We are now ready to fill in the remaining blanks on the stack:
-	@
-	@  r2 - sp_svc
-	@  r3 - lr_svc
-	@  r4 - lr_<exception>, already fixed up for correct return/restart
-	@  r5 - spsr_<exception>
-	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)
-	@
-	stmia	r7, {r2 - r6}
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_off
-#endif
-	.endm
-
 	.align	5
 __dabt_svc:
 	svc_entry
@@ -348,71 +297,8 @@ ENDPROC(__pabt_svc)
 
 /*
  * User mode handlers
- *
- * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
  */
 
-#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
-#error "sizeof(struct pt_regs) must be a multiple of 8"
-#endif
-
-	.macro	usr_entry
- UNWIND(.fnstart	)
- UNWIND(.cantunwind	)	@ don't unwind the user space
-	sub	sp, sp, #S_FRAME_SIZE
- ARM(	stmib	sp, {r1 - r12}	)
- THUMB(	stmia	sp, {r0 - r12}	)
-
-	ldmia	r0, {r3 - r5}
-	add	r0, sp, #S_PC		@ here for interlock avoidance
-	mov	r6, #-1			@  ""  ""     ""        ""
-
-	str	r3, [sp]		@ save the "real" r0 copied
-					@ from the exception stack
-
-	@
-	@ We are now ready to fill in the remaining blanks on the stack:
-	@
-	@  r4 - lr_<exception>, already fixed up for correct return/restart
-	@  r5 - spsr_<exception>
-	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)
-	@
-	@ Also, separately save sp_usr and lr_usr
-	@
-	stmia	r0, {r4 - r6}
- ARM(	stmdb	r0, {sp, lr}^			)
- THUMB(	store_user_sp_lr r0, r1, S_SP - S_PC	)
-
-	@
-	@ Enable the alignment trap while in kernel mode
-	@
-	alignment_trap r0
-
-	@
-	@ Clear FP to mark the first stack frame
-	@
-	zero_fp
-
-#ifdef CONFIG_IRQSOFF_TRACER
-	bl	trace_hardirqs_off
-#endif
-	.endm
-
-	.macro	kuser_cmpxchg_check
-#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
-#ifndef CONFIG_MMU
-#warning "NPTL on non MMU needs fixing"
-#else
-	@ Make sure our user space atomic helper is restarted
-	@ if it was interrupted in a critical region.  Here we
-	@ perform a quick test inline since it should be false
-	@ 99.9999% of the time.  The rest is done out of line.
-	cmp	r4, #TASK_SIZE
-	blhs	kuser_cmpxchg64_fixup
-#endif
-#endif
-	.endm
-
 	.align	5
 __dabt_usr:
 	usr_entry
@@ -846,6 +732,7 @@ __kuser_cmpxchg64:				@ 0xffff0f60
 	ldmfd	sp!, {r4, r5, r6, pc}
 
 	.text
+	.global kuser_cmpxchg64_fixup
 kuser_cmpxchg64_fixup:
 	@ Called from kuser_cmpxchg_fixup.
 	@ r4 = address of interrupted insn (must be preserved).
@@ -976,58 +863,6 @@ __kuser_helper_end:
 
  THUMB(	.thumb	)
 
-/*
- * Vector stubs.
- *
- * This code is copied to 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's.  Note that this code must not
- * exceed 0x300 bytes.
- *
- * Common stub entry macro:
- *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
- *
- * SP points to a minimal amount of processor-private memory, the address
- * of which is copied into r0 for the mode specific abort handler.
- */
-	.macro	vector_stub, name, mode, correction=0
-	.align	5
-
-vector_\name:
-	.if \correction
-	sub	lr, lr, #\correction
-	.endif
-
-	@
-	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
-	@ (parent CPSR)
-	@
-	stmia	sp, {r0, lr}		@ save r0, lr
-	mrs	lr, spsr
-	str	lr, [sp, #8]		@ save spsr
-
-	@
-	@ Prepare for SVC32 mode.  IRQs remain disabled.
-	@
-	mrs	r0, cpsr
-	eor	r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
-	msr	spsr_cxsf, r0
-
-	@
-	@ the branch table must immediately follow this code
-	@
-	and	lr, lr, #0x0f
- THUMB(	adr	r0, 1f			)
- THUMB(	ldr	lr, [r0, lr, lsl #2]	)
-	mov	r0, sp
- ARM(	ldr	lr, [pc, lr, lsl #2]	)
-	movs	pc, lr			@ branch to handler in SVC mode
-ENDPROC(vector_\name)
-
-	.align	2
-	@ handler addresses follow this label
-1:
-	.endm
-
 	.globl	__stubs_start
 __stubs_start:
 /*
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..c3c09ac 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -73,6 +73,109 @@
 	msr	cpsr_c, \rtemp			@ switch back to the SVC mode
 	.endm
 
+/*
+ * Vector stubs.
+ *
+ * This code is copied to 0xffff0200 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not
+ * exceed 0x300 bytes.
+ *
+ * Common stub entry macro:
+ *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
+ *
+ * SP points to a minimal amount of processor-private memory, the address
+ * of which is copied into r0 for the mode specific abort handler.
+ */
+	.macro	vector_stub, name, mode, correction=0
+	.align	5
+
+vector_\name:
+	.if \correction
+	sub	lr, lr, #\correction
+	.endif
+
+	@
+	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
+	@ (parent CPSR)
+	@
+	stmia	sp, {r0, lr}		@ save r0, lr
+	mrs	lr, spsr
+	str	lr, [sp, #8]		@ save spsr
+
+	@
+	@ Prepare for SVC32 mode.  IRQs remain disabled.
+	@
+	mrs	r0, cpsr
+	eor	r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
+	msr	spsr_cxsf, r0
+
+	@
+	@ the branch table must immediately follow this code
+	@
+	and	lr, lr, #0x0f
+ THUMB(	adr	r0, 1f			)
+ THUMB(	ldr	lr, [r0, lr, lsl #2]	)
+	mov	r0, sp
+ ARM(	ldr	lr, [pc, lr, lsl #2]	)
+	movs	pc, lr			@ branch to handler in SVC mode
+ENDPROC(vector_\name)
+
+	.align	2
+	@ handler addresses follow this label
+1:
+	.endm
+
+/*
+ * SVC mode handlers
+ */
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
+#define SPFIX(code...) code
+#else
+#define SPFIX(code...)
+#endif
+
+	.macro	svc_entry, stack_hole=0
+ UNWIND(.fnstart		)
+ UNWIND(.save {r0 - pc}		)
+	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+#ifdef CONFIG_THUMB2_KERNEL
+ SPFIX(	str	r0, [sp]	)	@ temporarily saved
+ SPFIX(	mov	r0, sp		)
+ SPFIX(	tst	r0, #4		)	@ test original stack alignment
+ SPFIX(	ldr	r0, [sp]	)	@ restored
+#else
+ SPFIX(	tst	sp, #4		)
+#endif
+ SPFIX(	subeq	sp, sp, #4	)
+	stmia	sp, {r1 - r12}
+
+	ldmia	r0, {r3 - r5}
+	add	r7, sp, #S_SP - 4	@ here for interlock avoidance
+	mov	r6, #-1			@  ""  ""      ""       ""
+	add	r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+ SPFIX(	addeq	r2, r2, #4	)
+	str	r3, [sp, #-4]!		@ save the "real" r0 copied
+					@ from the exception stack
+
+	mov	r3, lr
+
+	@
+	@ We are now ready to fill in the remaining blanks on the stack:
+	@
+	@  r2 - sp_svc
+	@  r3 - lr_svc
+	@  r4 - lr_<exception>, already fixed up for correct return/restart
+	@  r5 - spsr_<exception>
+	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)
+	@
+	stmia	r7, {r2 - r6}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
+	.endm
+
 #ifndef CONFIG_THUMB2_KERNEL
 	.macro	svc_exit, rpsr
 	msr	spsr_cxsf, \rpsr
@@ -164,6 +267,73 @@
 #endif	/* !CONFIG_THUMB2_KERNEL */
 
 /*
+ * User mode handlers
+ *
+ * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
+ */
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
+#error "sizeof(struct pt_regs) must be a multiple of 8"
+#endif
+
+	.macro	usr_entry
+ UNWIND(.fnstart	)
+ UNWIND(.cantunwind	)	@ don't unwind the user space
+	sub	sp, sp, #S_FRAME_SIZE
+ ARM(	stmib	sp, {r1 - r12}	)
+ THUMB(	stmia	sp, {r0 - r12}	)
+
+	ldmia	r0, {r3 - r5}
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r6, #-1			@  ""  ""     ""        ""
+
+	str	r3, [sp]		@ save the "real" r0 copied
+					@ from the exception stack
+
+	@
+	@ We are now ready to fill in the remaining blanks on the stack:
+	@
+	@  r4 - lr_<exception>, already fixed up for correct return/restart
+	@  r5 - spsr_<exception>
+	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)
+	@
+	@ Also, separately save sp_usr and lr_usr
+	@
+	stmia	r0, {r4 - r6}
+ ARM(	stmdb	r0, {sp, lr}^			)
+ THUMB(	store_user_sp_lr r0, r1, S_SP - S_PC	)
+
+	@
+	@ Enable the alignment trap while in kernel mode
+	@
+	alignment_trap r0
+
+	@
+	@ Clear FP to mark the first stack frame
+	@
+	zero_fp
+
+#ifdef CONFIG_IRQSOFF_TRACER
+	bl	trace_hardirqs_off
+#endif
+	.endm
+
+	.macro	kuser_cmpxchg_check
+#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#ifndef CONFIG_MMU
+#warning "NPTL on non MMU needs fixing"
+#else
+	@ Make sure our user space atomic helper is restarted
+	@ if it was interrupted in a critical region.  Here we
+	@ perform a quick test inline since it should be false
+	@ 99.9999% of the time.  The rest is done out of line.
+	cmp	r4, #TASK_SIZE
+	blhs	kuser_cmpxchg64_fixup
+#endif
+#endif
+	.endm
+
+/*
  * These are the registers used in the syscall handler, and allow us to
  * have in theory up to 7 arguments to a function - r0 to r6.
  *
-- 
1.7.12.3

^ permalink raw reply related

* [PATCH 3/4] ARM: OMAP2+: Move iommu/iovmm headers to platform_data
From: Tony Lindgren @ 2012-10-16  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016003640.19701.51749.stgit@muffinssi.local>

* Tony Lindgren <tony@atomide.com> [121015 17:38]:
> From: Ido Yariv <ido@wizery.com>
> 
> Move iommu/iovmm headers from plat/ to platform_data/ as part of the
> single zImage work.

Joerg, I'm planning to apply these four patches against -rc1 into
omap-for-v3.8/cleanup-headers-iommu branch if these look OK to you.

That branch won't contain other patches and you can pull it in too
if needed.

Regards,

Tony
 
> Cc: Joerg Roedel <joerg.roedel@amd.com>
> Cc: Ohad Ben-Cohen <ohad@wizery.com>
> Signed-off-by: Ido Yariv <ido@wizery.com>
> Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  arch/arm/mach-omap2/devices.c              |    2 +-
>  arch/arm/mach-omap2/iommu2.c               |    2 +-
>  arch/arm/mach-omap2/omap-iommu.c           |    2 +-
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |    2 +-
>  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    2 +-
>  drivers/iommu/omap-iommu-debug.c           |    4 ++--
>  drivers/iommu/omap-iommu.c                 |    2 +-
>  drivers/iommu/omap-iovmm.c                 |    4 ++--
>  drivers/media/platform/omap3isp/isp.h      |    5 +++--
>  drivers/media/platform/omap3isp/ispvideo.c |    5 ++---
>  include/linux/platform_data/iommu-omap.h   |    0 
>  include/linux/platform_data/iovmm-omap.h   |    0 
>  12 files changed, 15 insertions(+), 15 deletions(-)
>  rename arch/arm/plat-omap/include/plat/iommu.h => include/linux/platform_data/iommu-omap.h (100%)
>  rename arch/arm/plat-omap/include/plat/iovmm.h => include/linux/platform_data/iovmm-omap.h (100%)
> 
> diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
> index c8c2117..6cd0c2a 100644
> --- a/arch/arm/mach-omap2/devices.c
> +++ b/arch/arm/mach-omap2/devices.c
> @@ -126,7 +126,7 @@ static struct platform_device omap2cam_device = {
>  
>  #if defined(CONFIG_IOMMU_API)
>  
> -#include <plat/iommu.h>
> +#include <linux/platform_data/iommu-omap.h>
>  
>  static struct resource omap3isp_resources[] = {
>  	{
> diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
> index c986880..82f9174 100644
> --- a/arch/arm/mach-omap2/iommu2.c
> +++ b/arch/arm/mach-omap2/iommu2.c
> @@ -18,7 +18,7 @@
>  #include <linux/slab.h>
>  #include <linux/stringify.h>
>  
> -#include <plat/iommu.h>
> +#include <linux/platform_data/iommu-omap.h>
>  
>  /*
>   * omap2 architecture specific register bit definitions
> diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
> index df298d4..a6a4ff8 100644
> --- a/arch/arm/mach-omap2/omap-iommu.c
> +++ b/arch/arm/mach-omap2/omap-iommu.c
> @@ -13,7 +13,7 @@
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  
> -#include <plat/iommu.h>
> +#include <linux/platform_data/iommu-omap.h>
>  
>  #include "soc.h"
>  #include "common.h"
> diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> index f67b7ee..621bc71 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> @@ -26,8 +26,8 @@
>  #include <plat/mmc.h>
>  #include <linux/platform_data/asoc-ti-mcbsp.h>
>  #include <linux/platform_data/spi-omap2-mcspi.h>
> +#include <linux/platform_data/iommu-omap.h>
>  #include <plat/dmtimer.h>
> -#include <plat/iommu.h>
>  
>  #include "am35xx.h"
>  
> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> index 652d028..5850b3e 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> @@ -27,10 +27,10 @@
>  #include <plat/dma.h>
>  #include <linux/platform_data/spi-omap2-mcspi.h>
>  #include <linux/platform_data/asoc-ti-mcbsp.h>
> +#include <linux/platform_data/iommu-omap.h>
>  #include <plat/mmc.h>
>  #include <plat/dmtimer.h>
>  #include <plat/common.h>
> -#include <plat/iommu.h>
>  
>  #include "omap_hwmod_common_data.h"
>  #include "cm1_44xx.h"
> diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
> index a0b0309..8c1e30b 100644
> --- a/drivers/iommu/omap-iommu-debug.c
> +++ b/drivers/iommu/omap-iommu-debug.c
> @@ -19,8 +19,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/debugfs.h>
>  
> -#include <plat/iommu.h>
> -#include <plat/iovmm.h>
> +#include <linux/platform_data/iommu-omap.h>
> +#include <linux/platform_data/iovmm-omap.h>
>  
>  #include <plat/iopgtable.h>
>  
> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
> index 80844b3..6100334 100644
> --- a/drivers/iommu/omap-iommu.c
> +++ b/drivers/iommu/omap-iommu.c
> @@ -24,7 +24,7 @@
>  
>  #include <asm/cacheflush.h>
>  
> -#include <plat/iommu.h>
> +#include <linux/platform_data/iommu-omap.h>
>  
>  #include <plat/iopgtable.h>
>  
> diff --git a/drivers/iommu/omap-iovmm.c b/drivers/iommu/omap-iovmm.c
> index b362fb5..b5ac2cd 100644
> --- a/drivers/iommu/omap-iovmm.c
> +++ b/drivers/iommu/omap-iovmm.c
> @@ -21,8 +21,8 @@
>  #include <asm/cacheflush.h>
>  #include <asm/mach/map.h>
>  
> -#include <plat/iommu.h>
> -#include <plat/iovmm.h>
> +#include <linux/platform_data/iommu-omap.h>
> +#include <linux/platform_data/iovmm-omap.h>
>  
>  #include <plat/iopgtable.h>
>  
> diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h
> index 8be7487..62c76f9 100644
> --- a/drivers/media/platform/omap3isp/isp.h
> +++ b/drivers/media/platform/omap3isp/isp.h
> @@ -34,8 +34,9 @@
>  #include <linux/platform_device.h>
>  #include <linux/wait.h>
>  #include <linux/iommu.h>
> -#include <plat/iommu.h>
> -#include <plat/iovmm.h>
> +
> +#include <linux/platform_data/iommu-omap.h>
> +#include <linux/platform_data/iovmm-omap.h>
>  
>  #include "ispstat.h"
>  #include "ispccdc.h"
> diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
> index a0b737fe..75ecfc8 100644
> --- a/drivers/media/platform/omap3isp/ispvideo.c
> +++ b/drivers/media/platform/omap3isp/ispvideo.c
> @@ -34,9 +34,8 @@
>  #include <linux/vmalloc.h>
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-ioctl.h>
> -#include <plat/iommu.h>
> -#include <plat/iovmm.h>
> -#include <plat/omap-pm.h>
> +#include <linux/platform_data/iommu-omap.h>
> +#include <linux/platform_data/iovmm-omap.h>
>  
>  #include "ispvideo.h"
>  #include "isp.h"
> diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/include/linux/platform_data/iommu-omap.h
> similarity index 100%
> rename from arch/arm/plat-omap/include/plat/iommu.h
> rename to include/linux/platform_data/iommu-omap.h
> diff --git a/arch/arm/plat-omap/include/plat/iovmm.h b/include/linux/platform_data/iovmm-omap.h
> similarity index 100%
> rename from arch/arm/plat-omap/include/plat/iovmm.h
> rename to include/linux/platform_data/iovmm-omap.h
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v10 0/4] ARM: KDB FIQ debugger
From: Anton Vorontsov @ 2012-10-16  0:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Russell,

The KDB/NMI core support has been merged into v3.7-rc1, so the only ARM
bits are pending now. I believe I addressed all your previous comments,
but surely there might be something else to improve, thus would be great
if you could take a look at this.

The patches were rebased onto v3.7-rc1, and this is the only change in
v10.

Old changelogs and rationale for these patches can be found here:

	v1-v5, rationale: http://lkml.org/lkml/2012/9/10/2
	v6: http://lkml.org/lkml/2012/9/10/2
	v7: http://lkml.org/lkml/2012/9/13/367
	v8: http://lkml.org/lkml/2012/9/19/525
	v9: http://lkml.org/lkml/2012/9/24/538

Thanks!
Anton.

--
 arch/arm/Kconfig                    |  19 ++++
 arch/arm/common/vic.c               |  28 +++++
 arch/arm/include/asm/hardware/vic.h |   2 +
 arch/arm/include/asm/kgdb.h         |   8 ++
 arch/arm/kernel/Makefile            |   1 +
 arch/arm/kernel/entry-armv.S        | 167 +---------------------------
 arch/arm/kernel/entry-header.S      | 170 +++++++++++++++++++++++++++++
 arch/arm/kernel/kgdb_fiq.c          | 124 +++++++++++++++++++++
 arch/arm/kernel/kgdb_fiq_entry.S    |  87 +++++++++++++++
 arch/arm/mach-versatile/Makefile    |   1 +
 arch/arm/mach-versatile/kgdb_fiq.c  |  31 ++++++
 11 files changed, 472 insertions(+), 166 deletions(-)

^ permalink raw reply

* [PATCH 4/4] ARM: OMAP2+: Move iopgtable header to drivers/iommu/
From: Tony Lindgren @ 2012-10-16  0:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121016003513.19701.71718.stgit@muffinssi.local>

From: Ido Yariv <ido@wizery.com>

The iopgtable header file is only used by the iommu & iovmm drivers, so
move it to drivers/iommu/, as part of the single zImage effort.

Cc: Joerg Roedel <joerg.roedel@amd.com>
Cc: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Ido Yariv <ido@wizery.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/iommu/omap-iommu-debug.c            |    3 +--
 drivers/iommu/omap-iommu.c                  |    3 +--
 drivers/iommu/omap-iopgtable.h              |    0 
 drivers/iommu/omap-iovmm.c                  |    3 +--
 4 files changed, 3 insertions(+), 6 deletions(-)
 rename arch/arm/plat-omap/include/plat/iopgtable.h => drivers/iommu/omap-iopgtable.h (100%)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 8c1e30b..84dbfd2 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -22,8 +22,7 @@
 #include <linux/platform_data/iommu-omap.h>
 #include <linux/platform_data/iovmm-omap.h>
 
-#include <plat/iopgtable.h>
-
+#include "omap-iopgtable.h"
 #include "omap-iommu.h"
 
 #define MAXCOLUMN 100 /* for short messages */
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 6100334..1ca33b0 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -26,8 +26,7 @@
 
 #include <linux/platform_data/iommu-omap.h>
 
-#include <plat/iopgtable.h>
-
+#include "omap-iopgtable.h"
 #include "omap-iommu.h"
 
 #define for_each_iotlb_cr(obj, n, __i, cr)				\
diff --git a/arch/arm/plat-omap/include/plat/iopgtable.h b/drivers/iommu/omap-iopgtable.h
similarity index 100%
rename from arch/arm/plat-omap/include/plat/iopgtable.h
rename to drivers/iommu/omap-iopgtable.h
diff --git a/drivers/iommu/omap-iovmm.c b/drivers/iommu/omap-iovmm.c
index b5ac2cd..2820e3a 100644
--- a/drivers/iommu/omap-iovmm.c
+++ b/drivers/iommu/omap-iovmm.c
@@ -24,8 +24,7 @@
 #include <linux/platform_data/iommu-omap.h>
 #include <linux/platform_data/iovmm-omap.h>
 
-#include <plat/iopgtable.h>
-
+#include "omap-iopgtable.h"
 #include "omap-iommu.h"
 
 static struct kmem_cache *iovm_area_cachep;

^ permalink raw reply related


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