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

📄 spi_sd.c

📁 嵌入式linux系统下hi3510平台的osd开发源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 * extdrv/interface/spi_sd/spi_sd.c
 * Copyright (c) 2006 Hisilicon Co., Ltd. 
 *
 * 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.
 *
 * History:
 *      2006-4-11 create this file
 *     
 */
#include <asm-arm/arch-hi3510_v100_p01/hardware.h>
#include <linux/mmc/mmc.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <asm/arch/media-mem.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/hardware/clock.h>
#include <asm/arch/clock.h>

#include "sdcard.h"
#include "spi_sd.h"
#include "hi_ssp.h"



const int time_unit[8] = {1000000000,100000000,10000000,
							 1000000,100000,10000,1000,100};

/* timeout value table */							 
const char time_value[16] = {0,10,12,13,15,20,25,30,
                              35,40,45,50,55,60,70,80};
                              
const char r2w_fator[6] = {1,2,4,8,16,32}; 
	

unsigned int timeout_read;
unsigned int timeout_write;


#ifdef CONFIG_SSP_DMA

	DECLARE_WAIT_QUEUE_HEAD(sd_wq);

	struct dmac_ssp_t dmac_ssp_s;
	struct dmac_ssp_temp dmac_ssp_temp_s;
	int dmac_ssp_flag=0;

	/*
	 * ssp dma mode rx_hook sdcard routine.
	 *
	 */
	void rx_hook(void)
	{
		sd_wakup();
	}
	/*
	 * ssp dma mode init for sdcard routine.
	 * @param readbuf: dma mode readbuf
	 * @param writebuf: dma mode writebuf
	 *
	 * @return value: 0--success; -1--error.
	 *
	 */
	int sd_dmac_ssp_init(unsigned int *readbuf,unsigned int *writebuf)
	{
		hil_mmb_t *pBufAddr;
		
		memset(&dmac_ssp_s.ssptxchbufaddress,0,sizeof(dmac_ssp_s));
		dmac_ssp_temp_s.txbufaddress=0;
		dmac_ssp_temp_s.rxbufaddress=0;

		hi_ssp_dmac_init(rx_hook,NULL);
	        pBufAddr =hil_mmb_alloc("SSP_TEMP_TXBUF",PAGE_SIZE, 0, 0, NULL);
	        if(NULL == pBufAddr)
	        {
			printk("SSP_TEMP_TXBUF: cannot get mem\n");
			goto ssp_mmap_out;
	        }
	        dmac_ssp_temp_s.txbufaddress= hil_mmb_phys(pBufAddr);
	        dmac_ssp_temp_s.txbufmapaddress=(unsigned int)ioremap_nocache(dmac_ssp_temp_s.txbufaddress,PAGE_SIZE);
		memset((void *)dmac_ssp_temp_s.txbufmapaddress,0xff,PAGE_SIZE);
	
	        pBufAddr =hil_mmb_alloc("SSP_TEMP_RXBUF",PAGE_SIZE, 0, 0, NULL);
	        if(NULL == pBufAddr)
	        {
			printk("SSP_TEMP_RXBUF: cannot get mem\n");
			goto ssp_mmap_out;
	        }
	        dmac_ssp_temp_s.rxbufaddress= hil_mmb_phys(pBufAddr);
	        dmac_ssp_temp_s.rxbufmapaddress=(unsigned int)ioremap_nocache(dmac_ssp_temp_s.rxbufaddress,PAGE_SIZE);     
	
	        pBufAddr =hil_mmb_alloc("SSP_TXBUF1",DMAC_SSP_SIZE, 0, 0, NULL);
	        if(NULL == pBufAddr)
	        {
			printk("SSP_TXBUF1: cannot get mem\n");
			goto ssp_mmap_out;
	        }
	        dmac_ssp_s.ssptxchbufaddress= hil_mmb_phys(pBufAddr);
	        dmac_ssp_s.ssptxchbufmapaddress=(unsigned int)ioremap_nocache(dmac_ssp_s.ssptxchbufaddress,DMAC_SSP_SIZE);     
	        
	        pBufAddr= hil_mmb_alloc("SSP_RXBUF2",DMAC_SSP_SIZE, 0, 0, NULL);                          
	        if (NULL == pBufAddr) 
	        {
			printk("SSP_RXBUF2: cannot get mem\n");
			goto ssp_mmap_out;
	        }
	        dmac_ssp_s.ssprxchbufaddress =hil_mmb_phys(pBufAddr);
	        dmac_ssp_s.ssprxchbufmapaddress=(unsigned int)ioremap_nocache(dmac_ssp_s.ssprxchbufaddress,DMAC_SSP_SIZE);        
	
		*readbuf =dmac_ssp_s.ssprxchbufmapaddress;
		*writebuf=dmac_ssp_s.ssptxchbufmapaddress;
		memset((char *)dmac_ssp_s.ssprxchbufmapaddress,0,DMAC_SSP_SIZE);
		memset((char *)dmac_ssp_s.ssptxchbufmapaddress,0,DMAC_SSP_SIZE);
	        
	        return 0;  
	
	ssp_mmap_out:    
	        if(dmac_ssp_temp_s.txbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_temp_s.txbufaddress);
	        if(dmac_ssp_temp_s.rxbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_temp_s.rxbufaddress);
	        if(dmac_ssp_s.ssptxchbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_s.ssptxchbufaddress);
	        if(dmac_ssp_s.ssprxchbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_s.ssprxchbufaddress);
	        return -1;
		
	}

	/*
	 * ssp dma mode exit for sdcard routine.
	 *
	 */
	void sd_dmac_ssp_exit(void)
	{
	        if(dmac_ssp_temp_s.txbufaddress)
			hil_mmb_freeby_phys(dmac_ssp_temp_s.txbufaddress);
	        if(dmac_ssp_temp_s.rxbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_temp_s.rxbufaddress);
	        if(dmac_ssp_s.ssptxchbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_s.ssptxchbufaddress);
	        if(dmac_ssp_s.ssprxchbufaddress)
	        	hil_mmb_freeby_phys(dmac_ssp_s.ssprxchbufaddress);
	        hi_ssp_dmac_exit();       
	}
