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