This is an automated email from the ASF dual-hosted git repository.

kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 48df2deeb176d79619a71ee9d9fe346b995769ed
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Thu Jun 25 15:07:56 2026 +0200

    drivers/mmc: Rework to use change disk api
    
    Code limited card sie to 2GB due to how disk
    API worked (byte addressing).
    Now disk API uses block addressing.
    
    Code was also assuming that only FATFS can be
    used with MMC now card can be used as block
    device that can be mounted locally as FATFS
    but can also be accessed as disk by USB.
    
    Modlog is now supported.
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 hw/drivers/mmc/include/mmc/mmc.h |  76 ++--
 hw/drivers/mmc/pkg.yml           |   2 +
 hw/drivers/mmc/src/mmc.c         | 912 ++++++++++++++++++++++-----------------
 hw/drivers/mmc/syscfg.yml        |  36 +-
 4 files changed, 589 insertions(+), 437 deletions(-)

diff --git a/hw/drivers/mmc/include/mmc/mmc.h b/hw/drivers/mmc/include/mmc/mmc.h
index 07f78b594..4d376cbc3 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -47,67 +47,41 @@ extern "C" {
 #define MMC_ERASE_ERROR       (-11)
 #define MMC_ADDR_ERROR        (-12)
 
-extern struct disk_ops mmc_ops;
-
 struct mmc_spi_cfg {
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    const char *bus_name;
+#endif
     uint32_t initial_freq_khz;
     uint32_t freq_khz;
+    int pin_cs;
     uint8_t clock_mode;
 };
 
-/**
- * Initialize the MMC driver
- *
- * @param spi_num Number of the SPI channel to be used by MMC
- * @param spi_cfg Low-level device specific SPI configuration
- * @param ss_pin GPIO number of the SS pin
- *
- * @return 0 on success, non-zero on failure
- */
-int
-mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int ss_pin);
-
-/**
- * Read data from MMC
- *
- * @param mmc_id Id of the MMC device (currently must be 0)
- * @param addr Disk address (in bytes) to be read from
- * @param buf Buffer where data should be copied to
- * @param len Amount of data to read/copy
- *
- * @return 0 on success, non-zero on failure
- */
-int
-mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, uint32_t len);
-
-/**
- * Write data to the MMC
- *
- * @param mmc_id Id of the MMC device (currently must be 0)
- * @param addr Disk address (in bytes) to be written to
- * @param buf Buffer where data should be copied from
- * @param len Amount of data to copy/write
- *
- * @return 0 on success, non-zero on failure
- */
-int
-mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, uint32_t len);
-
-/**
- * TODO
- */
-int
-mmc_ioctl(uint8_t mmc_id, uint32_t cmd, void *arg);
-
+struct mmc_spi {
 #if MYNEWT_VAL(BUS_DRIVER_PRESENT)
-struct mmc_config {
-    struct bus_spi_node_cfg spi_cfg;
-};
-struct mmc {
     struct bus_spi_node node;
+#else
+    int spi_num;
+#endif
+    struct mmc_spi_cfg mmc_spi_cfg;
 };
 
-int mmc_create_dev(struct mmc *mmc, const char *name, struct mmc_config 
*mmc_cfg);
+typedef struct mmc_disk {
+    struct mmc_spi spi;
+    disk_t disk;
+    disk_info_t disk_info;
+    uint8_t ocr[4];
+    uint8_t csd[16];
+    uint8_t scr[8];
+    uint8_t cid[16];
+    uint8_t app_cmd : 1;
+    struct os_sem sem;
+} mmc_disk_t;
+
+#if MYNEWT_VAL_BUS_DRIVER_PRESENT
+int mmc_create_dev(mmc_disk_t *mmc, const char *name, struct mmc_spi_cfg 
*mmc_cfg);
+#else
+int mmc_create(mmc_disk_t *mmc, int spi_num, struct mmc_spi_cfg *mmc_cfg);
 #endif
 
 #ifdef __cplusplus
diff --git a/hw/drivers/mmc/pkg.yml b/hw/drivers/mmc/pkg.yml
index d7f9ced40..680bff770 100644
--- a/hw/drivers/mmc/pkg.yml
+++ b/hw/drivers/mmc/pkg.yml
@@ -25,6 +25,8 @@ pkg.keywords:
 
 pkg.deps:
     - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/util/bit_set"
+    - "@apache-mynewt-core/fs/disk"
 
 pkg.deps.BUS_DRIVER_PRESENT:
     - "@apache-mynewt-core/hw/bus/drivers/spi_common"
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index 8b93623ef..098d93c8c 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -24,13 +24,30 @@
 #include <disk/disk.h>
 #include <mmc/mmc.h>
 #include <stdio.h>
+#include <bit_set/bit_set.h>
 
 #define MIN(n, m) (((n) < (m)) ? (n) : (m))
 
+typedef enum {
+    FORMAT_R1,
+    FORMAT_R1B,
+    FORMAT_R2,
+    FORMAT_R3,
+    FORMAT_R4,
+    FORMAT_R5,
+    FORMAT_R6,
+    FORMAT_R7,
+} reponse_format_t;
+
+typedef uint8_t sd_cmd_t;
+
 /* MMC commands used by the driver */
 #define CMD0                (0)            /* GO_IDLE_STATE */
 #define CMD1                (1)            /* SEND_OP_COND (MMC) */
+#define CMD6                (8)            /* SEND_IF_COND */
 #define CMD8                (8)            /* SEND_IF_COND */
+#define CMD9                (9)            /* SEND_CSD */
+#define CMD10               (10)           /* SEND_CID */
 #define CMD12               (12)           /* STOP_TRANSMISSION */
 #define CMD16               (16)           /* SET_BLOCKLEN */
 #define CMD17               (17)           /* READ_SINGLE_BLOCK */
@@ -39,7 +56,10 @@
 #define CMD25               (25)           /* WRITE_MULTIPLE_BLOCK */
 #define CMD55               (55)           /* APP_CMD */
 #define CMD58               (58)           /* READ_OCR */
-#define ACMD41              (0x80 + 41)    /* SEND_OP_COND (SDC) */
+
+#define ACMD13              (13)           /*  */
+#define ACMD41              (41)           /* SEND_OP_COND (SDC) */
+#define ACMD51              (51)           /* SEND_SCR */
 
 #define HCS                 ((uint32_t) 1 << 30)
 
@@ -59,30 +79,57 @@
 #define R_ADDR_ERROR        (0x20)
 #define R_PARAM_ERROR       (0x40)
 
+#define CMD_OK(status)      (((status) & 0x7E) == 0)
+#define CMD_FAILED(status)  (((status) & 0x7E) != 0)
+
 #define START_BLOCK         (0xFE)
 #define START_BLOCK_TOKEN   (0xFC)
 #define STOP_TRAN_TOKEN     (0xFD)
 
 #define BLOCK_LEN           (512)
 
-static uint8_t g_block_buf[BLOCK_LEN + 2];
-
-#if !MYNEWT_VAL(BUS_DRIVER_PRESENT)
-
-static struct mmc {
-    int spi_num;
-    int ss_pin;
-    struct mmc_spi_cfg mmc_spi_cfg;
-} g_mmc;
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
 
-/* FIXME: currently limited to single MMC spi device */
-static struct mmc *mmcs[1] = { &g_mmc };
+static struct mmc_spi_cfg mmc0_config = {
+    .initial_freq_khz = 500,
+    .freq_khz = MYNEWT_VAL_MMC_SPI_FREQ,
+    .clock_mode = MYNEWT_VAL_MMC_SPI_CLOCK_MODE,
+    .bus_name = MYNEWT_VAL_MMC_SPI_BUS_NAME,
+    .pin_cs = MYNEWT_VAL_MMC_SPI_CS_PIN,
+};
 
-#else
-static struct mmc *mmcs[1];
-static uint8_t mmcs_count;
 #endif
 
+const char *
+mmc_error_str(char *buf, uint8_t status)
+{
+    sprintf(buf, "0x%X", status);
+    if (status == 0xff) {
+        strcat(buf, " MMC_CARD_ERROR");
+    } else if (status == 0x7F) {
+        strcat(buf, " Unsupported");
+    } else {
+        if (status & R_IDLE) {
+            strcat(buf, " R_IDLE");
+        }
+        if (status & R_ERASE_RESET) {
+            strcat(buf, " R_ERASE_RESET");
+        }
+        if (status & R_ILLEGAL_COMMAND) {
+            strcat(buf, " R_ILLEGAL_COMMAND");
+        } else if (status & R_CRC_ERROR) {
+            strcat(buf, " R_CRC_ERROR");
+        } else if (status & R_ERASE_ERROR) {
+            strcat(buf, " R_ERASE_ERROR");
+        } else if (status & R_ADDR_ERROR) {
+            strcat(buf, " R_ADDR_ERROR");
+        } else if (status & R_PARAM_ERROR) {
+            strcat(buf, " R_PARAM_ERROR");
+        }
+    }
+    return buf;
+}
+
 static int
 error_by_response(uint8_t status)
 {
@@ -111,90 +158,104 @@ error_by_response(uint8_t status)
     return (rc);
 }
 
-static struct mmc *
-mmc_cfg_dev(uint8_t id)
+static inline void
+mmc_led_on(void)
 {
-    if (id != 0) {
-        return NULL;
+    if (MYNEWT_VAL_MMC_LED_PIN >= 0) {
+        hal_gpio_write(MYNEWT_VAL_MMC_LED_PIN, MYNEWT_VAL_MMC_LED_ON_VALUE);
     }
-
-    return mmcs[0];
 }
 
-#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static inline void
+mmc_led_off(void)
+{
+    if (MYNEWT_VAL_MMC_LED_PIN >= 0) {
+        hal_gpio_write(MYNEWT_VAL_MMC_LED_PIN, !MYNEWT_VAL_MMC_LED_ON_VALUE);
+    }
+}
 
 static void
-mmc_spi_set_cs(struct mmc *mmc, int cs)
+mmc_spi_set_cs(mmc_disk_t *mmc, int cs)
 {
-    /* Let bus driver actiave CS, deactivation is done here */
-    if (cs) {
-        hal_gpio_write(mmc->node.pin_cs, cs);
-    }
+    hal_gpio_write(mmc->spi.mmc_spi_cfg.pin_cs, cs);
 }
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+
 static int
-mmc_spi_tx(struct mmc *mmc, const uint8_t *buf, uint16_t count)
+mmc_spi_tx(mmc_disk_t *mmc, const uint8_t *buf, uint16_t count)
 {
-    return bus_node_write(&mmc->node.bnode.odev, buf, count, 1000, 
BUS_F_NOSTOP);
+    return bus_node_write(&mmc->spi.node.bnode.odev, buf, count, 1000, 
BUS_F_NOSTOP);
 }
 
 static int
-mmc_spi_rx(struct mmc *mmc, uint8_t *buf, uint16_t count)
+mmc_spi_rx(mmc_disk_t *mmc, uint8_t *buf, uint16_t count)
 {
     memset(buf, 0xFF, count);
-    return bus_node_duplex_write_read(&mmc->node.bnode.odev, buf, buf, count, 
1000, BUS_F_NOSTOP);
+    return bus_node_duplex_write_read(&mmc->spi.node.bnode.odev, buf, buf,
+                                      count, 1000, BUS_F_NOSTOP);
 }
 
 #else
 
-static void
-mmc_spi_set_cs(struct mmc *mmc, int cs)
-{
-    hal_gpio_write(mmc->ss_pin, cs);
-}
-
 static int
-mmc_spi_tx(struct mmc *mmc, const uint8_t *buf, uint16_t count)
+mmc_spi_tx(mmc_disk_t *mmc, const uint8_t *buf, uint16_t count)
 {
+    mmc_led_on();
+
     for (int i = 0; i < count; i++) {
-        hal_spi_tx_val(mmc->spi_num, buf[i]);
+        hal_spi_tx_val(mmc->spi.spi_num, buf[i]);
     }
+
+    mmc_led_off();
     return 0;
 }
 
 static int
-mmc_spi_rx(struct mmc *mmc, uint8_t *buf, uint16_t count)
+mmc_spi_rx(mmc_disk_t *mmc, uint8_t *buf, uint16_t count)
 {
+    mmc_led_on();
+
     for (int i = 0; i < count; i++) {
-        buf[i] = hal_spi_tx_val(mmc->spi_num, 0xFF);
+        buf[i] = hal_spi_tx_val(mmc->spi.spi_num, 0xFF);
     }
+
+    mmc_led_off();
+
     return 0;
 }
 
 #endif
 
 static int
-mmc_spi_tx_byte(struct mmc *mmc, uint8_t b)
+mmc_spi_tx_byte(mmc_disk_t *mmc, uint8_t b)
 {
     return mmc_spi_tx(mmc, &b, 1);
 }
 
+static inline void
+mmc_send_extra_clocks(mmc_disk_t *mmc)
+{
+    static const uint8_t extra_bytes[] = { 0xFF, 0xFF, 0xFF };
+
+    if (MYNEWT_VAL_MMC_SEND_EXTRA_CLOCKS) {
+        mmc_spi_tx(mmc, extra_bytes, sizeof(extra_bytes));
+    }
+}
+
 static uint8_t
-send_mmc_cmd(struct mmc *mmc, uint8_t cmd, uint32_t payload)
+send_mmc_cmd(mmc_disk_t *mmc, sd_cmd_t cmd, uint32_t payload)
 {
     int n;
-    uint8_t status;
+    uint16_t status;
     uint8_t crc;
     uint8_t buf[6];
+    char strbuf[30];
 
-    if (cmd & 0x80) {
-        /* TODO: refactor recursion? */
-        /* TODO: error checking */
-        send_mmc_cmd(mmc, CMD55, 0);
-    }
+    mmc_led_on();
 
     /* 4.7.2: Command Format */
-    buf[0] = 0x40 | (cmd & ~0x80);
+    buf[0] = 0x40 | cmd;
     buf[1] = (uint8_t)(payload >> 24);
     buf[2] = (uint8_t)(payload >> 16);
     buf[3] = (uint8_t)(payload >> 8);
@@ -220,213 +281,309 @@ send_mmc_cmd(struct mmc *mmc, uint8_t cmd, uint32_t 
payload)
     buf[5] = crc;
     mmc_spi_tx(mmc, buf, 6);
 
-    for (n = 255; n > 0; n--) {
+    for (n = 10; n > 0; n--) {
         mmc_spi_rx(mmc, buf, 1);
         status = buf[0];
-        if ((status & 0x80) == 0) {
-            break;
+        if (status != 0xFF) {
+            if (status & 0x80) {
+                mmc_spi_rx(mmc, buf, 1);
+                status = status << 8 | buf[0];
+                while (status & 0x8000) {
+                    status <<= 1;
+                }
+                status >>= 8;
+            }
+            if (status != 0x7F) {
+                break;
+            }
         }
     }
+    if (CMD_FAILED(status)) {
+        MMC_LOG_ERROR("%sCMD%d status %s", mmc->app_cmd ? "A" : "", cmd,
+                      mmc_error_str(strbuf, status));
+    } else {
+        MMC_LOG_DEBUG("%sCMD%d status %s", mmc->app_cmd ? "A" : "", cmd,
+                      mmc_error_str(strbuf, status));
+    }
+    mmc->app_cmd = 0;
 
-    return status;
-}
+    mmc_led_off();
 
-#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    return (uint8_t)status;
+}
 
-static void
-mmc_open_cb(struct bus_node *node)
+static uint8_t
+mmc_cmd_rx(mmc_disk_t *mmc, uint8_t cmd, uint32_t payload, uint8_t response[],
+           size_t response_size)
 {
-    int rc;
-    int i;
     uint8_t status;
-    uint8_t cmd_resp[4];
-    uint32_t ocr;
-    os_time_t timeout;
-    struct mmc *mmc = (struct mmc *)node;
 
-    /**
-     * NOTE: The state machine below follows:
-     *       Section 6.4.1: Power Up Sequence for SD Bus Interface.
-     *       Section 7.2.1: Mode Selection and Initialization.
-     */
-
-    /* give 10ms for VDD rampup */
-    os_time_delay(OS_TICKS_PER_SEC / 100);
+    mmc_spi_set_cs(mmc, 0);
+    status = send_mmc_cmd(mmc, cmd, payload);
 
-    /* send the required >= 74 clock cycles (10 bytes, 80 clock cycles). */
-    for (i = 0; i < 10; i++) {
-        mmc_spi_tx_byte(mmc, 0xff);
+    if (response_size && response != NULL && CMD_OK(status)) {
+        mmc_spi_rx(mmc, response, response_size);
     }
 
-    /* put card in idle state */
-    status = send_mmc_cmd(mmc, CMD0, 0);
-
     mmc_spi_set_cs(mmc, 1);
-    /* No card inserted or bad card? */
-    if (status != R_IDLE) {
-        rc = error_by_response(status);
-        goto out;
-    }
 
-    /**
-     * FIXME: while doing a hot-swap of the card or powering off the board
-     * it is required to send a CMD1 here otherwise CMD8's response will
-     * be always invalid.
-     *
-     * Why is this happening? CMD1 should never be required for SDxC cards...
-     */
+    mmc_send_extra_clocks(mmc);
 
-    /**
-     * 4.3.13: Ask for 2.7-3.3V range, send 0xAA pattern
-     *
-     * NOTE: cards that are not compliant with "Physical Spec Version 2.00"
-     *       will answer this with R_ILLEGAL_COMMAND.
-     */
-    status = send_mmc_cmd(mmc, CMD8, 0x1AA);
-    if (status != 0xff && !(status & R_ILLEGAL_COMMAND)) {
+    return status;
+}
 
-        /**
-         * Ver2.00 or later SD Memory Card
-         */
+static uint8_t
+mmc_cmd_r1(mmc_disk_t *mmc, uint8_t cmd, uint32_t payload)
+{
+    return mmc_cmd_rx(mmc, cmd, payload, NULL, 0);
+}
 
-        /* Read the contents of R7 */
-        mmc_spi_rx(mmc, cmd_resp, 4);
+static uint8_t
+mmc_wait_for_data(mmc_disk_t *mmc, uint32_t timeout_ms)
+{
+    os_time_t timeout = os_time_get() + os_time_ms_to_ticks32(timeout_ms);
+    uint8_t res;
 
-        /* Did the card return the same pattern? */
-        if (cmd_resp[3] != 0xAA) {
-            rc = MMC_RESPONSE_ERROR;
-            goto out;
+    do {
+        mmc_spi_rx(mmc, &res, 1);
+        if (res != 0xFF) {
+            break;
         }
+    } while (OS_TIME_TICK_LT(os_time_get(), timeout));
 
-        /**
-         * 4.3.13 Send Interface Condition Command (CMD8)
-         *   Check VHS for 2.7-3.6V support
-         */
-        if (cmd_resp[2] != 0x01) {
-            rc = MMC_VOLTAGE_ERROR;
-            goto out;
-        }
+    return res;
+}
 
-        /**
-         * Wait for card to leave IDLE state or time out
-         */
+static uint8_t
+mmc_cmd_receive_data(mmc_disk_t *mmc, uint8_t cmd, uint32_t payload,
+                     uint8_t *buffer, int count)
+{
+    int status;
+    uint8_t res;
 
-        timeout = os_time_get() + OS_TICKS_PER_SEC;
-        for (;;) {
-            status = send_mmc_cmd(mmc, ACMD41, HCS);
-            if ((status & R_IDLE) == 0 || os_time_get() > timeout) {
-                break;
-            }
-            os_time_delay(OS_TICKS_PER_SEC / 10);
-        }
+    mmc_spi_set_cs(mmc, 0);
 
-        if (status) {
-            rc = error_by_response(status);
-            goto out;
+    status = send_mmc_cmd(mmc, cmd, payload);
+
+    if (CMD_OK(status)) {
+        res = mmc_wait_for_data(mmc, 20);
+        if (res == START_BLOCK) {
+            mmc_spi_rx(mmc, buffer, count);
         }
+    }
 
-        /**
-         * Check if this is an high density card
-         */
+    mmc_spi_set_cs(mmc, 1);
 
-        status = send_mmc_cmd(mmc, CMD58, 0);
-        mmc_spi_rx(mmc, cmd_resp, 4);
-        if (status == 0 && (cmd_resp[0] & (1 << 6))) {  /* FIXME: CCS */
-            /**
-             * TODO: if CCS is set this is an SDHC or SDXC card!
-             *       SDSC uses byte addressing, SDHC/SDXC block addressing
-             *
-             *       can also check the whole voltage range supported here
-             */
-        }
+    mmc_send_extra_clocks(mmc);
 
-    } else if (status != 0xff && status & R_ILLEGAL_COMMAND) {
+    return status;
+}
 
-        /**
-         * Ver1.x SD Memory Card or Not SD Memory Card
-         */
+static uint8_t
+mmc_acmd(mmc_disk_t *mmc, uint8_t cmd, uint32_t payload, uint8_t *response,
+         size_t response_size)
+{
+    uint8_t status;
 
-        ocr = send_mmc_cmd(mmc, CMD58, 0);
+    status = mmc_cmd_r1(mmc, CMD55, 0);
+    if (CMD_OK(status)) {
+        mmc->app_cmd = 1;
+        status = mmc_cmd_rx(mmc, cmd, payload, response, response_size);
+    }
 
-        /* TODO: check if voltage range is ok! */
+    return status;
+}
 
-        if (ocr & R_ILLEGAL_COMMAND) {
+static uint8_t
+mmc_acmd_with_data(mmc_disk_t *mmc, uint8_t cmd, uint32_t payload,
+                   uint8_t *buffer, size_t count)
+{
+    uint8_t status;
 
-        }
+    status = mmc_cmd_r1(mmc, CMD55, 0);
 
-        /* TODO: set blocklen */
+    if (CMD_OK(status)) {
+        mmc->app_cmd = 1;
+        status = mmc_cmd_receive_data(mmc, cmd, payload, buffer, count);
+    }
 
+    return status;
+}
+
+#define SCR_SCR_STRUCTURE_POS       60
+#define SCR_SCR_STRUCTURE_LEN       4
+#define SCR_SD_SPEC_POS             56
+#define SCR_SD_SPEC_LEN             4
+#define SD_BUS_WIDTHS_POS           48
+#define SD_BUS_WIDTHS_LEN           4
+#define SCR_SD_SPEC3_POS            47
+#define SCR_SD_SPEC3_LEN            1
+#define SCR_CMD_SUPPORT_POS         32
+#define SCR_CMD_SUPPORT_LEN         14
+
+#define CSD_V1_CSD_STRUCTURE_POS    126
+#define CSD_V1_CSD_STRUCTURE_LEN    2
+#define CSD_V1_CSD_STRUCTURE_VER_1  0
+#define CSD_V1_READ_BL_LEN_POS      80
+#define CSD_V1_READ_BL_LEN_LEN      4
+#define CSD_V1_C_SIZE_POS           62
+#define CSD_V1_C_SIZE_LEN           12
+#define CSD_V1_C_SIZE_MULT_POS      47
+#define CSD_V1_C_SIZE_MULT_LEN      3
+
+#define CSD_V2_CSD_STRUCTURE_POS    126
+#define CSD_V2_CSD_STRUCTURE_LEN    2
+#define CSD_V2_CSD_STRUCTURE_VER_2  1
+#define CSD_V2_C_SIZE_POS           48
+#define CSD_V2_C_SIZE_LEN           22
+
+static uint32_t
+csd_sector_count(const uint8_t csd[16])
+{
+    uint32_t ver = bit_set_get_uint32(csd, CSD_V1_CSD_STRUCTURE_POS,
+                                      CSD_V1_CSD_STRUCTURE_LEN);
+    uint32_t c_size;
+    uint32_t c_size_mult;
+
+    if (ver == CSD_V1_CSD_STRUCTURE_VER_1) {
+        c_size = bit_set_get_uint32(csd, CSD_V1_C_SIZE_POS, CSD_V1_C_SIZE_LEN);
+        c_size_mult = bit_set_get_uint32(csd, CSD_V1_C_SIZE_MULT_POS,
+                                         CSD_V1_C_SIZE_MULT_LEN);
+        return (c_size + 1) << (c_size_mult + 2);
     } else {
-        rc = error_by_response(status);
+        c_size = bit_set_get_uint32(csd, CSD_V2_C_SIZE_POS, CSD_V2_C_SIZE_LEN);
+        return (c_size + 1) << 10;
     }
-
-out:
-    mmc_spi_set_cs(mmc, 1);
-    (void)rc;
 }
 
 int
-mmc_create_dev(struct mmc *mmc, const char *name, struct mmc_config *mmc_cfg)
+mmc_read_csd(mmc_disk_t *mmc, uint8_t csd[16])
 {
-    int rc;
-    struct bus_node_callbacks cbs = {
-        .open = mmc_open_cb,
-    };
+    uint8_t status;
+    uint32_t ver;
+    uint32_t c_size;
 
-    bus_node_set_callbacks((struct os_dev *)mmc, &cbs);
+    status = mmc_cmd_receive_data(mmc, CMD9, 0, csd, 16);
+
+    if (CMD_OK(status)) {
+        bit_set_reverse(csd, 128);
 
-    rc = bus_spi_node_create(name, &mmc->node, &mmc_cfg->spi_cfg, NULL);
-    if (rc == 0 && mmcs_count < ARRAY_SIZE(mmcs)) {
-        mmcs[mmcs_count++] = mmc;
+        ver = bit_set_get_uint32(csd, CSD_V1_CSD_STRUCTURE_POS,
+                                 CSD_V1_CSD_STRUCTURE_LEN);
+        MMC_LOG_INFO("CSD ver %d", ver == CSD_V1_CSD_STRUCTURE_VER_1 ? 1 : 2);
+
+        if (ver == CSD_V1_CSD_STRUCTURE_VER_1) {
+            c_size = bit_set_get_uint32(csd, CSD_V1_C_SIZE_POS, 
CSD_V1_C_SIZE_LEN);
+            MMC_LOG_DEBUG("CSD c_size %d c_size_mult %d read_bl_len %d)", 
(int)c_size,
+                          (int)bit_set_get_uint32(csd, CSD_V1_C_SIZE_MULT_POS,
+                                                  CSD_V1_C_SIZE_MULT_LEN),
+                          (int)bit_set_get_uint32(csd, CSD_V1_READ_BL_LEN_POS,
+                                                  CSD_V1_READ_BL_LEN_LEN));
+        } else {
+            c_size = bit_set_get_uint32(csd, CSD_V2_C_SIZE_POS, 
CSD_V2_C_SIZE_LEN);
+            MMC_LOG_DEBUG("CSD c_size %d (%ul sectors %u MB)", (int)c_size,
+                          csd_sector_count(csd), csd_sector_count(csd) >> 11);
+        }
     }
 
-    return rc;
+    return status;
 }
 
-#else
-/**
- * Initialize the MMC driver
- *
- * @param spi_num Number of the SPI channel to be used by MMC
- * @param spi_cfg Low-level device specific SPI configuration
- * @param ss_pin Number of SS pin if SW controlled, -1 otherwise
- *
- * @return 0 on success, non-zero on failure
- */
-int
-mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int ss_pin)
+uint8_t
+mmc_read_cid(mmc_disk_t *mmc, uint8_t cid[16])
 {
-    int rc;
-    int i;
     uint8_t status;
-    uint8_t cmd_resp[4];
-    uint32_t ocr;
-    os_time_t timeout;
-    /* TODO: create new struct for every new spi mmc, add to SLIST */
-    struct mmc *mmc = mmcs[0];
-    mmc->ss_pin = ss_pin;
-    mmc->mmc_spi_cfg = *spi_cfg;
 
-    mmc->spi_num = spi_num;
+    status = mmc_cmd_receive_data(mmc, CMD10, 0, (uint8_t *)cid, 16);
+
+    if (CMD_OK(status)) {
+        MMC_LOG_INFO("CID MID 0x%x", cid[0]);
+        MMC_LOG_INFO("CID OID %c%c", cid[1], cid[2]);
+        MMC_LOG_INFO("CID PNM %c%c%c%c%c", cid[3], cid[4], cid[5], cid[6], 
cid[7]);
+        MMC_LOG_INFO("CID PRV %c.%c", (cid[8] >> 4) + '0', (cid[8] & 15) + 
'0');
+        MMC_LOG_INFO("CID MDT %d.%02d",
+                     2000 + ((cid[13] & 15) << 4) + (cid[14] >> 4), (cid[14] & 
15));
+    }
+
+    return status;
+}
+
+uint8_t
+mmc_read_scr(mmc_disk_t *mmc, uint8_t scr[8])
+{
+    uint8_t status;
+
+    status = mmc_acmd_with_data(mmc, ACMD51, 0, scr, 8);
+
+    if (CMD_OK(status)) {
+        bit_set_reverse(scr, 64);
+        MMC_LOG_INFO("SCR structure %d",
+                     (int)bit_set_get_uint32(scr, SCR_SCR_STRUCTURE_POS,
+                                             SCR_SCR_STRUCTURE_LEN));
+        MMC_LOG_INFO("SCR sd_spec %d",
+                     (int)bit_set_get_uint32(scr, SCR_SD_SPEC_POS, 
SCR_SD_SPEC_LEN));
+        MMC_LOG_INFO("SCR sd_bus_width 0x%x",
+                     (int)bit_set_get_uint32(scr, SD_BUS_WIDTHS_POS, 
SD_BUS_WIDTHS_LEN));
+    }
+
+    return status;
+}
+
+static void
+mmc_set_init_settings(mmc_disk_t *mmc)
+{
+#if MYNEWT_VAL_BUS_DRIVER_PRESENT
+    mmc->spi.node.freq = mmc->spi.mmc_spi_cfg.initial_freq_khz;
+#else
+    int rc;
+
     struct hal_spi_settings spi_settings = {
         .data_order = HAL_SPI_MSB_FIRST,
-        .data_mode = mmc->mmc_spi_cfg.clock_mode,
-        .baudrate = mmc->mmc_spi_cfg.initial_freq_khz,
+        .data_mode = mmc->spi.mmc_spi_cfg.clock_mode,
+        .baudrate = mmc->spi.mmc_spi_cfg.initial_freq_khz,
         .word_size = HAL_SPI_WORD_SIZE_8BIT,
     };
 
-    hal_gpio_init_out(mmc->ss_pin, 1);
-
-    rc = hal_spi_config(mmc->spi_num, &spi_settings);
-    if (rc) {
-        return (rc);
+    hal_spi_disable(mmc->spi.spi_num);
+    rc = hal_spi_config(mmc->spi.spi_num, &spi_settings);
+    if (rc == 0) {
+        hal_spi_enable(mmc->spi.spi_num);
     }
+#endif
+}
 
-    hal_spi_set_txrx_cb(mmc->spi_num, NULL, NULL);
-    rc = hal_spi_enable(mmc->spi_num);
-    if (rc) {
-        return (rc);
+static void
+mmc_set_working_settings(mmc_disk_t *mmc)
+{
+#if MYNEWT_VAL_BUS_DRIVER_PRESENT
+    mmc->spi.node.freq = mmc->spi.mmc_spi_cfg.freq_khz;
+#else
+    int rc;
+
+    struct hal_spi_settings spi_settings = {
+        .data_order = HAL_SPI_MSB_FIRST,
+        .data_mode = mmc->spi.mmc_spi_cfg.clock_mode,
+        .baudrate = mmc->spi.mmc_spi_cfg.freq_khz,
+        .word_size = HAL_SPI_WORD_SIZE_8BIT,
+    };
+
+    hal_spi_disable(mmc->spi.spi_num);
+    rc = hal_spi_config(mmc->spi.spi_num, &spi_settings);
+    if (rc == 0) {
+        hal_spi_enable(mmc->spi.spi_num);
     }
+#endif
+    MMC_LOG_INFO("Switching to %d kHz", mmc->spi.mmc_spi_cfg.freq_khz);
+}
+
+static int
+mmc_init(mmc_disk_t *mmc)
+{
+    int rc = 0;
+    uint8_t status;
+    uint8_t cmd_resp[4];
+    uint8_t buf[10] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF };
+    os_time_t timeout;
 
     /**
      * NOTE: The state machine below follows:
@@ -437,28 +594,25 @@ mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int 
ss_pin)
     /* give 10ms for VDD rampup */
     os_time_delay(OS_TICKS_PER_SEC / 100);
 
-    mmc_spi_set_cs(mmc, 0);
+    mmc_set_init_settings(mmc);
 
+    mmc_spi_set_cs(mmc, 1);
+
+    MMC_LOG_DEBUG("Send clocks to switch to SPI mode");
     /* send the required >= 74 clock cycles (10 bytes, 80 clock cycles). */
-    for (i = 0; i < 10; i++) {
-        mmc_spi_tx_byte(mmc, 0xff);
-    }
+    mmc_spi_tx(mmc, buf, 10);
 
     /* put card in idle state */
-    status = send_mmc_cmd(mmc, CMD0, 0);
+    status = mmc_cmd_r1(mmc, CMD0, 0);
 
-    mmc_spi_set_cs(mmc, 1);
     /* No card inserted or bad card? */
     if (status != R_IDLE) {
-        rc = error_by_response(status);
+        MMC_LOG_ERROR("Card not detected");
+        rc = MMC_CARD_ERROR;
         goto out;
     }
 
-    hal_spi_disable(mmc->spi_num);
-    spi_settings.baudrate = mmc->mmc_spi_cfg.freq_khz;
-    rc = hal_spi_config(mmc->spi_num, &spi_settings);
-    hal_spi_enable(mmc->spi_num);
-    mmc_spi_set_cs(mmc, 0);
+    mmc_set_working_settings(mmc);
 
     /**
      * FIXME: while doing a hot-swap of the card or powering off the board
@@ -474,18 +628,19 @@ mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int 
ss_pin)
      * NOTE: cards that are not compliant with "Physical Spec Version 2.00"
      *       will answer this with R_ILLEGAL_COMMAND.
      */
-    status = send_mmc_cmd(mmc, CMD8, 0x1AA);
+    status = mmc_cmd_rx(mmc, CMD8, 0x1AA, cmd_resp, 4);
+    if (status != R_IDLE) {
+        status = mmc_cmd_rx(mmc, CMD8, 0x1AA, cmd_resp, 4);
+    }
     if (status != 0xff && !(status & R_ILLEGAL_COMMAND)) {
 
         /**
          * Ver2.00 or later SD Memory Card
          */
 
-        /* Read the contents of R7 */
-        mmc_spi_rx(mmc, cmd_resp, 4);
-
         /* Did the card return the same pattern? */
         if (cmd_resp[3] != 0xAA) {
+            MMC_LOG_ERROR("CMD8 response error %02x%02x", cmd_resp[2], 
cmd_resp[3]);
             rc = MMC_RESPONSE_ERROR;
             goto out;
         }
@@ -495,6 +650,7 @@ mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int 
ss_pin)
          *   Check VHS for 2.7-3.6V support
          */
         if (cmd_resp[2] != 0x01) {
+            MMC_LOG_ERROR("CMD8 voltage error %02x%02x", cmd_resp[2], 
cmd_resp[3]);
             rc = MMC_VOLTAGE_ERROR;
             goto out;
         }
@@ -505,7 +661,7 @@ mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int 
ss_pin)
 
         timeout = os_time_get() + OS_TICKS_PER_SEC;
         for (;;) {
-            status = send_mmc_cmd(mmc, ACMD41, HCS);
+            status = mmc_acmd(mmc, ACMD41, HCS, NULL, 0);
             if ((status & R_IDLE) == 0 || os_time_get() > timeout) {
                 break;
             }
@@ -513,7 +669,6 @@ mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int 
ss_pin)
         }
 
         if (status) {
-            rc = error_by_response(status);
             goto out;
         }
 
@@ -521,42 +676,113 @@ mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int 
ss_pin)
          * Check if this is an high density card
          */
 
-        status = send_mmc_cmd(mmc, CMD58, 0);
-        mmc_spi_rx(mmc, cmd_resp, 4);
-        if (status == 0 && (cmd_resp[0] & (1 << 6))) {  /* FIXME: CCS */
-            /**
-             * TODO: if CCS is set this is an SDHC or SDXC card!
-             *       SDSC uses byte addressing, SDHC/SDXC block addressing
-             *
-             *       can also check the whole voltage range supported here
-             */
+        status = mmc_cmd_rx(mmc, CMD58, 0, mmc->ocr, 4);
+        if (CMD_FAILED(status)) {
+            goto out;
         }
 
+        memset(&mmc->csd, 0, sizeof(mmc->csd));
+        memset(&mmc->cid, 0, sizeof(mmc->cid));
+        memset(&mmc->scr, 0, sizeof(mmc->scr));
+
+        /* CMD9 read csd */
+        status = mmc_read_csd(mmc, mmc->csd);
+        if (CMD_FAILED(status)) {
+            goto out;
+        }
+        /* ACMD51 read scr */
+        status = mmc_read_scr(mmc, mmc->scr);
+        if (CMD_FAILED(status)) {
+            goto out;
+        }
+        /* CMD10 read cid, some older cards don't have this */
+        (void)mmc_read_cid(mmc, mmc->cid);
     } else if (status != 0xff && status & R_ILLEGAL_COMMAND) {
 
+        mmc_cmd_r1(mmc, CMD0, 0);
         /**
          * Ver1.x SD Memory Card or Not SD Memory Card
          */
 
-        ocr = send_mmc_cmd(mmc, CMD58, 0);
+        status = mmc_cmd_rx(mmc, CMD58, 0, cmd_resp, 4);
+    }
 
-        /* TODO: check if voltage range is ok! */
+out:
+    if (rc == 0 && status != 0) {
+        rc = error_by_response(status);
+    }
+    return rc;
+}
 
-        if (ocr & R_ILLEGAL_COMMAND) {
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
 
-        }
+static void
+mmc_open_cb(struct bus_node *node)
+{
+    mmc_disk_t *mmc = CONTAINER_OF(node, mmc_disk_t, spi);
+    mmc_init(mmc);
+}
 
-        /* TODO: set blocklen */
+int
+mmc_create_dev(mmc_disk_t *mmc, const char *name, struct mmc_spi_cfg *mmc_cfg)
+{
+    int rc;
+    struct bus_node_callbacks cbs = {
+        .open = mmc_open_cb,
+    };
+    struct bus_spi_node_cfg spi_cfg = {
+        .freq = mmc_cfg->initial_freq_khz,
+        .pin_cs = -1,
+        .data_order = BUS_SPI_DATA_ORDER_MSB,
+        .mode = mmc_cfg->clock_mode,
+        .node_cfg.bus_name = mmc_cfg->bus_name,
+    };
 
-    } else {
-        rc = error_by_response(status);
+    if (mmc_cfg->pin_cs >= 0) {
+        hal_gpio_init_out(mmc_cfg->pin_cs, 1);
     }
 
-out:
-    mmc_spi_set_cs(mmc, 1);
+    mmc->spi.mmc_spi_cfg = *mmc_cfg;
+    os_sem_init(&mmc->sem, 0);
+    bus_node_set_callbacks((struct os_dev *)mmc, &cbs);
+
+    rc = bus_spi_node_create(name, &mmc->spi.node, &spi_cfg, NULL);
+
     return rc;
 }
 
+#else
+
+int
+mmc_create(mmc_disk_t *mmc, int spi_num, struct mmc_spi_cfg *mmc_cfg)
+{
+    int rc;
+
+    mmc->spi.spi_num = spi_num;
+    mmc->spi.mmc_spi_cfg = *mmc_cfg;
+
+    struct hal_spi_settings spi_settings = {
+        .data_order = HAL_SPI_MSB_FIRST,
+        .data_mode = mmc->spi.mmc_spi_cfg.clock_mode,
+        .baudrate = mmc->spi.mmc_spi_cfg.initial_freq_khz,
+        .word_size = HAL_SPI_WORD_SIZE_8BIT,
+    };
+
+    hal_gpio_init_out(mmc->spi.mmc_spi_cfg.pin_cs, 1);
+
+    rc = hal_spi_config(mmc->spi.spi_num, &spi_settings);
+    if (rc) {
+        return (rc);
+    }
+
+    hal_spi_set_txrx_cb(mmc->spi.spi_num, NULL, NULL);
+    rc = hal_spi_enable(mmc->spi.spi_num);
+    if (rc) {
+        return (rc);
+    }
+    return 0;
+}
+
 #endif
 
 /**
@@ -565,7 +791,7 @@ out:
  * operations are in progress.
  */
 static uint8_t
-wait_busy(struct mmc *mmc)
+wait_busy(mmc_disk_t *mmc)
 {
     os_time_t timeout;
     uint8_t res;
@@ -582,59 +808,57 @@ wait_busy(struct mmc *mmc)
     return res;
 }
 
+static int
+mmc_get_info(const struct disk *disk, struct disk_info *info)
+{
+    mmc_disk_t *mmc = CONTAINER_OF(disk, mmc_disk_t, disk);
+
+    *info = mmc->disk_info;
+
+    return 0;
+}
+
+static int
+mmc_eject(struct disk *disk)
+{
+    mmc_disk_t *mmc = CONTAINER_OF(disk, mmc_disk_t, disk);
+    /* TODO: Check what needs to be done here */
+
+    mmc->disk_info.present = false;
+    return 0;
+}
+
 /**
  * @return 0 on success, non-zero on failure
  */
-int
-mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, uint32_t len)
+static int
+mmc_read(struct disk *disk, uint32_t lba, void *buf, uint32_t block_count)
 {
     uint8_t cmd;
     uint8_t res;
     int rc;
-    size_t block_len;
-    size_t block_count;
-    os_time_t timeout;
-    uint32_t block_addr;
-    size_t offset;
-    size_t index;
-    size_t amount;
-    struct mmc *mmc;
+    mmc_disk_t *mmc;
+    uint8_t crc[2];
 
-    mmc = mmc_cfg_dev(mmc_id);
-    if (mmc == NULL) {
-        return (MMC_DEVICE_ERROR);
-    }
+    mmc = CONTAINER_OF(disk, mmc_disk_t, disk);
 
     rc = MMC_OK;
 
-    block_len = (len + BLOCK_LEN - 1) & ~(BLOCK_LEN - 1);
-    block_count = block_len / BLOCK_LEN;
-    block_addr = addr / BLOCK_LEN;
-    offset = addr - (block_addr * BLOCK_LEN);
-
     mmc_spi_set_cs(mmc, 0);
 
     cmd = (block_count == 1) ? CMD17 : CMD18;
-    res = send_mmc_cmd(mmc, cmd, block_addr);
+    res = send_mmc_cmd(mmc, cmd, lba);
     if (res) {
         rc = error_by_response(res);
         goto out;
     }
 
-    index = 0;
     while (block_count--) {
         /**
          * 7.3.3 Control tokens
          *   Wait up to 200ms for control token.
          */
-        timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
-        do {
-            mmc_spi_rx(mmc, &res, 1);
-            if (res != 0xFF) {
-                break;
-            }
-            os_time_delay(OS_TICKS_PER_SEC / 20);
-        } while (os_time_get() < timeout);
+        res = mmc_wait_for_data(mmc, 200);
 
         /**
          * 7.3.3.2 Start Block Tokens and Stop Tran Token
@@ -644,23 +868,16 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, 
uint32_t len)
             goto out;
         }
 
-        mmc_spi_rx(mmc, g_block_buf, BLOCK_LEN + 2 /* CRC */);
-
-        /* TODO: CRC-16 not used here but would be cool to have */
-
-        amount = MIN(BLOCK_LEN - offset, len);
+        mmc_spi_rx(mmc, buf, BLOCK_LEN);
+        mmc_spi_rx(mmc, crc, 2);
 
-        memcpy(((uint8_t *)buf + index), &g_block_buf[offset], amount);
-
-        offset = 0;
-        len -= amount;
-        index += amount;
+        buf = (uint8_t *)buf + BLOCK_LEN;
     }
 
     if (cmd == CMD18) {
         send_mmc_cmd(mmc, CMD12, 0);
-        wait_busy(mmc);
     }
+    wait_busy(mmc);
 
 out:
     mmc_spi_set_cs(mmc, 1);
@@ -671,74 +888,25 @@ out:
  * @return 0 on success, non-zero on failure
  */
 int
-mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, uint32_t len)
+mmc_write(struct disk *disk, uint32_t lba, const void *buf, uint32_t 
block_count)
 {
     uint8_t cmd;
     uint8_t res;
-    size_t block_len;
-    size_t block_count;
-    os_time_t timeout;
-    uint32_t block_addr;
-    size_t offset;
-    size_t index;
-    size_t amount;
+    uint8_t crc[2] = { 0xFF, 0xFF };
     int rc;
-    struct mmc *mmc;
-
-    mmc = mmc_cfg_dev(mmc_id);
-    if (mmc == NULL) {
-        return (MMC_DEVICE_ERROR);
-    }
-
-    block_len = (len + BLOCK_LEN - 1) & ~(BLOCK_LEN - 1);
-    block_count = block_len / BLOCK_LEN;
-    block_addr = addr / BLOCK_LEN;
-    offset = addr - (block_addr * BLOCK_LEN);
+    mmc_disk_t *mmc;
+    mmc = CONTAINER_OF(disk, mmc_disk_t, disk);
 
     mmc_spi_set_cs(mmc, 0);
 
-    /**
-     * This code ensures that if the requested address doesn't align with the
-     * beginning address of a sector, the initial bytes are first read to the
-     * buffer to be then written later.
-     *
-     * NOTE: this code will never run when using a FS that is sector addressed
-     * like FAT (offset is always 0).
-     */
-    if (offset) {
-        res = send_mmc_cmd(mmc, CMD17, block_addr);
-        if (res != 0) {
-            rc = error_by_response(res);
-            goto out;
-        }
-
-        timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
-        do {
-            mmc_spi_rx(mmc, &res, 1);
-            if (res != 0xff) {
-                break;
-            }
-            os_time_delay(OS_TICKS_PER_SEC / 20);
-        } while (os_time_get() < timeout);
-
-        if (res != START_BLOCK) {
-            rc = MMC_CARD_ERROR;
-            goto out;
-        }
-
-        mmc_spi_rx(mmc, g_block_buf, BLOCK_LEN + 2);
-    }
-
     /* now start write */
-
     cmd = (block_count == 1) ? CMD24 : CMD25;
-    res = send_mmc_cmd(mmc, cmd, block_addr);
+    res = send_mmc_cmd(mmc, cmd, lba);
     if (res) {
         rc = error_by_response(res);
         goto out;
     }
 
-    index = 0;
     while (block_count--) {
         /**
          * 7.3.3.2 Start Block Tokens and Stop Tran Token
@@ -749,13 +917,8 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, 
uint32_t len)
             mmc_spi_tx_byte(mmc, START_BLOCK_TOKEN);
         }
 
-        amount = MIN(BLOCK_LEN - offset, len);
-        memcpy(&g_block_buf[offset], ((uint8_t *)buf + index), amount);
-
-        /* CRC */
-        g_block_buf[BLOCK_LEN] = 0xFF;
-        g_block_buf[BLOCK_LEN + 1] = 0xFF;
-        mmc_spi_tx(mmc, g_block_buf, BLOCK_LEN + 2);
+        mmc_spi_tx(mmc, buf, BLOCK_LEN);
+        mmc_spi_tx(mmc, crc, 2);
 
         /**
          * 7.3.3.1 Data Response Token
@@ -769,9 +932,7 @@ mmc_write(uint8_t mmc_id, uint32_t addr, const void *buf, 
uint32_t len)
             wait_busy(mmc);
         }
 
-        offset = 0;
-        len -= amount;
-        index += amount;
+        buf = (uint8_t *)buf + BLOCK_LEN;
     }
 
     if (cmd == CMD25) {
@@ -802,65 +963,46 @@ out:
 /*
  *
  */
-int
-mmc_ioctl(uint8_t mmc_id, uint32_t cmd, void *arg)
-{
-    return 0;
-}
-
-/*
- *
- */
-struct disk_ops mmc_ops = {
-    .read  = &mmc_read,
-    .write = &mmc_write,
-    .ioctl = &mmc_ioctl,
+disk_ops_t mmc_disk_ops = {
+    .get_info = mmc_get_info,
+    .eject = mmc_eject,
+    .read = mmc_read,
+    .write = mmc_write,
 };
 
-#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
-static struct mmc mmc;
-static struct mmc_config mmc_config = {
-    .spi_cfg = {
-        .pin_cs = MYNEWT_VAL(MMC_SPI_CS_PIN),
-        .freq = MYNEWT_VAL(MMC_SPI_FREQ),
-        .data_order = BUS_SPI_DATA_ORDER_MSB,
-        .mode = BUS_SPI_MODE_0,
-        .node_cfg.bus_name = MYNEWT_VAL(MMC_SPI_BUS_NAME),
-        .node_cfg.lock_timeout_ms = 1000,
+static mmc_disk_t mmc0 = {
+    .disk.ops = &mmc_disk_ops,
+    .disk_info = {
+        .name = "SD0",
     }
 };
-#endif
 
 void
 mmc_pkg_init(void)
 {
-#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
-    if (0 == mmc_create_dev(&mmc, MYNEWT_VAL(MMC_DEV_NAME), &mmc_config)) {
-        if (MYNEWT_VAL(MMC_AUTO_MOUNT)) {
-            os_dev_open(MYNEWT_VAL(MMC_DEV_NAME), 1000, NULL);
-        }
+    int rc;
+
+    if (MYNEWT_VAL_MMC_LED_PIN >= 0) {
+        hal_gpio_init_out(MYNEWT_VAL_MMC_LED_PIN, 
!MYNEWT_VAL_MMC_LED_ON_VALUE);
     }
+
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    rc = mmc_create_dev(&mmc0, MYNEWT_VAL(MMC_DEV_NAME), &mmc0_config);
 #else
     struct mmc_spi_cfg spi_cfg = {
-        .clock_mode = HAL_SPI_MODE0,
+        .clock_mode = MYNEWT_VAL_MMC_SPI_CLOCK_MODE,
         .initial_freq_khz = 400,
-        .freq_khz = MYNEWT_VAL(MMC_SPI_FREQ),
+        .freq_khz = MYNEWT_VAL_MMC_SPI_FREQ,
+        .pin_cs = MYNEWT_VAL_MMC_SPI_CS_PIN,
     };
-    mmc_init(MYNEWT_VAL(MMC_SPI_NUM), &spi_cfg, MYNEWT_VAL(MMC_SPI_CS_PIN));
+    rc = mmc_create(&mmc0, MYNEWT_VAL(MMC_SPI_NUM), &spi_cfg);
 #endif
-    if (MYNEWT_VAL(MMC_AUTO_MOUNT)) {
-        uint8_t *sector = malloc(512);
-
-        if (sector == NULL) {
-        } else {
-            /* For now only FAT partition are mounted */
-            if (mmc_read(0, 0, sector, 512) == 0) {
-                /* Check if first partition is FAT */
-                if (sector[450] == 0x0C || sector[450] == 0x07) {
-                    disk_register(MYNEWT_VAL(MMC_DEV_NAME), "fatfs", &mmc_ops);
-                }
-            }
+    if (rc == 0 && MYNEWT_VAL_MMC_AUTO_INIT) {
+        if (mmc_init(&mmc0) == 0) {
+            mmc0.disk_info.block_size = BLOCK_LEN;
+            mmc0.disk_info.block_count = csd_sector_count(mmc0.csd);
+            mmc0.disk_info.present = 1;
+            mn_disk_inserted(&mmc0.disk);
         }
-        free(sector);
     }
 }
diff --git a/hw/drivers/mmc/syscfg.yml b/hw/drivers/mmc/syscfg.yml
index 1c6bfad45..04d8caf35 100644
--- a/hw/drivers/mmc/syscfg.yml
+++ b/hw/drivers/mmc/syscfg.yml
@@ -29,12 +29,46 @@ syscfg.defs:
     MMC_SPI_CS_PIN:
         description: MMC SPI CS pin.
         value: -1
+    MMC_SPI_CLOCK_MODE:
+        description: >
+            MMC SPI clock mode. Mode 0 and 3 should work.
+            Mode 3 can be used in case of pullup on CLK line.
+        value: 0
     MMC_DEV_NAME:
         description: MMC SPI device name for bus driver build.
         value: '"mmc"'
+    MMC_LED_PIN:
+        description: Pin to use to indicate MMC access.
+        value: -1
+    MMC_LED_ON_VALUE:
+        description: Value of MSC_LED_PIN to turn LED on.
+        value: 1
+    MMC_SEND_EXTRA_CLOCKS:
+        description: >
+            Number of bytes to send AFTER CS is deactivated.
+            This can fix problem with some older cards that start
+            to send status with out of sync clock.
+        value: 0
+
     MMC_PKG_SYSINIT_STAGE:
         description: Sysinit stage for MMC package.
-        value: 5
+        value: 200
+    MMC_AUTO_INIT:
+        descritpion: >
+            Initialize disk during startup
+        value: 1
     MMC_AUTO_MOUNT:
         description: Try to mount disk at creation time.
         value: 1
+
+    MMC_LOG_MODULE:
+        description: 'Numeric module ID to use for MMC log messages.'
+        value: 11
+    MMC_LOG_LVL:
+        description: 'Minimum level for the MMC log.'
+        value: 1
+
+syscfg.logs:
+    MMC_LOG:
+        module: MYNEWT_VAL(MMC_LOG_MODULE)
+        level: MYNEWT_VAL(MMC_LOG_LVL)


Reply via email to