diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 10:57:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 10:57:16 -0800 |
commit | b8edf848e9119bab9d999b9ca80d8520641810f2 (patch) | |
tree | 76517286b247626ed37dda41a4f946f6c34b8bff /arch | |
parent | db5b0ae00712b5176d7405e7a1dd2bfd6e8f5070 (diff) | |
parent | 3f54db784a6af9a6d53396949cbecf62edbad247 (diff) |
Merge tag 'multiplatform' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC multiplatform conversion patches from Olof Johansson:
"Here are more patches in the progression towards multiplatform, sparse
irq conversions in particular.
Tegra has a handful of cleanups and general groundwork, but is not
quite there yet on full enablement.
Platforms that are enabled through this branch are VT8500 and Zynq.
Note that i.MX was converted in one of the earlier cleanup branches as
well (before we started a separate topic for multiplatform). And both
new platforms for this merge window, sunxi and bcm, were merged with
multiplatform support enabled."
Fix up conflicts mostly as per Olof.
* tag 'multiplatform' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (29 commits)
ARM: zynq: Remove all unused mach headers
ARM: zynq: add support for ARCH_MULTIPLATFORM
ARM: zynq: make use of debug_ll_io_init()
ARM: zynq: remove TTC early mapping
ARM: tegra: move debug-macro.S to include/debug
ARM: tegra: don't include iomap.h from debug-macro.S
ARM: tegra: decouple uncompress.h and debug-macro.S
ARM: tegra: simplify DEBUG_LL UART selection options
ARM: tegra: select SPARSE_IRQ
ARM: tegra: enhance timer.c to get IO address from device tree
ARM: tegra: enhance timer.c to get IRQ info from device tree
ARM: timer: fix checkpatch warnings
ARM: tegra: add TWD to device tree
ARM: tegra: define DT bindings for and instantiate RTC
ARM: tegra: define DT bindings for and instantiate timer
clocksource/mtu-nomadik: use apb_pclk
clk: ux500: Register mtu apb_pclocks
ARM: plat-nomadik: convert platforms to SPARSE_IRQ
mfd/db8500-prcmu: use the irq_domain_add_simple()
mfd/ab8500-core: use irq_domain_add_simple()
...
Diffstat (limited to 'arch')
52 files changed, 534 insertions, 1282 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3bb60c8adbf..2277f9530b0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -650,6 +650,7 @@ config ARCH_TEGRA select HAVE_CLK select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 + select SPARSE_IRQ select USE_OF help This enables support for NVIDIA Tegra based systems (Tegra APX, @@ -891,6 +892,7 @@ config ARCH_U8500 select GENERIC_CLOCKEVENTS select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 + select SPARSE_IRQ help Support for ST-Ericsson's Ux500 architecture @@ -905,6 +907,7 @@ config ARCH_NOMADIK select MIGHT_HAVE_CACHE_L2X0 select PINCTRL select PINCTRL_STN8815 + select SPARSE_IRQ help Support for the Nomadik platform by ST-Ericsson @@ -948,7 +951,7 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1/2/3/4). -config ARCH_VT8500 +config ARCH_VT8500_SINGLE bool "VIA/WonderMedia 85xx" select ARCH_HAS_CPUFREQ select ARCH_REQUIRE_GPIOLIB @@ -958,22 +961,12 @@ config ARCH_VT8500 select GENERIC_CLOCKEVENTS select GENERIC_GPIO select HAVE_CLK + select MULTI_IRQ_HANDLER + select SPARSE_IRQ select USE_OF help Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. -config ARCH_ZYNQ - bool "Xilinx Zynq ARM Cortex A9 Platform" - select ARM_AMBA - select ARM_GIC - select COMMON_CLK - select CPU_V7 - select GENERIC_CLOCKEVENTS - select ICST - select MIGHT_HAVE_CACHE_L2X0 - select USE_OF - help - Support for Xilinx Zynq ARM Cortex A9 Platform endchoice menu "Multiple platform selection" @@ -1074,7 +1067,6 @@ source "arch/arm/mach-mxs/Kconfig" source "arch/arm/mach-netx/Kconfig" source "arch/arm/mach-nomadik/Kconfig" -source "arch/arm/plat-nomadik/Kconfig" source "arch/arm/plat-omap/Kconfig" @@ -1137,8 +1129,12 @@ source "arch/arm/mach-versatile/Kconfig" source "arch/arm/mach-vexpress/Kconfig" source "arch/arm/plat-versatile/Kconfig" +source "arch/arm/mach-vt8500/Kconfig" + source "arch/arm/mach-w90x900/Kconfig" +source "arch/arm/mach-zynq/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 512b3943854..661030d6bc6 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -379,6 +379,13 @@ choice Say Y here if you want kernel low-level debugging support on Allwinner A1X based platforms on the UART1. + config DEBUG_TEGRA_UART + depends on ARCH_TEGRA + bool "Use Tegra UART for low-level debug" + help + Say Y here if you want kernel low-level debugging support + on Tegra based platforms. + config DEBUG_VEXPRESS_UART0_DETECT bool "Autodetect UART0 on Versatile Express Cortex-A core tiles" depends on ARCH_VEXPRESS && CPU_CP15_MMU @@ -452,6 +459,36 @@ config DEBUG_IMX6Q_UART_PORT Choose UART port on which kernel low-level debug messages should be output. +choice + prompt "Low-level debug console UART" + depends on DEBUG_LL && DEBUG_TEGRA_UART + + config TEGRA_DEBUG_UART_AUTO_ODMDATA + bool "Via ODMDATA" + help + Automatically determines which UART to use for low-level debug based + on the ODMDATA value. This value is part of the BCT, and is written + to the boot memory device using nvflash, or other flashing tool. + When bits 19:18 are 3, then bits 17:15 indicate which UART to use; + 0/1/2/3/4 are UART A/B/C/D/E. + + config TEGRA_DEBUG_UARTA + bool "UART A" + + config TEGRA_DEBUG_UARTB + bool "UART B" + + config TEGRA_DEBUG_UARTC + bool "UART C" + + config TEGRA_DEBUG_UARTD + bool "UART D" + + config TEGRA_DEBUG_UARTE + bool "UART E" + +endchoice + config DEBUG_LL_INCLUDE string default "debug/icedcc.S" if DEBUG_ICEDCC @@ -469,6 +506,8 @@ config DEBUG_LL_INCLUDE default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1 default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \ DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 + default "debug/tegra.S" if DEBUG_TEGRA_UART + default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 default "mach/debug-macro.S" config EARLY_PRINTK diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 9c60f474a55..30c443c406f 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -202,7 +202,6 @@ machine-$(CONFIG_ARCH_SUNXI) += sunxi plat-$(CONFIG_ARCH_OMAP) += omap plat-$(CONFIG_ARCH_S3C64XX) += samsung plat-$(CONFIG_PLAT_IOP) += iop -plat-$(CONFIG_PLAT_NOMADIK) += nomadik plat-$(CONFIG_PLAT_ORION) += orion plat-$(CONFIG_PLAT_PXA) += pxa plat-$(CONFIG_PLAT_S3C24XX) += s3c24xx samsung diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index fba998e3954..b8effa1cbda 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -91,6 +91,12 @@ }; }; + timer@50004600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x50040600 0x20>; + interrupts = <1 13 0x304>; + }; + cache-controller@50043000 { compatible = "arm,pl310-cache"; reg = <0x50043000 0x1000>; @@ -108,6 +114,15 @@ #interrupt-cells = <3>; }; + timer@60005000 { + compatible = "nvidia,tegra20-timer"; + reg = <0x60005000 0x60>; + interrupts = <0 0 0x04 + 0 1 0x04 + 0 41 0x04 + 0 42 0x04>; + }; + apbdma: dma { compatible = "nvidia,tegra20-apbdma"; reg = <0x6000a000 0x1200>; @@ -225,6 +240,12 @@ #pwm-cells = <2>; }; + rtc { + compatible = "nvidia,tegra20-rtc"; + reg = <0x7000e000 0x100>; + interrupts = <0 2 0x04>; + }; + i2c@7000c000 { compatible = "nvidia,tegra20-i2c"; reg = <0x7000c000 0x100>; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index efa603d47a6..529fdb82dfd 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -91,6 +91,12 @@ }; }; + timer@50004600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x50040600 0x20>; + interrupts = <1 13 0xf04>; + }; + cache-controller@50043000 { compatible = "arm,pl310-cache"; reg = <0x50043000 0x1000>; @@ -108,6 +114,17 @@ #interrupt-cells = <3>; }; + timer@60005000 { + compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer"; + reg = <0x60005000 0x400>; + interrupts = <0 0 0x04 + 0 1 0x04 + 0 41 0x04 + 0 42 0x04 + 0 121 0x04 + 0 122 0x04>; + }; + apbdma: dma { compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma"; reg = <0x6000a000 0x1400>; @@ -219,6 +236,12 @@ #pwm-cells = <2>; }; + rtc { + compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc"; + reg = <0x7000e000 0x100>; + interrupts = <0 2 0x04>; + }; + i2c@7000c000 { compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; reg = <0x7000c000 0x100>; diff --git a/arch/arm/include/debug/tegra.S b/arch/arm/include/debug/tegra.S new file mode 100644 index 00000000000..883d7c22fd9 --- /dev/null +++ b/arch/arm/include/debug/tegra.S @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2010,2011 Google, Inc. + * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved. + * + * Author: + * Colin Cross <ccross@google.com> + * Erik Gilling <konkers@google.com> + * Doug Anderson <dianders@chromium.org> + * Stephen Warren <swarren@nvidia.com> + * + * Portions based on mach-omap2's debug-macro.S + * Copyright (C) 1994-1999 Russell King + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/serial_reg.h> + +#define UART_SHIFT 2 + +/* Physical addresses */ +#define TEGRA_CLK_RESET_BASE 0x60006000 +#define TEGRA_APB_MISC_BASE 0x70000000 +#define TEGRA_UARTA_BASE 0x70006000 +#define TEGRA_UARTB_BASE 0x70006040 +#define TEGRA_UARTC_BASE 0x70006200 +#define TEGRA_UARTD_BASE 0x70006300 +#define TEGRA_UARTE_BASE 0x70006400 +#define TEGRA_PMC_BASE 0x7000e400 + +#define TEGRA_CLK_RST_DEVICES_L (TEGRA_CLK_RESET_BASE + 0x04) +#define TEGRA_CLK_RST_DEVICES_H (TEGRA_CLK_RESET_BASE + 0x08) +#define TEGRA_CLK_RST_DEVICES_U (TEGRA_CLK_RESET_BASE + 0x0c) +#define TEGRA_CLK_OUT_ENB_L (TEGRA_CLK_RESET_BASE + 0x10) +#define TEGRA_CLK_OUT_ENB_H (TEGRA_CLK_RESET_BASE + 0x14) +#define TEGRA_CLK_OUT_ENB_U (TEGRA_CLK_RESET_BASE + 0x18) +#define TEGRA_PMC_SCRATCH20 (TEGRA_PMC_BASE + 0xa0) +#define TEGRA_APB_MISC_GP_HIDREV (TEGRA_APB_MISC_BASE + 0x804) + +/* + * Must be 1MB-aligned since a 1MB mapping is used early on. + * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[]. + */ +#define UART_VIRTUAL_BASE 0xfe100000 + +#define checkuart(rp, rv, lhu, bit, uart) \ + /* Load address of CLK_RST register */ \ + movw rp, #TEGRA_CLK_RST_DEVICES_##lhu & 0xffff ; \ + movt rp, #TEGRA_CLK_RST_DEVICES_##lhu >> 16 ; \ + /* Load value from CLK_RST register */ \ + ldr rp, [rp, #0] ; \ + /* Test UART's reset bit */ \ + tst rp, #(1 << bit) ; \ + /* If set, can't use UART; jump to save no UART */ \ + bne 90f ; \ + /* Load address of CLK_OUT_ENB register */ \ + movw rp, #TEGRA_CLK_OUT_ENB_##lhu & 0xffff ; \ + movt rp, #TEGRA_CLK_OUT_ENB_##lhu >> 16 ; \ + /* Load value from CLK_OUT_ENB register */ \ + ldr rp, [rp, #0] ; \ + /* Test UART's clock enable bit */ \ + tst rp, #(1 << bit) ; \ + /* If clear, can't use UART; jump to save no UART */ \ + beq 90f ; \ + /* Passed all tests, load address of UART registers */ \ + movw rp, #TEGRA_UART##uart##_BASE & 0xffff ; \ + movt rp, #TEGRA_UART##uart##_BASE >> 16 ; \ + /* Jump to save UART address */ \ + b 91f + + .macro addruart, rp, rv, tmp + adr \rp, 99f @ actual addr of 99f + ldr \rv, [\rp] @ linked addr is stored there + sub \rv, \rv, \rp @ offset between the two + ldr \rp, [\rp, #4] @ linked tegra_uart_config + sub \tmp, \rp, \rv @ actual tegra_uart_config + ldr \rp, [\tmp] @ Load tegra_uart_config + cmp \rp, #1 @ needs initialization? + bne 100f @ no; go load the addresses + mov \rv, #0 @ yes; record init is done + str \rv, [\tmp] + +#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA + /* Check ODMDATA */ +10: movw \rp, #TEGRA_PMC_SCRATCH20 & 0xffff + movt \rp, #TEGRA_PMC_SCRATCH20 >> 16 + ldr \rp, [\rp, #0] @ Load PMC_SCRATCH20 + ubfx \rv, \rp, #18, #2 @ 19:18 are console type + cmp \rv, #2 @ 2 and 3 mean DCC, UART + beq 11f @ some boards swap the meaning + cmp \rv, #3 @ so accept either + bne 90f +11: ubfx \rv, \rp, #15, #3 @ 17:15 are UART ID + cmp \rv, #0 @ UART 0? + beq 20f + cmp \rv, #1 @ UART 1? + beq 21f + cmp \rv, #2 @ UART 2? + beq 22f + cmp \rv, #3 @ UART 3? + beq 23f + cmp \rv, #4 @ UART 4? + beq 24f + b 90f @ invalid +#endif + +#if defined(CONFIG_TEGRA_DEBUG_UARTA) || \ + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) + /* Check UART A validity */ +20: checkuart(\rp, \rv, L, 6, A) +#endif + +#if defined(CONFIG_TEGRA_DEBUG_UARTB) || \ + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) + /* Check UART B validity */ +21: checkuart(\rp, \rv, L, 7, B) +#endif + +#if defined(CONFIG_TEGRA_DEBUG_UARTC) || \ + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) + /* Check UART C validity */ +22: checkuart(\rp, \rv, H, 23, C) +#endif + +#if defined(CONFIG_TEGRA_DEBUG_UARTD) || \ + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) + /* Check UART D validity */ +23: checkuart(\rp, \rv, U, 1, D) +#endif + +#if defined(CONFIG_TEGRA_DEBUG_UARTE) || \ + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) + /* Check UART E validity */ +24: + checkuart(\rp, \rv, U, 2, E) +#endif + + /* No valid UART found */ +90: mov \rp, #0 + /* fall through */ + + /* Record whichever UART we chose */ +91: str \rp, [\tmp, #4] @ Store in tegra_uart_phys + cmp \rp, #0 @ Valid UART address? + bne 92f @ Yes, go process it + str \rp, [\tmp, #8] @ Store 0 in tegra_uart_virt + b 100f @ Done +92: and \rv, \rp, #0xffffff @ offset within 1MB section + add \rv, \rv, #UART_VIRTUAL_BASE + str \rv, [\tmp, #8] @ Store in tegra_uart_virt + movw \rv, #TEGRA_APB_MISC_GP_HIDREV & 0xffff + movt \rv, #TEGRA_APB_MISC_GP_HIDREV >> 16 + ldr \rv, [\rv, #0] @ Load HIDREV + ubfx \rv, \rv, #8, #8 @ 15:8 are SoC version + cmp \rv, #0x20 @ Tegra20? + moveq \rv, #0x75 @ Tegra20 divisor + movne \rv, #0xdd @ Tegra30 divisor + str \rv, [\tmp, #12] @ Save divisor to scratch + /* uart[UART_LCR] = UART_LCR_WLEN8 | UART_LCR_DLAB; */ + mov \rv, #UART_LCR_WLEN8 | UART_LCR_DLAB + str \rv, [\rp, #UART_LCR << UART_SHIFT] + /* uart[UART_DLL] = div & 0xff; */ + ldr \rv, [\tmp, #12] + and \rv, \rv, #0xff + str \rv, [\rp, #UART_DLL << UART_SHIFT] + /* uart[UART_DLM] = div >> 8; */ + ldr \rv, [\tmp, #12] + lsr \rv, \rv, #8 + str \rv, [\rp, #UART_DLM << UART_SHIFT] + /* uart[UART_LCR] = UART_LCR_WLEN8; */ + mov \rv, #UART_LCR_WLEN8 + str \rv, [\rp, #UART_LCR << UART_SHIFT] + b 100f + + .align +99: .word . + .word tegra_uart_config + .ltorg + + /* Load previously selected UART address */ +100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys + ldr \rv, [\tmp, #8] @ Load tegra_uart_virt + .endm + +/* + * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra + * check to make sure that the UART address is actually valid. + */ + + .macro senduart, rd, rx + cmp \rx, #0 + strneb \rd, [\rx, #UART_TX << UART_SHIFT] +1001: + .endm + + .macro busyuart, rd, rx + cmp \rx, #0 + beq 1002f +1001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] + and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE + teq \rd, #UART_LSR_TEMT | UART_LSR_THRE + bne 1001b +1002: + .endm + + .macro waituart, rd, rx +#ifdef FLOW_CONTROL + cmp \rx, #0 + beq 1002f +1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] + tst \rd, #UART_MSR_CTS + beq 1001b +1002: +#endif + .endm diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/include/debug/zynq.S index 3ab0be1f619..f9aa9740a73 100644 --- a/arch/arm/mach-zynq/include/mach/debug-macro.S +++ b/arch/arm/include/debug/zynq.S @@ -1,5 +1,4 @@ -/* arch/arm/mach-zynq/include/mach/debug-macro.S - * +/* * Debugging macro include header * * Copyright (C) 2011 Xilinx @@ -13,9 +12,25 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */ +#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */ +#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */ + +#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */ +#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ + +#define UART0_PHYS 0xE0000000 +#define UART1_PHYS 0xE0001000 +#define UART_SIZE SZ_4K +#define UART_VIRT 0xF0001000 + +#if IS_ENABLED(CONFIG_DEBUG_ZYNQ_UART1) +# define LL_UART_PADDR UART1_PHYS +#else +# define LL_UART_PADDR UART0_PHYS +#endif -#include <mach/zynq_soc.h> -#include <mach/uart.h> +#define LL_UART_VADDR UART_VIRT .macro addruart, rp, rv, tmp ldr \rp, =LL_UART_PADDR @ physical diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig index c744946ef02..706dc5727bb 100644 --- a/arch/arm/mach-nomadik/Kconfig +++ b/arch/arm/mach-nomadik/Kconfig @@ -4,7 +4,7 @@ menu "Nomadik boards" config MACH_NOMADIK_8815NHK bool "ST 8815 Nomadik Hardware Kit (evaluation board)" - select HAS_MTU + select CLKSRC_NOMADIK_MTU select NOMADIK_8815 endmenu diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 22ef8a1abe0..5ccdf53c5a9 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -25,18 +25,16 @@ #include <linux/io.h> #include <linux/pinctrl/machine.h> #include <linux/platform_data/pinctrl-nomadik.h> +#include <linux/platform_data/clocksource-nomadik-mtu.h> +#include <linux/platform_data/mtd-nomadik-nand.h> #include <asm/hardware/vic.h> #include <asm/sizes.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/irq.h> #include <asm/mach/flash.h> #include <asm/mach/time.h> - -#include <plat/mtu.h> - -#include <linux/platform_data/mtd-nomadik-nand.h> #include <mach/fsmc.h> +#include <mach/irqs.h> #include "cpu-8815.h" @@ -260,7 +258,7 @@ static void __init nomadik_timer_init(void) src_cr |= SRC_CR_INIT_VAL; writel(src_cr, io_p2v(NOMADIK_SRC_BASE)); - nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE)); + nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0); } static struct sys_timer nomadik_timer = { diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h index a118e615f86..b549d057154 100644 --- a/arch/arm/mach-nomadik/include/mach/irqs.h +++ b/arch/arm/mach-nomadik/include/mach/irqs.h @@ -72,7 +72,7 @@ #define NOMADIK_NR_GPIO 128 /* last 4 not wired to pins */ #define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_GPIO_OFFSET) #define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_GPIO_OFFSET) -#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) +#define NOMADIK_NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) /* Following two are used by entry_macro.S, to access our dual-vic */ #define VIC_REG_IRQSR0 0 diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 9ff6f6ea361..e426d1b7747 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -57,57 +57,6 @@ config TEGRA_AHB which controls AHB bus master arbitration and some perfomance parameters(priority, prefech size). -choice - prompt "Default low-level debug console UART" - default TEGRA_DEBUG_UART_NONE - -config TEGRA_DEBUG_UART_NONE - bool "None" - -config TEGRA_DEBUG_UARTA - bool "UART-A" - -config TEGRA_DEBUG_UARTB - bool "UART-B" - -config TEGRA_DEBUG_UARTC - bool "UART-C" - -config TEGRA_DEBUG_UARTD - bool "UART-D" - -config TEGRA_DEBUG_UARTE - bool "UART-E" - -endchoice - -choice - prompt "Automatic low-level debug console UART" - default TEGRA_DEBUG_UART_AUTO_NONE - -config TEGRA_DEBUG_UART_AUTO_NONE - bool "None" - -config TEGRA_DEBUG_UART_AUTO_ODMDATA - bool "Via ODMDATA" - help - Automatically determines which UART to use for low-level debug based - on the ODMDATA value. This value is part of the BCT, and is written - to the boot memory device using nvflash, or other flashing tool. - When bits 19:18 are 3, then bits 17:15 indicate which UART to use; - 0/1/2/3/4 are UART A/B/C/D/E. - -config TEGRA_DEBUG_UART_AUTO_SCRATCH - bool "Via UART scratch register" - help - Automatically determines which UART to use for low-level debug based - on the UART scratch register value. Some bootloaders put ASCII 'D' - in this register when they initialize their own console UART output. - Using this option allows the kernel to automatically pick the same - UART. - -endchoice - config TEGRA_EMC_SCALING_ENABLE bool "Enable scaling the memory frequency" diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 11a74db51e5..0816562725f 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -45,14 +45,15 @@ * kernel is loaded. The data is declared here rather than debug-macro.S so * that multiple inclusions of debug-macro.S point at the same data. */ -#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF) -u32 tegra_uart_config[3] = { +u32 tegra_uart_config[4] = { /* Debug UART initialization required */ 1, /* Debug UART physical address */ - (u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET), + 0, /* Debug UART virtual address */ - (u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET), + 0, + /* Scratch space for debug macro */ + 0, }; #ifdef CONFIG_OF diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S deleted file mode 100644 index 44ca7b1d8b8..00000000000 --- a/arch/arm/mach-tegra/include/mach/debug-macro.S +++ /dev/null @@ -1,100 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/debug-macro.S - * - * Copyright (C) 2010,2011 Google, Inc. - * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved. - * - * Author: - * Colin Cross <ccross@google.com> - * Erik Gilling <konkers@google.com> - * Doug Anderson <dianders@chromium.org> - * Stephen Warren <swarren@nvidia.com> - * - * Portions based on mach-omap2's debug-macro.S - * Copyright (C) 1994-1999 Russell King - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/serial_reg.h> - -#include "../../iomap.h" -#include "../../irammap.h" - - .macro addruart, rp, rv, tmp - adr \rp, 99f @ actual addr of 99f - ldr \rv, [\rp] @ linked addr is stored there - sub \rv, \rv, \rp @ offset between the two - ldr \rp, [\rp, #4] @ linked tegra_uart_config - sub \tmp, \rp, \rv @ actual tegra_uart_config - ldr \rp, [\tmp] @ Load tegra_uart_config - cmp \rp, #1 @ needs intitialization? - bne 100f @ no; go load the addresses - mov \rv, #0 @ yes; record init is done - str \rv, [\tmp] - mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM - ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET] - movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff - movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16 - cmp \rv, \rp @ Cookie present? - bne 100f @ No, use default UART - mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM - ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4] - str \rv, [\tmp, #4] @ Store in tegra_uart_phys - sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address - add \rv, \rv, #IO_APB_VIRT - str \rv, [\tmp, #8] @ Store in tegra_uart_virt - b 100f - - .align -99: .word . - .word tegra_uart_config - .ltorg - -100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys - ldr \rv, [\tmp, #8] @ Load tegra_uart_virt - .endm - -#define UART_SHIFT 2 - -/* - * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra - * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case. - * We use the fact that all 5 valid UART addresses all have something in the - * 2nd-to-lowest byte. - */ - - .macro senduart, rd, rx - tst \rx, #0x0000ff00 - strneb \rd, [\rx, #UART_TX << UART_SHIFT] -1001: - .endm - - .macro busyuart, rd, rx - tst \rx, #0x0000ff00 - beq 1002f -1001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] - and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE - teq \rd, #UART_LSR_TEMT | UART_LSR_THRE - bne 1001b -1002: - .endm - - .macro waituart, rd, rx -#ifdef FLOW_CONTROL - tst \rx, #0x0000ff00 - beq 1002f -1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] - tst \rd, #UART_MSR_CTS - beq 1001b -1002: -#endif - .endm diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h deleted file mode 100644 index aad1a2c1d71..00000000000 --- a/arch/arm/mach-tegra/include/mach/irqs.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/irqs.h - * - * Copyright (C) 2010 Google, Inc. - * - * Author: - * Colin Cross <ccross@google.com> - * Erik Gilling <konkers@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __MACH_TEGRA_IRQS_H -#define __MACH_TEGRA_IRQS_H - -#define INT_GIC_BASE 0 - -#define IRQ_LOCALTIMER 29 - -/* Primary Interrupt Controller */ -#define INT_PRI_BASE (INT_GIC_BASE + 32) -#define INT_TMR1 (INT_PRI_BASE + 0) -#define INT_TMR2 (INT_PRI_BASE + 1) -#define INT_RTC (INT_PRI_BASE + 2) -#define INT_I2S2 (INT_PRI_BASE + 3) -#define INT_SHR_SEM_INBOX_IBF (INT_PRI_BASE + 4) -#define INT_SHR_SEM_INBOX_IBE (INT_PRI_BASE + 5) -#define INT_SHR_SEM_OUTBOX_IBF (INT_PRI_BASE + 6) -#define INT_SHR_SEM_OUTBOX_IBE (INT_PRI_BASE + 7) -#define INT_VDE_UCQ_ERROR (INT_PRI_BASE + 8) -#define INT_VDE_SYNC_TOKEN (INT_PRI_BASE + 9) -#define INT_VDE_BSE_V (INT_PRI_BASE + 10) -#define INT_VDE_BSE_A (INT_PRI_BASE + 11) -#define INT_VDE_SXE (INT_PRI_BASE + 12) -#define INT_I2S1 (INT_PRI_BASE + 13) -#define INT_SDMMC1 (INT_PRI_BASE + 14) -#define INT_SDMMC2 (INT_PRI_BASE + 15) -#define INT_XIO (INT_PRI_BASE + 16) -#define INT_VDE (INT_PRI_BASE + 17) -#define INT_AVP_UCQ (INT_PRI_BASE + 18) -#define INT_SDMMC3 (INT_PRI_BASE + 19) -#define INT_USB (INT_PRI_BASE + 20) -#define INT_USB2 (INT_PRI_BASE + 21) -#define INT_PRI_RES_22 (INT_PRI_BASE + 22) -#define INT_EIDE (INT_PRI_BASE + 23) -#define INT_NANDFLASH (INT_PRI_BASE + 24) -#define INT_VCP (INT_PRI_BASE + 25) -#define INT_APB_DMA (INT_PRI_BASE + 26) -#define INT_AHB_DMA (INT_PRI_BASE + 27) -#define INT_GNT_0 (INT_PRI_BASE + 28) -#define INT_GNT_1 (INT_PRI_BASE + 29) -#define INT_OWR (INT_PRI_BASE + 30) -#define INT_SDMMC4 (INT_PRI_BASE + 31) - -/* Secondary Interrupt Controller */ -#define INT_SEC_BASE (INT_PRI_BASE + 32) -#define INT_GPIO1 (INT_SEC_BASE + 0) -#define INT_GPIO2 (INT_SEC_BASE + 1) -#define INT_GPIO3 (INT_SEC_BASE + 2) -#define INT_GPIO4 (INT_SEC_BASE + 3) -#define INT_UARTA (INT_SEC_BASE + 4) -#define INT_UARTB (INT_SEC_BASE + 5) -#define INT_I2C (INT_SEC_BASE + 6) -#define INT_SPI (INT_SEC_BASE + 7) -#define INT_TWC (INT_SEC_BASE + 8) -#define INT_TMR3 (INT_SEC_BASE + 9) -#define INT_TMR4 (INT_SEC_BASE + 10) -#define INT_FLOW_RSM0 (INT_SEC_BASE + 11) -#define INT_FLOW_RSM1 (INT_SEC_BASE + 12) -#define INT_SPDIF (INT_SEC_BASE + 13) -#define INT_UARTC (INT_SEC_BASE + 14) -#define INT_MIPI (INT_SEC_BASE + 15) -#define INT_EVENTA (INT_SEC_BASE + 16) -#define INT_EVENTB (INT_SEC_BASE + 17) -#define INT_EVENTC (INT_SEC_BASE + 18) -#define INT_EVENTD (INT_SEC_BASE + 19) -#define INT_VFIR (INT_SEC_BASE + 20) -#define INT_DVC (INT_SEC_BASE + 21) -#define INT_SYS_STATS_MON (INT_SEC_BASE + 22) -#define INT_GPIO5 (INT_SEC_BASE + 23) -#define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) -#define INT_CPU1_PMU_INTR (INT_SEC_BASE + 25) -#define INT_SEC_RES_26 (INT_SEC_BASE + 26) -#define INT_S_LINK1 (INT_SEC_BASE + 27) -#define INT_APB_DMA_COP (INT_SEC_BASE + 28) -#define INT_AHB_DMA_COP (INT_SEC_BASE + 29) -#define INT_DMA_TX (INT_SEC_BASE + 30) -#define INT_DMA_RX (INT_SEC_BASE + 31) - -/* Tertiary Interrupt Controller */ -#define INT_TRI_BASE (INT_SEC_BASE + 32) -#define INT_HOST1X_COP_SYNCPT (INT_TRI_BASE + 0) -#define INT_HOST1X_MPCORE_SYNCPT (INT_TRI_BASE + 1) -#define INT_HOST1X_COP_GENERAL (INT_TRI_BASE + 2) -#define INT_HOST1X_MPCORE_GENERAL (INT_TRI_BASE + 3) -#define INT_MPE_GENERAL (INT_TRI_BASE + 4) -#define INT_VI_GENERAL (INT_TRI_BASE + 5) -#define INT_EPP_GENERAL (INT_TRI_BASE + 6) -#define INT_ISP_GENERAL (INT_TRI_BASE + 7) -#define INT_2D_GENERAL (INT_TRI_BASE + 8) -#define INT_DISPLAY_GENERAL (INT_TRI_BASE + 9) -#define INT_DISPLAY_B_GENERAL (INT_TRI_BASE + 10) -#define INT_HDMI (INT_TRI_BASE + 11) -#define INT_TVO_GENERAL (INT_TRI_BASE + 12) -#define INT_MC_GENERAL (INT_TRI_BASE + 13) -#define INT_EMC_GENERAL (INT_TRI_BASE + 14) -#define INT_TRI_RES_15 (INT_TRI_BASE + 15) -#define INT_TRI_RES_16 (INT_TRI_BASE + 16) -#define INT_AC97 (INT_TRI_BASE + 17) -#define INT_SPI_2 (INT_TRI_BASE + 18) -#define INT_SPI_3 (INT_TRI_BASE + 19) -#define INT_I2C2 (INT_TRI_BASE + 20) -#define INT_KBC (INT_TRI_BASE + 21) -#define INT_EXTERNAL_PMU (INT_TRI_BASE + 22) -#define INT_GPIO6 (INT_TRI_BASE + 23) -#define INT_TVDAC (INT_TRI_BASE + 24) -#define INT_GPIO7 (INT_TRI_BASE + 25) -#define INT_UARTD (INT_TRI_BASE + 26) -#define INT_UARTE (INT_TRI_BASE + 27) -#define INT_I2C3 (INT_TRI_BASE + 28) -#define INT_SPI_4 (INT_TRI_BASE + 29) -#define INT_TRI_RES_30 (INT_TRI_BASE + 30) -#define INT_SW_RESERVED (INT_TRI_BASE + 31) - -/* Quaternary Interrupt Controller */ -#define INT_QUAD_BASE (INT_TRI_BASE + 32) -#define INT_SNOR (INT_QUAD_BASE + 0) -#define INT_USB3 (INT_QUAD_BASE + 1) -#define INT_PCIE_INTR (INT_QUAD_BASE + 2) -#define INT_PCIE_MSI (INT_QUAD_BASE + 3) -#define INT_QUAD_RES_4 (INT_QUAD_BASE + 4) -#define INT_QUAD_RES_5 (INT_QUAD_BASE + 5) -#define INT_QUAD_RES_6 (INT_QUAD_BASE + 6) -#define INT_QUAD_RES_7 (INT_QUAD_BASE + 7) -#define INT_APB_DMA_CH0 (INT_QUAD_BASE + 8) -#define INT_APB_DMA_CH1 (INT_QUAD_BASE + 9) -#define INT_APB_DMA_CH2 (INT_QUAD_BASE + 10) -#define INT_APB_DMA_CH3 (INT_QUAD_BASE + 11) -#define INT_APB_DMA_CH4 (INT_QUAD_BASE + 12) -#define INT_APB_DMA_CH5 (INT_QUAD_BASE + 13) -#define INT_APB_DMA_CH6 (INT_QUAD_BASE + 14) -#define INT_APB_DMA_CH7 (INT_QUAD_BASE + 15) -#define INT_APB_DMA_CH8 (INT_QUAD_BASE + 16) -#define INT_APB_DMA_CH9 (INT_QUAD_BASE + 17) -#define INT_APB_DMA_CH10 (INT_QUAD_BASE + 18) -#define INT_APB_DMA_CH11 (INT_QUAD_BASE + 19) -#define INT_APB_DMA_CH12 (INT_QUAD_BASE + 20) -#define INT_APB_DMA_CH13 (INT_QUAD_BASE + 21) -#define INT_APB_DMA_CH14 (INT_QUAD_BASE + 22) -#define INT_APB_DMA_CH15 (INT_QUAD_BASE + 23) -#define INT_QUAD_RES_24 (INT_QUAD_BASE + 24) -#define INT_QUAD_RES_25 (INT_QUAD_BASE + 25) -#define INT_QUAD_RES_26 (INT_QUAD_BASE + 26) -#define INT_QUAD_RES_27 (INT_QUAD_BASE + 27) -#define INT_QUAD_RES_28 (INT_QUAD_BASE + 28) -#define INT_QUAD_RES_29 (INT_QUAD_BASE + 29) -#define INT_QUAD_RES_30 (INT_QUAD_BASE + 30) -#define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) - -/* Tegra30 has 5 banks of 32 IRQs */ -#define INT_MAIN_NR (32 * 5) -#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR) - -/* Tegra30 has 8 banks of 32 GPIOs */ -#define INT_GPIO_NR (32 * 8) - -#define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) - -#define INT_BOARD_BASE TEGRA_NR_IRQS -#define NR_BOARD_IRQS 32 - -#define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS) - -#endif diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 27725750ca3..485003f9b63 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -29,7 +29,6 @@ #include <linux/serial_reg.h> #include "../../iomap.h" -#include "../../irammap.h" #define BIT(x) (1 << (x)) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -52,17 +51,6 @@ static inline void flush(void) { } -static inline void save_uart_address(void) -{ - u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET); - - if (uart) { - buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE; - buf[1] = (u32)uart; - } else - buf[0] = 0; -} - static const struct { u32 base; u32 reset_reg; @@ -139,51 +127,19 @@ int auto_odmdata(void) } #endif -#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH -int auto_scratch(void) -{ - int i; - - /* - * Look for the first UART that: - * a) Is not in reset. - * b) Is clocked. - * c) Has a 'D' in the scratchpad register. - * - * Note that on Tegra30, the first two conditions are required, since - * if not true, accesses to the UART scratch register will hang. - * Tegra20 doesn't have this issue. - * - * The intent is that the bootloader will tell the kernel which UART - * to use by setting up those conditions. If nothing found, we'll fall - * back to what's specified in TEGRA_DEBUG_UART_BASE. - */ - for (i = 0; i < ARRAY_SIZE(uarts); i++) { - if (!uart_clocked(i)) - continue; - - uart = (volatile u8 *)uarts[i].base; - if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D') - continue; - - return i; - } - - return -1; -} -#endif - /* * Setup before decompression. This is where we do UART selection for * earlyprintk and init the uart_base register. */ static inline void arch_decomp_setup(void) { - int uart_id, auto_uart_id; + int uart_id; volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; u32 chip, div; -#if defined(CONFIG_TEGRA_DEBUG_UARTA) +#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) + uart_id = auto_odmdata(); +#elif defined(CONFIG_TEGRA_DEBUG_UARTA) uart_id = 0; #elif defined(CONFIG_TEGRA_DEBUG_UARTB) uart_id = 1; @@ -193,19 +149,7 @@ static inline void arch_decomp_setup(void) uart_id = 3; #elif defined(CONFIG_TEGRA_DEBUG_UARTE) uart_id = 4; -#else - uart_id = -1; -#endif - -#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) - auto_uart_id = auto_odmdata(); -#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH) - auto_uart_id = auto_scratch(); -#else - auto_uart_id = -1; #endif - if (auto_uart_id != -1) - uart_id = auto_uart_id; if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) || !uart_clocked(uart_id)) @@ -213,7 +157,6 @@ static inline void arch_decomp_setup(void) else uart = (volatile u8 *)uarts[uart_id].base; - save_uart_address(); if (uart == NULL) return; diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c index 7d09f301b3a..bb9c9c29d18 100644 --- a/arch/arm/mach-tegra/io.c +++ b/arch/arm/mach-tegra/io.c @@ -59,5 +59,6 @@ static struct map_desc tegra_io_desc[] __initdata = { void __init tegra_map_common_io(void) { + debug_ll_io_init(); iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc)); } diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h index 53151030a07..db8be51cad8 100644 --- a/arch/arm/mach-tegra/iomap.h +++ b/arch/arm/mach-tegra/iomap.h @@ -261,20 +261,6 @@ #define TEGRA_SDMMC4_BASE 0xC8000600 #define TEGRA_SDMMC4_SIZE SZ_512 -#if defined(CONFIG_TEGRA_DEBUG_UART_NONE) -# define TEGRA_DEBUG_UART_BASE 0 -#elif defined(CONFIG_TEGRA_DEBUG_UARTA) -# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTB) -# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTC) -# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTD) -# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTE) -# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE -#endif - /* On TEGRA, many peripherals are very closely packed in * two 256MB io windows (that actually only use about 64KB * at the start of each). diff --git a/arch/arm/mach-tegra/irammap.h b/arch/arm/mach-tegra/irammap.h index 0cbe6326185..501952a8434 100644 --- a/arch/arm/mach-tegra/irammap.h +++ b/arch/arm/mach-tegra/irammap.h @@ -23,13 +23,4 @@ #define TEGRA_IRAM_RESET_HANDLER_OFFSET 0 #define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K -/* - * These locations are written to by uncompress.h, and read by debug-macro.S. - * The first word holds the cookie value if the data is valid. The second - * word holds the UART physical address. - */ -#define TEGRA_IRAM_DEBUG_UART_OFFSET SZ_1K -#define TEGRA_IRAM_DEBUG_UART_SIZE 8 -#define TEGRA_IRAM_DEBUG_UART_COOKIE 0x55415254 - #endif diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index f18fc3ab4e5..53d08587179 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -43,6 +43,9 @@ #include "board.h" #include "iomap.h" +/* Hack - need to parse this from DT */ +#define INT_PCIE_INTR 130 + /* register definitions */ #define AFI_OFFSET 0x3800 #define PADS_OFFSET 0x3000 diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 6ff50353651..e4863f3e9ee 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -26,16 +26,14 @@ #include <linux/clocksource.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/mach/time.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> -#include <mach/irqs.h> - #include "board.h" -#include "clock.h" -#include "iomap.h" #define RTC_SECONDS 0x08 #define RTC_SHADOW_SECONDS 0x0c @@ -53,8 +51,8 @@ #define TIMER_PTV 0x0 #define TIMER_PCR 0x4 -static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); -static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); +static void __iomem *timer_reg_base; +static void __iomem *rtc_base; static struct timespec persistent_ts; static u64 persistent_ms, last_persistent_ms; @@ -158,40 +156,66 @@ static struct irqaction tegra_timer_irq = { .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, .handler = tegra_timer_interrupt, .dev_id = &tegra_clockevent, - .irq = INT_TMR3, }; -#ifdef CONFIG_HAVE_ARM_TWD -static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, - TEGRA_ARM_PERIF_BASE + 0x600, - IRQ_LOCALTIMER); +static const struct of_device_id timer_match[] __initconst = { + { .compatible = "nvidia,tegra20-timer" }, + {} +}; -static void __init tegra_twd_init(void) -{ - int err = twd_local_timer_register(&twd_local_timer); - if (err) - pr_err("twd_local_timer_register failed %d\n", err); -} -#else -#define tegra_twd_init() do {} while(0) -#endif +static const struct of_device_id rtc_match[] __initconst = { + { .compatible = "nvidia,tegra20-rtc" }, + {} +}; static void __init tegra_init_timer(void) { + struct device_node *np; struct clk *clk; unsigned long rate; int ret; + np = of_find_matching_node(NULL, timer_match); + if (!np) { + pr_err("Failed to find timer DT node\n"); + BUG(); + } + + timer_reg_base = of_iomap(np, 0); + if (!timer_reg_base) { + pr_err("Can't map timer registers"); + BUG(); + } + + tegra_timer_irq.irq = irq_of_parse_and_map(np, 2); + if (tegra_timer_irq.irq <= 0) { + pr_err("Failed to map timer IRQ\n"); + BUG(); + } + clk = clk_get_sys("timer", NULL); if (IS_ERR(clk)) { - pr_warn("Unable to get timer clock." - " Assuming 12Mhz input clock.\n"); + pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); rate = 12000000; } else { clk_prepare_enable(clk); rate = clk_get_rate(clk); } + of_node_put(np); + + np = of_find_matching_node(NULL, rtc_match); + if (!np) { + pr_err("Failed to find RTC DT node\n"); + BUG(); + } + + rtc_base = of_iomap(np, 0); + if (!rtc_base) { + pr_err("Can't map RTC registers"); + BUG(); + } + /* * rtc registers are used by read_persistent_clock, keep the rtc clock * enabled @@ -202,6 +226,8 @@ static void __init tegra_init_timer(void) else clk_prepare_enable(clk); + of_node_put(np); + switch (rate) { case 12000000: timer_writel(0x000b, TIMERUS_USEC_CFG); @@ -223,13 +249,13 @@ static void __init tegra_init_timer(void) if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { - printk(KERN_ERR "Failed to register clocksource\n"); + pr_err("Failed to register clocksource\n"); BUG(); } ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); if (ret) { - printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret); + pr_err("Failed to register timer IRQ: %d\n", ret); BUG(); } @@ -241,7 +267,9 @@ static void __init tegra_init_timer(void) tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.irq = tegra_timer_irq.irq; clockevents_register_device(&tegra_clockevent); - tegra_twd_init(); +#ifdef CONFIG_HAVE_ARM_TWD + twd_local_timer_of_register(); +#endif register_persistent_clock(NULL, tegra_read_persistent_clock); } diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index e8c3f0d70ca..5dea90636d9 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -7,8 +7,8 @@ config UX500_SOC_COMMON select ARM_ERRATA_764369 if SMP select ARM_GIC select CACHE_L2X0 + select CLKSRC_NOMADIK_MTU select COMMON_CLK - select HAS_MTU select PINCTRL select PINCTRL_NOMADIK select PL310_ERRATA_753970 if CACHE_PL310 diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c index bde91a58e10..7209db7cdc7 100644 --- a/arch/arm/mach-ux500/board-mop500-audio.c +++ b/arch/arm/mach-ux500/board-mop500-audio.c @@ -8,8 +8,7 @@ #include <linux/init.h> #include <linux/gpio.h> #include <linux/platform_data/pinctrl-nomadik.h> - -#include <plat/ste_dma40.h> +#include <linux/platform_data/dma-ste-dma40.h> #include <mach/devices.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 9c8e4a9e83e..051b62c2710 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -11,9 +11,9 @@ #include <linux/amba/mmci.h> #include <linux/mmc/host.h> #include <linux/platform_device.h> +#include <linux/platform_data/dma-ste-dma40.h> #include <asm/mach-types.h> -#include <plat/ste_dma40.h> #include <mach/devices.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 5b70212c253..d453522edb0 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -36,13 +36,12 @@ #include <linux/leds.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_data/pinctrl-nomadik.h> +#include <linux/platform_data/dma-ste-dma40.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> -#include <plat/ste_dma40.h> - #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 93442fcd9eb..db0bb75e2c7 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -21,16 +21,19 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/regulator/machine.h> +#include <linux/platform_data/pinctrl-nomadik.h> #include <linux/random.h> #include <asm/pmu.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> + #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> #include <mach/db8500-regs.h> +#include <mach/irqs.h> #include "devices-db8500.h" #include "ste-dma40-db8500.h" diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 692a77a1c15..16b5f71e697 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -14,6 +14,7 @@ #include <linux/platform_data/pinctrl-nomadik.h> #include <mach/hardware.h> +#include <mach/irqs.h> #include "devices-common.h" diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 91754a8a0d4..318d4902089 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -12,11 +12,11 @@ #include <linux/gpio.h> #include <linux/amba/bus.h> #include <linux/amba/pl022.h> - -#include <plat/ste_dma40.h> +#include <linux/platform_data/dma-ste-dma40.h> #include <mach/hardware.h> #include <mach/setup.h> +#include <mach/irqs.h> #include "ste-dma40-db8500.h" diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index 3c8010f4fb3..4b24c999265 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -8,6 +8,7 @@ #ifndef __DEVICES_DB8500_H #define __DEVICES_DB8500_H +#include <mach/irqs.h> #include "devices-common.h" struct ske_keypad_platform_data; diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index e8928548b6a..fc77b4274c8 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -46,6 +46,6 @@ #include <mach/irqs-board-mop500.h> #endif -#define NR_IRQS IRQ_BOARD_END +#define UX500_NR_IRQS IRQ_BOARD_END #endif /* ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h index 3cc7142eee0..9991aea3d57 100644 --- a/arch/arm/mach-ux500/include/mach/msp.h +++ b/arch/arm/mach-ux500/include/mach/msp.h @@ -8,7 +8,7 @@ #ifndef __MSP_H #define __MSP_H -#include <plat/ste_dma40.h> +#include <linux/platform_data/dma-ste-dma40.h> enum msp_i2s_id { MSP_I2S_0 = 0, diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index 6f39731951b..875309acb02 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c @@ -9,11 +9,10 @@ #include <linux/clksrc-dbx500-prcmu.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/platform_data/clocksource-nomadik-mtu.h> #include <asm/smp_twd.h> -#include <plat/mtu.h> - #include <mach/setup.h> #include <mach/hardware.h> #include <mach/irqs.h> @@ -96,7 +95,7 @@ dt_fail: * */ - nmdk_timer_init(mtu_timer_base); + nmdk_timer_init(mtu_timer_base, IRQ_MTU0); clksrc_dbx500_prcmu_init(prcmu_timer_base); ux500_twd_init(); } diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 145482e7441..78ac65f62e8 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -7,10 +7,10 @@ #include <linux/platform_device.h> #include <linux/usb/musb.h> #include <linux/dma-mapping.h> +#include <linux/platform_data/usb-musb-ux500.h> +#include <linux/platform_data/dma-ste-dma40.h> -#include <plat/ste_dma40.h> #include <mach/hardware.h> -#include <linux/platform_data/usb-musb-ux500.h> #define MUSB_DMA40_RX_CH { \ .mode = STEDMA40_MODE_LOGICAL, \ diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig new file mode 100644 index 00000000000..2ed0b7d95db --- /dev/null +++ b/arch/arm/mach-vt8500/Kconfig @@ -0,0 +1,12 @@ +config ARCH_VT8500 + bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5 + default ARCH_VT8500_SINGLE + select ARCH_HAS_CPUFREQ + select ARCH_REQUIRE_GPIOLIB + select CLKDEV_LOOKUP + select CPU_ARM926T + select GENERIC_CLOCKEVENTS + select GENERIC_GPIO + select HAVE_CLK + help + Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h index 2b2419646e9..6f2b843115d 100644 --- a/arch/arm/mach-vt8500/common.h +++ b/arch/arm/mach-vt8500/common.h @@ -25,4 +25,7 @@ int __init vt8500_irq_init(struct device_node *node, /* defined in drivers/clk/clk-vt8500.c */ void __init vtwm_clk_init(void __iomem *pmc_base); +/* defined in irq.c */ +asmlinkage void vt8500_handle_irq(struct pt_regs *regs); + #endif diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S deleted file mode 100644 index 367d1b55fb9..00000000000 --- a/arch/arm/mach-vt8500/include/mach/entry-macro.S +++ /dev/null @@ -1,26 +0,0 @@ -/* - * arch/arm/mach-vt8500/include/mach/entry-macro.S - * - * Low-level IRQ helper macros for VIA VT8500 - * - * 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. - */ - - .macro get_irqnr_preamble, base, tmp - @ physical 0xd8140000 is virtual 0xf8140000 - mov \base, #0xf8000000 - orr \base, \base, #0x00140000 - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqnr, [\base] - cmp \irqnr, #63 @ may be false positive, check interrupt status - bne 1001f - ldr \irqstat, [\base, #0x84] - ands \irqstat, #0x80000000 - moveq \irqnr, #0 -1001: - .endm - diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/arch/arm/mach-vt8500/include/mach/irqs.h deleted file mode 100644 index a129fd1222f..00000000000 --- a/arch/arm/mach-vt8500/include/mach/irqs.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * arch/arm/mach-vt8500/include/mach/irqs.h - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * 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 - */ - -/* This value is just to make the core happy, never used otherwise */ -#define NR_IRQS 128 diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c index f8f9ab9bc56..b9cf5ce9efb 100644 --- a/arch/arm/mach-vt8500/irq.c +++ b/arch/arm/mach-vt8500/irq.c @@ -36,7 +36,7 @@ #include <linux/of_address.h> #include <asm/irq.h> - +#include <asm/exception.h> #define VT8500_ICPC_IRQ 0x20 #define VT8500_ICPC_FIQ 0x24 @@ -66,30 +66,34 @@ #define VT8500_EDGE ( VT8500_TRIGGER_RISING \ | VT8500_TRIGGER_FALLING) -static int irq_cnt; +/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */ +#define VT8500_INTC_MAX 2 -struct vt8500_irq_priv { - void __iomem *base; +struct vt8500_irq_data { + void __iomem *base; /* IO Memory base address */ + struct irq_domain *domain; /* Domain for this controller */ }; +/* Global variable for accessing io-mem addresses */ +static struct vt8500_irq_data intc[VT8500_INTC_MAX]; +static u32 active_cnt = 0; + static void vt8500_irq_mask(struct irq_data *d) { - struct vt8500_irq_priv *priv = - (struct vt8500_irq_priv *)(d->domain->host_data); + struct vt8500_irq_data *priv = d->domain->host_data; void __iomem *base = priv->base; - u8 edge; + void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4); + u8 edge, dctr; + u32 status; edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE; if (edge) { - void __iomem *stat_reg = base + VT8500_ICIS - + (d->hwirq < 32 ? 0 : 4); - unsigned status = readl(stat_reg); + status = readl(stat_reg); status |= (1 << (d->hwirq & 0x1f)); writel(status, stat_reg); } else { - u8 dctr = readb(base + VT8500_ICDC + d->hwirq); - + dctr = readb(base + VT8500_ICDC + d->hwirq); dctr &= ~VT8500_INT_ENABLE; writeb(dctr, base + VT8500_ICDC + d->hwirq); } @@ -97,8 +101,7 @@ static void vt8500_irq_mask(struct irq_data *d) static void vt8500_irq_unmask(struct irq_data *d) { - struct vt8500_irq_priv *priv = - (struct vt8500_irq_priv *)(d->domain->host_data); + struct vt8500_irq_data *priv = d->domain->host_data; void __iomem *base = priv->base; u8 dctr; @@ -109,8 +112,7 @@ static void vt8500_irq_unmask(struct irq_data *d) static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) { - struct vt8500_irq_priv *priv = - (struct vt8500_irq_priv *)(d->domain->host_data); + struct vt8500_irq_data *priv = d->domain->host_data; void __iomem *base = priv->base; u8 dctr; @@ -148,17 +150,15 @@ static struct irq_chip vt8500_irq_chip = { static void __init vt8500_init_irq_hw(void __iomem *base) { - unsigned int i; + u32 i; /* Enable rotating priority for IRQ */ writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ); writel(0x00, base + VT8500_ICPC_FIQ); - for (i = 0; i < 64; i++) { - /* Disable all interrupts and route them to IRQ */ - writeb(VT8500_INT_DISABLE | ICDC_IRQ, - base + VT8500_ICDC + i); - } + /* Disable all interrupts and route them to IRQ */ + for (i = 0; i < 64; i++) + writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i); } static int vt8500_irq_map(struct irq_domain *h, unsigned int virq, @@ -175,33 +175,67 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { .xlate = irq_domain_xlate_onecell, }; +asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) +{ + u32 stat, i; + int irqnr, virq; + void __iomem *base; + + /* Loop through each active controller */ + for (i=0; i<active_cnt; i++) { + base = intc[i].base; + irqnr = readl_relaxed(base) & 0x3F; + /* + Highest Priority register default = 63, so check that this + is a real interrupt by checking the status register + */ + if (irqnr == 63) { + stat = readl_relaxed(base + VT8500_ICIS + 4); + if (!(stat & BIT(31))) + continue; + } + + virq = irq_find_mapping(intc[i].domain, irqnr); + handle_IRQ(virq, regs); + } +} + int __init vt8500_irq_init(struct device_node *node, struct device_node *parent) { - struct irq_domain *vt8500_irq_domain; - struct vt8500_irq_priv *priv; int irq, i; struct device_node *np = node; - priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL); - priv->base = of_iomap(np, 0); + if (active_cnt == VT8500_INTC_MAX) { + pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n", + __func__); + goto out; + } + + intc[active_cnt].base = of_iomap(np, 0); + intc[active_cnt].domain = irq_domain_add_linear(node, 64, + &vt8500_irq_domain_ops, &intc[active_cnt]); - vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0, - &vt8500_irq_domain_ops, priv); - if (!vt8500_irq_domain) - pr_err("%s: Unable to add wmt irq domain!\n", __func__); + if (!intc[active_cnt].base) { + pr_err("%s: Unable to map IO memory\n", __func__); + goto out; + } + + if (!intc[active_cnt].domain) { + pr_err("%s: Unable to add irq domain!\n", __func__); + goto out; + } - irq_set_default_host(vt8500_irq_domain); + vt8500_init_irq_hw(intc[active_cnt].base); - vt8500_init_irq_hw(priv->base); + pr_info("vt8500-irq: Added interrupt controller\n"); - pr_info("Added IRQ Controller @ %x [virq_base = %d]\n", - (u32)(priv->base), irq_cnt); + active_cnt++; /* check if this is a slaved controller */ if (of_irq_count(np) != 0) { /* check that we have the correct number of interrupts */ if (of_irq_count(np) != 8) { - pr_err("%s: Incorrect IRQ map for slave controller\n", + pr_err("%s: Incorrect IRQ map for slaved controller\n", __func__); return -EINVAL; } @@ -213,9 +247,7 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent) pr_info("vt8500-irq: Enabled slave->parent interrupts\n"); } - - irq_cnt += 64; - +out: return 0; } diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c index a5bd28692b0..3c66d48ea08 100644 --- a/arch/arm/mach-vt8500/vt8500.c +++ b/arch/arm/mach-vt8500/vt8500.c @@ -192,5 +192,6 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") .timer = &vt8500_timer, .init_machine = vt8500_init, .restart = vt8500_restart, + .handle_irq = vt8500_handle_irq, MACHINE_END diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig new file mode 100644 index 00000000000..adb6c0ea0e5 --- /dev/null +++ b/arch/arm/mach-zynq/Kconfig @@ -0,0 +1,13 @@ +config ARCH_ZYNQ + bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7 + select ARM_AMBA + select ARM_GIC + select COMMON_CLK + select CPU_V7 + select GENERIC_CLOCKEVENTS + select ICST + select MIGHT_HAVE_CACHE_L2X0 + select USE_OF + select SPARSE_IRQ + help + Support for Xilinx Zynq ARM Cortex A9 Platform diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 79bf5fb4dad..e16d4bed0f7 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -30,10 +30,10 @@ #include <asm/mach/time.h> #include <asm/mach-types.h> #include <asm/page.h> +#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> -#include <mach/zynq_soc.h> #include "common.h" static struct of_device_id zynq_of_bus_ids[] __initdata = { @@ -68,32 +68,15 @@ static void __init xilinx_irq_init(void) of_irq_init(irq_match); } -/* The minimum devices needed to be mapped before the VM system is up and - * running include the GIC, UART and Timer Counter. - */ - -static struct map_desc io_desc[] __initdata = { - { - .virtual = TTC0_VIRT, - .pfn = __phys_to_pfn(TTC0_PHYS), - .length = TTC0_SIZE, - .type = MT_DEVICE, - }, { - .virtual = SCU_PERIPH_VIRT, - .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), - .length = SCU_PERIPH_SIZE, - .type = MT_DEVICE, - }, - -#ifdef CONFIG_DEBUG_LL - { - .virtual = LL_UART_VADDR, - .pfn = __phys_to_pfn(LL_UART_PADDR), - .length = UART_SIZE, - .type = MT_DEVICE, - }, -#endif +#define SCU_PERIPH_PHYS 0xF8F00000 +#define SCU_PERIPH_SIZE SZ_8K +#define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE) +static struct map_desc scu_desc __initdata = { + .virtual = SCU_PERIPH_VIRT, + .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), + .length = SCU_PERIPH_SIZE, + .type = MT_DEVICE, }; static void __init xilinx_zynq_timer_init(void) @@ -122,7 +105,8 @@ static struct sys_timer xttcpss_sys_timer = { */ static void __init xilinx_map_io(void) { - iotable_init(io_desc, ARRAY_SIZE(io_desc)); + debug_ll_io_init(); + iotable_init(&scu_desc, 1); } static const char *xilinx_dt_match[] = { diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h deleted file mode 100644 index d558d8a94be..00000000000 --- a/arch/arm/mach-zynq/include/mach/hardware.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arch/arm/mach-zynq/include/mach/hardware.h - * - * Copyright (C) 2011 Xilinx - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MACH_HARDWARE_H__ -#define __MACH_HARDWARE_H__ - -#endif diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h deleted file mode 100644 index 5fb04fd3bac..00000000000 --- a/arch/arm/mach-zynq/include/mach/irqs.h +++ /dev/null @@ -1,21 +0,0 @@ -/* arch/arm/mach-zynq/include/mach/irqs.h - * - * Copyright (C) 2011 Xilinx - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MACH_IRQS_H -#define __MACH_IRQS_H - -#define ARCH_NR_GPIOS 118 -#define NR_IRQS (128 + ARCH_NR_GPIOS) - -#endif diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h deleted file mode 100644 index 6c0245e42a5..00000000000 --- a/arch/arm/mach-zynq/include/mach/timex.h +++ /dev/null @@ -1,23 +0,0 @@ -/* arch/arm/mach-zynq/include/mach/timex.h - * - * Copyright (C) 2011 Xilinx - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MACH_TIMEX_H__ -#define __MACH_TIMEX_H__ - -/* the following is needed for the system to build but will be removed - in the future, the value is not important but won't hurt -*/ -#define CLOCK_TICK_RATE (100 * HZ) - -#endif diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h deleted file mode 100644 index 5c47c97156f..00000000000 --- a/arch/arm/mach-zynq/include/mach/uart.h +++ /dev/null @@ -1,25 +0,0 @@ -/* arch/arm/mach-zynq/include/mach/uart.h - * - * Copyright (C) 2011 Xilinx - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MACH_UART_H__ -#define __MACH_UART_H__ - -#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */ -#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */ -#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */ - -#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */ -#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ - -#endif diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h deleted file mode 100644 index af4e8447bfa..00000000000 --- a/arch/arm/mach-zynq/include/mach/uncompress.h +++ /dev/null @@ -1,51 +0,0 @@ -/* arch/arm/mach-zynq/include/mach/uncompress.h - * - * Copyright (C) 2011 Xilinx - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MACH_UNCOMPRESS_H__ -#define __MACH_UNCOMPRESS_H__ - -#include <linux/io.h> -#include <asm/processor.h> -#include <mach/zynq_soc.h> -#include <mach/uart.h> - -void arch_decomp_setup(void) -{ -} - -static inline void flush(void) -{ - /* - * Wait while the FIFO is not empty - */ - while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) & - UART_SR_TXEMPTY)) - cpu_relax(); -} - -#define arch_decomp_wdog() - -static void putc(char ch) -{ - /* - * Wait for room in the FIFO, then write the char into the FIFO - */ - while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) & - UART_SR_TXFULL) - cpu_relax(); - - __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET)); -} - -#endif diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h deleted file mode 100644 index 5ebbd8e6eee..00000000000 --- a/arch/arm/mach-zynq/include/mach/zynq_soc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* arch/arm/mach-zynq/include/mach/zynq_soc.h - * - * Copyright (C) 2011 Xilinx - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MACH_XILINX_SOC_H__ -#define __MACH_XILINX_SOC_H__ - -#include <asm/pgtable.h> - -#define PERIPHERAL_CLOCK_RATE 2500000 - -/* Static peripheral mappings are mapped at the top of the vmalloc region. The - * early uart mapping causes intermediate problems/failure at certain - * addresses, including the very top of the vmalloc region. Map it at an - * address that is known to work. - */ -#define UART0_PHYS 0xE0000000 -#define UART1_PHYS 0xE0001000 -#define UART_SIZE SZ_4K -#define UART_VIRT 0xF0001000 - -#define TTC0_PHYS 0xF8001000 -#define TTC0_SIZE SZ_4K -#define TTC0_VIRT (VMALLOC_END - TTC0_SIZE) - -#define SCU_PERIPH_PHYS 0xF8F00000 -#define SCU_PERIPH_SIZE SZ_8K -#define SCU_PERIPH_VIRT (TTC0_VIRT - SCU_PERIPH_SIZE) - -#if IS_ENABLED(CONFIG_DEBUG_ZYNQ_UART1) -# define LL_UART_PADDR UART1_PHYS -#else -# define LL_UART_PADDR UART0_PHYS -#endif - -#define LL_UART_VADDR UART_VIRT - -/* The following are intended for the devices that are mapped early */ - -#define TTC0_BASE IOMEM(TTC0_VIRT) -#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT) - -#endif diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c index 9662306aa12..de3df283da7 100644 --- a/arch/arm/mach-zynq/timer.c +++ b/arch/arm/mach-zynq/timer.c @@ -29,7 +29,6 @@ #include <linux/slab.h> #include <linux/clk-provider.h> -#include <mach/zynq_soc.h> #include "common.h" /* diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig deleted file mode 100644 index 19f55cae5d7..00000000000 --- a/arch/arm/plat-nomadik/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -# We keep common IP's here for Nomadik and other similar -# familiy of processors from ST-Ericsson. At the moment we have -# just MTU, others to follow soon. - -config PLAT_NOMADIK - bool - depends on ARCH_NOMADIK || ARCH_U8500 - default y - select CLKSRC_MMIO - help - Common platform code for Nomadik and other ST-Ericsson - platforms. - -if PLAT_NOMADIK - -config HAS_MTU - bool - help - Support for Multi Timer Unit. MTU provides access - to multiple interrupt generating programmable - 32-bit free running decrementing counters. - -config NOMADIK_MTU_SCHED_CLOCK - bool - depends on HAS_MTU - help - Use the Multi Timer Unit as the sched_clock. - -endif diff --git a/arch/arm/plat-nomadik/Makefile b/arch/arm/plat-nomadik/Makefile deleted file mode 100644 index 37c7cdd0f8f..00000000000 --- a/arch/arm/plat-nomadik/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# arch/arm/plat-nomadik/Makefile -# Copyright 2009 ST-Ericsson -# Licensed under GPLv2 - -obj-$(CONFIG_HAS_MTU) += timer.o diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h deleted file mode 100644 index 582641f3dc0..00000000000 --- a/arch/arm/plat-nomadik/include/plat/mtu.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __PLAT_MTU_H -#define __PLAT_MTU_H - -void nmdk_timer_init(void __iomem *base); -void nmdk_clkevt_reset(void); -void nmdk_clksrc_reset(void); - -#endif /* __PLAT_MTU_H */ - diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h deleted file mode 100644 index 9ff93b06568..00000000000 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2007-2010 - * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - * License terms: GNU General Public License (GPL) version 2 - */ - - -#ifndef STE_DMA40_H -#define STE_DMA40_H - -#include <linux/dmaengine.h> -#include <linux/scatterlist.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> - -/* - * Maxium size for a single dma descriptor - * Size is limited to 16 bits. - * Size is in the units of addr-widths (1,2,4,8 bytes) - * Larger transfers will be split up to multiple linked desc - */ -#define STEDMA40_MAX_SEG_SIZE 0xFFFF - -/* dev types for memcpy */ -#define STEDMA40_DEV_DST_MEMORY (-1) -#define STEDMA40_DEV_SRC_MEMORY (-1) - -enum stedma40_mode { - STEDMA40_MODE_LOGICAL = 0, - STEDMA40_MODE_PHYSICAL, - STEDMA40_MODE_OPERATION, -}; - -enum stedma40_mode_opt { - STEDMA40_PCHAN_BASIC_MODE = 0, - STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0, - STEDMA40_PCHAN_MODULO_MODE, - STEDMA40_PCHAN_DOUBLE_DST_MODE, - STEDMA40_LCHAN_SRC_PHY_DST_LOG, - STEDMA40_LCHAN_SRC_LOG_DST_PHY, -}; - -#define STEDMA40_ESIZE_8_BIT 0x0 -#define STEDMA40_ESIZE_16_BIT 0x1 -#define STEDMA40_ESIZE_32_BIT 0x2 -#define STEDMA40_ESIZE_64_BIT 0x3 - -/* The value 4 indicates that PEN-reg shall be set to 0 */ -#define STEDMA40_PSIZE_PHY_1 0x4 -#define STEDMA40_PSIZE_PHY_2 0x0 -#define STEDMA40_PSIZE_PHY_4 0x1 -#define STEDMA40_PSIZE_PHY_8 0x2 -#define STEDMA40_PSIZE_PHY_16 0x3 - -/* - * The number of elements differ in logical and - * physical mode - */ -#define STEDMA40_PSIZE_LOG_1 STEDMA40_PSIZE_PHY_2 -#define STEDMA40_PSIZE_LOG_4 STEDMA40_PSIZE_PHY_4 -#define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 -#define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 - -/* Maximum number of possible physical channels */ -#define STEDMA40_MAX_PHYS 32 - -enum stedma40_flow_ctrl { - STEDMA40_NO_FLOW_CTRL, - STEDMA40_FLOW_CTRL, -}; - -enum stedma40_periph_data_width { - STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT, - STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT, - STEDMA40_WORD_WIDTH = STEDMA40_ESIZE_32_BIT, - STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT -}; - -enum stedma40_xfer_dir { - STEDMA40_MEM_TO_MEM = 1, - STEDMA40_MEM_TO_PERIPH, - STEDMA40_PERIPH_TO_MEM, - STEDMA40_PERIPH_TO_PERIPH -}; - - -/** - * struct stedma40_chan_cfg - dst/src channel configuration - * - * @big_endian: true if the src/dst should be read as big endian - * @data_width: Data width of the src/dst hardware - * @p_size: Burst size - * @flow_ctrl: Flow control on/off. - */ -struct stedma40_half_channel_info { - bool big_endian; - enum stedma40_periph_data_width data_width; - int psize; - enum stedma40_flow_ctrl flow_ctrl; -}; - -/** - * struct stedma40_chan_cfg - Structure to be filled by client drivers. - * - * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH - * @high_priority: true if high-priority - * @realtime: true if realtime mode is to be enabled. Only available on DMA40 - * version 3+, i.e DB8500v2+ - * @mode: channel mode: physical, logical, or operation - * @mode_opt: options for the chosen channel mode - * @src_dev_type: Src device type - * @dst_dev_type: Dst device type - * @src_info: Parameters for dst half channel - * @dst_info: Parameters for dst half channel - * @use_fixed_channel: if true, use physical channel specified by phy_channel - * @phy_channel: physical channel to use, only if use_fixed_channel is true - * - * This structure has to be filled by the client drivers. - * It is recommended to do all dma configurations for clients in the machine. - * - */ -struct stedma40_chan_cfg { - enum stedma40_xfer_dir dir; - bool high_priority; - bool realtime; - enum stedma40_mode mode; - enum stedma40_mode_opt mode_opt; - int src_dev_type; - int dst_dev_type; - struct stedma40_half_channel_info src_info; - struct stedma40_half_channel_info dst_info; - - bool use_fixed_channel; - int phy_channel; -}; - -/** - * struct stedma40_platform_data - Configuration struct for the dma device. - * - * @dev_len: length of dev_tx and dev_rx - * @dev_tx: mapping between destination event line and io address - * @dev_rx: mapping between source event line and io address - * @memcpy: list of memcpy event lines - * @memcpy_len: length of memcpy - * @memcpy_conf_phy: default configuration of physical channel memcpy - * @memcpy_conf_log: default configuration of logical channel memcpy - * @disabled_channels: A vector, ending with -1, that marks physical channels - * that are for different reasons not available for the driver. - */ -struct stedma40_platform_data { - u32 dev_len; - const dma_addr_t *dev_tx; - const dma_addr_t *dev_rx; - int *memcpy; - u32 memcpy_len; - struct stedma40_chan_cfg *memcpy_conf_phy; - struct stedma40_chan_cfg *memcpy_conf_log; - int disabled_channels[STEDMA40_MAX_PHYS]; - bool use_esram_lcla; -}; - -#ifdef CONFIG_STE_DMA40 - -/** - * stedma40_filter() - Provides stedma40_chan_cfg to the - * ste_dma40 dma driver via the dmaengine framework. - * does some checking of what's provided. - * - * Never directly called by client. It used by dmaengine. - * @chan: dmaengine handle. - * @data: Must be of type: struct stedma40_chan_cfg and is - * the configuration of the framework. - * - * - */ - -bool stedma40_filter(struct dma_chan *chan, void *data); - -/** - * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave - * (=device) - * - * @chan: dmaengine handle - * @addr: source or destination physicall address. - * @size: bytes to transfer - * @direction: direction of transfer - * @flags: is actually enum dma_ctrl_flags. See dmaengine.h - */ - -static inline struct -dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, - dma_addr_t addr, - unsigned int size, - enum dma_transfer_direction direction, - unsigned long flags) -{ - struct scatterlist sg; - sg_init_table(&sg, 1); - sg.dma_address = addr; - sg.length = size; - - return dmaengine_prep_slave_sg(chan, &sg, 1, direction, flags); -} - -#else -static inline bool stedma40_filter(struct dma_chan *chan, void *data) -{ - return false; -} - -static inline struct -dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, - dma_addr_t addr, - unsigned int size, - enum dma_transfer_direction direction, - unsigned long flags) -{ - return NULL; -} -#endif - -#endif diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c deleted file mode 100644 index 9222e5522a4..00000000000 --- a/arch/arm/plat-nomadik/timer.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * linux/arch/arm/plat-nomadik/timer.c - * - * Copyright (C) 2008 STMicroelectronics - * Copyright (C) 2010 Alessandro Rubini - * Copyright (C) 2010 Linus Walleij for ST-Ericsson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - */ -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/clockchips.h> -#include <linux/clk.h> -#include <linux/jiffies.h> -#include <linux/err.h> -#include <asm/mach/time.h> -#include <asm/sched_clock.h> - -/* - * The MTU device hosts four different counters, with 4 set of - * registers. These are register names. - */ - -#define MTU_IMSC 0x00 /* Interrupt mask set/clear */ -#define MTU_RIS 0x04 /* Raw interrupt status */ -#define MTU_MIS 0x08 /* Masked interrupt status */ -#define MTU_ICR 0x0C /* Interrupt clear register */ - -/* per-timer registers take 0..3 as argument */ -#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */ -#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */ -#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */ -#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */ - -/* bits for the control register */ -#define MTU_CRn_ENA 0x80 -#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */ -#define MTU_CRn_PRESCALE_MASK 0x0c -#define MTU_CRn_PRESCALE_1 0x00 -#define MTU_CRn_PRESCALE_16 0x04 -#define MTU_CRn_PRESCALE_256 0x08 -#define MTU_CRn_32BITS 0x02 -#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/ - -/* Other registers are usual amba/primecell registers, currently not used */ -#define MTU_ITCR 0xff0 -#define MTU_ITOP 0xff4 - -#define MTU_PERIPH_ID0 0xfe0 -#define MTU_PERIPH_ID1 0xfe4 -#define MTU_PERIPH_ID2 0xfe8 -#define MTU_PERIPH_ID3 0xfeC - -#define MTU_PCELL0 0xff0 -#define MTU_PCELL1 0xff4 -#define MTU_PCELL2 0xff8 -#define MTU_PCELL3 0xffC - -static void __iomem *mtu_base; -static bool clkevt_periodic; -static u32 clk_prescale; -static u32 nmdk_cycle; /* write-once */ - -#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK -/* - * Override the global weak sched_clock symbol with this - * local implementation which uses the clocksource to get some - * better resolution when scheduling the kernel. - */ -static u32 notrace nomadik_read_sched_clock(void) -{ - if (unlikely(!mtu_base)) - return 0; - - return -readl(mtu_base + MTU_VAL(0)); -} -#endif - -/* Clockevent device: use one-shot mode */ -static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev) -{ - writel(1 << 1, mtu_base + MTU_IMSC); - writel(evt, mtu_base + MTU_LR(1)); - /* Load highest value, enable device, enable interrupts */ - writel(MTU_CRn_ONESHOT | clk_prescale | - MTU_CRn_32BITS | MTU_CRn_ENA, - mtu_base + MTU_CR(1)); - - return 0; -} - -void nmdk_clkevt_reset(void) -{ - if (clkevt_periodic) { - /* Timer: configure load and background-load, and fire it up */ - writel(nmdk_cycle, mtu_base + MTU_LR(1)); - writel(nmdk_cycle, mtu_base + MTU_BGLR(1)); - - writel(MTU_CRn_PERIODIC | clk_prescale | - MTU_CRn_32BITS | MTU_CRn_ENA, - mtu_base + MTU_CR(1)); - writel(1 << 1, mtu_base + MTU_IMSC); - } else { - /* Generate an interrupt to start the clockevent again */ - (void) nmdk_clkevt_next(nmdk_cycle, NULL); - } -} - -static void nmdk_clkevt_mode(enum clock_event_mode mode, - struct clock_event_device *dev) -{ - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - clkevt_periodic = true; - nmdk_clkevt_reset(); - break; - case CLOCK_EVT_MODE_ONESHOT: - clkevt_periodic = false; - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - writel(0, mtu_base + MTU_IMSC); - /* disable timer */ - writel(0, mtu_base + MTU_CR(1)); - /* load some high default value */ - writel(0xffffffff, mtu_base + MTU_LR(1)); - break; - case CLOCK_EVT_MODE_RESUME: - break; - } -} - -static struct clock_event_device nmdk_clkevt = { - .name = "mtu_1", - .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .rating = 200, - .set_mode = nmdk_clkevt_mode, - .set_next_event = nmdk_clkevt_next, -}; - -/* - * IRQ Handler for timer 1 of the MTU block. - */ -static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evdev = dev_id; - - writel(1 << 1, mtu_base + MTU_ICR); /* Interrupt clear reg */ - evdev->event_handler(evdev); - return IRQ_HANDLED; -} - -static struct irqaction nmdk_timer_irq = { - .name = "Nomadik Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER, - .handler = nmdk_timer_interrupt, - .dev_id = &nmdk_clkevt, -}; - -void nmdk_clksrc_reset(void) -{ - /* Disable */ - writel(0, mtu_base + MTU_CR(0)); - - /* ClockSource: configure load and background-load, and fire it up */ - writel(nmdk_cycle, mtu_base + MTU_LR(0)); - writel(nmdk_cycle, mtu_base + MTU_BGLR(0)); - - writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA, - mtu_base + MTU_CR(0)); -} - -void __init nmdk_timer_init(void __iomem *base) -{ - unsigned long rate; - struct clk *clk0; - - mtu_base = base; - clk0 = clk_get_sys("mtu0", NULL); - BUG_ON(IS_ERR(clk0)); - BUG_ON(clk_prepare(clk0) < 0); - BUG_ON(clk_enable(clk0) < 0); - - /* - * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz - * for ux500. - * Use a divide-by-16 counter if the tick rate is more than 32MHz. - * At 32 MHz, the timer (with 32 bit counter) can be programmed - * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer - * with 16 gives too low timer resolution. - */ - rate = clk_get_rate(clk0); - if (rate > 32000000) { - rate /= 16; - clk_prescale = MTU_CRn_PRESCALE_16; - } else { - clk_prescale = MTU_CRn_PRESCALE_1; - } - - nmdk_cycle = (rate + HZ/2) / HZ; - - - /* Timer 0 is the free running clocksource */ - nmdk_clksrc_reset(); - - if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", - rate, 200, 32, clocksource_mmio_readl_down)) - pr_err("timer: failed to initialize clock source %s\n", - "mtu_0"); - -#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK - setup_sched_clock(nomadik_read_sched_clock, 32, rate); -#endif - - /* Timer 1 is used for events, register irq and clockevents */ - setup_irq(IRQ_MTU0, &nmdk_timer_irq); - nmdk_clkevt.cpumask = cpumask_of(0); - clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); -} |