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.maude...@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@rtems.org >> http://lists.rtems.org/mailman/listinfo/devel -- -------------------------------------------- embedded brains GmbH Herr Christian Mauderer Dornierstr. 4 D-82178 Puchheim Germany email: christian.maude...@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. _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel