]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/mmc.c
Expression eval: Repair unary + and -
[z180-stamp.git] / avr / mmc.c
index d780fef4657ddcb5db01a8823ad9ef249456d92b..d45cdf540dba8c76ebe99010fdf48365476f84ff 100644 (file)
--- a/avr/mmc.c
+++ b/avr/mmc.c
@@ -7,44 +7,47 @@
 
 #include "common.h"
 #include <stdbool.h>
+#include <util/atomic.h>
 #include "timer.h"
 #include "spi.h"
 #include "diskio.h"
-//#include "debug.h"
+#include "debug.h"
 
 #define MAX_DRV                2
 
 /* Port Controls  (Platform dependent) */
 /* SD card socket connections */
 
-//#define SD_CD_0      SBIT(PORT,)             /* Card detect switch */
+/* TODO: config.h cofig macros */
+
+//#define SD_CD_0              SBIT(PORT,)                             /* Card detect switch */
 //#define SD_CD_0_IN   SBIT(PIN,)
 //#define SD_CD_0_DDR  SBIT(DDR,)
 
-//#define SD_WP_0      SBIT(PORT,)             /* Write protect switch */
+//#define SD_WP_0              SBIT(PORT,)                             /* Write protect switch */
 //#define SD_WP_0_IN   SBIT(PIN,)
 //#define SD_WP_0_DDR  SBIT(DDR,)
 
-#define SD_CS_0                SBIT(PORTB,0)           /* Chip select pin */
-#define SD_CS_0_IN     SBIT(PINB,0)
+#define SD_CS_0                SBIT(PORTB,0)                           /* Chip select/Card sense pin */
+//#define SD_CS_0_IN   SBIT(PINB,0)
 #define SD_CS_0_DDR    SBIT(DDRB,0)
 
-#define SD_CD_1                SBIT(PORTG,3)           /* Card detect switch */
+
+#define SD_CD_1                SBIT(PORTG,3)                           /* Card detect switch */
 #define SD_CD_1_IN     SBIT(PING,3)
 #define SD_CD_1_DDR    SBIT(DDRG,3)
 
-//#define SD_WP_1      SBIT(PORTG,5)           /* Write protect switch */
-#define SD_WP_1_IN     SBIT(PING,5)
-#define SD_WP_1_DDR    SBIT(DDRG,5)
+//#define SD_WP_1              SBIT(PORTG,5)                   /* Write protect switch */
+//#define SD_WP_1_IN   SBIT(PING,5)
+//#define SD_WP_1_DDR  SBIT(DDRG,5)
 
-#define SD_CS_1                SBIT(PORTG,4)           /* Chip select pin */
-#define SD_CS_1_IN     SBIT(PING,4)
+#define SD_CS_1                SBIT(PORTG,4)                           /* Chip select/Card sense pin */
+//#define SD_CS_1_IN   SBIT(PING,4)
 #define SD_CS_1_DDR    SBIT(DDRG,4)
 
 
-#define        FCLK_SLOW()     SPISetMMCInitClock()    /* Set slow clock (100k-400k) */
-#define        FCLK_FAST()     SPISetFastClock()       /* Set fast clock (depends on the CSD) */
-
+#define        SPI_CLK_SLOW()  SPISetMMCInitClock()    /* Set slow clock (100k-400k) */
+#define        SPI_CLK_FAST()  SPISetFastClock()               /* Set fast clock (depends on the CSD) */
 
 /*--------------------------------------------------------------------------
  Definitions for MMC/SDC command
@@ -113,14 +116,33 @@ int wait_ready (void)     /* 1:OK, 0:Timeout */
 static
 void deselect(BYTE drv)
 {
-//     debug("*** enter deselect()\n");
+       //debug("*** enter deselect(%.2x)\n", drv);
        if (drv == 0)
                SD_CS_0 = 1;
-       else
+       else {
                SD_CS_1 = 1;
+       }
+
        /* Dummy clock (TODO: force DO hi-z for multiple slave SPI) */
+       if (socket[drv].stat & STA_FAST)
+               SPI_CLK_FAST();
+       else
+               SPI_CLK_SLOW();
        spi_rcvr();
-//     debug("***  exit deselect()\n");
+       SPI_OFF();
+
+       if (drv == 0) {
+#ifdef SD_CS_0_IN
+               SD_CS_0_DDR = 0;                /* Input */
+               SD_CS_0 = 0;                    /* No Pullup */
+#endif
+       } else {
+#ifdef SD_CS_1_IN
+               SD_CS_1_DDR = 0;
+               SD_CS_1 = 0;
+#endif
+       }
+       //debug("***  exit deselect(%.2x)\n", drv);
 }
 
 /*-----------------------------------------------------------------------*/
