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

📄 sdregb.c

📁 ssd192Xv1 液晶驱动程序 驱动程序 彩屏液晶
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;
}

int sdhc_set_blklen (unsigned long blklen){
	unsigned long rsp[4];
	
#if 0
	// check blk len
	if (blklen < (1 << CSD_RD_BLK_LEN(&g_csd)))
	{
		if (!CSD_RD_BLK_PARTIAL(&g_csd))
		{
			db ("sdhc_set_blklen: Card does not support partial read\n");
			return -1;
		}
	}
	else if (blklen > (1 << CSD_RD_BLK_LEN (&g_csd)))
	{
		db ("set_blklen: cannot read larger(%ld) than rd_blk_len (%lu)\n", 
			blklen, (1 << CSD_RD_BLK_LEN(&g_csd)));
		return -1;
	}
#endif
	rsp[0] = blklen;
	if (send_cmd (CMD_SET_BLKLEN, NORMAL, R48, 0, 1, 1, rsp) < 0)	{
		db ("sdhc_set_blklen: Set Block Length(CMD16) failed\n");
		return -1;
	}

	if (rsp[0] & (R1_STAT_ERR | R1_STAT_BLK_LEN_ERR))
	{
		db ("sdhc_set_blklen: Set Block Length rejected by card\n");
		decode_r1 (rsp[0]);
		return -1;
	}

	return 0;
}

int sdhc_set_width (unsigned short g_rca, int width){
	unsigned long rsp[4];

	rsp[0] = (g_rca << 16) | 0x0000FFFFUL;
	rsp[1] = 0xFFFFFFFCUL | (width == 1 ? 0UL : 2UL);	// 2'b00=1-bit, 2'b10=4-bit
	if (send_app_cmd (ACMD_SET_BUS_WIDTH, NORMAL, R48, 1, 1, rsp) < 0)	{
		db ("sdhc_set_width: Set Width (ACMD6) failed\n");
		return -1;
	}

	if (rsp[0] & R1_STAT_ERR)
	{
		db ("sdhc_set_width: Set Width rejected by card\n");
		decode_r1 (rsp[0]);
		return -1;
	}

	if (width == 4)
		SSD_REGWB(REG_u8HstCntl, SSD_REGRB(REG_u8HstCntl) | HCR_TRANS_WIDTH);	else if (width == 1)
		SSD_REGWB(REG_u8HstCntl, SSD_REGRB(REG_u8HstCntl) & ~HCR_TRANS_WIDTH);
	return 0;
}
//
// start of mostly sdio functions
//
#define	IO_READ_DIRECT(fn,addr)	((((fn) & 0x07UL) << 28) | ((addr) << 9))
#define IO_WRITE_DIRECT(fn,raw,addr,data) ((1UL << 31) | (((fn) & 0x07UL) << 28) |\
	       				((raw) ? (1 << 27) : 0) |\
					((addr) << 9) |\
					((data) & 0xFFUL))

#define IO_RW_EXT_WRITE		BIT(31)
#define IO_RW_EXT_MULTIBLK	BIT(27)
#define IO_RW_EXT_OPCODE	BIT(26)
#define IO_READ_EXT(fn,flags,addr,nblk,blklen)	\
		((((fn) & 0x7) << 28) | \
		(RW_MULTIBLK_EN((flags)) ? ((nblk == 0) ? 0 : IO_RW_EXT_MULTIBLK) : 0) |\
		(RW_IO_INCR_EN((flags)) ? IO_RW_EXT_OPCODE : 0) |\
		(((addr) & 0x1FFFF) << 9) |\
		((((nblk) == 0) ? (blklen) : \
		  	(((nblk) > 0) ? (nblk) : 0)) & 0x1FF))
			
#define IO_WRITE_EXT(fn,flags,addr,nblk,blklen)	\
		(IO_RW_EXT_WRITE | \
		(((fn) & 0x7) << 28) | \
		(RW_MULTIBLK_EN((flags)) ? ((nblk == 0) ? 0 : IO_RW_EXT_MULTIBLK) : 0) |\
		(RW_IO_INCR_EN((flags)) ? IO_RW_EXT_OPCODE : 0) |\
		(((addr) & 0x1FFFF) << 9) |\
		((((nblk) == 0) ? (blklen) : \
		  	(((nblk) > 0) ? (nblk) : 0)) & 0x1FF))