#endif
/*  
 *  sdcard power on routine.
 *
 */
void sdcard_power_on(void)
{
	writel(3|readl(IO_ADDRESS(SSP_GPIO_DIR)),IO_ADDRESS(SSP_GPIO_DIR));
	writel(2,IO_ADDRESS(SSP_GPIO3_1));
}
/*
 * sdcardpower off routine.
 *
 */
void sdcard_power_off(void)
{
	writel(3|readl(IO_ADDRESS(SSP_GPIO_DIR)),IO_ADDRESS(SSP_GPIO_DIR));
	writel(0,IO_ADDRESS(SSP_GPIO3_1));
}
/*
 * sdcard delay routine.
 * @param x: delay time (ms) 
 *
 */
void sdcard_delay(unsigned int x)
{
	msleep(x);
}
/*
 * power sdcard routine.
 *
 */
void sdcard_repower(void)
{
	sdcard_power_off();
	sdcard_delay(500);
	sdcard_power_on();	
	sdcard_delay(500);
}
/*
 * enable sdcard cs routine.
 *
 */
void sdcard_enable(void)
{
	writel(3|readl(IO_ADDRESS(SSP_GPIO_DIR)),IO_ADDRESS(SSP_GPIO_DIR));
	writel(0,IO_ADDRESS(SSP_GPIO3_0));
}
/*
 * disable sdcard cs routine.
 *
 */
void sdcard_disable(void)
{
	writel(3|readl(IO_ADDRESS(SSP_GPIO_DIR)),IO_ADDRESS(SSP_GPIO_DIR));
	writel(1,IO_ADDRESS(SSP_GPIO3_0));
}
/*
 * sdcard exit routine.
 *
 */
void sdcard_exit(void)
{
	sdcard_power_off();	
}
/*
 * init ssp for sdcard routine.
 *
 */
void ssp_init_for_sdcard(void)
{ 
 	hi_ssp_disable();
  	hi_ssp_set_frameform(SSP_CR0_FRF_MOT,SSP_CR0_SPO,SSP_CR0_SPH,SSP_CR0_DSS_8);
  	hi_ssp_set_serialclock(SSP_CR0_SCR_DFLT,SSP_CPSR_DFLT);
	hi_ssp_set_inturrupt(0);
  	#ifdef CONFIG_SSP_DMA
  		hi_ssp_dmac_enable();
  	#else
  		hi_ssp_dmac_disable();
  	#endif
  	hi_ssp_enable();
  	hi_ssp_interrupt_clear();
}
/*
 * write one byte of sdcard routine.
 * @param byte: write data
 *
 * @return value: read back data
 *
 */
