From e53b7d87cc375fbe428551651094fb676764aae3 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 3 Jan 2012 12:05:47 +0000 Subject: ARM: tegra: Support Tegra30 in decompressor UART setup On Tegra20, the UART clock runs at 216MHz, whereas on Tegra30 it runs at 408MHz. Modify arch_decomp_setup() to detect Tegra20-vs-Tegra30 at run- time, and program the correct divisor. This makes uncompressor messages work correctly on Tegra30. This also fixes early printk, assuming zImage is used and this setup code runs. v2: Use CHIPID register to differentiate between chips, rather than a GIC register. This should be more future-proof. Volatile is required to prevent the compiler transforming the 32-bit apb_misc register read into an 8-bit read of address 1 higher, since the HW only supports 32- bit accesses, and will hang on an 8-bit access. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/include/mach/uncompress.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-tegra/include/mach') diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 4e8323770c7..39bd5e5a1af 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -45,15 +45,23 @@ static inline void flush(void) static inline void arch_decomp_setup(void) { + volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; + u32 chip, div; volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; int shift = 2; if (uart == NULL) return; + chip = (apb_misc[0x804 / 4] >> 8) & 0xff; + if (chip == 0x20) + div = 0x0075; + else + div = 0x00dd; + uart[UART_LCR << shift] |= UART_LCR_DLAB; - uart[UART_DLL << shift] = 0x75; - uart[UART_DLM << shift] = 0x0; + uart[UART_DLL << shift] = div & 0xff; + uart[UART_DLM << shift] = div >> 8; uart[UART_LCR << shift] = 3; } -- cgit v1.2.3-70-g09d2 From 229c7b22a24b9996e3a3eb1a2748e255e16bc323 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 6 Jan 2012 10:43:19 +0000 Subject: ARM: tegra: Introduce define DEBUG_UART_SHIFT This removes the need for the variable "shift" in all functions in uncompress.h. Signed-off-by: Doug Anderson [swarren: Extracted from a larger patch by Doug] Signed-off-by: Stephen Warren Tested-by: Doug Anderson Acked-by: Doug Anderson Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/include/mach/uncompress.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'arch/arm/mach-tegra/include/mach') diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 39bd5e5a1af..9797279e94d 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -2,10 +2,12 @@ * arch/arm/mach-tegra/include/mach/uncompress.h * * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2011 Google, Inc. * * Author: * Colin Cross * Erik Gilling + * Doug Anderson * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -26,17 +28,18 @@ #include +#define DEBUG_UART_SHIFT 2 + static void putc(int c) { volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; - int shift = 2; if (uart == NULL) return; - while (!(uart[UART_LSR << shift] & UART_LSR_THRE)) + while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE)) barrier(); - uart[UART_TX << shift] = c; + uart[UART_TX << DEBUG_UART_SHIFT] = c; } static inline void flush(void) @@ -48,7 +51,6 @@ static inline void arch_decomp_setup(void) volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; u32 chip, div; volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; - int shift = 2; if (uart == NULL) return; @@ -59,10 +61,10 @@ static inline void arch_decomp_setup(void) else div = 0x00dd; - uart[UART_LCR << shift] |= UART_LCR_DLAB; - uart[UART_DLL << shift] = div & 0xff; - uart[UART_DLM << shift] = div >> 8; - uart[UART_LCR << shift] = 3; + uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB; + uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff; + uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8; + uart[UART_LCR << DEBUG_UART_SHIFT] = 3; } static inline void arch_decomp_wdog(void) -- cgit v1.2.3-70-g09d2 From 31bac1375bda9787f18b2f60e0e1ca62258ea09c Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 6 Jan 2012 10:43:20 +0000 Subject: ARM: tegra: uncompress.h: Store UART address in a variable This will allow a future change to auto-detect which UART to use. Signed-off-by: Doug Anderson [swarren: Extracted from a larger patch by Doug] Signed-off-by: Stephen Warren Tested-by: Doug Anderson Acked-by: Doug Anderson Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/include/mach/uncompress.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-tegra/include/mach') diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 9797279e94d..bb3fd359f9f 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -30,10 +30,10 @@ #define DEBUG_UART_SHIFT 2 +volatile u8 *uart; + static void putc(int c) { - volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; - if (uart == NULL) return; @@ -50,8 +50,8 @@ static inline void arch_decomp_setup(void) { volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; u32 chip, div; - volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; + uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; if (uart == NULL) return; -- cgit v1.2.3-70-g09d2 From fe2639892cb618d5c42ea4570feea8dc497d0487 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Jan 2012 10:43:21 +0000 Subject: ARM: tegra: uncompress.h: Choose a UART at runtime With this change we automatically detect which UART to use for for printing during decompression. The detection involves coordination with the bootloader: it's expected that the bootloader will leave a 'D' (for [D]ebug) in the UART scratchpad register for whichever UART we should use for debugging. If we don't find any such UART, we fall back to the UART that was specified during config time: CONFIG_TEGRA_DEBUG_UART_XXX. As a side effect of this change, uncompress debug messages will work if you've specified CONFIG_TEGRA_DEBUG_UART_NONE, provided the bootloader obeys the protocol. This change is in line with what is documented in Documentation/arm/Booting. Other approaches considered: * Hardcode based on machine ID (as many other ARM boards do). OK, but nice to not have yet another place to add per-board code. Better to have bootloader parse device tree and pass us this info. * Check for TXE bit (like SA1110). Nice (and doesn't require a bootloader change), but a little less explicit. Also: if bootloader (for some reason) uses another UART, it needs to remember to turn it off before jumping to the kernel or we may print to it. NOTE: adapting this patch to check TXE too would be easy if desired. Signed-off-by: Doug Anderson [swarren: Added clock/reset condition checks] Signed-off-by: Stephen Warren Tested-by: Doug Anderson Acked-by: Doug Anderson Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/include/mach/uncompress.h | 75 ++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-tegra/include/mach') diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index bb3fd359f9f..6c087b6974b 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -3,11 +3,13 @@ * * Copyright (C) 2010 Google, Inc. * Copyright (C) 2011 Google, Inc. + * Copyright (C) 2011 NVIDIA CORPORATION. All Rights Reserved. * * Author: * Colin Cross * Erik Gilling * Doug Anderson + * Stephen Warren * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -23,6 +25,7 @@ #ifndef __MACH_TEGRA_UNCOMPRESS_H #define __MACH_TEGRA_UNCOMPRESS_H +#include #include #include @@ -46,12 +49,82 @@ static inline void flush(void) { } +/* + * 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) { + static const struct { + u32 base; + u32 reset_reg; + u32 clock_reg; + u32 bit; + } uarts[] = { + { + TEGRA_UARTA_BASE, + TEGRA_CLK_RESET_BASE + 0x04, + TEGRA_CLK_RESET_BASE + 0x10, + 6, + }, + { + TEGRA_UARTB_BASE, + TEGRA_CLK_RESET_BASE + 0x04, + TEGRA_CLK_RESET_BASE + 0x10, + 7, + }, + { + TEGRA_UARTC_BASE, + TEGRA_CLK_RESET_BASE + 0x08, + TEGRA_CLK_RESET_BASE + 0x14, + 23, + }, + { + TEGRA_UARTD_BASE, + TEGRA_CLK_RESET_BASE + 0x0c, + TEGRA_CLK_RESET_BASE + 0x18, + 1, + }, + { + TEGRA_UARTE_BASE, + TEGRA_CLK_RESET_BASE + 0x0c, + TEGRA_CLK_RESET_BASE + 0x18, + 2, + }, + }; + int i; volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; u32 chip, div; - uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; + /* + * 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 (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit)) + continue; + + if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit))) + continue; + + uart = (volatile u8 *)uarts[i].base; + if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D') + continue; + + break; + } + if (i == ARRAY_SIZE(uarts)) + uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; if (uart == NULL) return; -- cgit v1.2.3-70-g09d2 From 6d7d7b3ecd20a0fbcebdbdffe7b25d94cfa37d93 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Jan 2012 10:43:22 +0000 Subject: ARM: tegra: Pass uncompress.h UART selection to DEBUG_LL uncompress.h now saves the selected UART's physical address in Tegra's IRAM, along with a cookie to indicate validity. The first time it's run, macro addruart in debug-macro.S looks for this cookie, and if it's present, uses the UART address stored there. If not, the static value TEGRA_DEBUG_UART_BASE is used, as was previous behaviour. The static behaviour will thus be used when not booting using a zImage. This work was inspired by work by Doug Anderson ; see http://lkml.org/lkml/2011/9/26/284. However, this patch relies on the data passing describe above, rather than duplicating the UART selection logic in debug-macro.S; the latest selection logic is more complex due to the need to check reset/clock bits too. Signed-off-by: Stephen Warren Tested-by: Doug Anderson Acked-by: Doug Anderson Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/common.c | 17 +++++ arch/arm/mach-tegra/include/mach/debug-macro.S | 88 ++++++++++++++++++++++---- arch/arm/mach-tegra/include/mach/irammap.h | 35 ++++++++++ arch/arm/mach-tegra/include/mach/uncompress.h | 15 ++++- 4 files changed, 143 insertions(+), 12 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/irammap.h (limited to 'arch/arm/mach-tegra/include/mach') diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index a2eb90169ae..76210e5df56 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -33,6 +33,23 @@ #include "clock.h" #include "fuse.h" +/* + * Storage for debug-macro.S's state. + * + * This must be in .data not .bss so that it gets initialized each time the + * 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] = { + /* Debug UART initialization required */ + 1, + /* Debug UART physical address */ + (u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET), + /* Debug UART virtual address */ + (u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET), +}; + #ifdef CONFIG_OF static const struct of_device_id tegra_dt_irq_match[] __initconst = { { .compatible = "arm,cortex-a9-gic", .data = gic_of_init }, diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S index 619abc63aee..90069abd37b 100644 --- a/arch/arm/mach-tegra/include/mach/debug-macro.S +++ b/arch/arm/mach-tegra/include/mach/debug-macro.S @@ -1,11 +1,17 @@ /* * arch/arm/mach-tegra/include/mach/debug-macro.S * - * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010,2011 Google, Inc. + * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved. * * Author: * Colin Cross * Erik Gilling + * Doug Anderson + * Stephen Warren + * + * 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 @@ -18,18 +24,78 @@ * */ +#include + #include #include +#include + + .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 , 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 addruart, rp, rv, tmp - ldr \rp, =IO_APB_PHYS @ physical - ldr \rv, =IO_APB_VIRT @ virtual - orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF) - orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00) - orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF) - orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00) - .endm + .macro senduart, rd, rx + tst \rx, #0x0000ff00 + strneb \rd, [\rx, #UART_TX << UART_SHIFT] +1001: + .endm -#define UART_SHIFT 2 -#include + .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/irammap.h b/arch/arm/mach-tegra/include/mach/irammap.h new file mode 100644 index 00000000000..0cbe6326185 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/irammap.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +#ifndef __MACH_TEGRA_IRAMMAP_H +#define __MACH_TEGRA_IRAMMAP_H + +#include + +/* The first 1K of IRAM is permanently reserved for the CPU reset handler */ +#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/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 6c087b6974b..b066ba0ee3c 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -3,7 +3,7 @@ * * Copyright (C) 2010 Google, Inc. * Copyright (C) 2011 Google, Inc. - * Copyright (C) 2011 NVIDIA CORPORATION. All Rights Reserved. + * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved. * * Author: * Colin Cross @@ -30,6 +30,7 @@ #include #include +#include #define DEBUG_UART_SHIFT 2 @@ -49,6 +50,17 @@ 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; +} + /* * Setup before decompression. This is where we do UART selection for * earlyprintk and init the uart_base register. @@ -125,6 +137,7 @@ static inline void arch_decomp_setup(void) } if (i == ARRAY_SIZE(uarts)) uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; + save_uart_address(); if (uart == NULL) return; -- cgit v1.2.3-70-g09d2 From 6f74dc9bc8de41f3de474a7269a70921e773c40f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 4 Jan 2012 08:39:37 +0000 Subject: gpio: tegra: Dynamically allocate IRQ base, and support DT Enhance the driver to dynamically allocate the base IRQ number, and create an IRQ domain for itself. The use of an IRQ domain ensures that any device tree node interrupts properties are correctly parsed. Describe interrupt-related properties in the device tree binding docs, and the contents of "child" node interrupts property. Update tegra*.dtsi to specify the required interrupt-related properties. Finally, remove the definition of TEGRA_GPIO_TO_IRQ; this macro no longer gives correct results since the IRQ numbers for GPIOs are dynamically allocated. Signed-off-by: Stephen Warren Acked-by: Grant Likely Signed-off-by: Olof Johansson --- .../devicetree/bindings/gpio/gpio_nvidia.txt | 12 +++++++++++ arch/arm/boot/dts/tegra20.dtsi | 2 ++ arch/arm/boot/dts/tegra30.dtsi | 2 ++ arch/arm/mach-tegra/include/mach/gpio-tegra.h | 2 -- drivers/gpio/gpio-tegra.c | 25 ++++++++++++++++------ 5 files changed, 34 insertions(+), 9 deletions(-) (limited to 'arch/arm/mach-tegra/include/mach') diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt index 50b363c5b88..d114e1997d3 100644 --- a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt +++ b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt @@ -8,6 +8,16 @@ Required properties: second cell is used to specify optional parameters: - bit 0 specifies polarity (0 for normal, 1 for inverted) - gpio-controller : Marks the device node as a GPIO controller. +- #interrupt-cells : Should be 2. + The first cell is the GPIO number. + The second cell is used to specify flags: + bits[3:0] trigger type and level flags: + 1 = low-to-high edge triggered. + 2 = high-to-low edge triggered. + 4 = active high level-sensitive. + 8 = active low level-sensitive. + Valid combinations are 1, 2, 3, 4, 8. +- interrupt-controller : Marks the device node as an interrupt controller. Example: @@ -23,4 +33,6 @@ gpio: gpio@6000d000 { 0 89 0x04 >; #gpio-cells = <2>; gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; }; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 3195ad5562d..ec1f0101c79 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -101,6 +101,8 @@ 0 89 0x04 >; #gpio-cells = <2>; gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; }; pinmux: pinmux@70000000 { diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index fd25e8e9ffd..ac4b75cb26c 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -107,6 +107,8 @@ 0 125 0x04 >; #gpio-cells = <2>; gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; }; serial@70006000 { diff --git a/arch/arm/mach-tegra/include/mach/gpio-tegra.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h index 87d37fdf508..6140820555e 100644 --- a/arch/arm/mach-tegra/include/mach/gpio-tegra.h +++ b/arch/arm/mach-tegra/include/mach/gpio-tegra.h @@ -25,8 +25,6 @@ #define TEGRA_NR_GPIOS INT_GPIO_NR -#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) - struct tegra_gpio_table { int gpio; /* GPIO number */ bool enable; /* Enable for GPIO at init? */ diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index bdc29379159..bc923c7acce 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -74,7 +75,7 @@ struct tegra_gpio_bank { #endif }; - +static struct irq_domain irq_domain; static void __iomem *regs; static struct tegra_gpio_bank tegra_gpio_banks[7]; @@ -139,7 +140,7 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - return TEGRA_GPIO_TO_IRQ(offset); + return irq_domain_to_irq(&irq_domain, offset); } static struct gpio_chip tegra_gpio_chip = { @@ -155,28 +156,28 @@ static struct gpio_chip tegra_gpio_chip = { static void tegra_gpio_irq_ack(struct irq_data *d) { - int gpio = d->irq - INT_GPIO_BASE; + int gpio = d->hwirq; tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); } static void tegra_gpio_irq_mask(struct irq_data *d) { - int gpio = d->irq - INT_GPIO_BASE; + int gpio = d->hwirq; tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0); } static void tegra_gpio_irq_unmask(struct irq_data *d) { - int gpio = d->irq - INT_GPIO_BASE; + int gpio = d->hwirq; tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1); } static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) { - int gpio = d->irq - INT_GPIO_BASE; + int gpio = d->hwirq; struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); int port = GPIO_PORT(gpio); int lvl_type; @@ -343,6 +344,16 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) int i; int j; + irq_domain.irq_base = irq_alloc_descs(-1, 0, TEGRA_NR_GPIOS, 0); + if (irq_domain.irq_base < 0) { + dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n"); + return -ENODEV; + } + irq_domain.nr_irq = TEGRA_NR_GPIOS; + irq_domain.ops = &irq_domain_simple_ops; + irq_domain.of_node = pdev->dev.of_node; + irq_domain_add(&irq_domain); + for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, i); if (!res) { @@ -381,7 +392,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) gpiochip_add(&tegra_gpio_chip); for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) { - int irq = TEGRA_GPIO_TO_IRQ(gpio); + int irq = irq_domain_to_irq(&irq_domain, gpio); /* No validity check; all Tegra GPIOs are valid IRQs */ bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; -- cgit v1.2.3-70-g09d2