1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Altera TSE SGDMA and MSGDMA Linux driver |
3 | * Copyright (C) 2014 Altera Corporation. All rights reserved |
4 | */ |
5 | |
6 | #include <linux/netdevice.h> |
7 | #include "altera_utils.h" |
8 | #include "altera_tse.h" |
9 | #include "altera_msgdmahw.h" |
10 | #include "altera_msgdma.h" |
11 | |
12 | /* No initialization work to do for MSGDMA */ |
13 | int msgdma_initialize(struct altera_tse_private *priv) |
14 | { |
15 | return 0; |
16 | } |
17 | |
18 | void msgdma_uninitialize(struct altera_tse_private *priv) |
19 | { |
20 | } |
21 | |
22 | void msgdma_start_rxdma(struct altera_tse_private *priv) |
23 | { |
24 | } |
25 | |
26 | void msgdma_reset(struct altera_tse_private *priv) |
27 | { |
28 | int counter; |
29 | |
30 | /* Reset Rx mSGDMA */ |
31 | csrwr32(MSGDMA_CSR_STAT_MASK, mac: priv->rx_dma_csr, |
32 | msgdma_csroffs(status)); |
33 | csrwr32(MSGDMA_CSR_CTL_RESET, mac: priv->rx_dma_csr, |
34 | msgdma_csroffs(control)); |
35 | |
36 | counter = 0; |
37 | while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { |
38 | if (tse_bit_is_clear(ioaddr: priv->rx_dma_csr, msgdma_csroffs(status), |
39 | MSGDMA_CSR_STAT_RESETTING)) |
40 | break; |
41 | udelay(1); |
42 | } |
43 | |
44 | if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) |
45 | netif_warn(priv, drv, priv->dev, |
46 | "TSE Rx mSGDMA resetting bit never cleared!\n" ); |
47 | |
48 | /* clear all status bits */ |
49 | csrwr32(MSGDMA_CSR_STAT_MASK, mac: priv->rx_dma_csr, msgdma_csroffs(status)); |
50 | |
51 | /* Reset Tx mSGDMA */ |
52 | csrwr32(MSGDMA_CSR_STAT_MASK, mac: priv->tx_dma_csr, |
53 | msgdma_csroffs(status)); |
54 | |
55 | csrwr32(MSGDMA_CSR_CTL_RESET, mac: priv->tx_dma_csr, |
56 | msgdma_csroffs(control)); |
57 | |
58 | counter = 0; |
59 | while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { |
60 | if (tse_bit_is_clear(ioaddr: priv->tx_dma_csr, msgdma_csroffs(status), |
61 | MSGDMA_CSR_STAT_RESETTING)) |
62 | break; |
63 | udelay(1); |
64 | } |
65 | |
66 | if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) |
67 | netif_warn(priv, drv, priv->dev, |
68 | "TSE Tx mSGDMA resetting bit never cleared!\n" ); |
69 | |
70 | /* clear all status bits */ |
71 | csrwr32(MSGDMA_CSR_STAT_MASK, mac: priv->tx_dma_csr, msgdma_csroffs(status)); |
72 | } |
73 | |
74 | void msgdma_disable_rxirq(struct altera_tse_private *priv) |
75 | { |
76 | tse_clear_bit(ioaddr: priv->rx_dma_csr, msgdma_csroffs(control), |
77 | MSGDMA_CSR_CTL_GLOBAL_INTR); |
78 | } |
79 | |
80 | void msgdma_enable_rxirq(struct altera_tse_private *priv) |
81 | { |
82 | tse_set_bit(ioaddr: priv->rx_dma_csr, msgdma_csroffs(control), |
83 | MSGDMA_CSR_CTL_GLOBAL_INTR); |
84 | } |
85 | |
86 | void msgdma_disable_txirq(struct altera_tse_private *priv) |
87 | { |
88 | tse_clear_bit(ioaddr: priv->tx_dma_csr, msgdma_csroffs(control), |
89 | MSGDMA_CSR_CTL_GLOBAL_INTR); |
90 | } |
91 | |
92 | void msgdma_enable_txirq(struct altera_tse_private *priv) |
93 | { |
94 | tse_set_bit(ioaddr: priv->tx_dma_csr, msgdma_csroffs(control), |
95 | MSGDMA_CSR_CTL_GLOBAL_INTR); |
96 | } |
97 | |
98 | void msgdma_clear_rxirq(struct altera_tse_private *priv) |
99 | { |
100 | csrwr32(MSGDMA_CSR_STAT_IRQ, mac: priv->rx_dma_csr, msgdma_csroffs(status)); |
101 | } |
102 | |
103 | void msgdma_clear_txirq(struct altera_tse_private *priv) |
104 | { |
105 | csrwr32(MSGDMA_CSR_STAT_IRQ, mac: priv->tx_dma_csr, msgdma_csroffs(status)); |
106 | } |
107 | |
108 | /* return 0 to indicate transmit is pending */ |
109 | int msgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) |
110 | { |
111 | csrwr32(lower_32_bits(buffer->dma_addr), mac: priv->tx_dma_desc, |
112 | msgdma_descroffs(read_addr_lo)); |
113 | csrwr32(upper_32_bits(buffer->dma_addr), mac: priv->tx_dma_desc, |
114 | msgdma_descroffs(read_addr_hi)); |
115 | csrwr32(val: 0, mac: priv->tx_dma_desc, msgdma_descroffs(write_addr_lo)); |
116 | csrwr32(val: 0, mac: priv->tx_dma_desc, msgdma_descroffs(write_addr_hi)); |
117 | csrwr32(val: buffer->len, mac: priv->tx_dma_desc, msgdma_descroffs(len)); |
118 | csrwr32(val: 0, mac: priv->tx_dma_desc, msgdma_descroffs(burst_seq_num)); |
119 | csrwr32(MSGDMA_DESC_TX_STRIDE, mac: priv->tx_dma_desc, |
120 | msgdma_descroffs(stride)); |
121 | csrwr32(MSGDMA_DESC_CTL_TX_SINGLE, mac: priv->tx_dma_desc, |
122 | msgdma_descroffs(control)); |
123 | return 0; |
124 | } |
125 | |
126 | u32 msgdma_tx_completions(struct altera_tse_private *priv) |
127 | { |
128 | u32 ready = 0; |
129 | u32 inuse; |
130 | u32 status; |
131 | |
132 | /* Get number of sent descriptors */ |
133 | inuse = csrrd32(mac: priv->tx_dma_csr, msgdma_csroffs(rw_fill_level)) |
134 | & 0xffff; |
135 | |
136 | if (inuse) { /* Tx FIFO is not empty */ |
137 | ready = max_t(int, |
138 | priv->tx_prod - priv->tx_cons - inuse - 1, 0); |
139 | } else { |
140 | /* Check for buffered last packet */ |
141 | status = csrrd32(mac: priv->tx_dma_csr, msgdma_csroffs(status)); |
142 | if (status & MSGDMA_CSR_STAT_BUSY) |
143 | ready = priv->tx_prod - priv->tx_cons - 1; |
144 | else |
145 | ready = priv->tx_prod - priv->tx_cons; |
146 | } |
147 | return ready; |
148 | } |
149 | |
150 | /* Put buffer to the mSGDMA RX FIFO |
151 | */ |
152 | void msgdma_add_rx_desc(struct altera_tse_private *priv, |
153 | struct tse_buffer *rxbuffer) |
154 | { |
155 | u32 len = priv->rx_dma_buf_sz; |
156 | dma_addr_t dma_addr = rxbuffer->dma_addr; |
157 | u32 control = (MSGDMA_DESC_CTL_END_ON_EOP |
158 | | MSGDMA_DESC_CTL_END_ON_LEN |
159 | | MSGDMA_DESC_CTL_TR_COMP_IRQ |
160 | | MSGDMA_DESC_CTL_EARLY_IRQ |
161 | | MSGDMA_DESC_CTL_TR_ERR_IRQ |
162 | | MSGDMA_DESC_CTL_GO); |
163 | |
164 | csrwr32(val: 0, mac: priv->rx_dma_desc, msgdma_descroffs(read_addr_lo)); |
165 | csrwr32(val: 0, mac: priv->rx_dma_desc, msgdma_descroffs(read_addr_hi)); |
166 | csrwr32(lower_32_bits(dma_addr), mac: priv->rx_dma_desc, |
167 | msgdma_descroffs(write_addr_lo)); |
168 | csrwr32(upper_32_bits(dma_addr), mac: priv->rx_dma_desc, |
169 | msgdma_descroffs(write_addr_hi)); |
170 | csrwr32(val: len, mac: priv->rx_dma_desc, msgdma_descroffs(len)); |
171 | csrwr32(val: 0, mac: priv->rx_dma_desc, msgdma_descroffs(burst_seq_num)); |
172 | csrwr32(val: 0x00010001, mac: priv->rx_dma_desc, msgdma_descroffs(stride)); |
173 | csrwr32(val: control, mac: priv->rx_dma_desc, msgdma_descroffs(control)); |
174 | } |
175 | |
176 | /* status is returned on upper 16 bits, |
177 | * length is returned in lower 16 bits |
178 | */ |
179 | u32 msgdma_rx_status(struct altera_tse_private *priv) |
180 | { |
181 | u32 rxstatus = 0; |
182 | u32 pktlength; |
183 | u32 pktstatus; |
184 | |
185 | if (csrrd32(mac: priv->rx_dma_csr, msgdma_csroffs(resp_fill_level)) |
186 | & 0xffff) { |
187 | pktlength = csrrd32(mac: priv->rx_dma_resp, |
188 | msgdma_respoffs(bytes_transferred)); |
189 | pktstatus = csrrd32(mac: priv->rx_dma_resp, |
190 | msgdma_respoffs(status)); |
191 | rxstatus = pktstatus; |
192 | rxstatus = rxstatus << 16; |
193 | rxstatus |= (pktlength & 0xffff); |
194 | } |
195 | return rxstatus; |
196 | } |
197 | |