Merge patch series "UART support for higher baudrate"

Gokul Praveen <g-praveen@ti.com> says:

The OMAP specific UART driver is changed from a generic implementation of
certain ops functions to an OMAP specific implementation of it to add
support for higher baudrates for OMAP devices.

Hence to support the above change, static functionality of ops functions
in generic ns16550 UART U-Boot driver is removed and also migrated certain
macros to its header file for usage in device-specific drivers.

Boot logs link :

https://gist.github.com/GOKU-THUG/8b90117c963e5da5c1b6caeee427c82c

Link: https://lore.kernel.org/r/20241126105131.43359-1-g-praveen@ti.com
This commit is contained in:
Tom Rini 2024-12-14 09:33:03 -06:00
commit 6b01124f7c
3 changed files with 81 additions and 18 deletions

View file

@ -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;

View file

@ -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

View file

@ -25,6 +25,7 @@
#define __ns16550_h
#include <linux/types.h>
#include <serial.h>
#if CONFIG_IS_ENABLED(DM_SERIAL) || defined(CONFIG_NS16550_DYNAMIC) || \
defined(CONFIG_DEBUG_UART)
@ -116,6 +117,15 @@ struct ns16550 {
#endif
};
#if CONFIG_IS_ENABLED(DM_SERIAL)
#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)
#endif
#define thr rbr
#define iir fcr
#define dll rbr
@ -225,6 +235,14 @@ void ns16550_putc(struct ns16550 *com_port, char c);
char ns16550_getc(struct ns16550 *com_port);
int ns16550_tstc(struct ns16550 *com_port);
void ns16550_reinit(struct ns16550 *com_port, int baud_divisor);
int ns16550_serial_putc(struct udevice *dev, const char ch);
int ns16550_serial_pending(struct udevice *dev, bool input);
int ns16550_serial_getc(struct udevice *dev);
int ns16550_serial_setbrg(struct udevice *dev, int baudrate);
int ns16550_serial_setconfig(struct udevice *dev, uint serial_config);
int ns16550_serial_getinfo(struct udevice *dev, struct serial_device_info *info);
void ns16550_writeb(struct ns16550 *port, int offset, int value);
void ns16550_setbrg(struct ns16550 *com_port, int baud_divisor);
/**
* ns16550_calc_divisor() - calculate the divisor given clock and baud rate