summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDongwoo Lee <dwoo08.lee@samsung.com>2019-05-08 21:03:47 +0900
committerJaehoon Chung <jh80.chung@samsung.com>2023-10-17 13:19:19 +0900
commitb84e5e2a9016f05470b2c9f1bb55617b065d5387 (patch)
tree91d54c77608cac40de833df65157c825a1277951 /drivers
parentbc4a88667f8232aaf1f2f63c882d62700463293d (diff)
downloadu-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.c58
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(&regs->lsr) & BCM283X_MU_LSR_RX_READY))
- return -EAGAIN;
+ while (readl(&regs->lsr) & BCM283X_MU_LSR_RX_READY) {
+ if (bcm283x_mu_rx_buffer_full(priv) || --max_count == 0)
+ break;
+
+ bcm283x_mu_rx_buffer_put(priv, readl(&regs->io));
+ }
- data = readl(&regs->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