📄 s3c2410_spi.c
字号:
// 安装 SPI 中断处理程序
if (request_irq(IRQ_SPI, spi_intr, SA_INTERRUPT, "spi_drv", spi_local)){
SPI_DEBUG("s3c2410_spi: unable to get IRQ %d\n", IRQ_SPI);
return -EAGAIN;
}
DisInt_SPI;
set_external_irq(IRQ_PWR,3,0);
// 安装 power off 中断处理程序
if (request_irq(IRQ_PWR, powerOff, SA_INTERRUPT, "spi_drv", spi_local)){
SPI_DEBUG("s3c2410_power: unable to get IRQ %d\n", IRQ_SPI);
return -EAGAIN;
}
printk(KERN_INFO "SPI Module success load!!!\n");
return 0;
}
static void __exit spi_cleanup_module( )
{
free_irq(IRQ_SPI, spi_local);
free_irq(IRQ_PWR, spi_local);
printk(KERN_INFO "Exit SPI module!\n");
devfs_unregister_chrdev(spi_drv_major, "spi_drv");
devfs_unregister(dev_handle);
return;
}
static void send_packet(struct spi_dev *pdev)
{
int i,tail;
unsigned char *p=(unsigned char*)&ADSL_Packet;
//填写发送缓冲区
while(pdev->send_buf.size+ADSL_Packet.Length>BUF_SIZE)
schedule();
tail=pdev->send_buf.tail;
for(i=0;i<6;i++){
pdev->send_buf.buffer[tail++]=p[i];
tail%=BUF_SIZE;
}
if(ADSL_Packet.Data!=NULL)
for(i=0;i<ADSL_Packet.Length-10;i++){
pdev->send_buf.buffer[tail++]=ADSL_Packet.Data[i];
tail%=BUF_SIZE;
}
for(i=0;i<4;i++){
pdev->send_buf.buffer[tail++]=p[i+10];
tail%=BUF_SIZE;
}
pdev->send_buf.size+=ADSL_Packet.Length;
pdev->send_buf.tail=tail;
HaveSendPacket=YES;
DisInt_SPI;
TimeOut=NO;
inb(SPRDAT);
EnInt_SPI;
return;
}
static int spi_ioctl(struct inode *inode, struct file *p_file, unsigned int cmd, unsigned long arg)
{
struct spi_dev *plocal=p_file->private_data;
int head;
unsigned char *p;
unsigned long j,jj;
unsigned char tempdata;
/*
if ( _IOC_TYPE(cmd) != SPI_IOC_MAGIC )
return -ENOTTY;
*/
if ( _IOC_NR(cmd) > SPI_IOC_MAXNR )
return -ENOTTY;
switch (cmd){
case SPI_SET_BOOTLEN:
BootDataLen=arg;
SPI_DEBUG("Boot file length=%li\n",arg);
break;
case SPI_SEND_BOOTDATA:
write_gpio_bit(RESET,0);
Delay10ms(300);
write_gpio_bit(nSS,1);
write_gpio_bit(RESET,1);
j=jiffies+1000*(HZ/100);
while(read_gpio_bit(IO4)&&j>jiffies);
//wait IO4 to low
if(read_gpio_bit(IO4)){
printk(KERN_INFO "DSP Reset failor\n");
return -EINVAL;
}
cli();
for(i=0;i<BootDataLen;i++){
while(read_gpio_bit(IO4)); //wait IO4 to low
while(!(SPSTA&SPSTA_READY));
tempdata=*(unsigned char*)(arg+i);
write_gpio_bit(nSS,1);
outb(tempdata>>1,SPTDAT);
while(!(SPSTA&SPSTA_READY));
write_gpio_bit(nSS,0);
outb(tempdata<<7,SPTDAT);
}
sti();
Delay10ms(300);
write_gpio_bit(GPIO_G4,1);
SPI_DEBUG("Success send boot data to DSP\n");
break;
case SPI_ADSL_PSD:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("PSD Calibrate!\n");
}
else{
ADSL_Packet.CmdType=NormalModeTest;
SPI_DEBUG("PSD Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_PSD;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_PSD;
send_packet(plocal);
break;
case SPI_ADSL_RMS:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
}
else{
ADSL_Packet.CmdType=NormalModeTest;
}
ADSL_Packet.TestType=SPI_ADSL_RMS;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_RMS;
send_packet(plocal);
break;
case SPI_VALUE_UP:
ADSL_Packet.HeadFlag=0x55aa;
ADSL_Packet.CmdType=CalibrateMode;
ADSL_Packet.TestType=SPI_VALUE_UP;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_VALUE_UP;
send_packet(plocal);
break;
case SPI_VALUE_DOWN:
ADSL_Packet.HeadFlag=0x55aa;
ADSL_Packet.CmdType=CalibrateMode;
ADSL_Packet.TestType=SPI_VALUE_DOWN;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_VALUE_DOWN;
send_packet(plocal);
break;
case SPI_SEND:
ADSL_Packet.HeadFlag=0x55aa;
ADSL_Packet.CmdType=CalibrateMode;
ADSL_Packet.TestType=SPI_SEND;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_SEND;
send_packet(plocal);
break;
case SPI_SEND_END:
ADSL_Packet.HeadFlag=0x55aa;
ADSL_Packet.CmdType=CalibrateMode;
ADSL_Packet.TestType=SPI_SEND_END;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_SEND_END;
send_packet(plocal);
break;
case SPI_ADSL_ATT:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("Att Calibrate!\n");
}
else{
if(arg==0)
ADSL_Packet.CmdType=MasterModeTest;
else
ADSL_Packet.CmdType=SlaveModeTest;
SPI_DEBUG("Att Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_ATT;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_ATT;
send_packet(plocal);
break;
case SPI_ADSL_BALANCE:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("Balance Calibrate!\n");
}
else{
ADSL_Packet.CmdType=NormalModeTest;
SPI_DEBUG("Balance Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_BALANCE;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_BALANCE;
send_packet(plocal);
break;
case SPI_ADSL_FEXT:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("FEXT Calibrate!\n");
}
else{
if(arg==0) //arg=0,master mode
ADSL_Packet.CmdType=MasterModeTest;
else
ADSL_Packet.CmdType=SlaveModeTest; //arg=1,slave mode
SPI_DEBUG("FEXT Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_FEXT;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_FEXT;
send_packet(plocal);
break;
case SPI_ADSL_NEXT:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("NEXT Calibrate!\n");
}
else{
ADSL_Packet.CmdType=NormalModeTest;
SPI_DEBUG("NEXT Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_NEXT;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_NEXT;
send_packet(plocal);
break;
case SPI_ADSL_VOL:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("Vol Calibrate!\n");
}
else{
ADSL_Packet.CmdType=NormalModeTest;
SPI_DEBUG("Vol Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_VOL;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_VOL;
send_packet(plocal);
break;
case SPI_ADSL_RES:
ADSL_Packet.HeadFlag=0x55aa;
if(arg==5){
ADSL_Packet.CmdType=CalibrateMode;
SPI_DEBUG("Res Calibrate!\n");
}
else{
ADSL_Packet.CmdType=NormalModeTest;
SPI_DEBUG("Res Test!\n");
}
ADSL_Packet.TestType=SPI_ADSL_RES;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_RES;
send_packet(plocal);
break;
case SPI_ADSL_STOPTEST:
ADSL_Packet.HeadFlag=0x55aa;
ADSL_Packet.CmdType=StopTest;
ADSL_Packet.TestType=SPI_ADSL_RESERVE;
ADSL_Packet.Data=NULL;
ADSL_Packet.CRC32=0;
ADSL_Packet.Length=10;
CurTestType=SPI_ADSL_RESERVE;
send_packet(plocal);
break;
case SPI_CHECK_DATA:
if(TimeOut==YES)
return TestDataTimeOut;
if(RxPacketNum>0){
*(unsigned int*)arg=RxPacketNum;
return TestDataReady;
}
else
return TestDataNotReady;
break;
case SPI_GET_DATA:
head=plocal->recv_buf.head;
i=0;
p=(unsigned char*)arg;
while(RxCounters[RxPacketHead]--){
p[i]=plocal->recv_buf.buffer[head++];
head%=BUF_SIZE;
i++;
}
RxPacketHead++;
RxPacketHead%=1024;
RxPacketNum--;
plocal->recv_buf.head=head;
plocal->recv_buf.size-=i;
SPI_DEBUG("Get %d byte from recv\n",i);
break;
case SPI_POWER_OFF:
if(powerCTL_EN){
write_gpio_bit(GPIO_G8,0);
}
break;
case SPI_POWER_ON:
write_gpio_bit(GPIO_G8,1);
break;
case SPI_MODEM_RESET:
write_gpio_bit(GPIO_H4,0);
Delay10ms(500);
write_gpio_bit(GPIO_H4,1);
modem_reset = 1; //send signal to modem daemon.
break;
case SPI_BLIGHT_ON:
write_gpio_bit(GPIO_G4,1);
break;
case SPI_BLIGHT_OFF:
write_gpio_bit(GPIO_G4,0);
break;
case SPI_MODEM_STARTUP: //2005-5-8
enable_config = read_gpio_bit(GPIO_G9);
*(unsigned int*)arg = enable_config;
break;
case SPI_MODEM_RESET_FLAG:
*(unsigned int*)arg = modem_reset;
break;
case SPI_MODEM_FLAG_CLEAR:
modem_reset = 0;
enable_config = 0;
SPI_DEBUG("Modem FLAG CLEARED!\n");
break;
case SPI_PWRCTL_ENABLE:
powerCTL_EN = 1;
SPI_DEBUG("Enable PWR interrupt!\n");
break;
default:
return -EINVAL;
}
return ACCESS_OK;
}
static inline void Delay10ms(int num)
{
unsigned long j=jiffies+num*(HZ/100);
while(j>jiffies);
return;
}
module_init(spi_init_module);
module_exit(spi_cleanup_module);
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -