aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-03-04 21:00:27 +0000
committerArnd Bergmann <arnd@arndb.de>2012-03-04 21:03:30 +0000
commit7cb7f82611dddb4b471d42d0fad645dd0dc3f360 (patch)
tree61cb56ea1a885c96e6cb78fcd12e6abddd77e27c /arch
parent7169ff4a0942adf524f25713eaed30599d438926 (diff)
parente77a6b313fdfe4faa8f9a8edf919c7eb8d095fb5 (diff)
Merge tag 'tegra-soc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra into tegra/soc-drivers
Tegra SoC driver support. Some device tree conversions, some new drivers. and a fix for an issue introduced in Grant Likely's irq_domain conversion in his tree. Because of that, this branch depends on his branch to build (but not to merge): git://git.secretlab.ca/git/linux-2.6.git irqdomain/next * tag 'tegra-soc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra: (34 commits) ARM: tegra: uncompress.h: Don't depend on kernel headers gpio: tegra: Fix build issue due to irq_domain rework. ARM: tegra: Remove duplicate PMU interrupt inversion code ARM: tegra: Add a simple PMC driver ARM: tegra: dma: not required to move requestor when stopping. ARM: tegra: Fix EMC pdata initialization from registers gpio: tegra: Parameterize the number of banks gpio: tegra: Dynamically allocate IRQ base, and support DT ARM: tegra: Remove use of TEGRA_GPIO_TO_IRQ ARM: tegra: Pass uncompress.h UART selection to DEBUG_LL ARM: tegra: uncompress.h: Choose a UART at runtime ARM: tegra: uncompress.h: Store UART address in a variable ARM: tegra: Introduce define DEBUG_UART_SHIFT ARM: tegra: Support Tegra30 in decompressor UART setup ARM: tegra: Pause DMA when reading transfer count ARM: tegra: emc: device tree support ARM: tegra: emc: convert tegra2_emc to a platform driver ARM: tegra: fuse: add bct strapping reading ARM: tegra: fuse: add functions to access chip revision ARM: tegra: fuse: use apbio dma for register access ... Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/boot/dts/tegra-harmony.dts45
-rw-r--r--arch/arm/boot/dts/tegra-paz00.dts30
-rw-r--r--arch/arm/boot/dts/tegra-seaboard.dts78
-rw-r--r--arch/arm/boot/dts/tegra-trimslice.dts12
-rw-r--r--arch/arm/boot/dts/tegra-ventana.dts42
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi43
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi53
-rw-r--r--arch/arm/mach-tegra/Makefile3
-rw-r--r--arch/arm/mach-tegra/apbio.c145
-rw-r--r--arch/arm/mach-tegra/apbio.h39
-rw-r--r--arch/arm/mach-tegra/board-harmony-power.c15
-rw-r--r--arch/arm/mach-tegra/board-harmony.c2
-rw-r--r--arch/arm/mach-tegra/board-seaboard.c5
-rw-r--r--arch/arm/mach-tegra/common.c20
-rw-r--r--arch/arm/mach-tegra/dma.c128
-rw-r--r--arch/arm/mach-tegra/fuse.c107
-rw-r--r--arch/arm/mach-tegra/fuse.h34
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S88
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio-tegra.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/irammap.h35
-rw-r--r--arch/arm/mach-tegra/include/mach/uncompress.h120
-rw-r--r--arch/arm/mach-tegra/pmc.c76
-rw-r--r--arch/arm/mach-tegra/pmc.h23
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c2
-rw-r--r--arch/arm/mach-tegra/tegra2_emc.c224
-rw-r--r--arch/arm/mach-tegra/tegra2_emc.h11
26 files changed, 1204 insertions, 178 deletions
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
index 80afa1b70b8..6e8447dc020 100644
--- a/arch/arm/boot/dts/tegra-harmony.dts
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -10,19 +10,25 @@
reg = < 0x00000000 0x40000000 >;
};
+ pmc@7000f400 {
+ nvidia,invert-interrupt;
+ };
+
i2c@7000c000 {
clock-frequency = <400000>;
- codec: wm8903@1a {
+ wm8903: wm8903@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
- interrupts = < 347 >;
+ interrupt-parent = <&gpio>;
+ interrupts = < 187 0x04 >;
gpio-controller;
#gpio-cells = <2>;
- /* 0x8000 = Not configured */
- gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
+ micdet-cfg = <0>;
+ micdet-delay = <100>;
+ gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
};
};
@@ -38,13 +44,32 @@
clock-frequency = <400000>;
};
- sound {
- compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903";
+ i2s@70002a00 {
+ status = "disable";
+ };
- spkr-en-gpios = <&codec 2 0>;
- hp-det-gpios = <&gpio 178 0>;
- int-mic-en-gpios = <&gpio 184 0>;
- ext-mic-en-gpios = <&gpio 185 0>;
+ sound {
+ compatible = "nvidia,tegra-audio-wm8903-harmony",
+ "nvidia,tegra-audio-wm8903";
+ nvidia,model = "NVIDIA Tegra Harmony";
+
+ nvidia,audio-routing =
+ "Headphone Jack", "HPOUTR",
+ "Headphone Jack", "HPOUTL",
+ "Int Spk", "ROP",
+ "Int Spk", "RON",
+ "Int Spk", "LOP",
+ "Int Spk", "LON",
+ "Mic Jack", "MICBIAS",
+ "IN1L", "Mic Jack";
+
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&wm8903>;
+
+ nvidia,spkr-en-gpios = <&wm8903 2 0>;
+ nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+ nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
+ nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
};
serial@70006000 {
diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts
index 825d2957da0..e4b552b46fe 100644
--- a/arch/arm/boot/dts/tegra-paz00.dts
+++ b/arch/arm/boot/dts/tegra-paz00.dts
@@ -12,6 +12,13 @@
i2c@7000c000 {
clock-frequency = <400000>;
+
+ alc5632: alc5632@1e {
+ compatible = "realtek,alc5632";
+ reg = <0x1e>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
i2c@7000c400 {
@@ -37,6 +44,29 @@
clock-frequency = <400000>;
};
+ i2s@70002a00 {
+ status = "disable";
+ };
+
+ sound {
+ compatible = "nvidia,tegra-audio-alc5632-paz00",
+ "nvidia,tegra-audio-alc5632";
+
+ nvidia,model = "Compal PAZ00";
+
+ nvidia,audio-routing =
+ "Int Spk", "SPKOUT",
+ "Int Spk", "SPKOUTN",
+ "Headset Mic", "MICBIAS1",
+ "MIC1", "Headset Mic",
+ "Headset Stereophone", "HPR",
+ "Headset Stereophone", "HPL";
+
+ nvidia,audio-codec = <&alc5632>;
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+ };
+
serial@70006000 {
clock-frequency = <216000000>;
};
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
index b55a02e34ba..876d5c92ce3 100644
--- a/arch/arm/boot/dts/tegra-seaboard.dts
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -13,6 +13,20 @@
i2c@7000c000 {
clock-frequency = <400000>;
+
+ wm8903: wm8903@1a {
+ compatible = "wlf,wm8903";
+ reg = <0x1a>;
+ interrupt-parent = <&gpio>;
+ interrupts = < 187 0x04 >;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ micdet-cfg = <0>;
+ micdet-delay = <100>;
+ gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
+ };
};
i2c@7000c400 {
@@ -32,6 +46,32 @@
};
};
+ i2s@70002a00 {
+ status = "disable";
+ };
+
+ sound {
+ compatible = "nvidia,tegra-audio-wm8903-seaboard",
+ "nvidia,tegra-audio-wm8903";
+ nvidia,model = "NVIDIA Tegra Seaboard";
+
+ nvidia,audio-routing =
+ "Headphone Jack", "HPOUTR",
+ "Headphone Jack", "HPOUTL",
+ "Int Spk", "ROP",
+ "Int Spk", "RON",
+ "Int Spk", "LOP",
+ "Int Spk", "LON",
+ "Mic Jack", "MICBIAS",
+ "IN1R", "Mic Jack";
+
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&wm8903>;
+
+ nvidia,spkr-en-gpios = <&wm8903 2 0>;
+ nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */
+ };
+
serial@70006000 {
status = "disable";
};
@@ -93,4 +133,42 @@
gpio-key,wakeup;
};
};
+
+ emc@7000f400 {
+ emc-table@190000 {
+ reg = < 190000 >;
+ compatible = "nvidia,tegra20-emc-table";
+ clock-frequency = < 190000 >;
+ nvidia,emc-registers = < 0x0000000c 0x00000026
+ 0x00000009 0x00000003 0x00000004 0x00000004
+ 0x00000002 0x0000000c 0x00000003 0x00000003
+ 0x00000002 0x00000001 0x00000004 0x00000005
+ 0x00000004 0x00000009 0x0000000d 0x0000059f
+ 0x00000000 0x00000003 0x00000003 0x00000003
+ 0x00000003 0x00000001 0x0000000b 0x000000c8
+ 0x00000003 0x00000007 0x00000004 0x0000000f
+ 0x00000002 0x00000000 0x00000000 0x00000002
+ 0x00000000 0x00000000 0x00000083 0xa06204ae
+ 0x007dc010 0x00000000 0x00000000 0x00000000
+ 0x00000000 0x00000000 0x00000000 0x00000000 >;
+ };
+
+ emc-table@380000 {
+ reg = < 380000 >;
+ compatible = "nvidia,tegra20-emc-table";
+ clock-frequency = < 380000 >;
+ nvidia,emc-registers = < 0x00000017 0x0000004b
+ 0x00000012 0x00000006 0x00000004 0x00000005
+ 0x00000003 0x0000000c 0x00000006 0x00000006
+ 0x00000003 0x00000001 0x00000004 0x00000005
+ 0x00000004 0x00000009 0x0000000d 0x00000b5f
+ 0x00000000 0x00000003 0x00000003 0x00000006
+ 0x00000006 0x00000001 0x00000011 0x000000c8
+ 0x00000003 0x0000000e 0x00000007 0x0000000f
+ 0x00000002 0x00000000 0x00000000 0x00000002
+ 0x00000000 0x00000000 0x00000083 0xe044048b
+ 0x007d8010 0x00000000 0x00000000 0x00000000
+ 0x00000000 0x00000000 0x00000000 0x00000000 >;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts
index 3b3ee7db99f..252476867b5 100644
--- a/arch/arm/boot/dts/tegra-trimslice.dts
+++ b/arch/arm/boot/dts/tegra-trimslice.dts
@@ -26,6 +26,18 @@
status = "disable";
};
+ i2s@70002800 {
+ status = "disable";
+ };
+
+ i2s@70002a00 {
+ status = "disable";
+ };
+
+ das@70000c00 {
+ status = "disable";
+ };
+
serial@70006000 {
clock-frequency = < 216000000 >;
};
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
index c7d3b87f29d..2dcff8728e9 100644
--- a/arch/arm/boot/dts/tegra-ventana.dts
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -12,6 +12,20 @@
i2c@7000c000 {
clock-frequency = <400000>;
+
+ wm8903: wm8903@1a {
+ compatible = "wlf,wm8903";
+ reg = <0x1a>;
+ interrupt-parent = <&gpio>;
+ interrupts = < 187 0x04 >;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ micdet-cfg = <0>;
+ micdet-delay = <100>;
+ gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
+ };
};
i2c@7000c400 {
@@ -26,6 +40,34 @@
clock-frequency = <400000>;
};
+ i2s@70002a00 {
+ status = "disable";
+ };
+
+ sound {
+ compatible = "nvidia,tegra-audio-wm8903-ventana",
+ "nvidia,tegra-audio-wm8903";
+ nvidia,model = "NVIDIA Tegra Ventana";
+
+ nvidia,audio-routing =
+ "Headphone Jack", "HPOUTR",
+ "Headphone Jack", "HPOUTL",
+ "Int Spk", "ROP",
+ "Int Spk", "RON",
+ "Int Spk", "LOP",
+ "Int Spk", "LON",
+ "Mic Jack", "MICBIAS",
+ "IN1L", "Mic Jack";
+
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&wm8903>;
+
+ nvidia,spkr-en-gpios = <&wm8903 2 0>;
+ nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+ nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
+ nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+ };
+
serial@70006000 {
status = "disable";
};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 3da7afd4532..ec1f0101c79 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -4,6 +4,11 @@
compatible = "nvidia,tegra20";
interrupt-parent = <&intc>;
+ pmc@7000f400 {
+ compatible = "nvidia,tegra20-pmc";
+ reg = <0x7000e400 0x400>;
+ };
+
intc: interrupt-controller@50041000 {
compatible = "arm,cortex-a9-gic";
interrupt-controller;
@@ -12,6 +17,27 @@
< 0x50040100 0x0100 >;
};
+ apbdma: dma@6000a000 {
+ compatible = "nvidia,tegra20-apbdma";
+ reg = <0x6000a000 0x1200>;
+ interrupts = < 0 104 0x04
+ 0 105 0x04
+ 0 106 0x04
+ 0 107 0x04
+ 0 108 0x04
+ 0 109 0x04
+ 0 110 0x04
+ 0 111 0x04
+ 0 112 0x04
+ 0 113 0x04
+ 0 114 0x04
+ 0 115 0x04
+ 0 116 0x04
+ 0 117 0x04
+ 0 118 0x04
+ 0 119 0x04 >;
+ };
+
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -44,18 +70,18 @@
interrupts = < 0 53 0x04 >;
};
- i2s@70002800 {
+ tegra_i2s1: i2s@70002800 {
compatible = "nvidia,tegra20-i2s";
reg = <0x70002800 0x200>;
interrupts = < 0 13 0x04 >;
- dma-channel = < 2 >;
+ nvidia,dma-request-selector = < &apbdma 2 >;
};
- i2s@70002a00 {
+ tegra_i2s2: i2s@70002a00 {
compatible = "nvidia,tegra20-i2s";
reg = <0x70002a00 0x200>;
interrupts = < 0 3 0x04 >;
- dma-channel = < 1 >;
+ nvidia,dma-request-selector = < &apbdma 1 >;
};
das@70000c00 {
@@ -75,6 +101,8 @@
0 89 0x04 >;
#gpio-cells = <2>;
gpio-controller;
+ #interrupt-cells = <2>;
+ interrupt-controller;
};
pinmux: pinmux@70000000 {
@@ -120,6 +148,13 @@
interrupts = < 0 91 0x04 >;
};
+ emc@7000f400 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nvidia,tegra20-emc";
+ reg = <0x7000f400 0x200>;
+ };
+
sdhci@c8000000 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000000 0x200>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index ee7db9892e0..ac4b75cb26c 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -4,6 +4,11 @@
compatible = "nvidia,tegra30";
interrupt-parent = <&intc>;
+ pmc@7000f400 {
+ compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
+ reg = <0x7000e400 0x400>;
+ };
+
intc: interrupt-controller@50041000 {
compatible = "arm,cortex-a9-gic";
interrupt-controller;
@@ -12,6 +17,43 @@
< 0x50040100 0x0100 >;
};
+ apbdma: dma@6000a000 {
+ compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
+ reg = <0x6000a000 0x1400>;
+ interrupts = < 0 104 0x04
+ 0 105 0x04
+ 0 106 0x04
+ 0 107 0x04
+ 0 108 0x04
+ 0 109 0x04
+ 0 110 0x04
+ 0 111 0x04
+ 0 112 0x04
+ 0 113 0x04
+ 0 114 0x04
+ 0 115 0x04
+ 0 116 0x04
+ 0 117 0x04
+ 0 118 0x04
+ 0 119 0x04
+ 0 128 0x04
+ 0 129 0x04
+ 0 130 0x04
+ 0 131 0x04
+ 0 132 0x04
+ 0 133 0x04
+ 0 134 0x04
+ 0 135 0x04
+ 0 136 0x04
+ 0 137 0x04
+ 0 138 0x04
+ 0 139 0x04
+ 0 140 0x04
+ 0 141 0x04
+ 0 142 0x04
+ 0 143 0x04 >;
+ };
+
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -55,9 +97,18 @@
gpio: gpio@6000d000 {
compatible = "nvidia,tegra30-gpio", "nvidia,tegra20-gpio";
reg = < 0x6000d000 0x1000 >;
- interrupts = < 0 32 0x04 0 33 0x04 0 34 0x04 0 35 0x04 0 55 0x04 0 87 0x04 0 89 0x04 >;
+ interrupts = < 0 32 0x04
+ 0 33 0x04
+ 0 34 0x04
+ 0 35 0x04
+ 0 55 0x04
+ 0 87 0x04
+ 0 89 0x04
+ 0 125 0x04 >;
#gpio-cells = <2>;
gpio-controller;
+ #interrupt-cells = <2>;
+ interrupt-controller;
};
serial@70006000 {
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index e120ff54f66..e0b7a4d3259 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -7,6 +7,7 @@ obj-y += clock.o
obj-y += timer.o
obj-y += pinmux.o
obj-y += fuse.o
+obj-y += pmc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
@@ -15,7 +16,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o
+obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o apbio.o
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
obj-$(CONFIG_TEGRA_PCI) += pcie.o
obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
new file mode 100644
index 00000000000..e75451e517b
--- /dev/null
+++ b/arch/arm/mach-tegra/apbio.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2010 NVIDIA Corporation.
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * 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/kernel.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+
+#include <mach/dma.h>
+#include <mach/iomap.h>
+
+#include "apbio.h"
+
+static DEFINE_MUTEX(tegra_apb_dma_lock);
+
+static struct tegra_dma_channel *tegra_apb_dma;
+static u32 *tegra_apb_bb;
+static dma_addr_t tegra_apb_bb_phys;
+static DECLARE_COMPLETION(tegra_apb_wait);
+
+bool tegra_apb_init(void)
+{
+ struct tegra_dma_channel *ch;
+
+ mutex_lock(&tegra_apb_dma_lock);
+
+ /* Check to see if we raced to setup */
+ if (tegra_apb_dma)
+ goto out;
+
+ ch = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT |
+ TEGRA_DMA_SHARED);
+
+ if (!ch)
+ goto out_fail;
+
+ tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
+ &tegra_apb_bb_phys, GFP_KERNEL);
+ if (!tegra_apb_bb) {
+ pr_err("%s: can not allocate bounce buffer\n", __func__);
+ tegra_dma_free_channel(ch);
+ goto out_fail;
+ }
+
+ tegra_apb_dma = ch;
+out:
+ mutex_unlock(&tegra_apb_dma_lock);
+ return true;
+
+out_fail:
+ mutex_unlock(&tegra_apb_dma_lock);
+ return false;
+}
+
+static void apb_dma_complete(struct tegra_dma_req *req)
+{
+ complete(&tegra_apb_wait);
+}
+
+u32 tegra_apb_readl(unsigned long offset)
+{
+ struct tegra_dma_req req;
+ int ret;
+
+ if (!tegra_apb_dma && !tegra_apb_init())
+ return readl(IO_TO_VIRT(offset));
+
+ mutex_lock(&tegra_apb_dma_lock);
+ req.complete = apb_dma_complete;
+ req.to_memory = 1;
+ req.dest_addr = tegra_apb_bb_phys;
+ req.dest_bus_width = 32;
+ req.dest_wrap = 1;
+ req.source_addr = offset;
+ req.source_bus_width = 32;
+ req.source_wrap = 4;
+ req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
+ req.size = 4;
+
+ INIT_COMPLETION(tegra_apb_wait);
+
+ tegra_dma_enqueue_req(tegra_apb_dma, &req);
+
+ ret = wait_for_completion_timeout(&tegra_apb_wait,
+ msecs_to_jiffies(50));
+
+ if (WARN(ret == 0, "apb read dma timed out")) {
+ tegra_dma_dequeue_req(tegra_apb_dma, &req);
+ *(u32 *)tegra_apb_bb = 0;
+ }
+
+ mutex_unlock(&tegra_apb_dma_lock);
+ return *((u32 *)tegra_apb_bb);
+}
+
+void tegra_apb_writel(u32 value, unsigned long offset)
+{
+ struct tegra_dma_req req;
+ int ret;
+
+ if (!tegra_apb_dma && !tegra_apb_init()) {
+ writel(value, IO_TO_VIRT(offset));
+ return;
+ }
+
+ mutex_lock(&tegra_apb_dma_lock);
+ *((u32 *)tegra_apb_bb) = value;
+ req.complete = apb_dma_complete;
+ req.to_memory = 0;
+ req.dest_addr = offset;
+ req.dest_wrap = 4;
+ req.dest_bus_width = 32;
+ req.source_addr = tegra_apb_bb_phys;
+ req.source_bus_width = 32;
+ req.source_wrap = 1;
+ req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
+ req.size = 4;
+
+ INIT_COMPLETION(tegra_apb_wait);
+
+ tegra_dma_enqueue_req(tegra_apb_dma, &req);
+
+ ret = wait_for_completion_timeout(&tegra_apb_wait,
+ msecs_to_jiffies(50));
+
+ if (WARN(ret == 0, "apb write dma timed out"))
+ tegra_dma_dequeue_req(tegra_apb_dma, &req);
+
+ mutex_unlock(&tegra_apb_dma_lock);
+}
diff --git a/arch/arm/mach-tegra/apbio.h b/arch/arm/mach-tegra/apbio.h
new file mode 100644
index 00000000000..8b49e8c89a6
--- /dev/null
+++ b/arch/arm/mach-tegra/apbio.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 NVIDIA Corporation.
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * 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_APBIO_H
+#define __MACH_TEGRA_APBIO_H
+
+#ifdef CONFIG_TEGRA_SYSTEM_DMA
+
+u32 tegra_apb_readl(unsigned long offset);
+void tegra_apb_writel(u32 value, unsigned long offset);
+
+#else
+#include <asm/io.h>
+#include <mach/io.h>
+
+static inline u32 tegra_apb_readl(unsigned long offset)
+{
+ return readl(IO_TO_VIRT(offset));
+}
+
+static inline void tegra_apb_writel(u32 value, unsigned long offset)
+{
+ writel(value, IO_TO_VIRT(offset));
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c
index 21d1285731b..976edfb0591 100644
--- a/arch/arm/mach-tegra/board-harmony-power.c
+++ b/arch/arm/mach-tegra/board-harmony-power.c
@@ -18,18 +18,13 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
-#include <linux/io.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/tps6586x.h>
-#include <mach/iomap.h>
#include <mach/irqs.h>
#include "board-harmony.h"
-#define PMC_CTRL 0x0
-#define PMC_CTRL_INTR_LOW (1 << 17)
-
static struct regulator_consumer_supply tps658621_ldo0_supply[] = {
REGULATOR_SUPPLY("pex_clk", NULL),
};
@@ -114,16 +109,6 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
int __init harmony_regulator_init(void)
{
- void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
- u32 pmc_ctrl;
-
- /*
- * Configure the power management controller to trigger PMU
- * interrupts when low
- */
- pmc_ctrl = readl(pmc + PMC_CTRL);
- writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
-
i2c_register_board_info(3, harmony_regulators, 1);
return 0;
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 789bdc9e8f9..c00aadb01e0 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -101,7 +101,6 @@ static struct wm8903_platform_data harmony_wm8903_pdata = {
static struct i2c_board_info __initdata wm8903_board_info = {
I2C_BOARD_INFO("wm8903", 0x1a),
.platform_data = &harmony_wm8903_pdata,
- .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
};
static void __init harmony_i2c_init(void)
@@ -111,6 +110,7 @@ static void __init harmony_i2c_init(void)
platform_device_register(&tegra_i2c_device3);
platform_device_register(&tegra_i2c_device4);
+ wm8903_board_info.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
i2c_register_board_info(0, &wm8903_board_info, 1);
}
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index ebac65f5251..d669847f048 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -159,7 +159,6 @@ static struct platform_device *seaboard_devices[] __initdata = {
static struct i2c_board_info __initdata isl29018_device = {
I2C_BOARD_INFO("isl29018", 0x44),
- .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_ISL29018_IRQ),
};
static struct i2c_board_info __initdata adt7461_device = {
@@ -183,7 +182,6 @@ static struct wm8903_platform_data wm8903_pdata = {
static struct i2c_board_info __initdata wm8903_device = {
I2C_BOARD_INFO("wm8903", 0x1a),
.platform_data = &wm8903_pdata,
- .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
};
static int seaboard_ehci_init(void)
@@ -214,7 +212,10 @@ static void __init seaboard_i2c_init(void)
gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
+ isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ);
i2c_register_board_info(0, &isl29018_device, 1);
+
+ wm8903_device.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
i2c_register_board_info(0, &wm8903_device, 1);
i2c_register_board_info(3, &adt7461_device, 1);
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 2db20da1d58..47ad750209a 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -31,6 +31,24 @@
#include "board.h"
#include "clock.h"
#include "fuse.h"
+#include "pmc.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 = {
@@ -101,11 +119,13 @@ void __init tegra20_init_early(void)
tegra2_init_clocks();
tegra_clk_init_from_table(tegra20_clk_init_table);
tegra_init_cache(0x331, 0x441);
+ tegra_pmc_init();
}
#endif
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
void __init tegra30_init_early(void)
{
tegra_init_cache(0x441, 0x551);
+ tegra_pmc_init();
}
#endif
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
index c0cf967e47d..abea4f6e2dd 100644
--- a/arch/arm/mach-tegra/dma.c
+++ b/arch/arm/mach-tegra/dma.c
@@ -33,6 +33,8 @@
#include <mach/iomap.h>
#include <mach/suspend.h>
+#include "apbio.h"
+
#define APB_DMA_GEN 0x000
#define GEN_ENABLE (1<<31)
@@ -50,8 +52,6 @@
#define CSR_ONCE (1<<27)
#define CSR_FLOW (1<<21)
#define CSR_REQ_SEL_SHIFT 16
-#define CSR_REQ_SEL_MASK (0x1F<<CSR_REQ_SEL_SHIFT)
-#define CSR_REQ_SEL_INVALID (31<<CSR_REQ_SEL_SHIFT)
#define CSR_WCOUNT_SHIFT 2
#define CSR_WCOUNT_MASK 0xFFFC
@@ -133,6 +133,7 @@ struct tegra_dma_channel {
static bool tegra_dma_initialized;
static DEFINE_MUTEX(tegra_dma_lock);
+static DEFINE_SPINLOCK(enable_lock);
static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
@@ -180,36 +181,94 @@ static void tegra_dma_stop(struct tegra_dma_channel *ch)
static int tegra_dma_cancel(struct tegra_dma_channel *ch)
{
- u32 csr;
unsigned long irq_flags;
spin_lock_irqsave(&ch->lock, irq_flags);
while (!list_empty(&ch->list))
list_del(ch->list.next);
- csr = readl(ch->addr + APB_DMA_CHAN_CSR);
- csr &= ~CSR_REQ_SEL_MASK;
- csr |= CSR_REQ_SEL_INVALID;
- writel(csr, ch->addr + APB_DMA_CHAN_CSR);
-
tegra_dma_stop(ch);
spin_unlock_irqrestore(&ch->lock, irq_flags);
return 0;
}
+static unsigned int get_channel_status(struct tegra_dma_channel *ch,
+ struct tegra_dma_req *req, bool is_stop_dma)
+{
+ void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+ unsigned int status;
+
+ if (is_stop_dma) {
+ /*
+ * STOP the DMA and get the transfer count.
+ * Getting the transfer count is tricky.
+ * - Globally disable DMA on all channels
+ * - Read the channel's status register to know the number
+ * of pending bytes to be transfered.
+ * - Stop the dma channel
+ * - Globally re-enable DMA to resume other transfers
+ */
+ spin_lock(&enable_lock);
+ writel(0, addr + APB_DMA_GEN);
+ udelay(20);
+ status = readl(ch->addr + APB_DMA_CHAN_STA);
+ teg