diff options
author | Dongwoo Lee <dwoo08.lee@samsung.com> | 2019-05-08 21:03:47 +0900 |
---|---|---|
committer | Jaehoon Chung <jh80.chung@samsung.com> | 2023-10-17 13:19:19 +0900 |
commit | b84e5e2a9016f05470b2c9f1bb55617b065d5387 (patch) | |
tree | 91d54c77608cac40de833df65157c825a1277951 /drivers | |
parent | bc4a88667f8232aaf1f2f63c882d62700463293d (diff) | |
download | u-boot-b84e5e2a9016f05470b2c9f1bb55617b065d5387.tar.gz u-boot-b84e5e2a9016f05470b2c9f1bb55617b065d5387.tar.bz2 u-boot-b84e5e2a9016f05470b2c9f1bb55617b065d5387.zip |
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 <dwoo08.lee@samsung.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/serial_bcm283x_mu.c | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c index 7585f790d2..93f3657543 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; + + 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) @@ -186,6 +228,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 |