diff options
author | Simon Glass <sjg@chromium.org> | 2011-05-16 10:57:16 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-24 10:01:33 -0700 |
commit | 16016e7f644ba2301848f7769af6192cafc45c20 (patch) | |
tree | 8194afb175e3f5bcb278d8c270bc60ede11c1ad6 | |
parent | 85ef9e2437c06b70478013ac6203df5daaf79a29 (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.c | 15 | ||||
-rw-r--r-- | board/nvidia/common/board.h | 4 | ||||
-rw-r--r-- | board/nvidia/common/uart-spi-fix.c | 29 | ||||
-rw-r--r-- | common/fdt_decode.c | 47 | ||||
-rw-r--r-- | include/fdt_decode.h | 20 |
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); |