diff options
author | Dongwoo Lee <dwoo08.lee@samsung.com> | 2019-05-08 21:03:47 +0900 |
---|---|---|
committer | Dongwoo Lee <dwoo08.lee@samsung.com> | 2019-05-08 21:16:32 +0900 |
commit | e748adf178fcd378f87b8d6116e6a3c516100aa4 (patch) | |
tree | 676f13460f617753082db9c5acc659335f84442c | |
parent | 118b456bf17ac870afdb3ca3ee6e8ed94592935a (diff) | |
download | u-boot-e748adf178fcd378f87b8d6116e6a3c516100aa4.tar.gz u-boot-e748adf178fcd378f87b8d6116e6a3c516100aa4.tar.bz2 u-boot-e748adf178fcd378f87b8d6116e6a3c516100aa4.zip |
serial: bcm283x_mu: Support RX buffersubmit/tizen/20190509.014331accepted/tizen/unified/20190509.052830
Since mini uart has very small rx fifo, writing long string can
cause overrun. To prevent this, this patch appiles buffer for rx
process.
Change-Id: Ic5bd37875567fe51eb5491b8867f39c1a78de6b9
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
-rw-r--r-- | drivers/serial/serial_bcm283x_mu.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c index 606e233be7..5b88deb17d 100644 --- a/drivers/serial/serial_bcm283x_mu.c +++ b/drivers/serial/serial_bcm283x_mu.c @@ -48,8 +48,14 @@ struct bcm283x_mu_regs { #define BCM283X_MU_LSR_TX_EMPTY BIT(5) #define BCM283X_MU_LSR_RX_READY BIT(0) +#define BCM283X_MU_RX_BUFFER_LEN 1024 +#define BCM283X_MU_RX_BUFFER_INIT_POS -1 + struct bcm283x_mu_priv { struct bcm283x_mu_regs *regs; + int rx_buffer[BCM283X_MU_RX_BUFFER_LEN]; + int rx_buffer_in_pos; + int rx_buffer_out_pos; }; static int bcm283x_mu_serial_setbrg(struct udevice *dev, int baudrate) @@ -80,26 +86,65 @@ static int bcm283x_mu_serial_probe(struct udevice *dev) priv->regs = (struct bcm283x_mu_regs *)plat->base; + priv->rx_buffer_in_pos = BCM283X_MU_RX_BUFFER_INIT_POS; + priv->rx_buffer_out_pos = BCM283X_MU_RX_BUFFER_INIT_POS; + return 0; } +static inline int bcm283x_mu_rx_buffer_full(struct bcm283x_mu_priv *priv) +{ + return !!(priv->rx_buffer_in_pos == BCM283X_MU_RX_BUFFER_LEN - 1); +} + +static inline int bcm283x_mu_rx_buffer_empty(struct bcm283x_mu_priv *priv) +{ + return !!(priv->rx_buffer_out_pos == BCM283X_MU_RX_BUFFER_INIT_POS); +} + +static void bcm283x_mu_rx_buffer_put(struct bcm283x_mu_priv *priv, int data) +{ + if (bcm283x_mu_rx_buffer_empty(priv)) + priv->rx_buffer_out_pos++; + + priv->rx_buffer[++priv->rx_buffer_in_pos] = data; +} + +static int bcm283x_mu_rx_buffer_get(struct bcm283x_mu_priv *priv) +{ + int data = priv->rx_buffer[priv->rx_buffer_out_pos]; + + if (priv->rx_buffer_in_pos == priv->rx_buffer_out_pos) { + priv->rx_buffer_in_pos = BCM283X_MU_RX_BUFFER_INIT_POS; + priv->rx_buffer_out_pos = BCM283X_MU_RX_BUFFER_INIT_POS; + } else { + priv->rx_buffer_out_pos++; + } + + return data; +} + static int bcm283x_mu_serial_getc(struct udevice *dev) { struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev); struct bcm283x_mu_priv *priv = dev_get_priv(dev); struct bcm283x_mu_regs *regs = priv->regs; - u32 data; + int max_count = 256; if (plat->disabled) return -EAGAIN; - /* Wait until there is data in the FIFO */ - if (!(readl(®s->lsr) & BCM283X_MU_LSR_RX_READY)) - return -EAGAIN; + while (readl(®s->lsr) & BCM283X_MU_LSR_RX_READY) { + if (bcm283x_mu_rx_buffer_full(priv) || --max_count == 0) + break; + + bcm283x_mu_rx_buffer_put(priv, readl(®s->io)); + } - data = readl(®s->io); + if (bcm283x_mu_rx_buffer_empty(priv)) + return -EAGAIN; - return (int)data; + return (int)bcm283x_mu_rx_buffer_get(priv); } static int bcm283x_mu_serial_putc(struct udevice *dev, const char data) @@ -135,6 +180,9 @@ static int bcm283x_mu_serial_pending(struct udevice *dev, bool input) if (input) { WATCHDOG_RESET(); + if (!bcm283x_mu_rx_buffer_empty(priv)) + return 1; + return (lsr & BCM283X_MU_LSR_RX_READY) ? 1 : 0; } else { return (lsr & BCM283X_MU_LSR_TX_IDLE) ? 0 : 1; |