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

📄 sdio_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  *//* *  sdio_protocol.c - SDIO 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/suspend.h>#include <linux/mm.h>#include <asm/scatterlist.h>#include <linux/mmc/mss_core.h>#include <linux/mmc/sdio_protocol.h>/***************************************************************************** * *   internal functions * ****************************************************************************/#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 sdio_tran_speed( u8 ts ){	u32 clock = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];	return clock;}static int sdio_unpack_r1(struct mss_cmd *cmd, struct sdio_response_r1 *r1, struct sdio_card *sdio_card){	u8 *buf = cmd->response;	sdio_card->errno = SDIO_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)			sdio_card->errno = SDIO_ERROR_OUT_OF_RANGE;		if (r1->status & R1_COM_CRC_ERROR)		  	sdio_card->errno = SDIO_ERROR_COM_CRC;		if (r1->status & R1_ILLEGAL_COMMAND)		    	sdio_card->errno = SDIO_ERROR_ILLEGAL_COMMAND;		if (r1->status & R1_ERROR)	  		sdio_card->errno = SDIO_ERROR_GENERAL;	}	if (r1->cmd != cmd->opcode)	       	sdio_card->errno = SDIO_ERROR_HEADER_MISMATCH;	/* This should be last - it's the least dangerous error */		if (sdio_card->errno != SDIO_ERROR_NONE)		return MSS_ERROR_RESP_UNPACK;	return MSS_ERROR_NONE;}static int sdio_unpack_r4(struct mss_cmd *cmd, struct sdio_response_r4 *r4, struct sdio_card *sdio_card){	u8 *buf = cmd->response;	r4->ocr		= unstuff_bits(buf, 8, 24, 6);	r4->ready	= unstuff_bits(buf, 39, 1, 6);	r4->mem_present	= unstuff_bits(buf, 35, 1, 6);	r4->func_num	= unstuff_bits(buf, 36, 3, 6);	dbg("ocr=%08x,ready=%d,mp=%d,fun_num:%d\n", r4->ocr, r4->ready,			r4->mem_present, r4->func_num);	return 0;}static int sdio_unpack_r5(struct mss_cmd *cmd, struct sdio_response_r5 *r5, struct sdio_card *sdio_card){	u8 *buf = cmd->response;	sdio_card->errno = SDIO_ERROR_NONE;	r5->cmd		= unstuff_bits(buf, 40, 8, 6);	r5->status	= unstuff_bits(buf, 16, 8, 6);	r5->data	= unstuff_bits(buf, 8, 8, 6);	dbg("cmd=%d status=%02x,data:%02x", r5->cmd, r5->status, r5->data);				if (r5->status) {		if (r5->status & R5_OUT_OF_RANGE)			return SDIO_ERROR_OUT_OF_RANGE;		if (r5->status & R5_COM_CRC_ERROR)			return SDIO_ERROR_COM_CRC;		if (r5->status & R5_ILLEGAL_COMMAND)			return SDIO_ERROR_ILLEGAL_COMMAND;		if (r5->status & R5_ERROR)			return SDIO_ERROR_GENERAL;		if (r5->status & R5_FUNCTION_NUMBER)			return SDIO_ERROR_FUNC_NUM;	}	if (r5->cmd != cmd->opcode) {		return SDIO_ERROR_HEADER_MISMATCH;	}	return 0;}static u16 sdio_unpack_r6(struct mss_cmd *cmd, struct sdio_response_r6 *r6, struct sdio_card *sdio_card){	u8 *buf = cmd->response;	int errno = SDIO_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 = SDIO_ERROR_COM_CRC;		if (r6->status & R6_ILLEGAL_COMMAND) 			errno = SDIO_ERROR_ILLEGAL_COMMAND;		if (r6->status & R6_ERROR) 			errno = SDIO_ERROR_GENERAL;	}	if (r6->cmd != cmd->opcode) 		errno = SDIO_ERROR_HEADER_MISMATCH;	sdio_card->errno = errno;	if (errno)		return MSS_ERROR_RESP_UNPACK;	return 0 ;	}/***************************************************************************** * *   internal functions * ****************************************************************************//* sdio related function */static u32 sdio_make_cmd52_arg(int rw, int fun_num, int raw, int address, int write_data){	u32 ret;	dbg("rw:%d,fun:%d,raw:%d,address:%d,write_data:%d\n",			rw, fun_num, raw, address, write_data);	ret = (rw << 31) | (fun_num << 28) | (raw << 27) | (address << 9) | write_data;	return ret;}static u32 sdio_make_cmd53_arg(int rw, int fun_num, int block_mode, int op_code, int address, int count){	u32 ret;	dbg("rw:%d,fun:%d,block_mode:%d,op_code:%d,address:%d,count:%d\n",			rw, fun_num, block_mode, op_code, address, count);	ret = (rw << 31) | (fun_num << 28) | (block_mode << 27) | (op_code << 26) | (address << 9) | count;	return ret;}#if 0static int sdio_function_abort(struct mss_card_device *dev, u8 fun_id){	struct sdio_response_r5 r5;	int retval,arg;	u8 *buffer;	//buffer = dev->io_request->buffer;	buffer = NULL;	arg = sdio_make_cmd52_arg(SDIO_WRITE_REG, 0, 0, IO_ABORT, fun_id);	mss_simple_cmd( dev, IO_RW_DIRECT, arg, RESPONSE_R5, buffer );	if ( (retval = sdio_unpack_r5(dev->io_request, &r5)) ) {		DEBUG("error=%d (%s)\n",retval, sdio_result_to_string(retval) );		return retval;	}		return 0;}#endif	#define SDIO_FN0_READ_REG(addr)						\	do {								\		arg = sdio_make_cmd52_arg(SDIO_R, 0, 0, addr, 0);	\		ret = mss_send_simple_ll_req(host, llreq, cmd, 		\				IO_RW_DIRECT, arg, MSS_RESPONSE_R5, 	\				MSS_CMD_SDIO_EN);			\		if (ret)						\			return ret;					\		ret = sdio_unpack_r5(cmd, &r5, sdio_card);		\		if (ret)						\			return ret;					\	} while(0)	#define SDIO_FN0_WRITE_REG(addr, val)					\	do {								\		arg = sdio_make_cmd52_arg(SDIO_W, 0, 0, addr, val);	\		ret = mss_send_simple_ll_req(host, llreq, cmd, 		\				IO_RW_DIRECT, arg, MSS_RESPONSE_R5, 	\				MSS_CMD_SDIO_EN);			\		if (ret)						\			return ret;					\		ret = sdio_unpack_r5(cmd, &r5, sdio_card);		\		if (ret)						\			return ret;					\	} while(0)	static int sdio_reset(struct mss_card *card){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int ret,arg;	SDIO_FN0_WRITE_REG(IO_ABORT, 0x8);	return 0;}static int sdio_set_bus_width(struct mss_card *card, u8 buswidth){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int ret,arg;	SDIO_FN0_WRITE_REG(BUS_IF_CTRL, buswidth);	card->bus_width = MSS_BUSWIDTH_4BIT;	return 0;}static int sdio_set_block_size(struct mss_card *card, u16 size, int func){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int ret,arg;	u8 tmp;	if (func == 0) {		tmp = size & 0xff;		SDIO_FN0_WRITE_REG(FN0_BLKSZ_1, tmp);				tmp = (size & 0xff00) >> 8;		SDIO_FN0_WRITE_REG(FN0_BLKSZ_2, tmp);				sdio_card->cccr.fn0_blksz = size;	} else {		tmp = size & 0xff;		SDIO_FN0_WRITE_REG(FNn_BLKSZ_1(func), tmp);				tmp = (size & 0xff00) >> 8;		SDIO_FN0_WRITE_REG(FNn_BLKSZ_2(func), tmp);				sdio_card->fbr[func].fn_blksz = size;	}		return 0;}static int sdio_io_enable(struct mss_card *card, u8 set_mask){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int ret, arg;	SDIO_FN0_WRITE_REG(IO_ENABLE, set_mask);		return 0;}static int sdio_interrupt_enable(struct mss_card *card, u8 set_mask){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int ret, arg;	SDIO_FN0_WRITE_REG(INT_ENABLE, set_mask);	return 0;}static int sdio_csa_enable(struct mss_card *card, int func){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int arg;	int ret = 0;	if(sdio_card->fbr[func].fun_support_csa == 0)		return ret;		SDIO_FN0_WRITE_REG(FNn_IF_CODE(func), 0x80);	return 0;}static int get_sdio_fbr_info(struct mss_card *card, int func){	struct mss_host *host = card->slot->host;	struct sdio_card *sdio_card = card->prot_card;	struct mss_cmd *cmd = &sdio_card->cmd;	struct mss_ll_request *llreq = &sdio_card->llreq;	struct sdio_response_r5 r5;	int ret,arg;	u32 tmp;		SDIO_FN0_READ_REG(FNn_IF_CODE(func));	sdio_card->fbr[func].fun_if_code = r5.data & 0xF;	sdio_card->fbr[func].fun_support_csa = (r5.data >> 6) & 0x1;	sdio_card->fbr[func].fun_csa_enable	= (r5.data >> 7) & 0x1;	SDIO_FN0_READ_REG(FNn_EXT_IF_CODE(func));

⌨️ 快捷键说明

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