[BACK]Return to sdmmc_spi.c CVS log [TXT][DIR] Up to [local] / funnyos / dev / sdmmc

Diff for /funnyos/dev/sdmmc/sdmmc_spi.c between version 1.1 and 1.2

version 1.1, 2007/12/20 15:23:15 version 1.2, 2007/12/21 17:45:26
Line 18 
Line 18 
 };  };
   
 int     spisdmmc_attach(struct device *, uint32_t, uint8_t);  int     spisdmmc_attach(struct device *, uint32_t, uint8_t);
   void    spisdmmc_send_command(struct spisdmmc_dd *ddp, uint8_t cmd, uint32_t arg, uint32_t crc);
   uint8_t spisdmmc_get_response(struct spisdmmc_dd *ddp);
   int     spisdmmc_set_block_size(struct spisdmmc_dd *ddp, uint16_t blksize);
   void    spisdmmc_read_block(struct spisdmmc_dd *ddp, uint16_t nbytes, char *buffp);
   uint8_t spisdmmc_get_token(struct spisdmmc_dd *ddp);
   void    spisdmmc_read_cid(struct spisdmmc_dd *ddp, struct sdmmc_cid *cidp);
   
   
   
 struct driver spisdmmc_dr = {  struct driver spisdmmc_dr = {
         sizeof(struct spisdmmc_dd),          sizeof(struct spisdmmc_dd),
         spisdmmc_attach,          spisdmmc_attach,
Line 35 
Line 43 
   
         printf("SPI SD/MMC\n");          printf("SPI SD/MMC\n");
   
           spisdmmc_init(ddp);
   
         return(0);          return(0);
 }  }
   
Line 43 
Line 53 
 spisdmmc_init(struct spisdmmc_dd *ddp)  spisdmmc_init(struct spisdmmc_dd *ddp)
 {  {
         uint8_t i, resp;          uint8_t i, resp;
           struct sdmmc_cid cid;
   
         /*          /*
          * Apply 80 clock pulses.           * Apply 80 clock pulses.
          * XXX assert CS. (NPCS0)           * XXX assert CS. (NPCS0)
          */           */
           spi_cs_high(ddp->ss_sbhp);
         for (i = 0; i < 9; i++)          for (i = 0; i < 9; i++)
                 spi_transmit(ddp->ss_sbhp, 0xff);                  spi_transmit(ddp->ss_sbhp, 0xff);
   
         /*          /*
          * Apply 16 clocks.           * Apply 16 clocks.
          * XXX deassert CS.           * XXX deassert CS.
          */           */
         for (i = 0; i < 2; i ++)  //      for (i = 0; i < 2; i ++)
                 spi_transmit(ddp->ss_sbhp, 0xff);  //              spi_transmit(ddp->ss_sbhp, 0xff);
   
         /*          /*
          * Send CMD0_GO_IDLE_STATE.           * Send CMD0_GO_IDLE_STATE.
          */           */
           spi_cs_low(ddp->ss_sbhp);
         spisdmmc_send_command(ddp, CMD0_GO_IDLE_STATE, 0, CMD0_HARDCODED_CRC);          spisdmmc_send_command(ddp, CMD0_GO_IDLE_STATE, 0, CMD0_HARDCODED_CRC);
         if (spisdmmc_get_response(ddp) != 0) {  
           resp = spisdmmc_get_response(ddp);
   
           if (resp != 0) {
                 printf("spisdmmc_init: CMD0_GO_IDLE_STATE failed with %d\n", resp);                  printf("spisdmmc_init: CMD0_GO_IDLE_STATE failed with %d\n", resp);
   
                 return(-1);                  return(-1);
         }          }
           printf("spisdmmc_init: Card replied to CMD0_GO_IDLE_STATE with 0x%x\n", resp);
   
           /*
            * Okay. Try to initialize the card.
            * Periodically send CMD1 and poll for response with 0x01 cleared (card exit Idle state).
            * CRC is off so we can set it 0xff.
            * XXX send 0xff before.
            */
   //      spi_transmit(ddp->ss_sbhp, 0xff);
           do {
                   spisdmmc_send_command(ddp, CMD1_SEND_OP_COND, 0, 0xff);
                   resp = spisdmmc_get_response(ddp);
           } while(resp != 0x00);
   
           printf("spisdmmc_init: Card initialization completed\n");
   
           /*
            * Set block size to 512 bytes.
            */
           if(spisdmmc_set_block_size(ddp, SDMMC_BLOCK_SIZE) == -1) {
                   printf("spisdmmc_init: failed to set block size\n");
                   return(-1);
           }
           printf("spisdmmc_init: block size set to %d\n", SDMMC_BLOCK_SIZE);
   
           spisdmmc_read_cid(ddp, &cid);
           printf("cid.pnm: %s%s%s%s%s\n", cid.cid_pnm[0], cid.cid_pnm[1], cid.cid_pnm[2], cid.cid_pnm[3], cid.cid_pnm[4]);
   
           return(0);
 }  }
   
   