int io_reset () {
	unsigned long rsp[4];

	rsp[0] = IO_WRITE_DIRECT (0, 0, CCCR_ASR, CCCR_ASR_RESET);
	if (send_cmd (CMD_IO_RW_DIRECT, NORMAL, R0, 0, 0, 0, rsp) < 0) {		db ("IO reset failed\n");
		return -1;
	}
	return 0;
}

int io_write_byte (int fn, int raw, unsigned long addr, unsigned char data){
	unsigned long rsp[4];

	db ("io_write_byte: fn=%d, raw=%d, addr=0x%08lx, data=0x%02x\n", fn, raw, addr, data);
	rsp[0] = IO_WRITE_DIRECT (fn, raw, addr, data);
	if (send_cmd (CMD_IO_RW_DIRECT, NORMAL, R48, 0, 1, 1, rsp) < 0) {		db ("SDIO: io_write_byte failed\n");
		return -1;
	}
	else if (rsp[0] & R5_STAT_ERR) {
		decode_r5 (rsp[0]);
		return -1;
	}
	return raw ? rsp[0] & 0xFFUL : 0;
}

int io_read_byte (int fn, unsigned long addr, unsigned char *data){
	unsigned long rsp[4];

	rsp[0] = IO_READ_DIRECT (fn, addr);
	if (send_cmd (CMD_IO_RW_DIRECT, NORMAL, R48, 0, 1, 1, rsp) < 0) {		db ("SDIO: io_read_byte (fn=%d, addr=0x%08lx) failed\n", fn, addr);
		return -1;
	}
	else if (rsp[0] & R5_STAT_ERR) {
		db ("SDIO: io_read_byte (fn=%d, addr=0x%08lx) failed\n", fn, addr);
		decode_r5 (rsp[0]);
		return -1;
	}

	*data = (unsigned char) (rsp[0] & 0xffUL);
	db ("io_read_byte: fn=%d, addr=0x%08lx data=0x%02x\n", fn, addr, *data); 
	return 0;
}

int io_write_direct (int fn, unsigned long addr, unsigned char *data, int len){
	int i;
	unsigned long rsp[4];

	db ("io_write_direct: fn=%d, raw=0, addr=0x%08lx len=%d\n", fn, addr, len);
	for (i = 0; i < len; i++) {
		rsp[0] = IO_WRITE_DIRECT (fn, 0, addr+i, data[i]);
		if (send_cmd (CMD_IO_RW_DIRECT, NORMAL, R48, 0, 1, 1, rsp) < 0) {			db ("SDIO: direct write failed at offset=0x%x", i);
			return -1;
		}
		else if (rsp[0] & R5_STAT_ERR) {
			decode_r5 (rsp[0]);
			return -1;
		}
	}
	return 0;
}

int io_read_direct (int fn, unsigned long addr, unsigned char *data, int len){
	int i;
	unsigned long rsp[4];

	db ("io_read_direct: fn=%d, addr=0x%08lx len=%d\n", fn, addr, len);
	for (i = 0; i < len; i++) {
		rsp[0] = IO_READ_DIRECT (fn, addr+i);
		if (send_cmd (CMD_IO_RW_DIRECT, NORMAL, R48, 0, 1, 1, rsp) < 0) {			db ("SDIO: direct read failed at offset=0x%x\n", i);
			return -1;
		}
		else if (rsp[0] & R5_STAT_ERR) {
			decode_r5 (rsp[0]);
			return -1;
		}
		else
			data[i] = (unsigned char) (rsp[0] & 0xffUL);
	}
	return 0;
}

// end of mostly sdio functions


/* rw flags
 * byte0 - for sdhc hw options, eg. dma & autocmd12
 * byte1 - reserved
 * byte2 - for rd api
 * byte3 - for wr api
 */

