📄 mmc_pxa.c
字号:
ret = MMC_ERROR_ERASE_RESET; goto mmc_error; } } } if ( ret >= 0 ) pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_CMD ); goto out;mmc_error:#if 1 if ( send_abort ) { /* send CMD12 to abort failed transfer */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto error; MMC_CMD = CMD(12); /* STOP_TRANSMISSION */ MMC_CMDAT = MMC_CMDAT_R1; if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) goto error; ret = -EIO; goto error; }#endiferror: /* move controller to the IDLE state */ // printk(__FILE__" "__FUNCTION__"error RET IS %d\n", ret); pxa_mmc_stop_bus_clock( ctrlr ); pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );out: return ret;}/* int pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t cmd, mmc_dir_t dir, mmc_transfer_mode_t mode )Effects: finilizes data transfer request Reqires: controller is in the END_BUFFER stateModifies: moves controller to the IDLE stateReturns: zero upon success or error condition code otherwise */static mmc_error_t pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t dir, mmc_transfer_mode_t mode ){ int ret = MMC_ERROR_GENERIC; if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_IO ) ) goto error; switch ( mode ) { case MMC_TRANSFER_MODE_STREAM: /* FIXME */ if ( dir == MMC_WRITE ) { /* 1. wait for STOP_CMD intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_STOP_CMD )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_STOP_CMD )) ) goto error; } /* 2. send CMD12 */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto error; MMC_CMD = CMD(12); /* STOP_TRANSMISSION */ MMC_CMDAT = MMC_CMDAT_R1; if ( dir == MMC_WRITE ) MMC_CMDAT |= MMC_CMDAT_BUSY; /* 3. wait for CMD12 to complete */ MMC_DEBUG( MMC_DEBUG_LEVEL3, "ready for CMD12\n" ); if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) goto error; /* 4. wait for DATA_TRAN_DONE intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_DATA_TRAN_DONE )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_DATA_TRAN_DONE )) ) goto error; if ( dir == MMC_WRITE ) { /* 5. wait for PRG_DONE intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_PRG_DONE )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_PRG_DONE )) ) goto error; } break; case MMC_TRANSFER_MODE_BLOCK_MULTIPLE: /* 1. wait for DATA_TRAN done intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_DATA_TRAN_DONE )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_DATA_TRAN_DONE )) ) goto error; /* 2. send CMD12 */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto error; MMC_CMD = CMD(12); /* STOP_TRANSMISSION */ MMC_CMDAT = MMC_CMDAT_R1; if ( dir == MMC_WRITE ) MMC_CMDAT |= MMC_CMDAT_BUSY; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD12\n" ); if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) goto error; if ( dir == MMC_WRITE ) { /* 3. wait for PRG_DONE intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_PRG_DONE )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_PRG_DONE )) ) goto error; } break; case MMC_TRANSFER_MODE_BLOCK_SINGLE: /* 1. wait for DATA_TRAN_DONE intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_DATA_TRAN_DONE )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_DATA_TRAN_DONE )) ) goto error; if ( dir == MMC_WRITE ) { /* 2. wait for PRG_DONE intr */ if ( (ret = pxa_mmc_init_completion( ctrlr, MMC_I_MASK_PRG_DONE )) ) goto error; if ( (ret = pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_PRG_DONE )) ) goto error; } break; default: MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown transfer mode\n" ); goto error; }/* move the controller to the IDLE state */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto error; pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE ); ret = 0;error: return ret;}static inline int pxa_mmc_update_acq( mmc_controller_t ctrlr ){ int ret = -EINVAL; pxa_mmc_hostdata_t hostdata = NULL; mmc_card_t card = NULL; mmc_card_stack_rec_t fake; mmc_card_stack_t stack = &fake; u16 argl = 0U, argh = 0U; int ncards = 0; if ( !ctrlr ) goto error; hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; __mmc_card_stack_init( stack ); /*send the CMD55 to determined SD or MMC*/ ret = pxa_mmc_send_cmd55( ctrlr ); if (!ret) /* SD */ { pxa_mmc_stop_bus_clock( ctrlr ); // MMC_CLKRT = MMC_CLKRT_0_3125MHZ; MMC_CLKRT = MMC_CLKRT_20MHZ; MMC_RESTO = MMC_RES_TO_MAX; MMC_CMD = CMD(41); /*The command is ACMD, ask the accessed card to send its operating condition register(OCR)*/ MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R3; if(!(ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE))) { argh = (PXA_MMC_RESPONSE(ctrlr, 4)<<8) | PXA_MMC_RESPONSE(ctrlr, 3); argl = (PXA_MMC_RESPONSE(ctrlr, 2)<<8) | PXA_MMC_RESPONSE(ctrlr, 1); /* printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 4)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 3)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 2)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 1)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr,0)); */ } /*continue send CMD55+CMD41, untile the card power up */ while(! (PXA_MMC_RESPONSE(ctrlr, 4) & 0x80) ) { pxa_mmc_stop_bus_clock( ctrlr );// MMC_CLKRT = MMC_CLKRT_0_3125MHZ; MMC_CLKRT = MMC_CLKRT_20MHZ; //by huoran MMC_RESTO = MMC_RES_TO_MAX; MMC_CMD = CMD(55); MMC_ARGH = 0; MMC_ARGL = 0; MMC_CMDAT = MMC_CMDAT_R1; ret = pxa_mmc_complete_cmd(ctrlr, MMC_R1, FALSE); pxa_mmc_stop_bus_clock( ctrlr ); MMC_CMD = CMD(41); MMC_ARGH = argh | 0x80; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R3; ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE); if (ret == MMC_ERROR_TIME_OUT_RESPONSE) break; // argh = (PXA_MMC_RESPONSE(ctrlr, 4)<<8) | PXA_MMC_RESPONSE(ctrlr, 3); // argl = (PXA_MMC_RESPONSE(ctrlr, 2)<<8) | PXA_MMC_RESPONSE(ctrlr, 1); /* printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 4)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 3)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 2)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 1)); printk(KERN_EMERG"Volage is 0x%08x\n", PXA_MMC_RESPONSE(ctrlr, 0)); */ } /*card identification, if the card present then ask it to send RCA */ for(;;) { argh = 0; argl = 0; if ((ret=pxa_mmc_stop_bus_clock(ctrlr))) goto err_free; MMC_CMD = CMD(2); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R2; ret = pxa_mmc_complete_cmd(ctrlr, MMC_R2, FALSE); if (ret==MMC_ERROR_TIME_OUT_RESPONSE) break; else if(ret) goto err_free; /*if the response have receive , then the card present,and ask the RCA*/ if ((ret = pxa_mmc_stop_bus_clock( ctrlr ))) goto err_free; MMC_CMD = CMD(3); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R6; ret = pxa_mmc_complete_cmd(ctrlr, MMC_R3, FALSE); if (ret) goto err_free; argh = (PXA_MMC_RESPONSE(ctrlr, 4)<<8) | PXA_MMC_RESPONSE(ctrlr, 3) ; card = __mmc_card_alloc(sizeof(pxa_mmc_card_data_rec_t)); if (!card) goto err_free; card->info.rca = argh; card->slot = ctrlr->slot_next++; card->ctrlr =ctrlr; if (!__mmc_card_stack_add(stack, card)) goto err_free; ++ncards; } } /* SD */ else /* MMC */ { /* max open-drain mode frequency is 400kHZ */// MMC_CLKRT = MMC_CLKRT_0_3125MHZ; MMC_CLKRT = MMC_CLKRT_20MHZ; MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */ /* discover and add cards to the stack */ /* I. bus operation condition setup */ /* 1) send CMD1 */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto err_free; argl = 0x0000; argh = 0x0004; MMC_CMD = CMD(1); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl ); ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE ); if ( !ret ) { argh = (PXA_MMC_RESPONSE( ctrlr, 4 ) << 8) | PXA_MMC_RESPONSE( ctrlr, 3 ); argl = (PXA_MMC_RESPONSE( ctrlr, 2 ) << 8) | PXA_MMC_RESPONSE( ctrlr, 1 ); } else if ( ret != MMC_ERROR_TIME_OUT_RESPONSE ) goto err_free; if ( !argh && !argl ) { MMC_DEBUG( MMC_DEBUG_LEVEL0, "assuming full voltage range support\n" ); argh = 0x00ff; argl = 0xff00; } /* 2) continuously send CMD1 'till there're busy cards */ for(;;) { if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto err_free; MMC_CMD = CMD(1); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl ); ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE ); if ( ret == MMC_ERROR_TIME_OUT_RESPONSE ) break; else if ( !ret ) { /* busy state reported by LOW signal level * (MMC v3.2, p.58) * * Thanks to Alexander Samoutin :) */ if ( !(PXA_MMC_RESPONSE( ctrlr, 4 ) & 0x80) ) { MMC_DEBUG( MMC_DEBUG_LEVEL3, "busy state reported\n"); udelay( 20 ); continue; } else break; } else goto err_free; } // printk("end continuely send CMD1 \n\n");/* II. card identification: the cards in Ready state * are the only expected to respond */ for (;;) { argh = 0U; argl = 0U; // printk("run"); /* 1) send CMD2 */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto err_free; MMC_CMD = CMD(2); MMC_ARGH = 0x0003; MMC_ARGL = 0xf300; MMC_CMDAT = MMC_CMDAT_R2; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD2(0x%04x%04x)\n", argh, argl ); ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE ); if ( ret == MMC_ERROR_TIME_OUT_RESPONSE ) break; else if ( ret ) /* bus error */ goto err_free; // printk("run here, ret is %d \n\n ", ret); /* TODO: store CID for the card */ /* 2) assign RCA */ if ( !++ctrlr->rca_next ) /* overflow */ ++ctrlr->rca_next; argh = ctrlr->rca_next; /* 3) send it to the card last responded (CMD3) */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto err_free; MMC_CMD = CMD(3); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R1; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD3(0x%04x%04x)\n", argh, argl ); ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE ); if ( ret ) /* CMD3 failed */ goto err_free; card = __mmc_card_alloc( sizeof( pxa_mmc_card_data_rec_t ) ); if ( !card ) { MMC_ERROR( "out of memory\n" ); goto err_free; } card->info.rca = argh; card->slot = ctrlr->slot_next++; /* FIXME: minor encoding */ card->ctrlr = ctrlr; if ( !__mmc_card_stack_add( stack, card ) ) goto err_free; MMC_DEBUG( MMC_DEBUG_LEVEL2, "added card: " "slot %d, RCA=0x%04x\n", card->slot, argh ); ++ncards; } // printk("end card identification \n\n"); } /*MMC*/ if ( ncards ) {/* III. read CSD registers of all cards; DSR support also reported there */ for ( card = stack->first; card; card = card->next ) { pxa_mmc_card_data_t card_data = (pxa_mmc_card_data_t)card->card_data; /* 1) send CMD9 */ argh = card->info.rca; argl = 0U; if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto err_free; MMC_CMD = CMD(9); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R2; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD9(0x%04x%04x)\n", argh, argl ); if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE )) ) goto err_free; memcpy( &card->info.csd, hostdata->mmc_res, 15 ); MMC_DUMP_CSD( card );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -