+static void msgdma_reset(struct msgdma_csr *csr)
+{
+ u32 status;
+ ulong ctime;
+
+ /* Reset mSGDMA */
+ writel(MSGDMA_CSR_STAT_MASK, &csr->status);
+ writel(MSGDMA_CSR_CTL_RESET, &csr->control);
+ ctime = get_timer(0);
+ while (1) {
+ status = readl(&csr->status);
+ if (!(status & MSGDMA_CSR_STAT_RESETTING))
+ break;
+ if (get_timer(ctime) > ALT_TSE_SW_RESET_TIMEOUT) {
+ debug("Reset msgdma timeout\n");
+ break;
+ }
+ }
+ /* Clear status */
+ writel(MSGDMA_CSR_STAT_MASK, &csr->status);
+}
+
+static u32 msgdma_wait(struct msgdma_csr *csr)
+{
+ u32 status;
+ ulong ctime;
+
+ /* Wait for the descriptor to complete */
+ ctime = get_timer(0);
+ while (1) {
+ status = readl(&csr->status);
+ if (!(status & MSGDMA_CSR_STAT_BUSY))
+ break;
+ if (get_timer(ctime) > ALT_TSE_SGDMA_BUSY_TIMEOUT) {
+ debug("sgdma timeout\n");
+ break;
+ }
+ }
+ /* Clear status */
+ writel(MSGDMA_CSR_STAT_MASK, &csr->status);
+
+ return status;
+}
+
+static int altera_tse_send_msgdma(struct udevice *dev, void *packet,
+ int length)
+{
+ struct altera_tse_priv *priv = dev_get_priv(dev);
+ struct msgdma_extended_desc *desc = priv->tx_desc;
+ u32 tx_buf = virt_to_phys(packet);
+ u32 status;
+
+ writel(tx_buf, &desc->read_addr_lo);
+ writel(0, &desc->read_addr_hi);
+ writel(0, &desc->write_addr_lo);
+ writel(0, &desc->write_addr_hi);
+ writel(length, &desc->len);
+ writel(0, &desc->burst_seq_num);
+ writel(MSGDMA_DESC_TX_STRIDE, &desc->stride);
+ writel(MSGDMA_DESC_CTL_TX_SINGLE, &desc->control);
+ status = msgdma_wait(priv->sgdma_tx);
+ debug("sent %d bytes, status %08x\n", length, status);
+
+ return 0;
+}
+
+static int altera_tse_recv_msgdma(struct udevice *dev, int flags,
+ uchar **packetp)
+{
+ struct altera_tse_priv *priv = dev_get_priv(dev);
+ struct msgdma_csr *csr = priv->sgdma_rx;
+ struct msgdma_response *resp = priv->rx_resp;
+ u32 level, length, status;
+
+ level = readl(&csr->resp_fill_level);
+ if (level & 0xffff) {
+ length = readl(&resp->bytes_transferred);
+ status = readl(&resp->status);
+ debug("recv %d bytes, status %08x\n", length, status);
+ *packetp = priv->rx_buf;
+
+ return length;
+ }
+
+ return -EAGAIN;
+}
+
+static int altera_tse_free_pkt_msgdma(struct udevice *dev, uchar *packet,
+ int length)
+{
+ struct altera_tse_priv *priv = dev_get_priv(dev);
+ struct msgdma_extended_desc *desc = priv->rx_desc;
+ u32 rx_buf = virt_to_phys(priv->rx_buf);
+
+ writel(0, &desc->read_addr_lo);
+ writel(0, &desc->read_addr_hi);
+ writel(rx_buf, &desc->write_addr_lo);
+ writel(0, &desc->write_addr_hi);
+ writel(PKTSIZE_ALIGN, &desc->len);
+ writel(0, &desc->burst_seq_num);
+ writel(MSGDMA_DESC_RX_STRIDE, &desc->stride);
+ writel(MSGDMA_DESC_CTL_RX_SINGLE, &desc->control);
+ debug("recv setup\n");
+
+ return 0;
+}
+
+static void altera_tse_stop_msgdma(struct udevice *dev)
+{
+ struct altera_tse_priv *priv = dev_get_priv(dev);
+
+ msgdma_reset(priv->sgdma_rx);
+ msgdma_reset(priv->sgdma_tx);