📄 slic.c
字号:
#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 + -