I started ESP8266 project, the first step was to support SDMMC over SPI. I have implemented SDMMC SPI interface years ago. The main challenge was to adapt it to new MCU core. After many attempts, it was up and running. Below are lessons learned.

{multithumb}All in all, the main aim was to work-around the way, ESP HSPI treats MOSI level. It is 0 when inactive, i.e. all the time we reading SPI packets, slave receives 00s. No SDMMCs I know start communicating under these conditions. They expect high MOSI, as shown on picture below, taken from the same SDMMC code working on STM32 platform.
SDMMC over SPI. Platform - STM32F103xx

While, if used as-is, ESP8266 HSPI demonstrates the following MOSI behavior:
SDMMC over SPI. Platform -  ESP8266. Default behavior (MOSI = 0 when reading, or idle, not working with SDMMC)

What we have to do to work-around this, is to unconfigure MOSI function to GPIO13 output, while reading SPI, and set it to 1.
While, if we got to write to SPI, we heve to re-configure GPIO13 back to MOSI, and proceed as usual. After that, SDMMC starts answering, and initialization finally completes OK.
SDMMC over SPI, ESP8266, working HSPI work-arond, MOSI = 1 when reading.

Below are excerpt files from the working SDMMC project.
After initialization code is successful (SDMMC is "open") we may use our storage elsewhere, for instance in famous ELM FAT FS library calls.

SDMMC over SPI C source open-close sample

// ESP includes
#include <esp_common.h>
#include <gpio.h>
#include <spi_interface.h>

#include "retarget.h"
// Our ESFWXE tuneups
#include "sdmmc_spiIntf.h"
// ESFWXE Drivers
#include <esfwxe/drivers/flash/sdmmc_spi.h>

// Application-specific SDMMC driver pieces implementation
static SpiAttr s_spi;
static SdmmcInfo s_sdmmc;

spiHANDLE sdmmcSpiBusGet(void)
{
  return &s_spi;  
}

SdmmcInfo* sdmmcInfoGet(void)
{
  return &s_sdmmc;  
}

static void sdmmcInfoReset(void)
{
	memset( 
    &s_sdmmc, 
    0, 
    SdmmcInfo_SZE
  );  
}

esBL sdmmcOpen(void)
{
	ES_DEBUG_TRACE("sdmmcOpen...\n");

  // reconfigure spi to low speed and open it
  spiConfig( 
    &s_spi, 
    sdmmcInitFreq 
  );
  
  sdmmcPowerOn(
    &s_spi, 
    &s_sdmmc, 
    TRUE
  );
  
  if( 
    sdmmcInit(
      &s_spi, 
      &s_sdmmc, 
      3300, //< SDMMC expected VCC voltage
      TRUE // Use SDMMC CRC
    ) &&
    sdmmcOk == (s_sdmmc.flags & sdmmcOk) &&
    sdmmcVoltageMismatch != (s_sdmmc.flags & sdmmcVoltageMismatch)
  )
  {
    // Set full-speed spi
    spiConfig(
      &s_spi,
      20000000
    );
    
    // Recalculate sdmmc timings for general 500ms timeout
    sdmmcCalcIoTimings(
      &s_spi, 
      &s_sdmmc, 
      500
    );

    ES_DEBUG_TRACE("...OK\n");
    return TRUE;
  }

  sdmmcPowerOn(
    &s_spi, 
    &s_sdmmc, 
    FALSE
  );
  
	ES_DEBUG_TRACE("...NOK\n");
  return FALSE;
}

void sdmmcClose(void)
{
	ES_DEBUG_TRACE("sdmmcClose...\n");
  
  sdmmcPowerOn(
    &s_spi, 
    &s_sdmmc, 
    FALSE
  );  
  
  sdmmcInfoReset();
  
	ES_DEBUG_TRACE("...OK\n");  
}

void sdmmcHwInit(void)
{
	ES_DEBUG_TRACE("sdmmcHwInit...\n");
  
  sdmmcInfoReset();
  sdmmcSpiInit(&s_spi);
  
	ES_DEBUG_TRACE("...OK\n");
}