[PATCH rtems-libbsd 1/2] sdhci: Add some workarrounds for i.MX

Christian Mauderer christian.mauderer at embedded-brains.de
Thu Sep 10 07:05:45 UTC 2020


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