diff options
author | Gary King <gking@nvidia.com> | 2010-05-18 14:00:33 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-18 19:54:10 -0700 |
commit | 24796a8d8fde4371d518922d2a0006af7e0f389c (patch) | |
tree | 68bec5b916080109d42be4eaf0847dac6f6fa6af | |
parent | 19e0d62cd31e070836492c6dd3ce28d99ef5f29e (diff) |
[ARM/tegra] initialize debug console based on ODM query values
add a new board file for initialization of platform data and registration
of platform devices based on ODM-queried values, rather than compile-
time constants.
add debug console (UART) initialization to it.
Change-Id: I592cea3b714b03d3e122ad46d12305c43c9e382f
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-generic.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-nvodm.c | 130 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock_nvrm.c | 22 |
4 files changed, 148 insertions, 7 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 2f7dcf099355..fd9e1df56d92 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -27,6 +27,7 @@ ccflags-$(CONFIG_TEGRA_NVOS) += -DNV_USE_FUSE_CLOCK_ENABLE=0 obj-$(CONFIG_TEGRA_NVOS) += nvos_user.o obj-$(CONFIG_TEGRA_NVOS) += nvos/ +obj-$(CONFIG_TEGRA_NVRM) += board-nvodm.o obj-$(CONFIG_TEGRA_NVRM) += nvrm/ obj-$(CONFIG_TEGRA_NVRM) += nvodm/ obj-$(CONFIG_TEGRA_NVRM) += odm_kit/ diff --git a/arch/arm/mach-tegra/board-generic.c b/arch/arm/mach-tegra/board-generic.c index 8fcfe6be228e..25bc4b58e427 100644 --- a/arch/arm/mach-tegra/board-generic.c +++ b/arch/arm/mach-tegra/board-generic.c @@ -135,11 +135,13 @@ static struct platform_device *platform_devices[] = { }; +extern void __init tegra_setup_nvodm(void); extern void __init tegra_register_socdev(void); static void __init tegra_generic_init(void) { tegra_common_init(); + tegra_setup_nvodm(); tegra_register_socdev(); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); } diff --git a/arch/arm/mach-tegra/board-nvodm.c b/arch/arm/mach-tegra/board-nvodm.c new file mode 100644 index 000000000000..463a6f99f3f8 --- /dev/null +++ b/arch/arm/mach-tegra/board-nvodm.c @@ -0,0 +1,130 @@ +/* + * arch/arm/mach-tegra/board-nvodm.c + * + * Converts data from ODM query library into platform data + * + * Copyright (c) 2009-2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> + +#include <mach/iomap.h> +#include <mach/io.h> +#include <mach/pinmux.h> + +#include "nvodm_query.h" +#include "nvodm_query_pinmux.h" + +extern const struct tegra_pingroup_config *tegra_pinmux_get(const char *dev_id, + int config, int *len); + + +static struct plat_serial8250_port debug_uart_platform[] = { + { + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + }, { + .flags = 0, + } +}; +static struct platform_device debug_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = debug_uart_platform, + }, +}; + +static void __init tegra_setup_debug_uart(void) +{ + NvOdmDebugConsole uart = NvOdmQueryDebugConsole(); + const struct tegra_pingroup_config *pinmux = NULL; + const NvU32 *odm_table; + struct clk *c; + NvU32 odm_nr; + int nr_pins; + + if (uart < NvOdmDebugConsole_UartA || + uart > NvOdmDebugConsole_UartE) + return; + + NvOdmQueryPinMux(NvOdmIoModule_Uart, &odm_table, &odm_nr); + if (odm_nr <= (uart - NvOdmDebugConsole_UartA)) { + pr_err("%s: ODM query configured improperly\n", __func__); + WARN_ON(1); + return; + } + + odm_nr = odm_table[uart - NvOdmDebugConsole_UartA]; + + if (uart == NvOdmDebugConsole_UartA) { + pinmux = tegra_pinmux_get("tegra_uart.0", odm_nr, &nr_pins); + c = clk_get_sys("uart.0", NULL); + debug_uart_platform[0].membase = IO_ADDRESS(TEGRA_UARTA_BASE); + debug_uart_platform[0].mapbase = TEGRA_UARTA_BASE; + debug_uart_platform[0].irq = INT_UARTA; + } else if (uart == NvOdmDebugConsole_UartB) { + pinmux = tegra_pinmux_get("tegra_uart.1", odm_nr, &nr_pins); + c = clk_get_sys("uart.1", NULL); + debug_uart_platform[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE); + debug_uart_platform[0].mapbase = TEGRA_UARTB_BASE; + debug_uart_platform[0].irq = INT_UARTB; + } else if (uart == NvOdmDebugConsole_UartC) { + pinmux = tegra_pinmux_get("tegra_uart.2", odm_nr, &nr_pins); + c = clk_get_sys("uart.2", NULL); + debug_uart_platform[0].membase = IO_ADDRESS(TEGRA_UARTC_BASE); + debug_uart_platform[0].mapbase = TEGRA_UARTC_BASE; + debug_uart_platform[0].irq = INT_UARTC; + } else if (uart == NvOdmDebugConsole_UartD) { + pinmux = tegra_pinmux_get("tegra_uart.3", odm_nr, &nr_pins); + c = clk_get_sys("uart.3", NULL); + debug_uart_platform[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE); + debug_uart_platform[0].mapbase = TEGRA_UARTD_BASE; + debug_uart_platform[0].irq = INT_UARTD; + } else if (uart == NvOdmDebugConsole_UartE) { + pinmux = tegra_pinmux_get("tegra_uart.4", odm_nr, &nr_pins); + c = clk_get_sys("uart.4", NULL); + debug_uart_platform[0].membase = IO_ADDRESS(TEGRA_UARTE_BASE); + debug_uart_platform[0].mapbase = TEGRA_UARTE_BASE; + debug_uart_platform[0].irq = INT_UARTE; + } + + if (!c || !pinmux || !nr_pins) { + if (c) + clk_put(c); + return; + } + + tegra_pinmux_config_tristate_table(pinmux, nr_pins, TEGRA_TRI_NORMAL); + clk_set_rate(c, 115200*16); + clk_enable(c); + debug_uart_platform[0].uartclk = clk_get_rate(c); + clk_put(c); + + platform_device_register(&debug_uart); +} + + +void __init tegra_setup_nvodm(void) +{ + tegra_setup_debug_uart(); +} diff --git a/arch/arm/mach-tegra/clock_nvrm.c b/arch/arm/mach-tegra/clock_nvrm.c index f2a24956b4d3..b53c493c5b4b 100644 --- a/arch/arm/mach-tegra/clock_nvrm.c +++ b/arch/arm/mach-tegra/clock_nvrm.c @@ -68,14 +68,18 @@ static int tegra_periph_clk_enable(struct clk *c) e = NvRmPowerVoltageControl(s_hRmGlobal, c->module, clk_pwr_client, NvRmVoltsUnspecified, NvRmVoltsUnspecified, NULL, 0, NULL); - if (e!=NvSuccess) + if (e!=NvSuccess) { + pr_err("%s: failed to voltage control %s\n", __func__, c->name); return -ENXIO; + } e = NvRmPowerModuleClockControl(s_hRmGlobal, c->module, clk_pwr_client, NV_TRUE); - if (e!=NvSuccess) + if (e!=NvSuccess) { + pr_err("%s: failed to clock control %s\n", __func__, c->name); return -ENXIO; + } return 0; } @@ -101,9 +105,13 @@ static int tegra_periph_clk_set_rate(struct clk *c, unsigned long rate) { NvError e; NvRmFreqKHz freq = rate / 1000; + NvRmFreqKHz min, max; + + min = freq - (freq>>4); + max = freq + (freq>>4); e = NvRmPowerModuleClockConfig(s_hRmGlobal, c->module, clk_pwr_client, - NvRmFreqUnspecified, NvRmFreqUnspecified, &freq, 1, &freq, 0); + min, max, &freq, 1, &freq, 0); if (e!=NvSuccess) { pr_debug("%s: failed to configure %s to %luHz\n", @@ -182,10 +190,10 @@ static struct clk tegra_periph_clk[] = { PERIPH_CLK("rtc", "rtc-tegra", Rtc, 0), PERIPH_CLK("kbc", "tegra-kbc", Kbc, 0), PERIPH_CLK("uarta", "uart.0", Uart, 0), - PERIPH_CLK("uartb", "uart.1", Uart, 0), - PERIPH_CLK("uartc", "uart.2", Uart, 0), - PERIPH_CLK("uartd", "uart.3", Uart, 0), - PERIPH_CLK("uarte", "uart.4", Uart, 0), + PERIPH_CLK("uartb", "uart.1", Uart, 1), + PERIPH_CLK("uartc", "uart.2", Uart, 2), + PERIPH_CLK("uartd", "uart.3", Uart, 3), + PERIPH_CLK("uarte", "uart.4", Uart, 4), }; static struct clk tegra_clk_cpu = { |