⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd_protocol.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Core MMC driver functions * * Copyright (c) 2002 Hewlett-Packard Company *    * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: *   * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. *   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Many thanks to Alessandro Rubini and Jonathan Corbet! * * Author:  Andrew Christian *          6 May 2002  *//* * sd_protocol.c - SD protocol driver * * Copyright (C) 2006 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *  Author:  Bridge Wu <bridge.wu@intel.com> *   *(C) Copyright 2006 Marvell International Ltd.   * All Rights Reserved  * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/list.h>#include <linux/sysctl.h>#include <linux/mm.h>#include <asm/scatterlist.h>#include <linux/mmc/mss_core.h>#include <linux/mmc/sd_protocol.h>#if 0static char * sd_result_strings[] = {	"NO_RESPONSE",	"NO_ERROR",	"ERROR_OUT_OF_RANGE",	"ERROR_ADDRESS",	"ERROR_BLOCK_LEN",	"ERROR_ERASE_SEQ",	"ERROR_ERASE_PARAM",	"ERROR_WP_VIOLATION",	"ERROR_CARD_IS_LOCKED",	"ERROR_LOCK_UNLOCK_FAILED",	"ERROR_COM_CRC",	"ERROR_ILLEGAL_COMMAND",	"ERROR_CARD_ECC_FAILED",	"ERROR_CC",	"ERROR_GENERAL",	"ERROR_UNDERRUN",	"ERROR_OVERRUN",	"ERROR_CID_CSD_OVERWRITE",	"ERROR_STATE_MISMATCH",	"ERROR_HEADER_MISMATCH",	"ERROR_TIMEOUT",	"ERROR_CRC",	"ERROR_DRIVER_FAILURE",	"ERROR_FLASH",};static char * sd_state_strings[] = {	"empty",	"idle",	"ready",	"ident",	"stby",	"tran",	"data",	"rcv",	"prg",	"dis",};/***************************************************************************** * *   internal functions * ****************************************************************************/static inline char * sd_result_to_string( int i ){	return sd_result_strings[i+1];}static inline char * sd_state_to_string( int i ){	return sd_state_strings[i+1];}#endif#define KBPS 1#define MBPS 1000static u32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 };static u32 ts_mul[] = { 0,    1000, 1200, 1300, 1500, 2000, 2500, 3000, 			3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 };static u32 sd_tran_speed(u8 ts){	u32 clock = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];	return clock;}static int sd_unpack_r1(struct mss_cmd *cmd, struct sd_response_r1 *r1, struct sd_card *sd_card){	u8 *buf = cmd->response;	sd_card->errno = SD_ERROR_NONE;	r1->cmd    = unstuff_bits(buf, 40, 8, 6);	r1->status = unstuff_bits(buf, 8, 32, 6);	/* dbg("status 0x%x", r1->status);*/	if (R1_STATUS(r1->status)) {		if (r1->status & R1_OUT_OF_RANGE)			sd_card->errno = SD_ERROR_OUT_OF_RANGE;		if (r1->status & R1_ADDRESS_ERROR)		  	sd_card->errno = SD_ERROR_ADDRESS;		if (r1->status & R1_BLOCK_LEN_ERROR)		    	sd_card->errno = SD_ERROR_BLOCK_LEN;		if (r1->status & R1_ERASE_SEQ_ERROR)		    	sd_card->errno = SD_ERROR_ERASE_SEQ;		if (r1->status & R1_ERASE_PARAM)			sd_card->errno = SD_ERROR_ERASE_PARAM;		if (r1->status & R1_WP_VIOLATION)		 	sd_card->errno = SD_ERROR_WP_VIOLATION;		if (r1->status & R1_LOCK_UNLOCK_FAILED)			sd_card->errno = SD_ERROR_LOCK_UNLOCK_FAILED;		if (r1->status & R1_COM_CRC_ERROR)		  	sd_card->errno = SD_ERROR_COM_CRC;		if (r1->status & R1_ILLEGAL_COMMAND)		    	sd_card->errno = SD_ERROR_ILLEGAL_COMMAND;		if (r1->status & R1_CARD_ECC_FAILED)		    	sd_card->errno = SD_ERROR_CARD_ECC_FAILED;		if (r1->status & R1_CC_ERROR)	     		sd_card->errno = SD_ERROR_CC;		if (r1->status & R1_ERROR)	  		sd_card->errno = SD_ERROR_GENERAL;		if (r1->status & R1_CID_CSD_OVERWRITE)		      	sd_card->errno = SD_ERROR_CID_CSD_OVERWRITE;	}	if (r1->status & R1_AKE_SEQ_ERROR)	      	sd_card->errno = SD_ERROR_CID_CSD_OVERWRITE;	if (r1->cmd != cmd->opcode)	       	sd_card->errno = SD_ERROR_HEADER_MISMATCH;	/* This should be last - it's the least dangerous error */	if (R1_CURRENT_STATE(r1->status) != sd_card->state ) {		dbg("state dismatch:r1->status:%x,state:%x\n",R1_CURRENT_STATE(r1->status),sd_card->state);		sd_card->errno = SD_ERROR_STATE_MISMATCH;	}	dbg("sd card error %d", sd_card->errno);	if (sd_card->errno)		return MSS_ERROR_RESP_UNPACK;	return 0;}static int sd_unpack_r3(struct mss_cmd *cmd, struct sd_response_r3 *r3, struct sd_card *sd_card){	u8 *buf = cmd->response;	sd_card->errno = SD_ERROR_NONE;	r3->cmd = unstuff_bits(buf, 40, 8, 6);	r3->ocr = unstuff_bits(buf, 8, 32, 6);	dbg("ocr=0x%x", r3->ocr);	if (r3->cmd != 0x3f) {  		sd_card->errno = SD_ERROR_HEADER_MISMATCH;		return MSS_ERROR_RESP_UNPACK;	}	return 0;}	static int sd_unpack_r6(struct mss_cmd *cmd, struct sd_response_r6 *r6, struct sd_card *sd_card){	u8 *buf = cmd->response;	int errno = SD_ERROR_NONE;		r6->cmd = unstuff_bits(buf, 40, 8, 6);	r6->rca = unstuff_bits(buf, 24, 16, 6);	r6->status = unstuff_bits(buf, 8, 16, 6);	if (R6_STATUS(r6->status)) {		if (r6->status & R6_COM_CRC_ERROR) 			errno = SD_ERROR_COM_CRC;		if (r6->status & R6_ILLEGAL_COMMAND) 			errno = SD_ERROR_ILLEGAL_COMMAND;		if (r6->status & R6_ERROR) 			errno = SD_ERROR_CC;	}	if (r6->cmd != cmd->opcode) 		errno = SD_ERROR_HEADER_MISMATCH;	/* This should be last - it's the least dangerous error */	if (R1_CURRENT_STATE(r6->status) != sd_card->state) 		errno = SD_ERROR_STATE_MISMATCH;	sd_card->errno = errno;	if (errno)		return MSS_ERROR_RESP_UNPACK;	return 0 ;}static int sd_unpack_cid(struct mss_cmd *cmd, struct sd_cid *cid, struct sd_card *sd_card){	u8 *buf = cmd->response;	sd_card->errno = SD_ERROR_NONE;	if (buf[0] != 0x3f) {		sd_card->errno = SD_ERROR_HEADER_MISMATCH;		return MSS_ERROR_RESP_UNPACK;	}	buf = buf + 1;		cid->mid	= unstuff_bits(buf, 120, 8, 16);	cid->oid	= unstuff_bits(buf, 104, 16, 16);	cid->pnm[0]	= unstuff_bits(buf, 96, 8, 16);	cid->pnm[1]	= unstuff_bits(buf, 88, 8, 16);	cid->pnm[2]	= unstuff_bits(buf, 80, 8, 16);	cid->pnm[3]	= unstuff_bits(buf, 72, 8, 16);	cid->pnm[4]	= unstuff_bits(buf, 64, 8, 16);	cid->pnm[5]	= 0;	cid->prv	= unstuff_bits(buf, 56, 8, 16);	cid->psn	= unstuff_bits(buf, 24, 32, 16);	cid->mdt	= unstuff_bits(buf, 8, 12, 16);/*		DEBUG(" mid=%d oid=%d pnm=%s prv=%d.%d psn=%08x mdt=%d/%d\n",	      cid->mid, cid->oid, cid->pnm, 	      (cid->prv>>4), (cid->prv&0xf), 	      cid->psn, cid->mdt&&0xf, ((cid->mdt>>4)&0xff)+2000);*/      	return 0;}static int sd_unpack_csd(struct mss_cmd *cmd, struct sd_csd *csd, struct sd_card *sd_card){	u8 *buf = cmd->response;	sd_card->errno = SD_ERROR_NONE;	if (buf[0] != 0x3f) {		sd_card->errno = SD_ERROR_HEADER_MISMATCH;		return MSS_ERROR_RESP_UNPACK;	}	buf = buf + 1;		csd->csd_structure	= unstuff_bits(buf, 126, 2, 16);	csd->taac		= unstuff_bits(buf, 112, 8, 16);	csd->nsac		= unstuff_bits(buf, 104, 8, 16);	csd->tran_speed		= unstuff_bits(buf, 96, 8, 16);	csd->ccc		= unstuff_bits(buf, 84, 12, 16);	csd->read_bl_len	= unstuff_bits(buf, 80, 4, 16);	csd->read_bl_partial	= unstuff_bits(buf, 79, 1, 16);	csd->write_blk_misalign	= unstuff_bits(buf, 78, 1, 16);	csd->read_blk_misalign	= unstuff_bits(buf, 77, 1, 16);	csd->dsr_imp		= unstuff_bits(buf, 76, 1, 16);	if (csd->csd_structure == 0) {		csd->csd.csd1.c_size		= unstuff_bits(buf, 62, 12, 16);		csd->csd.csd1.vdd_r_curr_min	= unstuff_bits(buf, 59, 3, 16);		csd->csd.csd1.vdd_r_curr_max	= unstuff_bits(buf, 56, 3, 16);		csd->csd.csd1.vdd_w_curr_min	= unstuff_bits(buf, 53, 3, 16);		csd->csd.csd1.vdd_w_curr_max	= unstuff_bits(buf, 50, 3, 16);		csd->csd.csd1.c_size_mult	= unstuff_bits(buf, 47, 3, 16);	}	else if (csd->csd_structure == 1) {		csd->csd.csd2.c_size		= unstuff_bits(buf, 48, 22, 16);	}		csd->erase_blk_en	= unstuff_bits(buf, 46, 1, 16);	csd->sector_size	= unstuff_bits(buf, 39, 7, 16);	csd->wp_grp_size        = unstuff_bits(buf, 32, 7, 16);	csd->wp_grp_enable      = unstuff_bits(buf, 31, 1, 16);	csd->r2w_factor         = unstuff_bits(buf, 26, 3, 16);	csd->write_bl_len       = unstuff_bits(buf, 22, 4, 16);	csd->write_bl_partial   = unstuff_bits(buf, 21, 1, 16);	csd->file_format_grp    = unstuff_bits(buf, 15, 1, 16);	csd->copy               = unstuff_bits(buf, 14, 1, 16);	csd->perm_write_protect = unstuff_bits(buf, 13, 1, 16);	csd->tmp_write_protect  = unstuff_bits(buf, 12, 1, 16);	csd->file_format        = unstuff_bits(buf, 10, 2, 16);#if 0	if (csd->csd_structure == 0) {	dbg5("  csd_structure=%d taac=%02x  nsac=%02x  tran_speed=%02x\n"	      "  ccc=%04x  read_bl_len=%d  read_bl_partial=%d  write_blk_misalign=%d\n"	      "  read_blk_misalign=%d  dsr_imp=%d  c_size=%d  vdd_r_curr_min=%d\n"	      "  vdd_r_curr_max=%d  vdd_w_curr_min=%d  vdd_w_curr_max=%d  c_size_mult=%d\n"	      "  erase_blk_en=%d sector_size=%d wp_grp_size=%d  wp_grp_enable=%d r2w_factor=%d\n"	      "  write_bl_len=%d  write_bl_partial=%d  file_format_grp=%d  copy=%d\n"	      "  perm_write_protect=%d  tmp_write_protect=%d  file_format=%d\n",	      csd->csd_structure,csd->taac, csd->nsac, csd->tran_speed,	      csd->ccc, csd->read_bl_len, 	      csd->read_bl_partial, csd->write_blk_misalign,	      csd->read_blk_misalign, csd->dsr_imp, 	      csd->csd.csd1.c_size, csd->csd.csd1.vdd_r_curr_min,	      csd->csd.csd1.vdd_r_curr_max, csd->csd.csd1.vdd_w_curr_min, 	      csd->csd.csd1.vdd_w_curr_max, csd->csd.csd1.c_size_mult,	      csd->erase_blk_en,csd->sector_size,	      csd->wp_grp_size, csd->wp_grp_enable,	      csd->r2w_factor, 	      csd->write_bl_len, csd->write_bl_partial,	      csd->file_format_grp, csd->copy, 	      csd->perm_write_protect, csd->tmp_write_protect,      	csd->file_format);	}	else if (csd->csd_structure == 1) {      	      dbg5("  csd_structure=%d taac=%02x  nsac=%02x  tran_speed=%02x\n"	      "  ccc=%04x  read_bl_len=%d  read_bl_partial=%d  write_blk_misalign=%d\n"	      "  read_blk_misalign=%d  dsr_imp=%d  c_size=%d\n"	      "  erase_blk_en=%d sector_size=%d wp_grp_size=%d  wp_grp_enable=%d r2w_factor=%d\n"	      "  write_bl_len=%d  write_bl_partial=%d  file_format_grp=%d  copy=%d\n"	      "  perm_write_protect=%d  tmp_write_protect=%d  file_format=%d\n",	      csd->csd_structure,csd->taac, csd->nsac, csd->tran_speed,	      csd->ccc, csd->read_bl_len, 	      csd->read_bl_partial, csd->write_blk_misalign,	      csd->read_blk_misalign, csd->dsr_imp, 	      csd->csd.csd2.c_size,	      csd->erase_blk_en,csd->sector_size,	      csd->wp_grp_size, csd->wp_grp_enable,	      csd->r2w_factor, 	      csd->write_bl_len, csd->write_bl_partial,	      csd->file_format_grp, csd->copy, 	      csd->perm_write_protect, csd->tmp_write_protect,	      csd->file_format);	}#endif	return 0;}static int sd_unpack_swfuncstatus(char *buf, struct sw_func_status *status){	int i; 	buf += 34;	for (i = 0; i < 5; i++) {		status->func_busy[i] = buf[0] << 8 | buf[1];		buf += 2;	}	buf += 1;	for (i = 0; i <= 5; i = i + 2) {		status->group_status[i] = buf[0] & 0xFF;		status->group_status[(i + 1)] = (buf[0] >> 4) & 0xFF;		buf += 1;	}	for (i = 0; i <= 5; i++) {		status->func_support[i] = buf[0] << 8 | buf[1];		buf += 2;	}		status->current_consumption = buf[0] << 8 | buf[1]; 	return 0;}static int sd_unpack_r7(struct mss_cmd *cmd, struct sd_response_r7 *r7, u16 arg, struct sd_card *sd_card){	u8 *buf = cmd->response;		r7->cmd		= unstuff_bits(buf, 40, 8, 6);	r7->ver		= unstuff_bits(buf, 20, 20, 6);	r7->vca		= unstuff_bits(buf, 16, 4, 6);	r7->pattern	= unstuff_bits(buf, 8, 8, 6);	if (r7->cmd != SD_SEND_IF_COND || r7->ver != 0 			|| (r7->vca << 8 | r7->pattern) != arg) {		sd_card->errno = SD_ERROR_HEADER_MISMATCH;		return MSS_ERROR_RESP_UNPACK;	}	return 0;}static int sd_unpack_scr(u8 *buf, struct sd_scr *scr){	scr->scr_structure	= unstuff_bits(buf, 60, 4, 8);	scr->sd_spec		= unstuff_bits(buf, 56, 4, 8);	scr->data_stat_after_erase = unstuff_bits(buf, 55, 1, 8);	scr->sd_security	= unstuff_bits(buf, 52, 3, 8);	scr->sd_bus_width	= unstuff_bits(buf, 48, 4, 8);	scr->init = 1;		dbg("scr_stru:%d, spec:%d, sata:%d, security:%d, bus:%d", 			scr->scr_structure, scr->sd_spec, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -