* Copyright 2012, FranΓ§ois Revol, revol@free.fr.
* Distributed under the terms of the MIT License.
*
* Authors:
* FranΓ§ois Revol, revol@free.fr
* Alexander von Gluck IV, kallisti5@unixzen.com
*/
#include "fdt_serial.h"
#include <KernelExport.h>
#include <ByteOrder.h>
#include <ctype.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include <arch/generic/debug_uart_8250.h>
#if defined(__arm__)
#include <arch/arm/arch_uart_pl011.h>
#endif
extern "C" {
#include <fdt.h>
#include <libfdt.h>
#include <libfdt_env.h>
};
#include "fdt_support.h"
#ifdef TRACE_SERIAL
# define TRACE(x...) dprintf("INIT: " x)
#else
# define TRACE(x...) ;
#endif
DebugUART*
debug_uart_from_fdt(const void *fdt)
{
const char *name;
int node;
int len;
phys_addr_t regs;
int32 clock = 0;
int32 speed = 0;
const void *prop;
DebugUART *uart = NULL;
if (fdt == NULL)
return NULL;
name = fdt_get_alias(fdt, "serial");
if (name == NULL)
name = fdt_get_alias(fdt, "serial0");
if (name == NULL)
name = fdt_get_alias(fdt, "serial1");
if (name == NULL)
name = fdt_get_alias(fdt, "uart0");
if (name == NULL)
return NULL;
node = fdt_path_offset(fdt, name);
if (node < 0)
return NULL;
regs = fdt_get_device_reg(fdt, node, false);
if (regs == 0)
return NULL;
TRACE(("serial: using '%s', node %d @ %" B_PRIxPHYSADDR "\n",
name, node, regs));
prop = fdt_getprop(fdt, node, "clock-frequency", &len);
if (prop && len == 4) {
clock = fdt32_to_cpu(*(uint32_t *)prop);
TRACE(("serial: clock %ld\n", clock));
}
prop = fdt_getprop(fdt, node, "current-speed", &len);
if (prop && len == 4) {
speed = fdt32_to_cpu(*(uint32_t *)prop);
TRACE(("serial: speed %ld\n", speed));
}
if (fdt_node_check_compatible(fdt, node, "ns16550a") == 0
|| fdt_node_check_compatible(fdt, node, "ns16550") == 0) {
TRACE(("serial: Found 8250 serial UART!\n"));
uart = arch_get_uart_8250(regs, clock);
#if defined(__arm__)
} else if (fdt_node_check_compatible(fdt, node, "ti,omap3-uart") == 0
|| fdt_node_check_compatible(fdt, node, "ti,omap4-uart") == 0
|| fdt_node_check_compatible(fdt, node, "ti,omap5-uart") == 0
|| fdt_node_check_compatible(fdt, node, "ti,am3352-uart") == 0
|| fdt_node_check_compatible(fdt, node, "ti,am4372-uart") == 0
|| fdt_node_check_compatible(fdt, node, "ti,dra742-uart") == 0) {
TRACE(("serial: Found omap 8250 serial UART!\n"));
uart = arch_get_uart_8250_omap(regs, clock);
} else if (fdt_node_check_compatible(fdt, node, "arm,pl011") == 0
|| fdt_node_check_compatible(fdt, node, "arm,primecell") == 0) {
TRACE(("serial: Found pl011 serial UART!\n"));
uart = arch_get_uart_pl011(regs, clock);
#endif
} else {
return NULL;
}
return uart;
}