Index: head/sys/arm/allwinner/a10_mmc.h =================================================================== --- head/sys/arm/allwinner/a10_mmc.h +++ head/sys/arm/allwinner/a10_mmc.h @@ -56,7 +56,8 @@ #define A10_MMC_IDIE 0x8C /* IDMAC Interrupt Enable Register */ #define A10_MMC_CHDA 0x90 #define A10_MMC_CBDA 0x94 -#define A10_MMC_FIFO 0x100 /* FIFO Access Address */ +#define A10_MMC_FIFO 0x100 /* FIFO Access Address (A10/A20) */ +#define A31_MMC_FIFO 0x200 /* FIFO Access Address (A31) */ /* A10_MMC_GCTRL */ #define A10_MMC_SOFT_RESET (1U << 0) Index: head/sys/arm/allwinner/a10_mmc.c =================================================================== --- head/sys/arm/allwinner/a10_mmc.c +++ head/sys/arm/allwinner/a10_mmc.c @@ -86,6 +86,7 @@ uint32_t a10_intr; uint32_t a10_intr_wait; void * a10_intrhand; + bus_size_t a10_fifo_reg; /* Fields required for DMA access. */ bus_addr_t a10_dma_desc_phys; @@ -170,6 +171,21 @@ return (ENXIO); } + /* + * Later chips use a different FIFO offset. Unfortunately the FDT + * uses the same compatible string for old and new implementations. + */ + switch (allwinner_soc_family()) { + case ALLWINNERSOC_SUN4I: + case ALLWINNERSOC_SUN5I: + case ALLWINNERSOC_SUN7I: + sc->a10_fifo_reg = A10_MMC_FIFO; + break; + default: + sc->a10_fifo_reg = A31_MMC_FIFO; + break; + } + /* Activate the module clock. */ switch (allwinner_soc_type()) { #if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20) @@ -513,9 +529,9 @@ if ((A10_MMC_READ_4(sc, A10_MMC_STAS) & bit)) return (1); if (write) - A10_MMC_WRITE_4(sc, A10_MMC_FIFO, buf[i]); + A10_MMC_WRITE_4(sc, sc->a10_fifo_reg, buf[i]); else - buf[i] = A10_MMC_READ_4(sc, A10_MMC_FIFO); + buf[i] = A10_MMC_READ_4(sc, sc->a10_fifo_reg); sc->a10_resid = i + 1; }