📄 spi_sd.c
字号:
/*
* 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 + -