summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/Kconfig37
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra30.c10
-rw-r--r--arch/arm/mach-tegra/board-paz00.c3
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c2
-rw-r--r--arch/arm/mach-tegra/common.c22
-rw-r--r--arch/arm/mach-tegra/devices.c5
-rw-r--r--arch/arm/mach-tegra/devices.h4
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra-ahb.h19
-rw-r--r--arch/arm/mach-tegra/include/mach/uncompress.h176
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h4
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c4
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks.c9
-rw-r--r--arch/arm/mach-tegra/usb_phy.c15
13 files changed, 246 insertions, 64 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d0f2546..6a113a9 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -50,6 +50,14 @@ config TEGRA_PCI
depends on ARCH_TEGRA_2x_SOC
select PCI
+config TEGRA_AHB
+ bool "Enable AHB driver for NVIDIA Tegra SoCs"
+ default y
+ help
+ Adds AHB configuration functionality for NVIDIA Tegra SoCs,
+ which controls AHB bus master arbitration and some
+ perfomance parameters(priority, prefech size).
+
comment "Tegra board type"
config MACH_HARMONY
@@ -111,7 +119,7 @@ config MACH_VENTANA
Support for the nVidia Ventana development platform
choice
- prompt "Low-level debug console UART"
+ prompt "Default low-level debug console UART"
default TEGRA_DEBUG_UART_NONE
config TEGRA_DEBUG_UART_NONE
@@ -134,6 +142,33 @@ config TEGRA_DEBUG_UARTE
endchoice
+choice
+ prompt "Automatic low-level debug console UART"
+ default TEGRA_DEBUG_UART_AUTO_NONE
+
+config TEGRA_DEBUG_UART_AUTO_NONE
+ bool "None"
+
+config TEGRA_DEBUG_UART_AUTO_ODMDATA
+ bool "Via ODMDATA"
+ help
+ Automatically determines which UART to use for low-level debug based
+ on the ODMDATA value. This value is part of the BCT, and is written
+ to the boot memory device using nvflash, or other flashing tool.
+ When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
+ 0/1/2/3/4 are UART A/B/C/D/E.
+
+config TEGRA_DEBUG_UART_AUTO_SCRATCH
+ bool "Via UART scratch register"
+ help
+ Automatically determines which UART to use for low-level debug based
+ on the UART scratch register value. Some bootloaders put ASCII 'D'
+ in this register when they initialize their own console UART output.
+ Using this option allows the kernel to automatically pick the same
+ UART.
+
+endchoice
+
config TEGRA_SYSTEM_DMA
bool "Enable system DMA driver for NVIDIA Tegra SoCs"
default y
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index 5f7c03e..d96dae0 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -51,12 +51,22 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C500, "tegra-i2c.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL),
OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL),
+ OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
{}
};
static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
/* name parent rate enabled */
{ "uarta", "pll_p", 408000000, true },
+ { "pll_a", "pll_p_out1", 564480000, true },
+ { "pll_a_out0", "pll_a", 11289600, true },
+ { "extern1", "pll_a_out0", 0, true },
+ { "clk_out_1", "extern1", 0, true },
+ { "i2s0", "pll_a_out0", 11289600, false},
+ { "i2s1", "pll_a_out0", 11289600, false},
+ { "i2s2", "pll_a_out0", 11289600, false},
+ { "i2s3", "pll_a_out0", 11289600, false},
+ { "i2s4", "pll_a_out0", 11289600, false},
{ NULL, NULL, 0, 0},
};
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index d0735c7..55a1e6c 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -162,6 +162,8 @@ static void paz00_i2c_init(void)
static void paz00_usb_init(void)
{
+ tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_ULPI_RST;
+
platform_device_register(&tegra_ehci2_device);
platform_device_register(&tegra_ehci3_device);
}
@@ -179,7 +181,6 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
{ "uarta", "pll_p", 216000000, true },
{ "uartc", "pll_p", 216000000, true },
- { "pll_p_out4", "pll_p", 24000000, true },
{ "usbd", "clk_m", 12000000, false },
{ "usb2", "clk_m", 12000000, false },
{ "usb3", "clk_m", 12000000, false },
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index bc59b37..832fa93 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -118,6 +118,8 @@ static void trimslice_usb_init(void)
pdata = tegra_ehci1_device.dev.platform_data;
pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE;
+ tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_GPIO_PV0;
+
platform_device_register(&tegra_ehci3_device);
platform_device_register(&tegra_ehci2_device);
platform_device_register(&tegra_ehci1_device);
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 22df10f..2d80566 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -82,10 +82,12 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = {
{ "pll_p_out1", "pll_p", 28800000, true },
{ "pll_p_out2", "pll_p", 48000000, true },
{ "pll_p_out3", "pll_p", 72000000, true },
- { "pll_p_out4", "pll_p", 108000000, true },
- { "sclk", "pll_p_out4", 108000000, true },
- { "hclk", "sclk", 108000000, true },
- { "pclk", "hclk", 54000000, true },
+ { "pll_p_out4", "pll_p", 24000000, true },
+ { "pll_c", "clk_m", 600000000, true },
+ { "pll_c_out1", "pll_c", 120000000, true },
+ { "sclk", "pll_c_out1", 120000000, true },
+ { "hclk", "sclk", 120000000, true },
+ { "pclk", "hclk", 60000000, true },
{ "csite", NULL, 0, true },
{ "emc", NULL, 0, true },
{ "cpu", NULL, 0, true },
@@ -93,6 +95,17 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = {
};
#endif
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
+ /* name parent rate enabled */
+ { "clk_m", NULL, 0, true },
+ { "pll_p", "clk_m", 408000000, true },
+ { "pll_p_out1", "pll_p", 9600000, true },
+ { NULL, NULL, 0, 0},
+};
+#endif
+
+
static void __init tegra_init_cache(u32 tag_latency, u32 data_latency)
{
#ifdef CONFIG_CACHE_L2X0
@@ -127,6 +140,7 @@ void __init tegra30_init_early(void)
{
tegra_init_fuse();
tegra30_init_clocks();
+ tegra_clk_init_from_table(tegra30_clk_init_table);
tegra_init_cache(0x441, 0x551);
tegra_pmc_init();
tegra_powergate_init();
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 2d8dfa2..c70e65f 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -439,9 +439,8 @@ static struct resource tegra_usb3_resources[] = {
},
};
-static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
- /* All existing boards use GPIO PV0 for phy reset */
- .reset_gpio = TEGRA_GPIO_PV0,
+struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+ .reset_gpio = -1,
.clk = "cdev2",
};
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 138c642..4f50527 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -22,6 +22,10 @@
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
+#include <mach/usb_phy.h>
+
+extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config;
+
extern struct tegra_ehci_platform_data tegra_ehci1_pdata;
extern struct tegra_ehci_platform_data tegra_ehci2_pdata;
extern struct tegra_ehci_platform_data tegra_ehci3_pdata;
diff --git a/arch/arm/mach-tegra/include/mach/tegra-ahb.h b/arch/arm/mach-tegra/include/mach/tegra-ahb.h
new file mode 100644
index 0000000..e0f8c84
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/tegra-ahb.h
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#ifndef __MACH_TEGRA_AHB_H__
+#define __MACH_TEGRA_AHB_H__
+
+extern int tegra_ahb_enable_smmu(struct device_node *ahb);
+
+#endif /* __MACH_TEGRA_AHB_H__ */
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 5a440f3..937c4c5 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -63,52 +63,86 @@ static inline void save_uart_address(void)
buf[0] = 0;
}
-/*
- * 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,
+ },
+};
+
+static inline bool uart_clocked(int i)
+{
+ if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
+ return false;
+
+ if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
+ return false;
+
+ return true;
+}
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
+int auto_odmdata(void)
+{
+ volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
+ u32 odmdata = pmc[0xa0 / 4];
+
+ /*
+ * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
+ * Some boards apparently swap the last two values, but we don't have
+ * any way of catering for that here, so we just accept either. If this
+ * doesn't make sense for your board, just don't enable this feature.
+ *
+ * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
+ */
+
+ switch ((odmdata >> 18) & 3) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return -1;
+ }
+
+ return (odmdata >> 15) & 7;
+}
+#endif
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
+int auto_scratch(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;
/*
* Look for the first UART that:
@@ -125,20 +159,60 @@ static inline void arch_decomp_setup(void)
* 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)))
+ if (!uart_clocked(i))
continue;
uart = (volatile u8 *)uarts[i].base;
if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
continue;
- break;
+ return i;
}
- if (i == ARRAY_SIZE(uarts))
- uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
+
+ return -1;
+}
+#endif
+
+/*
+ * Setup before decompression. This is where we do UART selection for
+ * earlyprintk and init the uart_base register.
+ */
+static inline void arch_decomp_setup(void)
+{
+ int uart_id, auto_uart_id;
+ volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
+ u32 chip, div;
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+ uart_id = 0;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+ uart_id = 1;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+ uart_id = 2;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+ uart_id = 3;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+ uart_id = 4;
+#else
+ uart_id = -1;
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+ auto_uart_id = auto_odmdata();
+#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
+ auto_uart_id = auto_scratch();
+#else
+ auto_uart_id = -1;
+#endif
+ if (auto_uart_id != -1)
+ uart_id = auto_uart_id;
+
+ if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
+ !uart_clocked(uart_id))
+ uart = NULL;
+ else
+ uart = (volatile u8 *)uarts[uart_id].base;
+
save_uart_address();
if (uart == NULL)
return;
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index de1a0f6..935ce9f 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -61,8 +61,8 @@ struct tegra_usb_phy {
struct usb_phy *ulpi;
};
-struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
- void *config, enum tegra_usb_phy_mode phy_mode);
+struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
+ void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index bae09b8..b59315c 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -1486,6 +1486,10 @@ static struct clk tegra_clk_m = {
};
static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
+ { 12000000, 600000000, 600, 12, 1, 8 },
+ { 13000000, 600000000, 600, 13, 1, 8 },
+ { 19200000, 600000000, 500, 16, 1, 6 },
+ { 26000000, 600000000, 600, 26, 1, 8 },
{ 0, 0, 0, 0, 0, 0 },
};
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index 6d08b53..e33fe4b 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -3015,6 +3015,15 @@ struct clk_duplicate tegra_clk_duplicates[] = {
CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
CLK_DUPLICATE("twd", "smp_twd", NULL),
CLK_DUPLICATE("vcp", "nvavp", "vcp"),
+ CLK_DUPLICATE("i2s0", NULL, "i2s0"),
+ CLK_DUPLICATE("i2s1", NULL, "i2s1"),
+ CLK_DUPLICATE("i2s2", NULL, "i2s2"),
+ CLK_DUPLICATE("i2s3", NULL, "i2s3"),
+ CLK_DUPLICATE("i2s4", NULL, "i2s4"),
+ CLK_DUPLICATE("dam0", NULL, "dam0"),
+ CLK_DUPLICATE("dam1", NULL, "dam1"),
+ CLK_DUPLICATE("dam2", NULL, "dam2"),
+ CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
};
struct clk *tegra_ptr_clks[] = {
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index d71d2fe..54e353c 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <asm/mach-types.h>
@@ -654,8 +655,8 @@ static void ulpi_phy_power_off(struct tegra_usb_phy *phy)
clk_disable(phy->clk);
}
-struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
- void *config, enum tegra_usb_phy_mode phy_mode)
+struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
+ void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
{
struct tegra_usb_phy *phy;
struct tegra_ulpi_config *ulpi_config;
@@ -711,6 +712,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
err = -ENXIO;
goto err1;
}
+ if (!gpio_is_valid(ulpi_config->reset_gpio))
+ ulpi_config->reset_gpio =
+ of_get_named_gpio(dev->of_node,
+ "nvidia,phy-reset-gpio", 0);
+ if (!gpio_is_valid(ulpi_config->reset_gpio)) {
+ pr_err("%s: invalid reset gpio: %d\n", __func__,
+ ulpi_config->reset_gpio);
+ err = -EINVAL;
+ goto err1;
+ }
gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
gpio_direction_output(ulpi_config->reset_gpio, 0);
phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
OpenPOWER on IntegriCloud