From: Dongwoo Lee Date: Wed, 8 May 2019 12:03:47 +0000 (+0900) Subject: serial: bcm283x_mu: Support RX buffer X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b0ccdc7daaf890b61b09e799441a8ac04ecdb2d6;p=platform%2Fkernel%2Fu-boot.git serial: bcm283x_mu: Support RX buffer 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 Signed-off-by: Jaehoon Chung --- diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c index 58fa722..179bc36 100644 --- a/drivers/serial/serial_bcm283x_mu.c +++ b/drivers/serial/serial_bcm283x_mu.c @@ -47,8 +47,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_getc(struct udevice *dev); @@ -75,19 +81,55 @@ out: 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_priv *priv = dev_get_priv(dev); struct bcm283x_mu_regs *regs = priv->regs; - u32 data; + int max_count = 256; - /* 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; - data = readl(®s->io); + bcm283x_mu_rx_buffer_put(priv, 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) @@ -115,6 +157,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; @@ -186,6 +231,10 @@ 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; } #endif