Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Contribution from Petri Laakso:
details: https://anonhg.NetBSD.org/src/rev/db49c5ee0428
branches: trunk
changeset: 785203:db49c5ee0428
user: jkunz <jkunz%NetBSD.org@localhost>
date: Sun Mar 03 10:33:56 2013 +0000
description:
Contribution from Petri Laakso:
- DMA driver stub code replaced with working code.
- Add support to multi block DMA in ssp driver.
diffstat:
sys/arch/arm/imx/imx23_apbdma.c | 378 +++++++++++------
sys/arch/arm/imx/imx23_apbdmareg.h | 18 +-
sys/arch/arm/imx/imx23_apbdmavar.h | 137 ++++++
sys/arch/arm/imx/imx23_apbhdmareg.h | 26 +-
sys/arch/arm/imx/imx23_apbxdmareg.h | 30 +-
sys/arch/arm/imx/imx23_icollreg.h | 4 +-
sys/arch/arm/imx/imx23_ssp.c | 762 ++++++++++++++++++++++++++--------
sys/arch/evbarm/conf/IMX23_OLINUXINO | 18 +-
8 files changed, 1043 insertions(+), 330 deletions(-)
diffs (truncated from 1788 to 300 lines):
diff -r 768578a8b9b0 -r db49c5ee0428 sys/arch/arm/imx/imx23_apbdma.c
--- a/sys/arch/arm/imx/imx23_apbdma.c Sun Mar 03 10:26:18 2013 +0000
+++ b/sys/arch/arm/imx/imx23_apbdma.c Sun Mar 03 10:33:56 2013 +0000
@@ -1,4 +1,4 @@
-/* $Id: imx23_apbdma.c,v 1.2 2012/12/16 19:40:00 jkunz Exp $ */
+/* $Id: imx23_apbdma.c,v 1.3 2013/03/03 10:33:56 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,53 +30,25 @@
*/
#include <sys/param.h>
+#include <sys/types.h>
#include <sys/bus.h>
#include <sys/device.h>
#include <sys/errno.h>
+#include <sys/mutex.h>
#include <sys/kmem.h>
-#include <sys/queue.h>
#include <sys/systm.h>
+#include <arm/imx/imx23_apbdma.h>
#include <arm/imx/imx23_apbdmareg.h>
+#include <arm/imx/imx23_apbdmavar.h>
#include <arm/imx/imx23_apbhdmareg.h>
#include <arm/imx/imx23_apbxdmareg.h>
-#include <arm/imx/imx23_apbdma.h>
#include <arm/imx/imx23var.h>
static int apbdma_match(device_t, cfdata_t, void *);
static void apbdma_attach(device_t, device_t, void *);
static int apbdma_activate(device_t, enum devact);
-#define APBDMA_SOFT_RST_LOOP 455 /* At least 1 us ... */
-#define DMACTRL_RD(sc, reg) \
- bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
-#define DMACTRL_WR(sc, reg, val) \
- bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
-
-struct apbdma_softc {
- device_t sc_dev;
- bus_space_tag_t sc_iot;
- bus_space_handle_t sc_hdl;
- bus_dma_tag_t sc_dmat;
- bus_dmamap_t sc_dmamp;
- struct imx23_dma_channel *sc_channel;
- int n_channel;
-};
-
-struct imx23_dma_cmd {
- uint32_t next_cmd;
- uint32_t cmd;
- uint32_t buffer;
- uint32_t pio[CMDPIOWORDS_MAX];
- SIMPLEQ_ENTRY(imx23_dma_cmd) entries;
-};
-
-struct imx23_dma_channel {
- SIMPLEQ_HEAD(simplehead, imx23_dma_cmd) head;
- struct simplehead *headp;
- struct apbdma_softc *sc;
-};
-
CFATTACH_DECL3_NEW(apbdma,
sizeof(struct apbdma_softc),
apbdma_match,
@@ -88,6 +60,14 @@
0);
static void apbdma_reset(struct apbdma_softc *);
+static void apbdma_init(struct apbdma_softc *);
+
+#define DMA_RD(sc, reg) \
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, (reg))
+#define DMA_WR(sc, reg, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, (reg), (val))
+
+#define APBDMA_SOFT_RST_LOOP 455 /* At least 1 us ... */
static int
apbdma_match(device_t parent, cfdata_t match, void *aux)
@@ -108,67 +88,44 @@
{
struct apb_attach_args *aa = aux;
struct apbdma_softc *sc = device_private(self);
- //struct apb_softc *scp = device_private(parent);
+ struct apb_softc *sc_parent = device_private(parent);
+ static u_int apbdma_attached = 0;
-// static int apbdma_attached = 0;
-// struct imx23_dma_channel *chan;
-// int i;
- int error;
-
-// if (apbdma_attached)
-// return;
+ if ((strncmp(device_xname(parent), "apbh", 4) == 0) &&
+ (apbdma_attached & F_AHBH_DMA))
+ return;
+ if ((strncmp(device_xname(parent), "apbx", 4) == 0) &&
+ (apbdma_attached & F_AHBX_DMA))
+ return;
sc->sc_dev = self;
sc->sc_iot = aa->aa_iot;
sc->sc_dmat = aa->aa_dmat;
- /*
- * Parent bus softc has a pointer to DMA controller device_t for
- * specific bus. As different busses need different instances of the
- * DMA driver. The apb_softc.dmac is set up here. Now device drivers
- * which use DMA can pass apb_softc.dmac from their parent to apbdma
- * functions.
- */
if (bus_space_map(sc->sc_iot,
- aa->aa_addr, aa->aa_size, 0, &(sc->sc_hdl))) {
+ aa->aa_addr, aa->aa_size, 0, &sc->sc_ioh)) {
aprint_error_dev(sc->sc_dev, "unable to map bus space\n");
return;
}
- error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,
- PAGE_SIZE, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmamp);
- if (error) {
- aprint_error_dev(sc->sc_dev,
- "couldn't create dma map. (error=%d)\n", error);
- return;
- }
-#ifdef notyet
- if (aa->aa_addr == HW_APBHDMA_BASE && aa->aa_size == HW_APBHDMA_SIZE) {
- sc->sc_channel = kmem_alloc(sizeof(struct imx23_dma_channel)
- * APBH_DMA_N_CHANNELS, KM_SLEEP);
- sc->n_channel = APBH_DMA_N_CHANNELS;
- }
+ if (strncmp(device_xname(parent), "apbh", 4) == 0)
+ sc->flags = F_AHBH_DMA;
+
+ if (strncmp(device_xname(parent), "apbx", 4) == 0)
+ sc->flags = F_AHBX_DMA;
+
+ apbdma_reset(sc);
+ apbdma_init(sc);
- if (aa->aa_addr == HW_APBXDMA_BASE && aa->aa_size == HW_APBXDMA_SIZE) {
- sc->sc_channel = kmem_alloc(sizeof(struct imx23_dma_channel)
- * APBX_DMA_N_CHANNELS, KM_SLEEP);
- sc->n_channel = APBX_DMA_N_CHANNELS;
- }
+ if (sc->flags & F_AHBH_DMA)
+ apbdma_attached |= F_AHBH_DMA;
+ if (sc->flags & F_AHBX_DMA)
+ apbdma_attached |= F_AHBX_DMA;
- if (sc->sc_channel == NULL) {
- aprint_error_dev(sc->sc_dev, "unable to allocate memory for"
- " DMA channel structures\n");
- return;
- }
+ sc_parent->dmac = self;
- for (i=0; i < sc->n_channel; i++) {
- chan = (struct imx23_dma_channel *)sc->sc_channel+i;
- chan->sc = sc;
- SIMPLEQ_INIT(&chan->head);
- }
-#endif
- apbdma_reset(sc);
-// apbdma_attached = 1;
+ /* Initialize mutex to control concurrent access from the drivers. */
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
aprint_normal("\n");
@@ -195,85 +152,242 @@
* Prepare for soft-reset by making sure that SFTRST is not currently
* asserted. Also clear CLKGATE so we can wait for its assertion below.
*/
- DMACTRL_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_SFTRST);
+ DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_SFTRST);
/* Wait at least a microsecond for SFTRST to deassert. */
loop = 0;
- while ((DMACTRL_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_SFTRST) ||
- (loop < APBDMA_SOFT_RST_LOOP))
- {
+ while ((DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_SFTRST) ||
+ (loop < APBDMA_SOFT_RST_LOOP))
loop++;
- }
/* Clear CLKGATE so we can wait for its assertion below. */
- DMACTRL_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_CLKGATE);
+ DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_CLKGATE);
/* Soft-reset the block. */
- DMACTRL_WR(sc, HW_APB_CTRL0_SET, HW_APB_CTRL0_SFTRST);
+ DMA_WR(sc, HW_APB_CTRL0_SET, HW_APB_CTRL0_SFTRST);
/* Wait until clock is in the gated state. */
- while (!(DMACTRL_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_CLKGATE));
+ while (!(DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_CLKGATE));
/* Bring block out of reset. */
- DMACTRL_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_SFTRST);
+ DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_SFTRST);
loop = 0;
- while ((DMACTRL_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_SFTRST) ||
- (loop < APBDMA_SOFT_RST_LOOP))
- {
+ while ((DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_SFTRST) ||
+ (loop < APBDMA_SOFT_RST_LOOP))
loop++;
+
+ DMA_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_CLKGATE);
+
+ /* Wait until clock is in the NON-gated state. */
+ while (DMA_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_CLKGATE);
+
+ return;
+}
+
+/*
+ * Initialize APB{H,X}DMA block.
+ */
+static void
+apbdma_init(struct apbdma_softc *sc)
+{
+
+ if (sc->flags & F_AHBH_DMA) {
+ DMA_WR(sc, HW_APBH_CTRL0_SET, HW_APBH_CTRL0_AHB_BURST8_EN);
+ DMA_WR(sc, HW_APBH_CTRL0_SET, HW_APBH_CTRL0_APB_BURST4_EN);
}
-
- DMACTRL_WR(sc, HW_APB_CTRL0_CLR, HW_APB_CTRL0_CLKGATE);
+ return;
+}
+
+/*
+ * Chain DMA commands together.
+ *
+ * Set src->next point to trg's physical DMA mapped address.
+ */
+void
+apbdma_cmd_chain(apbdma_command_t src, apbdma_command_t trg, void *buf,
+ bus_dmamap_t dmap)
+{
+ int i;
+ bus_size_t daddr;
+ bus_addr_t trg_offset;
+
+ trg_offset = (bus_addr_t)trg - (bus_addr_t)buf;
+ daddr = 0;
+
+ for (i = 0; i < dmap->dm_nsegs; i++) {
+ daddr += dmap->dm_segs[i].ds_len;
+ if (trg_offset < daddr) {
+ src->next = (void *)(dmap->dm_segs[i].ds_addr +
+ (trg_offset - (daddr - dmap->dm_segs[i].ds_len)));
+ break;
+ }
+ }
+
+ return;
+}
- /* Wait until clock is in the NON-gated state. */
- while (DMACTRL_RD(sc, HW_APB_CTRL0) & HW_APB_CTRL0_CLKGATE);
+/*
+ * Set DMA command buffer.
+ *
+ * Set cmd->buffer point to physical DMA address at offset in DMA map.
+ */
+void
+apbdma_cmd_buf(apbdma_command_t cmd, bus_addr_t offset, bus_dmamap_t dmap)
+{
+ int i;
+ bus_size_t daddr;
+
+ daddr = 0;
- return;
+ for (i = 0; i < dmap->dm_nsegs; i++) {
+ daddr += dmap->dm_segs[i].ds_len;
+ if (offset < daddr) {
+ cmd->buffer = (void *)(dmap->dm_segs[i].ds_addr +
+ (offset - (daddr - dmap->dm_segs[i].ds_len)));
+ break;
+ }
+ }
+
+ return;
+}
+
+/*
+ * Initialize DMA channel.
+ */
+void
+apbdma_chan_init(struct apbdma_softc *sc, unsigned int channel)
Home |
Main Index |
Thread Index |
Old Index