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