diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 37 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-dt-tegra30.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-paz00.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-trimslice.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/common.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-tegra/devices.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/devices.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra-ahb.h | 19 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/uncompress.h | 176 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/usb_phy.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra30_clocks.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 15 |
13 files changed, 246 insertions, 64 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d0f2546706ca..6a113a9bb87a 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 5f7c03e972f3..d96dae0b4aa7 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 d0735c70d688..55a1e6ccf4a2 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 bc59b379c6fe..832fa931c710 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 22df10fb9972..2d80566b5383 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 2d8dfa2faf8f..c70e65ffa36b 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 138c642e59f4..4f5052726495 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 000000000000..e0f8c84b1d8c --- /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 5a440f315e57..937c4c50219e 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 de1a0f602b28..935ce9f65590 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 bae09b859891..b59315ce3691 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 6d08b53f92d2..e33fe4b14a2a 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 d71d2fed6721..54e353c8e304 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); |