summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-05-06 09:30:53 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2013-05-06 09:30:53 +0200
commit740f01feb7a86161362d05dbc0f9b5cf8c4159b5 (patch)
tree165d73b6d9403f04b2ede1914b9f606d77845fc1 /arch
parente9a39d79b9c57dfe0e5736de9ed192cc6273a56b (diff)
parentfbcb481c60d80e76f3c5d537ae05d0adf01ac9e1 (diff)
downloadbarebox-740f01feb7a86161362d05dbc0f9b5cf8c4159b5.tar.gz
barebox-740f01feb7a86161362d05dbc0f9b5cf8c4159b5.tar.xz
Merge branch 'for-next/tegra'
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig11
-rw-r--r--arch/arm/boards/toshiba-ac100/Makefile2
-rw-r--r--arch/arm/boards/toshiba-ac100/board.c8
-rw-r--r--arch/arm/boards/toshiba-ac100/lowlevel.c10
-rw-r--r--arch/arm/boards/toshiba-ac100/serial.c39
-rw-r--r--arch/arm/configs/toshiba_ac100_defconfig7
-rw-r--r--arch/arm/dts/tegra20-paz00.dts12
-rw-r--r--arch/arm/dts/tegra20.dtsi41
-rw-r--r--arch/arm/mach-tegra/Kconfig53
-rw-r--r--arch/arm/mach-tegra/Makefile9
-rw-r--r--arch/arm/mach-tegra/clock.c56
-rw-r--r--arch/arm/mach-tegra/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/iomap.h3
-rw-r--r--arch/arm/mach-tegra/include/mach/lowlevel.h146
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra20-car.h179
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra20-pmc.h67
-rw-r--r--arch/arm/mach-tegra/reset.c39
-rw-r--r--arch/arm/mach-tegra/tegra20-car.c120
-rw-r--r--arch/arm/mach-tegra/tegra20-pmc.c68
-rw-r--r--arch/arm/mach-tegra/tegra20-timer.c119
-rw-r--r--arch/arm/mach-tegra/tegra20.c65
-rw-r--r--arch/arm/mach-tegra/tegra_avp_init.c226
-rw-r--r--arch/arm/mach-tegra/tegra_maincomplex_init.c46
24 files changed, 1172 insertions, 162 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index bb9b47b2de..0a4f821814 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -136,9 +136,16 @@ config ARCH_VEXPRESS
select COMMON_CLK
config ARCH_TEGRA
- bool "Nvidia Tegra-based boards"
- select CPU_ARM926T
+ bool "NVIDIA Tegra"
+ select CPU_V7
select HAS_DEBUG_LL
+ select BUILTIN_DTB
+ select COMMON_CLK
+ select CLKDEV_LOOKUP
+ select GPIOLIB
+ select GPIO_TEGRA
+ select OFDEVICE
+ select OFTREE
config ARCH_ZYNQ
bool "Xilinx Zynq-based boards"
diff --git a/arch/arm/boards/toshiba-ac100/Makefile b/arch/arm/boards/toshiba-ac100/Makefile
index 4d321e1622..dcfc2937d3 100644
--- a/arch/arm/boards/toshiba-ac100/Makefile
+++ b/arch/arm/boards/toshiba-ac100/Makefile
@@ -1,3 +1 @@
obj-y += board.o
-obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial.o
-lwl-y += lowlevel.o
diff --git a/arch/arm/boards/toshiba-ac100/board.c b/arch/arm/boards/toshiba-ac100/board.c
index 0eb85c5edc..51232ef427 100644
--- a/arch/arm/boards/toshiba-ac100/board.c
+++ b/arch/arm/boards/toshiba-ac100/board.c
@@ -23,14 +23,6 @@
#include <usb/ehci.h>
#include <mach/iomap.h>
-static int ac100_mem_init(void)
-{
- arm_add_mem_device("ram0", 0x0, SZ_512M);
-
- return 0;
-}
-mem_initcall(ac100_mem_init);
-
static struct ehci_platform_data ehci_pdata = {
.flags = EHCI_HAS_TT,
};
diff --git a/arch/arm/boards/toshiba-ac100/lowlevel.c b/arch/arm/boards/toshiba-ac100/lowlevel.c
deleted file mode 100644
index 2f99d709a4..0000000000
--- a/arch/arm/boards/toshiba-ac100/lowlevel.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <common.h>
-#include <sizes.h>
-#include <asm/barebox-arm-head.h>
-#include <asm/barebox-arm.h>
-
-void __naked barebox_arm_reset_vector(void)
-{
- arm_cpu_lowlevel_init();
- barebox_arm_entry(0x0, SZ_512M, 0);
-}
diff --git a/arch/arm/boards/toshiba-ac100/serial.c b/arch/arm/boards/toshiba-ac100/serial.c
deleted file mode 100644
index 880270ddde..0000000000
--- a/arch/arm/boards/toshiba-ac100/serial.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2011 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * See file CREDITS for list of people who contributed to this project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <common.h>
-#include <types.h>
-#include <driver.h>
-#include <init.h>
-#include <ns16550.h>
-#include <asm/io.h>
-#include <asm/common.h>
-#include <mach/iomap.h>
-
-static struct NS16550_plat serial_plat = {
- .clock = 0x75 * 115200 * 16 /* MODE_X_DIV */,
- .shift = 2,
-};
-
-static int ac100_serial_console_init(void)
-{
- /* Register the serial port */
- add_ns16550_device(DEVICE_ID_DYNAMIC, TEGRA_UARTA_BASE, 8 << serial_plat.shift,
- IORESOURCE_MEM_8BIT, &serial_plat);
-
- return 0;
-}
-console_initcall(ac100_serial_console_init);
diff --git a/arch/arm/configs/toshiba_ac100_defconfig b/arch/arm/configs/toshiba_ac100_defconfig
index 065189d490..19039108a1 100644
--- a/arch/arm/configs/toshiba_ac100_defconfig
+++ b/arch/arm/configs/toshiba_ac100_defconfig
@@ -1,4 +1,6 @@
+CONFIG_BUILTIN_DTB_NAME="tegra20-paz00"
CONFIG_ARCH_TEGRA=y
+CONFIG_TEGRA_UART_A=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_TEXT_BASE=0x01000000
CONFIG_BROKEN=y
@@ -14,6 +16,7 @@ CONFIG_ENABLE_DEVICE_NOISE=y
CONFIG_CMD_SLEEP=y
# CONFIG_CMD_TRUE is not set
# CONFIG_CMD_FALSE is not set
+CONFIG_CMD_TFTP=y
CONFIG_CMD_LOADB=y
CONFIG_CMD_LOADY=y
CONFIG_CMD_LOADS=y
@@ -23,11 +26,10 @@ CONFIG_CMD_SHA1SUM=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_PING=y
-CONFIG_CMD_TFTP=y
-CONFIG_FS_TFTP=y
CONFIG_NET_NETCONSOLE=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_NET_USB=y
@@ -36,4 +38,5 @@ CONFIG_NET_USB_ASIX=y
CONFIG_USB=y
CONFIG_USB_EHCI=y
CONFIG_USB_STORAGE=y
+CONFIG_FS_TFTP=y
CONFIG_FS_FAT=y
diff --git a/arch/arm/dts/tegra20-paz00.dts b/arch/arm/dts/tegra20-paz00.dts
new file mode 100644
index 0000000000..09ccb8ba3a
--- /dev/null
+++ b/arch/arm/dts/tegra20-paz00.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+ model = "Toshiba AC100 / Dynabook AZ";
+ compatible = "compal,paz00", "nvidia,tegra20";
+
+ memory {
+ reg = <0x00000000 0x20000000>;
+ };
+};
diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
new file mode 100644
index 0000000000..b7d1e27de2
--- /dev/null
+++ b/arch/arm/dts/tegra20.dtsi
@@ -0,0 +1,41 @@
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "nvidia,tegra20";
+
+ timer@60005000 {
+ compatible = "nvidia,tegra20-timer";
+ reg = <0x60005000 0x60>;
+ interrupts = <0 0 0x04
+ 0 1 0x04
+ 0 41 0x04
+ 0 42 0x04>;
+ };
+
+ tegra_car: clock {
+ compatible = "nvidia,tegra20-car";
+ reg = <0x60006000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ gpio: gpio {
+ compatible = "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>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ };
+
+ pmc {
+ compatible = "nvidia,tegra20-pmc";
+ reg = <0x7000e400 0x400>;
+ };
+};
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index eda786bafb..965e7ab6ba 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -1,11 +1,56 @@
if ARCH_TEGRA
+choice
+ prompt "Tegra processor type"
+
+config ARCH_TEGRA_2x_SOC
+ bool "Tegra 20"
+
+endchoice
+
+choice
+ prompt "Tegra debug UART"
+ help
+ This is the first serial console that gets activated by barebox.
+ Normally each board vendor should program a valid debug UART into
+ the ODMdata section of the boot configuration table, so it's a
+ reasonably good bet to use that.
+ If you know your ODMdata is broken, or you don't wish to activate
+ any serial console at all you can override the default here.
+
+config TEGRA_UART_ODMDATA
+ bool "ODMdata defined UART"
+
+config TEGRA_UART_A
+ bool "UART A"
+
+config TEGRA_UART_B
+ bool "UART B"
+
+config TEGRA_UART_C
+ bool "UART C"
+
+config TEGRA_UART_D
+ bool "UART D"
+
+config TEGRA_UART_E
+ bool "UART E"
+
+config TEGRA_UART_NONE
+ bool "None"
+
+endchoice
+
+# ---------------------------------------------------------
+
+if ARCH_TEGRA_2x_SOC
+
config ARCH_TEXT_BASE
hex
- default 0x31fc0000
+ default 0x00108000
choice
- prompt "Tegra Board Type"
+ prompt "Tegra 20 Board Type"
config MACH_TOSHIBA_AC100
bool "Toshiba AC100"
@@ -16,4 +61,8 @@ endchoice
source arch/arm/boards/toshiba-ac100/Kconfig
+endif #ARCH_TEGRA_2x_SOC
+
+# ---------------------------------------------------------
+
endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 11915e5e23..f9c771f6a5 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,2 +1,7 @@
-obj-y += clock.o
-obj-y += reset.o
+CFLAGS_tegra_avp_init.o := -mcpu=arm7tdmi -march=armv4t
+lwl-y += tegra_avp_init.o
+lwl-y += tegra_maincomplex_init.o
+obj-y += tegra20.o
+obj-y += tegra20-car.o
+obj-y += tegra20-pmc.o
+obj-y += tegra20-timer.o
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
deleted file mode 100644
index 82065ee74f..0000000000
--- a/arch/arm/mach-tegra/clock.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * See file CREDITS for list of people who contributed to this project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-/**
- * @file
- * @brief Clocksource based on Tegra internal timer
- */
-
-#include <common.h>
-#include <clock.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <init.h>
-#include <asm/io.h>
-#include <mach/iomap.h>
-
-static void __iomem *timer_reg_base = (void __iomem *) (TEGRA_TMR1_BASE);
-
-#define timer_writel(value, reg) \
- __raw_writel(value, (u32)timer_reg_base + (reg))
-#define timer_readl(reg) \
- __raw_readl((u32)timer_reg_base + (reg))
-
-static uint64_t tegra_clocksource_read(void)
-{
- return timer_readl(0x10);
-}
-
-static struct clocksource cs = {
- .read = tegra_clocksource_read,
- .mask = 0xffffffff,
-};
-
-/* FIXME: here we have no initialization. All initialization made by U-Boot */
-static int clocksource_init(void)
-{
- cs.mult = clocksource_hz2mult(1000000, cs.shift);
- init_clock(&cs);
-
- return 0;
-}
-core_initcall(clocksource_init);
diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h
new file mode 100644
index 0000000000..04b37a8980
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
new file mode 100644
index 0000000000..306ab4c9f2
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -0,0 +1 @@
+#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index ba478e7b25..b74e5d2fbe 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -59,6 +59,9 @@
#define TEGRA_GART_BASE 0x58000000
#define TEGRA_GART_SIZE SZ_32M
+#define TEGRA_UP_TAG_BASE 0x60000000
+#define TEGRA_UP_TAG_SIZE SZ_4K
+
#define TEGRA_RES_SEMA_BASE 0x60001000
#define TEGRA_RES_SEMA_SIZE SZ_4K
diff --git a/arch/arm/mach-tegra/include/mach/lowlevel.h b/arch/arm/mach-tegra/include/mach/lowlevel.h
new file mode 100644
index 0000000000..b7c01c0995
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/lowlevel.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * @brief Boot informations provided by the Tegra SoC and it's BootROM. All
+ * accessor functions are a header only implementations, as they are meant to
+ * be used by both the main CPU complex (ARMv7) and the AVP (ARMv4).
+ */
+
+#include <sizes.h>
+#include <io.h>
+#include <mach/iomap.h>
+
+/* Bootinfotable */
+
+#define NV_BIT_BCTSIZE 0x38 /* size of the BCT in IRAM */
+#define NV_BIT_BCTPTR 0x3C /* location of the BCT in IRAM */
+
+/* ODM data */
+#define BCT_ODMDATA_OFFSET 12 /* offset from the _end_ of the BCT */
+
+#define T20_ODMDATA_RAMSIZE_SHIFT 28
+#define T20_ODMDATA_RAMSIZE_MASK (3 << T20_ODMDATA_RAMSIZE_SHIFT)
+#define T20_ODMDATA_UARTTYPE_SHIFT 18
+#define T20_ODMDATA_UARTTYPE_MASK (3 << T20_ODMDATA_UARTTYPE_SHIFT)
+#define T20_ODMDATA_UARTID_SHIFT 15
+#define T20_ODMDATA_UARTID_MASK (7 << T20_ODMDATA_UARTID_SHIFT)
+
+static inline u32 tegra_get_odmdata(void)
+{
+ u32 bctsize, bctptr, odmdata;
+
+ bctsize = cpu_readl(TEGRA_IRAM_BASE + NV_BIT_BCTSIZE);
+ bctptr = cpu_readl(TEGRA_IRAM_BASE + NV_BIT_BCTPTR);
+
+ odmdata = cpu_readl(bctptr + bctsize - BCT_ODMDATA_OFFSET);
+
+ return odmdata;
+}
+
+/* chip ID */
+#define APB_MISC_HIDREV 0x804
+#define HIDREV_CHIPID_SHIFT 8
+#define HIDREV_CHIPID_MASK (0xff << HIDREV_CHIPID_SHIFT)
+
+enum tegra_chiptype {
+ TEGRA_UNK_REV = -1,
+ TEGRA20 = 0,
+};
+
+static inline enum tegra_chiptype tegra_get_chiptype(void)
+{
+ u32 hidrev;
+
+ hidrev = readl(TEGRA_APB_MISC_BASE + APB_MISC_HIDREV);
+
+ switch ((hidrev & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT) {
+ case 0x20:
+ return TEGRA20;
+ default:
+ return TEGRA_UNK_REV;
+ }
+}
+
+static inline int tegra_get_num_cores(void)
+{
+ switch (tegra_get_chiptype()) {
+ case TEGRA20:
+ return 2;
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+/* Runtime data */
+static inline int tegra_cpu_is_maincomplex(void)
+{
+ u32 tag0;
+
+ tag0 = readl(TEGRA_UP_TAG_BASE);
+
+ return (tag0 & 0xff) == 0x55;
+}
+
+static inline uint32_t tegra20_get_ramsize(void)
+{
+ switch ((tegra_get_odmdata() & T20_ODMDATA_RAMSIZE_MASK) >>
+ T20_ODMDATA_RAMSIZE_SHIFT) {
+ case 1:
+ return SZ_256M;
+ default:
+ case 2:
+ return SZ_512M;
+ case 3:
+ return SZ_1G;
+ }
+}
+
+static long uart_id_to_base[] = {
+ TEGRA_UARTA_BASE,
+ TEGRA_UARTB_BASE,
+ TEGRA_UARTC_BASE,
+ TEGRA_UARTD_BASE,
+ TEGRA_UARTE_BASE,
+};
+
+static inline long tegra20_get_debuguart_base(void)
+{
+ u32 odmdata;
+ int id;
+
+ odmdata = tegra_get_odmdata();
+
+ /*
+ * Get type, we accept both "2" and "3", as they both demark a UART,
+ * depending on the board type.
+ */
+ if (!(((odmdata & T20_ODMDATA_UARTTYPE_MASK) >>
+ T20_ODMDATA_UARTTYPE_SHIFT) & 0x2))
+ return 0;
+
+ id = (odmdata & T20_ODMDATA_UARTID_MASK) >> T20_ODMDATA_UARTID_SHIFT;
+ if (id > ARRAY_SIZE(uart_id_to_base))
+ return 0;
+
+ return uart_id_to_base[id];
+}
+
+/* reset vector for the main CPU complex */
+void tegra_maincomplex_entry(void);
diff --git a/arch/arm/mach-tegra/include/mach/tegra20-car.h b/arch/arm/mach-tegra/include/mach/tegra20-car.h
new file mode 100644
index 0000000000..566973283d
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/tegra20-car.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* Register definitions */
+#define CRC_CLK_OUT_ENB_L 0x010
+#define CRC_CLK_OUT_ENB_L_CACHE2 (1 << 31)
+#define CRC_CLK_OUT_ENB_L_VCP (1 << 29)
+#define CRC_CLK_OUT_ENB_L_HOST1X (1 << 28)
+#define CRC_CLK_OUT_ENB_L_DISP1 (1 << 27)
+#define CRC_CLK_OUT_ENB_L_DISP2 (1 << 26)
+#define CRC_CLK_OUT_ENB_L_IDE (1 << 25)
+#define CRC_CLK_OUT_ENB_L_3D (1 << 24)
+#define CRC_CLK_OUT_ENB_L_ISP (1 << 23)
+#define CRC_CLK_OUT_ENB_L_USBD (1 << 22)
+#define CRC_CLK_OUT_ENB_L_2D (1 << 21)
+#define CRC_CLK_OUT_ENB_L_VI (1 << 20)
+#define CRC_CLK_OUT_ENB_L_EPP (1 << 19)
+#define CRC_CLK_OUT_ENB_L_I2S2 (1 << 18)
+#define CRC_CLK_OUT_ENB_L_PWM (1 << 17)
+#define CRC_CLK_OUT_ENB_L_TWC (1 << 16)
+#define CRC_CLK_OUT_ENB_L_SDMMC4 (1 << 15)
+#define CRC_CLK_OUT_ENB_L_SDMMC1 (1 << 14)
+#define CRC_CLK_OUT_ENB_L_NDFLASH (1 << 13)
+#define CRC_CLK_OUT_ENB_L_I2C1 (1 << 12)
+#define CRC_CLK_OUT_ENB_L_I2S1 (1 << 11)
+#define CRC_CLK_OUT_ENB_L_SPDIF (1 << 10)
+#define CRC_CLK_OUT_ENB_L_SDMMC2 (1 << 9)
+#define CRC_CLK_OUT_ENB_L_GPIO (1 << 8)
+#define CRC_CLK_OUT_ENB_L_UART2 (1 << 7)
+#define CRC_CLK_OUT_ENB_L_UART1 (1 << 6)
+#define CRC_CLK_OUT_ENB_L_TMR (1 << 5)
+#define CRC_CLK_OUT_ENB_L_RTC (1 << 4)
+#define CRC_CLK_OUT_ENB_L_AC97 (1 << 3)
+#define CRC_CLK_OUT_ENB_L_CPU (1 << 0)
+
+#define CRC_SCLK_BURST_POLICY 0x028
+#define CRC_SCLK_BURST_POLICY_SYS_STATE_SHIFT 28
+#define CRC_SCLK_BURST_POLICY_SYS_STATE_FIQ 8
+#define CRC_SCLK_BURST_POLICY_SYS_STATE_IRQ 4
+#define CRC_SCLK_BURST_POLICY_SYS_STATE_RUN 2
+#define CRC_SCLK_BURST_POLICY_SYS_STATE_IDLE 1
+#define CRC_SCLK_BURST_POLICY_SYS_STATE_STDBY 0
+
+#define CRC_SUPER_SCLK_DIV 0x02c
+#define CRC_SUPER_SDIV_ENB (1 << 31)
+#define CRC_SUPER_SDIV_DIS_FROM_COP_FIQ (1 << 27)
+#define CRC_SUPER_SDIV_DIS_FROM_CPU_FIQ (1 << 26)
+#define CRC_SUPER_SDIV_DIS_FROM_COP_IRQ (1 << 25)
+#define CRC_SUPER_SDIV_DIS_FROM_CPU_IRQ (1 << 24)
+#define CRC_SUPER_SDIV_DIVIDEND_SHIFT 8
+#define CRC_SUPER_SDIV_DIVIDEND_MASK (0xff << CRC_SUPER_SDIV_DIVIDEND_SHIFT)
+#define CRC_SUPER_SDIV_DIVISOR_SHIFT 0
+#define CRC_SUPER_SDIV_DIVISOR_MASK (0xff << CRC_SUPER_SDIV_DIVISOR_SHIFT)
+
+#define CRC_CLK_CPU_CMPLX 0x04c
+#define CRC_CLK_CPU_CMPLX_CPU3_CLK_STP (1 << 11)
+#define CRC_CLK_CPU_CMPLX_CPU2_CLK_STP (1 << 10)
+#define CRC_CLK_CPU_CMPLX_CPU1_CLK_STP (1 << 9)
+#define CRC_CLK_CPU_CMPLX_CPU0_CLK_STP (1 << 8)
+#define CRC_CLK_CPU_CMPLX_CPU_BRIDGE_DIV_SHIFT 0
+#define CRC_CLK_CPU_CMPLX_CPU_BRIDGE_DIV_4 3
+#define CRC_CLK_CPU_CMPLX_CPU_BRIDGE_DIV_3 2
+#define CRC_CLK_CPU_CMPLX_CPU_BRIDGE_DIV_2 1
+#define CRC_CLK_CPU_CMPLX_CPU_BRIDGE_DIV_1 0
+
+#define CRC_OSC_CTRL 0x050
+#define CRC_OSC_CTRL_OSC_FREQ_SHIFT 30
+#define CRC_OSC_CTRL_OSC_FREQ_MASK (0x3 << CRC_OSC_CTRL_OSC_FREQ_SHIFT)
+#define CRC_OSC_CTRL_PLL_REF_DIV_SHIFT 28
+#define CRC_OSC_CTRL_PLL_REF_DIV_MASK (0x3 << CRC_OSC_CTRL_PLL_REF_DIV_SHIFT)
+
+#define CRC_PLLX_BASE 0x0e0
+#define CRC_PLLX_BASE_BYPASS (1 << 31)
+#define CRC_PLLX_BASE_ENABLE (1 << 30)
+#define CRC_PLLX_BASE_REF_DIS (1 << 29)
+#define CRC_PLLX_BASE_LOCK (1 << 27)
+#define CRC_PLLX_BASE_DIVP_SHIFT 20
+#define CRC_PLLX_BASE_DIVP_MASK (0x7 << CRC_PLLX_BASE_DIVP_SHIFT)
+#define CRC_PLLX_BASE_DIVN_SHIFT 8
+#define CRC_PLLX_BASE_DIVN_MASK (0x3ff << CRC_PLLX_BASE_DIVN_SHIFT)
+#define CRC_PLLX_BASE_DIVM_SHIFT 0
+#define CRC_PLLX_BASE_DIVM_MASK (0xf << CRC_PLLX_BASE_DIVM_SHIFT)
+
+#define CRC_PLLX_MISC 0x0e4
+#define CRC_PLLX_MISC_SETUP_SHIFT 24
+#define CRC_PLLX_MISC_SETUP_MASK (0xf << CRC_PLLX_MISC_SETUP_SHIFT)
+#define CRC_PLLX_MISC_PTS_SHIFT 22
+#define CRC_PLLX_MISC_PTS_MASK (0x3 << CRC_PLLX_MISC_PTS_SHIFT)
+#define CRC_PLLX_MISC_DCCON (1 << 20)
+#define CRC_PLLX_MISC_LOCK_ENABLE (1 << 18)
+#define CRC_PLLX_MISC_LOCK_SEL_SHIFT 12
+#define CRC_PLLX_MISC_LOCK_SEL_MASK (0x3f << CRC_PLLX_MISC_LOCK_SEL_SHIFT)
+#define CRC_PLLX_MISC_CPCON_SHIFT 8
+#define CRC_PLLX_MISC_CPCON_MASK (0xf << CRC_PLLX_MISC_CPCON_SHIFT)
+#define CRC_PLLX_MISC_LFCON_SHIFT 4
+#define CRC_PLLX_MISC_LFCON_MASK (0xf << CRC_PLLX_MISC_LFCON_SHIFT)
+#define CRC_PLLX_MISC_VCOCON_SHIFT 0
+#define CRC_PLLX_MISC_VCOCON_MASK (0xf << CRC_PLLX_MISC_VCOCON_SHIFT)
+
+#define CRC_RST_DEV_L_SET 0x300
+#define CRC_RST_DEV_L_SET_CACHE2 (1 << 31)
+#define CRC_RST_DEV_L_SET_VCP (1 << 29)
+#define CRC_RST_DEV_L_SET_HOST1X (1 << 28)
+#define CRC_RST_DEV_L_SET_DISP1 (1 << 27)
+#define CRC_RST_DEV_L_SET_DISP2 (1 << 26)
+#define CRC_RST_DEV_L_SET_IDE (1 << 25)
+#define CRC_RST_DEV_L_SET_3D (1 << 24)
+#define CRC_RST_DEV_L_SET_ISP (1 << 23)
+#define CRC_RST_DEV_L_SET_USBD (1 << 22)
+#define CRC_RST_DEV_L_SET_2D (1 << 21)
+#define CRC_RST_DEV_L_SET_VI (1 << 20)
+#define CRC_RST_DEV_L_SET_EPP (1 << 19)
+#define CRC_RST_DEV_L_SET_I2S2 (1 << 18)
+#define CRC_RST_DEV_L_SET_PWM (1 << 17)
+#define CRC_RST_DEV_L_SET_TWC (1 << 16)
+#define CRC_RST_DEV_L_SET_SDMMC4 (1 << 15)
+#define CRC_RST_DEV_L_SET_SDMMC1 (1 << 14)
+#define CRC_RST_DEV_L_SET_NDFLASH (1 << 13)
+#define CRC_RST_DEV_L_SET_I2C1 (1 << 12)
+#define CRC_RST_DEV_L_SET_I2S1 (1 << 11)
+#define CRC_RST_DEV_L_SET_SPDIF (1 << 10)
+#define CRC_RST_DEV_L_SET_SDMMC2 (1 << 9)
+#define CRC_RST_DEV_L_SET_GPIO (1 << 8)
+#define CRC_RST_DEV_L_SET_UART2 (1 << 7)
+#define CRC_RST_DEV_L_SET_UART1 (1 << 6)
+#define CRC_RST_DEV_L_SET_TMR (1 << 5)
+#define CRC_RST_DEV_L_SET_AC97 (1 << 3)
+#define CRC_RST_DEV_L_SET_SYS (1 << 2)
+#define CRC_RST_DEV_L_SET_COP (1 << 1)
+#define CRC_RST_DEV_L_SET_CPU (1 << 0)
+
+#define CRC_RST_DEV_L_CLR 0x304
+#define CRC_RST_DEV_L_CLR_CACHE2 (1 << 31)
+#define CRC_RST_DEV_L_CLR_VCP (1 << 29)
+#define CRC_RST_DEV_L_CLR_HOST1X (1 << 28)
+#define CRC_RST_DEV_L_CLR_DISP1 (1 << 27)
+#define CRC_RST_DEV_L_CLR_DISP2 (1 << 26)
+#define CRC_RST_DEV_L_CLR_IDE (1 << 25)
+#define CRC_RST_DEV_L_CLR_3D (1 << 24)
+#define CRC_RST_DEV_L_CLR_ISP (1 << 23)
+#define CRC_RST_DEV_L_CLR_USBD (1 << 22)
+#define CRC_RST_DEV_L_CLR_2D (1 << 21)
+#define CRC_RST_DEV_L_CLR_VI (1 << 20)
+#define CRC_RST_DEV_L_CLR_EPP (1 << 19)
+#define CRC_RST_DEV_L_CLR_I2S2 (1 << 18)
+#define CRC_RST_DEV_L_CLR_PWM (1 << 17)
+#define CRC_RST_DEV_L_CLR_TWC (1 << 16)
+#define CRC_RST_DEV_L_CLR_SDMMC4 (1 << 15)
+#define CRC_RST_DEV_L_CLR_SDMMC1 (1 << 14)
+#define CRC_RST_DEV_L_CLR_NDFLASH (1 << 13)
+#define CRC_RST_DEV_L_CLR_I2C1 (1 << 12)
+#define CRC_RST_DEV_L_CLR_I2S1 (1 << 11)
+#define CRC_RST_DEV_L_CLR_SPDIF (1 << 10)
+#define CRC_RST_DEV_L_CLR_SDMMC2 (1 << 9)
+#define CRC_RST_DEV_L_CLR_GPIO (1 << 8)
+#define CRC_RST_DEV_L_CLR_UART2 (1 << 7)
+#define CRC_RST_DEV_L_CLR_UART1 (1 << 6)
+#define CRC_RST_DEV_L_CLR_TMR (1 << 5)
+#define CRC_RST_DEV_L_CLR_AC97 (1 << 3)
+#define CRC_RST_DEV_L_CLR_SYS (1 << 2)
+#define CRC_RST_DEV_L_CLR_COP (1 << 1)
+#define CRC_RST_DEV_L_CLR_CPU (1 << 0)
+
+#define CRC_RST_CPU_CMPLX_SET 0x340
+
+#define CRC_RST_CPU_CMPLX_CLR 0x344
diff --git a/arch/arm/mach-tegra/include/mach/tegra20-pmc.h b/arch/arm/mach-tegra/include/mach/tegra20-pmc.h
new file mode 100644
index 0000000000..d56b845b9f
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/tegra20-pmc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* register definitions */
+#define PMC_CNTRL 0x000
+#define PMC_CNTRL_FUSE_OVERRIDE (1 << 18)
+#define PMC_CNTRL_INTR_POLARITY (1 << 17)
+#define PMC_CNTRL_CPUPWRREQ_OE (1 << 16)
+#define PMC_CNTRL_CPUPWRREQ_POLARITY (1 << 15)
+#define PMC_CNTRL_SIDE_EFFECT_LP0 (1 << 14)
+#define PMC_CNTRL_AOINIT (1 << 13)
+#define PMC_CNTRL_PWRGATE_DIS (1 << 12)
+#define PMC_CNTRL_SYSCLK_OE (1 << 11)
+#define PMC_CNTRL_SYSCLK_POLARITY (1 << 10)
+#define PMC_CNTRL_PWRREQ_OE (1 << 9)
+#define PMC_CNTRL_PWRREQ_POLARITY (1 << 8)
+#define PMC_CNTRL_BLINK_EN (1 << 7)
+#define PMC_CNTRL_GLITCHDET_DIS (1 << 6)
+#define PMC_CNTRL_LATCHWAKE_EN (1 << 5)
+#define PMC_CNTRL_MAIN_RST (1 << 4)
+#define PMC_CNTRL_KBC_RST (1 << 3)
+#define PMC_CNTRL_RTC_RST (1 << 2)
+#define PMC_CNTRL_RTC_CLK_DIS (1 << 1)
+#define PMC_CNTRL_KBC_CLK_DIS (1 << 0)
+
+#define PMC_PWRGATE_TOGGLE 0x030
+#define PMC_PWRGATE_TOGGLE_PARTID_SHIFT 0
+#define PMC_PWRGATE_TOGGLE_PARTID_MASK (0x3 << PMC_PWRGATE_TOGGLE_PARTID_SHIFT)
+#define PMC_PWRGATE_TOGGLE_PARTID_CPU 0
+#define PMC_PWRGATE_TOGGLE_PARTID_TD 1
+#define PMC_PWRGATE_TOGGLE_PARTID_VE 2
+#define PMC_PWRGATE_TOGGLE_PARTID_PCX 3
+#define PMC_PWRGATE_TOGGLE_PARTID_VDE 4
+#define PMC_PWRGATE_TOGGLE_PARTID_L2C 5
+#define PMC_PWRGATE_TOGGLE_PARTID_MPE 6
+#define PMC_PWRGATE_TOGGLE_START (1 << 8)
+
+#define PMC_REMOVE_CLAMPING_CMD 0x034
+#define PMC_REMOVE_CLAMPING_CMD_MPE (1 << 6)
+#define PMC_REMOVE_CLAMPING_CMD_L2C (1 << 5)
+#define PMC_REMOVE_CLAMPING_CMD_PCX (1 << 4)
+#define PMC_REMOVE_CLAMPING_CMD_VDE (1 << 3)
+#define PMC_REMOVE_CLAMPING_CMD_VE (1 << 2)
+#define PMC_REMOVE_CLAMPING_CMD_TD (1 << 1)
+#define PMC_REMOVE_CLAMPING_CMD_CPU (1 << 0)
+
+#define PMC_PWRGATE_STATUS 0x038
+#define PMC_PWRGATE_STATUS_MPE (1 << 6)
+#define PMC_PWRGATE_STATUS_L2C (1 << 5)
+#define PMC_PWRGATE_STATUS_VDE (1 << 4)
+#define PMC_PWRGATE_STATUS_PCX (1 << 3)
+#define PMC_PWRGATE_STATUS_VE (1 << 2)
+#define PMC_PWRGATE_STATUS_TD (1 << 1)
+#define PMC_PWRGATE_STATUS_CPU (1 << 0)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
deleted file mode 100644
index 91f9b3b62e..0000000000
--- a/arch/arm/mach-tegra/reset.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2011 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * See file CREDITS for list of people who contributed to this project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-/**
- * @file
- * @brief Resetting an malta board
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <mach/iomap.h>
-
-#define PRM_RSTCTRL TEGRA_PMC_BASE
-
-void __noreturn reset_cpu(ulong addr)
-{
- int rstctrl;
-
- rstctrl = __raw_readl((char *)PRM_RSTCTRL);
- rstctrl |= 0x10;
- __raw_writel(rstctrl, (char *)PRM_RSTCTRL);
-
- unreachable();
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-tegra/tegra20-car.c b/arch/arm/mach-tegra/tegra20-car.c
new file mode 100644
index 0000000000..3af7bdcc4a
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20-car.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * @brief Device driver for the Tegra 20 clock and reset (CAR) controller
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <mach/iomap.h>
+
+#include <mach/tegra20-car.h>
+
+static void __iomem *car_base;
+
+enum tegra20_clks {
+ cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1,
+ ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp,
+ gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma,
+ kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3,
+ dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2,
+ usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
+ pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb,
+ iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2,
+ uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve,
+ osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0,
+ pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1,
+ pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_u,
+ pll_x, audio, pll_ref, twd, clk_max,
+};
+
+static struct clk *clks[clk_max];
+
+static unsigned long get_osc_frequency(void)
+{
+ u32 osc_ctrl = readl(car_base + CRC_OSC_CTRL);
+
+ switch ((osc_ctrl & CRC_OSC_CTRL_OSC_FREQ_MASK) >>
+ CRC_OSC_CTRL_OSC_FREQ_SHIFT) {
+ case 0:
+ return 13000000;
+ case 1:
+ return 19200000;
+ case 2:
+ return 12000000;
+ case 3:
+ return 26000000;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_pll_ref_div(void)
+{
+ u32 osc_ctrl = readl(car_base + CRC_OSC_CTRL);
+
+ return 1U << ((osc_ctrl & CRC_OSC_CTRL_PLL_REF_DIV_MASK) >>
+ CRC_OSC_CTRL_PLL_REF_DIV_SHIFT);
+}
+
+static int tegra20_car_probe(struct device_d *dev)
+{
+ car_base = dev_request_mem_region(dev, 0);
+ if (!car_base)
+ return -EBUSY;
+
+ /* primary clocks */
+ clks[clk_m] = clk_fixed("clk_m", get_osc_frequency());
+ clks[clk_32k] = clk_fixed("clk_32k", 32768);
+
+ clks[pll_ref] = clk_fixed_factor("pll_ref", "clk_m", 1,
+ get_pll_ref_div());
+
+ /* derived clocks */
+ /* timer is a gate, but as it's enabled by BOOTROM we needn't worry */
+ clks[timer] = clk_fixed_factor("timer", "clk_m", 1, 1);
+
+ /* device to clock links */
+ clkdev_add_physbase(clks[timer], TEGRA_TMR1_BASE, NULL);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id tegra20_car_dt_ids[] = {
+ {
+ .compatible = "nvidia,tegra20-car",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d tegra20_car_driver = {
+ .probe = tegra20_car_probe,
+ .name = "tegra20-car",
+ .of_compatible = DRV_OF_COMPAT(tegra20_car_dt_ids),
+};
+
+static int tegra20_car_init(void)
+{
+ return platform_driver_register(&tegra20_car_driver);
+}
+postcore_initcall(tegra20_car_init);
diff --git a/arch/arm/mach-tegra/tegra20-pmc.c b/arch/arm/mach-tegra/tegra20-pmc.c
new file mode 100644
index 0000000000..b7d84d89ba
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20-pmc.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * @brief Device driver for the Tegra 20 power management controller.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+
+#include <mach/tegra20-pmc.h>
+
+static void __iomem *pmc_base;
+
+/* main SoC reset trigger */
+void __noreturn reset_cpu(ulong addr)
+{
+ writel(PMC_CNTRL_MAIN_RST, pmc_base + PMC_CNTRL);
+
+ unreachable();
+}
+EXPORT_SYMBOL(reset_cpu);
+
+static int tegra20_pmc_probe(struct device_d *dev)
+{
+ pmc_base = dev_request_mem_region(dev, 0);
+ if (!pmc_base) {
+ dev_err(dev, "could not get memory region\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id tegra20_pmc_dt_ids[] = {
+ {
+ .compatible = "nvidia,tegra20-pmc",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d tegra20_pmc_driver = {
+ .probe = tegra20_pmc_probe,
+ .name = "tegra20-pmc",
+ .of_compatible = DRV_OF_COMPAT(tegra20_pmc_dt_ids),
+};
+
+static int tegra20_pmc_init(void)
+{
+ return platform_driver_register(&tegra20_pmc_driver);
+}
+coredevice_initcall(tegra20_pmc_init);
diff --git a/arch/arm/mach-tegra/tegra20-timer.c b/arch/arm/mach-tegra/tegra20-timer.c
new file mode 100644
index 0000000000..aafbfd43c7
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20-timer.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * @brief Device driver for the Tegra 20 timer, which exposes a clocksource.
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+
+/* register definitions */
+#define TIMERUS_CNTR_1US 0x10
+#define TIMERUS_USEC_CFG 0x14
+
+static void __iomem *timer_base;
+
+static uint64_t tegra20_timer_cs_read(void)
+{
+ return readl(timer_base + TIMERUS_CNTR_1US);
+}
+
+static struct clocksource cs = {
+ .read = tegra20_timer_cs_read,
+ .mask = CLOCKSOURCE_MASK(32),
+};
+
+static int tegra20_timer_probe(struct device_d *dev)
+{
+ struct clk *timer_clk;
+ unsigned long rate;
+ u32 reg;
+
+ /* use only one timer */
+ if (timer_base)
+ return -EBUSY;
+
+ timer_base = dev_request_mem_region(dev, 0);
+ if (!timer_base) {
+ dev_err(dev, "could not get memory region\n");
+ return -ENODEV;
+ }
+
+ timer_clk = clk_get(dev, NULL);
+ if (!timer_clk) {
+ dev_err(dev, "could not get clock\n");
+ return -ENODEV;
+ }
+
+ clk_enable(timer_clk);
+
+ /*
+ * calibrate timer to run at 1MHz
+ * TIMERUS_USEC_CFG selects the scale down factor with bits [0:7]
+ * representing the divisor and bits [8:15] representing the dividend
+ * each in n+1 form.
+ */
+ rate = clk_get_rate(timer_clk);
+ switch (rate) {
+ case 12000000:
+ reg = 0x000b;
+ break;
+ case 13000000:
+ reg = 0x000c;
+ break;
+ case 19200000:
+ reg = 0x045f;
+ break;
+ case 26000000:
+ reg = 0x0019;
+ break;
+ default:
+ reg = 0;
+ dev_warn(dev, "unknown timer clock rate\n");
+ break;
+ }
+ writel(reg, timer_base + TIMERUS_USEC_CFG);
+
+ cs.mult = clocksource_hz2mult(1000000, cs.shift);
+ init_clock(&cs);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id tegra20_timer_dt_ids[] = {
+ {
+ .compatible = "nvidia,tegra20-timer",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d tegra20_timer_driver = {
+ .probe = tegra20_timer_probe,
+ .name = "tegra20-timer",
+ .of_compatible = DRV_OF_COMPAT(tegra20_timer_dt_ids),
+};
+
+static int tegra20_timer_init(void)
+{
+ return platform_driver_register(&tegra20_timer_driver);
+}
+coredevice_initcall(tegra20_timer_init);
diff --git a/arch/arm/mach-tegra/tegra20.c b/arch/arm/mach-tegra/tegra20.c
new file mode 100644
index 0000000000..cc2d748641
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <ns16550.h>
+#include <asm/memory.h>
+#include <mach/iomap.h>
+#include <mach/lowlevel.h>
+
+static struct NS16550_plat debug_uart = {
+ .clock = 216000000, /* pll_p rate */
+ .shift = 2,
+};
+
+static int tegra20_add_debug_console(void)
+{
+ unsigned long base = 0;
+
+ /* figure out which UART to use */
+ if (IS_ENABLED(CONFIG_TEGRA_UART_NONE))
+ return 0;
+ if (IS_ENABLED(CONFIG_TEGRA_UART_ODMDATA))
+ base = tegra20_get_debuguart_base();
+ if (IS_ENABLED(CONFIG_TEGRA_UART_A))
+ base = TEGRA_UARTA_BASE;
+ if (IS_ENABLED(CONFIG_TEGRA_UART_B))
+ base = TEGRA_UARTB_BASE;
+ if (IS_ENABLED(CONFIG_TEGRA_UART_C))
+ base = TEGRA_UARTC_BASE;
+ if (IS_ENABLED(CONFIG_TEGRA_UART_D))
+ base = TEGRA_UARTD_BASE;
+ if (IS_ENABLED(CONFIG_TEGRA_UART_E))
+ base = TEGRA_UARTE_BASE;
+
+ if (!base)
+ return -ENODEV;
+
+ add_ns16550_device(DEVICE_ID_DYNAMIC, base, 8 << debug_uart.shift,
+ IORESOURCE_MEM_8BIT, &debug_uart);
+
+ return 0;
+}
+console_initcall(tegra20_add_debug_console);
+
+static int tegra20_mem_init(void)
+{
+ arm_add_mem_device("ram0", 0x0, tegra20_get_ramsize());
+
+ return 0;
+}
+mem_initcall(tegra20_mem_init);
diff --git a/arch/arm/mach-tegra/tegra_avp_init.c b/arch/arm/mach-tegra/tegra_avp_init.c
new file mode 100644
index 0000000000..4823733418
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_avp_init.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * Partly based on code (C) Copyright 2010-2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <asm/barebox-arm-head.h>
+#include <mach/lowlevel.h>
+#include <mach/tegra20-car.h>
+#include <mach/tegra20-pmc.h>
+
+static inline void tegra_cpu_lowlevel_setup(void)
+{
+ uint32_t r;
+
+ /* set the cpu to SVC32 mode */
+ __asm__ __volatile__("mrs %0, cpsr":"=r"(r));
+ r &= ~0x1f;
+ r |= 0xd3;
+ __asm__ __volatile__("msr cpsr, %0" : : "r"(r));
+}
+
+/* instruct the PMIC to enable the CPU power rail */
+static void enable_maincomplex_powerrail(void)
+{
+ u32 reg;
+
+ reg = readl(TEGRA_PMC_BASE + PMC_CNTRL);
+ reg |= PMC_CNTRL_CPUPWRREQ_OE;
+ writel(reg, TEGRA_PMC_BASE);
+}
+
+/* put every core in the main CPU complex into reset state */
+static void assert_maincomplex_reset(int num_cores)
+{
+ u32 mask = 0;
+ int i;
+
+ for (i = 0; i < num_cores; i++)
+ mask |= 0x1111 << i;
+
+ writel(mask, TEGRA_CLK_RESET_BASE + CRC_RST_CPU_CMPLX_SET);
+ writel(CRC_RST_DEV_L_SET_CPU, TEGRA_CLK_RESET_BASE + CRC_RST_DEV_L_SET);
+}
+
+/* release reset state of the first core of the main CPU complex */
+static void deassert_cpu0_reset(void)
+{
+ writel(0x1111, TEGRA_CLK_RESET_BASE + CRC_RST_CPU_CMPLX_CLR);
+ writel(CRC_RST_DEV_L_CLR_CPU, TEGRA_CLK_RESET_BASE + CRC_RST_DEV_L_CLR);
+}
+
+/* stop all internal and external clocks to the main CPU complex */
+static void stop_maincomplex_clocks(int num_cores)
+{
+ u32 reg;
+ int i;
+
+ reg = readl(TEGRA_CLK_RESET_BASE + CRC_CLK_CPU_CMPLX);
+ for (i = 0; i < num_cores; i++)
+ reg |= 0x1 << (8 + i);
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_CLK_CPU_CMPLX);
+
+ reg = readl(TEGRA_CLK_RESET_BASE + CRC_CLK_OUT_ENB_L);
+ reg &= ~CRC_CLK_OUT_ENB_L_CPU;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_CLK_OUT_ENB_L);
+}
+
+struct pll_config {
+ u16 divn;
+ u16 divm;
+ u16 divp;
+ u16 cpcon;
+};
+
+static struct pll_config pllx_config_table[][4] = {
+ {
+ {1000, 13, 0, 12}, /* OSC 13.0 MHz */
+ {625, 12, 0, 8 }, /* OSC 19.2 MHz */
+ {1000, 12, 0, 12}, /* OSC 12.0 MHz */
+ {1000, 26, 0, 12}, /* OSC 26.0 MHz */
+ }, /* TEGRA 20 */
+};
+
+static void init_pllx(void)
+{
+ struct pll_config *conf;
+ enum tegra_chiptype chiptype;
+ u8 osc_freq;
+ u32 reg;
+
+ /* If PLLX is already enabled, just return */
+ if (readl(TEGRA_CLK_RESET_BASE + CRC_PLLX_BASE) & CRC_PLLX_BASE_ENABLE)
+ return;
+
+ chiptype = tegra_get_chiptype();
+ if (chiptype < 0)
+ BUG();
+
+ osc_freq = (readl(TEGRA_CLK_RESET_BASE + CRC_OSC_CTRL) &
+ CRC_OSC_CTRL_OSC_FREQ_MASK) >> CRC_OSC_CTRL_OSC_FREQ_SHIFT;
+
+ conf = &pllx_config_table[chiptype][osc_freq];
+
+ /* set PLL bypass and frequency parameters */
+ reg = CRC_PLLX_BASE_BYPASS;
+ reg |= (conf->divm << CRC_PLLX_BASE_DIVM_SHIFT) &
+ CRC_PLLX_BASE_DIVM_MASK;
+ reg |= (conf->divn << CRC_PLLX_BASE_DIVN_SHIFT) &
+ CRC_PLLX_BASE_DIVN_MASK;
+ reg |= (conf->divp << CRC_PLLX_BASE_DIVP_SHIFT) &
+ CRC_PLLX_BASE_DIVP_MASK;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_PLLX_BASE);
+
+ /* set chargepump parameters */
+ reg = (conf->cpcon << CRC_PLLX_MISC_CPCON_SHIFT) &
+ CRC_PLLX_MISC_CPCON_MASK;
+ if (conf->divn > 600)
+ reg |= CRC_PLLX_MISC_DCCON;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_PLLX_MISC);
+
+ /* enable PLL and disable bypass */
+ reg = readl(TEGRA_CLK_RESET_BASE + CRC_PLLX_BASE);
+ reg |= CRC_PLLX_BASE_ENABLE;
+ reg &= ~CRC_PLLX_BASE_BYPASS;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_PLLX_BASE);
+
+ /* enable PLL lock */
+ reg = readl(TEGRA_CLK_RESET_BASE + CRC_PLLX_MISC);
+ reg |= CRC_PLLX_MISC_LOCK_ENABLE;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_PLLX_MISC);
+}
+
+/* start internal and external clocks to core 0 of the main CPU complex */
+static void start_cpu0_clocks(void)
+{
+ u32 reg;
+
+ /* setup PLLX */
+ init_pllx();
+
+ /* setup super CLK */
+ writel(CRC_SCLK_BURST_POLICY_SYS_STATE_RUN <<
+ CRC_SCLK_BURST_POLICY_SYS_STATE_SHIFT,
+ TEGRA_CLK_RESET_BASE + CRC_SCLK_BURST_POLICY);
+ writel(CRC_SUPER_SDIV_ENB, TEGRA_CLK_RESET_BASE + CRC_SUPER_SCLK_DIV);
+
+ /* deassert clock stop for cpu 0 */
+ reg = readl(TEGRA_CLK_RESET_BASE + CRC_CLK_CPU_CMPLX);
+ reg &= ~CRC_CLK_CPU_CMPLX_CPU0_CLK_STP;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_CLK_CPU_CMPLX);
+
+ /* enable main CPU complex clock */
+ reg = readl(TEGRA_CLK_RESET_BASE + CRC_CLK_OUT_ENB_L);
+ reg |= CRC_CLK_OUT_ENB_L_CPU;
+ writel(reg, TEGRA_CLK_RESET_BASE + CRC_CLK_OUT_ENB_L);
+}
+
+static void maincomplex_powerup(void)
+{
+ u32 reg;
+
+ if (!(readl(TEGRA_PMC_BASE + PMC_PWRGATE_STATUS) &
+ PMC_PWRGATE_STATUS_CPU)) {
+ writel(PMC_PWRGATE_TOGGLE_START | PMC_PWRGATE_TOGGLE_PARTID_CPU,
+ TEGRA_PMC_BASE + PMC_PWRGATE_TOGGLE);
+
+ while (!(readl(TEGRA_PMC_BASE + PMC_PWRGATE_STATUS) &
+ PMC_PWRGATE_STATUS_CPU));
+
+ reg = readl(TEGRA_PMC_BASE + PMC_REMOVE_CLAMPING_CMD);
+ reg |= PMC_REMOVE_CLAMPING_CMD_CPU;
+ writel(reg, TEGRA_PMC_BASE + PMC_REMOVE_CLAMPING_CMD);
+ }
+}
+void barebox_arm_reset_vector(void)
+{
+ int num_cores;
+
+ /* minimal initialization, OK for both ARMv4 and ARMv7 */
+ tegra_cpu_lowlevel_setup();
+
+ /*
+ * If we are already running on the main CPU complex jump straight
+ * to the maincomplex entry point.
+ */
+ if (tegra_cpu_is_maincomplex())
+ tegra_maincomplex_entry();
+
+ /* get the number of cores in the main CPU complex of the current SoC */
+ num_cores = tegra_get_num_cores();
+ if (!num_cores)
+ BUG();
+
+ /* bring down main CPU complex (this may be a warm boot) */
+ enable_maincomplex_powerrail();
+ assert_maincomplex_reset(num_cores);
+ stop_maincomplex_clocks(num_cores);
+
+ /* set start address for the main CPU complex processors */
+ writel(barebox_arm_head, TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
+
+ /* bring up main CPU complex */
+ start_cpu0_clocks();
+ maincomplex_powerup();
+ deassert_cpu0_reset();
+
+ /* assert AVP reset to stop execution here */
+ writel(CRC_RST_DEV_L_SET_COP, TEGRA_CLK_RESET_BASE + CRC_RST_DEV_L_SET);
+
+ unreachable();
+}
diff --git a/arch/arm/mach-tegra/tegra_maincomplex_init.c b/arch/arm/mach-tegra/tegra_maincomplex_init.c
new file mode 100644
index 0000000000..dea9c9151d
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_maincomplex_init.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <sizes.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <mach/lowlevel.h>
+
+void tegra_maincomplex_entry(void)
+{
+ uint32_t rambase, ramsize;
+
+ arm_cpu_lowlevel_init();
+
+ switch (tegra_get_chiptype()) {
+ case TEGRA20:
+ rambase = 0x0;
+ ramsize = tegra20_get_ramsize();
+ break;
+ default:
+ /* If we don't know the chiptype, better bail out */
+ BUG();
+ }
+
+ /*
+ * The standard load address for Tegra systems is 0x10800 which means
+ * the barebox binary will always be below the malloc area for all
+ * reasonable malloc area sizes. We offset the RAM base address by 8MB
+ * to pretend barebox is in another bank.
+ */
+ barebox_arm_entry(rambase + SZ_8M, ramsize - SZ_8M, 0);
+}