summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-11-10 18:00:20 -0700
committerSimon Glass <sjg@chromium.org>2014-11-21 07:24:11 +0100
commit469a579df2907a421afec06e37d50e61b7d80227 (patch)
tree6c122952681674360e6360b0d6d923c6741824e3
parenta9f04d49e519383f98689d603facdee227a2f94d (diff)
dm: serial: Move current serial port pointer to global_data
In general we can't store things in the data section until we have inited SDRAM. Some platforms allow this (e.g. those with SPL) but some don't. Move the pointer to global_data so that it will work on all platforms. Without this fix the serial port will not work prior to relocation with driver model on some platforms. Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--drivers/serial/serial-uclass.c35
-rw-r--r--include/asm-generic/global_data.h1
2 files changed, 20 insertions, 16 deletions
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 71f1a5cb91..0f019c8f50 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -19,15 +19,14 @@
DECLARE_GLOBAL_DATA_PTR;
-/* The currently-selected console serial device */
-struct udevice *cur_dev __attribute__ ((section(".data")));
-
#ifndef CONFIG_SYS_MALLOC_F_LEN
#error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
#endif
static void serial_find_console_or_panic(void)
{
+ struct udevice *dev;
+
#ifdef CONFIG_OF_CONTROL
int node;
@@ -35,18 +34,21 @@ static void serial_find_console_or_panic(void)
node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path");
if (node < 0)
node = fdtdec_get_alias_node(gd->fdt_blob, "console");
- if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev))
+ if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) {
+ gd->cur_serial_dev = dev;
return;
+ }
/*
* If the console is not marked to be bound before relocation, bind
* it anyway.
*/
if (node > 0 &&
- !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) {
- if (!device_probe(cur_dev))
+ !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) {
+ if (!device_probe(dev)) {
+ gd->cur_serial_dev = dev;
return;
- cur_dev = NULL;
+ }
}
#endif
/*
@@ -61,11 +63,12 @@ static void serial_find_console_or_panic(void)
#else
#define INDEX 0
#endif
- if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) &&
- uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) &&
- (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
+ if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) &&
+ uclass_get_device(UCLASS_SERIAL, INDEX, &dev) &&
+ (uclass_first_device(UCLASS_SERIAL, &dev) || !dev))
panic("No serial driver found");
#undef INDEX
+ gd->cur_serial_dev = dev;
}
/* Called prior to relocation */
@@ -127,30 +130,30 @@ static int _serial_tstc(struct udevice *dev)
void serial_putc(char ch)
{
- _serial_putc(cur_dev, ch);
+ _serial_putc(gd->cur_serial_dev, ch);
}
void serial_puts(const char *str)
{
- _serial_puts(cur_dev, str);
+ _serial_puts(gd->cur_serial_dev, str);
}
int serial_getc(void)
{
- return _serial_getc(cur_dev);
+ return _serial_getc(gd->cur_serial_dev);
}
int serial_tstc(void)
{
- return _serial_tstc(cur_dev);
+ return _serial_tstc(gd->cur_serial_dev);
}
void serial_setbrg(void)
{
- struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ struct dm_serial_ops *ops = serial_get_ops(gd->cur_serial_dev);
if (ops->setbrg)
- ops->setbrg(cur_dev, gd->baudrate);
+ ops->setbrg(gd->cur_serial_dev, gd->baudrate);
}
void serial_stdio_init(void)
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 74df210033..f61acbc4fc 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -91,6 +91,7 @@ typedef struct global_data {
unsigned long malloc_limit; /* limit address */
unsigned long malloc_ptr; /* current address */
#endif
+ struct udevice *cur_serial_dev; /* current serial device */
struct arch_global_data arch; /* architecture-specific data */
} gd_t;
#endif