[prev in list] [next in list] [prev in thread] [next in thread]
List: openbsd-arm
Subject: Re: miniroot-am335x-55.fs installing to BeagleBone Black: no sd1
From: Sylvestre Gallon <ccna.syl () gmail ! com>
Date: 2014-11-03 9:49:07
Message-ID: 20141103094906.GA830 () gmail ! com
[Download RAW message or body]
On Sun, Nov 02, 2014 at 09:31:26PM +1100, Jonathan Gray wrote:
> On Mon, Oct 20, 2014 at 02:40:13AM -0400, Andrew Hills wrote:
> > On 10/19/14, 11:15 AM, Gerke M. Preussner wrote:
> > > I haven't had any time yet to look into this. Were you able to make any
> > > progress on your end?
> >
> > I'm not sure I'd call it progress; I'm not familiar with the MMC
> > protocol, so I'm spending most of my time learning rather than debugging.
> >
> > During the initialization, I see sys/dev/sdmmc roughly follow this order:
> >
> > sdmmc_card_attach()
> > . sdmmc_enable()
> > .. sdmmc_mem_enable()
> > ... sdmmc_mem_send_op_cond() reads memory OCR
> > ... sdmmc_mem_send_op_cond() attempts to send memory OCR
> > .... sdmmc_mmc_command() doesn't fail, but doesn't succeed
> > (MMC_OCR_MEM_READY is not set)
> > .... command times out after 100 attempts (sdmmc_mem.c:519-538)
> >
> > What I haven't been able to figure out is why the command doesn't have
> > the intended effect. Unfortunately, I enabled debug statements in
> > sys/arch/armv7/omap/ommmc.c without thinking, so the system is unusable
> > until I get the old bsd.umg back. Hopefully more to come soon.
> >
>
> I tracked the problem down, it seems u-boot only sets up CAPA for emmc.
ok syl@.
>
> With the diff below I can access the sd card on my bbb rev C (sd0) in
> addition to the emmc (sd1). Both are still quite slow though, with
> reads to the raw device around 780 KB/s on sd and 800 KB/s on emmc.
>
> Besides DMA, it sounds like opting into a higher bus width
> (4 bit on sd, 8 bit on emmc) and clock speeds might help there?
> Then there is also the HSPE/High Speed Enable bit in HCTL.
If you want I already tried to do something for the DMA. The diff below
works 95% of the time, but the 5 other pourcent it broke your
filesystem...
I think the problem has something to do with arm cache, perhaps in
bus_dmamap_sync ? I've already shared this diff with rapha@
but we haven't find how to fix this. I broke my BBB few weeks ago
so I haven't test this diff with the fix for l1 pte...
If you want to try the dma code (at your own fs risk :)) you will
need to remove my fist goto without_dma;
Cheers,
Index: am335x.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/omap/am335x.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 am335x.c
--- am335x.c 18 Oct 2013 15:23:58 -0000 1.4
+++ am335x.c 22 Oct 2013 14:00:41 -0000
@@ -72,6 +72,10 @@
#define EDMACOMP_IRQ 12
#define EDMAMPERR_IRQ 13
#define EDMAERR_IRQ 14
+#define SDQTXEVT1 2
+#define SDQRXEVT1 3
+#define SDQTXEVT0 24
+#define SDQRXEVT0 25
#define UARTx_SIZE 0x90
#define UART0_ADDR 0x44E09000
@@ -177,13 +181,15 @@ struct omap_dev am335x_devs[] = {
{ .name = "ommmc",
.unit = 0,
.mem = { { HSMMC0_ADDR, HSMMCx_SIZE } },
- .irq = { HSMMC0_IRQ }
+ .irq = { HSMMC0_IRQ },
+ .dma = { SDQRXEVT0, SDQTXEVT0 }
},
{ .name = "ommmc",
.unit = 1,
.mem = { { HSMMC1_ADDR, HSMMCx_SIZE } },
- .irq = { HSMMC1_IRQ }
+ .irq = { HSMMC1_IRQ },
+ .dma = { SDQRXEVT1, SDQTXEVT1 }
},
/* cpsw Ethernet */
Index: ommmc.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/omap/ommmc.c,v
retrieving revision 1.7
diff -u -p -u -p -r1.7 ommmc.c
--- ommmc.c 18 Oct 2013 15:23:58 -0000 1.7
+++ ommmc.c 22 Oct 2013 14:00:46 -0000
@@ -33,6 +33,7 @@
#include <armv7/omap/omapvar.h>
#include <armv7/omap/prcmvar.h>
+#include <armv7/omap/edmavar.h>
/*
* NOTE: on OMAP4430/AM335x these registers skew by 0x100
@@ -178,23 +179,35 @@
#define SDHC_BUFFER_TIMEOUT hz
#define SDHC_TRANSFER_TIMEOUT hz
+#define OMMMC_DMA_BUFSIZE MAXPHYS
+#define OMMMC_DMA_SEGSIZE OMMMC_DMA_BUFSIZE
+
void ommmc_attach(struct device *parent, struct device *self, void *args);
struct ommmc_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
- void *sc_ih; /* Interrupt handler */
- uint32_t sc_flags;
+ void *sc_ih; /* Interrupt handler */
- struct device *sdmmc; /* generic SD/MMC device */
- int clockbit; /* clock control bit */
- uint32_t clkbase; /* base clock frequency in KHz */
- int maxblklen; /* maximum block length */
- int flags; /* flags for this host */
- uint32_t ocr; /* OCR value from capabilities */
- uint32_t intr_status; /* soft interrupt status */
- uint32_t intr_error_status; /* */
+ /* DMA */
+ bus_dma_tag_t sc_bdt;
+ bus_dmamap_t sc_dmap;
+ uint32_t sc_dma_tx_ch;
+ uint32_t sc_dma_rx_ch;
+ uint32_t sc_hwfifo_addr;
+ bus_dma_segment_t sc_segs;
+ caddr_t sc_datakvap;
+ int sc_rsegs;
+
+ struct device *sdmmc; /* generic SD/MMC device */
+ int clockbit; /* clock control bit */
+ uint32_t clkbase; /* base clock frequency in KHz */
+ int maxblklen; /* maximum block length */
+ int flags; /* flags for this host */
+ uint32_t ocr; /* OCR value from capabilities */
+ uint32_t intr_status; /* soft interrupt status */
+ uint32_t intr_error_status; /* */
};
@@ -236,6 +249,8 @@ int ommmc_wait_state(struct ommmc_softc
int ommmc_soft_reset(struct ommmc_softc *, int);
int ommmc_wait_intr(struct ommmc_softc *, int, int);
void ommmc_transfer_data(struct ommmc_softc *, struct sdmmc_command *);
+int ommmc_dma_xfer_init(struct ommmc_softc *, struct sdmmc_command *);
+int ommmc_dma_xfer_finish(struct ommmc_softc *, struct sdmmc_command *);
void ommmc_read_data(struct ommmc_softc *, uint8_t *, int);
void ommmc_write_data(struct ommmc_softc *, uint8_t *, int);
@@ -274,15 +289,24 @@ struct cfattach ommmc_ca = {
sizeof(struct ommmc_softc), NULL, ommmc_attach
};
+static void
+edma_it(void *sc)
+{
+ wakeup(sc);
+}
+
void
ommmc_attach(struct device *parent, struct device *self, void *args)
{
struct ommmc_softc *sc = (struct ommmc_softc *) self;
struct armv7_attach_args *aa = args;
struct sdmmcbus_attach_args saa;
uint32_t caps;
sc->sc_iot = aa->aa_iot;
+ sc->sc_bdt = aa->aa_dmat;
+ sc->sc_hwfifo_addr = aa->aa_dev->mem[0].addr + MMCHS_DATA;
+
if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
panic("%s: bus_space_map failed!", __func__);
@@ -311,12 +334,26 @@ ommmc_attach(struct device *parent, stru
/* Determine host capabilities. */
caps = HREAD4(sc, MMCHS_CAPA);
-#if 0
- /* we want this !! */
- /* Use DMA if the host system and the controller support it. */
- if (usedma && ISSET(caps, SDHC_DMA_SUPPORT))
+ if (ISSET(caps, MMCHS_CAPA_DS)) {
+ goto without_dma;
+ if (board_id != BOARD_ID_AM335X_BEAGLEBONE)
+ goto without_dma;
+
+ /* Get DMA channels */
+ sc->sc_dma_rx_ch = aa->aa_dev->dma[0];
+ sc->sc_dma_tx_ch = aa->aa_dev->dma[1];
+
+ if (edma_intr_dma_en(sc->sc_dma_rx_ch, edma_it, sc) ||
+ edma_intr_dma_en(sc->sc_dma_tx_ch, edma_it, sc))
+ goto without_dma;
+
+ if (bus_dmamap_create(sc->sc_bdt, OMMMC_DMA_BUFSIZE, 1,
+ OMMMC_DMA_SEGSIZE, 0 , BUS_DMA_WAITOK, &sc->sc_dmap) != 0)
+ goto without_dma;
+
SET(sc->flags, SHF_USE_DMA);
-#endif
+ }
+without_dma:
/*
* Determine the base clock frequency. (2.2.24)
@@ -798,8 +837,13 @@ ommmc_exec_command(sdmmc_chipset_handle_
* If the command has data to transfer in any direction,
* execute the transfer now.
*/
- if (cmd->c_error == 0 && cmd->c_data != NULL)
- ommmc_transfer_data(sc, cmd);
+
+ if (cmd->c_error == 0 && cmd->c_data != NULL) {
+ if (!ISSET(sc->flags, SHF_USE_DMA))
+ ommmc_transfer_data(sc, cmd);
+ else
+ ommmc_dma_xfer_finish(sc, cmd);
+ }
#if 0
/* Turn off the LED. */
@@ -860,16 +904,15 @@ ommmc_start_command(struct ommmc_softc *
command |= MMCHS_CMD_ACEN;
}
}
-#ifdef notyet
+
if (ISSET(sc->flags, SHF_USE_DMA))
command |= MMCHS_CMD_DE;
-#endif
/*
* Prepare command register value. (2.2.6)
*/
command |= (cmd->c_opcode << MMCHS_CMD_INDX_SHIFT) &
- MMCHS_CMD_INDX_SHIFT_MASK;
+ MMCHS_CMD_INDX_SHIFT_MASK;
if (ISSET(cmd->c_flags, SCF_RSP_CRC))
command |= MMCHS_CMD_CCCE;
@@ -890,6 +933,9 @@ ommmc_start_command(struct ommmc_softc *
/* Wait until command and data inhibit bits are clear. (1.5) */
if ((error = ommmc_wait_state(sc, MMCHS_PSTATE_CMDI, 0)) != 0)
return (error);
+ /* Wait until command and data inhibit bits are clear. (1.5) */
+ if ((error = ommmc_wait_state(sc, MMCHS_PSTATE_DATI, 0)) != 0)
+ return (error);
s = splsdmmc();
@@ -898,11 +944,15 @@ ommmc_start_command(struct ommmc_softc *
HSET1(sc, SDHC_HOST_CTL, SDHC_LED_ON);
#endif
- /* XXX: Set DMA start address if SHF_USE_DMA is set. */
-
DPRINTF(1,("%s: cmd=%#x blksize=%d blkcount=%d\n",
DEVNAME(sc), command, blksize, blkcount));
+ if (cmd->c_datalen > 0 && ISSET(sc->flags, SHF_USE_DMA)) {
+ error = ommmc_dma_xfer_init(sc, cmd);
+ if (error)
+ return (error);
+ }
+
/*
* Start a CPU data transfer. Writing to the high order byte
* of the SDHC_COMMAND register triggers the SD command. (1.5)
@@ -914,6 +964,141 @@ ommmc_start_command(struct ommmc_softc *
splx(s);
return (0);
+}
+
+int
+ommmc_dma_xfer_init(struct ommmc_softc *sc, struct sdmmc_command *cmd)
+{
+ struct edma_param params;
+ uint32_t blksize = 0;
+ uint32_t blkcount = 0;
+ int error;
+ uint32_t ch;
+ int read;
+
+ blksize = MIN(cmd->c_datalen, cmd->c_blklen);
+ blkcount = cmd->c_datalen / blksize;
+ read = ISSET(cmd->c_flags, SCF_CMD_READ);
+
+
+ /* Allocate and map DMA memory for data xfer */
+ error = bus_dmamem_alloc(sc->sc_bdt, cmd->c_datalen, 0, 0,
+ &sc->sc_segs, 1, &sc->sc_rsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (error) {
+ printf("%s: could not allocate %d bytes\n",
+ DEVNAME(sc), cmd->c_datalen);
+ goto ret;
+ }
+
+ error = bus_dmamem_map(sc->sc_bdt, &sc->sc_segs, sc->sc_rsegs,
+ cmd->c_datalen, &sc->sc_datakvap, BUS_DMA_WAITOK |
+ BUS_DMA_COHERENT);
+ if (error) {
+ printf("%s: could not map data buffer\n", DEVNAME(sc));
+ goto free_databuf;
+ }
+
+ /* If it is a write, copy data from sdmmmc-provided buffer. */
+ if (!read)
+ memcpy(sc->sc_datakvap, cmd->c_data, cmd->c_datalen);
+
+ /* Load the data buffer and sync it */
+ error = bus_dmamap_load(sc->sc_bdt, sc->sc_dmap, sc->sc_datakvap,
+ cmd->c_datalen, NULL, ((read) ? BUS_DMA_READ : BUS_DMA_WRITE)
+ | BUS_DMA_WAITOK);
+ if (error) {
+ printf("%s: could not load DMA map\n", DEVNAME(sc));
+ goto unmap_databuf;
+ }
+
+ bus_dmamap_sync(sc->sc_bdt, sc->sc_dmap, 0, cmd->c_datalen,
+ BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(sc->sc_bdt, sc->sc_dmap, 0, cmd->c_datalen,
+ BUS_DMASYNC_PREWRITE);
+
+ /* set edma params and enable dma xfer trigged by device */
+ bzero(¶ms, sizeof(params));
+ if (read) {
+ ch = sc->sc_dma_rx_ch;
+ params.src = sc->sc_hwfifo_addr;
+ params.dst = sc->sc_dmap->dm_segs[0].ds_addr;
+ params.dstbidx = 64;
+ params.dstcidx = blksize;
+ params.opt = 1; /* enable sam */
+ } else {
+ ch = sc->sc_dma_tx_ch;
+ params.src = sc->sc_dmap->dm_segs[0].ds_addr;
+ params.dst = sc->sc_hwfifo_addr;
+ params.srcbidx = 64;
+ params.srccidx = blksize;
+ params.opt = (1 << 1); /* enable dam */
+ }
+ params.acnt = 64;
+ params.bcnt = blksize / 64;
+ params.ccnt = blkcount;
+ params.link = 0xffff;
+ params.opt |= (1<<20) | (ch << 12) | (2 << 8) | (1 << 2);
+
+ edma_param_write(ch, ¶ms);
+ edma_trig_xfer_by_dev(ch);
+
+ return (0);
+
+unmap_databuf:
+ bus_dmamem_unmap(sc->sc_bdt, sc->sc_datakvap, cmd->c_datalen);
+free_databuf:
+ bus_dmamem_free(sc->sc_bdt, &sc->sc_segs, sc->sc_rsegs);
+ret:
+ printf("%s: xfer error=%d\n", DEVNAME(sc), error);
+
+ return (error);
+}
+
+int
+ommmc_dma_xfer_finish(struct ommmc_softc *sc, struct sdmmc_command *cmd)
+{
+ int error = 0;
+ int read;
+
+ read = ISSET(cmd->c_flags, SCF_CMD_READ);
+
+ /* wait for completion */
+ if (!ommmc_wait_intr(sc, MMCHS_STAT_TC, SDHC_TRANSFER_TIMEOUT))
+ error = ETIMEDOUT;
+ /* Wait until command and data inhibit bits are clear. (1.5) */
+ if (!error)
+ error = ommmc_wait_state(sc, MMCHS_PSTATE_DATI, 0);
+
+ if (error != 0)
+ cmd->c_error = error;
+ SET(cmd->c_flags, SCF_ITSDONE);
+
+ DPRINTF(1,("%s: data transfer done (error=%d)\n", DEVNAME(sc),
+ cmd->c_error));
+
+ if (error)
+ goto unload_databuf;
+
+ bus_dmamap_sync(sc->sc_bdt, sc->sc_dmap, 0, cmd->c_datalen,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(sc->sc_bdt, sc->sc_dmap, 0, cmd->c_datalen,
+ BUS_DMASYNC_POSTWRITE);
+
+unload_databuf:
+ bus_dmamap_unload(sc->sc_bdt, sc->sc_dmap);
+
+ /* If this is a read, copy data into sdmmc-provided buffer. */
+ if (error == 0 && read)
+ memcpy(cmd->c_data, sc->sc_datakvap, cmd->c_datalen);
+
+ /* Free DMA data buffer */
+
+ bus_dmamem_unmap(sc->sc_bdt, sc->sc_datakvap, cmd->c_datalen);
+ bus_dmamem_free(sc->sc_bdt, &sc->sc_segs, sc->sc_rsegs);
+
+ if (error)
+ printf("%s: xfer done, error=%d\n", DEVNAME(sc), error);
+ return (error);
}
void
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic