Merge contributed patch to extend support of atxmega.
[bertos.git] / bertos / cpu / cortex-m3 / drv / sd_sam3.c
index 8bb27ae48fbfc164e8120cfa9809bcad9f19b90f..0c1c0a0628f51acd7980c6237e59df6bfd344e33 100644 (file)
  * invalidate any other reasons why the executable file might be covered by
  * the GNU General Public License.
  *
- * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
  * -->
  *
  * \brief Function library for secure digital memory.
  *
- * \author Francesco Sacchi <batt@develer.com>
+ * \author Daniele Basile <asterix@develer.com>
  */
 
 
@@ -85,6 +85,7 @@
 #define CMD8_V_ECHO_REPLY         0xFF
 #define CMD8_SUPP_V_RANGE_REPLY   0xFF00
 
+#define SD_STATUS_ERROR          BV(19)
 
 #define SD_GET_ERRORS(status)   ((status) & 0xFFF80000)
 #define SD_ADDR_TO_RCA(addr)    (uint32_t)(((addr) << 16) & 0xFFFF0000)
@@ -310,7 +311,6 @@ int sd_sendIfCond(Sd *sd)
                return 0;
        }
        LOG_ERR("IF_COND: %lx\n", (sd->status));
-
        return -1;
 }
 
@@ -340,6 +340,7 @@ int sd_sendAppOpCond(Sd *sd)
                        }
                }
        }
+
        return -1;
 }
 
@@ -429,6 +430,7 @@ int sd_appStatus(Sd *sd)
        if (hsmci_sendCmd(13, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT))
        {
                LOG_ERR("STATUS: %lx\n", HSMCI_SR);
+               sd->status |= SD_STATUS_ERROR;
                return -1;
        }
 
@@ -451,6 +453,7 @@ INLINE int sd_cardSelection(Sd *sd, uint32_t rca)
        if (hsmci_sendCmd(7, rca, HSMCI_CMDR_RSPTYP_R1B))
        {
                LOG_ERR("SELECT_SD: %lx\n", HSMCI_SR);
+               sd->status |= SD_STATUS_ERROR;
                return -1;
        }
 
@@ -521,7 +524,6 @@ int sd_setBusWidth(Sd *sd, size_t len)
        hsmci_readResp(&(sd->status), 1);
        if ((sd->status) & (SD_STATUS_APP_CMD | SD_STATUS_READY))
        {
-               hsmci_setBusWidth(len);
 
                uint8_t arg = 0;
                if (len == 4)
@@ -539,7 +541,10 @@ int sd_setBusWidth(Sd *sd, size_t len)
                LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status));
 
                if (sd->status & SD_STATUS_READY)
+               {
+                       hsmci_setBusWidth(len);
                        return 0;
+               }
        }
 
        LOG_ERR("SET_BUS_WIDTH REP %lx\n", (sd->status));
@@ -628,19 +633,18 @@ void sd_setHightSpeed(Sd *sd)
 static size_t sd_SdReadDirect(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size)
 {
        ASSERT(buf);
+       ASSERT(!((uint32_t)buf & 0x3));
+
        Sd *sd = SD_CAST(b);
        LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size);
 
-       if (sd_selectCard(sd) < 0)
-               return -1;
-
+       hsmci_waitTransfer();
        hsmci_read(buf, size / 4, sd->b.blk_size);
 
        if (hsmci_sendCmd(17, idx * sd->b.blk_size + offset, HSMCI_CMDR_RSPTYP_48_BIT |
                        BV(HSMCI_CMDR_TRDIR) | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
        {
                LOG_ERR("SIGLE_BLK_READ: %lx\n", HSMCI_SR);
-               sd_deSelectCard(sd);
                return -1;
        }
 
@@ -652,31 +656,27 @@ static size_t sd_SdReadDirect(struct KBlock *b, block_idx_t idx, void *buf, size
        if (sd->status & SD_STATUS_READY)
        {
                hsmci_waitTransfer();
-               sd_deSelectCard(sd);
                return size;
        }
-
-       sd_deSelectCard(sd);
        return -1;
 }
 
 static size_t sd_SdWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size_t offset, size_t size)
 {
        ASSERT(buf);
+       ASSERT(!((uint32_t)buf & 0x3));
+
        Sd *sd = SD_CAST(b);
        const uint32_t *_buf = (const uint32_t *)buf;
-       LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size);
-
-       if (sd_selectCard(sd) < 0)
-               return 0;
+       LOG_INFO("writing block %ld, offset %d, size %d\n", idx, offset, size);
 
+       hsmci_waitTransfer();
        hsmci_write(_buf, size / 4, sd->b.blk_size);
 
        if (hsmci_sendCmd(24, idx * sd->b.blk_size + offset, HSMCI_CMDR_RSPTYP_48_BIT |
                                                HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
        {
                LOG_ERR("SIGLE_BLK_WRITE: %lx\n", HSMCI_SR);
-               sd_deSelectCard(sd);
                return -1;
        }
 
@@ -687,12 +687,9 @@ static size_t sd_SdWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size
 
        if (sd->status & SD_STATUS_READY)
        {
-               hsmci_waitTransfer();
-               sd_deSelectCard(sd);
                return size;
        }
 
-       sd_deSelectCard(sd);
        return -1;
 }
 
@@ -783,7 +780,6 @@ static bool sd_blockInit(Sd *sd, KFile *ch)
                        sd_set_BlockLen(sd, SD_DEFAULT_BLOCKLEN);
                        sd_setBus4bit(sd);
                        sd_setHightSpeed(sd);
-                       sd_deSelectCard(sd);
 
                        #if CONFIG_SD_AUTOASSIGN_FAT
                                disk_assignDrive(&sd->b, 0);