summaryrefslogtreecommitdiff
path: root/pciradio.c
diff options
context:
space:
mode:
authorjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-11-21 04:29:53 +0000
committerjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-11-21 04:29:53 +0000
commit5528607cba498ef8c2806f99c10ce954ebaec700 (patch)
treecbbc93a456d98e3bd5c0f9f7b338380ff52f25c9 /pciradio.c
parent803d3dee15620df0f8d62f25a36906438eda39c3 (diff)
Added support files for new version of pciradio card and updates to driver.
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@500 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'pciradio.c')
-rwxr-xr-xpciradio.c385
1 files changed, 225 insertions, 160 deletions
diff --git a/pciradio.c b/pciradio.c
index 9ed9f85..e2e0fee 100755
--- a/pciradio.c
+++ b/pciradio.c
@@ -67,17 +67,15 @@ With PL check: 267722 (13.2 % -- will be much improved with new Xilinx)
#define RAD_OPER 0x01
#define RAD_AUXC 0x02
#define RAD_AUXD 0x03
- #define MX828_DOUT 0x02 /* Data from MX828 */
- #define MX828_DIN 0x04 /* Data to MX828 */
- #define MX828_CS0 0x08 /* MX828 CS Channel 0 */
- #define MX828_CS1 0x10 /* MX828 CS Channel 1 */
- #define MX828_CS2 0x20 /* MX828 CS Channel 2 */
- #define MX828_CS3 0x40 /* MX828 CS Channel 3 */
- #define MX828_SCLK 0x80 /* MX828 Serial Clock */
+ #define XPGM 4
+ #define XCS 2
+
#define RAD_MASK0 0x04
#define RAD_MASK1 0x05
#define RAD_INTSTAT 0x06
#define RAD_AUXR 0x07
+ #define XINIT 8
+ #define XDONE 0x10
#define RAD_DMAWS 0x08
#define RAD_DMAWI 0x0c
@@ -105,6 +103,16 @@ With PL check: 267722 (13.2 % -- will be much improved with new Xilinx)
#define RAD_GOTRX_DEBOUNCE_TIME 75
+/* bits for port 0 in */
+#define MX828_DOUT 0x10 /* Data from MX828 */
+/* bits for port 0 out */
+#define MX828_DIN 0x2 /* Data to MX828 */
+#define MX828_CS0 0x10 /* MX828 CS Channel 0 */
+#define MX828_CS1 0x20 /* MX828 CS Channel 1 */
+#define MX828_CS2 0x40 /* MX828 CS Channel 2 */
+#define MX828_CS3 0x80 /* MX828 CS Channel 3 */
+#define MX828_SCLK 0x1 /* MX828 Serial Clock */
+
/*
* MX828 Commands
*/
@@ -185,6 +193,7 @@ struct tonedef {
unsigned char b2;
} ;
+#include "radfw.h"
static struct tonedef cttable_tx [] = {
{0,0,0},
@@ -448,169 +457,156 @@ static void wait_just_a_bit(int foo)
}
/*
-* Output a byte to the MX828 ctcss encoder/decoder chip
+* Output a byte to the MX828 PL encoder/decoder chip
*/
-
-void mx828_set_serdata(struct pciradio *rad, char bit)
+
+void mx828_set_serdata(struct pciradio *rad,int bit)
{
- unsigned char regsave;
-
- regsave = inb(rad->ioaddr + RAD_AUXR);
- regsave &= ~MX828_DIN;
- if(bit)
- regsave |= MX828_DIN;
- outb(regsave, rad->ioaddr + RAD_AUXD);
+ rad->p0save &= ~MX828_DIN;
+ if(bit)
+ rad->p0save |= MX828_DIN;
+ __pciradio_setcreg(rad,0,rad->p0save);
}
-
+
void mx828_wiggle_sclk(struct pciradio *rad)
{
- unsigned char regsave;
-
- regsave = inb(rad->ioaddr + RAD_AUXR);
- regsave &= ~MX828_SCLK; /* SCLK 1 -> 0 */
- outb(regsave, rad->ioaddr + RAD_AUXD);
+ rad->p0save &= ~MX828_SCLK; /* SCLK 1 -> 0 */
+ __pciradio_setcreg(rad,0,rad->p0save);
udelay(1);
-
- regsave = inb(rad->ioaddr + RAD_AUXR);
- regsave |= MX828_SCLK; /* SCLK 0 -> 1 */
- outb(regsave, rad->ioaddr + RAD_AUXD);
+ rad->p0save |= MX828_SCLK; /* SCLK 0 -> 1 */
+ __pciradio_setcreg(rad,0,rad->p0save);
udelay(1);
}
-
-
+
+
/*
* Output a command to the MX828 over the serial bus
*/
-
-
+
+
void mx828_command(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2)
{
-
- int i, param = 1, wr = 1, word = 0;
- unsigned char byte, regsave;
-
- if(channel > 3)
- return;
-
- /* Pull the transfer info from the command code */
-
- switch(command){
- case MX828_GEN_RESET: /* Commands with no param */
- param = 0;
- break;
-
- case MX828_SAUDIO_CTRL: /* 8 bit write commands */
- case MX828_SAUDIO_SETUP:
- case MX828_DCS1:
- case MX828_DCS2:
- case MX828_DCS3:
- case MX828_IRQ_MASK:
- case MX828_GEN_CTRL:
- case MX828_GPT:
- break;
-
- case MX828_SAUDIO_STATUS: /* 8 bit read commands */
- case MX828_IRQ_FLAG:
- case 0:
- wr = 0;
- break;
-
- case MX828_TX_TONE: /* 16 bit write commands */
- case MX828_RX_TONE:
- case MX828_AUD_CTRL:
- case MX828_SELCALL:
- word = 1;
- break;
-
- default:
- return;
- }
-
-
- mx828_set_serdata(rad,1); /* Start with data = 1 */
-
+
+ int i, param = 1, wr = 1, word = 0;
+ unsigned char byte;
+
+ if(channel > 3)
+ return;
+
+ /* Pull the transfer info from the command code */
+
+ switch(command){
+ case MX828_GEN_RESET: /* Commands with no param */
+ param = 0;
+ break;
+
+ case MX828_SAUDIO_CTRL: /* 8 bit write commands */
+ case MX828_SAUDIO_SETUP:
+ case MX828_DCS1:
+ case MX828_DCS2:
+ case MX828_DCS3:
+ case MX828_IRQ_MASK:
+ case MX828_GEN_CTRL:
+ case MX828_GPT:
+ break;
+
+ case MX828_SAUDIO_STATUS: /* 8 bit read commands */
+ case MX828_IRQ_FLAG:
+ case 0:
+ wr = 0;
+ break;
+
+ case MX828_TX_TONE: /* 16 bit write commands */
+ case MX828_RX_TONE:
+ case MX828_AUD_CTRL:
+ case MX828_SELCALL:
+ word = 1;
+ break;
+
+ default:
+ return;
+ }
+
+
+ mx828_set_serdata(rad,1); /* Start with data = 1 */
+
udelay(2);
-
- /* Set the proper CS */
-
- byte = (unsigned char ) 1 << (channel + 3);
-
- regsave = inb(rad->ioaddr + RAD_AUXR);
- regsave |= (MX828_CS0 | MX828_CS1 | MX828_CS2 | MX828_CS3);
- regsave &= ~byte;
- outb(regsave, rad->ioaddr + RAD_AUXD);
-
-
+
+ /* Set the proper CS */
+
+ byte = (unsigned char ) 1 << (channel + 4);
+
+ rad->p0save |= (MX828_CS0 | MX828_CS1 | MX828_CS2 | MX828_CS3);
+ rad->p0save &= ~byte;
+ __pciradio_setcreg(rad,0,rad->p0save);
+
+
udelay(2);
-
- /* Output the command byte */
-
- byte = command;
-
- for( i = 0 ; i < 8 ; i++){
- udelay(2);
- mx828_set_serdata(rad,0x80 & byte); /* MSB first */
- byte <<= 1;
- mx828_wiggle_sclk(rad);
- }
- if(param){
- udelay(4);
- if(wr){
- byte = *byte1;
- for( i = 0 ; i < 8 ; i++){
- udelay(2);
- mx828_set_serdata(rad,0x80 & byte);
- byte <<= 1;
- mx828_wiggle_sclk(rad);
- }
- if(word){
- udelay(4);
- byte = *byte2;
- for( i = 0 ; i < 8 ; i++){
- udelay(2);
- mx828_set_serdata(rad,0x80 & byte);
- byte <<= 1;
- mx828_wiggle_sclk(rad);
- }
- }
- }
- else { /* rd */
- byte = 0;
- for( i = 0 ; i < 8 ; i++){
- mx828_wiggle_sclk(rad);
- byte <<= 1;
- udelay(2);
- if(inb(rad->ioaddr + RAD_AUXR) & MX828_DOUT)
- byte |= 0x01;
- }
- *byte1 = byte;
- if(word){
- byte = 0;
- udelay(4);
- for( i = 0 ; i < 8 ; i++){
- mx828_wiggle_sclk(rad);
- byte <<= 1;
- udelay(2);
- if(inb(rad->ioaddr + RAD_AUXR) & MX828_DOUT)
- byte |= 0x01;
- }
- *byte2 = byte;
+
+ /* Output the command byte */
+
+ byte = command;
+
+ for( i = 0 ; i < 8 ; i++){
+ udelay(2);
+ mx828_set_serdata(rad,0x80 & byte); /* MSB first */
+ byte <<= 1;
+ mx828_wiggle_sclk(rad);
+ }
+ if(param){
+ udelay(4);
+ if(wr){
+ byte = *byte1;
+ for( i = 0 ; i < 8 ; i++){
+ udelay(2);
+ mx828_set_serdata(rad,0x80 & byte);
+ byte <<= 1;
+ mx828_wiggle_sclk(rad);
+ }
+ if(word){
+ udelay(4);
+ byte = *byte2;
+ for( i = 0 ; i < 8 ; i++){
+ udelay(2);
+ mx828_set_serdata(rad,0x80 & byte);
+ byte <<= 1;
+ mx828_wiggle_sclk(rad);
+ }
+ }
+ }
+ else { /* rd */
+ byte = 0;
+ for( i = 0 ; i < 8 ; i++){
+ mx828_wiggle_sclk(rad);
+ byte <<= 1;
+ udelay(2);
+ if(__pciradio_getcreg(rad,0) & MX828_DOUT)
+ byte |= 0x01;
+ }
+ *byte1 = byte;
+ if(word){
+ byte = 0;
+ udelay(4);
+ for( i = 0 ; i < 8 ; i++){
+ mx828_wiggle_sclk(rad);
+ byte <<= 1;
+ udelay(2);
+ if(__pciradio_getcreg(rad,0) & MX828_DOUT)
+ byte |= 0x01;
+ }
+ *byte2 = byte;
}
-
-
- }
- }
-
+
+ }
+ }
+
udelay(4);
-
- /* Release chip selects */
-
- regsave = inb(rad->ioaddr + RAD_AUXR);
- regsave |= (MX828_CS0 | MX828_CS1 | MX828_CS2 | MX828_CS3);
- outb(regsave, rad->ioaddr + RAD_AUXD);
-
-
-}
+
+ /* Release chip selects */
+ rad->p0save |= (MX828_CS0 | MX828_CS1 | MX828_CS2 | MX828_CS3);
+ __pciradio_setcreg(rad,0,rad->p0save);
+}
+
static void _set_encdec(struct pciradio *rad, int n)
{
@@ -635,7 +631,7 @@ unsigned short txcode;
txcode = rad->txcode[n][myindex];
if (txcode & 0x8000) dcstx = 1; else if (txcode) cttx = 1;
if (rad->radmode[n] & RADMODE_NOENCODE) dcstx = cttx = 0;
- if ((!rad->gottx[n]) || rad->bursttimer[n]) dcstx = cttx = 0;
+ if ((!rad->gottx[n]) || rad->bursttimer[n]) dcstx = cttx = 0;
saudio_ctrl = 0;
saudio_setup = 0;
if (dcstx && (!dcsrx)) /* if to transmit DCS */
@@ -1285,19 +1281,19 @@ static int pciradio_hardware_init(struct pciradio *rad)
{
unsigned char byte1,byte2;
int x;
+unsigned long endjif;
/* Signal Reset */
outb(0x01, rad->ioaddr + RAD_CNTL);
/* Reset PCI Interface chip and registers (and serial) */
outb(0x06, rad->ioaddr + RAD_CNTL);
- /* Setup our proper outputs for when we switch for our "serial" port */
- rad->ios = BIT_CS | BIT_SCLK | BIT_SDI;
-
+ /* Setup our proper outputs */
+ rad->ios = 0xfe;
outb(rad->ios, rad->ioaddr + RAD_AUXD);
- /* Set all to outputs except AUX 2, which is an input */
- outb(0xfd, rad->ioaddr + RAD_AUXC);
+ /* Set all to outputs except AUX 3 & 4, which are inputs */
+ outb(0x67, rad->ioaddr + RAD_AUXC);
/* Select alternate function for AUX0 */
outb(0x4, rad->ioaddr + RAD_AUXFUNC);
@@ -1305,6 +1301,75 @@ int x;
/* Wait 1/4 of a sec */
wait_just_a_bit(HZ/4);
+ /* attempt to load the Xilinx Chip */
+ /* De-assert CS+Write */
+ rad->ios |= XCS;
+ outb(rad->ios, rad->ioaddr + RAD_AUXD);
+ /* Assert PGM */
+ rad->ios &= ~XPGM;
+ outb(rad->ios, rad->ioaddr + RAD_AUXD);
+ /* wait for INIT and DONE to go low */
+ endjif = jiffies + 10;
+ while (inb(rad->ioaddr + RAD_AUXR) & (XINIT | XDONE) && (jiffies <= endjif));
+ if (endjif < jiffies) {
+ printk("Timeout waiting for INIT and DONE to go low\n");
+ return -1;
+ }
+ if (debug) printk("fwload: Init and done gone to low\n");
+ /* De-assert PGM */
+ rad->ios |= XPGM;
+ outb(rad->ios, rad->ioaddr + RAD_AUXD);
+ /* wait for INIT to go high (clearing done */
+ endjif = jiffies + 10;
+ while (!(inb(rad->ioaddr + RAD_AUXR) & XINIT) && (jiffies <= endjif));
+ if (endjif < jiffies) {
+ printk("Timeout waiting for INIT to go high\n");
+ return -1;
+ }
+ if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n");
+ /* Assert CS+Write */
+ rad->ios &= ~XCS;
+ outb(rad->ios, rad->ioaddr + RAD_AUXD);
+ for (x = 0; x < sizeof(radfw); x++)
+ {
+ /* write the byte */
+ outb(radfw[x],rad->ioaddr + RAD_REGBASE);
+ /* if DONE signal, we're done, exit */
+ if (inb(rad->ioaddr + RAD_AUXR) & XDONE) break;
+ /* if INIT drops, we're screwed, exit */
+ if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) break;
+ }
+ if (debug) printk("fwload: Transferred %d bytes into chip\n",x);
+ /* Wait for FIFO to clear */
+ endjif = jiffies + 2;
+ while (jiffies < endjif); /* wait */
+ printk("Transfered %d bytes into chip\n",x);
+ /* De-assert CS+Write */
+ rad->ios |= XCS;
+ outb(rad->ios, rad->ioaddr + RAD_AUXD);
+ if (debug) printk("fwload: Loading done!\n");
+ /* Wait for FIFO to clear */
+ endjif = jiffies + 2;
+ while (jiffies < endjif); /* wait */
+ if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT))
+ {
+ printk("Drove Init low!! CRC Error!!!\n");
+ return -1;
+ }
+ if (!(inb(rad->ioaddr + RAD_AUXR) & XDONE))
+ {
+ printk("Did not get DONE signal. Short file maybe??\n");
+ return -1;
+ }
+ printk("Xilinx Chip successfully loaded, configured and started!!\n");
+
+
+ rad->p0save = 0xf0;
+ __pciradio_setcreg(rad,0,rad->p0save);
+
+ rad->p1save = 0;
+ __pciradio_setcreg(rad,1,rad->p1save);
+
/* Back to normal, with automatic DMA wrap around */
outb(0x30 | 0x01, rad->ioaddr + RAD_CNTL);
@@ -1346,7 +1411,7 @@ int x;
mx828_command(rad,x, MX828_GEN_CTRL, &byte1, &byte2);
}
- udelay(1000);
+
return 0;
}