From: Dongwoo Lee Date: Wed, 8 May 2019 12:03:47 +0000 (+0900) Subject: serial: bcm283x_mu: Support RX buffer X-Git-Tag: accepted/tizen/unified/20241126.175211~459 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5800898a19a9f74bd13f81a795a587d1fc510c6d;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 7fa26244b1..e89056502b 100644 --- a/drivers/serial/serial_bcm283x_mu.c +++ b/drivers/serial/serial_bcm283x_mu.c @@ -46,8 +46,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); @@ -74,19 +80,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; + + 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) @@ -185,6 +227,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