summaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/ns16550.c25
-rw-r--r--drivers/serial/serial_omap.c56
2 files changed, 63 insertions, 18 deletions
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 3f6860f3916..c3b884b6d00 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -12,7 +12,6 @@
#include <log.h>
#include <ns16550.h>
#include <reset.h>
-#include <serial.h>
#include <spl.h>
#include <watchdog.h>
#include <asm/global_data.h>
@@ -158,7 +157,7 @@ static inline int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
#endif /* CONFIG_NS16550_DYNAMIC */
-static void ns16550_writeb(struct ns16550 *port, int offset, int value)
+void ns16550_writeb(struct ns16550 *port, int offset, int value)
{
struct ns16550_plat *plat = port->plat;
unsigned char *addr;
@@ -193,13 +192,6 @@ static u32 ns16550_getfcr(struct ns16550 *port)
return plat->fcr;
}
-/* We can clean these up once everything is moved to driver model */
-#define serial_out(value, addr) \
- ns16550_writeb(com_port, \
- (unsigned char *)addr - (unsigned char *)com_port, value)
-#define serial_in(addr) \
- ns16550_readb(com_port, \
- (unsigned char *)addr - (unsigned char *)com_port)
#else
static u32 ns16550_getfcr(struct ns16550 *port)
{
@@ -214,7 +206,7 @@ int ns16550_calc_divisor(struct ns16550 *port, int clock, int baudrate)
return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
}
-static void ns16550_setbrg(struct ns16550 *com_port, int baud_divisor)
+void ns16550_setbrg(struct ns16550 *com_port, int baud_divisor)
{
/* to keep serial format, read lcr before writing BKSE */
int lcr_val = serial_in(&com_port->lcr) & ~UART_LCR_BKSE;
@@ -380,7 +372,7 @@ DEBUG_UART_FUNCS
#endif
#if CONFIG_IS_ENABLED(DM_SERIAL)
-static int ns16550_serial_putc(struct udevice *dev, const char ch)
+int ns16550_serial_putc(struct udevice *dev, const char ch)
{
struct ns16550 *const com_port = dev_get_priv(dev);
@@ -400,7 +392,7 @@ static int ns16550_serial_putc(struct udevice *dev, const char ch)
return 0;
}
-static int ns16550_serial_pending(struct udevice *dev, bool input)
+int ns16550_serial_pending(struct udevice *dev, bool input)
{
struct ns16550 *const com_port = dev_get_priv(dev);
@@ -410,7 +402,7 @@ static int ns16550_serial_pending(struct udevice *dev, bool input)
return (serial_in(&com_port->lsr) & UART_LSR_THRE) ? 0 : 1;
}
-static int ns16550_serial_getc(struct udevice *dev)
+int ns16550_serial_getc(struct udevice *dev)
{
struct ns16550 *const com_port = dev_get_priv(dev);
@@ -420,7 +412,7 @@ static int ns16550_serial_getc(struct udevice *dev)
return serial_in(&com_port->rbr);
}
-static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
+int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
{
struct ns16550 *const com_port = dev_get_priv(dev);
struct ns16550_plat *plat = com_port->plat;
@@ -433,7 +425,7 @@ static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
return 0;
}
-static int ns16550_serial_setconfig(struct udevice *dev, uint serial_config)
+int ns16550_serial_setconfig(struct udevice *dev, uint serial_config)
{
struct ns16550 *const com_port = dev_get_priv(dev);
int lcr_val = UART_LCR_WLS_8;
@@ -466,8 +458,7 @@ static int ns16550_serial_setconfig(struct udevice *dev, uint serial_config)
return 0;
}
-static int ns16550_serial_getinfo(struct udevice *dev,
- struct serial_device_info *info)
+int ns16550_serial_getinfo(struct udevice *dev, struct serial_device_info *info)
{
struct ns16550 *const com_port = dev_get_priv(dev);
struct ns16550_plat *plat = com_port->plat;
diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c
index 94672655c28..224d9cbf29d 100644
--- a/drivers/serial/serial_omap.c
+++ b/drivers/serial/serial_omap.c
@@ -15,6 +15,12 @@
#include <clk.h>
#include <linux/err.h>
+/*
+ * These are the definitions for the MDR1 register
+ */
+#define UART_OMAP_MDR1_16X_MODE 0x00 /* UART 16x mode */
+#define UART_OMAP_MDR1_13X_MODE 0x03 /* UART 13x mode */
+
#ifndef CFG_SYS_NS16550_CLK
#define CFG_SYS_NS16550_CLK 0
#endif
@@ -151,6 +157,54 @@ static const struct udevice_id omap_serial_ids[] = {
};
#endif /* OF_REAL */
+static int omap_serial_calc_divisor(struct ns16550 *com_port, int clock, int baudrate)
+{
+ unsigned int div_13, div_16;
+ unsigned int abs_d13, abs_d16;
+ /*
+ * The below logic sets the MDR1 register based on clock and baudrate.
+ */
+ div_13 = DIV_ROUND_CLOSEST(clock, 13 * baudrate);
+ div_16 = DIV_ROUND_CLOSEST(clock, 16 * baudrate);
+
+ if (!div_13)
+ div_13 = 1;
+ if (!div_16)
+ div_16 = 1;
+
+ abs_d13 = abs(baudrate - clock / 13 / div_13);
+ abs_d16 = abs(baudrate - clock / 16 / div_16);
+
+ if (abs_d13 >= abs_d16)
+ serial_out(UART_OMAP_MDR1_16X_MODE, &com_port->mdr1);
+ else
+ serial_out(UART_OMAP_MDR1_13X_MODE, &com_port->mdr1);
+
+ return abs_d13 >= abs_d16 ? div_16 : div_13;
+}
+
+static int omap_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+ struct ns16550_plat *plat = com_port->plat;
+ int clock_divisor;
+
+ clock_divisor = omap_serial_calc_divisor(com_port, plat->clock, baudrate);
+
+ ns16550_setbrg(com_port, clock_divisor);
+
+ return 0;
+}
+
+const struct dm_serial_ops omap_serial_ops = {
+ .putc = ns16550_serial_putc,
+ .pending = ns16550_serial_pending,
+ .getc = ns16550_serial_getc,
+ .setbrg = omap_serial_setbrg,
+ .setconfig = ns16550_serial_setconfig,
+ .getinfo = ns16550_serial_getinfo,
+};
+
#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
U_BOOT_DRIVER(omap_serial) = {
.name = "omap_serial",
@@ -162,7 +216,7 @@ U_BOOT_DRIVER(omap_serial) = {
#endif
.priv_auto = sizeof(struct ns16550),
.probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
+ .ops = &omap_serial_ops,
#if !CONFIG_IS_ENABLED(OF_CONTROL)
.flags = DM_FLAG_PRE_RELOC,
#endif