#define RWF_DMA		0x00000001UL
#define RWF_AUTOCMD12	0x00000002UL
#define RWF_MULTIBLK	0x00000004UL	// set only for IO && when Multi block transfer is enabled
#define RWF_IO_INCR	0x00000008UL	// set only for IO, OP Code bit in IO_RW_EXTENDED, 0=fixed,1=incr
#define RWF_IO		0x00000010UL	// set for IO and cleared for Memory Read/Write

#define RWF_CONT	0x00000100UL	// not used
#define RWF_END		0x00000200UL	// not used
#define RWF_CURR_BUF	0x00000400UL	// used when RW_NOFILL_EN or RW_NOREAD_EN is enabled to signal selected buffer
#define RWF_SYNC	0x00000800UL	// used by interrupt routines

#define RWF_BYTECMP	0x00010000UL
#define RWF_BLKCMP	0x00020000UL
#define RWF_FILESAVE	0x00040000UL
#define RWF_NOREAD	0x00080000UL

#define RWF_BYTEFILL	0x01000000UL
#define RWF_BLKFILL	0x02000000UL
#define RWF_FILEFILL	0x04000000UL
#define RWF_NOFILL	0x08000000UL

// for both write & read
#define RW_DMA_EN(x)		((x) & RWF_DMA)
#define RW_AUTOCMD12_EN(x)	((x) & RWF_AUTOCMD12)
#define RW_MULTIBLK_EN(x)	((x) & RWF_MULTIBLK)	// checked for SDIO only
#define RW_IO_INCR_EN(x)	((x) & RWF_IO_INCR)	// checked for SDIO only
#define RW_IO_EN(x)		((x) & RWF_IO)		// checked for memory or SDIO access

// for continuous mode write via internal memory (RW_NOFILLE_EN=1)
#define RW_CONT_EN(x)		((x) & RWF_CONT)
#define RW_END_EN(x)		((x) & RWF_END)
#define RW_CURR_BUF(x)		((x) & RWF_CURR_BUF)
#define RW_SYNC_EN(x)		((x) & RWF_SYNC)

// for read_data
#define RW_BYTECMP_EN(x)	((x) & RWF_BYTECMP)
#define RW_BLKCMP_EN(x)		((x) & RWF_BLKCMP)
#define RW_FILESAVE_EN(x)	((x) & RWF_FILESAVE)
#define RW_NOREAD_EN(x)		((x) & RWF_NOREAD)
// for write_data
#define RW_BYTEFILL_EN(x)	((x) & RWF_BYTEFILL)
#define RW_BLKFILL_EN(x)	((x) & RWF_BLKFILL)
#define RW_FILEFILL_EN(x)	((x) & RWF_FILEFILL)
#define RW_NOFILL_EN(x)		((x) & RWF_NOFILL)

