Home | History | Annotate | Line # | Download | only in imx
imx23_apbdma.c revision 1.3.14.1
      1  1.3.14.1  skrll /* $Id: imx23_apbdma.c,v 1.3.14.1 2015/04/06 15:17:52 skrll Exp $ */
      2       1.1  jkunz 
      3       1.1  jkunz /*
      4       1.1  jkunz  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5       1.1  jkunz  * All rights reserved.
      6       1.1  jkunz  *
      7       1.1  jkunz  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1  jkunz  * by Petri Laakso.
      9       1.1  jkunz  *
     10       1.1  jkunz  * Redistribution and use in source and binary forms, with or without
     11       1.1  jkunz  * modification, are permitted provided that the following conditions
     12       1.1  jkunz  * are met:
     13       1.1  jkunz  * 1. Redistributions of source code must retain the above copyright
     14       1.1  jkunz  *    notice, this list of conditions and the following disclaimer.
     15       1.1  jkunz  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1  jkunz  *    notice, this list of conditions and the following disclaimer in the
     17       1.1  jkunz  *    documentation and/or other materials provided with the distribution.
     18       1.1  jkunz  *
     19       1.1  jkunz  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1  jkunz  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1  jkunz  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1  jkunz  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1  jkunz  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1  jkunz  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1  jkunz  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1  jkunz  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1  jkunz  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1  jkunz  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1  jkunz  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1  jkunz  */
     31       1.1  jkunz 
     32       1.1  jkunz #include <sys/param.h>
     33       1.3  jkunz #include <sys/types.h>
     34       1.1  jkunz #include <sys/bus.h>
     35       1.1  jkunz #include <sys/device.h>
     36       1.1  jkunz #include <sys/errno.h>
     37       1.3  jkunz #include <sys/mutex.h>
     38       1.1  jkunz #include <sys/kmem.h>
     39       1.1  jkunz #include <sys/systm.h>
     40       1.1  jkunz 
     41       1.3  jkunz #include <arm/imx/imx23_apbdma.h>
     42       1.1  jkunz #include <arm/imx/imx23_apbdmareg.h>
     43       1.3  jkunz #include <arm/imx/imx23_apbdmavar.h>
     44       1.1  jkunz #include <arm/imx/imx23_apbhdmareg.h>
     45       1.1  jkunz #include <arm/imx/imx23_apbxdmareg.h>
     46       1.1  jkunz #include <arm/imx/imx23var.h>
     47       1.1  jkunz 
     48       1.1  jkunz static int	apbdma_match(device_t, cfdata_t, void *);
     49       1.1  jkunz static void	apbdma_attach(device_t, device_t, void *);
     50       1.1  jkunz static int	apbdma_activate(device_t, enum devact);
     51       1.1  jkunz 
     52       1.1  jkunz CFATTACH_DECL3_NEW(apbdma,
     53       1.1  jkunz 	sizeof(struct apbdma_softc),
     54       1.1  jkunz 	apbdma_match,
     55       1.1  jkunz 	apbdma_attach,
     56       1.1  jkunz 	NULL,
     57       1.1  jkunz 	apbdma_activate,
     58       1.1  jkunz 	NULL,
     59       1.1  jkunz 	NULL,
     60       1.1  jkunz 	0);
     61       1.1  jkunz 
     62       1.1  jkunz static void	apbdma_reset(struct apbdma_softc *);
     63       1.3  jkunz static void	apbdma_init(struct apbdma_softc *);
     64       1.3  jkunz 
     65       1.3  jkunz #define DMA_RD(sc, reg)							\
     66       1.3  jkunz 		bus_space_read_4(sc->sc_iot, sc->sc_ioh, (reg))
     67       1.3  jkunz #define DMA_WR(sc, reg, val)						\
     68       1.3  jkunz 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, (reg), (val))
     69       1.3  jkunz 
     70       1.3  jkunz #define APBDMA_SOFT_RST_LOOP 455 /* At least 1 us ... */
     71       1.1  jkunz 
     72       1.1  jkunz static int
     73       1.1  jkunz apbdma_match(device_t parent, cfdata_t match, void *aux)
     74       1.1  jkunz {
     75       1.1  jkunz 	struct apb_attach_args *aa = aux;
     76       1.1  jkunz 
     77       1.1  jkunz 	if (aa->aa_addr == HW_APBHDMA_BASE && aa->aa_size == HW_APBHDMA_SIZE)
     78       1.1  jkunz 			return 1;
     79       1.1  jkunz 
     80       1.1  jkunz 	if (aa->aa_addr == HW_APBXDMA_BASE && aa->aa_size == HW_APBXDMA_SIZE)
     81       1.1  jkunz 			return 1;
     82       1.1  jkunz 
     83       1.1  jkunz 	return 0;
     84       1.1  jkunz }
     85       1.1  jkunz 
     86       1.1  jkunz static void
     87       1.1  jkunz apbdma_attach(device_t parent, device_t self, void *aux)
     88       1.1  jkunz {
     89       1.1  jkunz 	struct apb_attach_args *aa = aux;
     90       1.1  jkunz 	struct apbdma_softc *sc = device_private(self);
     91       1.3  jkunz 	struct apb_softc *sc_parent = device_private(parent);
     92       1.3  jkunz 	static u_int apbdma_attached = 0;
     93       1.1  jkunz 
     94       1.3  jkunz 	if ((strncmp(device_xname(parent), "apbh", 4) == 0) &&
     95  1.3.14.1  skrll 	    (apbdma_attached & F_APBH_DMA))
     96       1.3  jkunz 		return;
     97       1.3  jkunz 	if ((strncmp(device_xname(parent), "apbx", 4) == 0) &&
     98  1.3.14.1  skrll 	    (apbdma_attached & F_APBX_DMA))
     99       1.3  jkunz 		return;
    100       1.1  jkunz 
    101       1.1  jkunz 	sc->sc_dev = self;
    102       1.1  jkunz 	sc->sc_iot = aa->aa_iot;
    103       1.1  jkunz 	sc->sc_dmat = aa->aa_dmat;
    104       1.1  jkunz 
    105       1.1  jkunz 	if (bus_space_map(sc->sc_iot,
    106       1.3  jkunz 	    aa->aa_addr, aa->aa_size, 0, &sc->sc_ioh)) {
    107       1.1  jkunz 		aprint_error_dev(sc->sc_dev, "unable to map bus space\n");
    108       1.1  jkunz 		return;
    109       1.1  jkunz 	}
    110       1.1  jkunz 
    111       1.3  jkunz 	if (strncmp(device_xname(parent), "apbh", 4) == 0)
    112  1.3.14.1  skrll 		sc->flags = F_APBH_DMA;
    113       1.3  jkunz 
    114       1.3  jkunz 	if (strncmp(device_xname(parent), "apbx", 4) == 0)
    115  1.3.14.1  skrll 		sc->flags = F_APBX_DMA;
    116       1.3  jkunz 
    117       1.3  jkunz 	apbdma_reset(sc);
    118       1.3  jkunz 	apbdma_init(sc);
    119       1.1  jkunz 
    120  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA)
    121  1.3.14.1  skrll 		apbdma_attached |= F_APBH_DMA;
    122  1.3.14.1  skrll 	if (sc->flags & F_APBX_DMA)
    123  1.3.14.1  skrll 		apbdma_attached |= F_APBX_DMA;
    124       1.1  jkunz 
    125       1.3  jkunz 	sc_parent->dmac = self;
    126       1.1  jkunz 
    127       1.3  jkunz 	/* Initialize mutex to control concurrent access from the drivers. */
    128       1.3  jkunz 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
    129       1.1  jkunz 
    130  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA)
    131  1.3.14.1  skrll 		aprint_normal(": APBH DMA\n");
    132  1.3.14.1  skrll 	else if (sc->flags & F_APBX_DMA)
    133  1.3.14.1  skrll 		aprint_normal(": APBX DMA\n");
    134  1.3.14.1  skrll 	else
    135  1.3.14.1  skrll 		panic("dma flag missing!\n");
    136       1.1  jkunz 
    137       1.1  jkunz 	return;
    138       1.1  jkunz }
    139       1.1  jkunz 
    140       1.1  jkunz static int
    141       1.1  jkunz apbdma_activate(device_t self, enum devact act)
    142       1.1  jkunz {
    143       1.1  jkunz 	return EOPNOTSUPP;
    144       1.1  jkunz }
    145       1.1  jkunz 
    146       1.1  jkunz /*
    147       1.1  jkunz  * Reset the APB{H,X}DMA block.
    148       1.1  jkunz  *
    149       1.2  jkunz  * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
    150       1.1  jkunz  */
    151       1.1  jkunz static void
    152       1.1  jkunz apbdma_reset(struct apbdma_softc *sc)
    153       1.1  jkunz {
    154       1.1  jkunz 	unsigned int loop;
    155       1.1  jkunz 
    156       1.1  jkunz 	/*
    157       1.1  jkunz 	 * Prepare for soft-reset by making sure that SFTRST is not currently
    158       1.1  jkunz 	 * asserted. Also clear CLKGATE so we can wait for its assertion below.
    159       1.1  jkunz 	 */
    160       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_SFTRST);
    161       1.1  jkunz 
    162       1.1  jkunz 	/* Wait at least a microsecond for SFTRST to deassert. */
    163       1.1  jkunz 	loop = 0;
    164       1.3  jkunz 	while ((DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_SFTRST) ||
    165       1.3  jkunz 	    (loop < APBDMA_SOFT_RST_LOOP))
    166       1.1  jkunz 		loop++;
    167       1.1  jkunz 
    168       1.1  jkunz 	/* Clear CLKGATE so we can wait for its assertion below. */
    169       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_CLKGATE);
    170       1.1  jkunz 
    171       1.1  jkunz 	/* Soft-reset the block. */
    172       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL0_SET, HW_APB_CTRL0_SFTRST);
    173       1.1  jkunz 
    174       1.1  jkunz 	/* Wait until clock is in the gated state. */
    175       1.3  jkunz 	while (!(DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_CLKGATE));
    176       1.1  jkunz 
    177       1.1  jkunz 	/* Bring block out of reset. */
    178       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_SFTRST);
    179       1.1  jkunz 
    180       1.1  jkunz 	loop = 0;
    181       1.3  jkunz 	while ((DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_SFTRST) ||
    182       1.3  jkunz 	    (loop < APBDMA_SOFT_RST_LOOP))
    183       1.1  jkunz 		loop++;
    184       1.3  jkunz 
    185       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_CLKGATE);
    186       1.3  jkunz 
    187       1.3  jkunz 	/* Wait until clock is in the NON-gated state. */
    188       1.3  jkunz 	while (DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_CLKGATE);
    189       1.3  jkunz 
    190       1.3  jkunz 	return;
    191       1.3  jkunz }
    192       1.3  jkunz 
    193       1.3  jkunz /*
    194       1.3  jkunz  * Initialize APB{H,X}DMA block.
    195       1.3  jkunz  */
    196       1.3  jkunz static void
    197       1.3  jkunz apbdma_init(struct apbdma_softc *sc)
    198       1.3  jkunz {
    199       1.3  jkunz 
    200  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA) {
    201       1.3  jkunz 		DMA_WR(sc, HW_APBH_CTRL0_SET, HW_APBH_CTRL0_AHB_BURST8_EN);
    202       1.3  jkunz 		DMA_WR(sc, HW_APBH_CTRL0_SET, HW_APBH_CTRL0_APB_BURST4_EN);
    203       1.3  jkunz 	}
    204       1.3  jkunz 	return;
    205       1.3  jkunz }
    206       1.3  jkunz 
    207       1.3  jkunz /*
    208       1.3  jkunz  * Chain DMA commands together.
    209       1.3  jkunz  *
    210       1.3  jkunz  * Set src->next point to trg's physical DMA mapped address.
    211       1.3  jkunz  */
    212       1.3  jkunz void
    213       1.3  jkunz apbdma_cmd_chain(apbdma_command_t src, apbdma_command_t trg, void *buf,
    214       1.3  jkunz     bus_dmamap_t dmap)
    215       1.3  jkunz {
    216       1.3  jkunz 	int i;
    217       1.3  jkunz 	bus_size_t daddr;
    218       1.3  jkunz 	bus_addr_t trg_offset;
    219       1.3  jkunz 
    220       1.3  jkunz 	trg_offset = (bus_addr_t)trg - (bus_addr_t)buf;
    221       1.3  jkunz 	daddr = 0;
    222       1.3  jkunz 
    223       1.3  jkunz 	for (i = 0; i < dmap->dm_nsegs; i++) {
    224       1.3  jkunz 		daddr += dmap->dm_segs[i].ds_len;
    225       1.3  jkunz 		if (trg_offset < daddr) {
    226       1.3  jkunz 			src->next = (void *)(dmap->dm_segs[i].ds_addr +
    227       1.3  jkunz 			    (trg_offset - (daddr - dmap->dm_segs[i].ds_len)));
    228       1.3  jkunz 			break;
    229       1.3  jkunz 		}
    230       1.3  jkunz 	}
    231       1.3  jkunz 
    232       1.3  jkunz 	return;
    233       1.3  jkunz }
    234       1.3  jkunz 
    235       1.3  jkunz /*
    236       1.3  jkunz  * Set DMA command buffer.
    237       1.3  jkunz  *
    238       1.3  jkunz  * Set cmd->buffer point to physical DMA address at offset in DMA map.
    239       1.3  jkunz  */
    240       1.3  jkunz void
    241       1.3  jkunz apbdma_cmd_buf(apbdma_command_t cmd, bus_addr_t offset, bus_dmamap_t dmap)
    242       1.3  jkunz {
    243       1.3  jkunz 	int i;
    244       1.3  jkunz 	bus_size_t daddr;
    245       1.3  jkunz 
    246       1.3  jkunz 	daddr = 0;
    247       1.3  jkunz 
    248       1.3  jkunz 	for (i = 0; i < dmap->dm_nsegs; i++) {
    249       1.3  jkunz 		daddr += dmap->dm_segs[i].ds_len;
    250       1.3  jkunz 		if (offset < daddr) {
    251       1.3  jkunz 			cmd->buffer = (void *)(dmap->dm_segs[i].ds_addr +
    252       1.3  jkunz 			    (offset - (daddr - dmap->dm_segs[i].ds_len)));
    253       1.3  jkunz 			break;
    254       1.3  jkunz 		}
    255       1.3  jkunz 	}
    256       1.3  jkunz 
    257       1.3  jkunz 	return;
    258       1.3  jkunz }
    259       1.3  jkunz 
    260       1.3  jkunz /*
    261       1.3  jkunz  * Initialize DMA channel.
    262       1.3  jkunz  */
    263       1.3  jkunz void
    264       1.3  jkunz apbdma_chan_init(struct apbdma_softc *sc, unsigned int channel)
    265       1.3  jkunz {
    266       1.3  jkunz 
    267       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    268       1.3  jkunz 
    269       1.3  jkunz 	/* Enable CMDCMPLT_IRQ. */
    270       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL1_SET, (1<<channel)<<16);
    271       1.3  jkunz 
    272       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    273       1.3  jkunz 
    274       1.3  jkunz 	return;
    275       1.3  jkunz }
    276       1.3  jkunz 
    277       1.3  jkunz /*
    278       1.3  jkunz  * Set command chain for DMA channel.
    279       1.3  jkunz  */
    280       1.3  jkunz #define HW_APB_CHN_NXTCMDAR(base, channel)	(base + (0x70 * channel))
    281       1.3  jkunz void
    282       1.3  jkunz apbdma_chan_set_chain(struct apbdma_softc *sc, unsigned int channel,
    283       1.3  jkunz 	bus_dmamap_t dmap)
    284       1.3  jkunz {
    285       1.3  jkunz 	uint32_t reg;
    286       1.3  jkunz 
    287  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA)
    288       1.3  jkunz 		reg = HW_APB_CHN_NXTCMDAR(HW_APBH_CH0_NXTCMDAR, channel);
    289       1.3  jkunz 	else
    290       1.3  jkunz 		reg = HW_APB_CHN_NXTCMDAR(HW_APBX_CH0_NXTCMDAR, channel);
    291       1.3  jkunz 
    292       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    293       1.3  jkunz 	DMA_WR(sc, reg, dmap->dm_segs[0].ds_addr);
    294       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    295       1.3  jkunz 
    296       1.3  jkunz 	return;
    297       1.3  jkunz }
    298       1.3  jkunz 
    299       1.3  jkunz /*
    300       1.3  jkunz  * Initiate DMA transfer.
    301       1.3  jkunz  */
    302       1.3  jkunz #define HW_APB_CHN_SEMA(base, channel)	(base + (0x70 * channel))
    303       1.3  jkunz void
    304       1.3  jkunz apbdma_run(struct apbdma_softc *sc, unsigned int channel)
    305       1.3  jkunz {
    306       1.3  jkunz 	uint32_t reg;
    307       1.3  jkunz 	uint8_t val;
    308       1.3  jkunz 
    309  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA) {
    310       1.3  jkunz 		reg = HW_APB_CHN_SEMA(HW_APBH_CH0_SEMA, channel);
    311       1.3  jkunz 		val = __SHIFTIN(1, HW_APBH_CH0_SEMA_INCREMENT_SEMA);
    312       1.3  jkunz 	 } else {
    313       1.3  jkunz 		reg = HW_APB_CHN_SEMA(HW_APBX_CH0_SEMA, channel);
    314       1.3  jkunz 		val = __SHIFTIN(1, HW_APBX_CH0_SEMA_INCREMENT_SEMA);
    315       1.1  jkunz 	}
    316       1.1  jkunz 
    317       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    318       1.3  jkunz 	DMA_WR(sc, reg, val);
    319       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    320       1.1  jkunz 
    321       1.3  jkunz 	return;
    322       1.1  jkunz }
    323       1.1  jkunz 
    324       1.1  jkunz /*
    325       1.3  jkunz  * Acknowledge command complete IRQ.
    326       1.3  jkunz  */
    327       1.3  jkunz void
    328       1.3  jkunz apbdma_ack_intr(struct apbdma_softc *sc, unsigned int channel)
    329       1.3  jkunz {
    330       1.3  jkunz 
    331       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    332  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA) {
    333  1.3.14.1  skrll 		DMA_WR(sc, HW_APB_CTRL1_CLR, (1<<channel));
    334  1.3.14.1  skrll 	} else {
    335  1.3.14.1  skrll 		DMA_WR(sc, HW_APB_CTRL1_CLR, (1<<channel));
    336  1.3.14.1  skrll 	}
    337       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    338       1.3  jkunz 
    339       1.3  jkunz 	return;
    340       1.3  jkunz }
    341       1.3  jkunz 
    342       1.3  jkunz /*
    343       1.3  jkunz  * Acknowledge error IRQ.
    344       1.3  jkunz  */
    345       1.3  jkunz void
    346       1.3  jkunz apbdma_ack_error_intr(struct apbdma_softc *sc, unsigned int channel)
    347       1.3  jkunz {
    348       1.3  jkunz 
    349       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    350       1.3  jkunz 	DMA_WR(sc, HW_APB_CTRL2_CLR, (1<<channel));
    351       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    352       1.3  jkunz 
    353       1.3  jkunz 	return;
    354       1.3  jkunz }
    355       1.3  jkunz 
    356       1.3  jkunz /*
    357       1.3  jkunz  * Return reason for the IRQ.
    358       1.3  jkunz  */
    359       1.3  jkunz unsigned int
    360       1.3  jkunz apbdma_intr_status(struct apbdma_softc *sc, unsigned int channel)
    361       1.3  jkunz {
    362       1.3  jkunz 	unsigned int reason;
    363       1.3  jkunz 
    364       1.3  jkunz 	reason = 0;
    365       1.3  jkunz 
    366       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    367       1.3  jkunz 
    368       1.3  jkunz 	/* Check if this was command complete IRQ. */
    369       1.3  jkunz 	if (DMA_RD(sc, HW_APB_CTRL1) & (1<<channel))
    370       1.3  jkunz 		reason = DMA_IRQ_CMDCMPLT;
    371       1.3  jkunz 
    372       1.3  jkunz 	/* Check if error was set. */
    373       1.3  jkunz 	if (DMA_RD(sc, HW_APB_CTRL2) & (1<<channel)) {
    374       1.3  jkunz 		if (DMA_RD(sc, HW_APB_CTRL2) & (1<<channel)<<16)
    375       1.3  jkunz 			reason = DMA_IRQ_BUS_ERROR;
    376       1.3  jkunz 		else
    377       1.3  jkunz 			reason = DMA_IRQ_TERM;
    378       1.3  jkunz 	}
    379       1.3  jkunz 
    380       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    381       1.3  jkunz 
    382       1.3  jkunz 	return reason;
    383       1.3  jkunz }
    384       1.3  jkunz 
    385       1.3  jkunz /*
    386       1.3  jkunz  * Reset DMA channel.
    387       1.3  jkunz  * Use only for devices on APBH bus.
    388       1.3  jkunz  */
    389       1.3  jkunz void
    390       1.3  jkunz apbdma_chan_reset(struct apbdma_softc *sc, unsigned int channel)
    391       1.3  jkunz {
    392       1.3  jkunz 
    393       1.3  jkunz 	mutex_enter(&sc->sc_lock);
    394       1.3  jkunz 
    395  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA) {
    396  1.3.14.1  skrll 		DMA_WR(sc, HW_APB_CTRL0_SET,
    397  1.3.14.1  skrll 		    __SHIFTIN((1<<channel), HW_APBH_CTRL0_RESET_CHANNEL));
    398  1.3.14.1  skrll 		while(DMA_RD(sc, HW_APB_CTRL0) & HW_APBH_CTRL0_RESET_CHANNEL);
    399  1.3.14.1  skrll 	} else {
    400  1.3.14.1  skrll 		DMA_WR(sc, HW_APBX_CHANNEL_CTRL_SET,
    401  1.3.14.1  skrll 			__SHIFTIN((1<<channel), HW_APBH_CTRL0_RESET_CHANNEL));
    402  1.3.14.1  skrll 		while(DMA_RD(sc, HW_APBX_CHANNEL_CTRL) & (1<<channel));
    403  1.3.14.1  skrll 	}
    404       1.3  jkunz 
    405       1.3  jkunz 	mutex_exit(&sc->sc_lock);
    406       1.3  jkunz 
    407       1.3  jkunz 	return;
    408       1.1  jkunz }
    409  1.3.14.1  skrll 
    410  1.3.14.1  skrll void
    411  1.3.14.1  skrll apbdma_wait(struct apbdma_softc *sc, unsigned int channel)
    412  1.3.14.1  skrll {
    413  1.3.14.1  skrll 
    414  1.3.14.1  skrll 	mutex_enter(&sc->sc_lock);
    415  1.3.14.1  skrll 
    416  1.3.14.1  skrll 	if (sc->flags & F_APBH_DMA) {
    417  1.3.14.1  skrll 		while (DMA_RD(sc, HW_APB_CHN_SEMA(HW_APBH_CH0_SEMA, channel)) & HW_APBH_CH0_SEMA_PHORE)
    418  1.3.14.1  skrll 			;
    419  1.3.14.1  skrll 	 } else {
    420  1.3.14.1  skrll 		while (DMA_RD(sc, HW_APB_CHN_SEMA(HW_APBX_CH0_SEMA, channel)) & HW_APBX_CH0_SEMA_PHORE)
    421  1.3.14.1  skrll 			;
    422  1.3.14.1  skrll 	}
    423  1.3.14.1  skrll 
    424  1.3.14.1  skrll 	mutex_exit(&sc->sc_lock);
    425  1.3.14.1  skrll }
    426