1 /*        $NetBSD: psc.c,v 1.11 2019/07/23 15:19:07 rin Exp $         */
2 
3 /*-
4  * Copyright (c) 1997 David Huang <khym@azeotrope.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 /*
29  * This handles registration/unregistration of PSC (Peripheral
30  * Subsystem Controller) interrupts. The PSC is used only on the
31  * Centris/Quadra 660av and the Quadra 840av.
32  */
33 
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: psc.c,v 1.11 2019/07/23 15:19:07 rin Exp $");
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 
40 #include <machine/bus.h>
41 #include <machine/cpu.h>
42 #include <machine/psc.h>
43 
44 static void         psc_kill_dma(void);
45 int                 psc_lev3_intr(void *);
46 static void         psc_lev3_noint(void *);
47 int                 psc_lev4_intr(void *);
48 static int          psc_lev4_noint(void *);
49 int                 psc_lev5_intr(void *);
50 static void         psc_lev5_noint(void *);
51 int                 psc_lev6_intr(void *);
52 static void         psc_lev6_noint(void *);
53 
54 static int          stop_read_psc_dma(int, int, uint32_t *);
55 static int          stop_write_psc_dma(int, int, uint32_t *);
56 
57 void      (*psc3_ihandler)(void *) = psc_lev3_noint;
58 void      *psc3_iarg;
59 
60 int (*psc4_itab[4])(void *) = {
61           psc_lev4_noint, /* 0 */
62           psc_lev4_noint, /* 1 */
63           psc_lev4_noint, /* 2 */
64           psc_lev4_noint  /* 3 */
65 };
66 
67 void *psc4_iarg[4] = {
68           (void *)0, (void *)1, (void *)2, (void *)3
69 };
70 
71 void (*psc5_itab[2])(void *) = {
72           psc_lev5_noint, /* 0 */
73           psc_lev5_noint  /* 1 */
74 };
75 
76 void *psc5_iarg[2] = {
77           (void *)0, (void *)1
78 };
79 
80 void (*psc6_itab[3])(void *) = {
81           psc_lev6_noint, /* 0 */
82           psc_lev6_noint, /* 1 */
83           psc_lev6_noint  /* 2 */
84 };
85 
86 void *psc6_iarg[3] = {
87           (void *)0, (void *)1, (void *)2
88 };
89 
90 /*
91  * Make excessively sure that all PSC DMA is shut down.
92  */
93 void
psc_kill_dma(void)94 psc_kill_dma(void)
95 {
96           int       i;
97 
98           for (i = 0; i < 9; i++) {
99                     psc_reg2(PSC_CTLBASE + (i << 4)) = 0x8800;
100                     psc_reg2(PSC_CTLBASE + (i << 4)) = 0x1000;
101                     psc_reg2(PSC_CMDBASE + (i << 5)) = 0x1100;
102                     psc_reg2(PSC_CMDBASE + (i << 5) + PSC_SET1) = 0x1100;
103           }
104 }
105 
106 /*
107  * Setup the interrupt vectors and disable most of the PSC interrupts
108  */
109 void
psc_init(void)110 psc_init(void)
111 {
112           int       s, i;
113 
114           /*
115            * Only Quadra AVs have a PSC.
116            */
117           if (current_mac_model->class == MACH_CLASSAV) {
118                     s = splhigh();
119                     psc_kill_dma();
120                     intr_establish(psc_lev3_intr, NULL, 3);
121                     intr_establish(psc_lev4_intr, NULL, 4);
122                     intr_establish(psc_lev5_intr, NULL, 5);
123                     intr_establish(psc_lev6_intr, NULL, 6);
124                     for (i = 3; i < 7; i++) {
125                               /* Clear any flags */
126                               psc_reg1(PSC_ISR_BASE + 0x10 * i) = 0x0F;
127                               /* Clear any interrupt enable */
128                               psc_reg1(PSC_IER_BASE + 0x10 * i) = 0x0F;
129                     }
130                     psc_reg1(PSC_LEV4_IER) = 0x86; /* enable SCC */
131                     splx(s);
132           }
133 }
134 
135 int
add_psc_lev3_intr(void (* handler)(void *),void * arg)136 add_psc_lev3_intr(void (*handler)(void *), void *arg)
137 {
138           int s;
139 
140           s = splhigh();
141 
142           psc3_ihandler = handler;
143           psc3_iarg = arg;
144 
145           splx(s);
146 
147           return 1;
148 }
149 
150 int
remove_psc_lev3_intr(void)151 remove_psc_lev3_intr(void)
152 {
153           return add_psc_lev3_intr(psc_lev3_noint, (void *)0);
154 }
155 
156 int
psc_lev3_intr(void * arg)157 psc_lev3_intr(void *arg)
158 {
159           u_int8_t intbits;
160 
161           while ((intbits = psc_reg1(PSC_LEV3_ISR)) != psc_reg1(PSC_LEV3_ISR))
162                     ;
163           intbits &= 0x1 & psc_reg1(PSC_LEV3_IER);
164 
165           if (intbits)
166                     psc3_ihandler(psc3_iarg);
167 
168           return 0;
169 }
170 
171 static void
psc_lev3_noint(void * arg)172 psc_lev3_noint(void *arg)
173 {
174           printf("psc_lev3_noint\n");
175 }
176 
177 int
psc_lev4_intr(void * arg)178 psc_lev4_intr(void *arg)
179 {
180           u_int8_t intbits, bitnum;
181           u_int mask;
182 
183           while ((intbits = psc_reg1(PSC_LEV4_ISR)) != psc_reg1(PSC_LEV4_ISR))
184                     ;
185           intbits &= 0xf & psc_reg1(PSC_LEV4_IER);
186 
187           mask = 1;
188           bitnum = 0;
189           do {
190                     if (intbits & mask)
191                               psc4_itab[bitnum](psc4_iarg[bitnum]);
192                     mask <<= 1;
193           } while (intbits >= mask && ++bitnum);
194 
195           return 0;
196 }
197 
198 int
add_psc_lev4_intr(int dev,int (* handler)(void *),void * arg)199 add_psc_lev4_intr(int dev, int (*handler)(void *), void *arg)
200 {
201           int s;
202 
203           if ((dev < 0) || (dev > 3))
204                     return 0;
205 
206           s = splhigh();
207 
208           psc4_itab[dev] = handler;
209           psc4_iarg[dev] = arg;
210 
211           splx(s);
212 
213           return 1;
214 }
215 
216 int
remove_psc_lev4_intr(int dev)217 remove_psc_lev4_intr(int dev)
218 {
219           return add_psc_lev4_intr(dev, psc_lev4_noint, (void *)dev);
220 }
221 
222 int
psc_lev4_noint(void * arg)223 psc_lev4_noint(void *arg)
224 {
225           printf("psc_lev4_noint: device %d\n", (int)arg);
226           return 0;
227 }
228 
229 int
psc_lev5_intr(void * arg)230 psc_lev5_intr(void *arg)
231 {
232           u_int8_t intbits, bitnum;
233           u_int mask;
234 
235           while ((intbits = psc_reg1(PSC_LEV5_ISR)) != psc_reg1(PSC_LEV5_ISR))
236                     ;
237           intbits &= 0x3 & psc_reg1(PSC_LEV5_IER);
238 
239           mask = 1;
240           bitnum = 0;
241           do {
242                     if (intbits & mask)
243                               psc5_itab[bitnum](psc5_iarg[bitnum]);
244                     mask <<= 1;
245           } while (intbits >= mask && ++bitnum);
246 
247           return 0;
248 }
249 
250 int
add_psc_lev5_intr(int dev,void (* handler)(void *),void * arg)251 add_psc_lev5_intr(int dev, void (*handler)(void *), void *arg)
252 {
253           int s;
254 
255           if ((dev < 0) || (dev > 1))
256                     return 0;
257 
258           s = splhigh();
259 
260           psc5_itab[dev] = handler;
261           psc5_iarg[dev] = arg;
262 
263           splx(s);
264 
265           return 1;
266 }
267 
268 int
remove_psc_lev5_intr(int dev)269 remove_psc_lev5_intr(int dev)
270 {
271           return add_psc_lev5_intr(dev, psc_lev5_noint, (void *)dev);
272 }
273 
274 void
psc_lev5_noint(void * arg)275 psc_lev5_noint(void *arg)
276 {
277           printf("psc_lev5_noint: device %d\n", (int)arg);
278 }
279 
280 int
psc_lev6_intr(void * arg)281 psc_lev6_intr(void *arg)
282 {
283           u_int8_t intbits, bitnum;
284           u_int mask;
285 
286           while ((intbits = psc_reg1(PSC_LEV6_ISR)) != psc_reg1(PSC_LEV6_ISR))
287                     ;
288           intbits &= 0x7 & psc_reg1(PSC_LEV6_IER);
289 
290           mask = 1;
291           bitnum = 0;
292           do {
293                     if (intbits & mask)
294                               psc6_itab[bitnum](psc6_iarg[bitnum]);
295                     mask <<= 1;
296           } while (intbits >= mask && ++bitnum);
297 
298           return 0;
299 }
300 
301 int
add_psc_lev6_intr(int dev,void (* handler)(void *),void * arg)302 add_psc_lev6_intr(int dev, void (*handler)(void *), void *arg)
303 {
304           int s;
305 
306           if ((dev < 0) || (dev > 2))
307                     return 0;
308 
309           s = splhigh();
310 
311           psc6_itab[dev] = handler;
312           psc6_iarg[dev] = arg;
313 
314           splx(s);
315 
316           return 1;
317 }
318 
319 int
remove_psc_lev6_intr(int dev)320 remove_psc_lev6_intr(int dev)
321 {
322           return add_psc_lev6_intr(dev, psc_lev6_noint, (void *)dev);
323 }
324 
325 void
psc_lev6_noint(void * arg)326 psc_lev6_noint(void *arg)
327 {
328           printf("psc_lev6_noint: device %d\n", (int)arg);
329 }
330 
331 /*
332  * DMA Control routines for esp(4).
333  * XXX Need to be merged with DMA engine of mc(4).
334  */
335 
336 int
start_psc_dma(int channel,int * rset,bus_addr_t addr,uint32_t len,int datain)337 start_psc_dma(int channel, int *rset, bus_addr_t addr, uint32_t len, int datain)
338 {
339           int chan_ctrl, rset_addr, rset_len, rset_cmd, s;
340 
341           s = splhigh();
342 
343           chan_ctrl = PSC_CTLBASE + (channel << 4);
344 
345           pause_psc_dma(channel);
346 
347           *rset = (psc_reg2(chan_ctrl) & 1) << 4;
348 
349           rset_addr = PSC_ADDRBASE + (0x20 * channel) + *rset;
350           rset_len = rset_addr + 4;
351           rset_cmd = rset_addr + 8;
352 
353           (void)psc_reg2(rset_cmd);
354           psc_reg4(rset_len) = len;
355           psc_reg4(rset_addr) = addr;
356 
357           if (datain)
358                     psc_reg2(rset_cmd) = 0x8200;
359           else
360                     psc_reg2(rset_cmd) = 0x200;
361 
362           psc_reg2(rset_cmd) = 0x100;
363           psc_reg2(rset_cmd) = 0x8800;
364           psc_reg2(chan_ctrl) = 0x400;
365 
366           splx(s);
367 
368           return 0;
369 }
370 
371 int
pause_psc_dma(int channel)372 pause_psc_dma(int channel)
373 {
374           int chan_ctrl, s;
375 
376           s = splhigh();
377 
378           chan_ctrl = PSC_CTLBASE + (channel << 4);
379 
380           psc_reg2(chan_ctrl) = 0x8400;
381 
382           while (!(psc_reg2(chan_ctrl) & 0x4000))
383                     continue;
384 
385           splx(s);
386 
387           return 0;
388 }
389 
390 int
wait_psc_dma(int channel,int rset,uint32_t * residual)391 wait_psc_dma(int channel, int rset, uint32_t *residual)
392 {
393           int rset_addr, rset_len, rset_cmd, s;
394 
395           s = splhigh();
396 
397           rset_addr = PSC_ADDRBASE + (0x20 * channel) + rset;
398           rset_len = rset_addr + 4;
399           rset_cmd = rset_addr + 8;
400 
401           while (!(psc_reg2(rset_cmd) & 0x100))
402                     continue;
403 
404           while (psc_reg2(rset_cmd) & 0x800)
405                     continue;
406 
407           *residual = psc_reg4(rset_len);
408 
409           splx(s);
410 
411           if (*residual)
412                     return -1;
413           else
414                     return 0;
415 }
416 
417 int
stop_psc_dma(int channel,int rset,uint32_t * residual,int datain)418 stop_psc_dma(int channel, int rset, uint32_t *residual, int datain)
419 {
420           int rval, s;
421 
422           s = splhigh();
423 
424           if (datain)
425                     rval = stop_read_psc_dma(channel, rset, residual);
426           else
427                     rval = stop_write_psc_dma(channel, rset, residual);
428 
429           splx(s);
430 
431           return rval;
432 }
433 
434 static int
stop_read_psc_dma(int channel,int rset,uint32_t * residual)435 stop_read_psc_dma(int channel, int rset, uint32_t *residual)
436 {
437           int chan_ctrl, rset_addr, rset_len, rset_cmd;
438 
439           chan_ctrl = PSC_CTLBASE + (channel << 4);
440           rset_addr = PSC_ADDRBASE + (0x20 * channel) + rset;
441           rset_len = rset_addr + 4;
442           rset_cmd = rset_addr + 8;
443 
444           if (psc_reg2(rset_cmd) & 0x400) {
445                     *residual = 0;
446                     return 0;
447           }
448 
449           psc_reg2(chan_ctrl) = 0x8200;
450 
451           while (psc_reg2(chan_ctrl) & 0x200)
452                     continue;
453 
454           pause_psc_dma(channel);
455 
456           *residual = psc_reg4(rset_len);
457           if (*residual == 0)
458                     return 0;
459 
460           do {
461                     psc_reg4(rset_len) = 0;
462           } while (psc_reg4(rset_len));
463 
464           return 0;
465 }
466 
467 static int
stop_write_psc_dma(int channel,int rset,uint32_t * residual)468 stop_write_psc_dma(int channel, int rset, uint32_t *residual)
469 {
470           int chan_ctrl, rset_addr, rset_len, rset_cmd;
471 
472           rset_addr = PSC_ADDRBASE + (0x20 * channel) + rset;
473           rset_cmd = rset_addr + 8;
474 
475           if (psc_reg2(rset_cmd) & 0x400) {
476                     *residual = 0;
477                     return 0;
478           }
479 
480           chan_ctrl = PSC_CTLBASE + (channel << 4);
481           rset_len = rset_addr + 4;
482 
483           pause_psc_dma(channel);
484 
485           *residual = psc_reg4(rset_len);
486 
487           psc_reg2(chan_ctrl) = 0x8800;
488 
489           return 0;
490 }
491