summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormogorman <mogorman@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-01-05 23:32:56 +0000
committermogorman <mogorman@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-01-05 23:32:56 +0000
commit0ea497d0eb3c943e5af3899966c2f90daf5aade4 (patch)
treea1b1960df51e7c5fed1bcf6888efe7c7bfe95b0f
parentc8c19c565ea5c5c6e9f20c710d98541b2c9c8ed6 (diff)
this allows transcoder card to work with newest revision of the card
if you have the older revision do not upgrade or this will break you. patch provided by john sloan git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1787 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--ztcodec_dte.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/ztcodec_dte.c b/ztcodec_dte.c
index 31b400e..4aeec7f 100644
--- a/ztcodec_dte.c
+++ b/ztcodec_dte.c
@@ -98,7 +98,12 @@
#define PCI_WINDOW_SIZE ((2* 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
-
+#define MDIO_SHIFT_CLK 0x10000
+#define MDIO_DATA_WRITE0 0x00000
+#define MDIO_DATA_WRITE1 0x20000
+#define MDIO_ENB 0x00000
+#define MDIO_ENB_IN 0x40000
+#define MDIO_DATA_READ 0x80000
#define RCV_CSMENCAPS 1
#define RCV_RTP 2
@@ -1188,12 +1193,86 @@ static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int use_
}
+static int wcdte_read_phy(struct wcdte *wc, int location)
+{
+ int i;
+ long mdio_addr = 0x0048;
+ int read_cmd = (0xf6 << 10) | (1 << 5) | location;
+ int retval = 0;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1);
+ wcdte_getctl(wc, mdio_addr);
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK);
+ wcdte_getctl(wc, mdio_addr);
+ }
+ /* Shift the read command bits out. */
+ for (i = 17; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval);
+ wcdte_getctl(wc, mdio_addr);
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK);
+ wcdte_getctl(wc, mdio_addr);
+ }
+
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN);
+ wcdte_getctl(wc, mdio_addr);
+ retval = (retval << 1) | ((wcdte_getctl(wc, mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK);
+ wcdte_getctl(wc, mdio_addr);
+ }
+ retval = (retval>>1) & 0xffff;
+ return retval;
+}
+
+
+void wcdte_write_phy(struct wcdte *wc, int location, int value)
+{
+ int i;
+ int cmd = (0x5002 << 16) | (1 << 23) | (location<<18) | value;
+ long mdio_addr = 0x0048;
+
+ /* Establish sync by sending 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1);
+ wcdte_getctl(wc, mdio_addr);
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK);
+ wcdte_getctl(wc, mdio_addr);
+ }
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval);
+ wcdte_getctl(wc, mdio_addr);
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK);
+ wcdte_getctl(wc, mdio_addr);
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN);
+ wcdte_getctl(wc, mdio_addr);
+ wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK);
+ wcdte_getctl(wc, mdio_addr);
+ }
+ return;
+}
+
+
static int wcdte_boot_processor(struct wcdte *wc)
{
int i, j, byteloc, last_byteloc, length, delay_count;
unsigned int reg, ret;
#ifndef USE_TEST_HW
+ /* Turn off auto negotiation */
+ wcdte_write_phy(wc, 0, 0x2100);
+ if (debug)
+ printk("wcdte: PHY register 0 = %X", wcdte_read_phy(wc, 0));
+
/* Set reset */
wcdte_setctl(wc, 0x00A0, 0x04000000);