@@ -130,20 +152,35 @@ void deselect(BYTE drv)
 static
 int select(BYTE drv)   /* 1:Successful, 0:Timeout */
 {
-//     debug("*** enter select()\n");
-       if (drv == 0)
+       //debug("*** enter select(%.2x)\n", drv);
+       if (drv == 0) {
+#ifdef SD_CS_0_IN
+               SD_CS_0 = 1;
+               SD_CS_0_DDR = 1;
+#endif
                SD_CS_0 = 0;
-       else
+       } else {
+#ifdef SD_CS_1_IN
+               SD_CS_1 = 1;
+               SD_CS_1_DDR = 1;
+#endif
                SD_CS_1 = 0;
+       }
+
+       if (socket[drv].stat & STA_FAST)
+               SPI_CLK_FAST();
+       else
+               SPI_CLK_SLOW();
+
        /* Dummy clock (force DO enabled) */
        spi_rcvr();
 
        if (wait_ready()) {
-//             debug("***  exit select() == 1\n");
+               //debug("***  exit select() == 1\n");
                return 1;       /* OK */
        }
        deselect(drv);
-//     debug("***  exit select() == 0\n");
+       //debug("***  exit select() == 0\n");
 
        return 0;       /* Timeout */
 }
@@ -157,57 +194,29 @@ int select(BYTE drv)      /* 1:Successful, 0:Timeout */
 static
 void power_on(BYTE drv)
 {
-//     debug("*** enter power_on()\n");
+       //debug("*** enter power_on(%.2x)\n", drv);
 
        if (drv == 0) {
 #ifdef SD_PWR_0
-               SD_PWR_0_DDR = 1;       /* Turns on PWR pin as output */
                SD_PWR_0 = 0;           /* Drives PWR pin high */
-
-               for (uint32_t to = get_timer(0); get_timer(to) < 30;)
-                       ; /* Wait for 30ms */
 #endif
 
-#ifdef SD_CD_0
-               /* Card detect, input with pullup */
-               SD_CD_0_DDR = 0;
-               SD_CD_0 = 1;
-#endif
-#ifdef SD_WP_0
-               SD_WP_0_DDR = 0;
-               SD_WP_0 = 1;
-#endif
-               SD_CS_0 = 1;
-               SD_CS_0_DDR = 1;
        } else {
 #ifdef SD_PWR_1
-               SD_PWR_1_DDR = 1;       /* Turns on PWR pin as output */
                SD_PWR_1 = 0;           /* Drives PWR pin high */
-
+#endif
+       }
+#if defined SD_PWR_0 || defined SD_PWR_1
                for (uint32_t to = get_timer(0); get_timer(to) < 30;)
                        ; /* Wait for 30ms */
 #endif
-
-#ifdef SD_CD_1
-               /* Card detect, input with pullup */
-               SD_CD_1_DDR = 0;
-               SD_CD_1 = 1;
-#endif
-#ifdef SD_WP_1
-               SD_WP_1_DDR = 0;
-               SD_WP_1 = 1;
-#endif
-               SD_CS_1 = 1;
-               SD_CS_1_DDR = 1;
-       }
-
-//     debug("***  exit power_on()\n");
+       //debug("***  exit power_on(%.2x)\n", drv);
 }
 
 static
 void power_off(BYTE drv)
 {
-//     debug("*** enter power_off()\n");
+       //debug("*** enter power_off(%.2x)\n", drv);
        select(drv);            /* Wait for card ready */
        deselect(drv);
 
@@ -220,8 +229,10 @@ void power_off(BYTE drv)
                SD_PWR_1 = 1;           /* Socket power OFF */
 #endif
        }
-       socket[drv].stat |= STA_NOINIT;
-//     debug("***  exit power_off()\n");
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               socket[drv].stat |= STA_NOINIT;
+       }
+       //debug("***  exit power_off(%.2x)\n", drv);
 }
 
 #if 0
@@ -330,8 +341,6 @@ BYTE send_cmd (             /* Returns R1 resp (bit7==1:Send failed) */
        } argtmp;
        BYTE n, res;
 
-//     debug("*** send_cmd( %.2x )\n", cmd);
-
        if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
                cmd &= 0x7F;
                res = send_cmd(drv, CMD55, 0);
