[PATCH rtems-libbsd 1/2] sdhci: Add some workarrounds for i.MX
Gedare Bloom
gedare at rtems.org
Thu Sep 10 15:17:14 UTC 2020
Thanks, good luck :)
On Thu, Sep 10, 2020 at 7:19 AM Christian Mauderer
<christian.mauderer at embedded-brains.de> wrote:
>
> Hello Gedare,
>
> I created a ticket for this in FreeBSD (I really hope I picked the right
> way for this). I'll wait whether it needs some adaption and then re-send
> an adapted patch for libbsd as soon as I have a version that is accepted
> in FreeBSD.
>
> Best regards
>
> Christian
>
> On 10/09/2020 09:05, Christian Mauderer wrote:
> > Hello Gedare,
> >
> > I'll have to rework some parts (the ones where I checked for the BSP)
> > but I'll try.
> >
> > Best regards
> >
> > Christian>
> > On 09/09/2020 17:58, Gedare Bloom wrote:
> >> Can this be pushed upstream in a non-RTEMS specific way?
> >>
> >> On Wed, Sep 9, 2020 at 5:16 AM Christian Mauderer
> >> <christian.mauderer at embedded-brains.de> wrote:
> >>>
> >>> Some bits are in the wrong order. Beneath that, the interrupts can occur
> >>> in an unexpected order. The DATA_AVAIL interrupt can occur at the same
> >>> time as the DMA interrupt (or slightly before it). With that, the DMA
> >>> and PIO interrupt handling doesn't work well together. Beneath that the
> >>> DMA interrupt isn't only executed at block ends but also if all data is
> >>> transfered. That can lead to problems with the DATA_END interrupt.
> >>> Therefore check whether there is really data left to unload.
> >>>
> >>> Update #3869
> >>> ---
> >>> freebsd/sys/dev/sdhci/fsl_sdhci.c | 41 +++++++++++++++++++++++++++++++
> >>> freebsd/sys/dev/sdhci/sdhci.c | 40 ++++++++++++++++++++++++++++++
> >>> 2 files changed, 81 insertions(+)
> >>>
> >>> diff --git a/freebsd/sys/dev/sdhci/fsl_sdhci.c b/freebsd/sys/dev/sdhci/fsl_sdhci.c
> >>> index be3d1de3..acef1c4a 100644
> >>> --- a/freebsd/sys/dev/sdhci/fsl_sdhci.c
> >>> +++ b/freebsd/sys/dev/sdhci/fsl_sdhci.c
> >>> @@ -74,6 +74,9 @@ uint32_t mpc85xx_get_system_clock(void);
> >>> #endif /* __rtems__ */
> >>> #endif
> >>>
> >>> +#ifndef __rtems__
> >>> +#include <bsp.h>
> >>> +#endif /* __rtems__ */
> >>> #include <dev/gpio/gpiobusvar.h>
> >>>
> >>> #include <dev/ofw/ofw_bus.h>
> >>> @@ -168,6 +171,16 @@ struct fsl_sdhci_softc {
> >>> #define SDHC_PROT_CDSS (1 << 7)
> >>>
> >>> #define SDHC_SYS_CTRL 0x2c
> >>> +#ifdef __rtems__
> >>> +
> >>> +/*
> >>> + * Freescale messed up the INT DMA ERR bit and placed it at bit 28 instead of
> >>> + * bit 25 which would be standard.
> >>> + */
> >>> +#define SDHC_INT_DMAES (1 << 28)
> >>> +
> >>> +#define SDHC_CAN_DO_ADMA2 0x00100000
> >>> +#endif /* __rtems__ */
> >>>
> >>> /*
> >>> * The clock enable bits exist in different registers for ESDHC vs USDHC, but
> >>> @@ -349,6 +362,16 @@ fsl_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
> >>> val32 &= ~SDHCI_CAN_VDD_180;
> >>> val32 &= ~SDHCI_CAN_DO_SUSPEND;
> >>> val32 |= SDHCI_CAN_DO_8BITBUS;
> >>> +#ifdef __rtems__
> >>> + /*
> >>> + * Freescale signals ADMA2 capability via bit 20 (which would be
> >>> + * ADMA1) instead of 19.
> >>> + */
> >>> + if (val32 & SDHC_CAN_DO_ADMA2) {
> >>> + val32 &= ~SDHC_CAN_DO_ADMA2;
> >>> + val32 |= SDHCI_CAN_DO_ADMA2;
> >>> + }
> >>> +#endif /* __rtems__ */
> >>> return (val32);
> >>> }
> >>>
> >>> @@ -373,6 +396,13 @@ fsl_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
> >>> * command with an R1B response, mix it into the hardware status.
> >>> */
> >>> if (off == SDHCI_INT_STATUS) {
> >>> +#ifdef __rtems__
> >>> + /* Fix messed up DMA error. */
> >>> + if (val32 & SDHC_INT_DMAES) {
> >>> + val32 &= ~SDHC_INT_DMAES;
> >>> + val32 |= SDHCI_INT_ADMAERR;
> >>> + }
> >>> +#endif /* __rtems__ */
> >>> return (val32 | sc->r1bfix_intmask);
> >>> }
> >>>
> >>> @@ -519,6 +549,15 @@ fsl_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_
> >>> if (off == SDHCI_INT_STATUS) {
> >>> sc->r1bfix_intmask &= ~val;
> >>> }
> >>> +#ifdef __rtems__
> >>> + /* Fix messed up DMA error. */
> >>> + if (off == SDHCI_INT_STATUS || off == SDHCI_INT_ENABLE || off == SDHCI_SIGNAL_ENABLE) {
> >>> + if (val & SDHCI_INT_ADMAERR) {
> >>> + val &= ~SDHCI_INT_ADMAERR;
> >>> + val |= SDHC_INT_DMAES;
> >>> + }
> >>> + }
> >>> +#endif /* __rtems__ */
> >>>
> >>> WR4(sc, off, val);
> >>> }
> >>> @@ -884,10 +923,12 @@ fsl_sdhci_attach(device_t dev)
> >>>
> >>> sc->slot.quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
> >>>
> >>> +#if !defined(__rtems__) || !defined(LIBBSP_ARM_IMX_BSP_H)
> >>> /*
> >>> * DMA is not really broken, I just haven't implemented it yet.
> >>> */
> >>> sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
> >>> +#endif /* __rtems__ */
> >>>
> >>> /*
> >>> * Set the buffer watermark level to 128 words (512 bytes) for both read
> >>> diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c
> >>> index ed6010e8..53d86fe8 100644
> >>> --- a/freebsd/sys/dev/sdhci/sdhci.c
> >>> +++ b/freebsd/sys/dev/sdhci/sdhci.c
> >>> @@ -68,6 +68,9 @@ __FBSDID("$FreeBSD$");
> >>> #include <rtems/bsd/local/sdhci_if.h>
> >>>
> >>> #include <rtems/bsd/local/opt_mmccam.h>
> >>> +#ifdef __rtems__
> >>> +#include <bsp.h>
> >>> +#endif /* __rtems__ */
> >>>
> >>> SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver");
> >>>
> >>> @@ -766,6 +769,17 @@ sdhci_dma_alloc(struct sdhci_slot *slot)
> >>> else
> >>> slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K;
> >>> }
> >>> +#ifdef __rtems__
> >>> +#if defined(LIBBSP_ARM_IMX_BSP_H)
> >>> + /*
> >>> + * i.MX6ULL doesn't have the SDMA Buffer Boundary bits. Instead the
> >>> + * BLKSIZE is one bit larger and would overlap the Buffer Boundary.
> >>> + * Setting the Buffer Boundary to 4K makes sure that the highest BLKSIZE
> >>> + * bit is always 0.
> >>> + */
> >>> + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K;
> >>> +#endif
> >>> +#endif /* __rtems__ */
> >>> slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary);
> >>>
> >>> /*
> >>> @@ -1896,6 +1910,10 @@ sdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data)
> >>> BUS_DMASYNC_PREWRITE);
> >>> }
> >>> WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
> >>> +#ifdef __rtems__
> >>> + /* Avoid PIO interrupt if we use DMA */
> >>> + slot->intmask &= ~(SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL);
> >>> +#endif /* __rtems__ */
> >>> /*
> >>> * Interrupt aggregation: Mask border interrupt for the last
> >>> * bounce buffer and unmask otherwise.
> >>> @@ -1932,15 +1950,27 @@ sdhci_finish_data(struct sdhci_slot *slot)
> >>> WR4(slot, SDHCI_SIGNAL_ENABLE,
> >>> slot->intmask |= SDHCI_INT_RESPONSE);
> >>> }
> >>> +#ifdef __rtems__
> >>> + /* Restore PIO interrupts in case they are necessary elsewhere */
> >>> + if (slot->flags & SDHCI_USE_DMA) {
> >>> + slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
> >>> + }
> >>> +#endif /* __rtems__ */
> >>> /* Unload rest of data from DMA buffer. */
> >>> if (!slot->data_done && (slot->flags & SDHCI_USE_DMA) &&
> >>> slot->curcmd->data != NULL) {
> >>> if (data->flags & MMC_DATA_READ) {
> >>> left = data->len - slot->offset;
> >>> +#ifdef __rtems__
> >>> + if (left > 0) {
> >>> +#endif /* __rtems__ */
> >>> bus_dmamap_sync(slot->dmatag, slot->dmamap,
> >>> BUS_DMASYNC_POSTREAD);
> >>> memcpy((u_char*)data->data + slot->offset, slot->dmamem,
> >>> ulmin(left, slot->sdma_bbufsz));
> >>> +#ifdef __rtems__
> >>> + }
> >>> +#endif /* __rtems__ */
> >>> } else
> >>> bus_dmamap_sync(slot->dmatag, slot->dmamap,
> >>> BUS_DMASYNC_POSTWRITE);
> >>> @@ -2201,8 +2231,15 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
> >>> BUS_DMASYNC_POSTWRITE);
> >>> }
> >>> /* ... and reload it again. */
> >>> +#ifdef __rtems__
> >>> + slot->offset += ulmin(left, sdma_bbufsz);
> >>> +#else /* __rtems__ */
> >>> slot->offset += sdma_bbufsz;
> >>> +#endif /* __rtems__ */
> >>> left = data->len - slot->offset;
> >>> +#ifdef __rtems__
> >>> + if (left > 0) {
> >>> +#endif /* __rtems__ */
> >>> if (data->flags & MMC_DATA_READ) {
> >>> bus_dmamap_sync(slot->dmatag, slot->dmamap,
> >>> BUS_DMASYNC_PREREAD);
> >>> @@ -2222,6 +2259,9 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
> >>> }
> >>> /* Restart DMA. */
> >>> WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
> >>> +#ifdef __rtems__
> >>> + }
> >>> +#endif /* __rtems__ */
> >>> }
> >>> /* We have got all data. */
> >>> if (intmask & SDHCI_INT_DATA_END) {
> >>> --
> >>> 2.26.2
> >>>
> >>> _______________________________________________
> >>> devel mailing list
> >>> devel at rtems.org
> >>> http://lists.rtems.org/mailman/listinfo/devel
> >
>
> --
> --------------------------------------------
> embedded brains GmbH
> Herr Christian Mauderer
> Dornierstr. 4
> D-82178 Puchheim
> Germany
> email: christian.mauderer at embedded-brains.de
> Phone: +49-89-18 94 741 - 18
> Fax: +49-89-18 94 741 - 08
> PGP: Public key available on request.
>
> Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
More information about the devel
mailing list