unsigned char sdcard_write_byte(unsigned char byte)
{
	unsigned char tmp;
	
	while (hi_ssp_busystate_check());
   	hi_ssp_writedata(byte);
   	
   	while (hi_ssp_busystate_check());
   	tmp = hi_ssp_readdata();
  
   	return(tmp);
}
/*
 * read one byte of sdcard routine.
 *
 * @return value: read data
 *
 */
unsigned char sdcard_read_byte(void)
{
	unsigned char tmp;
	
	while (hi_ssp_busystate_check());
   	hi_ssp_writedata(0xff);
   	
   	while (hi_ssp_busystate_check());
   	tmp = hi_ssp_readdata();
  
   	return(tmp);
}
/*
 * transmit command of sdcard routine.
 * @param cmd: sdcard command
 *
 * @return value: command response signal
 *
 */
unsigned char sdcard_command(unsigned char *cmd)
{
	unsigned char tmp = 0xff;
	unsigned int i,timeout=0;
	
  	sdcard_disable();
       
  	for(i=0;i<16;i++)
  	{
  		sdcard_write_byte(0xff);
  	}
	sdcard_enable();

	for(i=0;i<6;i++)
	{
		sdcard_write_byte(*(cmd++));
	}
   
	while (tmp == 0xff)
	{
		tmp = sdcard_write_byte(0xff); 
		if (timeout++ > 100) 
		{
	 		break;
		}
	}
	 
	sdcard_disable();
   	
	for(i=0;i<16;i++)
	{
  		sdcard_write_byte(0xff);
  	}

  	return(tmp);
}
/*
 * transmit command1 of sdcard routine.
 * @param cmd: sdcard command
 *
 * @return value: command response signal
 *
 */
unsigned char sdcard_command1(unsigned char *cmd)
{
	unsigned short tmp = 0xff;
	unsigned int i,timeout=0;
	
  	sdcard_disable();
       
  	for(i=0;i<16;i++)
  	{
  		sdcard_write_byte(0xff);
  	}
  	    
    	sdcard_enable();
    	for(i=0;i<6;i++)
    	{
    		sdcard_write_byte(*(cmd+i));
    	}
   
	while (tmp != 0x0) 
	{
		tmp = sdcard_write_byte(0xff);
		if (timeout++ > 20) 
		{
	 		break;
		}
		if(tmp==1 ){break;}
	}
	for(i=0;i<16;i++)
	{
  		sdcard_write_byte(0xff);
  	}
	sdcard_disable();
  	return(tmp);
}
/*
 * transmit command2 of sdcard routine.
 * @param cmd: sdcard command
 *
 * @return value: command response signal
 *
 */
unsigned char sdcard_command2(unsigned char *cmd)
{
	unsigned char tmp = 0xff;
	unsigned int i,timeout=0;
	
  	sdcard_disable();
       
  	for(i=0;i<16;i++)
  	{
  		sdcard_write_byte(0xff);
  	}
  	    
	sdcard_enable();

	for(i=0;i<6;i++)
	{
		tmp=sdcard_write_byte(*(cmd+i));
	}

	do
	{
		tmp = sdcard_write_byte(0xff);
		if (timeout++ > 100) 
		{
	 		break;
		}
		
		if(*cmd==0x77)
		{
			if(tmp==1 )
			break;
		}
		
	}while(tmp != 0);
	
  	return(tmp);
}
/*
 * init sdcard routine.
 *
 * @return value: 0--success; 1-- command 0 send faiture,2-- ACMD41 send faiture.  
 */
unsigned int sdcard_init(void)
{
	unsigned char CMD0[]={0x40,0x00,0x00,0x00,0x00,0x95};
	unsigned char CMD55[]={0x77,0x00,0x00,0x00,0x00,0xff};
	unsigned char ACMD41[]={0x69,0x00,0x00,0x00,0x00,0xff};
	unsigned char tmp =0xff;
	unsigned int timeout=0;
	
	ssp_init_for_sdcard();	

	timeout=0;tmp=0xff;
	do{
		tmp=sdcard_command(CMD0);
		if(timeout++>100)
			return 1;
	}while(tmp!=1);

	timeout=0;tmp=0xff;
	while(tmp != 0x00)
	{
		msleep(10);

⌨️ 快捷键说明

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