diff options
author | jim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2004-11-21 04:29:53 +0000 |
---|---|---|
committer | jim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2004-11-21 04:29:53 +0000 |
commit | 5528607cba498ef8c2806f99c10ce954ebaec700 (patch) | |
tree | cbbc93a456d98e3bd5c0f9f7b338380ff52f25c9 /pciradio.c | |
parent | 803d3dee15620df0f8d62f25a36906438eda39c3 (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-x | pciradio.c | 385 |
1 files changed, 225 insertions, 160 deletions
@@ -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; } |