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