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

📄 slic.c

📁 linux下的SPI总线驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <linux/autoconf.h>#include <asicRegs.h>#include <rtl8651_tblAsicDrv.h>#include "../../rtl865x/voip_support.h"#include "rtl_glue.h"#include "rtl_types.h"#include "rtl_errno.h"#include "gpio.h"#include "spi.h"#include "slic.h"#include "../pcm2.h"static rtl8651_spi_dev_t dev[TOTAL_SLIC_CHANNEL];rtl8651_spi_dev_t* spiDev = dev;static PROSLIC_t chipData[TOTAL_SLIC_CHANNEL];PROSLIC_t* slic_data = chipData;/*  The following Array contains: Reg# Label Initial Value*/indirectRegister  indirectRegisters[] ={	{	0,	"DTMF_ROW_0_PEAK",		0x55C2	},	{	1,	"DTMF_ROW_1_PEAK",		0x51E6	},	{	2,	"DTMF_ROW2_PEAK",		0x4B85	},	{	3,	"DTMF_ROW3_PEAK",		0x4937	},	{	4,	"DTMF_COL1_PEAK",		0x3333	},	{	5,	"DTMF_FWD_TWIST",		0x0202	},	{	6,	"DTMF_RVS_TWIST",		0x0202	},	{	7,	"DTMF_ROW_RATIO",		0x0198	},	{	8,	"DTMF_COL_RATIO",		0x0198	},	{	9,	"DTMF_ROW_2ND_ARM",		0x0611	},	{	10,	"DTMF_COL_2ND_ARM",		0x0202	},	{	11,	"DTMF_PWR_MIN_",		0x00E5	},	{	12,	"DTMF_OT_LIM_TRES",		0x0A1C	},	{	13,	"OSC1_COEF",			0x7b30	},	{	14,	"OSC1X",				0x0063	},	{	15,	"OSC1Y",				0x0000	},	{	16,	"OSC2_COEF",			0x7870	},	{	17,	"OSC2X",				0x007d	},	{	18,	"OSC2Y",				0x0000	},	{	19,	"RING_V_OFF",			0x0000	},	{	20,	"RING_OSC",				0x7EF0	},	{	21,	"RING_X",				0x0160	},	{	22,	"RING_Y",				0x0000	},	{	23,	"PULSE_ENVEL",			0x2000	},	{	24,	"PULSE_X",				0x2000	},	{	25,	"PULSE_Y",				0x0000	},	{	26,	"RECV_DIGITAL_GAIN",	0x4000	},	{	27,	"XMIT_DIGITAL_GAIN",	0x4000	},	{	28,	"LOOP_CLOSE_TRES",		0x1000	},	{	29,	"RING_TRIP_TRES",		0x3600	},	{	30,	"COMMON_MIN_TRES",		0x1000	},	{	31,	"COMMON_MAX_TRES",		0x0080	},	{	32,	"PWR_ALARM_Q1Q2",		0x07c0  },	{	33,	"PWR_ALARM_Q3Q4",		0x376f	},	{	34,	"PWR_ALARM_Q5Q6",		0x1B80	},	{	35,	"LOOP_CLSRE_FlTER",		0x8000	},	{	36,	"RING_TRIP_FILTER",		0x0320	},	{	37,	"TERM_LP_POLE_Q1Q2",	0x008c  },	{	38,	"TERM_LP_POLE_Q3Q4",	0x008c  },	{	39,	"TERM_LP_POLE_Q5Q6",	0x0010	},	{	40,	"CM_BIAS_RINGING",		0x0200	},	{	41,	"DCDC_MIN_V",			0x0C00	},	{	43,	"LOOP_CLOSE_TRES Low",	0x1000	},	{	99,	"FSK 0 FREQ PARAM",		0x00DA	},	{	100,"FSK 0 AMPL PARAM",		0x6B60	},	{	101,"FSK 1 FREQ PARAM",		0x0074	},	{	102,"FSK 1 AMPl PARAM",		0x79C0	},	{	103,"FSK 0to1 SCALER",		0X1120	},	{	104,"FSK 1to0 SCALER",		0x3BE0	},	{	 97,"RCV_FLTR",				0},	{     0,"",                     0},};/****************** COMMON TELEPHONEY TONES*********************************//* DialTone: when you take up the phone */tone_struct DialTone = {  /* OSC1= 350 Hz OSC2= 440 Hz .0975 Volts -18 dBm */	{0x7b30,0x0063,0,0,0,0,0},{0x7870,0x007d,0,0,0,0,0}};/* when caller does not dial properly */tone_struct ReorderTone = {	/* OSC1= 480 Hz OSC2 = 620 .0975 Volts -18 dBm */	{0x7700,0x0089,0,0x09,0x60,0x06,0x40},{0x7120,0x00b2,0,0x09,0x60,0x06,0x40}};/* when callee is busy */tone_struct CongestionTone = { /* OSC1= 480 Hz OSC2 = 620 .0975 Volts -18 dBM */	{0x7700,0x0089,0,0x06,0x40,0x09,0x60},{0x7120,0x00b2,0,0x06,0x40,0x09,0x60}};tone_struct RingbackPBX = {	/* OSC1 = 440 Hz OSC2= 480 .0975 Volts -18 dBM */	{0x7870,0x007d,0,0x1f,0x40,0x5d,0xc0},{0x7700,0x0089,0,0x1f,0x40,0x5d,0xc0}};tone_struct RingbackNormal = { /* OSC1 = 440 Hz OSC2 = 480 .0975 Volts -18 dBm */	{0x7870,0x007d,0,0x3e,0x80,0x7d,0x00},{0x7700,0x0089,0,0x3e,0x80,0x7d,0x00}};tone_struct BusySignal = { /* OSC1= 480  OSC2 = 620 .0975 Voltz -18 dBm 8*/	{0x7700,0x0089,0,0x0f,0xa0,0x0f,0xa0},{0x7120,0x00b2,0,0x0f,0xa0,0x0f,0xa0}};tone_struct RingbackJapan = { /* OSC1 = 400 Hz OSC2 = 435 .0975 Volts -18 dBm */	{0x79c0,0x00e9,0,0x1f,0x40,0x3e,0x80},{0x7940,0x00f2,0,0x1f,0x40,0x3e,0x80}};tone_struct BusyJapan = { /* OSC1 = 400 Hz OSC2 = 435 .0975 Volts -18 dBm */	{0x79c0,0x00e9,0,0x0f,0xa0,0x0f,0xa0},{0,0,0,0,0,0,0}};tone_struct JapanDialTone = { /* OSC1 = 400 Hz OSC2 = 435 .0975 Volts -18 dBm */	{0x79c0,0x00e9,0,0,0,0,0},{0,0,0,0,0,0,0}};int32 current_channel = 0;/*INFO: Freq = 400.000000    for n=1 or n=2 OSCn = 0x79c0, OSCnX = 0x0071, OSCnY = 0x0000C:\>tone 420 .0975INFO: Freq = 420.000000    for n=1 or n=2 OSCn = 0x7920, OSCnX = 0x0077, OSCnY = 0x0000C:\>tone 415 .0975INFO: Freq = 415.000000    for n=1 or n=2 OSCn = 0x7940, OSCnX = 0x0076, OSCnY = 0x0000C:\>tone 415 .2INFO: Freq = 415.000000    for n=1 or n=2 OSCn = 0x7940, OSCnX = 0x00f2, OSCnY = 0x0000C:\>tone 400 .2INFO: Freq = 400.000000    for n=1 or n=2 OSCn = 0x79c0, OSCnX = 0x00e9, OSCnY = 0x0000 *//*@ ZONE: register read/write, the functions in the following is@ only used when slic generates kinds of tones*/uint8 _slic_read_DirectReg(uint32 reg, int channel){	uint8 buf;	buf = reg | 0x80;	_rtl865x_spi_rawWrite( &dev[channel], &buf, 8);	_rtl865x_spi_rawRead(  &dev[channel], &buf, 8);	return buf;}void _slic_write_DirectReg(uint32 reg, uint8 data, int channel){	uint8 buf;	buf = reg;	_rtl865x_spi_rawWrite( &dev[channel], &buf, 8 );	buf = data;	_rtl865x_spi_rawWrite( &dev[channel], &buf, 8 );}uint16 _slic_read_IndirectReg(uint32 reg, int channel){	uint8 data8 = 0;	uint16 data = 0;	while(readDirectReg(31, channel));	writeDirectReg(30, reg, channel);	while(readDirectReg(31, channel));	data8 = readDirectReg(28, channel);	data  = data8;	data8 = 0;	data8 = readDirectReg(29, channel);	data  = data | data8 << 8;	return data;}void _slic_write_IndirectReg(uint32 reg, uint16 data, int channel){	while(readDirectReg(31, channel));	writeDirectReg(28,(uint8)(data & 0xFF), channel);	writeDirectReg(29,(uint8)((data & 0xFF00)>>8), channel);	writeDirectReg(30, reg, channel);}/*@ ZONE: Initialization, the functions in the following is@ only used in the start-up of slic communications*//* INIT: FIRST, GPIO pins */void slic_init_GPIO(uint32 channel){	uint32 i;	uint32 resetDelay = 50000000;	/* SLIC 0 initialization */	if(channel ==0)	{		/* Relay is used as when we use the phone and no electricity */		rtlglue_printf("pin RELAY initialize ...");		_rtl865x_initGpioPin(PIN_RELAY,	 GPIO_PERI_GPIO, GPIO_DIR_OUT, GPIO_INT_DISABLE); /* Relay */		_rtl865x_initGpioPin(PIN_CS1,    GPIO_PERI_GPIO, GPIO_DIR_OUT, GPIO_INT_DISABLE );/* CS_ */		_rtl865x_initGpioPin(PIN_RESET1, GPIO_PERI_GPIO, GPIO_DIR_OUT, GPIO_INT_DISABLE );/* RESET_ */		for( i = resetDelay; i > 0; i-- );       /*50MHz ~= 250ms*/		_rtl865x_setGpioDataBit( PIN_CS1,    0 );/* CS_ preset to high state*/		_rtl865x_setGpioDataBit( PIN_RESET1, 1 );/* RESET_ */		for( i = resetDelay; i > 0; i-- );		_rtl865x_setGpioDataBit( PIN_RESET1, 0 );/* RESET_ Hold RESET_ low PCLK and FS is present and stable*/		for( i = resetDelay; i > 0; i-- );		_rtl865x_setGpioDataBit( PIN_RESET1, 1 );/* RESET_ */		for( i = resetDelay; i > 0; i-- );/*Hold 2 ms or longer*/		_rtl865x_spi_init( &dev[0],			PIN_CLK,	/*SLIC0: SPI CLK*/			PIN_CS1,	/*SLIC0: CS*/			PIN_DO,	/*SLIC0: Data out from 865x*/			PIN_DI,	/*SLIC0: Data int to   865x*/			1000000 );				_rtl865x_setGpioDataBit(PIN_CS1,   1);/* CS_ preset to high state(no selection)*/		_rtl865x_setGpioDataBit(PIN_RELAY, 1);		rtlglue_printf("PIN_RELAY(GPIO_E0) set to 1\n");	}		/* SLIC 1 initialization */	if(channel==1)	{		_rtl865x_initGpioPin(PIN_RESET1, GPIO_PERI_GPIO, GPIO_DIR_OUT, GPIO_INT_DISABLE );/* RESET_ */		_rtl865x_initGpioPin(PIN_CS2,    GPIO_PERI_GPIO, GPIO_DIR_OUT, GPIO_INT_DISABLE );/* CS_ */		_rtl865x_initGpioPin(PIN_RESET2, GPIO_PERI_GPIO, GPIO_DIR_OUT, GPIO_INT_DISABLE );/* RESET_ */		for( i = resetDelay; i > 0; i-- );       /* 50MHz ~= 250ms*/		_rtl865x_setGpioDataBit( PIN_CS2,    0 );/* CS_ preset to high state*/		_rtl865x_setGpioDataBit( PIN_RESET2, 1 );/* RESET_ */		for( i = resetDelay; i > 0; i-- );		_rtl865x_setGpioDataBit( PIN_RESET2, 0 );/* RESET_ Hold RESET_ low PCLK and FS is present and stable*/		for( i = resetDelay; i > 0; i-- );		_rtl865x_setGpioDataBit( PIN_RESET2, 1 );/* RESET_ */		for( i = resetDelay; i > 0; i-- );		_rtl865x_spi_init( &dev[1],			PIN_CLK2,	/*SLIC1: SPI CLK*/			PIN_CS2,		/*SLIC1: CS*/			PIN_DO2,		/*SLIC1: Data out from 865x*/			PIN_DI2,		/*SLIC1: Data in  to   865x*/			1000000 );		_rtl865x_setGpioDataBit( PIN_CS2, 1 );/* CS_ preset to high state(no selection)*/	}}int32 slic_init_Test(int channel){	int32 ret = SUCCESS;	if( readDirectReg(8,  channel) != 0x02 ||		readDirectReg(11, channel) != 0x33 ||		readDirectReg(64, channel) != 0x00 )	{		ret = FAILED;	}	return ret;}/*SECOND*/int32 slic_init(uint32 channel){	uint16 temp[5];	int32 ret = SUCCESS;	if(channel < 0 || channel > 1 )	{		rtlglue_printf("Given unavailable slic channel\n");		return FAILED;	}	/*Test*/	ret = slic_init_Test(channel);	slic_read_PCMCLK(channel);	if( ret == FAILED )	{		rtlglue_printf("SLIC not communicating\n");		rtlglue_printf("Possible reason:\n");		rtlglue_printf("	1	PCM:PCLK not providing clocks\n");		rtlglue_printf("	2	Slic already init\n");		return ret;	}	/* identify type & version */	chipData[channel].version = 0xf & readDirectReg(0, channel);	chipData[channel].type   = (0x30 & readDirectReg(0, channel)) >> 4;	rtlglue_printf("SLIC %d, type : %d\t",channel,chipData[channel].type);	rtlglue_printf("version : %c\n",'A'-1 + chipData[channel].version);	/* initial indirect registers */	slic_init_IndirectReg(channel);	/* settings */	writeDirectReg(8, 0, channel);/* audio path no loop back */	writeDirectReg(108, 0xEB, channel);/* enhancement enable register */	if (chipData[channel].type ==0) /* Si3210 only */	{		writeDirectReg(67,0x17, channel);/* Automatic control setting, why bit[3] is set to 0? which means no automatic switching to low battery in off-hook state */		writeDirectReg(66,0x1, channel);/* VBAT tracks VRING */	}	if (chipData[channel].version <=2 )/*REVISION B and before*/		writeDirectReg(73,4, channel);/* set common mode voltage to 6 volts */		/*  Flush ProSLIC digital filters by setting Coefficients to clear */	/*  Save OSC control, Atimer, Itimer of OSC1 OSC2 */	temp[0] = readIndirectReg(35, channel);	writeIndirectReg(35, 0x8000, channel);	temp[1] = readIndirectReg(36, channel);	writeIndirectReg(36, 0x8000, channel);	temp[2] = readIndirectReg(37, channel);	writeIndirectReg(37, 0x8000, channel);	temp[3] = readIndirectReg(38, channel);	writeIndirectReg(38, 0x8000, channel);	temp[4] = readIndirectReg(39, channel);	writeIndirectReg(39, 0x8000, channel);	/* Do Flush durring powerUp and calibrate */	if (chipData[channel].type == 0 || chipData[channel].type==3) /*  Si3210 */	{		ret = slic_init_powerUp(channel);  /* Turn on the DC-DC converter and verify voltage. */		if(ret!=SUCCESS)		{			rtlglue_printf("PowerUp Failed\t");			return ret;		}		ret = slic_init_powerLeakTest(channel); /* Check for power leaks */		if(ret!=SUCCESS)		{			rtlglue_printf("Power leak\t");			return ret;		}		ret = slic_init_powerUp(channel); /* Turn on the DC-DC converter again */		if(ret!=SUCCESS)		{			rtlglue_printf("PowerUp Failed\n");			return ret;		}	}	slic_init_DirectReg(channel);	slic_init_calibrate(channel);	writeIndirectReg(35, temp[0], channel);	writeIndirectReg(36, temp[1], channel);	writeIndirectReg(37, temp[2], channel);	writeIndirectReg(38, temp[3], channel);	writeIndirectReg(39, temp[4], channel);	clearInterrupts(channel);/*maybe redundant ? */	goActive(channel);	slic_read_PCMCLK(channel);	rtlglue_printf("ProSLIC device %d initialized\n", channel);	return SUCCESS;}void clearInterrupts(int channel){	writeDirectReg(	18	,	INIT_DR18	, channel);	writeDirectReg(	19	,	INIT_DR19	, channel);	writeDirectReg(	20	,	INIT_DR20	, channel);}/* indirect initials are defined according to silicon lab datasheet */void slic_init_IndirectReg(int channel){	unsigned char i=0;	while (indirectRegisters[i].initial || 		   indirectRegisters[i].address ) 	{		writeIndirectReg(			indirectRegisters[i].address,			indirectRegisters[i].initial,			channel			);		i++;	}}void slic_init_DirectReg(int channel){	writeDirectReg(0,	INIT_DR0	, channel);/*0X00	Serial Interface */	writeDirectReg(1,	INIT_DR1	, channel);/*0X28	PCM Mode */	writeDirectReg(2,	INIT_DR2	, channel);/*0X00	PCM TX Clock Slot Low Byte (1 PCLK cycle/LSB) */	writeDirectReg(3,	INIT_DR3	, channel);/*0x00	PCM TX Clock Slot High Byte */	writeDirectReg(4,	INIT_DR4	, channel);/*0x00	PCM RX Clock Slot Low Byte (1 PCLK cycle/LSB) */	writeDirectReg(5,	INIT_DR5	, channel);/*0x00	PCM RX Clock Slot High Byte */	writeDirectReg(8,	INIT_DR8	, channel);/*0X00	Loopbacks (digital loopback default) */	writeDirectReg(9,	INIT_DR9	, channel);/*0x00	Transmit and receive path gain and control */	writeDirectReg(10,	INIT_DR10	, channel);/*0X28	Initialization Two-wire impedance (600  and enabled) */	writeDirectReg(11,	INIT_DR11	, channel);/*0x33	Transhybrid Balance/Four-wire Return Loss */	writeDirectReg(18,	INIT_DR18	, channel);/*0xff	Normal Oper. Interrupt Register 1 (clear with 0xFF) */	writeDirectReg(19,	INIT_DR19	, channel);/*0xff	Normal Oper. Interrupt Register 2 (clear with 0xFF) */	writeDirectReg(20,	INIT_DR20	, channel);/*0xff	Normal Oper. Interrupt Register 3 (clear with 0xFF) */	writeDirectReg(21,	INIT_DR21	, channel);/*0xff	Interrupt Mask 1 */	writeDirectReg(22,	INIT_DR22	, channel);/*0xff	Initialization Interrupt Mask 2 */	writeDirectReg(23,	INIT_DR23	, channel);/*0xff	 Initialization Interrupt Mask 3 */	writeDirectReg(32,	INIT_DR32	, channel);/*0x00	Oper. Oscillator 1 Controltone generation */	writeDirectReg(33,	INIT_DR33	, channel);/*0x00	Oper. Oscillator 2 Controltone generation */	writeDirectReg(34,	INIT_DR34	, channel);/*0X18	34 0x22 0x00 Initialization Ringing Oscillator Control */	writeDirectReg(35,	INIT_DR35	, channel);/*0x00	Oper. Pulse Metering Oscillator Control */	writeDirectReg(36,	INIT_DR36	, channel);/*0x00	36 0x24 0x00 Initialization OSC1 Active Low Byte (125 祍/LSB) */	writeDirectReg(37,	INIT_DR37	, channel);/*0x00	37 0x25 0x00 Initialization OSC1 Active High Byte (125 祍/LSB) */	writeDirectReg(38,	INIT_DR38	, channel);/*0x00	38 0x26 0x00 Initialization OSC1 Inactive Low Byte (125 祍/LSB) */	writeDirectReg(39,	INIT_DR39	, channel);/*0x00	39 0x27 0x00 Initialization OSC1 Inactive High Byte (125 祍/LSB) */	writeDirectReg(40,	INIT_DR40	, channel);/*0x00	40 0x28 0x00 Initialization OSC2 Active Low Byte (125 祍/LSB) */	writeDirectReg(41,	INIT_DR41	, channel);/*0x00	41 0x29 0x00 Initialization OSC2 Active High Byte (125 祍/LSB) */	writeDirectReg(42,	INIT_DR42	, channel);/*0x00	42 0x2A 0x00 Initialization OSC2 Inactive Low Byte (125 祍/LSB) */	writeDirectReg(43,	INIT_DR43	, channel);/*0x00	43 0x2B 0x00 Initialization OSC2 Inactive High Byte (125 祍/LSB) */	writeDirectReg(44,	INIT_DR44	, channel);/*0x00	44 0x2C 0x00 Initialization Pulse Metering Active Low Byte (125 祍/LSB) */	writeDirectReg(45,	INIT_DR45	, channel);/*0x00	45 0x2D 0x00 Initialization Pulse Metering Active High Byte (125 祍/LSB) */	writeDirectReg(46,	INIT_DR46	, channel);/*0x00	46 0x2E 0x00 Initialization Pulse Metering Inactive Low Byte (125 祍/LSB) */	writeDirectReg(47,	INIT_DR47	, channel);/*0x00	47 0x2F 0x00 Initialization Pulse Metering Inactive High Byte (125 祍/LSB) */	writeDirectReg(48,	INIT_DR48	, channel);/*0X80	48 0x30 0x00 0x80 Initialization Ringing Osc. Active Timer Low Byte (2 s,125 祍/LSB) */	writeDirectReg(49,	INIT_DR49	, channel);/*0X3E	49 0x31 0x00 0x3E Initialization Ringing Osc. Active Timer High Byte (2 s,125 祍/LSB) */	writeDirectReg(50,	INIT_DR50	, channel);/*0X00	50 0x32 0x00 0x00 Initialization Ringing Osc. Inactive Timer Low Byte (4 s, 125 祍/LSB) */	writeDirectReg(51,	INIT_DR51	, channel);/*0X7D	51 0x33 0x00 0x7D Initialization Ringing Osc. Inactive Timer High Byte (4 s, 125 祍/LSB) */	writeDirectReg(52,	INIT_DR52	, channel);/*0X00	52 0x34 0x00 Normal Oper. FSK Data Bit */	writeDirectReg(63,	INIT_DR63	, channel);/*0X54	63 0x3F 0x54 Initialization Ringing Mode Loop Closure Debounce Interval */	writeDirectReg(64,	INIT_DR64	, channel);/*0x00	64 0x40 0x00 Normal Oper. Mode Byte梡rimary control */	writeDirectReg(65,	INIT_DR65	, channel);/*0X61	65 0x41 0x61 Initialization External Bipolar Transistor Settings */	writeDirectReg(66,	INIT_DR66	, channel);/*0X03	66 0x42 0x03 Initialization Battery Control */	writeDirectReg(67,	INIT_DR67	, channel);/*0X1F	67 0x43 0x1F Initialization Automatic/Manual Control */	writeDirectReg(69,	INIT_DR69	, channel);/*0X0C	69 0x45 0x0A 0x0C Initialization Loop Closure Debounce Interval (1.25 ms/LSB) */	writeDirectReg(70,	INIT_DR70	, channel);/*0X0A	70 0x46 0x0A Initialization Ring Trip Debounce Interval (1.25 ms/LSB) */	writeDirectReg(71,	INIT_DR71	, channel);/*0X01	71 0x47 0x00 0x01 Initialization Off-Hook Loop Current Limit (20 mA + 3 mA/LSB) */	writeDirectReg(72,	INIT_DR72	, channel);/*0X20	72 0x48 0x20 Initialization On-Hook Voltage (open circuit voltage) = 48 V(1.5 V/LSB) */	writeDirectReg(73,	INIT_DR73	, channel);/*0X02	73 0x49 0x02 Initialization Common Mode VoltageVCM = 3 V(1.5 V/LSB) */

⌨️ 快捷键说明

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