summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2011-05-16 10:57:16 -0700
committerSimon Glass <sjg@chromium.org>2011-08-24 10:01:33 -0700
commit16016e7f644ba2301848f7769af6192cafc45c20 (patch)
tree8194afb175e3f5bcb278d8c270bc60ede11c1ad6
parent85ef9e2437c06b70478013ac6203df5daaf79a29 (diff)
fdt: Use device tree to provide SPI switch details
Rather than having the Seaboard SPI/UART switch in CONFIG options in the header files, use the device tree to configure this BUG=chromium-os:11623 TEST=build and boot U-Boot on Seaboard Change-Id: If3b92b685b5fe31a97ef4bc3578a6aa00208d827 Reviewed-on: http://gerrit.chromium.org/gerrit/1661 Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Simon Glass <sjg@chromium.org>
-rw-r--r--board/nvidia/common/board.c15
-rw-r--r--board/nvidia/common/board.h4
-rw-r--r--board/nvidia/common/uart-spi-fix.c29
-rw-r--r--common/fdt_decode.c47
-rw-r--r--include/fdt_decode.h20
5 files changed, 89 insertions, 26 deletions
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index e68dcfdfeba..679ac3ded32 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -145,14 +145,15 @@ static void pinmux_init(int uart_ids)
pin_mux_uart(uart_ids);
}
-/*
- * Routine: gpio_init
- * Description: Do individual peripheral GPIO configs
+/**
+ * Do individual peripheral GPIO configs
+ *
+ * @param blob FDT blob with configuration information
*/
-static void gpio_init(void)
+static void gpio_init(const void *blob)
{
#ifdef CONFIG_SPI_UART_SWITCH
- gpio_early_init_uart();
+ gpio_early_init_uart(blob);
#endif
}
@@ -168,7 +169,7 @@ int board_init(void)
gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
#ifdef CONFIG_SPI_UART_SWITCH
- gpio_config_uart();
+ gpio_config_uart(gd->blob);
#endif
#ifdef CONFIG_USB_EHCI_TEGRA
board_usb_init();
@@ -204,7 +205,7 @@ int board_early_init_f(void)
pinmux_init(uart_ids);
/* Initialize periph GPIOs */
- gpio_init();
+ gpio_init(gd->blob);
return 0;
}
diff --git a/board/nvidia/common/board.h b/board/nvidia/common/board.h
index 5c23d41b10b..c406c892298 100644
--- a/board/nvidia/common/board.h
+++ b/board/nvidia/common/board.h
@@ -25,7 +25,7 @@
#define _BOARD_H_
void tegra2_start(void);
-void gpio_config_uart(void);
-void gpio_early_init_uart(void);
+void gpio_config_uart(const void *blob);
+void gpio_early_init_uart(const void *blob);
#endif /* BOARD_H */
diff --git a/board/nvidia/common/uart-spi-fix.c b/board/nvidia/common/uart-spi-fix.c
index 4f022158c4b..051f7492304 100644
--- a/board/nvidia/common/uart-spi-fix.c
+++ b/board/nvidia/common/uart-spi-fix.c
@@ -24,6 +24,7 @@
#include <asm/io.h>
#include <ns16550.h>
#include <libfdt.h>
+#include <fdt_decode.h>
#include <fdt_support.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/gpio.h>
@@ -41,20 +42,14 @@ enum spi_uart_switch {
SWITCH_BOTH
};
-/* Information about the spi/uart switch */
-struct spi_uart {
- int gpio; /* GPIO to control switch */
- NS16550_t regs; /* Address of UART affected */
- u32 port; /* Port number of UART affected */
-};
-
-static struct spi_uart local;
+static struct fdt_spi_uart local;
static enum spi_uart_switch switch_pos; /* Current switch position */
-
-static void get_config(struct spi_uart *config)
+static void get_config(const void *blob, struct fdt_spi_uart *config)
{
-#if defined CONFIG_SPI_CORRUPTS_UART
+#ifdef CONFIG_OF_CONTROL
+ fdt_decode_get_spi_switch(blob, config);
+#elif defined CONFIG_SPI_CORRUPTS_UART
config->gpio = UART_DISABLE_GPIO;
config->regs = (NS16550_t)CONFIG_SPI_CORRUPTS_UART;
config->port = CONFIG_SPI_CORRUPTS_UART_NR;
@@ -67,11 +62,11 @@ static void get_config(struct spi_uart *config)
* Init the UART / SPI switch. This can be called before relocation so we must
* not access BSS.
*/
-void gpio_early_init_uart(void)
+void gpio_early_init_uart(const void *blob)
{
- struct spi_uart config;
+ struct fdt_spi_uart config;
- get_config(&config);
+ get_config(blob, &config);
if (config.gpio != -1)
gpio_direction_output(config.gpio, 0);
switch_pos = SWITCH_BOTH;
@@ -80,9 +75,9 @@ void gpio_early_init_uart(void)
/*
* Configure the UART / SPI switch.
*/
-void gpio_config_uart(void)
+void gpio_config_uart(const void *blob)
{
- get_config(&local);
+ get_config(blob, &local);
switch_pos = SWITCH_BOTH;
if (local.gpio != -1) {
gpio_direction_output(local.gpio, 0);
@@ -92,7 +87,7 @@ void gpio_config_uart(void)
#ifdef CONFIG_SPI_UART_SWITCH
-static void spi_uart_switch(struct spi_uart *config,
+static void spi_uart_switch(struct fdt_spi_uart *config,
enum spi_uart_switch new_pos)
{
if (switch_pos == SWITCH_BOTH || new_pos == switch_pos)
diff --git a/common/fdt_decode.c b/common/fdt_decode.c
index d316d918d86..6af6af9907b 100644
--- a/common/fdt_decode.c
+++ b/common/fdt_decode.c
@@ -31,6 +31,7 @@
*/
static struct fdt_compat compat_types[] = {
{ COMPAT_UNKNOWN, "<none>" },
+ { COMPAT_SPI_UART_SWITCH, "spi-uart-select" },
};
/**
@@ -99,6 +100,28 @@ static s32 get_int(const void *blob, int node, const char *prop_name,
}
/**
+ * Look up a phandle and follow it to its node. Then return the offset
+ * of that node.
+ *
+ * @param blob FDT blob
+ * @param node node to examine
+ * @param prop_name name of property to find
+ * @return node offset if found, -ve error code on error
+ */
+static int lookup_phandle(const void *blob, int node, const char *prop_name)
+{
+ const u32 *phandle;
+ int lookup;
+
+ phandle = fdt_getprop(blob, node, prop_name, NULL);
+ if (!phandle)
+ return -FDT_ERR_NOTFOUND;
+
+ lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle));
+ return lookup;
+}
+
+/**
* Checks whether a node is enabled.
* This looks for a 'status' property. If this exists, then returns 1 if
* the status is 'ok' and 0 otherwise. If there is no status property,
@@ -164,3 +187,27 @@ enum fdt_compat_id fdt_decode_lookup(const void *blob, int node)
return id;
return COMPAT_UNKNOWN;
}
+
+int fdt_decode_get_spi_switch(const void *blob, struct fdt_spi_uart *config)
+{
+ int node, uart_node;
+ const u32 *gpio;
+
+ node = fdt_node_offset_by_compatible(blob, 0,
+ "nvidia,spi-uart-switch");
+ if (node < 0)
+ return node;
+
+ uart_node = lookup_phandle(blob, node, "uart");
+ if (uart_node < 0)
+ return uart_node;
+ config->port = get_int(blob, uart_node, "id", -1);
+ if (config->port == -1)
+ return -FDT_ERR_NOTFOUND;
+ config->gpio = -1;
+ config->regs = (NS16550_t)get_addr(blob, uart_node, "reg");
+ gpio = fdt_getprop(blob, node, "gpios", NULL);
+ if (gpio)
+ config->gpio = fdt32_to_cpu(gpio[1]);
+ return 0;
+}
diff --git a/include/fdt_decode.h b/include/fdt_decode.h
index 303d5a8d332..7f9c1d5821e 100644
--- a/include/fdt_decode.h
+++ b/include/fdt_decode.h
@@ -28,6 +28,8 @@
* changes to support FDT are minimized.
*/
+#include <ns16550.h>
+
/* A typedef for a physical address. We should move it to a generic place */
#ifdef CONFIG_PHYS_64BIT
typedef u64 addr_t;
@@ -46,6 +48,7 @@ typedef u32 addr_t;
*/
enum fdt_compat_id {
COMPAT_UNKNOWN,
+ COMPAT_SPI_UART_SWITCH, /* SPI / UART switch */
COMPAT_COUNT,
};
@@ -71,6 +74,13 @@ struct fdt_uart {
enum fdt_compat_id compat; /* our selected driver */
};
+/* Information about the spi/uart switch */
+struct fdt_spi_uart {
+ int gpio; /* GPIO to control switch */
+ NS16550_t regs; /* Address of UART affected */
+ u32 port; /* Port number of UART affected */
+};
+
/**
* Return information from the FDT about the console UART. This looks for
* an alias node called 'console' which must point to a UART. It then reads
@@ -115,3 +125,13 @@ void fdt_decode_uart_calc_divisor(struct fdt_uart *uart);
* determining which driver will implement the decide described by the node.
*/
enum fdt_compat_id fdt_decode_lookup(const void *blob, int node);
+
+/**
+ * Returns information from the FDT about the SPI / UART switch on tegra
+ * platforms.
+ *
+ * @param blob FDT blob to use
+ * @param config structure to use to return information
+ * @returns 0 on success, -ve on error, in which case config is unchanged
+ */
+int fdt_decode_get_spi_switch(const void *blob, struct fdt_spi_uart *config);