* Identifying Primecells
From: Rob Herring @ 2011-09-23 12:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKON4OxqqBh4xFLwiMZzsGrnoG8erQ0hMFX-_VA-EDMvdNkvQQ@mail.gmail.com>
On 09/22/2011 01:19 PM, jonsmirl at gmail.com wrote:
> I'm working on device tree support for the NXP LPC3130. To do this
> right I need to know what specific Primecells were used in the chip.
> How do I identify the primecell numbers for the devices? It is a
> 926ejs core.
>
I'm not sure I understand the question.
The primecell periph id numbers are only in the DT if they are wrong in
the h/w for some reason. The compatible property should contain the
device model number (i.e. "arm,pl011" for the uart).
Rob
^ permalink raw reply
* [PATCHv9 18/18] TEMP: OMAP device: change pr_warnings to pr_debugs
From: Tero Kristo @ 2011-09-23 12:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316781986-30642-1-git-send-email-t-kristo@ti.com>
Prevents a hang when omap_device would want to print something for
serial console device while enabling / disabling its clocks.
Should be handled properly by serial runtime PM support.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/plat-omap/omap_device.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d8f2299..ecec0cc 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -154,7 +154,7 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
"%d: %llu\n",
od->pm_lat_level, act_lat);
} else
- dev_warn(&od->pdev->dev,
+ dev_dbg(&od->pdev->dev,
"activate latency %d "
"higher than exptected. (%llu > %d)\n",
od->pm_lat_level, act_lat,
@@ -221,7 +221,7 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
"%d: %llu\n",
od->pm_lat_level, deact_lat);
} else
- dev_warn(&od->pdev->dev,
+ dev_dbg(&od->pdev->dev,
"deactivate latency %d "
"higher than exptected. (%llu > %d)\n",
od->pm_lat_level, deact_lat,
--
1.7.4.1
Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
^ permalink raw reply related
* [PATCH v4 2/3] omap_twl: Prevent SR to enable for am3517/am3505 devices
From: Koyamangalath, Abhilash @ 2011-09-23 12:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87zkhws1ja.fsf@ti.com>
hi Kevin,
On Fri, Sep 23, 2011 at 3:05 PM, Hilman, Kevin wrote:
>
> Abhilash K V <abhilash.kv@ti.com> writes:
>
>> In case of AM3517 & AM3505, SmartReflex is not applicable so
>> we must not enable it.
>
> This part is fine, but...
>
>> So omap3_twl_init() is now not called when the processor does not
>> support SR.
>
> ...I don't think this is right. DVFS using the PMIC is still doable
> without SR.
>
> Are you assuming that no DVFS is done on these devices?
[Abhilash K V] yes, I just verified (in sprugr0b), that DVFS is not supported on am35xx
DPS however is supported, though I'm unsure of how or whether it needs
software control.
-Abhilash
>
> Kevin
>
>
>> Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
>> Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
>> ---
>> arch/arm/mach-omap2/id.c | 2 +-
>> arch/arm/mach-omap2/pm.c | 3 ++-
>> arch/arm/plat-omap/include/plat/cpu.h | 2 ++
>> 3 files changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
>> index d27daf9..b7e3082 100644
>> --- a/arch/arm/mach-omap2/id.c
>> +++ b/arch/arm/mach-omap2/id.c
>> @@ -188,7 +188,7 @@ static void __init omap3_check_features(void)
>> if (cpu_is_omap3630())
>> omap_features |= OMAP3_HAS_192MHZ_CLK;
>> if (!cpu_is_omap3505() && !cpu_is_omap3517())
>> - omap_features |= OMAP3_HAS_IO_WAKEUP;
>> + omap_features |= (OMAP3_HAS_IO_WAKEUP | OMAP3_HAS_SR);
>>
>> omap_features |= OMAP3_HAS_SDRC;
>>
>> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
>> index d34fc52..da71abc 100644
>> --- a/arch/arm/mach-omap2/pm.c
>> +++ b/arch/arm/mach-omap2/pm.c
>> @@ -252,7 +252,8 @@ postcore_initcall(omap2_common_pm_init);
>> static int __init omap2_common_pm_late_init(void)
>> {
>> /* Init the OMAP TWL parameters */
>> - omap3_twl_init();
>> + if (omap3_has_sr())
>> + omap3_twl_init();
>> omap4_twl_init();
>>
>> /* Init the voltage layer */
>> diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
>> index 2f90269..cc6fcd3 100644
>> --- a/arch/arm/plat-omap/include/plat/cpu.h
>> +++ b/arch/arm/plat-omap/include/plat/cpu.h
>> @@ -413,6 +413,7 @@ extern u32 omap_features;
>> #define OMAP4_HAS_MPU_1GHZ BIT(8)
>> #define OMAP4_HAS_MPU_1_2GHZ BIT(9)
>> #define OMAP4_HAS_MPU_1_5GHZ BIT(10)
>> +#define OMAP3_HAS_SR BIT(11)
>>
>>
>> #define OMAP3_HAS_FEATURE(feat,flag) \
>> @@ -429,6 +430,7 @@ OMAP3_HAS_FEATURE(isp, ISP)
>> OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
>> OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
>> OMAP3_HAS_FEATURE(sdrc, SDRC)
>> +OMAP3_HAS_FEATURE(sr, SR)
>>
>> /*
>> * Runtime detection of OMAP4 features
>
^ permalink raw reply
* Identifying Primecells
From: jonsmirl at gmail.com @ 2011-09-23 13:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4E7C7FA2.30404@gmail.com>
On Fri, Sep 23, 2011 at 8:46 AM, Rob Herring <robherring2@gmail.com> wrote:
> On 09/22/2011 01:19 PM, jonsmirl at gmail.com wrote:
>> I'm working on device tree support for the NXP LPC3130. To do this
>> right I need to know what specific Primecells were used in the chip.
>> How do I identify the primecell numbers for the devices? It is a
>> 926ejs core.
>>
>
> I'm not sure I understand the question.
>
> The primecell periph id numbers are only in the DT if they are wrong in
> the h/w for some reason. The compatible property should contain the
> device model number (i.e. "arm,pl011" for the uart).
So how do I figure out which id numbers to use for the NXP LPC3130?
Is the UART a pl011?
>
> Rob
>
--
Jon Smirl
jonsmirl at gmail.com
^ permalink raw reply
* [PATCH v2] AM3517 : support for suspend/resume
From: Koyamangalath, Abhilash @ 2011-09-23 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87obycqm2v.fsf@ti.com>
hi Kevin
Thanks for reviewing the patch.
On Fri, Sep 23, 2011 at 3:25 AM, Hilman, Kevin wrote:
>
> Abhilash K V <abhilash.kv@ti.com> writes:
>
>> This patch-set adds support for suspension to RAM and
>> resumption on the AM3517. This includes:
>> 1. Patch to disable dynamic sleep (as it is not supported
>> on AM35xx).
>
> This should still be a separate patch, with justification. More on this
> below.
[Abhilash K V] OK
>
>> 2. Imported the unique suspend/resume sequence for AM3517,
>> contained in the new file arch/arm/mach-omap2/sleep3517.S.
>>
>> Caveat: If "no_console_suspend" is enabled (via boot-args),the
>> device doesnot resume but simply hangs.
>> Kevin's fix below should fix this:
>> http://marc.info/?l=linux-omap&m=131593828001388&w=2#1
>
> should fix? I assumed you tested it along with this.
[Abhilash K V] I've tested that it does; pardon my choice of words.
>
>> Signed-off-by: Ranjith Lohithakshan <ranjithl@ti.com>
>> Reviewed-by: Vaibhav Hiremath <hvaibhav@ti.com>
>> Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
>> ---
>> This patch is dependent on the following patch-sets:
>> * [PATCH v3 0/2] AM3517: Booting up
>> at http://marc.info/?l=linux-omap&m=131548349725176&w=2
>> * [PATCH v2 0/3] AM35x: Adding PM init
>> at http://marc.info/?l=linux-kernel&m=131548606728209&w=2
>>
>> The patches are tested on master of tmlind/linux-omap-2.6.git.
>> Kernel version is 3.1-rc3 and last commit on top of which these patches
>> were added is:
>> b148d763841161894ed6629794064065a834aa2b: Linux-omap rebuilt: Updated to
>> use omap_sdrc_init
>>
>> with the folowing commit reverted:
>> f3637a5f2e2eb391ff5757bc83fb5de8f9726464: irq: Always set IRQF_ONESHOT
>> if no primary handler is specified
>>
>> Changes in v2:
>> * Synchronised with the cleaned-up suspend-resume code for OMAP3
>> * Removed unused *_get_restore_pointer code
>> * Added SECURE_SRAM feature to disallow saving and restoring
>> secure ram context for AM35x
>
> Adding a new feature flag should be a separate patch.
>
>> * Compacted the number of patches by squashing three closely coupled
>> ones and eliminating one that was no longer needed.
>>
>> arch/arm/mach-omap2/Makefile | 3 +-
>> arch/arm/mach-omap2/id.c | 4 +-
>> arch/arm/mach-omap2/pm.h | 3 +
>> arch/arm/mach-omap2/pm34xx.c | 21 ++++-
>> arch/arm/mach-omap2/sleep3517.S | 156 +++++++++++++++++++++++++++++++++
>> arch/arm/plat-omap/include/plat/cpu.h | 2 +
>> 6 files changed, 183 insertions(+), 6 deletions(-)
>> create mode 100644 arch/arm/mach-omap2/sleep3517.S
>>
>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>> index 590e797..37f62ae 100644
>> --- a/arch/arm/mach-omap2/Makefile
>> +++ b/arch/arm/mach-omap2/Makefile
>> @@ -61,7 +61,7 @@ endif
>> ifeq ($(CONFIG_PM),y)
>> obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
>> obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o
>> -obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \
>> +obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o sleep3517.o \
>> cpuidle34xx.o
>> obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o
>> obj-$(CONFIG_PM_DEBUG) += pm-debug.o
>> @@ -70,6 +70,7 @@ obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
>>
>> AFLAGS_sleep24xx.o :=-Wa,-march=armv6
>> AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
>> +AFLAGS_sleep3517.o :=-Wa,-march=armv7-a$(plus_sec)
>>
>> ifeq ($(CONFIG_PM_VERBOSE),y)
>> CFLAGS_pm_bus.o += -DDEBUG
>> diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
>> index da71098..3e40c02 100644
>> --- a/arch/arm/mach-omap2/id.c
>> +++ b/arch/arm/mach-omap2/id.c
>> @@ -202,7 +202,9 @@ static void __init omap3_check_features(void)
>> if (cpu_is_omap3630())
>> omap_features |= OMAP3_HAS_192MHZ_CLK;
>> if (!cpu_is_omap3505() && !cpu_is_omap3517())
>> - omap_features |= (OMAP3_HAS_IO_WAKEUP | OMAP3_HAS_SR);
>> + omap_features |= (OMAP3_HAS_IO_WAKEUP
>> + | OMAP3_HAS_SR
>> + | OMAP3_HAS_SECURE_SRAM);
>
> This is not related to suspend either, and should probably be part of
> the bootup series.
>
> The HAS_SECURE_SRAM part should be added to the separate patch that adds
> this new feature flag.
>
>> omap_features |= OMAP3_HAS_SDRC;
>>
>> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
>> index ce028f6..952eb2b 100644
>> --- a/arch/arm/mach-omap2/pm.h
>> +++ b/arch/arm/mach-omap2/pm.h
>> @@ -82,10 +82,13 @@ extern unsigned int omap24xx_cpu_suspend_sz;
>>
>> /* 3xxx */
>> extern void omap34xx_cpu_suspend(int save_state);
>> +extern void omap3517_cpu_suspend(int save_state);
>>
>> /* omap3_do_wfi function pointer and size, for copy to SRAM */
>> extern void omap3_do_wfi(void);
>> +extern void omap3517_do_wfi(void);
>> extern unsigned int omap3_do_wfi_sz;
>> +extern unsigned int omap3517_do_wfi_sz;
>> /* ... and its pointer from SRAM after copy */
>> extern void (*omap3_do_wfi_sram)(void);
>>
>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
>> index 7255d9b..44f7bac 100644
>> --- a/arch/arm/mach-omap2/pm34xx.c
>> +++ b/arch/arm/mach-omap2/pm34xx.c
>> @@ -80,6 +80,7 @@ static LIST_HEAD(pwrst_list);
>>
>> static int (*_omap_save_secure_sram)(u32 *addr);
>> void (*omap3_do_wfi_sram)(void);
>> +void (*omap3517_do_wfi_sram)(void);
>>
>> static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
>> static struct powerdomain *core_pwrdm, *per_pwrdm;
>> @@ -323,7 +324,10 @@ static void omap34xx_save_context(u32 *save)
>>
>> static int omap34xx_do_sram_idle(unsigned long save_state)
>> {
>> - omap34xx_cpu_suspend(save_state);
>> + if (cpu_is_omap3505() || cpu_is_omap3517())
>> + omap3517_cpu_suspend(save_state);
>> + else
>> + omap34xx_cpu_suspend(save_state);
>
> We don't want cpu_is_* checks at runtime. Make this a function pointer
> that is initialized at init time based on SoC.
>
>> return 0;
>> }
>>
>> @@ -485,6 +489,8 @@ console_still_active:
>>
>> int omap3_can_sleep(void)
>> {
>> + if (cpu_is_omap3505() || cpu_is_omap3517())
>> + return 0;
>
> This needs to be a separate patch with a descriptive changelog and
> justification as to why you can't do WFI in idle.
[Abhilash K V]OK
>
> Adding something like this means the device will *never* attempt a WFI
> during idle.
[Abhilash K V] This patch was put in as dynamic sleep feature is not supported
by the device, there are no C states etc. The only PM supported is forced suspend
/resume. There is just one power-domain and it can be in ON or RET states.
>
> I suspect that avoiding WFI in idle is masking a bug that you don't see
> in the suspend path.
[Abhilash K V] I need to recap a bit to find out if there is a better way to
indicate the lack of "idle" feature.
>
>> if (!omap_uart_can_sleep())
>> return 0;
>> return 1;
>> @@ -843,11 +849,18 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
>> */
>> void omap_push_sram_idle(void)
>> {
>> - omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
>> + if (cpu_is_omap3505() || cpu_is_omap3517())
>> + omap3517_do_wfi_sram = omap_sram_push(omap3517_do_wfi,
>> + omap3517_do_wfi_sz);
>> + else
>> + omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi,
>> + omap3_do_wfi_sz);
>>
>> if (omap_type() != OMAP2_DEVICE_TYPE_GP)
>> - _omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
>> - save_secure_ram_context_sz);
>> + if (omap3_has_secure_sram())
>> + _omap_save_secure_sram = omap_sram_push(
>> + save_secure_ram_context,
>> + save_secure_ram_context_sz);
>
> This should be part of the separate patch that add the secure SRAM
> feature flag.
[Abhilash K V] OK
>
> Kevin
>
^ permalink raw reply
* Identifying Primecells
From: Rob Herring @ 2011-09-23 13:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKON4OzGEo+XvcNg=mzp3jhq3d3m7Z9bvZTSVCNLNjZ=KYbNBQ@mail.gmail.com>
On 09/23/2011 08:11 AM, jonsmirl at gmail.com wrote:
> On Fri, Sep 23, 2011 at 8:46 AM, Rob Herring <robherring2@gmail.com> wrote:
>> On 09/22/2011 01:19 PM, jonsmirl at gmail.com wrote:
>>> I'm working on device tree support for the NXP LPC3130. To do this
>>> right I need to know what specific Primecells were used in the chip.
>>> How do I identify the primecell numbers for the devices? It is a
>>> 926ejs core.
>>>
>>
>> I'm not sure I understand the question.
>>
>> The primecell periph id numbers are only in the DT if they are wrong in
>> the h/w for some reason. The compatible property should contain the
>> device model number (i.e. "arm,pl011" for the uart).
>
> So how do I figure out which id numbers to use for the NXP LPC3130?
> Is the UART a pl011?
>
The chip's documentation or ARM's documentation. The existing board
code. Read each periph ID register.
Or the ones with drivers in the kernel:
find drivers -name '*pl[0-3]*'
Rob
^ permalink raw reply
* Git pull request: mach/vmalloc.h removal, and ioremap optimizations
From: Nicolas Pitre @ 2011-09-23 13:32 UTC (permalink / raw)
To: linux-arm-kernel
Russell, please pull
git://git.linaro.org/people/nico/linux vmalloc
This patch series removes all instances of mach/vmalloc.h in order to
have a more unified memory map across all ARM architectures. To do so,
the static mappings are moved inside the vmalloc area. And finally this
allows for a generic optimization to ioremap where static mappings are
reused whenever possible, using common code instead of having this
duplicated in a couple places.
This also provides a net reduction of more than 1200 lines of code.
One regression was discovered on shmobile during testing because that
platform asks for 158MB of consistent DMA memory while the documented
maximum is 14MB. Inspection of the code doesn't tell why this is
required, and listed maintainers did not respond yet after a couple
days. So a temporary exception to the definition of VMALLOC_END was
added for CONFIG_SHMOBILE and a noisy warning to get those maintainers'
attention.
Based on v3.1-rc4.
Nicolas Pitre (21):
ARM: mach-dove: remove inclusion of <mach/vmalloc.h>
ARM: mach-prima2: don't define SIRFSOC_VA in terms of VMALLOC_END
ARM: plat-mxc: remove inclusion of <mach/vmalloc.h>
ARM: plat-omap: don't define OMAP1_SRAM_VA in terms of VMALLOC_END
ARM: mach-at91: remove arch specific special handling for ioremap
ARM: mach-davinci: remove arch specific special handling for ioremap
ARM: mach-tegra: remove arch specific special handling for ioremap
ARM: plat-omap: remove arch specific special handling for ioremap
ARM: mach-bcmring: use proper constant to identify DMA memory area
ARM: mach-orion5x: remove arch specific special handling for ioremap
ARM: mach-kirkwood: remove arch specific special handling for ioremap
ARM: mach-ixp23xx: remove arch specific special handling for ioremap
ARM: plat-iop: remove arch specific special handling for ioremap
ARM: sort the meminfo array earlier
ARM: move initialization of the high_memory variable earlier
mm: add vm_area_add_early()
ARM: move iotable mappings within the vmalloc region
ARM: simplify __iounmap() when dealing with section based mapping
ARM: add generic ioremap optimization by reusing static mappings
ARM: big removal of now unused vmalloc.h files
ARM: move VMALLOC_END down temporarily for shmobile
Documentation/arm/memory.txt | 11 +-
arch/arm/include/asm/pgtable.h | 13 +-
arch/arm/kernel/setup.c | 8 +
arch/arm/mach-at91/include/mach/io.h | 8 -
arch/arm/mach-at91/include/mach/vmalloc.h | 26 ---
arch/arm/mach-at91/setup.c | 18 --
arch/arm/mach-bcmring/dma.c | 2 +-
arch/arm/mach-bcmring/include/mach/vmalloc.h | 25 ---
arch/arm/mach-clps711x/include/mach/vmalloc.h | 20 ---
arch/arm/mach-cns3xxx/include/mach/vmalloc.h | 11 --
arch/arm/mach-davinci/Makefile | 2 +-
arch/arm/mach-davinci/include/mach/io.h | 8 -
arch/arm/mach-davinci/include/mach/vmalloc.h | 14 --
arch/arm/mach-davinci/io.c | 48 ------
arch/arm/mach-dove/include/mach/dove.h | 2 -
arch/arm/mach-dove/include/mach/vmalloc.h | 5 -
arch/arm/mach-ebsa110/include/mach/vmalloc.h | 10 --
arch/arm/mach-ep93xx/include/mach/vmalloc.h | 5 -
arch/arm/mach-exynos4/include/mach/vmalloc.h | 22 ---
arch/arm/mach-footbridge/include/mach/vmalloc.h | 10 --
arch/arm/mach-gemini/include/mach/vmalloc.h | 10 --
arch/arm/mach-h720x/include/mach/vmalloc.h | 10 --
arch/arm/mach-integrator/include/mach/vmalloc.h | 20 ---
arch/arm/mach-iop13xx/include/mach/vmalloc.h | 4 -
arch/arm/mach-iop32x/include/mach/io.h | 7 -
arch/arm/mach-iop32x/include/mach/vmalloc.h | 5 -
arch/arm/mach-iop33x/include/mach/io.h | 7 -
arch/arm/mach-iop33x/include/mach/vmalloc.h | 5 -
arch/arm/mach-ixp2000/include/mach/vmalloc.h | 20 ---
arch/arm/mach-ixp23xx/include/mach/io.h | 29 ----
arch/arm/mach-ixp23xx/include/mach/vmalloc.h | 10 --
arch/arm/mach-ixp4xx/include/mach/vmalloc.h | 5 -
arch/arm/mach-kirkwood/include/mach/io.h | 25 ---
arch/arm/mach-kirkwood/include/mach/vmalloc.h | 5 -
arch/arm/mach-ks8695/include/mach/vmalloc.h | 19 ---
arch/arm/mach-lpc32xx/include/mach/vmalloc.h | 24 ---
arch/arm/mach-mmp/include/mach/vmalloc.h | 5 -
arch/arm/mach-msm/include/mach/vmalloc.h | 22 ---
arch/arm/mach-mv78xx0/include/mach/vmalloc.h | 5 -
arch/arm/mach-mxs/include/mach/vmalloc.h | 22 ---
arch/arm/mach-netx/include/mach/vmalloc.h | 19 ---
arch/arm/mach-nomadik/include/mach/vmalloc.h | 2 -
arch/arm/mach-nuc93x/include/mach/vmalloc.h | 23 ---
arch/arm/mach-omap1/include/mach/vmalloc.h | 20 ---
arch/arm/mach-omap2/include/mach/vmalloc.h | 20 ---
arch/arm/mach-orion5x/include/mach/io.h | 25 ---
arch/arm/mach-orion5x/include/mach/vmalloc.h | 5 -
arch/arm/mach-pnx4008/include/mach/vmalloc.h | 20 ---
arch/arm/mach-prima2/include/mach/map.h | 6 +-
arch/arm/mach-prima2/include/mach/vmalloc.h | 16 --
arch/arm/mach-pxa/include/mach/vmalloc.h | 11 --
arch/arm/mach-realview/include/mach/vmalloc.h | 21 ---
arch/arm/mach-rpc/include/mach/vmalloc.h | 10 --
arch/arm/mach-s3c2410/include/mach/vmalloc.h | 20 ---
arch/arm/mach-s3c64xx/include/mach/vmalloc.h | 20 ---
arch/arm/mach-s5p64x0/include/mach/vmalloc.h | 20 ---
arch/arm/mach-s5pc100/include/mach/vmalloc.h | 17 --
arch/arm/mach-s5pv210/include/mach/vmalloc.h | 22 ---
arch/arm/mach-sa1100/include/mach/vmalloc.h | 4 -
arch/arm/mach-shark/include/mach/vmalloc.h | 4 -
arch/arm/mach-shmobile/include/mach/vmalloc.h | 7 -
arch/arm/mach-spear3xx/include/mach/vmalloc.h | 19 ---
arch/arm/mach-spear6xx/include/mach/vmalloc.h | 19 ---
arch/arm/mach-tegra/include/mach/io.h | 6 -
arch/arm/mach-tegra/include/mach/vmalloc.h | 28 ----
arch/arm/mach-tegra/io.c | 21 ---
arch/arm/mach-u300/include/mach/vmalloc.h | 12 --
arch/arm/mach-ux500/include/mach/vmalloc.h | 18 --
arch/arm/mach-versatile/include/mach/vmalloc.h | 21 ---
arch/arm/mach-vexpress/include/mach/vmalloc.h | 21 ---
arch/arm/mach-vt8500/include/mach/vmalloc.h | 20 ---
arch/arm/mach-w90x900/include/mach/vmalloc.h | 23 ---
arch/arm/mach-zynq/include/mach/vmalloc.h | 20 ---
arch/arm/mm/init.c | 40 +----
arch/arm/mm/ioremap.c | 70 ++++++---
arch/arm/mm/mm.h | 14 ++
arch/arm/mm/mmu.c | 48 ++++--
arch/arm/mm/nommu.c | 2 +
arch/arm/plat-iop/Makefile | 2 -
arch/arm/plat-iop/io.c | 59 -------
arch/arm/plat-mxc/include/mach/mx1.h | 2 -
arch/arm/plat-mxc/include/mach/vmalloc.h | 22 ---
arch/arm/plat-omap/Makefile | 2 +-
arch/arm/plat-omap/include/plat/io.h | 6 -
arch/arm/plat-omap/io.c | 141 -----------------
arch/arm/plat-omap/sram.c | 2 +-
arch/arm/plat-spear/include/plat/vmalloc.h | 19 ---
arch/arm/plat-tcc/include/mach/vmalloc.h | 10 --
include/linux/vmalloc.h | 1 +
mm/vmalloc.c | 28 +++-
90 files changed, 159 insertions(+), 1376 deletions(-)
^ permalink raw reply
* Identifying Primecells
From: jonsmirl at gmail.com @ 2011-09-23 13:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4E7C89FC.4090209@gmail.com>
On Fri, Sep 23, 2011 at 9:30 AM, Rob Herring <robherring2@gmail.com> wrote:
> On 09/23/2011 08:11 AM, jonsmirl at gmail.com wrote:
>> On Fri, Sep 23, 2011 at 8:46 AM, Rob Herring <robherring2@gmail.com> wrote:
>>> On 09/22/2011 01:19 PM, jonsmirl at gmail.com wrote:
>>>> I'm working on device tree support for the NXP LPC3130. To do this
>>>> right I need to know what specific Primecells were used in the chip.
>>>> How do I identify the primecell numbers for the devices? It is a
>>>> 926ejs core.
>>>>
>>>
>>> I'm not sure I understand the question.
>>>
>>> The primecell periph id numbers are only in the DT if they are wrong in
>>> the h/w for some reason. The compatible property should contain the
>>> device model number (i.e. "arm,pl011" for the uart).
>>
>> So how do I figure out which id numbers to use for the NXP LPC3130?
>> Is the UART a pl011?
>>
> The chip's documentation or ARM's documentation. The existing board
> code. Read each periph ID register.
Kernel support is out of tree, I'm trying to get it into shape for
submission. Nothing in the existing driver code mentions the
peripheral ID. I've asked NXP to identify them and they have not
responded.
Is peripheral use documented at ARM for the lpc3130? What I don't know
is if the peripherals have been modified or replaced with an
alternative implementation.
So I guess I need to figure out how to read the ID register.
>
> Or the ones with drivers in the kernel:
> find drivers -name '*pl[0-3]*'
>
> Rob
>
--
Jon Smirl
jonsmirl at gmail.com
^ permalink raw reply
* [PATCH 01/10] cpufreq: OMAP: cleanup for multi-SoC support, move into drivers/cpufreq
From: Kevin Hilman @ 2011-09-23 14:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9bc8649a2e151bec117424b678bb09f8@mail.gmail.com>
Vishwanath Sripathy <vishwanath.bs@ti.com> writes:
[...]
>> +#ifdef CONFIG_CPU_FREQ_DEBUG
>> + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old,
>> freqs.new);
>> +#endif
>> +
>> + ret = clk_set_rate(mpu_clk, freqs.new * 1000);
>
> Do you plan to post follow up patches to scale voltage along with Clock?
Yes.
This series is just a move of existing code + minor cleanups.
The next step is to finalize/merge Tero's regulator driver and use
that to scale voltage along with frequency here.
Now that the voltage domain cleanups are merged, I hope to have
regulator series + voltage scaling changes in this driver ready next week.
Kevin
^ permalink raw reply
* Identifying Primecells
From: Pawel Moll @ 2011-09-23 14:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKON4OxZPFFL5NAgxLPRw2xxnS=v7iVWtQSSLcUJWfOYh4yfjA@mail.gmail.com>
> Is peripheral use documented at ARM for the lpc3130? What I don't know
> is if the peripherals have been modified or replaced with an
> alternative implementation.
>
> So I guess I need to figure out how to read the ID register.
I'm not sure what your problem exactly is, but if you want to know what
PeriphID for PL011 is, have a look here:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183g/I18381.html
So if your UART is PL011, reading four 8-bit wide registers at
* base + 0xfe0
* base + 0xfe4
* base + 0xfe8
* base + 0xfec
should give you (respectively):
* 0x11
* 0x10
* 0x_4 (_ depends on the cell revision)
* 0x00
Of course AMBA bus match_id will do this for you so, as I said, I'm not
sure what the problem is...
If you don't know what the base address is, well, only NXP and their
datasheet can help you here.
Cheers!
Pawe?
^ permalink raw reply
* Identifying Primecells
From: jonsmirl at gmail.com @ 2011-09-23 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316787049.4611.920.camel@hornet.cambridge.arm.com>
On Fri, Sep 23, 2011 at 10:10 AM, Pawel Moll <pawel.moll@arm.com> wrote:
>> Is peripheral use documented at ARM for the lpc3130? What I don't know
>> is if the peripherals have been modified or replaced with an
>> alternative implementation.
>>
>> So I guess I need to figure out how to read the ID register.
>
> I'm not sure what your problem exactly is, but if you want to know what
> PeriphID for PL011 is, have a look here:
>
> http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183g/I18381.html
>
> So if your UART is PL011, reading four 8-bit wide registers at
> * base + 0xfe0
> * base + 0xfe4
> * base + 0xfe8
> * base + 0xfec
> should give you (respectively):
> * 0x11
> * 0x10
> * 0x_4 (_ depends on the cell revision)
> * 0x00
>
> Of course AMBA bus match_id will do this for you so, as I said, I'm not
> sure what the problem is...
My registers don't seem to match up with the pl011 documentation...
Table 437. Register overview: UART (register base address 0x1500 1000)
Name R/W Address Offset Description
RBR R 0x000 Receiver Buffer Register
THR W 0x000 Transmitter Holding Register
DLL R/W 0x000 Divisor Latch LSB
DLM R/W 0x004 Divisor Latch MSB
IER R/W 0x004 Interrupt Enable Register
IIR R 0x008 Interrupt Identification Register
FCR W 0x008 FIFO Control Register
LCR R/W 0x00C Line Control Register
MCR R/W 0x010 Modem Control Register
LSR R 0x014 Line Status Register
MSR R 0x018 Modem Status Register
SCR R/W 0x01C Scratch Register
- - 0x020 Reserved
ICR R/W 0x024 IrDA Control Register
FDR R/W 0x028 Fractional Divider Register
- - 0x02C Reserved
POP W 0x030 NHP Pop Register
MODE R/W 0x034 NHP Mode Selection Register
- - 0x038-0xFD4 Reserved
INTCE W 0xFD8 Interrupt Clear Enable Register
INTSE W 0xFDC Interrupt Set Enable Register
INTS R 0xFE0 Interrupt Status Register
INTE R 0xFE4 Interrupt Enable Register
>
> If you don't know what the base address is, well, only NXP and their
> datasheet can help you here.
>
> Cheers!
>
> Pawe?
>
>
>
>
--
Jon Smirl
jonsmirl at gmail.com
^ permalink raw reply
* Identifying Primecells
From: jonsmirl at gmail.com @ 2011-09-23 14:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKON4OxHwjrw-dhH2qvXopqUqmKSx2TCPgW4eVHF9dmQO4=Cvw@mail.gmail.com>
On Fri, Sep 23, 2011 at 10:17 AM, jonsmirl at gmail.com <jonsmirl@gmail.com> wrote:
>>
>> Of course AMBA bus match_id will do this for you so, as I said, I'm not
>> sure what the problem is...
The problem is that I have a bunch of drivers for all of the
peripherals that were written by NXP. But the kernel has standardized
drivers for a lot of the primecells. If the LPC3130 has used a
standard primecell I want to get rid of the NXP supplied driver and
switch to the standard one. But in order to do that I need to
identify the peripherals that are unmodified primecells.
--
Jon Smirl
jonsmirl at gmail.com
^ permalink raw reply
* Identifying Primecells
From: Pawel Moll @ 2011-09-23 14:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKON4OxHwjrw-dhH2qvXopqUqmKSx2TCPgW4eVHF9dmQO4=Cvw@mail.gmail.com>
> My registers don't seem to match up with the pl011 documentation...
<...>
> INTCE W 0xFD8 Interrupt Clear Enable Register
> INTSE W 0xFDC Interrupt Set Enable Register
> INTS R 0xFE0 Interrupt Status Register
> INTE R 0xFE4 Interrupt Enable Register
... nor any other PrimeCell, actually :-)
"Compliant" PrimeCells must have the PCellID in the last 4 registers:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183g/I54776.html
* base + 0xff0 = 0x0d
* base + 0xff4 = 0xf0
* base + 0xff8 = 0x05
* base + 0xffc = 0xb1
Cheers!
Pawe?
^ permalink raw reply
* [PATCH] ARM i.MX avic: convert to use generic irq chip
From: Sascha Hauer @ 2011-09-23 14:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4E7C49AE.8070101@gmail.com>
On Fri, Sep 23, 2011 at 04:56:14PM +0800, Hui Wang wrote:
> Shawn Guo wrote:
> >On Thu, Sep 22, 2011 at 05:40:08PM +0800, Hui Wang wrote:
> >>Convert i.MX avic irq handler to use generic irq chip. This not only
> >>provides a cleanup implementation of irq chip handler, but also
> >>implements suspend/resume interface with the help of generic irq chip
> >>interface.
> >>
> >>Change mxc_irq_chip to a new structure mxc_extra_irq to handle fiq
> >>and priority functions.
> >>
> >>Signed-off-by: Hui Wang <jason77.wang@gmail.com>
> >>---
> >>
> >>This patch is basing on imx-features branch of linux-pengu. Have
> >>validated this patch on 31pdk and 35pdk platforms, while have no
> >>chance to validate it on mx2 and mx1 platforms since we don't have
> >>those hardwares.
> >>
> >>The purpose of changing avic to use generic irq chip is because i
> >>added suspend/resume functions for 35pdk, and generic irq chip
> >>naturally has suspend/resume interface. If this patch can be
> >>accepted, i will continue to send out those 35pdk pm patches.
> >>
> >> arch/arm/plat-mxc/avic.c | 79 ++++++++++++++++++++++++++++------------
> >> arch/arm/plat-mxc/irq-common.c | 21 ++++++-----
> >> arch/arm/plat-mxc/irq-common.h | 3 +-
> >> arch/arm/plat-mxc/tzic.c | 8 ++++-
> >> 4 files changed, 75 insertions(+), 36 deletions(-)
> >>
> >Acked-by: Shawn Guo <shawn.guo@linaro.org>
> >
> >However, I'm wondering if you can add the suspend/resume interface for
> >tzic as well.
> Yes, this is the next plan, if this patch can be accepted, i will
> add tzic suspend/resume as well.
It is, go ahead.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* DT vs ARM static mappings
From: Arnd Bergmann @ 2011-09-23 15:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316708611.4611.873.camel@hornet.cambridge.arm.com>
On Thursday 22 September 2011, Pawel Moll wrote:
> Executive summary:
>
> * I have second map_desc with pfn for RS1 memory map, but using the same
> virtual address as the legacy one. The legacy one is used if root of the
> tree is compatible with "arm,vexpress-legacy".
>
> * The devices I need to use in v2m.c have aliases in DTS so I can find
> their offsets in the flat tree (the *_find_node_by_alias() function is
> rather generic and could be moved to drivers/of/fdt.c if you think it
> would be useful for others).
>
> * There are no more users of MMIO_P2V in v2m.c, next thing I will do is
> the same in core tile; then the macro can be killed. Once this happens
> the virtual address currently taken from __MMIO_P2V(V2M_PA_CS7) will be
> replaced by some kind of "#define V2M_PERIPH_BASE 0xf8000000".
>
> * Once Nico's changes regarding static maps are in, the manual pointer
> operations in v2m_dt_map_io can be replaced with neat ioremap()-s.
>
> All feedback appreciated, cheers!
Look ok to me. Just a comment on the submission:
Even when you post something for review instead of inclusion, please add
a Signed-off-by: line and a diffstat.
Arnd
^ permalink raw reply
* [PATCH v2] ARM: OMAP2+: clock: cleanup CPUfreq leftovers
From: Kevin Hilman @ 2011-09-23 16:00 UTC (permalink / raw)
To: linux-arm-kernel
Now that we have OPP layer, and OMAP CPUfreq driver is using it, we no
longer need/use the clock framework code for filling up CPUfreq
tables. Remove it.
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c | 80 --------------------------
arch/arm/mach-omap2/clock.c | 5 --
arch/arm/mach-omap2/clock.h | 8 ---
3 files changed, 0 insertions(+), 93 deletions(-)
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 39f9d5a..9a13e07 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -164,83 +164,3 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate)
return 0;
}
-
-#ifdef CONFIG_CPU_FREQ
-/*
- * Walk PRCM rate table and fillout cpufreq freq_table
- * XXX This should be replaced by an OPP layer in the near future
- */
-static struct cpufreq_frequency_table *freq_table;
-
-void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
-{
- const struct prcm_config *prcm;
- int i = 0;
- int tbl_sz = 0;
-
- if (!cpu_is_omap24xx())
- return;
-
- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
- if (!(prcm->flags & cpu_mask))
- continue;
- if (prcm->xtal_speed != sclk->rate)
- continue;
-
- /* don't put bypass rates in table */
- if (prcm->dpll_speed == prcm->xtal_speed)
- continue;
-
- tbl_sz++;
- }
-
- /*
- * XXX Ensure that we're doing what CPUFreq expects for this error
- * case and the following one
- */
- if (tbl_sz == 0) {
- pr_warning("%s: no matching entries in rate_table\n",
- __func__);
- return;
- }
-
- /* Include the CPUFREQ_TABLE_END terminator entry */
- tbl_sz++;
-
- freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz,
- GFP_ATOMIC);
- if (!freq_table) {
- pr_err("%s: could not kzalloc frequency table\n", __func__);
- return;
- }
-
- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
- if (!(prcm->flags & cpu_mask))
- continue;
- if (prcm->xtal_speed != sclk->rate)
- continue;
-
- /* don't put bypass rates in table */
- if (prcm->dpll_speed == prcm->xtal_speed)
- continue;
-
- freq_table[i].index = i;
- freq_table[i].frequency = prcm->mpu_speed / 1000;
- i++;
- }
-
- freq_table[i].index = i;
- freq_table[i].frequency = CPUFREQ_TABLE_END;
-
- *table = &freq_table[0];
-}
-
-void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
-{
- if (!cpu_is_omap24xx())
- return;
-
- kfree(freq_table);
-}
-
-#endif
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 1f3481f..160e61c 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -536,10 +536,5 @@ struct clk_functions omap2_clk_functions = {
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
-#ifdef CONFIG_CPU_FREQ
- /* These will be removed when the OPP code is integrated */
- .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
- .clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table,
-#endif
};
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 48ac568..7fa20b3 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -144,14 +144,6 @@ extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
-extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
-extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
-#else
-#define omap2_clk_init_cpufreq_table 0
-#define omap2_clk_exit_cpufreq_table 0
-#endif
-
extern const struct clkops clkops_omap2_iclk_dflt_wait;
extern const struct clkops clkops_omap2_iclk_dflt;
extern const struct clkops clkops_omap2_iclk_idle_only;
--
1.7.6
^ permalink raw reply related
* [PATCH v3 0/3] genirq: handling GIC per-cpu interrupts
From: Marc Zyngier @ 2011-09-23 16:03 UTC (permalink / raw)
To: linux-arm-kernel
The current GIC per-cpu interrupts (aka PPIs) suffer from a number of
problems:
- They use a completely separate scheme to handle the interrupts,
mostly because the PPI concept doesn't really match the kernel view
of an interrupt.
- PPIs can only be used by the timer code, unless we add more low-level
assembly code.
- The local timer code can only be used by devices generating PPIs,
and not SPIs.
- At least one platform (msm) has started implementing its own
alternative scheme.
- Some low-level code gets duplicated, as usual...
The proposed solution is to handle the PPIs using the same path as
SPIs. A new core API is added to deal with per-cpu interrupts in a
less awkward way. The local timer code is updated to reflect these
changes.
The core API changes are based on an initial idea by Thomas Gleixner.
Tested on ARM Versatile Express (Cortex A15), ARM RealView PB11MP,
OMAP4 (Panda) and Tegra (Harmony). Patch series against next-20110923.
^ permalink raw reply
* [PATCH v3 1/3] genirq: add support for per-cpu dev_id interrupts
From: Marc Zyngier @ 2011-09-23 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316793788-14500-1-git-send-email-marc.zyngier@arm.com>
The ARM GIC interrupt controller offers per CPU interrupts (PPIs),
which are usually used to connect local timers to each core.
Each CPU has its own private interface to the GIC,
and only sees the PPIs that are directly connect to it.
While these timers are separate devices and have a separate
interrupt line to a core, they all use the same IRQ number.
For these devices, request_irq() is not the right API as it
assumes that an IRQ number is visible by a number of CPUs
(through the affinity setting), but makes it very awkward to
express that an IRQ number can be handled by all CPUs, and
yet be a different interrupt line on each CPU, requiring a
different dev_id cookie to be passed back to the handler.
The *_percpu_irq() functions is designed to overcome these
limitations, by providing a per-cpu dev_id vector:
int request_percpu_irq(unsigned int irq, irq_handler_t handler,
const char *devname, void __percpu *percpu_dev_id);
void free_percpu_irq(unsigned int, void __percpu *);
int setup_percpu_irq(unsigned int irq, struct irqaction *new);
void remove_percpu_irq(unsigned int irq, struct irqaction *act);
void enable_percpu_irq(unsigned int irq);
void disable_percpu_irq(unsigned int irq);
The API has a number of limitations:
- no interrupt sharing
- no threading
- common handler across all the CPUs
Once the interrupt is requested using setup_percpu_irq() or
request_percpu_irq(), it must be enabled by each core that wishes
its local interrupt to be delivered.
Based on an initial patch by Thomas Gleixner.
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/interrupt.h | 40 +++++++---
include/linux/irq.h | 16 ++++-
include/linux/irqdesc.h | 1 +
kernel/irq/Kconfig | 4 +
kernel/irq/chip.c | 54 ++++++++++++
kernel/irq/internals.h | 2 +
kernel/irq/irqdesc.c | 25 ++++++
kernel/irq/manage.c | 206 ++++++++++++++++++++++++++++++++++++++++++++-
kernel/irq/settings.h | 7 ++
9 files changed, 339 insertions(+), 16 deletions(-)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index a103732..85d07ce 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -95,6 +95,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
* @flags: flags (see IRQF_* above)
* @name: name of the device
* @dev_id: cookie to identify the device
+ * @percpu_dev_id: cookie to identify the device
* @next: pointer to the next irqaction for shared interrupts
* @irq: interrupt number
* @dir: pointer to the proc/irq/NN/name entry
@@ -104,17 +105,20 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
* @thread_mask: bitmask for keeping track of @thread activity
*/
struct irqaction {
- irq_handler_t handler;
- unsigned long flags;
- void *dev_id;
- struct irqaction *next;
- int irq;
- irq_handler_t thread_fn;
- struct task_struct *thread;
- unsigned long thread_flags;
- unsigned long thread_mask;
- const char *name;
- struct proc_dir_entry *dir;
+ irq_handler_t handler;
+ unsigned long flags;
+ void *dev_id;
+#ifdef CONFIG_IRQ_PERCPU_DEVID
+ void __percpu *percpu_dev_id;
+#endif
+ struct irqaction *next;
+ int irq;
+ irq_handler_t thread_fn;
+ struct task_struct *thread;
+ unsigned long thread_flags;
+ unsigned long thread_mask;
+ const char *name;
+ struct proc_dir_entry *dir;
} ____cacheline_internodealigned_in_smp;
extern irqreturn_t no_action(int cpl, void *dev_id);
@@ -136,6 +140,10 @@ extern int __must_check
request_any_context_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name, void *dev_id);
+extern int __must_check
+request_percpu_irq(unsigned int irq, irq_handler_t handler,
+ const char *devname, void __percpu *percpu_dev_id);
+
extern void exit_irq_thread(void);
#else
@@ -164,10 +172,18 @@ request_any_context_irq(unsigned int irq, irq_handler_t handler,
return request_irq(irq, handler, flags, name, dev_id);
}
+static inline int __must_check
+request_percpu_irq(unsigned int irq, irq_handler_t handler,
+ const char *devname, void __percpu *percpu_dev_id)
+{
+ return request_irq(irq, handler, 0, devname, percpu_dev_id);
+}
+
static inline void exit_irq_thread(void) { }
#endif
extern void free_irq(unsigned int, void *);
+extern void free_percpu_irq(unsigned int, void __percpu *);
struct device;
@@ -207,7 +223,9 @@ extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
extern void disable_irq_nosync(unsigned int irq);
extern void disable_irq(unsigned int irq);
+extern void disable_percpu_irq(unsigned int irq);
extern void enable_irq(unsigned int irq);
+extern void enable_percpu_irq(unsigned int irq);
/* The following three functions are for the core kernel use only. */
#ifdef CONFIG_GENERIC_HARDIRQS
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 73e31ab..59e49c8 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -66,6 +66,7 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data);
* IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set)
* IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context
* IRQ_NESTED_TRHEAD - Interrupt nests into another thread
+ * IRQ_PER_CPU_DEVID - Dev_id is a per-cpu variable
*/
enum {
IRQ_TYPE_NONE = 0x00000000,
@@ -88,12 +89,13 @@ enum {
IRQ_MOVE_PCNTXT = (1 << 14),
IRQ_NESTED_THREAD = (1 << 15),
IRQ_NOTHREAD = (1 << 16),
+ IRQ_PER_CPU_DEVID = (1 << 17),
};
#define IRQF_MODIFY_MASK \
(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
- IRQ_PER_CPU | IRQ_NESTED_THREAD)
+ IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID)
#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
@@ -367,6 +369,8 @@ enum {
struct irqaction;
extern int setup_irq(unsigned int irq, struct irqaction *new);
extern void remove_irq(unsigned int irq, struct irqaction *act);
+extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
+extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
extern void irq_cpu_online(void);
extern void irq_cpu_offline(void);
@@ -394,6 +398,7 @@ extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
+extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_nested_irq(unsigned int irq);
@@ -422,6 +427,8 @@ static inline void irq_set_chip_and_handler(unsigned int irq, struct irq_chip *c
irq_set_chip_and_handler_name(irq, chip, handle, NULL);
}
+extern int irq_set_percpu_devid(unsigned int irq);
+
extern void
__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
const char *name);
@@ -483,6 +490,13 @@ static inline void irq_set_nested_thread(unsigned int irq, bool nest)
irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
}
+static inline void irq_set_percpu_devid_flags(unsigned int irq)
+{
+ irq_set_status_flags(irq,
+ IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |
+ IRQ_NOPROBE | IRQ_PER_CPU_DEVID);
+}
+
/* Handle dynamic irq creation and destruction */
extern unsigned int create_irq_nr(unsigned int irq_want, int node);
extern int create_irq(void);
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 150134a..281ccd1 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -53,6 +53,7 @@ struct irq_desc {
unsigned long last_unhandled; /* Aging timer for unhandled count */
unsigned int irqs_unhandled;
raw_spinlock_t lock;
+ cpumask_var_t *percpu_enabled;
#ifdef CONFIG_SMP
const struct cpumask *affinity_hint;
struct irq_affinity_notify *affinity_notify;
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 5a38bf4..75c0631 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -60,6 +60,10 @@ config IRQ_DOMAIN
config IRQ_FORCED_THREADING
bool
+# Support per CPU dev id
+config IRQ_PERCPU_DEVID
+ bool
+
config SPARSE_IRQ
bool "Support sparse irq numbering"
depends on HAVE_SPARSE_IRQ
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index dc5114b..38942d8 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -204,6 +204,26 @@ void irq_disable(struct irq_desc *desc)
}
}
+#ifdef CONFIG_IRQ_PERCPU_DEVID
+void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu)
+{
+ if (desc->irq_data.chip->irq_enable)
+ desc->irq_data.chip->irq_enable(&desc->irq_data);
+ else
+ desc->irq_data.chip->irq_unmask(&desc->irq_data);
+ cpumask_set_cpu(cpu, *desc->percpu_enabled);
+}
+
+void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu)
+{
+ if (desc->irq_data.chip->irq_disable) {
+ desc->irq_data.chip->irq_disable(&desc->irq_data);
+ irq_state_set_masked(desc);
+ }
+ cpumask_clear_cpu(cpu, *desc->percpu_enabled);
+}
+#endif
+
static inline void mask_ack_irq(struct irq_desc *desc)
{
if (desc->irq_data.chip->irq_mask_ack)
@@ -544,6 +564,40 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
chip->irq_eoi(&desc->irq_data);
}
+#ifdef CONFIG_IRQ_PERCPU_DEVID
+/**
+ * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids
+ * @irq: the interrupt number
+ * @desc: the interrupt description structure for this irq
+ *
+ * Per CPU interrupts on SMP machines without locking requirements. Same as
+ * handle_percpu_irq() above but with the following extras:
+ *
+ * action->percpu_dev_id is a pointer to percpu variables which
+ * contain the real device id for the cpu on which this handler is
+ * called
+ */
+void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct irqaction *action = desc->action;
+ void *dev_id = __this_cpu_ptr(action->percpu_dev_id);
+ irqreturn_t res;
+
+ kstat_incr_irqs_this_cpu(irq, desc);
+
+ if (chip->irq_ack)
+ chip->irq_ack(&desc->irq_data);
+
+ trace_irq_handler_entry(irq, action);
+ res = action->handler(irq, dev_id);
+ trace_irq_handler_exit(irq, action, res);
+
+ if (chip->irq_eoi)
+ chip->irq_eoi(&desc->irq_data);
+}
+#endif
+
void
__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
const char *name)
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 6546431..04f8d5a 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -71,6 +71,8 @@ extern int irq_startup(struct irq_desc *desc);
extern void irq_shutdown(struct irq_desc *desc);
extern void irq_enable(struct irq_desc *desc);
extern void irq_disable(struct irq_desc *desc);
+extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
+extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
extern void mask_irq(struct irq_desc *desc);
extern void unmask_irq(struct irq_desc *desc);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 039b889..fa93f4d 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -443,6 +443,31 @@ void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus)
chip_bus_sync_unlock(desc);
}
+#ifdef CONFIG_IRQ_PERCPU_DEVID
+int irq_set_percpu_devid(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ if (!desc)
+ return -EINVAL;
+
+ if (desc->percpu_enabled)
+ return -EINVAL;
+
+ desc->percpu_enabled = kzalloc(sizeof(*desc->percpu_enabled), GFP_KERNEL);
+
+ if (!desc->percpu_enabled ||
+ !zalloc_cpumask_var(desc->percpu_enabled, GFP_KERNEL)) {
+ kfree(desc->percpu_enabled);
+ desc->percpu_enabled = NULL;
+ return -ENOMEM;
+ }
+
+ irq_set_percpu_devid_flags(irq);
+ return 0;
+}
+#endif
+
/**
* dynamic_irq_cleanup - cleanup a dynamically allocated irq
* @irq: irq number to initialize
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 7e1a3ed..2e05d92 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1121,6 +1121,8 @@ int setup_irq(unsigned int irq, struct irqaction *act)
int retval;
struct irq_desc *desc = irq_to_desc(irq);
+ if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+ return -EINVAL;
chip_bus_lock(desc);
retval = __setup_irq(irq, desc, act);
chip_bus_sync_unlock(desc);
@@ -1129,7 +1131,7 @@ int setup_irq(unsigned int irq, struct irqaction *act)
}
EXPORT_SYMBOL_GPL(setup_irq);
- /*
+/*
* Internal function to unregister an irqaction - used to free
* regular and special interrupts that are part of the architecture.
*/
@@ -1227,7 +1229,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
*/
void remove_irq(unsigned int irq, struct irqaction *act)
{
- __free_irq(irq, act->dev_id);
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+ __free_irq(irq, act->dev_id);
}
EXPORT_SYMBOL_GPL(remove_irq);
@@ -1249,7 +1254,7 @@ void free_irq(unsigned int irq, void *dev_id)
{
struct irq_desc *desc = irq_to_desc(irq);
- if (!desc)
+ if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
return;
#ifdef CONFIG_SMP
@@ -1327,7 +1332,8 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
if (!desc)
return -EINVAL;
- if (!irq_settings_can_request(desc))
+ if (!irq_settings_can_request(desc) ||
+ WARN_ON(irq_settings_is_per_cpu_devid(desc)))
return -EINVAL;
if (!handler) {
@@ -1412,3 +1418,195 @@ int request_any_context_irq(unsigned int irq, irq_handler_t handler,
return !ret ? IRQC_IS_HARDIRQ : ret;
}
EXPORT_SYMBOL_GPL(request_any_context_irq);
+
+#ifdef CONFIG_IRQ_PERCPU_DEVID
+void enable_percpu_irq(unsigned int irq)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned long flags;
+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+
+ if (!desc)
+ return;
+
+ irq_percpu_enable(desc, cpu);
+ irq_put_desc_busunlock(desc, flags);
+}
+EXPORT_SYMBOL_GPL(enable_percpu_irq);
+
+void disable_percpu_irq(unsigned int irq)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned long flags;
+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+
+ if (!desc)
+ return;
+
+ irq_percpu_disable(desc, cpu);
+ irq_put_desc_busunlock(desc, flags);
+}
+EXPORT_SYMBOL_GPL(disable_percpu_irq);
+
+/*
+ * Internal function to unregister a percpu irqaction.
+ */
+static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct irqaction *action;
+ unsigned long flags;
+
+ WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
+
+ if (!desc)
+ return NULL;
+
+ raw_spin_lock_irqsave(&desc->lock, flags);
+
+ action = desc->action;
+ if (!action || action->percpu_dev_id != dev_id) {
+ WARN(1, "Trying to free already-free IRQ %d\n", irq);
+ goto bad;
+ }
+
+ if (!cpumask_empty(*desc->percpu_enabled)) {
+ WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",
+ irq, cpumask_first(*desc->percpu_enabled));
+ goto bad;
+ }
+
+ /* Found it - now remove it from the list of entries: */
+ desc->action = NULL;
+
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
+
+ unregister_handler_proc(irq, action);
+
+ module_put(desc->owner);
+ return action;
+
+bad:
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
+ return NULL;
+}
+
+/**
+ * remove_percpu_irq - free a per-cpu interrupt
+ * @irq: Interrupt line to free
+ * @act: irqaction for the interrupt
+ *
+ * Used to remove interrupts statically setup by the early boot process.
+ */
+void remove_percpu_irq(unsigned int irq, struct irqaction *act)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ if (desc && irq_settings_is_per_cpu_devid(desc))
+ __free_percpu_irq(irq, act->percpu_dev_id);
+}
+EXPORT_SYMBOL_GPL(remove_percpu_irq);
+
+/**
+ * free_percpu_irq - free an interrupt allocated with request_percpu_irq
+ * @irq: Interrupt line to free
+ * @dev_id: Device identity to free
+ *
+ * Remove a percpu interrupt handler. The handler is removed, but
+ * the interrupt line is not disabled. This must be done on each
+ * CPU before calling this function. The function does not return
+ * until any executing interrupts for this IRQ have completed.
+ *
+ * This function must not be called from interrupt context.
+ */
+void free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ if (!desc || !irq_settings_is_per_cpu_devid(desc))
+ return;
+
+#ifdef CONFIG_SMP
+ if (WARN_ON(desc->affinity_notify))
+ desc->affinity_notify = NULL;
+#endif
+
+ chip_bus_lock(desc);
+ kfree(__free_percpu_irq(irq, dev_id));
+ chip_bus_sync_unlock(desc);
+}
+EXPORT_SYMBOL_GPL(free_percpu_irq);
+
+/**
+ * setup_percpu_irq - setup a per-cpu interrupt
+ * @irq: Interrupt line to setup
+ * @act: irqaction for the interrupt
+ *
+ * Used to statically setup per-cpu interrupts in the early boot process.
+ */
+int setup_percpu_irq(unsigned int irq, struct irqaction *act)
+{
+ int retval;
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ if (!irq_settings_is_per_cpu_devid(desc))
+ return -EINVAL;
+ chip_bus_lock(desc);
+ retval = __setup_irq(irq, desc, act);
+ chip_bus_sync_unlock(desc);
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(setup_percpu_irq);
+
+/**
+ * request_percpu_irq - allocate a percpu interrupt line
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs.
+ * @devname: An ascii name for the claiming device
+ * @dev_id: A percpu cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources, but doesn't
+ * automatically enable the interrupt. It has to be done on each
+ * CPU using enable_percpu_irq().
+ *
+ * Dev_id must be globally unique. It is a per-cpu variable, and
+ * the handler gets called with the interrupted CPU's instance of
+ * that variable.
+ */
+int request_percpu_irq(unsigned int irq, irq_handler_t handler,
+ const char *devname, void __percpu *dev_id)
+{
+ struct irqaction *action;
+ struct irq_desc *desc;
+ int retval;
+
+ if (!dev_id)
+ return -EINVAL;
+
+ desc = irq_to_desc(irq);
+ if (!desc || !irq_settings_can_request(desc) ||
+ !irq_settings_is_per_cpu_devid(desc))
+ return -EINVAL;
+
+ action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+ if (!action)
+ return -ENOMEM;
+
+ action->handler = handler;
+ action->flags = IRQF_PERCPU;
+ action->name = devname;
+ action->percpu_dev_id = dev_id;
+
+ chip_bus_lock(desc);
+ retval = __setup_irq(irq, desc, action);
+ chip_bus_sync_unlock(desc);
+
+ if (retval)
+ kfree(action);
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(request_percpu_irq);
+
+#endif
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
index f166783..1162f10 100644
--- a/kernel/irq/settings.h
+++ b/kernel/irq/settings.h
@@ -13,6 +13,7 @@ enum {
_IRQ_MOVE_PCNTXT = IRQ_MOVE_PCNTXT,
_IRQ_NO_BALANCING = IRQ_NO_BALANCING,
_IRQ_NESTED_THREAD = IRQ_NESTED_THREAD,
+ _IRQ_PER_CPU_DEVID = IRQ_PER_CPU_DEVID,
_IRQF_MODIFY_MASK = IRQF_MODIFY_MASK,
};
@@ -24,6 +25,7 @@ enum {
#define IRQ_NOTHREAD GOT_YOU_MORON
#define IRQ_NOAUTOEN GOT_YOU_MORON
#define IRQ_NESTED_THREAD GOT_YOU_MORON
+#define IRQ_PER_CPU_DEVID GOT_YOU_MORON
#undef IRQF_MODIFY_MASK
#define IRQF_MODIFY_MASK GOT_YOU_MORON
@@ -39,6 +41,11 @@ static inline bool irq_settings_is_per_cpu(struct irq_desc *desc)
return desc->status_use_accessors & _IRQ_PER_CPU;
}
+static inline bool irq_settings_is_per_cpu_devid(struct irq_desc *desc)
+{
+ return desc->status_use_accessors & _IRQ_PER_CPU_DEVID;
+}
+
static inline void irq_settings_set_per_cpu(struct irq_desc *desc)
{
desc->status_use_accessors |= _IRQ_PER_CPU;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 2/3] ARM: gic: consolidate PPI handling
From: Marc Zyngier @ 2011-09-23 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316793788-14500-1-git-send-email-marc.zyngier@arm.com>
PPI handling is a bit of an odd beast. It uses its own low level
handling code and is hardwired to the local timers (hence lacking
a registration interface).
Instead, switch the low handling to the normal SPI handling code.
PPIs are handled by the handle_percpu_devid_irq flow.
This also allows the removal of some duplicated code.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: David Brown <davidb@codeaurora.org>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/common/Kconfig | 1 +
arch/arm/common/gic.c | 70 +++++++++++++++++++-
arch/arm/include/asm/entry-macro-multi.S | 7 --
arch/arm/include/asm/hardirq.h | 3 -
arch/arm/include/asm/hardware/entry-macro-gic.S | 19 +-----
arch/arm/include/asm/localtimer.h | 6 +-
arch/arm/include/asm/smp.h | 5 --
arch/arm/kernel/irq.c | 3 -
arch/arm/kernel/smp.c | 27 ++------
arch/arm/mach-exynos4/include/mach/entry-macro.S | 6 +--
arch/arm/mach-msm/board-msm8x60.c | 11 ---
arch/arm/mach-msm/include/mach/entry-macro-qgic.S | 73 +--------------------
arch/arm/mach-omap2/include/mach/entry-macro.S | 14 +----
arch/arm/mach-shmobile/entry-intc.S | 3 -
arch/arm/mach-shmobile/include/mach/entry-macro.S | 3 -
15 files changed, 84 insertions(+), 167 deletions(-)
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 4b71766..114a432 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,4 +1,5 @@
config ARM_GIC
+ select IRQ_PERCPU_DEVID
bool
config ARM_VIC
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index bdbb3f7..9b83077 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -28,10 +28,14 @@
#include <linux/smp.h>
#include <linux/cpumask.h>
#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
+#include <asm/localtimer.h>
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -255,6 +259,32 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
irq_set_chained_handler(irq, gic_handle_cascade_irq);
}
+#ifdef CONFIG_LOCAL_TIMERS
+#define gic_ppi_handler percpu_timer_handler
+#else
+static irqreturn_t gic_ppi_handler(int irq, void *dev_id)
+{
+ return IRQ_NONE;
+}
+#endif
+
+#define PPI_IRQACT(nr) \
+ { \
+ .handler = gic_ppi_handler, \
+ .flags = IRQF_PERCPU | IRQF_TIMER, \
+ .irq = nr, \
+ .name = "PPI-" # nr, \
+ }
+
+static struct irqaction ppi_irqaction_template[16] __initdata = {
+ PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3),
+ PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7),
+ PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11),
+ PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15),
+};
+
+static struct irqaction *ppi_irqaction;
+
static void __init gic_dist_init(struct gic_chip_data *gic,
unsigned int irq_start)
{
@@ -262,6 +292,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
u32 cpumask;
void __iomem *base = gic->dist_base;
u32 cpu = 0;
+ u32 nrppis = 0, ppi_base = 0;
#ifdef CONFIG_SMP
cpu = cpu_logical_map(smp_processor_id());
@@ -283,6 +314,28 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
gic_irqs = 1020;
/*
+ * Nobody would be insane enough to use PPIs on a secondary
+ * GIC, right?
+ */
+ if (gic == &gic_data[0]) {
+ nrppis = 16 - (irq_start & 15);
+ ppi_base = gic->irq_offset + 32 - nrppis;
+
+ ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis],
+ sizeof(*ppi_irqaction) * nrppis,
+ GFP_KERNEL);
+
+ if (nrppis && !ppi_irqaction) {
+ pr_err("GIC: Can't allocate PPI memory");
+ nrppis = 0;
+ ppi_base = 0;
+ }
+ }
+
+ pr_info("Configuring GIC with %d sources (%d PPIs)\n",
+ gic_irqs, (gic == &gic_data[0]) ? nrppis : 0);
+
+ /*
* Set all global interrupts to be level triggered, active low.
*/
for (i = 32; i < gic_irqs; i += 16)
@@ -317,7 +370,22 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
/*
* Setup the Linux IRQ subsystem.
*/
- for (i = irq_start; i < irq_limit; i++) {
+ for (i = 0; i < nrppis; i++) {
+ int ppi = i + ppi_base;
+ int err;
+
+ irq_set_percpu_devid(ppi);
+ irq_set_chip_and_handler(ppi, &gic_chip,
+ handle_percpu_devid_irq);
+ irq_set_chip_data(ppi, gic);
+ set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN);
+
+ err = setup_percpu_irq(ppi, &ppi_irqaction[i]);
+ if (err)
+ pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err);
+ }
+
+ for (i = irq_start + nrppis; i < irq_limit; i++) {
irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
irq_set_chip_data(i, gic);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 2f1e209..88d6181 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -25,13 +25,6 @@
movne r1, sp
adrne lr, BSYM(1b)
bne do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
- test_for_ltirq r0, r2, r6, lr
- movne r0, sp
- adrne lr, BSYM(1b)
- bne do_local_timer
-#endif
#endif
9997:
.endm
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 89ad180..ddf07a9 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -9,9 +9,6 @@
typedef struct {
unsigned int __softirq_pending;
-#ifdef CONFIG_LOCAL_TIMERS
- unsigned int local_timer_irqs;
-#endif
#ifdef CONFIG_SMP
unsigned int ipi_irqs[NR_IPI];
#endif
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
index c115b82..74ebc80 100644
--- a/arch/arm/include/asm/hardware/entry-macro-gic.S
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -22,15 +22,11 @@
* interrupt controller spec. To wit:
*
* Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
+ * 16-31 are local. We allow 30 to be used for the watchdog.
* 32-1020 are global
* 1021-1022 are reserved
* 1023 is "spurious" (no interrupt)
*
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
- *
* A simple read from the controller will tell us the number of the highest
* priority enabled interrupt. We then just need to check whether it is in the
* valid range for an IRQ (30-1020 inclusive).
@@ -43,7 +39,7 @@
ldr \tmp, =1021
bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
+ cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
@@ -62,14 +58,3 @@
strcc \irqstat, [\base, #GIC_CPU_EOI]
cmpcs \irqnr, \irqnr
.endm
-
-/* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
index 080d74f..e3663f7 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -10,6 +10,8 @@
#ifndef __ASM_ARM_LOCALTIMER_H
#define __ASM_ARM_LOCALTIMER_H
+#include <linux/interrupt.h>
+
struct clock_event_device;
/*
@@ -18,9 +20,9 @@ struct clock_event_device;
void percpu_timer_setup(void);
/*
- * Called from assembly, this is the local timer IRQ handler
+ * Per-cpu timer IRQ handler
*/
-asmlinkage void do_local_timer(struct pt_regs *);
+irqreturn_t percpu_timer_handler(int irq, void *dev_id);
#ifdef CONFIG_LOCAL_TIMERS
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 674ebcd..7c2299f 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -94,9 +94,4 @@ extern void platform_cpu_enable(unsigned int cpu);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-/*
- * show local interrupt info
- */
-extern void show_local_irqs(struct seq_file *, int);
-
#endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index e20a5d0..8e744f6 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -58,9 +58,6 @@ int arch_show_interrupts(struct seq_file *p, int prec)
#ifdef CONFIG_SMP
show_ipi_list(p, prec);
#endif
-#ifdef CONFIG_LOCAL_TIMERS
- show_local_irqs(p, prec);
-#endif
seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
return 0;
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e08d2e8..8f73342 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -504,10 +504,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
for (i = 0; i < NR_IPI; i++)
sum += __get_irq_stat(cpu, ipi_irqs[i]);
-#ifdef CONFIG_LOCAL_TIMERS
- sum += __get_irq_stat(cpu, local_timer_irqs);
-#endif
-
return sum;
}
@@ -525,29 +521,16 @@ static void ipi_timer(void)
}
#ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
+irqreturn_t percpu_timer_handler(int irq, void *dev_id)
{
- struct pt_regs *old_regs = set_irq_regs(regs);
- int cpu = smp_processor_id();
+ struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
if (local_timer_ack()) {
- __inc_irq_stat(cpu, local_timer_irqs);
- ipi_timer();
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
}
- set_irq_regs(old_regs);
-}
-
-void show_local_irqs(struct seq_file *p, int prec)
-{
- unsigned int cpu;
-
- seq_printf(p, "%*s: ", prec, "LOC");
-
- for_each_present_cpu(cpu)
- seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
-
- seq_printf(p, " Local timer interrupts\n");
+ return IRQ_NONE;
}
#endif
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index d7a1e28..807d05d 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -55,7 +55,7 @@
bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
+ cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
@@ -77,7 +77,3 @@
cmpcs \irqnr, \irqnr
.endm
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- .endm
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index a4bd858..30c6b58 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -53,8 +53,6 @@ static void __init msm8x60_map_io(void)
static void __init msm8x60_init_irq(void)
{
- unsigned int i;
-
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
@@ -66,15 +64,6 @@ static void __init msm8x60_init_irq(void)
*/
if (!machine_is_msm8x60_sim())
writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
- /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
- * as they are configured as level, which does not play nice with
- * handle_percpu_irq.
- */
- for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
- if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
- irq_set_handler(i, handle_percpu_irq);
- }
}
static void __init msm8x60_init(void)
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
index 1246715..717076f 100644
--- a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
+++ b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
@@ -8,81 +8,10 @@
* warranty of any kind, whether express or implied.
*/
-#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =gic_cpu_base_addr
- ldr \base, [\base]
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Migrated the code from ARM MP port to be more consistent
- * with interrupt processing , the following still holds true
- * however, all interrupts are treated the same regardless of
- * if they are local IPI or PPI
- *
- * Interrupts 0-15 are IPI
- * 16-31 are PPI
- * (16-18 are the timers)
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * A simple read from the controller will tell us the number of the
- * highest priority enabled interrupt. We then just need to check
- * whether it is in the valid range for an IRQ (0-1020 inclusive).
- *
- * Base ARM code assumes that the local (private) peripheral interrupts
- * are not valid, we treat them differently, in that the privates are
- * handled like normal shared interrupts with the exception that only
- * one processor can register the interrupt and the handler must be
- * the same for all processors.
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
- 9-0 =int # */
-
- bic \irqnr, \irqstat, #0x1c00 @mask src
- cmp \irqnr, #15
- ldr \tmp, =1021
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
-
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt on the
- * controller, since this requires the original irqstat value which
- * we won't easily be able to recreate later.
- */
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #16
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index ceb8b7e..feb90a1 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -78,7 +78,7 @@
4401: ldr \irqstat, [\base, #GIC_CPU_INTACK]
ldr \tmp, =1021
bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
+ cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
@@ -101,18 +101,6 @@
it cs
cmpcs \irqnr, \irqnr
.endm
-
- /* As above, this assumes that irqstat and base are preserved */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- itt eq
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
#endif /* CONFIG_SMP */
#else /* MULTI_OMAP2 */
diff --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S
index cac0a7a..1a1c00c 100644
--- a/arch/arm/mach-shmobile/entry-intc.S
+++ b/arch/arm/mach-shmobile/entry-intc.S
@@ -51,7 +51,4 @@
.macro test_for_ipi, irqnr, irqstat, base, tmp
.endm
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- .endm
-
arch_irq_handler shmobile_handle_irq_intc
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S
index d791f10..8d4a416 100644
--- a/arch/arm/mach-shmobile/include/mach/entry-macro.S
+++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S
@@ -27,8 +27,5 @@
.macro test_for_ipi, irqnr, irqstat, base, tmp
.endm
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 3/3] ARM: gic, local timers: use the request_percpu_irq() interface
From: Marc Zyngier @ 2011-09-23 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316793788-14500-1-git-send-email-marc.zyngier@arm.com>
This patch remove the hardcoded link between local timers and PPIs,
and convert the PPI users (TWD and MSM timers) to the new *_percpu_irq
interface. Also some collateral cleanup (local_timer_ack() is gone,
and the interrupt handler is strictly private to each driver).
PPIs are now useable for more than just the local timers.
Cc: David Brown <davidb@codeaurora.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/common/gic.c | 52 --------------------------
arch/arm/include/asm/hardware/gic.h | 1 -
arch/arm/include/asm/localtimer.h | 17 ++++-----
arch/arm/include/asm/smp_twd.h | 2 +-
arch/arm/kernel/smp.c | 16 +--------
arch/arm/kernel/smp_twd.c | 47 +++++++++++++++++++++++-
arch/arm/mach-exynos4/mct.c | 5 ---
arch/arm/mach-msm/timer.c | 69 ++++++++++++++++++++---------------
8 files changed, 94 insertions(+), 115 deletions(-)
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 9b83077..a3f335c 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -35,7 +35,6 @@
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
-#include <asm/localtimer.h>
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -259,32 +258,6 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
irq_set_chained_handler(irq, gic_handle_cascade_irq);
}
-#ifdef CONFIG_LOCAL_TIMERS
-#define gic_ppi_handler percpu_timer_handler
-#else
-static irqreturn_t gic_ppi_handler(int irq, void *dev_id)
-{
- return IRQ_NONE;
-}
-#endif
-
-#define PPI_IRQACT(nr) \
- { \
- .handler = gic_ppi_handler, \
- .flags = IRQF_PERCPU | IRQF_TIMER, \
- .irq = nr, \
- .name = "PPI-" # nr, \
- }
-
-static struct irqaction ppi_irqaction_template[16] __initdata = {
- PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3),
- PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7),
- PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11),
- PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15),
-};
-
-static struct irqaction *ppi_irqaction;
-
static void __init gic_dist_init(struct gic_chip_data *gic,
unsigned int irq_start)
{
@@ -320,16 +293,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
if (gic == &gic_data[0]) {
nrppis = 16 - (irq_start & 15);
ppi_base = gic->irq_offset + 32 - nrppis;
-
- ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis],
- sizeof(*ppi_irqaction) * nrppis,
- GFP_KERNEL);
-
- if (nrppis && !ppi_irqaction) {
- pr_err("GIC: Can't allocate PPI memory");
- nrppis = 0;
- ppi_base = 0;
- }
}
pr_info("Configuring GIC with %d sources (%d PPIs)\n",
@@ -372,17 +335,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
*/
for (i = 0; i < nrppis; i++) {
int ppi = i + ppi_base;
- int err;
irq_set_percpu_devid(ppi);
irq_set_chip_and_handler(ppi, &gic_chip,
handle_percpu_devid_irq);
irq_set_chip_data(ppi, gic);
set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN);
-
- err = setup_percpu_irq(ppi, &ppi_irqaction[i]);
- if (err)
- pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err);
}
for (i = irq_start + nrppis; i < irq_limit; i++) {
@@ -443,16 +401,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr)
gic_cpu_init(&gic_data[gic_nr]);
}
-void __cpuinit gic_enable_ppi(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- irq_set_status_flags(irq, IRQ_NOPROBE);
- gic_unmask_irq(irq_get_irq_data(irq));
- local_irq_restore(flags);
-}
-
#ifdef CONFIG_SMP
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 435d3f8..2dadd50 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -40,7 +40,6 @@ void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
void gic_secondary_init(unsigned int);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-void gic_enable_ppi(unsigned int);
struct gic_chip_data {
unsigned int irq_offset;
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
index e3663f7..f5e1cec 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -19,27 +19,20 @@ struct clock_event_device;
*/
void percpu_timer_setup(void);
-/*
- * Per-cpu timer IRQ handler
- */
-irqreturn_t percpu_timer_handler(int irq, void *dev_id);
-
-
#ifdef CONFIG_LOCAL_TIMERS
#ifdef CONFIG_HAVE_ARM_TWD
#include "smp_twd.h"
-#define local_timer_ack() twd_timer_ack()
+#define local_timer_stop(c) twd_timer_stop((c))
#else
/*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
+ * Stop the local timer
*/
-int local_timer_ack(void);
+void local_timer_stop(struct clock_event_device *);
#endif
@@ -54,6 +47,10 @@ static inline int local_timer_setup(struct clock_event_device *evt)
{
return -ENXIO;
}
+
+static inline void local_timer_stop(struct clock_event_device *evt)
+{
+}
#endif
#endif
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index fed9981..ef9ffba 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -22,7 +22,7 @@ struct clock_event_device;
extern void __iomem *twd_base;
-int twd_timer_ack(void);
void twd_timer_setup(struct clock_event_device *);
+void twd_timer_stop(struct clock_event_device *);
#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8f73342..fcca40b 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -520,20 +520,6 @@ static void ipi_timer(void)
irq_exit();
}
-#ifdef CONFIG_LOCAL_TIMERS
-irqreturn_t percpu_timer_handler(int irq, void *dev_id)
-{
- struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
-
- if (local_timer_ack()) {
- evt->event_handler(evt);
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
-}
-#endif
-
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask)
{
@@ -584,7 +570,7 @@ static void percpu_timer_stop(void)
unsigned int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ local_timer_stop(evt);
}
#endif
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 01c1862..566c0fe 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
#include <asm/hardware/gic.h>
/* set up by the platform code */
@@ -26,6 +27,8 @@ void __iomem *twd_base;
static unsigned long twd_timer_rate;
+static struct clock_event_device __percpu **twd_evt;
+
static void twd_set_mode(enum clock_event_mode mode,
struct clock_event_device *clk)
{
@@ -80,6 +83,12 @@ int twd_timer_ack(void)
return 0;
}
+void twd_timer_stop(struct clock_event_device *clk)
+{
+ twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+ disable_percpu_irq(clk->irq);
+}
+
static void __cpuinit twd_calibrate_rate(void)
{
unsigned long count;
@@ -119,11 +128,43 @@ static void __cpuinit twd_calibrate_rate(void)
}
}
+static irqreturn_t twd_handler(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+ if (twd_timer_ack()) {
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
+ struct clock_event_device **this_cpu_clk;
+
+ if (!twd_evt) {
+ int err;
+
+ twd_evt = alloc_percpu(struct clock_event_device *);
+ if (!twd_evt) {
+ pr_err("twd: can't allocate memory\n");
+ return;
+ }
+
+ err = request_percpu_irq(clk->irq, twd_handler,
+ "twd", twd_evt);
+ if (err) {
+ pr_err("twd: can't register interrupt %d (%d)\n",
+ clk->irq, err);
+ return;
+ }
+ }
+
twd_calibrate_rate();
clk->name = "local_timer";
@@ -137,8 +178,10 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
+ this_cpu_clk = __this_cpu_ptr(twd_evt);
+ *this_cpu_clk = clk;
+
clockevents_register_device(clk);
- /* Make sure our local interrupt controller has this enabled */
- gic_enable_ppi(clk->irq);
+ enable_percpu_irq(clk->irq);
}
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index ddd8686..b3a0016 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -402,11 +402,6 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
return 0;
}
-int local_timer_ack(void)
-{
- return 0;
-}
-
#endif /* CONFIG_LOCAL_TIMERS */
static void __init exynos4_timer_resources(void)
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 63621f1..701d5e6 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -71,12 +71,16 @@ enum timer_location {
struct msm_clock {
struct clock_event_device clockevent;
struct clocksource clocksource;
- struct irqaction irq;
+ unsigned int irq;
void __iomem *regbase;
uint32_t freq;
uint32_t shift;
void __iomem *global_counter;
void __iomem *local_counter;
+ union {
+ struct clock_event_device *evt;
+ struct clock_event_device __percpu **percpu_evt;
+ };
};
enum {
@@ -87,13 +91,10 @@ enum {
static struct msm_clock msm_clocks[];
-static struct clock_event_device *local_clock_event;
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = dev_id;
- if (smp_processor_id() != 0)
- evt = local_clock_event;
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
if (evt->event_handler == NULL)
return IRQ_HANDLED;
evt->event_handler(evt);
@@ -171,13 +172,7 @@ static struct msm_clock msm_clocks[] = {
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
},
- .irq = {
- .name = "gp_timer",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
- .handler = msm_timer_interrupt,
- .dev_id = &msm_clocks[0].clockevent,
- .irq = INT_GP_TIMER_EXP
- },
+ .irq = INT_GP_TIMER_EXP,
.freq = GPT_HZ,
},
[MSM_CLOCK_DGT] = {
@@ -196,13 +191,7 @@ static struct msm_clock msm_clocks[] = {
.mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
},
- .irq = {
- .name = "dg_timer",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
- .handler = msm_timer_interrupt,
- .dev_id = &msm_clocks[1].clockevent,
- .irq = INT_DEBUG_TIMER_EXP
- },
+ .irq = INT_DEBUG_TIMER_EXP,
.freq = DGT_HZ >> MSM_DGT_SHIFT,
.shift = MSM_DGT_SHIFT,
}
@@ -261,10 +250,30 @@ static void __init msm_timer_init(void)
printk(KERN_ERR "msm_timer_init: clocksource_register "
"failed for %s\n", cs->name);
- res = setup_irq(clock->irq.irq, &clock->irq);
+ ce->irq = clock->irq;
+ if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+ clock->percpu_evt = alloc_percpu(struct clock_event_device *);
+ if (!clock->percpu_evt) {
+ pr_err("msm_timer_init: memory allocation "
+ "failed for %s\n", ce->name);
+ continue;
+ }
+
+ *__this_cpu_ptr(clock->percpu_evt) = ce;
+ res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+ ce->name, clock->percpu_evt);
+ if (!res)
+ enable_percpu_irq(ce->irq);
+ } else {
+ clock->evt = ce;
+ res = request_irq(ce->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+ ce->name, &clock->evt);
+ }
+
if (res)
- printk(KERN_ERR "msm_timer_init: setup_irq "
- "failed for %s\n", cs->name);
+ pr_err("msm_timer_init: request_irq failed for %s\n",
+ ce->name);
clockevents_register_device(ce);
}
@@ -273,6 +282,7 @@ static void __init msm_timer_init(void)
#ifdef CONFIG_SMP
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
+ static bool local_timer_inited;
struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
/* Use existing clock_event for cpu 0 */
@@ -281,12 +291,13 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
- if (!local_clock_event) {
+ if (!local_timer_inited) {
writel(0, clock->regbase + TIMER_ENABLE);
writel(0, clock->regbase + TIMER_CLEAR);
writel(~0, clock->regbase + TIMER_MATCH_VAL);
+ local_timer_inited = true;
}
- evt->irq = clock->irq.irq;
+ evt->irq = clock->irq;
evt->name = "local_timer";
evt->features = CLOCK_EVT_FEAT_ONESHOT;
evt->rating = clock->clockevent.rating;
@@ -298,17 +309,17 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
evt->min_delta_ns = clockevent_delta2ns(4, evt);
- local_clock_event = evt;
-
- gic_enable_ppi(clock->irq.irq);
+ *__this_cpu_ptr(clock->percpu_evt) = evt;
+ enable_percpu_irq(evt->irq);
clockevents_register_device(evt);
return 0;
}
-inline int local_timer_ack(void)
+void local_timer_stop(struct clock_event_device *evt)
{
- return 1;
+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ disable_percpu_irq(evt->irq);
}
#endif
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2] AM3517 : support for suspend/resume
From: Kevin Hilman @ 2011-09-23 16:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <FCCFB4CDC6E5564B9182F639FC356087037AF843F0@dbde02.ent.ti.com>
"Koyamangalath, Abhilash" <abhilash.kv@ti.com> writes:
[...]
>>> @@ -485,6 +489,8 @@ console_still_active:
>>>
>>> int omap3_can_sleep(void)
>>> {
>>> + if (cpu_is_omap3505() || cpu_is_omap3517())
>>> + return 0;
>>
>> This needs to be a separate patch with a descriptive changelog and
>> justification as to why you can't do WFI in idle.
> [Abhilash K V]OK
>>
>> Adding something like this means the device will *never* attempt a WFI
>> during idle.
>
> [Abhilash K V] This patch was put in as dynamic sleep feature is not
> supported by the device, there are no C states etc. The only PM
> supported is forced suspend /resume. There is just one power-domain
> and it can be in ON or RET states.
>
If the device can WFI and hit retention in suspend, there should be no
not to target the same power state in idle.
You don't have to have CPUidle with multiple C-states to use idle.
>> I suspect that avoiding WFI in idle is masking a bug that you don't see
>> in the suspend path.
>
> [Abhilash K V] I need to recap a bit to find out if there is a better
> way to indicate the lack of "idle" feature.
Yes please. From my POV, deciding not to go idle is a SW decision, not
a hardware decision. As the same SW mechanisms are involved, whatever
power state that can be acheived from suspend should be targetted in
idle.
Kevin
^ permalink raw reply
* [PATCH 0/4] arm/tegra: Convert gpio & pinmux to platform devices
From: Arnd Bergmann @ 2011-09-23 16:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725567-17881-1-git-send-email-swarren@nvidia.com>
On Thursday 22 September 2011, Stephen Warren wrote:
>
> This series converts the Tegra GPIO and pinmux drivers to be regular
> platform devices.
Looks good overall.
> The series is extracted from an earlier series I posted that augmented
> these drivers to initialize HW state from the device-tree. I'm holding
> off on that aspect of the changes, since it's not entirely clear to me
> whether the new pinmux API should drive the initial pinmux state setup
> via "system hog" definitions, or whether pinmux drivers should indeed
> do their own thing.
I think at least you should try to do an ioremap of the pinmux register
area in the pinmux probe function and make sure that it's called early
enough, if at all possible.
Right now, there is an empty probe() function, which is a bit silly,
and the pg_readl()/pg_writel() functions use hardcoded register
addresses.
Arnd
^ permalink raw reply
* [RFC PATCH 00/14] Switch GIC users (and omap2plus) to CONFIG_MULTI_IRQ_HANDLER
From: Marc Zyngier @ 2011-09-23 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In order to support multiple primary interrupt controllers in the same
image, it is necessary to use the MULTI_IRQ_HANDLER config option.
This patch series makes a first step in that direction by:
- having the GIC code to provides a global handler,
- make GIC users to provide this handler from their machine descriptor.
A side effect of this is that it forces OMAP2/3 platforms to be
converted too in order to preserve the MULTI_OMAP feature. This leads
to a certain simplification of the interrupt handling for the
OMAP2/3/4 platforms.
The primary IRQ handlers have been written in C, and the performance
degradation is hardly noticeable. Should some tests reveal a major
increase in latency, it is always possible to restore the ASM version.
This series has been tested on VE (A9, A5, A15), PB11MP, Panda, IGEPv2
and Harmony. Patches against next-2011 plus my PPI series.
Marc Zyngier (14):
ARM: GIC: Add global gic_handle_irq() function
ARM: RealView: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: VExpress: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: msm: convert SMP platforms to CONFIG_MULTI_IRQ_HANDLER
ARM: GIC: Add global gic_handle_irq_offset() function
ARM: exynos4: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: tegra2: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: ux500: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: shmobile: convert smp platforms to gic_handle_irq()
ARM: cns3xxx: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: zynq: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: omap2/3: Add global omap2/3_intc_handle_irq() functions
ARM: omap2plus: convert to CONFIG_MULTI_IRQ_HANDLER
ARM: GIC: Make MULTI_IRQ_HANDLER mandatory
arch/arm/Kconfig | 2 +
arch/arm/common/Kconfig | 1 +
arch/arm/common/gic.c | 49 +++++++-
arch/arm/include/asm/hardware/entry-macro-gic.S | 60 ---------
arch/arm/include/asm/hardware/gic.h | 3 +-
arch/arm/mach-cns3xxx/cns3420vb.c | 2 +
arch/arm/mach-cns3xxx/include/mach/entry-macro.S | 2 -
arch/arm/mach-exynos4/include/mach/entry-macro.S | 62 ---------
arch/arm/mach-exynos4/mach-armlex4210.c | 2 +
arch/arm/mach-exynos4/mach-nuri.c | 2 +
arch/arm/mach-exynos4/mach-origen.c | 2 +
arch/arm/mach-exynos4/mach-smdk4212.c | 2 +
arch/arm/mach-exynos4/mach-smdkv310.c | 2 +
arch/arm/mach-exynos4/mach-universal_c210.c | 2 +
arch/arm/mach-msm/board-msm8960.c | 2 +
arch/arm/mach-msm/board-msm8x60.c | 4 +
arch/arm/mach-msm/include/mach/entry-macro-qgic.S | 17 ---
arch/arm/mach-msm/include/mach/entry-macro-vic.S | 37 ------
arch/arm/mach-msm/include/mach/entry-macro.S | 27 ++++-
arch/arm/mach-omap2/Kconfig | 2 +
arch/arm/mach-omap2/board-2430sdp.c | 1 +
arch/arm/mach-omap2/board-3430sdp.c | 1 +
arch/arm/mach-omap2/board-3630sdp.c | 1 +
arch/arm/mach-omap2/board-4430sdp.c | 2 +
arch/arm/mach-omap2/board-am3517crane.c | 1 +
arch/arm/mach-omap2/board-am3517evm.c | 1 +
arch/arm/mach-omap2/board-apollon.c | 1 +
arch/arm/mach-omap2/board-cm-t35.c | 2 +
arch/arm/mach-omap2/board-cm-t3517.c | 1 +
arch/arm/mach-omap2/board-devkit8000.c | 1 +
arch/arm/mach-omap2/board-generic.c | 1 +
arch/arm/mach-omap2/board-h4.c | 1 +
arch/arm/mach-omap2/board-igep0020.c | 2 +
arch/arm/mach-omap2/board-ldp.c | 1 +
arch/arm/mach-omap2/board-n8x0.c | 3 +
arch/arm/mach-omap2/board-omap3beagle.c | 1 +
arch/arm/mach-omap2/board-omap3evm.c | 1 +
arch/arm/mach-omap2/board-omap3logic.c | 2 +
arch/arm/mach-omap2/board-omap3pandora.c | 1 +
arch/arm/mach-omap2/board-omap3stalker.c | 1 +
arch/arm/mach-omap2/board-omap3touchbook.c | 1 +
arch/arm/mach-omap2/board-omap4panda.c | 2 +
arch/arm/mach-omap2/board-overo.c | 1 +
arch/arm/mach-omap2/board-rm680.c | 1 +
arch/arm/mach-omap2/board-rx51.c | 1 +
arch/arm/mach-omap2/board-zoom.c | 2 +
arch/arm/mach-omap2/include/mach/entry-macro.S | 137 ---------------------
arch/arm/mach-omap2/irq.c | 49 ++++++++
arch/arm/mach-realview/include/mach/entry-macro.S | 2 -
arch/arm/mach-realview/realview_eb.c | 1 +
arch/arm/mach-realview/realview_pb1176.c | 1 +
arch/arm/mach-realview/realview_pb11mp.c | 1 +
arch/arm/mach-realview/realview_pba8.c | 1 +
arch/arm/mach-realview/realview_pbx.c | 1 +
arch/arm/mach-shmobile/Makefile | 1 -
arch/arm/mach-shmobile/board-ag5evm.c | 2 +-
arch/arm/mach-shmobile/entry-gic.S | 18 ---
arch/arm/mach-shmobile/include/mach/common.h | 1 -
arch/arm/mach-tegra/board-dt.c | 2 +
arch/arm/mach-tegra/board-harmony.c | 2 +
arch/arm/mach-tegra/board-paz00.c | 2 +
arch/arm/mach-tegra/board-seaboard.c | 4 +
arch/arm/mach-tegra/board-trimslice.c | 2 +
arch/arm/mach-tegra/include/mach/entry-macro.S | 22 +---
arch/arm/mach-ux500/board-mop500.c | 4 +
arch/arm/mach-ux500/board-u5500.c | 2 +
arch/arm/mach-ux500/include/mach/entry-macro.S | 2 -
arch/arm/mach-vexpress/include/mach/entry-macro.S | 2 -
arch/arm/mach-vexpress/v2m.c | 2 +
arch/arm/mach-zynq/common.c | 1 +
arch/arm/mach-zynq/include/mach/entry-macro.S | 3 -
arch/arm/plat-omap/include/plat/irqs.h | 2 +
72 files changed, 212 insertions(+), 371 deletions(-)
delete mode 100644 arch/arm/include/asm/hardware/entry-macro-gic.S
delete mode 100644 arch/arm/mach-msm/include/mach/entry-macro-qgic.S
delete mode 100644 arch/arm/mach-msm/include/mach/entry-macro-vic.S
delete mode 100644 arch/arm/mach-shmobile/entry-gic.S
^ permalink raw reply
* [RFC PATCH 01/14] ARM: GIC: Add global gic_handle_irq() function
From: Marc Zyngier @ 2011-09-23 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316796692-15964-1-git-send-email-marc.zyngier@arm.com>
Provide the GIC code with a low level handler that can be used
by platforms using CONFIG_MULTI_IRQ_HANDLER. Though the handler is
written in C, the compiled code doesn't feel much slower than its
assembly counterpart (at least with my gcc 4.4.1).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/common/gic.c | 23 +++++++++++++++++++++++
arch/arm/include/asm/hardware/gic.h | 1 +
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index a3f335c..a7b2a4a 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -209,6 +209,29 @@ static int gic_set_wake(struct irq_data *d, unsigned int on)
#define gic_set_wake NULL
#endif
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+ u32 irqstat, irqnr;
+
+ do {
+ irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
+ irqnr = irqstat & ~0x1c00;
+
+ if (likely(irqnr > 15 && irqnr < 1021)) {
+ handle_IRQ(irqnr, regs);
+ continue;
+ }
+ if (irqnr < 16) {
+ writel_relaxed(irqstat, gic_cpu_base_addr + GIC_CPU_EOI);
+#ifdef CONFIG_SMP
+ do_IPI(irqnr, regs);
+#endif
+ continue;
+ }
+ break;
+ } while (1);
+}
+
static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
{
struct gic_chip_data *chip_data = irq_get_handler_data(irq);
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 2dadd50..45e4ab4 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -38,6 +38,7 @@ extern struct irq_chip gic_arch_extn;
void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
void gic_secondary_init(unsigned int);
+void gic_handle_irq(struct pt_regs *regs);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 02/14] ARM: RealView: convert to CONFIG_MULTI_IRQ_HANDLER
From: Marc Zyngier @ 2011-09-23 16:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316796692-15964-1-git-send-email-marc.zyngier@arm.com>
Convert the RealView platforms to be using the gic_handle_irq
function as their primary interrupt handler.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/Kconfig | 1 +
arch/arm/mach-realview/include/mach/entry-macro.S | 2 --
arch/arm/mach-realview/realview_eb.c | 1 +
arch/arm/mach-realview/realview_pb1176.c | 1 +
arch/arm/mach-realview/realview_pb11mp.c | 1 +
arch/arm/mach-realview/realview_pba8.c | 1 +
arch/arm/mach-realview/realview_pbx.c | 1 +
7 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 472a7f8..6c31cc2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -262,6 +262,7 @@ config ARCH_REALVIEW
select PLAT_VERSATILE_CLCD
select ARM_TIMER_SP804
select GPIO_PL061 if GPIOLIB
+ select MULTI_IRQ_HANDLER
help
This enables support for ARM Ltd RealView boards.
diff --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S
index 4071164..e8a5179 100644
--- a/arch/arm/mach-realview/include/mach/entry-macro.S
+++ b/arch/arm/mach-realview/include/mach/entry-macro.S
@@ -7,8 +7,6 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-#include <mach/hardware.h>
-#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 427e44e..f01e332 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -470,6 +470,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_eb_timer,
+ .handle_irq = gic_handle_irq,
.init_machine = realview_eb_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index 863f286..539cde3 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -365,6 +365,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pb1176_timer,
+ .handle_irq = gic_handle_irq,
.init_machine = realview_pb1176_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 6cb8318..32d18e5 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -367,6 +367,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pb11mp_timer,
+ .handle_irq = gic_handle_irq,
.init_machine = realview_pb11mp_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 3db72c5..0896cc4 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -317,6 +317,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pba8_timer,
+ .handle_irq = gic_handle_irq,
.init_machine = realview_pba8_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 7e5d540..eaedeaa 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -400,6 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pbx_timer,
+ .handle_irq = gic_handle_irq,
.init_machine = realview_pbx_init,
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox