diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/ns16550.c | 25 | ||||
-rw-r--r-- | drivers/serial/serial_omap.c | 56 |
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 |