#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);
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)
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