int fifo_reset (SDHCEXT_T *ext){	int i;	ext->u16FIFOCntl |= SWAP16(0x0001);	for (i = 0; i < MAX_WAIT; i++) {	       	delay_us (1);		if (!(ext->u16FIFOCntl & SWAP16(0x0001)))			break;	}	return 0;}int fifo_readback (SDHCEXT_T *ext, int n, unsigned char *data, int len){#define FIFOCNTL_RST	BIT16(0)#define FIFOCNTL_RDBK	BIT16(1)#define FIFOCNTL_SYSBUFSEL	BIT16(8)#define FIFOCNTL_SIBUFSEL	BIT16(9)	int i;	// turn on fifo readback bit in the extension register	// select the sys_buf_sel 0=fifo0, 1=fifo1	// copy data from fifo upto len bytes into g_data	db ("fifo_readback: status before reset: SYSBUFSEL=%d, SIBUFSEL=%d\n", 			SWAP16(ext->u16FIFOCntl & FIFOCNTL_SYSBUFSEL) ? 1:0,			SWAP16(ext->u16FIFOCntl & FIFOCNTL_SIBUFSEL) ? 1:0);	sdhc_reset (SW_RESET_DATA);	sdhc_reset (SW_RESET_CMD);		ext->u16FIFOCntl |= FIFOCNTL_RST;	for (i = 0; i < MAX_WAIT; i++) {	       	delay_us (1);		if (!(ext->u16FIFOCntl & FIFOCNTL_RST))			break;	}	ext->u16FIFOCntl |= FIFOCNTL_RDBK;	if (n)		ext->u16FIFOCntl |= FIFOCNTL_SYSBUFSEL;	else		ext->u16FIFOCntl &= ~FIFOCNTL_SYSBUFSEL;	db ("fifo_readback: FIFOCNTL = 0x%04x, SYSBUFSEL=%d\n", SWAP16(ext->u16FIFOCntl), n);	for (i = 0; i < len; i++)		*data++ = SSD_REGRB(REG_u8DataPort);		ext->u16FIFOCntl &= ~FIFOCNTL_RDBK;	sdhc_reset (SW_RESET_DATA);	sdhc_reset (SW_RESET_CMD);		return 0;}#ifdef __KERNEL__void sdhc_interrupt (void){	// interrupts are turned off here	// interrupts are enabled in sdhc_write_th	SSD_REGWW(REG_u16NrmIntrSignalEn , 0);	SSD_REGWW(REG_u16ErrIntrSignalEn , 0);	return;}int sdhc_read_ex ( 		unsigned long addr, 
		unsigned long data, // dma start address in amazon memory		int blklen, 
		long nblk, 
		unsigned long flags, 
		void *param)
{
	int	error = 0;
	unsigned short event = 0;
	unsigned short nisr = 0;
	unsigned short blkcnt = 0;
	unsigned long tmp;	unsigned long rsp[4];
	unsigned long blks_per_buf = 0;		// number of blocks that will fit into one dma buffer	unsigned long status = 0;
	// nblk = 0 -> single
	// nblk > 0 -> multiple
	// nblk < 0 -> not supported for sdhc_read_ex/sdhc_write#if 1/*	db ("sdhc_read_ex: addr=0x%08lx, data=0x%08lx, blklen=%d, nblk=%ld, flags=0x%08lx\n",		 addr, (unsigned long)data, blklen, nblk, flags);*/#endif
	if (RW_NOREAD_EN (flags)) {	       	if (!RW_DMA_EN(flags)) {			//debug ("sdhc_read_ex: dma must be enabled for RW_NOREAD_EN\n");			return -1;		}	}

	CEIL (nblk, 65535);

	SSD_REGWW(REG_u16NrmIntrStatus , (RW_DMA_EN(flags) ? INTR_DMA : INTR_BUF_RD_RDY));		// enable the data status registers
	SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn)& ~(INTR_BUF_RD_RDY | INTR_DMA));	SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn) | (INTR_DAT_COMPLETE | INTR_DMA | INTR_ERR));	SSD_REGWW(REG_u16ErrIntrStatusEn, SSD_REGRW(REG_u16ErrIntrStatusEn) | (EINTR_DAT_TOUT | EINTR_DAT_CRC | EINTR_DAT_END | EINTR_AUTOCMD12 |EINTR_VS_RSP_DIR | EINTR_VS_DAT_CONFLICT));#if 0	SSD_REGWW(REG_u16NrmIntrSignalEn |= (INTR_DAT_COMPLETE | INTR_DMA | INTR_ERR);	SSD_REGWW(REG_u16ErrIntrSignalEn |= (EINTR_DAT_TOUT | EINTR_DAT_CRC | EINTR_DAT_END | EINTR_AUTOCMD12 | 				EINTR_VS_RSP_DIR | EINTR_VS_DAT_CONFLICT);#endif	SSD_REGWW(REG_u16BlkSize , 0);	SSD_REGWW(REG_u16TrnsfrMode , TMR_RD_EN);	// make sure direction bit toggles	SSD_REGWW(REG_u16TrnsfrMode , 0);	SSD_REGWW(REG_u16TrnsfrMode, SSD_REGRW(REG_u16TrnsfrMode)| TMR_RD_EN | TMR_AUTOCMD12_EN |			(nblk != 0 ? TMR_MULTI_EN : 0) |	// nblk > 0 or nblk < 0 -> enable multiple
			(nblk > 0 ? TMR_BLKCNT_EN : 0));	// setup for read transfer 	SSD_REGWW(REG_u16BlkCount , (unsigned short) SWAP32 (nblk));	SSD_REGWW(REG_u16BlkSize , SWAP16 (blklen));	event = INTR_ERR;
	// calculate how many blocks can fit into the buffer without crossing the boundary	blks_per_buf=nblk; // (DMA_BASE_END - data) / blklen;//update on 2005-11-23 	//db ("sdhc_read_ex: blks_per_buf = %lu\n", blks_per_buf);
	SSD_REGWW(REG_u16TrnsfrMode, SSD_REGRW(REG_u16TrnsfrMode) | TMR_DMA_EN);	SSD_REGWW(REG_u16BlkSize ,SSD_REGRW(REG_u16BlkSize)| SWAP16 (HST_BNDRY_512KB << 12));	SSD_REGWL(REG_u32DMAAddr , SWAP32 (data));
	// start timer here			rsp[0] = addr;	if (send_cmd (			nblk ? CMD_RD_MULTIPLE : CMD_RD_SINGLE, 			NORMAL, R48, 1, 1, 1, rsp) < 0)	{
		debug ("sdhc_read_ex: Read Command(CMD%d) Failed\n",			nblk ? CMD_RD_MULTIPLE : CMD_RD_SINGLE);		error = 1;		goto l_err;	}

	if (rsp[0] & (R1_STAT_ERR | R1_STAT_ADDR_ERR | R1_STAT_OORANGE))	{
		debug ("sdhc_read_ex: Read Command(CMD%d) rejected by card\n",			nblk ? CMD_RD_MULTIPLE : CMD_RD_SINGLE);		decode_r1 (rsp[0]);		error = 1;
		goto l_err;
	}

	blkcnt = 0;	event |= ((nblk <= blks_per_buf) ? INTR_DAT_COMPLETE : INTR_DMA);	// start receiving data
	do {		int trial;		// for IO, INTR_DAT_COMPLETE is only set when the last block has been read out from the FIFO.
		// for DMA, INTR_DAT_COMPLETE is set when the last block has been transferred from FIFO into 
		// amazon memory even though the last address may not be on a DMA host boundary
		db ("sdhc_read_ex: nblk=%ld, blks_read = %lu event=0x%04x\n",			nblk, (unsigned long)blkcnt, SWAP16(event));				for(trial=0;trial<2000000;trial++)		{
			if( (nisr = SSD_REGRW(REG_u16NrmIntrStatus)) & event)			{				break;
			}			udelay(10);		}
				//while (!(nisr = SSD_REGWW(REG_u16NrmIntrStatus) & event)		//	;
		// any errors		if (SSD_REGRW(REG_u16ErrIntrStatus)) {			db ("sdhc_read_ex: (Error!) NISR = 0x%x, EISR =0x%x\n", 				SWAP16 (SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus)));			error = 1;
			break;
		}

		SSD_REGWW(REG_u16NrmIntrStatus , ((event & INTR_DMA) ? INTR_DMA : INTR_DAT_COMPLETE));		if (event & INTR_DMA)		{
			// set the next address here to continue the dma before any overrun			// occurs			SSD_REGWL(REG_u32DMAAddr , SWAP32(data));			blkcnt += blks_per_buf;			event = INTR_ERR | (((nblk - blkcnt) <= blks_per_buf) ? INTR_DAT_COMPLETE : INTR_DMA);		} else {			// we got a INTR_DAT_COMPLETE			tmp = nblk ? (nblk - blkcnt) : 1;			blkcnt += tmp;		}

	} while (nblk && blkcnt < nblk);	// stop timer here	if (error) {		sdhc_reset (SW_RESET_DATA);		sdhc_reset (SW_RESET_CMD);	}	// though an autocmd12 could have been sent, we c

⌨️ 快捷键说明

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