From ce45612d40b13f445fda9162321021af4fc3acfc Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 5 Dec 2011 23:20:17 +0000 Subject: [PATCH] --- yaml --- r: 279862 b: refs/heads/master c: 742eaa6a6e356a16788ce6530271de89bc4f8fb5 h: refs/heads/master v: v3 --- [refs] | 2 +- .../devicetree/bindings/arm/gic.txt | 4 + .../devicetree/bindings/arm/vic.txt | 29 +++ trunk/arch/arm/common/Kconfig | 6 + trunk/arch/arm/common/gic.c | 165 +++++++++++++--- trunk/arch/arm/common/vic.c | 143 +++++++++++--- trunk/arch/arm/include/asm/entry-macro-vic2.S | 57 ------ .../include/asm/hardware/entry-macro-gic.S | 60 ------ trunk/arch/arm/include/asm/hardware/gic.h | 26 +-- trunk/arch/arm/include/asm/hardware/vic.h | 10 +- trunk/arch/arm/include/asm/mach/arch.h | 9 +- trunk/arch/arm/include/asm/system.h | 1 + trunk/arch/arm/kernel/entry-armv.S | 7 +- trunk/arch/arm/kernel/machine_kexec.c | 4 +- trunk/arch/arm/kernel/process.c | 35 ++-- trunk/arch/arm/kernel/setup.c | 7 +- trunk/arch/arm/mach-clps711x/Makefile | 2 +- .../arm/mach-clps711x/{irq.c => common.c} | 95 ++++++++- .../arm/mach-clps711x/include/mach/system.h | 2 +- trunk/arch/arm/mach-clps711x/mm.c | 48 ----- trunk/arch/arm/mach-clps711x/time.c | 84 -------- trunk/arch/arm/mach-cns3xxx/cns3420vb.c | 2 + .../mach-cns3xxx/include/mach/entry-macro.S | 2 - trunk/arch/arm/mach-ebsa110/core.c | 2 +- .../arm/mach-ebsa110/include/mach/system.h | 2 +- trunk/arch/arm/mach-ep93xx/adssphere.c | 2 + trunk/arch/arm/mach-ep93xx/edb93xx.c | 9 + trunk/arch/arm/mach-ep93xx/gesbc9312.c | 2 + .../mach-ep93xx/include/mach/entry-macro.S | 42 ---- .../arm/mach-ep93xx/include/mach/system.h | 2 - trunk/arch/arm/mach-ep93xx/micro9.c | 5 + trunk/arch/arm/mach-ep93xx/simone.c | 2 + trunk/arch/arm/mach-ep93xx/snappercl15.c | 2 + trunk/arch/arm/mach-ep93xx/ts72xx.c | 2 + trunk/arch/arm/mach-exynos/cpu.c | 20 +- .../mach-exynos/include/mach/entry-macro.S | 75 ------- trunk/arch/arm/mach-exynos/mach-armlex4210.c | 2 + trunk/arch/arm/mach-exynos/mach-nuri.c | 2 + trunk/arch/arm/mach-exynos/mach-origen.c | 2 + trunk/arch/arm/mach-exynos/mach-smdk4x12.c | 3 + trunk/arch/arm/mach-exynos/mach-smdkv310.c | 3 + .../arm/mach-exynos/mach-universal_c210.c | 2 + trunk/arch/arm/mach-exynos/platsmp.c | 28 +-- trunk/arch/arm/mach-footbridge/cats-hw.c | 2 +- .../arm/mach-footbridge/include/mach/system.h | 2 +- trunk/arch/arm/mach-highbank/highbank.c | 1 + .../mach-highbank/include/mach/entry-macro.S | 2 - .../arm/mach-iop32x/include/mach/system.h | 4 +- .../arm/mach-iop33x/include/mach/system.h | 2 +- .../arm/mach-ixp2000/include/mach/system.h | 2 - .../arm/mach-ixp4xx/include/mach/system.h | 2 +- .../arm/mach-ks8695/include/mach/system.h | 2 +- .../arm/mach-lpc32xx/include/mach/system.h | 3 - trunk/arch/arm/mach-mmp/include/mach/system.h | 4 +- trunk/arch/arm/mach-msm/board-msm8960.c | 2 + trunk/arch/arm/mach-msm/board-msm8x60.c | 4 + .../mach-msm/include/mach/entry-macro-qgic.S | 17 -- .../mach-msm/include/mach/entry-macro-vic.S | 37 ---- .../arm/mach-msm/include/mach/entry-macro.S | 27 ++- trunk/arch/arm/mach-mxs/system.c | 2 +- .../arm/mach-netx/include/mach/entry-macro.S | 13 -- trunk/arch/arm/mach-netx/nxdb500.c | 2 + trunk/arch/arm/mach-netx/nxdkn.c | 2 + trunk/arch/arm/mach-netx/nxeb500hmi.c | 2 + trunk/arch/arm/mach-nomadik/board-nhk8815.c | 2 + .../mach-nomadik/include/mach/entry-macro.S | 30 --- trunk/arch/arm/mach-omap1/board-ams-delta.c | 2 +- trunk/arch/arm/mach-omap1/board-fsample.c | 2 +- trunk/arch/arm/mach-omap1/board-generic.c | 2 +- trunk/arch/arm/mach-omap1/board-h2.c | 2 +- trunk/arch/arm/mach-omap1/board-h3.c | 2 +- trunk/arch/arm/mach-omap1/board-htcherald.c | 2 +- trunk/arch/arm/mach-omap1/board-innovator.c | 2 +- trunk/arch/arm/mach-omap1/board-nokia770.c | 2 +- trunk/arch/arm/mach-omap1/board-osk.c | 2 +- trunk/arch/arm/mach-omap1/board-palmte.c | 2 +- trunk/arch/arm/mach-omap1/board-palmtt.c | 2 +- trunk/arch/arm/mach-omap1/board-palmz71.c | 2 +- trunk/arch/arm/mach-omap1/board-perseus2.c | 2 +- trunk/arch/arm/mach-omap1/board-sx1.c | 2 +- trunk/arch/arm/mach-omap1/board-voiceblue.c | 2 +- trunk/arch/arm/mach-omap1/common.h | 61 ++++++ trunk/arch/arm/mach-omap1/devices.c | 2 +- trunk/arch/arm/mach-omap1/time.c | 2 +- trunk/arch/arm/mach-omap1/timer32k.c | 2 +- trunk/arch/arm/mach-omap2/Kconfig | 2 + trunk/arch/arm/mach-omap2/board-2430sdp.c | 3 +- trunk/arch/arm/mach-omap2/board-3430sdp.c | 3 +- trunk/arch/arm/mach-omap2/board-3630sdp.c | 3 +- trunk/arch/arm/mach-omap2/board-4430sdp.c | 5 +- trunk/arch/arm/mach-omap2/board-am3517crane.c | 3 +- trunk/arch/arm/mach-omap2/board-am3517evm.c | 3 +- trunk/arch/arm/mach-omap2/board-apollon.c | 3 +- trunk/arch/arm/mach-omap2/board-cm-t35.c | 4 +- trunk/arch/arm/mach-omap2/board-cm-t3517.c | 3 +- trunk/arch/arm/mach-omap2/board-devkit8000.c | 3 +- trunk/arch/arm/mach-omap2/board-generic.c | 4 +- trunk/arch/arm/mach-omap2/board-h4.c | 3 +- trunk/arch/arm/mach-omap2/board-igep0020.c | 4 +- trunk/arch/arm/mach-omap2/board-ldp.c | 3 +- trunk/arch/arm/mach-omap2/board-n8x0.c | 5 +- trunk/arch/arm/mach-omap2/board-omap3beagle.c | 3 +- trunk/arch/arm/mach-omap2/board-omap3evm.c | 3 +- trunk/arch/arm/mach-omap2/board-omap3logic.c | 4 +- .../arch/arm/mach-omap2/board-omap3pandora.c | 3 +- .../arch/arm/mach-omap2/board-omap3stalker.c | 3 +- .../arm/mach-omap2/board-omap3touchbook.c | 3 +- trunk/arch/arm/mach-omap2/board-omap4panda.c | 5 +- trunk/arch/arm/mach-omap2/board-overo.c | 3 +- trunk/arch/arm/mach-omap2/board-rm680.c | 3 +- .../arm/mach-omap2/board-rx51-peripherals.c | 2 +- trunk/arch/arm/mach-omap2/board-rx51.c | 3 +- trunk/arch/arm/mach-omap2/board-ti8168evm.c | 2 +- .../arm/mach-omap2/board-zoom-peripherals.c | 2 +- trunk/arch/arm/mach-omap2/board-zoom.c | 4 +- trunk/arch/arm/mach-omap2/cm2xxx_3xxx.c | 2 +- trunk/arch/arm/mach-omap2/cm44xx.c | 2 +- trunk/arch/arm/mach-omap2/cminst44xx.c | 2 +- trunk/arch/arm/mach-omap2/common.c | 2 +- trunk/arch/arm/mach-omap2/common.h | 185 ++++++++++++++++++ trunk/arch/arm/mach-omap2/control.c | 2 +- trunk/arch/arm/mach-omap2/cpuidle34xx.c | 1 + trunk/arch/arm/mach-omap2/i2c.c | 2 +- trunk/arch/arm/mach-omap2/id.c | 2 +- .../arm/mach-omap2/include/mach/entry-macro.S | 137 ------------- .../mach-omap2/include/mach/omap4-common.h | 43 ---- trunk/arch/arm/mach-omap2/io.c | 7 +- trunk/arch/arm/mach-omap2/irq.c | 51 +++++ trunk/arch/arm/mach-omap2/omap-hotplug.c | 3 +- trunk/arch/arm/mach-omap2/omap-smp.c | 3 +- trunk/arch/arm/mach-omap2/omap4-common.c | 9 +- trunk/arch/arm/mach-omap2/omap_hwmod.c | 2 +- trunk/arch/arm/mach-omap2/pm.c | 2 +- trunk/arch/arm/mach-omap2/pm24xx.c | 1 + trunk/arch/arm/mach-omap2/pm34xx.c | 1 + trunk/arch/arm/mach-omap2/pm44xx.c | 2 +- trunk/arch/arm/mach-omap2/prcm.c | 2 +- trunk/arch/arm/mach-omap2/prcm_mpu44xx.c | 2 +- trunk/arch/arm/mach-omap2/prm2xxx_3xxx.c | 2 +- trunk/arch/arm/mach-omap2/prm44xx.c | 2 +- trunk/arch/arm/mach-omap2/prminst44xx.c | 2 +- trunk/arch/arm/mach-omap2/sdram-nokia.c | 2 +- trunk/arch/arm/mach-omap2/sdrc.c | 2 +- trunk/arch/arm/mach-omap2/sdrc2xxx.c | 2 +- trunk/arch/arm/mach-omap2/serial.c | 2 +- trunk/arch/arm/mach-omap2/smartreflex.c | 2 +- trunk/arch/arm/mach-omap2/timer.c | 2 +- trunk/arch/arm/mach-omap2/vc3xxx_data.c | 2 +- trunk/arch/arm/mach-omap2/vc44xx_data.c | 2 +- trunk/arch/arm/mach-omap2/voltage.c | 2 +- .../arm/mach-omap2/voltagedomains3xxx_data.c | 2 +- .../arm/mach-omap2/voltagedomains44xx_data.c | 2 +- trunk/arch/arm/mach-omap2/vp.c | 2 +- trunk/arch/arm/mach-omap2/vp3xxx_data.c | 2 +- trunk/arch/arm/mach-omap2/vp44xx_data.c | 2 +- trunk/arch/arm/mach-picoxcell/common.c | 9 +- .../mach-picoxcell/include/mach/entry-macro.S | 11 +- .../arm/mach-pnx4008/include/mach/system.h | 2 +- .../arm/mach-pxa/include/mach/entry-macro.S | 36 ---- trunk/arch/arm/mach-pxa/mioa701.c | 1 + trunk/arch/arm/mach-pxa/poodle.c | 6 - trunk/arch/arm/mach-pxa/reset.c | 2 +- trunk/arch/arm/mach-pxa/spitz.c | 3 + trunk/arch/arm/mach-pxa/tosa.c | 1 + .../mach-realview/include/mach/entry-macro.S | 2 - trunk/arch/arm/mach-realview/realview_eb.c | 1 + .../arch/arm/mach-realview/realview_pb1176.c | 1 + .../arch/arm/mach-realview/realview_pb11mp.c | 1 + trunk/arch/arm/mach-realview/realview_pba8.c | 1 + trunk/arch/arm/mach-realview/realview_pbx.c | 1 + trunk/arch/arm/mach-rpc/include/mach/system.h | 2 +- .../mach-s3c2410/include/mach/system-reset.h | 4 +- .../mach-s3c64xx/include/mach/entry-macro.S | 7 +- .../arm/mach-s3c64xx/include/mach/system.h | 2 +- trunk/arch/arm/mach-s3c64xx/mach-anw6410.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-crag6410.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-hmt.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-mini6410.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-ncp.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-real6410.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-smartq5.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-smartq7.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-smdk6400.c | 2 + trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c | 2 + .../mach-s5p64x0/include/mach/entry-macro.S | 7 +- trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c | 2 + trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c | 2 + .../mach-s5pc100/include/mach/entry-macro.S | 25 --- trunk/arch/arm/mach-s5pc100/mach-smdkc100.c | 2 + .../mach-s5pv210/include/mach/entry-macro.S | 37 ---- trunk/arch/arm/mach-s5pv210/mach-aquila.c | 2 + trunk/arch/arm/mach-s5pv210/mach-goni.c | 2 + trunk/arch/arm/mach-s5pv210/mach-smdkc110.c | 2 + trunk/arch/arm/mach-s5pv210/mach-smdkv210.c | 2 + trunk/arch/arm/mach-s5pv210/mach-torbreck.c | 2 + .../arm/mach-sa1100/include/mach/system.h | 2 +- trunk/arch/arm/mach-shark/core.c | 1 - trunk/arch/arm/mach-shmobile/Makefile | 1 - trunk/arch/arm/mach-shmobile/board-ag5evm.c | 2 +- trunk/arch/arm/mach-shmobile/board-kota2.c | 2 +- trunk/arch/arm/mach-shmobile/entry-gic.S | 18 -- .../arm/mach-shmobile/include/mach/common.h | 1 - .../mach-shmobile/include/mach/entry-macro.S | 9 - .../arm/mach-shmobile/include/mach/system.h | 2 +- .../mach-spear3xx/include/mach/entry-macro.S | 27 --- trunk/arch/arm/mach-spear3xx/spear300_evb.c | 2 + trunk/arch/arm/mach-spear3xx/spear310_evb.c | 2 + trunk/arch/arm/mach-spear3xx/spear320_evb.c | 2 + .../mach-spear6xx/include/mach/entry-macro.S | 36 ---- trunk/arch/arm/mach-spear6xx/spear600_evb.c | 2 + trunk/arch/arm/mach-tegra/board-dt.c | 2 + trunk/arch/arm/mach-tegra/board-harmony.c | 2 + trunk/arch/arm/mach-tegra/board-paz00.c | 2 + trunk/arch/arm/mach-tegra/board-seaboard.c | 4 + trunk/arch/arm/mach-tegra/board-trimslice.c | 2 + .../arm/mach-tegra/include/mach/entry-macro.S | 22 +-- .../arm/mach-u300/include/mach/entry-macro.S | 24 --- .../arch/arm/mach-u300/include/mach/system.h | 2 - trunk/arch/arm/mach-u300/u300.c | 2 + trunk/arch/arm/mach-ux500/board-mop500.c | 4 + trunk/arch/arm/mach-ux500/board-u5500.c | 2 + .../arm/mach-ux500/include/mach/entry-macro.S | 2 - .../mach-versatile/include/mach/entry-macro.S | 30 --- trunk/arch/arm/mach-versatile/versatile_ab.c | 2 + trunk/arch/arm/mach-versatile/versatile_dt.c | 2 + trunk/arch/arm/mach-versatile/versatile_pb.c | 2 + .../mach-vexpress/include/mach/entry-macro.S | 2 - trunk/arch/arm/mach-vexpress/v2m.c | 2 + .../arm/mach-w90x900/include/mach/system.h | 2 +- trunk/arch/arm/mach-w90x900/irq.c | 2 + trunk/arch/arm/mach-w90x900/nuc910.h | 9 +- trunk/arch/arm/mach-w90x900/nuc950.h | 9 +- trunk/arch/arm/mach-w90x900/nuc960.h | 9 +- trunk/arch/arm/mach-w90x900/nuc9xx.h | 23 +++ trunk/arch/arm/mach-w90x900/time.c | 2 + trunk/arch/arm/mach-zynq/common.c | 1 + .../arm/mach-zynq/include/mach/entry-macro.S | 3 - trunk/arch/arm/mm/idmap.c | 2 +- trunk/arch/arm/mm/nommu.c | 2 +- trunk/arch/arm/plat-mxc/Makefile | 1 - trunk/arch/arm/plat-mxc/gic.c | 41 ---- trunk/arch/arm/plat-mxc/include/mach/common.h | 1 - .../arm/plat-mxc/include/mach/entry-macro.S | 11 -- trunk/arch/arm/plat-mxc/system.c | 2 +- .../arch/arm/plat-omap/include/plat/common.h | 82 -------- trunk/arch/arm/plat-omap/include/plat/io.h | 68 ------- trunk/arch/arm/plat-omap/include/plat/irqs.h | 14 -- trunk/arch/arm/plat-s5p/Kconfig | 1 + .../arch/arm/plat-spear/include/plat/system.h | 2 +- 249 files changed, 1103 insertions(+), 1469 deletions(-) create mode 100644 trunk/Documentation/devicetree/bindings/arm/vic.txt delete mode 100644 trunk/arch/arm/include/asm/entry-macro-vic2.S delete mode 100644 trunk/arch/arm/include/asm/hardware/entry-macro-gic.S rename trunk/arch/arm/mach-clps711x/{irq.c => common.c} (59%) delete mode 100644 trunk/arch/arm/mach-clps711x/mm.c delete mode 100644 trunk/arch/arm/mach-clps711x/time.c delete mode 100644 trunk/arch/arm/mach-msm/include/mach/entry-macro-qgic.S delete mode 100644 trunk/arch/arm/mach-msm/include/mach/entry-macro-vic.S create mode 100644 trunk/arch/arm/mach-omap1/common.h create mode 100644 trunk/arch/arm/mach-omap2/common.h delete mode 100644 trunk/arch/arm/mach-omap2/include/mach/omap4-common.h delete mode 100644 trunk/arch/arm/mach-shmobile/entry-gic.S create mode 100644 trunk/arch/arm/mach-w90x900/nuc9xx.h delete mode 100644 trunk/arch/arm/plat-mxc/gic.c diff --git a/[refs] b/[refs] index ce033aa484ce..06908943ef74 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ae72fd588a2b302222769b44775912b83f0785eb +refs/heads/master: 742eaa6a6e356a16788ce6530271de89bc4f8fb5 diff --git a/trunk/Documentation/devicetree/bindings/arm/gic.txt b/trunk/Documentation/devicetree/bindings/arm/gic.txt index 52916b4aa1fe..9b4b82a721b6 100644 --- a/trunk/Documentation/devicetree/bindings/arm/gic.txt +++ b/trunk/Documentation/devicetree/bindings/arm/gic.txt @@ -42,6 +42,10 @@ Optional - interrupts : Interrupt source of the parent interrupt controller. Only present on secondary GICs. +- cpu-offset : per-cpu offset within the distributor and cpu interface + regions, used when the GIC doesn't have banked registers. The offset is + cpu-offset * cpu-nr. + Example: intc: interrupt-controller@fff11000 { diff --git a/trunk/Documentation/devicetree/bindings/arm/vic.txt b/trunk/Documentation/devicetree/bindings/arm/vic.txt new file mode 100644 index 000000000000..266716b23437 --- /dev/null +++ b/trunk/Documentation/devicetree/bindings/arm/vic.txt @@ -0,0 +1,29 @@ +* ARM Vectored Interrupt Controller + +One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM +system for interrupt routing. For multiple controllers they can either be +nested or have the outputs wire-OR'd together. + +Required properties: + +- compatible : should be one of + "arm,pl190-vic" + "arm,pl192-vic" +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : The number of cells to define the interrupts. Must be 1 as + the VIC has no configuration options for interrupt sources. The cell is a u32 + and defines the interrupt number. +- reg : The register bank for the VIC. + +Optional properties: + +- interrupts : Interrupt source for parent controllers if the VIC is nested. + +Example: + + vic0: interrupt-controller@60000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x60000 0x1000>; + }; diff --git a/trunk/arch/arm/common/Kconfig b/trunk/arch/arm/common/Kconfig index 74df9ca2be31..81a933eb0903 100644 --- a/trunk/arch/arm/common/Kconfig +++ b/trunk/arch/arm/common/Kconfig @@ -1,8 +1,14 @@ config ARM_GIC select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + bool + +config GIC_NON_BANKED bool config ARM_VIC + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER bool config ARM_VIC_NR diff --git a/trunk/arch/arm/common/gic.c b/trunk/arch/arm/common/gic.c index 410a546060a2..b2dc2dd7f1df 100644 --- a/trunk/arch/arm/common/gic.c +++ b/trunk/arch/arm/common/gic.c @@ -40,13 +40,36 @@ #include #include +#include #include #include -static DEFINE_RAW_SPINLOCK(irq_controller_lock); +union gic_base { + void __iomem *common_base; + void __percpu __iomem **percpu_base; +}; -/* Address of GIC 0 CPU interface */ -void __iomem *gic_cpu_base_addr __read_mostly; +struct gic_chip_data { + unsigned int irq_offset; + union gic_base dist_base; + union gic_base cpu_base; +#ifdef CONFIG_CPU_PM + u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; + u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; + u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; + u32 __percpu *saved_ppi_enable; + u32 __percpu *saved_ppi_conf; +#endif +#ifdef CONFIG_IRQ_DOMAIN + struct irq_domain domain; +#endif + unsigned int gic_irqs; +#ifdef CONFIG_GIC_NON_BANKED + void __iomem *(*get_base)(union gic_base *); +#endif +}; + +static DEFINE_RAW_SPINLOCK(irq_controller_lock); /* * Supported arch specific GIC irq extension. @@ -67,16 +90,48 @@ struct irq_chip gic_arch_extn = { static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; +#ifdef CONFIG_GIC_NON_BANKED +static void __iomem *gic_get_percpu_base(union gic_base *base) +{ + return *__this_cpu_ptr(base->percpu_base); +} + +static void __iomem *gic_get_common_base(union gic_base *base) +{ + return base->common_base; +} + +static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data) +{ + return data->get_base(&data->dist_base); +} + +static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data) +{ + return data->get_base(&data->cpu_base); +} + +static inline void gic_set_base_accessor(struct gic_chip_data *data, + void __iomem *(*f)(union gic_base *)) +{ + data->get_base = f; +} +#else +#define gic_data_dist_base(d) ((d)->dist_base.common_base) +#define gic_data_cpu_base(d) ((d)->cpu_base.common_base) +#define gic_set_base_accessor(d,f) +#endif + static inline void __iomem *gic_dist_base(struct irq_data *d) { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); - return gic_data->dist_base; + return gic_data_dist_base(gic_data); } static inline void __iomem *gic_cpu_base(struct irq_data *d) { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); - return gic_data->cpu_base; + return gic_data_cpu_base(gic_data); } static inline unsigned int gic_irq(struct irq_data *d) @@ -215,6 +270,32 @@ 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; + struct gic_chip_data *gic = &gic_data[0]; + void __iomem *cpu_base = gic_data_cpu_base(gic); + + do { + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); + irqnr = irqstat & ~0x1c00; + + if (likely(irqnr > 15 && irqnr < 1021)) { + irqnr = irq_domain_to_irq(&gic->domain, irqnr); + handle_IRQ(irqnr, regs); + continue; + } + if (irqnr < 16) { + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); +#ifdef CONFIG_SMP + handle_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); @@ -225,7 +306,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); raw_spin_lock(&irq_controller_lock); - status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK); + status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); raw_spin_unlock(&irq_controller_lock); gic_irq = (status & 0x3ff); @@ -270,7 +351,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) u32 cpumask; unsigned int gic_irqs = gic->gic_irqs; struct irq_domain *domain = &gic->domain; - void __iomem *base = gic->dist_base; + void __iomem *base = gic_data_dist_base(gic); u32 cpu = 0; #ifdef CONFIG_SMP @@ -330,8 +411,8 @@ static void __init gic_dist_init(struct gic_chip_data *gic) static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) { - void __iomem *dist_base = gic->dist_base; - void __iomem *base = gic->cpu_base; + void __iomem *dist_base = gic_data_dist_base(gic); + void __iomem *base = gic_data_cpu_base(gic); int i; /* @@ -368,7 +449,7 @@ static void gic_dist_save(unsigned int gic_nr) BUG(); gic_irqs = gic_data[gic_nr].gic_irqs; - dist_base = gic_data[gic_nr].dist_base; + dist_base = gic_data_dist_base(&gic_data[gic_nr]); if (!dist_base) return; @@ -403,7 +484,7 @@ static void gic_dist_restore(unsigned int gic_nr) BUG(); gic_irqs = gic_data[gic_nr].gic_irqs; - dist_base = gic_data[gic_nr].dist_base; + dist_base = gic_data_dist_base(&gic_data[gic_nr]); if (!dist_base) return; @@ -439,8 +520,8 @@ static void gic_cpu_save(unsigned int gic_nr) if (gic_nr >= MAX_GIC_NR) BUG(); - dist_base = gic_data[gic_nr].dist_base; - cpu_base = gic_data[gic_nr].cpu_base; + dist_base = gic_data_dist_base(&gic_data[gic_nr]); + cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); if (!dist_base || !cpu_base) return; @@ -465,8 +546,8 @@ static void gic_cpu_restore(unsigned int gic_nr) if (gic_nr >= MAX_GIC_NR) BUG(); - dist_base = gic_data[gic_nr].dist_base; - cpu_base = gic_data[gic_nr].cpu_base; + dist_base = gic_data_dist_base(&gic_data[gic_nr]); + cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); if (!dist_base || !cpu_base) return; @@ -491,6 +572,11 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) int i; for (i = 0; i < MAX_GIC_NR; i++) { +#ifdef CONFIG_GIC_NON_BANKED + /* Skip over unused GICs */ + if (!gic_data[i].get_base) + continue; +#endif switch (cmd) { case CPU_PM_ENTER: gic_cpu_save(i); @@ -564,8 +650,9 @@ const struct irq_domain_ops gic_irq_domain_ops = { #endif }; -void __init gic_init(unsigned int gic_nr, int irq_start, - void __iomem *dist_base, void __iomem *cpu_base) +void __init gic_init_bases(unsigned int gic_nr, int irq_start, + void __iomem *dist_base, void __iomem *cpu_base, + u32 percpu_offset) { struct gic_chip_data *gic; struct irq_domain *domain; @@ -575,8 +662,36 @@ void __init gic_init(unsigned int gic_nr, int irq_start, gic = &gic_data[gic_nr]; domain = &gic->domain; - gic->dist_base = dist_base; - gic->cpu_base = cpu_base; +#ifdef CONFIG_GIC_NON_BANKED + if (percpu_offset) { /* Frankein-GIC without banked registers... */ + unsigned int cpu; + + gic->dist_base.percpu_base = alloc_percpu(void __iomem *); + gic->cpu_base.percpu_base = alloc_percpu(void __iomem *); + if (WARN_ON(!gic->dist_base.percpu_base || + !gic->cpu_base.percpu_base)) { + free_percpu(gic->dist_base.percpu_base); + free_percpu(gic->cpu_base.percpu_base); + return; + } + + for_each_possible_cpu(cpu) { + unsigned long offset = percpu_offset * cpu_logical_map(cpu); + *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset; + *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset; + } + + gic_set_base_accessor(gic, gic_get_percpu_base); + } else +#endif + { /* Normal, sane GIC... */ + WARN(percpu_offset, + "GIC_NON_BANKED not enabled, ignoring %08x offset!", + percpu_offset); + gic->dist_base.common_base = dist_base; + gic->cpu_base.common_base = cpu_base; + gic_set_base_accessor(gic, gic_get_common_base); + } /* * For primary GICs, skip over SGIs. @@ -584,8 +699,6 @@ void __init gic_init(unsigned int gic_nr, int irq_start, */ domain->hwirq_base = 32; if (gic_nr == 0) { - gic_cpu_base_addr = cpu_base; - if ((irq_start & 31) > 0) { domain->hwirq_base = 16; if (irq_start != -1) @@ -597,7 +710,7 @@ void __init gic_init(unsigned int gic_nr, int irq_start, * Find out how many interrupts are supported. * The GIC only supports up to 1020 interrupt sources. */ - gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f; + gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f; gic_irqs = (gic_irqs + 1) * 32; if (gic_irqs > 1020) gic_irqs = 1020; @@ -645,7 +758,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) dsb(); /* this always happens on GIC0 */ - writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); + writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); } #endif @@ -656,6 +769,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) { void __iomem *cpu_base; void __iomem *dist_base; + u32 percpu_offset; int irq; struct irq_domain *domain = &gic_data[gic_cnt].domain; @@ -668,9 +782,12 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) cpu_base = of_iomap(node, 1); WARN(!cpu_base, "unable to map gic cpu registers\n"); + if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) + percpu_offset = 0; + domain->of_node = of_node_get(node); - gic_init(gic_cnt, -1, dist_base, cpu_base); + gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset); if (parent) { irq = irq_of_parse_and_map(node, 0); diff --git a/trunk/arch/arm/common/vic.c b/trunk/arch/arm/common/vic.c index 01f18a421b17..6ed41ec2bbf5 100644 --- a/trunk/arch/arm/common/vic.c +++ b/trunk/arch/arm/common/vic.c @@ -19,17 +19,22 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include +#include +#include +#include +#include #include #include #include +#include #include #include -#ifdef CONFIG_PM /** * struct vic_device - VIC PM device * @irq: The IRQ number for the base of the VIC. @@ -40,6 +45,7 @@ * @int_enable: Save for VIC_INT_ENABLE. * @soft_int: Save for VIC_INT_SOFT. * @protect: Save for VIC_PROTECT. + * @domain: The IRQ domain for the VIC. */ struct vic_device { void __iomem *base; @@ -50,13 +56,13 @@ struct vic_device { u32 int_enable; u32 soft_int; u32 protect; + struct irq_domain domain; }; /* we cannot allocate memory when VICs are initially registered */ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; static int vic_id; -#endif /* CONFIG_PM */ /** * vic_init2 - common initialisation code @@ -156,39 +162,50 @@ static int __init vic_pm_init(void) return 0; } late_initcall(vic_pm_init); +#endif /* CONFIG_PM */ /** - * vic_pm_register - Register a VIC for later power management control + * vic_register() - Register a VIC. * @base: The base address of the VIC. * @irq: The base IRQ for the VIC. * @resume_sources: bitmask of interrupts allowed for resume sources. + * @node: The device tree node associated with the VIC. * * Register the VIC with the system device tree so that it can be notified * of suspend and resume requests and ensure that the correct actions are * taken to re-instate the settings on resume. + * + * This also configures the IRQ domain for the VIC. */ -static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources) +static void __init vic_register(void __iomem *base, unsigned int irq, + u32 resume_sources, struct device_node *node) { struct vic_device *v; - if (vic_id >= ARRAY_SIZE(vic_devices)) + if (vic_id >= ARRAY_SIZE(vic_devices)) { printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); - else { - v = &vic_devices[vic_id]; - v->base = base; - v->resume_sources = resume_sources; - v->irq = irq; - vic_id++; + return; } + + v = &vic_devices[vic_id]; + v->base = base; + v->resume_sources = resume_sources; + v->irq = irq; + vic_id++; + + v->domain.irq_base = irq; + v->domain.nr_irq = 32; +#ifdef CONFIG_OF_IRQ + v->domain.of_node = of_node_get(node); + v->domain.ops = &irq_domain_simple_ops; +#endif /* CONFIG_OF */ + irq_domain_add(&v->domain); } -#else -static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { } -#endif /* CONFIG_PM */ static void vic_ack_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq & 31; + unsigned int irq = d->hwirq; writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); /* moreover, clear the soft-triggered, in case it was the reason */ writel(1 << irq, base + VIC_INT_SOFT_CLEAR); @@ -197,14 +214,14 @@ static void vic_ack_irq(struct irq_data *d) static void vic_mask_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq & 31; + unsigned int irq = d->hwirq; writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); } static void vic_unmask_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq & 31; + unsigned int irq = d->hwirq; writel(1 << irq, base + VIC_INT_ENABLE); } @@ -226,7 +243,7 @@ static struct vic_device *vic_from_irq(unsigned int irq) static int vic_set_wake(struct irq_data *d, unsigned int on) { struct vic_device *v = vic_from_irq(d->irq); - unsigned int off = d->irq & 31; + unsigned int off = d->hwirq; u32 bit = 1 << off; if (!v) @@ -330,15 +347,9 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, vic_set_irq_sources(base, irq_start, vic_sources); } -/** - * vic_init - initialise a vectored interrupt controller - * @base: iomem base address - * @irq_start: starting interrupt number, must be muliple of 32 - * @vic_sources: bitmask of interrupt sources to allow - * @resume_sources: bitmask of interrupt sources to allow for resume - */ -void __init vic_init(void __iomem *base, unsigned int irq_start, - u32 vic_sources, u32 resume_sources) +static void __init __vic_init(void __iomem *base, unsigned int irq_start, + u32 vic_sources, u32 resume_sources, + struct device_node *node) { unsigned int i; u32 cellid = 0; @@ -375,5 +386,81 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, vic_set_irq_sources(base, irq_start, vic_sources); - vic_pm_register(base, irq_start, resume_sources); + vic_register(base, irq_start, resume_sources, node); +} + +/** + * vic_init() - initialise a vectored interrupt controller + * @base: iomem base address + * @irq_start: starting interrupt number, must be muliple of 32 + * @vic_sources: bitmask of interrupt sources to allow + * @resume_sources: bitmask of interrupt sources to allow for resume + */ +void __init vic_init(void __iomem *base, unsigned int irq_start, + u32 vic_sources, u32 resume_sources) +{ + __vic_init(base, irq_start, vic_sources, resume_sources, NULL); +} + +#ifdef CONFIG_OF +int __init vic_of_init(struct device_node *node, struct device_node *parent) +{ + void __iomem *regs; + int irq_base; + + if (WARN(parent, "non-root VICs are not supported")) + return -EINVAL; + + regs = of_iomap(node, 0); + if (WARN_ON(!regs)) + return -EIO; + + irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); + if (WARN_ON(irq_base < 0)) + goto out_unmap; + + __vic_init(regs, irq_base, ~0, ~0, node); + + return 0; + + out_unmap: + iounmap(regs); + + return -EIO; +} +#endif /* CONFIG OF */ + +/* + * Handle each interrupt in a single VIC. Returns non-zero if we've + * handled at least one interrupt. This does a single read of the + * status register and handles all interrupts in order from LSB first. + */ +static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) +{ + u32 stat, irq; + int handled = 0; + + stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); + while (stat) { + irq = ffs(stat) - 1; + handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); + stat &= ~(1 << irq); + handled = 1; + } + + return handled; +} + +/* + * Keep iterating over all registered VIC's until there are no pending + * interrupts. + */ +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ + int i, handled; + + do { + for (i = 0, handled = 0; i < vic_id; ++i) + handled |= handle_one_vic(&vic_devices[i], regs); + } while (handled); } diff --git a/trunk/arch/arm/include/asm/entry-macro-vic2.S b/trunk/arch/arm/include/asm/entry-macro-vic2.S deleted file mode 100644 index 3ceb85e43850..000000000000 --- a/trunk/arch/arm/include/asm/entry-macro-vic2.S +++ /dev/null @@ -1,57 +0,0 @@ -/* arch/arm/include/asm/entry-macro-vic2.S - * - * Originally arch/arm/mach-s3c6400/include/mach/entry-macro.S - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * Low-level IRQ helper macros for a device with two VICs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. -*/ - -/* This should be included from with the necessary - * defines for virtual addresses and IRQ bases for the two vics. - * - * The code needs the following defined: - * IRQ_VIC0_BASE IRQ number of VIC0's first IRQ - * IRQ_VIC1_BASE IRQ number of VIC1's first IRQ - * VA_VIC0 Virtual address of VIC0 - * VA_VIC1 Virtual address of VIC1 - * - * Note, code assumes VIC0's virtual address is an ARM immediate constant - * away from VIC1. -*/ - -#include - - .macro disable_fiq - .endm - - .macro get_irqnr_preamble, base, tmp - ldr \base, =VA_VIC0 - .endm - - .macro arch_ret_to_user, tmp1, tmp2 - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - @ check the vic0 - mov \irqnr, #IRQ_VIC0_BASE + 31 - ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] - teq \irqstat, #0 - - @ otherwise try vic1 - addeq \tmp, \base, #(VA_VIC1 - VA_VIC0) - addeq \irqnr, \irqnr, #(IRQ_VIC1_BASE - IRQ_VIC0_BASE) - ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] - teqeq \irqstat, #0 - - clzne \irqstat, \irqstat - subne \irqnr, \irqnr, \irqstat - .endm diff --git a/trunk/arch/arm/include/asm/hardware/entry-macro-gic.S b/trunk/arch/arm/include/asm/hardware/entry-macro-gic.S deleted file mode 100644 index 74ebc803904d..000000000000 --- a/trunk/arch/arm/include/asm/hardware/entry-macro-gic.S +++ /dev/null @@ -1,60 +0,0 @@ -/* - * arch/arm/include/asm/hardware/entry-macro-gic.S - * - * Low-level IRQ helper macros for GIC - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include - -#ifndef HAVE_GET_IRQNR_PREAMBLE - .macro get_irqnr_preamble, base, tmp - ldr \base, =gic_cpu_base_addr - ldr \base, [\base] - .endm -#endif - -/* - * The interrupt numbering scheme is defined in the - * interrupt controller spec. To wit: - * - * Interrupts 0-15 are IPI - * 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) - * - * 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). - */ - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - ldr \irqstat, [\base, #GIC_CPU_INTACK] - /* bits 12-10 = src CPU, 9-0 = int # */ - - ldr \tmp, =1021 - bic \irqnr, \irqstat, #0x1c00 - cmp \irqnr, #15 - 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 diff --git a/trunk/arch/arm/include/asm/hardware/gic.h b/trunk/arch/arm/include/asm/hardware/gic.h index 3e91f22046f5..4bdfe0018696 100644 --- a/trunk/arch/arm/include/asm/hardware/gic.h +++ b/trunk/arch/arm/include/asm/hardware/gic.h @@ -36,30 +36,22 @@ #include struct device_node; -extern void __iomem *gic_cpu_base_addr; extern struct irq_chip gic_arch_extn; -void gic_init(unsigned int, int, void __iomem *, void __iomem *); +void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, + u32 offset); int gic_of_init(struct device_node *node, struct device_node *parent); 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); -struct gic_chip_data { - void __iomem *dist_base; - void __iomem *cpu_base; -#ifdef CONFIG_CPU_PM - u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; - u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; - u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; - u32 __percpu *saved_ppi_enable; - u32 __percpu *saved_ppi_conf; -#endif -#ifdef CONFIG_IRQ_DOMAIN - struct irq_domain domain; -#endif - unsigned int gic_irqs; -}; +static inline void gic_init(unsigned int nr, int start, + void __iomem *dist , void __iomem *cpu) +{ + gic_init_bases(nr, start, dist, cpu, 0); +} + #endif #endif diff --git a/trunk/arch/arm/include/asm/hardware/vic.h b/trunk/arch/arm/include/asm/hardware/vic.h index 5d72550a8097..f42ebd619590 100644 --- a/trunk/arch/arm/include/asm/hardware/vic.h +++ b/trunk/arch/arm/include/asm/hardware/vic.h @@ -41,7 +41,15 @@ #define VIC_PL192_VECT_ADDR 0xF00 #ifndef __ASSEMBLY__ +#include +#include + +struct device_node; +struct pt_regs; + void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); -#endif +int vic_of_init(struct device_node *node, struct device_node *parent); +void vic_handle_irq(struct pt_regs *regs); +#endif /* __ASSEMBLY__ */ #endif diff --git a/trunk/arch/arm/include/asm/mach/arch.h b/trunk/arch/arm/include/asm/mach/arch.h index 2b0efc3104ac..bcb0c883e21e 100644 --- a/trunk/arch/arm/include/asm/mach/arch.h +++ b/trunk/arch/arm/include/asm/mach/arch.h @@ -31,10 +31,10 @@ struct machine_desc { unsigned int video_start; /* start of video RAM */ unsigned int video_end; /* end of video RAM */ - unsigned int reserve_lp0 :1; /* never has lp0 */ - unsigned int reserve_lp1 :1; /* never has lp1 */ - unsigned int reserve_lp2 :1; /* never has lp2 */ - unsigned int soft_reboot :1; /* soft reboot */ + unsigned char reserve_lp0 :1; /* never has lp0 */ + unsigned char reserve_lp1 :1; /* never has lp1 */ + unsigned char reserve_lp2 :1; /* never has lp2 */ + char restart_mode; /* default restart mode */ void (*fixup)(struct tag *, char **, struct meminfo *); void (*reserve)(void);/* reserve mem blocks */ @@ -46,6 +46,7 @@ struct machine_desc { #ifdef CONFIG_MULTI_IRQ_HANDLER void (*handle_irq)(struct pt_regs *); #endif + void (*restart)(char, const char *); }; /* diff --git a/trunk/arch/arm/include/asm/system.h b/trunk/arch/arm/include/asm/system.h index 984014b92647..fe7de7571bac 100644 --- a/trunk/arch/arm/include/asm/system.h +++ b/trunk/arch/arm/include/asm/system.h @@ -101,6 +101,7 @@ extern int __pure cpu_architecture(void); extern void cpu_init(void); void arm_machine_restart(char mode, const char *cmd); +void soft_restart(unsigned long); extern void (*arm_pm_restart)(char str, const char *cmd); #define UDBG_UNDEFINED (1 << 0) diff --git a/trunk/arch/arm/kernel/entry-armv.S b/trunk/arch/arm/kernel/entry-armv.S index b145f16c91bc..3a456c6c7005 100644 --- a/trunk/arch/arm/kernel/entry-armv.S +++ b/trunk/arch/arm/kernel/entry-armv.S @@ -36,12 +36,11 @@ #ifdef CONFIG_MULTI_IRQ_HANDLER ldr r1, =handle_arch_irq mov r0, sp - ldr r1, [r1] adr lr, BSYM(9997f) - teq r1, #0 - movne pc, r1 -#endif + ldr pc, [r1] +#else arch_irq_handler_default +#endif 9997: .endm diff --git a/trunk/arch/arm/kernel/machine_kexec.c b/trunk/arch/arm/kernel/machine_kexec.c index e59bbd496c39..29620b632ed9 100644 --- a/trunk/arch/arm/kernel/machine_kexec.c +++ b/trunk/arch/arm/kernel/machine_kexec.c @@ -16,7 +16,7 @@ extern const unsigned char relocate_new_kernel[]; extern const unsigned int relocate_new_kernel_size; -extern void setup_mm_for_reboot(char mode); +extern void setup_mm_for_reboot(void); extern unsigned long kexec_start_address; extern unsigned long kexec_indirection_page; @@ -113,7 +113,7 @@ void machine_kexec(struct kimage *image) kexec_reinit(); local_irq_disable(); local_fiq_disable(); - setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ + setup_mm_for_reboot(); flush_cache_all(); outer_flush_all(); outer_disable(); diff --git a/trunk/arch/arm/kernel/process.c b/trunk/arch/arm/kernel/process.c index 3d0c6fb74ae4..eeb3e16c6046 100644 --- a/trunk/arch/arm/kernel/process.c +++ b/trunk/arch/arm/kernel/process.c @@ -57,7 +57,7 @@ static const char *isa_modes[] = { "ARM" , "Thumb" , "Jazelle", "ThumbEE" }; -extern void setup_mm_for_reboot(char mode); +extern void setup_mm_for_reboot(void); static volatile int hlt_counter; @@ -92,7 +92,7 @@ static int __init hlt_setup(char *__unused) __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); -void arm_machine_restart(char mode, const char *cmd) +void soft_restart(unsigned long addr) { /* Disable interrupts first */ local_irq_disable(); @@ -103,7 +103,7 @@ void arm_machine_restart(char mode, const char *cmd) * we may need it to insert some 1:1 mappings so that * soft boot works. */ - setup_mm_for_reboot(mode); + setup_mm_for_reboot(); /* Clean and invalidate caches */ flush_cache_all(); @@ -114,18 +114,17 @@ void arm_machine_restart(char mode, const char *cmd) /* Push out any further dirty data, and ensure cache is empty */ flush_cache_all(); - /* - * Now call the architecture specific reboot code. - */ - arch_reset(mode, cmd); + cpu_reset(addr); +} - /* - * Whoops - the architecture was unable to reboot. - * Tell the user! - */ - mdelay(1000); - printk("Reboot failed -- System halted\n"); - while (1); +void arm_machine_restart(char mode, const char *cmd) +{ + /* Disable interrupts first */ + local_irq_disable(); + local_fiq_disable(); + + /* Call the architecture specific reboot code. */ + arch_reset(mode, cmd); } /* @@ -253,7 +252,15 @@ void machine_power_off(void) void machine_restart(char *cmd) { machine_shutdown(); + arm_pm_restart(reboot_mode, cmd); + + /* Give a grace period for failure to restart of 1s */ + mdelay(1000); + + /* Whoops - the platform was unable to reboot. Tell the user! */ + printk("Reboot failed -- System halted\n"); + while (1); } void __show_regs(struct pt_regs *regs) diff --git a/trunk/arch/arm/kernel/setup.c b/trunk/arch/arm/kernel/setup.c index 3448a3f9cc8c..6c2b0db5d1e9 100644 --- a/trunk/arch/arm/kernel/setup.c +++ b/trunk/arch/arm/kernel/setup.c @@ -904,8 +904,8 @@ void __init setup_arch(char **cmdline_p) machine_desc = mdesc; machine_name = mdesc->name; - if (mdesc->soft_reboot) - reboot_setup("s"); + if (mdesc->restart_mode) + reboot_setup(&mdesc->restart_mode); init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; @@ -924,6 +924,9 @@ void __init setup_arch(char **cmdline_p) paging_init(mdesc); request_standard_resources(mdesc); + if (mdesc->restart) + arm_pm_restart = mdesc->restart; + unflatten_device_tree(); #ifdef CONFIG_SMP diff --git a/trunk/arch/arm/mach-clps711x/Makefile b/trunk/arch/arm/mach-clps711x/Makefile index 4a197315f0cf..f2f0256232e3 100644 --- a/trunk/arch/arm/mach-clps711x/Makefile +++ b/trunk/arch/arm/mach-clps711x/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y := irq.o mm.o time.o +obj-y := common.o obj-m := obj-n := obj- := diff --git a/trunk/arch/arm/mach-clps711x/irq.c b/trunk/arch/arm/mach-clps711x/common.c similarity index 59% rename from trunk/arch/arm/mach-clps711x/irq.c rename to trunk/arch/arm/mach-clps711x/common.c index c2eceee645e3..ced2a4e406f4 100644 --- a/trunk/arch/arm/mach-clps711x/irq.c +++ b/trunk/arch/arm/mach-clps711x/common.c @@ -1,7 +1,9 @@ /* - * linux/arch/arm/mach-clps711x/irq.c + * linux/arch/arm/mach-clps711x/core.c * - * Copyright (C) 2000 Deep Blue Solutions Ltd. + * Core support for the CLPS711x-based machines. + * + * Copyright (C) 2001,2011 Deep Blue Solutions Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,16 +19,42 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include #include -#include +#include #include +#include +#include +#include -#include +#include #include #include - +#include +#include +#include +#include +#include #include +/* + * This maps the generic CLPS711x registers + */ +static struct map_desc clps711x_io_desc[] __initdata = { + { + .virtual = CLPS7111_VIRT_BASE, + .pfn = __phys_to_pfn(CLPS7111_PHYS_BASE), + .length = SZ_1M, + .type = MT_DEVICE + } +}; + +void __init clps711x_map_io(void) +{ + iotable_init(clps711x_io_desc, ARRAY_SIZE(clps711x_io_desc)); +} + static void int1_mask(struct irq_data *d) { u32 intmr1; @@ -112,15 +140,15 @@ void __init clps711x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { if (INT1_IRQS & (1 << i)) { - irq_set_chip_and_handler(i, &int1_chip, + irq_set_chip_and_handler(i, &int1_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } if (INT2_IRQS & (1 << i)) { irq_set_chip_and_handler(i, &int2_chip, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } + } } /* @@ -141,3 +169,54 @@ void __init clps711x_init_irq(void) clps_writel(0, SYNCIO); clps_writel(0, KBDEOI); } + +/* + * gettimeoffset() returns time since last timer tick, in usecs. + * + * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. + * 'tick' is usecs per jiffy. + */ +static unsigned long clps711x_gettimeoffset(void) +{ + unsigned long hwticks; + hwticks = LATCH - (clps_readl(TC2D) & 0xffff); /* since last underflow */ + return (hwticks * (tick_nsec / 1000)) / LATCH; +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t p720t_timer_interrupt(int irq, void *dev_id) +{ + timer_tick(); + return IRQ_HANDLED; +} + +static struct irqaction clps711x_timer_irq = { + .name = "CLPS711x Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = p720t_timer_interrupt, +}; + +static void __init clps711x_timer_init(void) +{ + struct timespec tv; + unsigned int syscon; + + syscon = clps_readl(SYSCON1); + syscon |= SYSCON1_TC2S | SYSCON1_TC2M; + clps_writel(syscon, SYSCON1); + + clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */ + + setup_irq(IRQ_TC2OI, &clps711x_timer_irq); + + tv.tv_nsec = 0; + tv.tv_sec = clps_readl(RTCDR); + do_settimeofday(&tv); +} + +struct sys_timer clps711x_timer = { + .init = clps711x_timer_init, + .offset = clps711x_gettimeoffset, +}; diff --git a/trunk/arch/arm/mach-clps711x/include/mach/system.h b/trunk/arch/arm/mach-clps711x/include/mach/system.h index f916cd7a477d..6c119937d398 100644 --- a/trunk/arch/arm/mach-clps711x/include/mach/system.h +++ b/trunk/arch/arm/mach-clps711x/include/mach/system.h @@ -34,7 +34,7 @@ static inline void arch_idle(void) static inline void arch_reset(char mode, const char *cmd) { - cpu_reset(0); + soft_restart(0); } #endif diff --git a/trunk/arch/arm/mach-clps711x/mm.c b/trunk/arch/arm/mach-clps711x/mm.c deleted file mode 100644 index 986592176767..000000000000 --- a/trunk/arch/arm/mach-clps711x/mm.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * linux/arch/arm/mach-clps711x/mm.c - * - * Generic MM setup for the CLPS711x-based machines. - * - * Copyright (C) 2001 Deep Blue Solutions Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* - * This maps the generic CLPS711x registers - */ -static struct map_desc clps711x_io_desc[] __initdata = { - { - .virtual = CLPS7111_VIRT_BASE, - .pfn = __phys_to_pfn(CLPS7111_PHYS_BASE), - .length = SZ_1M, - .type = MT_DEVICE - } -}; - -void __init clps711x_map_io(void) -{ - iotable_init(clps711x_io_desc, ARRAY_SIZE(clps711x_io_desc)); -} diff --git a/trunk/arch/arm/mach-clps711x/time.c b/trunk/arch/arm/mach-clps711x/time.c deleted file mode 100644 index d581ef0bcd24..000000000000 --- a/trunk/arch/arm/mach-clps711x/time.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * linux/arch/arm/mach-clps711x/time.c - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - - -/* - * gettimeoffset() returns time since last timer tick, in usecs. - * - * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. - * 'tick' is usecs per jiffy. - */ -static unsigned long clps711x_gettimeoffset(void) -{ - unsigned long hwticks; - hwticks = LATCH - (clps_readl(TC2D) & 0xffff); /* since last underflow */ - return (hwticks * (tick_nsec / 1000)) / LATCH; -} - -/* - * IRQ handler for the timer - */ -static irqreturn_t -p720t_timer_interrupt(int irq, void *dev_id) -{ - timer_tick(); - return IRQ_HANDLED; -} - -static struct irqaction clps711x_timer_irq = { - .name = "CLPS711x Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = p720t_timer_interrupt, -}; - -static void __init clps711x_timer_init(void) -{ - struct timespec tv; - unsigned int syscon; - - syscon = clps_readl(SYSCON1); - syscon |= SYSCON1_TC2S | SYSCON1_TC2M; - clps_writel(syscon, SYSCON1); - - clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */ - - setup_irq(IRQ_TC2OI, &clps711x_timer_irq); - - tv.tv_nsec = 0; - tv.tv_sec = clps_readl(RTCDR); - do_settimeofday(&tv); -} - -struct sys_timer clps711x_timer = { - .init = clps711x_timer_init, - .offset = clps711x_gettimeoffset, -}; diff --git a/trunk/arch/arm/mach-cns3xxx/cns3420vb.c b/trunk/arch/arm/mach-cns3xxx/cns3420vb.c index 55f7b4b08ab9..594852fe24cc 100644 --- a/trunk/arch/arm/mach-cns3xxx/cns3420vb.c +++ b/trunk/arch/arm/mach-cns3xxx/cns3420vb.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -201,5 +202,6 @@ MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board") .map_io = cns3420_map_io, .init_irq = cns3xxx_init_irq, .timer = &cns3xxx_timer, + .handle_irq = gic_handle_irq, .init_machine = cns3420_init, MACHINE_END diff --git a/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S index d87bfc397d39..01c57df5f716 100644 --- a/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -8,8 +8,6 @@ * published by the Free Software Foundation. */ -#include - .macro disable_fiq .endm diff --git a/trunk/arch/arm/mach-ebsa110/core.c b/trunk/arch/arm/mach-ebsa110/core.c index d0ce8abdd4b6..ce3ed244c4b0 100644 --- a/trunk/arch/arm/mach-ebsa110/core.c +++ b/trunk/arch/arm/mach-ebsa110/core.c @@ -283,7 +283,7 @@ MACHINE_START(EBSA110, "EBSA110") .atag_offset = 0x400, .reserve_lp0 = 1, .reserve_lp2 = 1, - .soft_reboot = 1, + .restart_mode = 's', .map_io = ebsa110_map_io, .init_irq = ebsa110_init_irq, .timer = &ebsa110_timer, diff --git a/trunk/arch/arm/mach-ebsa110/include/mach/system.h b/trunk/arch/arm/mach-ebsa110/include/mach/system.h index 9a26245bf1fc..0d5df72a03f6 100644 --- a/trunk/arch/arm/mach-ebsa110/include/mach/system.h +++ b/trunk/arch/arm/mach-ebsa110/include/mach/system.h @@ -34,6 +34,6 @@ static inline void arch_idle(void) asm volatile ("mcr p15, 0, ip, c15, c1, 2" : : : "cc"); } -#define arch_reset(mode, cmd) cpu_reset(0x80000000) +#define arch_reset(mode, cmd) soft_restart(0x80000000) #endif diff --git a/trunk/arch/arm/mach-ep93xx/adssphere.c b/trunk/arch/arm/mach-ep93xx/adssphere.c index 0713448206a5..d9b0ea2ba4d8 100644 --- a/trunk/arch/arm/mach-ep93xx/adssphere.c +++ b/trunk/arch/arm/mach-ep93xx/adssphere.c @@ -16,6 +16,7 @@ #include +#include #include #include @@ -36,6 +37,7 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = adssphere_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/edb93xx.c b/trunk/arch/arm/mach-ep93xx/edb93xx.c index 70ef8c527d27..9bbae0835f27 100644 --- a/trunk/arch/arm/mach-ep93xx/edb93xx.c +++ b/trunk/arch/arm/mach-ep93xx/edb93xx.c @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -250,6 +251,7 @@ MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -261,6 +263,7 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -272,6 +275,7 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -283,6 +287,7 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -294,6 +299,7 @@ MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -305,6 +311,7 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -316,6 +323,7 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END @@ -327,6 +335,7 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/gesbc9312.c b/trunk/arch/arm/mach-ep93xx/gesbc9312.c index 45ee205856f8..1dd32a7c5f15 100644 --- a/trunk/arch/arm/mach-ep93xx/gesbc9312.c +++ b/trunk/arch/arm/mach-ep93xx/gesbc9312.c @@ -16,6 +16,7 @@ #include +#include #include #include @@ -36,6 +37,7 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = gesbc9312_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/include/mach/entry-macro.S b/trunk/arch/arm/mach-ep93xx/include/mach/entry-macro.S index 96b85e2c2c0b..9be6edcf9045 100644 --- a/trunk/arch/arm/mach-ep93xx/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-ep93xx/include/mach/entry-macro.S @@ -9,51 +9,9 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ -#include .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =(EP93XX_AHB_VIRT_BASE) - orr \base, \base, #0x000b0000 - mov \irqnr, #0 - ldr \irqstat, [\base] @ lower 32 interrupts - cmp \irqstat, #0 - bne 1001f - - eor \base, \base, #0x00070000 - ldr \irqstat, [\base] @ upper 32 interrupts - cmp \irqstat, #0 - beq 1002f - mov \irqnr, #0x20 - -1001: - movs \tmp, \irqstat, lsl #16 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #16 - - movs \tmp, \irqstat, lsl #8 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #8 - - movs \tmp, \irqstat, lsl #4 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #4 - - movs \tmp, \irqstat, lsl #2 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #2 - - movs \tmp, \irqstat, lsl #1 - addeq \irqnr, \irqnr, #1 - orrs \base, \base, #1 - -1002: - .endm diff --git a/trunk/arch/arm/mach-ep93xx/include/mach/system.h b/trunk/arch/arm/mach-ep93xx/include/mach/system.h index 6d661fe9d66c..bdf6c4f1feef 100644 --- a/trunk/arch/arm/mach-ep93xx/include/mach/system.h +++ b/trunk/arch/arm/mach-ep93xx/include/mach/system.h @@ -11,8 +11,6 @@ static inline void arch_idle(void) static inline void arch_reset(char mode, const char *cmd) { - local_irq_disable(); - /* * Set then clear the SWRST bit to initiate a software reset */ diff --git a/trunk/arch/arm/mach-ep93xx/micro9.c b/trunk/arch/arm/mach-ep93xx/micro9.c index e72f7368876e..a6dae6c2e3c1 100644 --- a/trunk/arch/arm/mach-ep93xx/micro9.c +++ b/trunk/arch/arm/mach-ep93xx/micro9.c @@ -18,6 +18,7 @@ #include +#include #include #include @@ -80,6 +81,7 @@ MACHINE_START(MICRO9, "Contec Micro9-High") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine, MACHINE_END @@ -91,6 +93,7 @@ MACHINE_START(MICRO9M, "Contec Micro9-Mid") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine, MACHINE_END @@ -102,6 +105,7 @@ MACHINE_START(MICRO9L, "Contec Micro9-Lite") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine, MACHINE_END @@ -113,6 +117,7 @@ MACHINE_START(MICRO9S, "Contec Micro9-Slim") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/simone.c b/trunk/arch/arm/mach-ep93xx/simone.c index 52e090dc9d27..40121ba8e711 100644 --- a/trunk/arch/arm/mach-ep93xx/simone.c +++ b/trunk/arch/arm/mach-ep93xx/simone.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -80,6 +81,7 @@ MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = simone_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/snappercl15.c b/trunk/arch/arm/mach-ep93xx/snappercl15.c index 8121e3aedc0a..ec7c63ff01e2 100644 --- a/trunk/arch/arm/mach-ep93xx/snappercl15.c +++ b/trunk/arch/arm/mach-ep93xx/snappercl15.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -177,6 +178,7 @@ MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = snappercl15_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/ts72xx.c b/trunk/arch/arm/mach-ep93xx/ts72xx.c index 8b2f1435bcac..760384e6407d 100644 --- a/trunk/arch/arm/mach-ep93xx/ts72xx.c +++ b/trunk/arch/arm/mach-ep93xx/ts72xx.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -247,6 +248,7 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") .atag_offset = 0x100, .map_io = ts72xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = ts72xx_init_machine, MACHINE_END diff --git a/trunk/arch/arm/mach-exynos/cpu.c b/trunk/arch/arm/mach-exynos/cpu.c index 90ec247f3b37..22316cb31a8c 100644 --- a/trunk/arch/arm/mach-exynos/cpu.c +++ b/trunk/arch/arm/mach-exynos/cpu.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -33,8 +34,6 @@ #include #include -unsigned int gic_bank_offset __read_mostly; - extern int combiner_init(unsigned int combiner_nr, void __iomem *base, unsigned int irq_start); extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq); @@ -207,27 +206,14 @@ void __init exynos4_init_clocks(int xtal) exynos4_setup_clocks(); } -static void exynos4_gic_irq_fix_base(struct irq_data *d) -{ - struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); - - gic_data->cpu_base = S5P_VA_GIC_CPU + - (gic_bank_offset * smp_processor_id()); - - gic_data->dist_base = S5P_VA_GIC_DIST + - (gic_bank_offset * smp_processor_id()); -} - void __init exynos4_init_irq(void) { int irq; + unsigned int gic_bank_offset; gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; - gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); - gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base; - gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base; - gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base; + gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset); for (irq = 0; irq < MAX_COMBINER_NR; irq++) { diff --git a/trunk/arch/arm/mach-exynos/include/mach/entry-macro.S b/trunk/arch/arm/mach-exynos/include/mach/entry-macro.S index f5e9fd8e37b4..3ba4f547534b 100644 --- a/trunk/arch/arm/mach-exynos/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-exynos/include/mach/entry-macro.S @@ -9,83 +9,8 @@ * warranty of any kind, whether express or implied. */ -#include -#include -#include - .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - mov \tmp, #0 - - mrc p15, 0, \base, c0, c0, 5 - and \base, \base, #3 - cmp \base, #0 - beq 1f - - ldr \tmp, =gic_bank_offset - ldr \tmp, [\tmp] - cmp \base, #1 - beq 1f - - cmp \base, #2 - addeq \tmp, \tmp, \tmp - addne \tmp, \tmp, \tmp, LSL #1 - -1: ldr \base, =gic_cpu_base_addr - ldr \base, [\base] - add \base, \base, \tmp - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - /* - * The interrupt numbering scheme is defined in the - * 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. - * 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). - */ - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ - - ldr \tmp, =1021 - - bic \irqnr, \irqstat, #0x1c00 - - cmp \irqnr, #15 - cmpcc \irqnr, \irqnr - cmpne \irqnr, \tmp - cmpcs \irqnr, \irqnr - addne \irqnr, \irqnr, #32 - - .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 diff --git a/trunk/arch/arm/mach-exynos/mach-armlex4210.c b/trunk/arch/arm/mach-exynos/mach-armlex4210.c index f0ca6c157d29..49da3089249a 100644 --- a/trunk/arch/arm/mach-exynos/mach-armlex4210.c +++ b/trunk/arch/arm/mach-exynos/mach-armlex4210.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -210,6 +211,7 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210") .atag_offset = 0x100, .init_irq = exynos4_init_irq, .map_io = armlex4210_map_io, + .handle_irq = gic_handle_irq, .init_machine = armlex4210_machine_init, .timer = &exynos4_timer, MACHINE_END diff --git a/trunk/arch/arm/mach-exynos/mach-nuri.c b/trunk/arch/arm/mach-exynos/mach-nuri.c index 236bbe187163..5acec11821a4 100644 --- a/trunk/arch/arm/mach-exynos/mach-nuri.c +++ b/trunk/arch/arm/mach-exynos/mach-nuri.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -1333,6 +1334,7 @@ MACHINE_START(NURI, "NURI") .atag_offset = 0x100, .init_irq = exynos4_init_irq, .map_io = nuri_map_io, + .handle_irq = gic_handle_irq, .init_machine = nuri_machine_init, .timer = &exynos4_timer, .reserve = &nuri_reserve, diff --git a/trunk/arch/arm/mach-exynos/mach-origen.c b/trunk/arch/arm/mach-exynos/mach-origen.c index f80b563f2be7..5561b06c38ec 100644 --- a/trunk/arch/arm/mach-exynos/mach-origen.c +++ b/trunk/arch/arm/mach-exynos/mach-origen.c @@ -22,6 +22,7 @@ #include #include +#include #include #include