@@ -339,11 +348,15 @@ BYTE send_cmd (           /* Returns R1 resp (bit7==1:Send failed) */
                        return res;
        }
 
+       //debug("*** send_cmd( %.2x )", cmd);
+
        /* Select the card and wait for ready except to stop multiple block read */
        if (cmd != CMD12) {
                deselect(drv);
-               if (!select(drv))
+               if (!select(drv)) {
+                       //debug(" == %.2x\n", 0xff);
                        return 0xFF;
+               }
        }
 
        /* Send command packet */
@@ -369,6 +382,7 @@ BYTE send_cmd (             /* Returns R1 resp (bit7==1:Send failed) */
                res = spi_rcvr();
        while ((res & 0x80) && --n);
 
+       //debug(" == %.2x\n", res);
        return res; /* Return with the response value */
 }
 
@@ -378,6 +392,57 @@ BYTE send_cmd (            /* Returns R1 resp (bit7==1:Send failed) */
 
  ---------------------------------------------------------------------------*/
 
+void setup_mmc(void)
+{
+#ifdef SD_PWR_0
+               SD_PWR_1 = 1;           /* Drives PWR pin low */
+               SD_PWR_0_DDR = 1;       /* Turns on PWR pin as output */
+#endif
+#ifdef SD_WP_0
+               SD_WP_0_DDR = 0;
+               SD_WP_0 = 1;            /* Pullup */
+#endif
+
+#ifdef SD_PWR_1
+               SD_PWR_1 = 1;           /* Drives PWR pin low */
+               SD_PWR_1_DDR = 1;       /* Turns on PWR pin as output */
+#endif
+#ifdef SD_WP_1
+               SD_WP_1_DDR = 0;
+               SD_WP_1 = 1;            /* Pullup */
+#endif
+
+       /* SPI as master */
+       PRR0 &= ~_BV(PRSPI);
+       SPI_DDR = (SPI_DDR & ~(_BV(SPI_MISO) | _BV(SPI_SS)))
+                       | _BV(SPI_MOSI) | _BV(SPI_SCK);
+       SPI_PORT = SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK));
+
+#if defined SD_CD_0
+       SD_CD_0_DDR = 0;
+       SD_CD_0 = 1;                    /* Pullup */
+#elif defined SD_CS_0_IN
+       SD_CS_0_DDR = 0;
+       SD_CS_0 = 0;
+#endif
+#if defined SD_CD_0 || !defined SD_CS_0_IN
+       SD_CS_0 = 1;
+       SD_CS_0_DDR = 1;
+#endif
+
+#if defined SD_CD_1
+       SD_CD_1_DDR = 0;
+       SD_CD_1 = 1;                    /* Pullup */
+#elif defined SD_CS_1_IN
+       SD_CS_1_DDR = 0;
+       SD_CS_1 = 0;                    /* No Pullup */
+#endif
+#if defined SD_CD_1 || !defined SD_CS_1_IN
+       SD_CS_1 = 1;                    /* Set High */
+       SD_CS_1_DDR = 1;
+#endif
+}
+
 /*-----------------------------------------------------------------------*/
 /* Initialize Disk Drive                                                 */
 /*-----------------------------------------------------------------------*/
@@ -389,14 +454,19 @@ DSTATUS disk_initialize (
 )
 {
        BYTE n, cmd, ty, ocr[4];
+       DSTATUS res;
 
        if (drv >= MAX_DRV)
-               return STA_NOINIT; /* Supports only single drive */
-       if (socket[drv].stat & STA_NODISK)
-               return socket[drv].stat; /* No card in the socket */
-
+               return STA_NOINIT;
+       res = socket[drv].stat;
+       if (res & STA_NODISK) {
+               return res & STAT_MASK; /* No card in the socket */
+       }
        power_on(drv); /* Force socket power on */
-       FCLK_SLOW();
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               socket[drv].stat &= ~STA_FAST;
+       }
+       SPI_CLK_SLOW();
        for (n = 10; n; n--)
                spi_rcvr(); /* 80 dummy clocks */
 
@@ -441,12 +511,16 @@ DSTATUS disk_initialize (
        deselect(drv);
 
        if (ty) { /* Initialization succeded */
-               socket[drv].stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
+               /* Clear STA_NOINIT */
+               ATOMIC_BLOCK(ATOMIC_FORCEON) {
+                       res = (socket[drv].stat & ~STA_NOINIT) | STA_FAST;
+                       socket[drv].stat = res;
+               }
        } else { /* Initialization failed */
                power_off(drv);
        }
 
-       return socket[drv].stat;
+       return socket[drv].stat & STAT_MASK;
 }
 
 /*-----------------------------------------------------------------------*/
