1 /* $NetBSD: wdc_obio.c,v 1.51 2008/04/28 20:23:27 martin Exp $ */
4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Onno van der Linden.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: wdc_obio.c,v 1.51 2008/04/28 20:23:27 martin Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/malloc.h>
40 #include <uvm/uvm_extern.h>
42 #include <machine/bus.h>
43 #include <machine/autoconf.h>
44 #include <machine/pio.h>
46 #include <dev/ata/atareg.h>
47 #include <dev/ata/atavar.h>
48 #include <dev/ic/wdcvar.h>
50 #include <dev/ofw/openfirm.h>
52 #include <macppc/dev/dbdma.h>
54 #define WDC_REG_NPORTS 8
55 #define WDC_AUXREG_OFFSET 0x16
56 #define WDC_DEFAULT_PIO_IRQ 13 /* XXX */
57 #define WDC_DEFAULT_DMA_IRQ 2 /* XXX */
59 #define WDC_OPTIONS_DMA 0x01
62 * XXX This code currently doesn't even try to allow 32-bit data port use.
65 struct wdc_obio_softc
{
66 struct wdc_softc sc_wdcdev
;
67 struct ata_channel
*sc_chanptr
;
68 struct ata_channel sc_channel
;
69 struct ata_queue sc_chqueue
;
70 struct wdc_regs sc_wdc_regs
;
71 bus_space_handle_t sc_dmaregh
;
72 dbdma_regmap_t
*sc_dmareg
;
73 dbdma_command_t
*sc_dmacmd
;
74 u_int sc_dmaconf
[2]; /* per target value of CONFIG_REG */
78 static int wdc_obio_match(device_t
, cfdata_t
, void *);
79 static void wdc_obio_attach(device_t
, device_t
, void *);
80 static int wdc_obio_detach(device_t
, int);
81 static int wdc_obio_dma_init(void *, int, int, void *, size_t, int);
82 static void wdc_obio_dma_start(void *, int, int);
83 static int wdc_obio_dma_finish(void *, int, int, int);
85 static void wdc_obio_select(struct ata_channel
*, int);
86 static void adjust_timing(struct ata_channel
*);
87 static void ata4_adjust_timing(struct ata_channel
*);
89 CFATTACH_DECL_NEW(wdc_obio
, sizeof(struct wdc_obio_softc
),
90 wdc_obio_match
, wdc_obio_attach
, wdc_obio_detach
, NULL
);
92 static const char * const ata_names
[] = {
100 wdc_obio_match(device_t parent
, cfdata_t match
, void *aux
)
102 struct confargs
*ca
= aux
;
104 /* XXX should not use name */
105 if (strcmp(ca
->ca_name
, "ATA") == 0 ||
106 strcmp(ca
->ca_name
, "ata") == 0 ||
107 strcmp(ca
->ca_name
, "ata0") == 0 ||
108 strcmp(ca
->ca_name
, "ide") == 0)
111 if (of_compatible(ca
->ca_node
, ata_names
) >= 0)
118 wdc_obio_attach(device_t parent
, device_t self
, void *aux
)
120 struct wdc_obio_softc
*sc
= device_private(self
);
121 struct wdc_regs
*wdr
;
122 struct confargs
*ca
= aux
;
123 struct ata_channel
*chp
= &sc
->sc_channel
;
124 int intr
, i
, type
= IST_EDGE
;
128 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
129 if (device_cfdata(sc
->sc_wdcdev
.sc_atac
.atac_dev
)->cf_flags
&
131 if (ca
->ca_nreg
>= 16 || ca
->ca_nintr
== -1)
132 use_dma
= 1; /* XXX Don't work yet. */
135 if (ca
->ca_nintr
>= 4 && ca
->ca_nreg
>= 8) {
136 intr
= ca
->ca_intr
[0];
137 aprint_normal(" irq %d", intr
);
138 if (ca
->ca_nintr
> 8) {
139 type
= ca
->ca_intr
[1] ? IST_LEVEL
: IST_EDGE
;
141 aprint_normal(", %s triggered", (type
== IST_EDGE
) ? "edge" : "level");
142 } else if (ca
->ca_nintr
== -1) {
143 intr
= WDC_DEFAULT_PIO_IRQ
;
144 aprint_normal(" irq property not found; using %d", intr
);
146 aprint_error(": couldn't get irq property\n");
151 aprint_normal(": DMA transfer");
155 sc
->sc_wdcdev
.regs
= wdr
= &sc
->sc_wdc_regs
;
157 wdr
->cmd_iot
= wdr
->ctl_iot
= ca
->ca_tag
;
159 if (bus_space_map(wdr
->cmd_iot
, ca
->ca_baseaddr
+ ca
->ca_reg
[0],
160 WDC_REG_NPORTS
<< 4, 0, &wdr
->cmd_baseioh
) ||
161 bus_space_subregion(wdr
->cmd_iot
, wdr
->cmd_baseioh
,
162 WDC_AUXREG_OFFSET
<< 4, 1, &wdr
->ctl_ioh
)) {
163 aprint_error_dev(self
, "couldn't map registers\n");
167 for (i
= 0; i
< WDC_NREG
; i
++) {
168 if (bus_space_subregion(wdr
->cmd_iot
, wdr
->cmd_baseioh
, i
<< 4,
169 i
== 0 ? 4 : 1, &wdr
->cmd_iohs
[i
]) != 0) {
170 bus_space_unmap(wdr
->cmd_iot
, wdr
->cmd_baseioh
,
171 WDC_REG_NPORTS
<< 4);
172 aprint_error_dev(self
,
173 "couldn't subregion registers\n");
178 wdr
->data32iot
= wdr
->cmd_iot
;
179 wdr
->data32ioh
= wdr
->cmd_ioh
;
182 sc
->sc_ih
= intr_establish(intr
, type
, IPL_BIO
, wdcintr
, chp
);
185 sc
->sc_dmacmd
= dbdma_alloc(sizeof(dbdma_command_t
) * 20);
188 * we don't use ca->ca_reg[3] for size here because at least
189 * on the PB3400c it says 0x200 for both IDE channels ( the
190 * one on the mainboard and the other on the mediabay ) but
191 * their start addresses are only 0x100 apart. Since those
192 * DMA registers are always 0x100 or less we don't really
193 * have to care though
195 if (bus_space_map(wdr
->cmd_iot
, ca
->ca_baseaddr
+ ca
->ca_reg
[2],
196 0x100, BUS_SPACE_MAP_LINEAR
, &sc
->sc_dmaregh
)) {
198 aprint_error_dev(self
,
199 "unable to map DMA registers (%08x)\n",
201 /* should unmap stuff here */
204 sc
->sc_dmareg
= bus_space_vaddr(wdr
->cmd_iot
, sc
->sc_dmaregh
);
206 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DMA
;
207 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 2;
208 if (strcmp(ca
->ca_name
, "ata-4") == 0) {
209 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_UDMA
;
210 sc
->sc_wdcdev
.sc_atac
.atac_udma_cap
= 4;
211 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
=
214 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= adjust_timing
;
217 /* Minimum cycle time is 150ns (DMA MODE 1) on ohare. */
219 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 3;
220 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 1;
224 /* all non-DMA controllers can use adjust_timing */
225 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= adjust_timing
;
228 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 4;
229 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DATA16
;
230 sc
->sc_chanptr
= chp
;
231 sc
->sc_wdcdev
.sc_atac
.atac_channels
= &sc
->sc_chanptr
;
232 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= 1;
233 sc
->sc_wdcdev
.dma_arg
= sc
;
234 sc
->sc_wdcdev
.dma_init
= wdc_obio_dma_init
;
235 sc
->sc_wdcdev
.dma_start
= wdc_obio_dma_start
;
236 sc
->sc_wdcdev
.dma_finish
= wdc_obio_dma_finish
;
238 chp
->ch_atac
= &sc
->sc_wdcdev
.sc_atac
;
239 chp
->ch_queue
= &sc
->sc_chqueue
;
242 wdc_init_shadow_regs(chp
);
244 #define OHARE_FEATURE_REG 0xf3000038
246 /* XXX Enable wdc1 by feature reg. */
247 memset(path
, 0, sizeof(path
));
248 OF_package_to_path(ca
->ca_node
, path
, sizeof(path
));
249 if (strcmp(path
, "/bandit@F2000000/ohare@10/ata@21000") == 0) {
252 x
= in32rb(OHARE_FEATURE_REG
);
254 out32rb(OHARE_FEATURE_REG
, x
);
260 /* Multiword DMA transfer timings */
262 int cycle
; /* minimum cycle time [ns] */
263 int active
; /* minimum command active time [ns] */
265 static const struct ide_timings pio_timing
[5] = {
266 { 600, 180 }, /* Mode 0 */
267 { 390, 150 }, /* 1 */
268 { 240, 105 }, /* 2 */
272 static const struct ide_timings dma_timing
[3] = {
273 { 480, 240 }, /* Mode 0 */
274 { 165, 90 }, /* Mode 1 */
275 { 120, 75 } /* Mode 2 */
278 static const struct ide_timings udma_timing
[5] = {
279 { 120, 180 }, /* Mode 0 */
280 { 90, 150 }, /* Mode 1 */
281 { 60, 120 }, /* Mode 2 */
282 { 45, 90 }, /* Mode 3 */
283 { 30, 90 } /* Mode 4 */
286 #define TIME_TO_TICK(time) howmany((time), 30)
287 #define PIO_REC_OFFSET 4
288 #define PIO_REC_MIN 1
289 #define PIO_ACT_MIN 1
290 #define DMA_REC_OFFSET 1
291 #define DMA_REC_MIN 1
292 #define DMA_ACT_MIN 1
294 #define ATA4_TIME_TO_TICK(time) howmany((time), 15) /* 15 ns clock */
296 #define CONFIG_REG (0x200) /* IDE access timing register */
299 wdc_obio_select(struct ata_channel
*chp
, int drive
)
301 struct wdc_obio_softc
*sc
= (struct wdc_obio_softc
*)chp
->ch_atac
;
302 struct wdc_regs
*wdr
= CHAN_TO_WDC_REGS(chp
);
304 bus_space_write_4(wdr
->cmd_iot
, wdr
->cmd_baseioh
,
305 CONFIG_REG
, sc
->sc_dmaconf
[drive
]);
309 adjust_timing(struct ata_channel
*chp
)
311 struct wdc_obio_softc
*sc
= (struct wdc_obio_softc
*)chp
->ch_atac
;
313 int min_cycle
= 0, min_active
= 0;
314 int cycle_tick
= 0, act_tick
= 0, inact_tick
= 0, half_tick
;
316 for (drive
= 0; drive
< 2; drive
++) {
318 struct ata_drive_datas
*drvp
;
320 drvp
= &chp
->ch_drive
[drive
];
321 /* set up pio mode timings */
322 if (drvp
->drive_flags
& DRIVE
) {
323 int piomode
= drvp
->PIO_mode
;
324 min_cycle
= pio_timing
[piomode
].cycle
;
325 min_active
= pio_timing
[piomode
].active
;
327 cycle_tick
= TIME_TO_TICK(min_cycle
);
328 act_tick
= TIME_TO_TICK(min_active
);
329 if (act_tick
< PIO_ACT_MIN
)
330 act_tick
= PIO_ACT_MIN
;
331 inact_tick
= cycle_tick
- act_tick
- PIO_REC_OFFSET
;
332 if (inact_tick
< PIO_REC_MIN
)
333 inact_tick
= PIO_REC_MIN
;
334 /* mask: 0x000007ff */
335 conf
|= (inact_tick
<< 5) | act_tick
;
337 /* Set up DMA mode timings */
338 if (drvp
->drive_flags
& DRIVE_DMA
) {
339 int dmamode
= drvp
->DMA_mode
;
340 min_cycle
= dma_timing
[dmamode
].cycle
;
341 min_active
= dma_timing
[dmamode
].active
;
342 cycle_tick
= TIME_TO_TICK(min_cycle
);
343 act_tick
= TIME_TO_TICK(min_active
);
344 inact_tick
= cycle_tick
- act_tick
- DMA_REC_OFFSET
;
345 if (inact_tick
< DMA_REC_MIN
)
346 inact_tick
= DMA_REC_MIN
;
347 half_tick
= 0; /* XXX */
348 /* mask: 0xfffff800 */
351 (inact_tick
<< 16) | (act_tick
<< 11);
355 printf("conf[%d] = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
356 drive
, conf
, cycle_tick
, min_cycle
, act_tick
, min_active
, inact_tick
);
359 sc
->sc_dmaconf
[drive
] = conf
;
361 sc
->sc_wdcdev
.select
= 0;
362 if (sc
->sc_dmaconf
[0]) {
363 wdc_obio_select(chp
,0);
364 if (sc
->sc_dmaconf
[1] &&
365 (sc
->sc_dmaconf
[0] != sc
->sc_dmaconf
[1])) {
366 sc
->sc_wdcdev
.select
= wdc_obio_select
;
368 } else if (sc
->sc_dmaconf
[1]) {
369 wdc_obio_select(chp
,1);
374 ata4_adjust_timing(struct ata_channel
*chp
)
376 struct wdc_obio_softc
*sc
= (struct wdc_obio_softc
*)chp
->ch_atac
;
378 int min_cycle
= 0, min_active
= 0;
379 int cycle_tick
= 0, act_tick
= 0, inact_tick
= 0;
381 for (drive
= 0; drive
< 2; drive
++) {
383 struct ata_drive_datas
*drvp
;
385 drvp
= &chp
->ch_drive
[drive
];
386 /* set up pio mode timings */
388 if (drvp
->drive_flags
& DRIVE
) {
389 int piomode
= drvp
->PIO_mode
;
390 min_cycle
= pio_timing
[piomode
].cycle
;
391 min_active
= pio_timing
[piomode
].active
;
393 cycle_tick
= ATA4_TIME_TO_TICK(min_cycle
);
394 act_tick
= ATA4_TIME_TO_TICK(min_active
);
395 inact_tick
= cycle_tick
- act_tick
;
396 /* mask: 0x000003ff */
397 conf
|= (inact_tick
<< 5) | act_tick
;
399 /* set up dma mode timings */
400 if (drvp
->drive_flags
& DRIVE_DMA
) {
401 int dmamode
= drvp
->DMA_mode
;
402 min_cycle
= dma_timing
[dmamode
].cycle
;
403 min_active
= dma_timing
[dmamode
].active
;
404 cycle_tick
= ATA4_TIME_TO_TICK(min_cycle
);
405 act_tick
= ATA4_TIME_TO_TICK(min_active
);
406 inact_tick
= cycle_tick
- act_tick
;
407 /* mask: 0x001ffc00 */
408 conf
|= (act_tick
<< 10) | (inact_tick
<< 15);
410 /* set up udma mode timings */
411 if (drvp
->drive_flags
& DRIVE_UDMA
) {
412 int udmamode
= drvp
->UDMA_mode
;
413 min_cycle
= udma_timing
[udmamode
].cycle
;
414 min_active
= udma_timing
[udmamode
].active
;
415 act_tick
= ATA4_TIME_TO_TICK(min_active
);
416 cycle_tick
= ATA4_TIME_TO_TICK(min_cycle
);
417 /* mask: 0x1ff00000 */
418 conf
|= (cycle_tick
<< 21) | (act_tick
<< 25) | 0x100000;
422 printf("ata4 conf[%d] = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
423 drive
, conf
, cycle_tick
, min_cycle
, act_tick
, min_active
, inact_tick
);
426 sc
->sc_dmaconf
[drive
] = conf
;
428 sc
->sc_wdcdev
.select
= 0;
429 if (sc
->sc_dmaconf
[0]) {
430 wdc_obio_select(chp
,0);
431 if (sc
->sc_dmaconf
[1] &&
432 (sc
->sc_dmaconf
[0] != sc
->sc_dmaconf
[1])) {
433 sc
->sc_wdcdev
.select
= wdc_obio_select
;
435 } else if (sc
->sc_dmaconf
[1]) {
436 wdc_obio_select(chp
,1);
441 wdc_obio_detach(device_t self
, int flags
)
443 struct wdc_obio_softc
*sc
= device_private(self
);
446 if ((error
= wdcdetach(self
, flags
)) != 0)
449 intr_disestablish(sc
->sc_ih
);
451 /* Unmap our i/o space. */
452 bus_space_unmap(sc
->sc_wdcdev
.regs
->cmd_iot
,
453 sc
->sc_wdcdev
.regs
->cmd_baseioh
, WDC_REG_NPORTS
<< 4);
455 /* Unmap DMA registers. */
456 bus_space_unmap(sc
->sc_wdcdev
.regs
->cmd_iot
, sc
->sc_dmaregh
, 0x100);
457 free(sc
->sc_dmacmd
, M_DEVBUF
);
463 wdc_obio_dma_init(void *v
, int channel
, int drive
, void *databuf
,
464 size_t datalen
, int flags
)
466 struct wdc_obio_softc
*sc
= v
;
467 vaddr_t va
= (vaddr_t
)databuf
;
468 dbdma_command_t
*cmdp
;
470 int read
= flags
& WDC_DMA_READ
;
472 cmdp
= sc
->sc_dmacmd
;
473 cmd
= read
? DBDMA_CMD_IN_MORE
: DBDMA_CMD_OUT_MORE
;
475 offset
= va
& PGOFSET
;
477 /* if va is not page-aligned, setup the first page */
479 int rest
= PAGE_SIZE
- offset
; /* the rest of the page */
481 if (datalen
> rest
) { /* if continues to next page */
482 DBDMA_BUILD(cmdp
, cmd
, 0, rest
, vtophys(va
),
483 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
,
491 /* now va is page-aligned */
492 while (datalen
> PAGE_SIZE
) {
493 DBDMA_BUILD(cmdp
, cmd
, 0, PAGE_SIZE
, vtophys(va
),
494 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
495 datalen
-= PAGE_SIZE
;
500 /* the last page (datalen <= PAGE_SIZE here) */
501 cmd
= read
? DBDMA_CMD_IN_LAST
: DBDMA_CMD_OUT_LAST
;
502 DBDMA_BUILD(cmdp
, cmd
, 0, datalen
, vtophys(va
),
503 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
506 DBDMA_BUILD(cmdp
, DBDMA_CMD_STOP
, 0, 0, 0,
507 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
513 wdc_obio_dma_start(void *v
, int channel
, int drive
)
515 struct wdc_obio_softc
*sc
= v
;
517 dbdma_start(sc
->sc_dmareg
, sc
->sc_dmacmd
);
521 wdc_obio_dma_finish(void *v
, int channel
, int drive
, int read
)
523 struct wdc_obio_softc
*sc
= v
;
525 dbdma_stop(sc
->sc_dmareg
);