📄 mmc_pxa.c
字号:
card->info.read_bl_len = (1<<card->info.csd.read_bl_len); card->info.write_bl_len = (1<<card->info.csd.write_bl_len); card->info.capacity = (card->info.csd.c_size + 1) * (1<<(card->info.csd.c_size_mult + 2)) * card->info.read_bl_len; MMC_DEBUG( MMC_DEBUG_LEVEL2, "card capacity=%dMb\n", card->info.capacity>>20 ); card->info.tran_speed = 20*1024; /* FIXME */ card->info.transfer_mode = MMC_TRANSFER_MODE_BLOCK_SINGLE; /* 2) set bus operation freq */ card_data->clkrt = pxa_mmc_clkrt( card->info.tran_speed ); /* 3) register card with MMC core */ mmc_register( MMC_REG_TYPE_CARD, card, 0 ); }/* IV. set DSR registers of the cards */#if 0 /* TODO */ if ( card->info.csd.dsr_imp ) { set_dsr = TRUE; /* calculate DSR */ }#endif }#if 0 /* TODO */ if ( set_dsr ) { /* send CMD4 */ }#endif/* merge list of the newly inserted cards into controller card stack */ if ( !ctrlr->stack.ncards ) { ctrlr->stack.first = stack->first; ctrlr->stack.last = stack->last; } else ctrlr->stack.last->next = stack->first; ctrlr->stack.ncards += stack->ncards; ret = 0; goto out;err_free: __mmc_card_stack_free( stack );error:out: return ret;}static inline int pxa_mmc_bus_width( mmc_controller_t ctrlr, mmc_card_t card, u8 width ){ int ret = 0; if ((ret=pxa_mmc_stop_bus_clock( ctrlr ))) return ret; MMC_CMD = CMD(55); MMC_ARGH = card->info.rca; MMC_ARGL = 0; MMC_CMDAT = MMC_CMDAT_R1; if ((ret=pxa_mmc_complete_cmd(ctrlr, MMC_R1, FALSE))) return ret; if ((ret = pxa_mmc_stop_bus_clock( ctrlr ))) return ret; MMC_CMD = CMD(6); MMC_ARGH = 0; MMC_ARGL = (width == 1) ?0: (width == 4) ?2: -1; MMC_CMDAT = MMC_CMDAT_R1 | (1<<8); /*if ((ret=pxa_mmc_complete_cmd(ctrlr, MMC_R1, FALSE))) return ret; */ return 0;}static inline int pxa_mmc_send_csd( mmc_controller_t ctrlr ){ int ret = -EINVAL; pxa_mmc_stop_bus_clock( ctrlr ); MMC_CMD = CMD(9); MMC_ARGH = 0xa95d; MMC_ARGL = 0x0; MMC_CMDAT = MMC_CMDAT_R2; ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE ); { int i=15; for(i=15; i>=0; i--) printk(KERN_EMERG"CSD %d is 0x%08x\n", i, PXA_MMC_RESPONSE(ctrlr, i)); } return 0;}static inline void pxa_mmc_send_rca( mmc_controller_t ctrlr){ int ret = -EINVAL; u16 argl=0, argh=0;// pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; pxa_mmc_stop_bus_clock( ctrlr ); MMC_CMD = CMD(3); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R6; ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE); { int i=6; for(i=5; i>=0; i--) printk(KERN_EMERG"RCA %d is 0x%08x\n", i, PXA_MMC_RESPONSE(ctrlr, i)); }}static inline void pxa_mmc_send_cid( mmc_controller_t ctrlr){ int ret = -EINVAL; u16 argl=0, argh=0; 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(2); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R2; ret = pxa_mmc_complete_cmd(ctrlr, MMC_R2, FALSE); // if(! ret) { int i=15; for(i=15; i>=0; i--) { printk(KERN_EMERG"CID %d is 0x%08x\n ", i, PXA_MMC_RESPONSE(ctrlr, i)); } printk(KERN_EMERG"CID[OID] is %c, %c \n", PXA_MMC_RESPONSE(ctrlr, 13), PXA_MMC_RESPONSE(ctrlr, 12)); printk(KERN_EMERG"CID[PNM] is %c. %c, %c, %c,%c\n", PXA_MMC_RESPONSE(ctrlr,11), PXA_MMC_RESPONSE(ctrlr, 10), PXA_MMC_RESPONSE(ctrlr, 9), PXA_MMC_RESPONSE(ctrlr, 8), PXA_MMC_RESPONSE(ctrlr, 7)); }}static inline int pxa_mmc_send_cmd55( mmc_controller_t ctrlr ){ int ret = -EINVAL; u16 argl=0, argh=0; 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(55); /*APP_CMD, then the next command is ACMD */ MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R1; ret = pxa_mmc_complete_cmd(ctrlr, MMC_R1, FALSE); return ret;}static inline int pxa_mmc_send_ocr( mmc_controller_t ctrlr ){ int ret = -EINVAL; u16 argl=0, argh=0; 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(55); /*APP_CMD, then the next command is ACMD */ MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R1; ret = pxa_mmc_complete_cmd(ctrlr, MMC_R1, FALSE); if (!ret) // is 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)); } while(! (PXA_MMC_RESPONSE(ctrlr, 4) & 0x80) ) { 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(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); 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)); } } else // is MMC or non-card printk(KERN_EMERG"pxa_mmc_send_ocr() CMD(55) error \n"); return ret;}/* MMC protocol macros: v3.4, p.120 */static int pxa_mmc_init_card_stack( mmc_controller_t ctrlr ){ int ret = -EIO; u16 argl = 0U, argh = 0U; if ( !ctrlr || ctrlr->stack.ncards ) { ret = -EINVAL; goto error; } /* initialize stack */ /* 1) send CMD0 */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) {//printk("pxa_mmc_stop_bus_clock() error\n"); goto error;} /* 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 */ MMC_SPI = MMC_SPI_DISABLE; MMC_CMD = CMD(0); /* CMD0 with zero argument */ MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_INIT; //MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", argh, argl ); if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, FALSE )) ) { MMC_DEBUG(MMC_DEBUG_LEVEL0, "pxa_mmc_complete_cmd error\n"); goto error; } /* pxa_mmc_send_ocr(ctrlr); pxa_mmc_send_cid(ctrlr); pxa_mmc_send_rca(ctrlr); pxa_mmc_send_rca(ctrlr); pxa_mmc_send_csd(ctrlr); */ /* update card stack */ if ( (ret = pxa_mmc_update_acq( ctrlr )) ) {MMC_DEBUG(MMC_DEBUG_LEVEL0, "pxa_mmc_update_acq error \n"); goto err_free; } //pxa_mmc_send_cid(ctrlr); /* move the controller to the IDLE state */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) {MMC_DEBUG(MMC_DEBUG_LEVEL0, "pxa_mmc_stop_bus_clock error \n"); goto err_free;} pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE ); ret = 0; MMC_DEBUG( MMC_DEBUG_LEVEL2, "ncards=%d\n", ctrlr->stack.ncards ); goto out;err_free: __mmc_card_stack_free( &ctrlr->stack ); error:out: return ret;}static int pxa_mmc_check_card_stack( mmc_controller_t ctrlr ){ int ret = -1; mmc_card_t card; //printk(KERN_EMERG"%s::%s\n\n",__FILE__,__FUNCTION__); if ( !ctrlr ) goto error; if ( ctrlr->stack.ncards > 0 ) {/* for each card in the stack: */ for( card = ctrlr->stack.first; card; card = card->next ) { u16 argh = card->info.rca; u16 argl = 0UL; /* 1) send CMD9( card->rca ) */ if ( pxa_mmc_stop_bus_clock( ctrlr ) ) goto error; /* SanDisk's cards do not respond to CMD9 */ MMC_CMD = CMD(13); MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = MMC_CMDAT_R1; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD13(0x%04x%04x)\n", argh, argl ); ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );/* 2) if card responded, it is still there */ if ( ret ) { //printk(KERN_EMERG"pxa_mmc_check_card_stack() MMC_CARD_STATE_UNPLUGGE ret is %d\n", ret); card->state = MMC_CARD_STATE_UNPLUGGED;} } } ret = 0; error: return ret;}/* This procedure links the bus master with a single card * 1) cross checks with the internal stack management data if a card still * exists in the slot * 2) send CMD7( card->public.rca ) * 3) setup data path and controller options */static int pxa_mmc_setup_card( mmc_controller_t ctrlr, mmc_card_t card ) { int ret = -ENODEV; pxa_mmc_hostdata_t hostdata; pxa_mmc_card_data_t card_data; u16 argh = 0U;#ifdef CONFIG_MMC_DEBUG u16 argl = 0U;#endif if ( !ctrlr || !card ) { ret = -EINVAL; goto error; } if ( card->ctrlr != ctrlr ) { MMC_DEBUG( MMC_DEBUG_LEVEL3, "card is on another bus\n" ); goto error; } hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; card_data = (pxa_mmc_card_data_t)card->card_data; argh = card->info.rca; /* select requested card */ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) goto error; MMC_CMD = CMD(7); MMC_ARGH = argh; MMC_CMDAT = MMC_CMDAT_R1; MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD7(0x%04x%04x)\n", argh, argl ); if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) goto error;/* set controller options *///#ifndef CONFIG_MMC_DEBUG MMC_CLKRT = card_data->clkrt; printk(" MMC_CLKRT = %x\n",MMC_CLKRT );//#endif /* 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 );/* if ((ret = pxa_mmc_bus_width(ctrlr, card, 4))) { printk(KERN_EMERG" ret is %d\n ", ret ); goto error; }*/ ret = 0;error: return ret;}static inline int pxa_mmc_iobuf_init( mmc_controller_t ctrlr, ssize_t cnt ){#ifdef PIO pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;#endif #ifndef PIO/* TODO */#else hostdata->iobuf.buf.pos = hostdata->iobuf.iodata; hostdata->iobuf.buf.cnt = cnt;#endif return 0;}/* TODO: ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )effects: reads at most cnt bytes from the card to the controller I/O buffer; takes care of partial data transfersrequieres: modifies: ctrlr->iobufreturns: number of bytes actually transferred or negative error code if there were any errors */ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt ){ ssize_t ret = -EIO; pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;#ifndef PIO register int ndesc; int chan = hostdata->iobuf.buf.chan; pxa_dma_desc *desc;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -