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

📄 hw_sdmmc.c

📁 pocket pc hx4700 bootloader
💻 C
字号:
/* * Copyright (C) 2006-2007 Pawel Kolodziejski * * Some defines are from linux 2.6 kernel sources * * 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 */#include "types.h"#include "pxa-regs.h"#include "gpio.h"#define STOP_CLOCK		(1 << 0)#define START_CLOCK		(2 << 0)#define STAT_END_CMD_RES		(1 << 13)#define STAT_PRG_DONE			(1 << 12)#define STAT_DATA_TRAN_DONE		(1 << 11)#define STAT_CLK_EN			(1 << 8)#define STAT_RECV_FIFO_FULL		(1 << 7)#define STAT_XMIT_FIFO_EMPTY		(1 << 6)#define STAT_RES_CRC_ERR		(1 << 5)#define STAT_SPI_READ_ERROR_TOKEN	(1 << 4)#define STAT_CRC_READ_ERROR		(1 << 3)#define STAT_CRC_WRITE_ERROR		(1 << 2)#define STAT_TIME_OUT_RESPONSE		(1 << 1)#define STAT_READ_TIME_OUT		(1 << 0)#define CMDAT_DMAEN		(1 << 7)#define CMDAT_INIT		(1 << 6)#define CMDAT_BUSY		(1 << 5)#define CMDAT_STREAM		(1 << 4)	/* 1 = stream */#define CMDAT_WRITE		(1 << 3)	/* 1 = write */#define CMDAT_DATAEN		(1 << 2)#define CMDAT_RESP_NONE		(0 << 0)#define CMDAT_RESP_SHORT	(1 << 0)#define CMDAT_RESP_R2		(2 << 0)#define CMDAT_RESP_R3		(3 << 0)#define TXFIFO_WR_REQ		(1 << 6)#define RXFIFO_RD_REQ		(1 << 5)#define CLK_IS_OFF		(1 << 4)#define STOP_CMD		(1 << 3)#define END_CMD_RES		(1 << 2)#define PRG_DONE		(1 << 1)#define DATA_TRAN_DONE		(1 << 0)#define MMC_VDD_32_33	0x00100000	/* VDD voltage 3.2 ~ 3.3 */#define MMC_VDD_33_34	0x00200000	/* VDD voltage 3.3 ~ 3.4 */#define MMC_CARD_BUSY	0x80000000#define	MMC_GO_IDLE_STATE         0#define MMC_SEND_OP_COND          1#define MMC_ALL_SEND_CID          2#define MMC_SET_RELATIVE_ADDR     3#define MMC_SELECT_CARD           7#define MMC_SEND_CSD              9#define MMC_SET_BLOCKLEN         16#define MMC_READ_SINGLE_BLOCK    17#define MMC_WRITE_BLOCK          24#define SD_APP_OP_COND           41#define MMC_APP_CMD              55int sd_check_inserted(void) {	return GPLR0 & 0x400 ? -1 : 0;}static int sd_error(char *str) {	drawText(0, 21, str, 0, 0xf800);	for (;;) {}}static int sd_send_cmd(u8 cmd, u32 param, u16 cmdat) {	int i;	MMC_STRPCL = STOP_CLOCK;	for (i = 100; i; i--) {		if ((MMC_STAT & STAT_CLK_EN) != STAT_CLK_EN)			goto ok1;	}	sd_error("sd_send_cmd: clock not stopped");ok1:	if (cmd == MMC_SET_BLOCKLEN) {		MMC_RDTO = 0xffff;		MMC_BLKLEN = 512;		MMC_NOB = 1;	}	MMC_CMD = cmd;	MMC_ARGH = param >> 16;	MMC_ARGL = param & 0xffff;	MMC_CMDAT = cmdat;	MMC_STRPCL = START_CLOCK;	for (i = 300000; i; i--) {		if ((MMC_STAT & STAT_END_CMD_RES) == STAT_END_CMD_RES)			goto ok2;	}	sd_error("sd_send_cmd: missing response");ok2: ;}int sd_setup_for_transfer(int addr) {	//drawText(0, 18, "MMC_SELECT_CARD      ", 0, 0x0000);	sd_send_cmd(MMC_SELECT_CARD, addr << 16, CMDAT_RESP_SHORT);	sd_read_resp_short();	//drawText(0, 18, "MMC_SET_BLOCKLEN      ", 0, 0x0000);	sd_send_cmd(MMC_SET_BLOCKLEN, 512, CMDAT_RESP_SHORT);	sd_read_resp_short();}int sd_turn_on(void) {	int i;	CKEN |= CKEN12_MMC;	gpo_clear(GPO_A716_SD_POWER_N);	mdelay(10);	MMC_STRPCL = STOP_CLOCK;	for (i = 100; i; i--) {		if ((MMC_STAT & STAT_CLK_EN) != STAT_CLK_EN)			break;		mdelay(1);	}	MMC_SPI = 0;	MMC_RESTO = 64;}int sd_turn_off(void) {	int i;	MMC_STRPCL = STOP_CLOCK;	for (i = 100; i; i--) {		if ((MMC_STAT & STAT_CLK_EN) != STAT_CLK_EN)			break;		mdelay(1);	}	gpo_set(GPO_A716_SD_POWER_N);	//CKEN &= ~CKEN12_MMC;}int sd_read_resp_short(void) {	int l;	int *response = (int *)0xA3100200;	u8 *res = (u8 *)0xA3100200;	char string[32];	u32 v;	for (l = 0; l < 4; l++) {		response[l] = MMC_RES & 0xffff;	}/*	drawText(0, 19, "                         ", 0, 0xffff);	drawText(0, 20, "                         ", 0, 0xffff);	sprintf(string, "%04x %04x %04x %04x %04x", response[0], response[1], response[2], response[3], response[4]);	drawText(0, 19, string, 0, 0x0000);*/}static int sd_read_resp_long(void) {	int l;	int *response = (int *)0xA3100200;	u8 *res = (u8 *)0xA3100200;	char string[32];	u32 v;	for (l = 0; l < 8; l++) {		response[l] = MMC_RES & 0xffff;	}/*	drawText(0, 19, "                         ", 0, 0xffff);	drawText(0, 20, "                         ", 0, 0xffff);	sprintf(string, "%04x %04x %04x %04x", response[0], response[1], response[2], response[3]);	drawText(0, 19, string, 0, 0x0000);	sprintf(string, "%04x %04x %04x %04x %04x", response[4], response[5], response[6], response[7], response[8]);	drawText(0, 20, string, 0, 0x0000);*/}int sd_card_init(void) {	int i;	int addr;	int *response = (int *)0xA3100200;	char string[32];	int is_sd = 0;	MMC_CLKRT = 6; // set to minimum clock rate	//drawText(0, 18, "MMC_GO_IDLE_STATE        ", 0, 0x0000);	sd_send_cmd(MMC_GO_IDLE_STATE, 0, CMDAT_RESP_NONE);	//mdelay(5000);	for (i = 300000; i; i--) {		if (is_sd == 0) {			//drawText(0, 18, "MMC_APP_CMD      ", 0, 0x0000);			sd_send_cmd(MMC_APP_CMD, 0, CMDAT_RESP_SHORT);			sd_read_resp_short();			//sprintf(string, "%04x", response[0]);			//drawText(0, 26, string, 0, 0x0000);			//mdelay(5000);			if (response[0] != 0x3700) {				is_sd = -1;			}		}		//mdelay(5000);		//drawText(0, 18, "SD_APP_OP_COND   ", 0, 0x0000);		//sprintf(string, "%04x", response[0]);		//drawText(0, 26, string, 0, 0x0000);		//mdelay(5000);		if (is_sd == 0)			sd_send_cmd(SD_APP_OP_COND, MMC_VDD_32_33 | MMC_VDD_33_34, CMDAT_INIT | CMDAT_RESP_R3);		else			sd_send_cmd(MMC_SEND_OP_COND, MMC_VDD_32_33 | MMC_VDD_33_34, CMDAT_INIT | CMDAT_RESP_R3);		sd_read_resp_short();		//sprintf(string, "%04x", response[0]);		//drawText(0, 26, string, 0, 0x0000);		//mdelay(5000);		if (response[0] == 0x3f80)			goto ok1;	}	sd_error("SD/MMC card not initialised");	return 0;ok1:	//drawText(0, 18, "MMC_ALL_SEND_CID          ", 0, 0x0000);	sd_send_cmd(MMC_ALL_SEND_CID, 0, CMDAT_RESP_R2);	sd_read_resp_long();	//mdelay(5000);	//drawText(0, 18, "MMC_SET_RELATIVE_ADDR     ", 0, 0x0000);	sd_send_cmd(MMC_SET_RELATIVE_ADDR, 0, CMDAT_RESP_SHORT);	sd_read_resp_short();	if (is_sd == 0)		addr = ((response[0] & 0xff) << 8) | ((response[1] & 0xff00) >> 8);	else		addr = 1;	//sprintf(string, "%04x", addr);	//drawText(0, 26, string, 0, 0x0000);	//mdelay(5000);	//drawText(0, 18, "MMC_SEND_CSD              ", 0, 0x0000);	sd_send_cmd(MMC_SEND_CSD, addr << 16, CMDAT_RESP_R2);	sd_read_resp_long();	//mdelay(5000);	MMC_CLKRT = 0; // set to maximum clock rate	return addr;}int sd_read_sector(u8 *buffer, unsigned long sector) {	unsigned long i, r, s;	char string[32];	//drawText(0, 18, "MMC_READ_SINGLE_BLOCK      ", 0, 0x0000);	sd_send_cmd(MMC_READ_SINGLE_BLOCK, sector * 512, CMDAT_RESP_SHORT | CMDAT_DATAEN);	sd_read_resp_short();	//mdelay(5000);	for (r = 0; r < 16; r++) {		for (i = 300000; i; i--) {			if (MMC_STAT & STAT_RECV_FIFO_FULL)				goto ok2;		}		sd_error("sd_read_sector: no data in fifo");ok2: ;		for (s = 0; s < 32; s++) {			buffer[s + (r * 32)] = MMC_RXFIFO & 0xff;		}		if (MMC_STAT & STAT_READ_TIME_OUT) {			sd_error("sd_read_sector: read data timeout");			return -1;		}		if (MMC_STAT & STAT_CRC_READ_ERROR) {			sd_error("sd_read_sector: data crc error");			return -1;		}	}	return 0;}

⌨️ 快捷键说明

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