@@ -457,9 +531,16 @@ DSTATUS disk_status (
        BYTE drv        /* Physical drive nmuber (0) */
 )
 {
+       DSTATUS res;
+
+       //debug("*****  disk_status(%.2x)", drv);
        if (drv >= MAX_DRV)
-               return STA_NOINIT;
-       return socket[drv].stat;
+               res = STA_NOINIT;
+       else
+               res = socket[drv].stat & STAT_MASK;
+
+       //debug(" == %.2x\n", res);
+       return res;
 }
 
 /*-----------------------------------------------------------------------*/
@@ -483,7 +564,6 @@ DRESULT disk_read (
        /* Convert to byte address if needed */
        if (!(socket[drv].CardType & CT_BLOCK))
                sector *= 512;
-       FCLK_FAST();
 
        /*  READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
        cmd = count > 1 ? CMD18 : CMD17;
@@ -513,17 +593,19 @@ DRESULT disk_write (
        UINT count      /* Sector count (1..255) */
 )
 {
+       DSTATUS res;
+
        if (drv >= MAX_DRV || !count)
                return RES_PARERR;
-       if (socket[drv].stat & STA_NOINIT)
+       res = socket[drv].stat;
+       if ( res & STA_NOINIT)
                return RES_NOTRDY;
-       if (socket[drv].stat & STA_PROTECT)
+       if (res & STA_PROTECT)
                return RES_WRPRT;
 
        /* Convert to byte address if needed */
        if (!(socket[drv].CardType & CT_BLOCK))
                sector *= 512;
-       FCLK_FAST();
 
        if (count == 1) {
                /* Single block write */
@@ -574,7 +656,8 @@ DRESULT disk_ioctl (
        if (socket[drv].stat & STA_NOINIT)
                return RES_NOTRDY;
 
-       FCLK_FAST();
+       /* TODO: SPI clock? */
+
        switch (cmd) {
        case CTRL_SYNC :                /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
                if (select(drv))
@@ -655,7 +738,6 @@ DRESULT disk_ioctl (
 
        case CTRL_POWER_OFF :   /* Power off */
                power_off(drv);
-               socket[drv].stat |= STA_NOINIT;
                res = RES_OK;
                break;
 
@@ -682,29 +764,45 @@ void disk_timerproc (void)
 #ifdef SD_WP_0
        if (SD_WP_0_IN == 0)                    /* Write protected */
                s |= STA_PROTECT;
-       else                                    /* Write enabled */
+       else                                                    /* Write enabled */
                s &= ~STA_PROTECT;
 #endif
-#ifdef SD_CD_0
+
+#if defined SD_CD_0
        if (SD_CD_0_IN == 0)                    /* Card inserted */
                s &= ~STA_NODISK;
-       else                                    /* Socket empty */
+       else                                                    /* Socket empty */
                s |= (STA_NODISK | STA_NOINIT);
+#elif defined SD_CS_0_IN
+       if (SD_CS_0_DDR == 0) {
+               if (SD_CS_0_IN == 1)            /* Card inserted */
+                       s &= ~STA_NODISK;
+               else                                            /* Socket empty */
+                       s |= (STA_NODISK | STA_NOINIT);
+       }
 #endif
-       socket[0].stat = s;                     /* Update MMC status */
+       socket[0].stat = s;                             /* Update MMC status */
 
        s = socket[1].stat;
 #ifdef SD_WP_1
        if (SD_WP_1_IN == 0)                    /* Write protected */
                s |= STA_PROTECT;
-       else                                    /* Write enabled */
+       else                                                    /* Write enabled */
                s &= ~STA_PROTECT;
 #endif
-#ifdef SD_CD_1
+
+#if defined SD_CD_1
        if (SD_CD_1_IN == 0)                    /* Card inserted */
                s &= ~STA_NODISK;
-       else                                    /* Socket empty */
+       else                                                    /* Socket empty */
                s |= (STA_NODISK | STA_NOINIT);
+#elif defined SD_CS_1_IN
+       if (SD_CS_1_DDR == 0) {
+               if (SD_CS_1_IN == 1)            /* Card inserted */
+                       s &= ~STA_NODISK;
+               else                                            /* Socket empty */
+                       s |= (STA_NODISK | STA_NOINIT);
+       }
 #endif
        socket[1].stat = s;                     /* Update MMC status */
 }