mal.c revision 1.4 1 1.4 rin /* $NetBSD: mal.c,v 1.4 2021/02/27 20:43:58 rin Exp $ */
2 1.1 kiyohara /*
3 1.1 kiyohara * Copyright (c) 2010 KIYOHARA Takashi
4 1.1 kiyohara * All rights reserved.
5 1.1 kiyohara *
6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without
7 1.1 kiyohara * modification, are permitted provided that the following conditions
8 1.1 kiyohara * are met:
9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright
10 1.1 kiyohara * notice, this list of conditions and the following disclaimer.
11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the
13 1.1 kiyohara * documentation and/or other materials provided with the distribution.
14 1.1 kiyohara *
15 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE.
26 1.1 kiyohara */
27 1.1 kiyohara
28 1.1 kiyohara #include <sys/cdefs.h>
29 1.4 rin __KERNEL_RCSID(0, "$NetBSD: mal.c,v 1.4 2021/02/27 20:43:58 rin Exp $");
30 1.1 kiyohara
31 1.1 kiyohara #include <sys/param.h>
32 1.1 kiyohara #include <sys/device.h>
33 1.2 matt #include <sys/cpu.h>
34 1.2 matt #include <sys/intr.h>
35 1.1 kiyohara
36 1.2 matt #include <powerpc/ibm4xx/cpu.h>
37 1.1 kiyohara #include <powerpc/ibm4xx/dcr4xx.h>
38 1.1 kiyohara #include <powerpc/ibm4xx/dev/if_emacvar.h>
39 1.1 kiyohara #include <powerpc/ibm4xx/dev/malvar.h>
40 1.1 kiyohara #include <powerpc/ibm4xx/spr.h>
41 1.1 kiyohara
42 1.3 matt #define STAT_TO_CHAN(stat) __builtin_clz(stat)
43 1.1 kiyohara
44 1.1 kiyohara
45 1.1 kiyohara static int mal_txeob_intr(void *);
46 1.1 kiyohara static int mal_rxeob_intr(void *);
47 1.1 kiyohara static int mal_txde_intr(void *);
48 1.1 kiyohara static int mal_rxde_intr(void *);
49 1.1 kiyohara static int mal_serr_intr(void *);
50 1.1 kiyohara
51 1.1 kiyohara
52 1.1 kiyohara const static struct maltbl {
53 1.1 kiyohara int pvr;
54 1.1 kiyohara int intrs[5];
55 1.1 kiyohara int flags;
56 1.1 kiyohara #define MAL_GEN2 (1<<0) /* Generation 2 (405EX/EXr/440GP/GX/SP/SPe) */
57 1.1 kiyohara } maltbl[] = { /* TXEOB RXEOB TXDE RXDE SERR */
58 1.1 kiyohara { IBM405GP, { 11, 12, 13, 14, 10 }, 0 },
59 1.1 kiyohara { IBM405GPR, { 11, 12, 13, 14, 10 }, 0 },
60 1.1 kiyohara { AMCC405EX, { 10, 11, 32+ 1, 32+ 2, 32+ 0 }, MAL_GEN2 },
61 1.1 kiyohara };
62 1.1 kiyohara
63 1.1 kiyohara /* Max channel is 4 on 440GX. Others is 2 or 1. */
64 1.1 kiyohara static void *iargs[4];
65 1.1 kiyohara
66 1.1 kiyohara
67 1.1 kiyohara void
68 1.1 kiyohara mal_attach(int pvr)
69 1.1 kiyohara {
70 1.1 kiyohara int i, to;
71 1.1 kiyohara
72 1.1 kiyohara for (i = 0; i < __arraycount(maltbl); i++)
73 1.1 kiyohara if (maltbl[i].pvr == pvr)
74 1.1 kiyohara break;
75 1.1 kiyohara if (i == __arraycount(maltbl)) {
76 1.1 kiyohara aprint_error("%s: unknwon pvr 0x%x\n", __func__, pvr);
77 1.1 kiyohara return;
78 1.1 kiyohara }
79 1.1 kiyohara
80 1.1 kiyohara /*
81 1.1 kiyohara * Reset MAL.
82 1.1 kiyohara * We wait for the completion of reset in maximums for five seconds.
83 1.1 kiyohara */
84 1.1 kiyohara mtdcr(DCR_MAL0_CFG, MAL0_CFG_SR);
85 1.1 kiyohara to = 0;
86 1.1 kiyohara while (mfdcr(DCR_MAL0_CFG) & MAL0_CFG_SR) {
87 1.1 kiyohara if (to > 5000) {
88 1.1 kiyohara aprint_error("%s: Soft reset failed\n", __func__);
89 1.1 kiyohara return;
90 1.1 kiyohara }
91 1.1 kiyohara delay(1000); /* delay 1m sec */
92 1.1 kiyohara to++;
93 1.1 kiyohara }
94 1.1 kiyohara
95 1.1 kiyohara /* establish MAL interrupts */
96 1.4 rin intr_establish_xname(maltbl[i].intrs[0], IST_LEVEL, IPL_NET,
97 1.4 rin mal_txeob_intr, NULL, "mal txeob");
98 1.4 rin intr_establish_xname(maltbl[i].intrs[1], IST_LEVEL, IPL_NET,
99 1.4 rin mal_rxeob_intr, NULL, "mal rxeob");
100 1.4 rin intr_establish_xname(maltbl[i].intrs[2], IST_LEVEL, IPL_NET,
101 1.4 rin mal_txde_intr, NULL, "mal txde");
102 1.4 rin intr_establish_xname(maltbl[i].intrs[3], IST_LEVEL, IPL_NET,
103 1.4 rin mal_rxde_intr, NULL, "mal rxde");
104 1.4 rin intr_establish_xname(maltbl[i].intrs[4], IST_LEVEL, IPL_NET,
105 1.4 rin mal_serr_intr, NULL, "mal serr");
106 1.1 kiyohara
107 1.1 kiyohara /* Set the MAL configuration register */
108 1.1 kiyohara if (maltbl[i].flags & MAL_GEN2)
109 1.1 kiyohara mtdcr(DCR_MAL0_CFG,
110 1.1 kiyohara MAL0_CFG_RMBS_32 |
111 1.1 kiyohara MAL0_CFG_WMBS_32 |
112 1.1 kiyohara MAL0_CFG_PLBLT |
113 1.1 kiyohara MAL0_CFG_EOPIE |
114 1.1 kiyohara MAL0_CFG_PLBB |
115 1.1 kiyohara MAL0_CFG_OPBBL |
116 1.1 kiyohara MAL0_CFG_LEA |
117 1.1 kiyohara MAL0_CFG_SD);
118 1.1 kiyohara else
119 1.1 kiyohara mtdcr(DCR_MAL0_CFG,
120 1.1 kiyohara MAL0_CFG_PLBLT |
121 1.1 kiyohara MAL0_CFG_PLBB |
122 1.1 kiyohara MAL0_CFG_OPBBL |
123 1.1 kiyohara MAL0_CFG_LEA |
124 1.1 kiyohara MAL0_CFG_SD);
125 1.1 kiyohara
126 1.1 kiyohara /* Enable MAL SERR Interrupt */
127 1.1 kiyohara mtdcr(DCR_MAL0_IER,
128 1.1 kiyohara MAL0_IER_PT |
129 1.1 kiyohara MAL0_IER_PRE |
130 1.1 kiyohara MAL0_IER_PWE |
131 1.1 kiyohara MAL0_IER_DE |
132 1.1 kiyohara MAL0_IER_NWE |
133 1.1 kiyohara MAL0_IER_TO |
134 1.1 kiyohara MAL0_IER_OPB |
135 1.1 kiyohara MAL0_IER_PLB);
136 1.1 kiyohara }
137 1.1 kiyohara
138 1.1 kiyohara static int
139 1.1 kiyohara mal_txeob_intr(void *arg)
140 1.1 kiyohara {
141 1.1 kiyohara uint32_t tcei;
142 1.1 kiyohara int chan, handled = 0;
143 1.1 kiyohara
144 1.1 kiyohara while ((tcei = mfdcr(DCR_MAL0_TXEOBISR))) {
145 1.1 kiyohara chan = STAT_TO_CHAN(tcei);
146 1.1 kiyohara if (iargs[chan] != NULL) {
147 1.1 kiyohara mtdcr(DCR_MAL0_TXEOBISR, MAL0__XCAR_CHAN(chan));
148 1.1 kiyohara handled |= emac_txeob_intr(iargs[chan]);
149 1.1 kiyohara }
150 1.1 kiyohara }
151 1.1 kiyohara return handled;
152 1.1 kiyohara }
153 1.1 kiyohara
154 1.1 kiyohara static int
155 1.1 kiyohara mal_rxeob_intr(void *arg)
156 1.1 kiyohara {
157 1.1 kiyohara uint32_t rcei;
158 1.1 kiyohara int chan, handled = 0;
159 1.1 kiyohara
160 1.1 kiyohara while ((rcei = mfdcr(DCR_MAL0_RXEOBISR))) {
161 1.1 kiyohara chan = STAT_TO_CHAN(rcei);
162 1.1 kiyohara if (iargs[chan] != NULL) {
163 1.1 kiyohara /* Clear the interrupt */
164 1.1 kiyohara mtdcr(DCR_MAL0_RXEOBISR, MAL0__XCAR_CHAN(chan));
165 1.1 kiyohara
166 1.1 kiyohara handled |= emac_rxeob_intr(iargs[chan]);
167 1.1 kiyohara }
168 1.1 kiyohara }
169 1.1 kiyohara return handled;
170 1.1 kiyohara }
171 1.1 kiyohara
172 1.1 kiyohara static int
173 1.1 kiyohara mal_txde_intr(void *arg)
174 1.1 kiyohara {
175 1.1 kiyohara uint32_t txde;
176 1.1 kiyohara int chan, handled = 0;
177 1.1 kiyohara
178 1.1 kiyohara while ((txde = mfdcr(DCR_MAL0_TXDEIR))) {
179 1.1 kiyohara chan = STAT_TO_CHAN(txde);
180 1.1 kiyohara if (iargs[chan] != NULL) {
181 1.1 kiyohara handled |= emac_txde_intr(iargs[chan]);
182 1.1 kiyohara
183 1.1 kiyohara /* Clear the interrupt */
184 1.1 kiyohara mtdcr(DCR_MAL0_TXDEIR, MAL0__XCAR_CHAN(chan));
185 1.1 kiyohara }
186 1.1 kiyohara }
187 1.1 kiyohara return handled;
188 1.1 kiyohara }
189 1.1 kiyohara
190 1.1 kiyohara static int
191 1.1 kiyohara mal_rxde_intr(void *arg)
192 1.1 kiyohara {
193 1.1 kiyohara uint32_t rxde;
194 1.1 kiyohara int chan, handled = 0;
195 1.1 kiyohara
196 1.1 kiyohara while ((rxde = mfdcr(DCR_MAL0_RXDEIR))) {
197 1.1 kiyohara chan = STAT_TO_CHAN(rxde);
198 1.1 kiyohara if (iargs[chan] != NULL) {
199 1.1 kiyohara handled |= emac_rxde_intr(iargs[chan]);
200 1.1 kiyohara
201 1.1 kiyohara /* Clear the interrupt */
202 1.1 kiyohara mtdcr(DCR_MAL0_RXDEIR, MAL0__XCAR_CHAN(chan));
203 1.1 kiyohara
204 1.1 kiyohara /* Reenable the receive channel */
205 1.1 kiyohara mtdcr(DCR_MAL0_RXCASR, MAL0__XCAR_CHAN(chan));
206 1.1 kiyohara }
207 1.1 kiyohara }
208 1.1 kiyohara return handled;
209 1.1 kiyohara }
210 1.1 kiyohara
211 1.1 kiyohara static int
212 1.1 kiyohara mal_serr_intr(void *arg)
213 1.1 kiyohara {
214 1.1 kiyohara uint32_t esr;
215 1.1 kiyohara
216 1.1 kiyohara esr = mfdcr(DCR_MAL0_ESR);
217 1.1 kiyohara
218 1.1 kiyohara /* not yet... */
219 1.1 kiyohara aprint_error("MAL SERR: ESR 0x%08x\n", esr);
220 1.1 kiyohara
221 1.1 kiyohara /* Clear the interrupt status bits. */
222 1.1 kiyohara mtdcr(DCR_MAL0_ESR, esr);
223 1.1 kiyohara
224 1.1 kiyohara return 1;
225 1.1 kiyohara }
226 1.1 kiyohara
227 1.1 kiyohara
228 1.1 kiyohara void
229 1.1 kiyohara mal_intr_establish(int chan, void *arg)
230 1.1 kiyohara {
231 1.1 kiyohara
232 1.1 kiyohara if (chan >= __arraycount(iargs))
233 1.1 kiyohara panic("MAL channel %d not support (max %d)\n",
234 1.1 kiyohara chan, __arraycount(iargs));
235 1.1 kiyohara
236 1.1 kiyohara iargs[chan] = arg;
237 1.1 kiyohara }
238 1.1 kiyohara
239 1.1 kiyohara int
240 1.1 kiyohara mal_start(int chan, uint32_t cdtxaddr, uint32_t cdrxaddr)
241 1.1 kiyohara {
242 1.1 kiyohara
243 1.1 kiyohara /*
244 1.1 kiyohara * Give the transmit and receive rings to the MAL.
245 1.1 kiyohara * And set the receive channel buffer size (in units of 16 bytes).
246 1.1 kiyohara */
247 1.1 kiyohara #if MCLBYTES > (4096 - 16) /* XXX! */
248 1.1 kiyohara # error MCLBYTES > max rx channel buffer size
249 1.1 kiyohara #endif
250 1.1 kiyohara /* The mtdcr() allows only the constant in the first argument... */
251 1.1 kiyohara switch (chan) {
252 1.1 kiyohara case 0:
253 1.1 kiyohara mtdcr(DCR_MAL0_TXCTP0R, cdtxaddr);
254 1.1 kiyohara mtdcr(DCR_MAL0_RXCTP0R, cdrxaddr);
255 1.1 kiyohara mtdcr(DCR_MAL0_RCBS0, MCLBYTES / 16);
256 1.1 kiyohara break;
257 1.1 kiyohara
258 1.1 kiyohara case 1:
259 1.1 kiyohara mtdcr(DCR_MAL0_TXCTP1R, cdtxaddr);
260 1.1 kiyohara mtdcr(DCR_MAL0_RXCTP1R, cdrxaddr);
261 1.1 kiyohara mtdcr(DCR_MAL0_RCBS1, MCLBYTES / 16);
262 1.1 kiyohara break;
263 1.1 kiyohara
264 1.1 kiyohara case 2:
265 1.1 kiyohara mtdcr(DCR_MAL0_TXCTP2R, cdtxaddr);
266 1.1 kiyohara mtdcr(DCR_MAL0_RXCTP2R, cdrxaddr);
267 1.1 kiyohara mtdcr(DCR_MAL0_RCBS2, MCLBYTES / 16);
268 1.1 kiyohara break;
269 1.1 kiyohara
270 1.1 kiyohara case 3:
271 1.1 kiyohara mtdcr(DCR_MAL0_TXCTP3R, cdtxaddr);
272 1.1 kiyohara mtdcr(DCR_MAL0_RXCTP3R, cdrxaddr);
273 1.1 kiyohara mtdcr(DCR_MAL0_RCBS3, MCLBYTES / 16);
274 1.1 kiyohara break;
275 1.1 kiyohara
276 1.1 kiyohara default:
277 1.1 kiyohara aprint_error("MAL unknown channel no.%d\n", chan);
278 1.1 kiyohara return EINVAL;
279 1.1 kiyohara }
280 1.1 kiyohara
281 1.1 kiyohara /* Enable the transmit and receive channel on the MAL. */
282 1.1 kiyohara mtdcr(DCR_MAL0_RXCASR, MAL0__XCAR_CHAN(chan));
283 1.1 kiyohara mtdcr(DCR_MAL0_TXCASR, MAL0__XCAR_CHAN(chan));
284 1.1 kiyohara
285 1.1 kiyohara return 0;
286 1.1 kiyohara }
287 1.1 kiyohara
288 1.1 kiyohara void
289 1.1 kiyohara mal_stop(int chan)
290 1.1 kiyohara {
291 1.1 kiyohara
292 1.1 kiyohara /* Disable the receive and transmit channels. */
293 1.1 kiyohara mtdcr(DCR_MAL0_RXCARR, MAL0__XCAR_CHAN(chan));
294 1.1 kiyohara mtdcr(DCR_MAL0_TXCARR, MAL0__XCAR_CHAN(chan));
295 1.1 kiyohara }
296