summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-05-18 14:00:33 -0700
committerGary King <gking@nvidia.com>2010-05-18 19:54:10 -0700
commit24796a8d8fde4371d518922d2a0006af7e0f389c (patch)
tree68bec5b916080109d42be4eaf0847dac6f6fa6af
parent19e0d62cd31e070836492c6dd3ce28d99ef5f29e (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/Makefile1
-rw-r--r--arch/arm/mach-tegra/board-generic.c2
-rw-r--r--arch/arm/mach-tegra/board-nvodm.c130
-rw-r--r--arch/arm/mach-tegra/clock_nvrm.c22
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 = {