Line 80 
Line 123 
         /* construct frame */          /* construct frame */
         sdcf = sdmmc_command(cmd, arg, crc);          sdcf = sdmmc_command(cmd, arg, crc);
   
         /* transmit token */          printf("spisdmmc_send_command: sending cmd %d arg 0x%x crc 0x%x\n", sdcf.sc_cmd & ~0xc0, sdcf.sc_arg, sdcf.sc_crc);
           /* transmit cmd */
         spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd);          spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd);
   
         /* transmit 32 bit argument XXX MSB first */          /* transmit 32 bit argument XXX MSB first */
Line 88 
Line 132 
                 spi_transmit(ddp->ss_sbhp, ((sdcf.sc_arg & (0xff000000 >> i)) >> (8 * (4 - i + 1))) );                  spi_transmit(ddp->ss_sbhp, ((sdcf.sc_arg & (0xff000000 >> i)) >> (8 * (4 - i + 1))) );
   
         /* transmit CRC field */          /* transmit CRC field */
         spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd)          spi_transmit(ddp->ss_sbhp, sdcf.sc_crc);
   
           /* XXX Apply NCR clock pulses */
   //      spi_transmit(ddp->ss_sbhp, 0xff);
 }  }
   
   
   uint8_t
   spisdmmc_get_response(struct spisdmmc_dd *ddp)
   {
           uint8_t i, resp;
           /*
            * Get response from card.
            * After command response comes in 8 to 64 pulses (all this bits will be 1).
            */
   
           for(i = 0; i < 64; i++) {
                   resp = spi_transmit(ddp->ss_sbhp, 0xff);
   
                   if (resp == 0x00 || resp == 0x01)
                           return(resp);
           }
   }
   
   uint8_t
   spisdmmc_get_token(struct spisdmmc_dd *ddp)
   {
           uint16_t i, token;
           /*
            * Get token.
            */
   
           for(i = 0; i < 1000; i++) {
                   token = spi_transmit(ddp->ss_sbhp, 0xff);
   
                   if (token == TOK_READ_BLOCK || token == TOK_WRITE_BLOCK_MULTIPLE)
                           return(token);
           }
   }
   
   
   int
   spisdmmc_set_block_size(struct spisdmmc_dd *ddp, uint16_t blksize)
   {
           uint8_t resp;
           /*
            * Set block size (CMD16).
            */
           spisdmmc_send_command(ddp,CMD16_SET_BLOCKLEN, blksize, 0xff);
           resp = spisdmmc_get_response(ddp);
           if (resp != 0x00) {
                   printf("spisdmmc_set_block_size: set block size to %d failed (0x%x)\n", blksize, resp);
                   return(-1);
           }
           return(0);
   }
   
   void
   spisdmmc_read_cid(struct spisdmmc_dd *ddp, struct sdmmc_cid *cidp)
   {
           uint8_t resp;
           struct sdmmc_cid cid;
           /*
            * Read Card ID register.
            */
           spisdmmc_send_command(ddp, CMD10_SEND_CID, 0, 0xff);
           resp = spisdmmc_get_response(ddp);
           printf("spisdmmc_read_cid: got r1 response 0x%x\n", resp);
   
           /*
            * Wait R1 response.
            */
           if (resp != 0x00) {
                   printf("spisdmmc_read_cid: bad response 0x%x\n", resp);
                   return;
           }
   
           spisdmmc_read_block(ddp, 16, (char *)&cid);
   }
   
   
   void
   spisdmmc_read_block(struct spisdmmc_dd *ddp, uint16_t nbytes, char *buffp)
   {
           uint8_t token;
           uint16_t crc;
           /*
            * Read block.
            */
           token = spisdmmc_get_token(ddp);
           printf("spisdmmc_read_block: got token 0x%x\n", token);
           if (token != TOK_READ_BLOCK) {
                   printf("spisdmmc_read_block: error, foreign token\n");
                   return;
           }
           /*
            * Okay, next is the data.
            */
           while(nbytes != 0) {
                   *buffp = spi_transmit(ddp->ss_sbhp, 0xff);
                   printf("byte read 0x%x\n", *buffp);
   
                   buffp++;
                   nbytes--;
           }
   
           /*
            * Read CRC.
            */
           crc = spi_transmit(ddp->ss_sbhp, 0xff);
           crc <<= 8;
           crc = spi_transmit(ddp->ss_sbhp, 0xff);
   };
   

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

CVSweb