📄 tda8007.c
字号:
/****************************************Copyright (c)**************************************************
** 北京研祥兴业有限公司
** 研发部
** http://www.FFTChina.com
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名: TDA8007.c
**创 建 人: 刘丙毓
**最后修改日期: 2007年9月26日
**-------------- 历史版本信息----------------------------------------------------------------------------
** 创建人: 刘丙毓
** 版 本: v1.0
** 日 期: 2007年9月26日
** 描 述: 原始版本
**
**AD0 ---- BA0 ----- A0
**AD1 ---- BA1 ----- A1
**AD2 ---- BA2 ----- A2
**AD9 ---- BA9 ----- A9
**TDA_INT --- EINT3
**TDA_CS ---- CPLD_67
**TDA_WR ---- CPLD_68
**TDA_RD ---- CPLD_69
**TDA_PWR_EN ---- GPB3
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
/*
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/param.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/TdaDriver.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/irq.h> /* For IRQ_MACHSPEC */
#include <asm/uaccess.h>
#include <asm/io.h>
#include "TDA8007.h"
/* For IRQ_MACHSPEC */
static const char* __file__ = __FILE__;
#define IC_MINOR 0
#define DEVICE_NAME "s3c2410IC"
#define _INLINE_ inline
#define DEBUG 1
static u8 *TDA1addr;
unsigned int *can0addr;
void clearATRstruct(struct ATR*);
static int tda_ATRsequence(uchar mode, uchar *rec_buf, int * rec_len);
#define TDA_ICCARD_BUF_SIZE 1024
static struct ICCARDFIFO {
unsigned char buffer[TDA_ICCARD_BUF_SIZE];
int len;
}iccardfifo;
#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_ICraw;
#endif
static int iccard_device_open = 0;
static int DbIcMajor = 0;
static int card_selected = NONECARD;
static int samcard_err = -1;
static int usrcard_err = -1;
static char place_err ;
//static char reset_err ;
unsigned char *temp_60;
struct ATR lastATR[CARD_SLOTS];
uchar TMode[CARD_SLOTS]; // T=0 or T=1
uint WWT[CARD_SLOTS]; // Work wait time
uint CWT[CARD_SLOTS]; // Character wait time
uchar currentSlot = 0;
#define C1_IC (1<<12) /* icache off/on */
#define C1_DC (1<<2) /* dcache off/on */
static void cp_delay (void)
{
volatile int i;
/* copro seems to need some delay between reading and writing */
for (i = 0; i < 100; i++);
}
static unsigned long read_p15_c1 (void)
{
unsigned long value;
__asm__ __volatile__(
"mrc p15, 0, %0, c1, c0, 0 @ read control reg\n"
: "=r" (value)
:
: "memory");
return value;
}
static void write_p15_c1 (unsigned long value)
{
#ifdef MMU_DEBUG
printf ("write %08lx to p15/c1\n", value);
#endif
__asm__ __volatile__(
"mcr p15, 0, %0, c1, c0, 0 @ write it back\n"
:
: "r" (value)
: "memory");
read_p15_c1 ();
}
void dcache_enable (void)
{
ulong reg;
reg = read_p15_c1 ();
cp_delay ();
write_p15_c1 (reg | C1_DC);
}
void dcache_disable (void)
{
ulong reg;
reg = read_p15_c1 ();
cp_delay ();
reg &= ~C1_DC;
write_p15_c1 (reg);
}
int dcache_status (void)
{
return (read_p15_c1 () & C1_DC) != 0;
}
void icache_enable (void)
{
ulong reg;
reg = read_p15_c1 (); /* get control reg. */
cp_delay ();
write_p15_c1 (reg | C1_IC);
}
void icache_disable (void)
{
ulong reg;
reg = read_p15_c1 ();
cp_delay ();
write_p15_c1 (reg & ~C1_IC);
}
int icache_status (void)
{
return (read_p15_c1 () & C1_IC) != 0;
}
/*************************************************************************
功能:delay us
参数:
返回值:-1: error
0: OK
**************************************************************************/
static void delay_us(uint usnum)
{
volatile int i;
for(;usnum > 0;usnum--)
for(i = 0; i < 50; i++);
}
/*************************************************************************
功能:
参数:
返回值:-1: error
0: OK
**************************************************************************/
static _INLINE_ void tda_writeregister(int address,u8 value)
{
switch (address)
{
case TOC:
case UTR:
// If writing TOC or UTR, check the CRED bit in MSR so that
// we don't overrun the 8007. See MSR.CRED bit description on page
// 18 of 8007 spec.
while (!(readb(TDA1addr + MSR) & MSR_CRED_MASK));
break;
default:
break;
}
writeb(value, TDA1addr + address);//(unsigned long)
//*(volatile unsigned short*)(TDA1addr + address) = value;
//printk("WR : Command = 0x%p Data = 0x%x\n",TDA1addr + address,value);
//delay_us(100);
}
/*************************************************************************
功能:
参数:
返回值:-1: error
0: OK
**************************************************************************/
static _INLINE_ u8 tda_readregister(int address)
{
u8 toReturn = 0;
switch (address)
{
case URR:
// If reading URR, check the CRED bit in MSR so that
// we don't overrun the 8007. See MSR.CRED bit description on page
// 18 of 8007 spec.
while (!(readb(TDA1addr + MSR) & MSR_CRED_MASK))
{
// If card de-powers exit with zero return value.
//delay_us(100);
if ((readb(TDA1addr + PCR) & 0x01) == 0)// there is possible to become permanent cycle run
{
return 0;
}
}
break;
default:
break;
}
//printk("Command = 0x%p", TDA1addr + address);//(unsigned long)
toReturn = readb( TDA1addr + address);//(unsigned long)
//delay_us(100);
//printk(" Data = 0x%x\n",toReturn);
return toReturn;
}
/*************************************************************************
功能:Dump formatted contents of ATR struct
参数:
返回值:-1: error
0: OK
**************************************************************************/
void s3c2410_isr_tda(int irq,void *dev_id,struct pt_regs *reg)
{
uchar tmp = 0;
tmp = tda_readregister(USR);
if(tmp & USR_TOL1_MASK)printk("Time-Out counter 1 has reched terminal count.\n");
if(tmp & USR_TOL2_MASK)printk("Time-Out counter 2 has reched terminal count.\n");
if(tmp & USR_TOL3_MASK)printk("Time-Out counter 3 has reched terminal count.\n");
tmp = tda_readregister(HSR);
if(tmp & HSR_PTL_MASK)
{
tda_selectcard(USRCARD);
tda_powerdown();
tda_selectcard(SAMCARD);
tda_powerdown();
}
}
/*************************************************************************
功能:
参数:
返回值:-1: error
0: OK
**************************************************************************/
static void clearATRStruct(struct ATR *myatr)
{
memset(myatr,0xFF,sizeof(struct ATR));
myatr->HistoricalLength = 0;
}
/*************************************************************************
功能:
参数:
返回值:-1: error
0: OK
**************************************************************************/
static int tda_init(void)
{
u8 val = 0;
val = tda_readregister(CSR);
tda_writeregister(CSR,val & ~(CSR_SC1_MASK | CSR_SC2_MASK | CSR_SC1_MASK));
val = tda_readregister(CSR);
tda_writeregister(CSR,(val | CSR_SC1_MASK) & ~(CSR_SC2_MASK | CSR_SC3_MASK));
val = tda_readregister(CSR);
tda_writeregister(CSR,val & ~CSR_nRIU_MASK);
tda_writeregister(CSR,val | CSR_nRIU_MASK);
val = tda_readregister(CSR);
tda_writeregister(CSR,(val | CSR_SC2_MASK) & ~(CSR_SC1_MASK | CSR_SC3_MASK));
val = tda_readregister(CSR);
tda_writeregister(CSR,val & ~CSR_nRIU_MASK);
tda_writeregister(CSR,val | CSR_nRIU_MASK);
val = tda_readregister(CSR);
tda_writeregister(CSR,(val | CSR_SC3_MASK) & ~(CSR_SC1_MASK | CSR_SC2_MASK));
val = tda_readregister(CSR);
tda_writeregister(CSR,val & ~CSR_nRIU_MASK);
tda_writeregister(CSR,val | CSR_nRIU_MASK);
//tda_readregister(CSR);//debug
// Select smart card slot 1
val = tda_readregister(CSR);
tda_writeregister(CSR,(val | CSR_SC1_MASK) & ~(CSR_SC2_MASK | CSR_SC3_MASK));
// Make sure card is powered down
val = tda_readregister(PCR);
tda_writeregister(PCR,val & ~PCR_START_MASK);
// Select smart card slot 2
val = tda_readregister(CSR);
tda_writeregister(CSR,(val | CSR_SC2_MASK) & ~(CSR_SC1_MASK | CSR_SC2_MASK));
// Make sure card is powered down
val = tda_readregister(PCR);
tda_writeregister(PCR,val & ~PCR_START_MASK);
//tda_readregister(CSR);//debug
// Deselect all cards
val = tda_readregister(CSR);
tda_writeregister(CSR,val & ~(CSR_SC1_MASK | CSR_SC2_MASK | CSR_SC3_MASK));
return 0;
}
/*************************************************************************
功能:
参数:
返回值:-1: error
0: OK
**************************************************************************/
static int tda_powerup(uchar mode, uchar voltage)
{
uchar val;
// Compile time setting of operating crystal frequency
#if ((CRYSTAL_FREQUENCY_8007 >= 1000000L) && (CRYSTAL_FREQUENCY_8007 <= 5000000L))
// Set smartcard clock to 1/1 crystal
tda_writeregister(CCR,0x00);
#elif ((CRYSTAL_FREQUENCY_8007 >= 2000000L) && (CRYSTAL_FREQUENCY_8007 <= 10000000L))
// Set smartcard clock to 1/2 crystal
tda_writeregister(CCR,0x01);
#elif ((CRYSTAL_FREQUENCY_8007 >= 4000000L) && (CRYSTAL_FREQUENCY_8007 <= 20000000L))
// Set smartcard clock to 1/4 crystal
tda_writeregister(CCR,0x02);
#elif ((CRYSTAL_FREQUENCY_8007 >= 8000000L) && (CRYSTAL_FREQUENCY_8007 <= 40000000L))
// Set smartcard clock to 1/8 crystal
tda_writeregister(CCR,0x03);
#else
// Set smartcard clock to 1/2 internal oscillator (about 1.44MHz)
// NOTE: Can only change CCR.2 when shifting to internal oscillator
tda_writeregister(CCR,0x01);
tda_writeregister(CCR,0x05);
// Wait for internal oscillator to engage (check the MSR.CLKSW bit on page 18)
if ( DEBUG > 2 )
printk("Waiting for Clock to switch\n");
do
{
val = tda_readregister(MSR);
}while (!(val & MSR_CLKSW_MASK));
#endif
printk("Preparing to Apply Power1\n");
// Set the power supply voltage
val = tda_readregister(PCR);
// Clear 1.8V and 3V bits
tda_writeregister(PCR,val & ~(PCR_3V_5V_MASK|PCR_1V8_MASK));
switch(voltage)
{
case POWERUP_5V:
// Do nothing
break;
case POWERUP_3V:
val = tda_readregister(PCR);
// Set 3V bit
tda_writeregister(PCR,val | PCR_3V_5V_MASK);
break;
case POWERUP_1p8V:
val = tda_readregister(PCR);
// Set 1.8V bit
tda_writeregister(PCR,val | PCR_1V8_MASK);
break;
default:
return ERR_POWERUP_VOLTAGE_INVALID;
break;
}
// Apply reset
val = tda_readregister(PCR);
tda_writeregister(PCR,val & ~PCR_RSTIN_MASK);
printk("Preparing to Apply Power1\n");
val = tda_readregister(HSR);//clear HSR
do
{
//Power the card, RST low, C4 and C8 high
val = tda_readregister(PCR);
tda_writeregister(PCR,val | (PCR_C8_MASK|PCR_C4_MASK|PCR_START_MASK));
//tda_writeregister(PCR,val | PCR_START_MASK);
val = tda_readregister(HSR);
if (val & (HSR_PRTL2_MASK|HSR_PRTL1_MASK|HSR_PRL2_MASK|HSR_PRL1_MASK|HSR_PTL_MASK))
{
#if DEBUG > 0
printk("Power problem detected 0x%2x\n",val);
#endif
tda_powerdown();
return ERR_POWERUP_INTERRUPTED;
}
val = tda_readregister(PCR);
}while (!(val & PCR_START_MASK));
#if DEBUG > 1
printk("Power is on\n");
#endif
// Call common getATR routine
return 0;
//return tda_ATRsequence(mode);
}
/*************************************************************************
功能:
参数:
Read a byte from the UART or timeout after BWT (T=1), CWT (T=1) or WWT (T=0).
Not tested
返回值:-1: error
0: OK
**************************************************************************/
static signed char readByte(uchar *temp)
{
u8 val;
uint timeout;
//printk("tda_readregister(UCR1) = 0x%x\n",tda_readregister(UCR1));
if (TMode[currentSlot] == 0)
timeout = WWT[currentSlot]; // Use WWT for T=0
else
timeout = CWT[currentSlot]; // Use CWT for T=1
// Set up timer for 24 bit timer, start immediately
//while(!(tda_readregister(USR) & USR_TBE_RBF_MASK))
while(!(tda_readregister(MSR) & MSR_TBE_RBF_MASK))
{
val = tda_readregister(USR);
if (val & USR_PE_MASK)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -