summaryrefslogtreecommitdiff
path: root/kernel/xpp/init_card_3_30
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/xpp/init_card_3_30')
-rwxr-xr-xkernel/xpp/init_card_3_30439
1 files changed, 439 insertions, 0 deletions
diff --git a/kernel/xpp/init_card_3_30 b/kernel/xpp/init_card_3_30
new file mode 100755
index 0000000..ce8ad01
--- /dev/null
+++ b/kernel/xpp/init_card_3_30
@@ -0,0 +1,439 @@
+#! /usr/bin/perl -w
+use strict;
+
+#
+# $Id$
+#
+
+#
+# Written by Oron Peled <oron@actcom.co.il>
+# Copyright (C) 2006, Xorcom
+#
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# See the file LICENSE in the top level of this tarball.
+#
+
+# This script is run from the xpp kernel module upon detection
+# of a new XPD.
+#
+# Expects the following environment variables to be set:
+# XBUS_NAME - bus name
+# UNIT_NUMBER - xpd unit number
+# UNIT_SUBUNITS - number of subunits in this xpd
+# UNIT_TYPE - xpd type number (from protocol reply):
+# 1 - FXS
+# 2 - FXO
+# 3 - BRI
+# 4 - PRI
+# XBUS_REVISION - xbus revision number
+# XBUS_CONNECTOR - xbus connector string
+#
+# Output data format:
+# - An optional comment start with ';' or '#' until the end of line
+# - Optional Blank lines are ignored
+# - Fields are whitespace separated (spaces or tabs)
+#
+# The fields are (in command line order):
+# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number)
+# 2. Command word:
+# - RD Read Direct register.
+# - RI Read Indirect register.
+# - WD Write Direct register.
+# - RI Write Indirect register.
+# 3. Register number in hexadecimal.
+# 4. Subregister number in hexadecimal. (for RI and WI commands).
+# 5. Data byte in hexadecimal. (for WD and WI commands only).
+#
+
+package main;
+use File::Basename;
+use Getopt::Std;
+
+my $program = basename("$0");
+my $init_dir = dirname("$0");
+my $unit_id;
+my %opts;
+$ENV{XPP_BASE} = '/proc/xpp';
+
+getopts('o:', \%opts);
+
+sub logit {
+ print STDERR "$unit_id: @_\n";
+}
+
+# Arrange for error logging
+if (-t STDERR) {
+ $unit_id = 'Interactive';
+ logit "Interactive startup";
+} else {
+ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
+ open (STDERR, "| logger -t $program -p kern.info") || die;
+ logit "Non Interactive startup";
+}
+
+sub select_subunit($) {
+ my $subunit = shift;
+ die unless defined $subunit;
+ my $output;
+
+ if($opts{o}) {
+ $output = $opts{o};
+ } else {
+ my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit);
+ $output = "$ENV{XPP_BASE}/$ENV{XBUS_NAME}/$xpd_name/chipregs";
+ }
+ open(REG, ">$output") || die "Failed to open '$output': $!\n";
+ my $oldfh = select REG;
+ print "# Selecting subunit $subunit\n" if $opts{o};
+ return $oldfh;
+}
+
+package BRI;
+
+sub gen {
+ my $fmt = shift;
+ $| = 1;
+ printf "$fmt\n", @_;
+}
+
+# Turning on/off multi-byte packet reception.
+sub multibyte($) {
+ my $active = (shift) ? 'M' : 'm';
+ for my $subunit (0 .. $ENV{UNIT_SUBUNITS} - 1) {
+ #main::logit "multibyte(): $subunit -> $active";
+ main::select_subunit($subunit);
+
+ BRI::gen "$subunit W$active";
+ }
+}
+
+package BRI::Port;
+
+sub new {
+ my $pack = shift;
+ my $port = { @_ };
+ bless $port, $pack;
+}
+
+# zap_xhfc_su.c:995
+sub init_su {
+ my $port = shift;
+ my $portnum = $port->{PORT_NUM};
+ my $port_mode_up = $port->{PORT_MODE_UP};
+ my $port_mode_exch = $port->{PORT_MODE_EXCH};
+ my $bri_nt = $port->{BRI_NT};
+ #main::logit "init_su(portnum=$portnum, port_mode_up=$port_mode_up, bri_nt=$bri_nt)";
+
+ # Setting PLL
+ # R_PLL_CTRL = 0 (V_PLL_M = 0, Reset PLL, Disable PLL_
+ # R_CLK_CFG = 05 (PLL clock as system clock, output it to CLK_OUT pin)
+ # R_PLL_P = 1
+ # R_PLL_N = 6
+ # R_PLL_S = 1
+ # R_PLL_CTRL = 1 (V_PLL_M)
+
+ BRI::gen "#--------------------------- init_su($portnum, $bri_nt, $port_mode_up, $port_mode_exch)";
+ BRI::gen "$portnum WD 02 04";
+ BRI::gen "$portnum WD 50 00"; # disable PLL
+ BRI::gen "$portnum WD 51 02";
+ BRI::gen "$portnum WD 52 06";
+ BRI::gen "$portnum WD 53 04";
+ BRI::gen "$portnum WD 50 01"; # Enable PLL
+ BRI::gen "$portnum WD 02 05"; # Enable PLL
+
+ su_sel($portnum); # select port
+ if ("$port_mode_up" == 1) {
+ $port->{CTRL3} = 0x01; # A_ST_CTRL3: V_ST_SEL = 1
+ $port->{CTRL0} = 0x10; # A_SU_CTRL0: V_ST_SQ_EN = 1
+ BRI::gen "$portnum WD 34 0F"; # A_MS_TX:
+ # (multiframe/superframe transmit register)
+ } else {
+ $port->{CTRL3} = 0x00; # A_ST_CTRL3: V_ST_SEL = 0
+ $port->{CTRL0} = 0x00; # A_SU_CTRL0: V_ST_SQ_EN = 0
+ }
+ if ("$bri_nt" == 1) {
+ $port->{CTRL0} |= 0x04; # V_SU_MD
+ }
+ # ((V_SU_EXCH)?0x80:00) (change polarity)
+ if($port_mode_exch) {
+ $port->{CTRL2} = 0x80;
+ } else {
+ $port->{CTRL2} = 0x00;
+ }
+ BRI::gen "$portnum WD 35 %02X", $port->{CTRL3}; # A_ST_CTRL3
+ BRI::gen "$portnum WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0
+ BRI::gen "$portnum WD 35 F8"; # A_ST_CTRL3 = set end of pulse control to 0xF8
+ BRI::gen "$portnum WD 32 09"; # A_SU_CTRL1 = Ignore E-channel data, Force automatic transition from G2 to G3
+ BRI::gen "$portnum WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2
+
+ # zap_xhfc_su.c:1030 in init_su()
+ # A_SU_CLK_DLY
+ my $clk_dly;
+ if ("$bri_nt" == 1) {
+ $clk_dly = 0x6C;
+ } else {
+ $clk_dly = 0x0E;
+ }
+ #main::logit "clk_dly=$clk_dly";
+ BRI::gen "$portnum WD 37 %02X", "$clk_dly";
+}
+
+sub su_sel {
+ if (@_ != 1 ) {
+ main::logit "ERROR: su_sel() called with " . scalar(@_) . " parameters";
+ exit 1;
+ }
+ my $portnum = shift;
+ BRI::gen "$portnum WD 16 %02X", $portnum; # R_SU_SEL
+}
+
+# zap_xhfc_su.c:281
+sub xhfc_selfifo {
+ my $port = shift;
+ my $portnum = $port->{PORT_NUM};
+
+ if (@_ != 1 ) {
+ main::logit "ERROR: xhfc_selfifo() called with " . scalar(@_) . " parameters";
+ exit 1;
+ }
+ my $fifonum = shift;
+ #main::logit "xhfc_selfifo($fifonum)";
+ BRI::gen "$portnum WD 0F %02X", $fifonum;
+ # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0
+}
+
+# zap_xhfc_su.c:295
+sub xhfc_resetfifo() {
+ my $port = shift;
+ my $portnum = $port->{PORT_NUM};
+
+ #main::logit "xhfc_resetfifo()";
+ # A_INC_RES_FIFO = M_RES_FIFO | M_RES_FIFO_ERR
+ BRI::gen "$portnum WD 0E 0A";
+ # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0
+}
+
+# zap_xhfc_su.c:1040
+# Initialize fifo (called for each portnum, channel, direction)
+sub setup_fifo {
+ my $port = shift;
+ my $chan = shift;
+ my $direction = shift;
+ my $conhdlc = shift;
+ my $subcfg = shift;
+ my $fifoctrl = shift;
+ my $portnum = $port->{PORT_NUM};
+ my $port_mode_up = $port->{PORT_MODE_UP};
+ my $port_mode_exch = $port->{PORT_MODE_EXCH};
+ my $bri_nt = $port->{BRI_NT};
+
+ BRI::gen "#--------------------------- setup_fifo($portnum, $chan, $direction)";
+ # my $fifonum = 0x80 | ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first
+ my $fifonum = ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first
+ my $r_slot = ($portnum << 3) | ($chan << 1) | ($direction);
+
+ # channel order workaround, swap odd and even portnums in $r_slot for PCM (chan 0, 1) only
+ if ("$chan" == 0 || "$chan" == 1) {
+ $r_slot = $r_slot ^ 0x08;
+ }
+
+ my $short_portnum = $portnum & 0x03;
+ my $a_sl_cfg = (0x80 | ($short_portnum << 3) | ($chan << 1) | ($direction)); # receive data from STIO2, transmit to STIO1
+
+ #main::logit "setup_fifo($fifonum)";
+ $port->xhfc_selfifo($fifonum);
+ # A_CON_HDLC: transparent mode selection
+ BRI::gen "$portnum WD FA %02X", $conhdlc;
+ # A_SUBCH_CFG: subchnl params
+ BRI::gen "$portnum WD FB %02X", $subcfg;
+ # A_FIFO_CTRL: FIFO Control Register
+ BRI::gen "$portnum WD FF %02X", $fifoctrl;
+ $port->xhfc_resetfifo();
+ $port->xhfc_selfifo($fifonum); # wait for busy is builtin in this command
+ BRI::gen "$portnum WD 10 %02X", $r_slot; # R_SLOT
+ BRI::gen "$portnum WD D0 %02X", $a_sl_cfg; # A_SL_CFG
+
+ #system("/bin/echo \"----=====TE\" \"short_portnum=\"$short_portnum \"portnum=\" $portnum \"chan=\" $chan\"======----\n\" >>/root/xortel/test_init");
+}
+
+# zap_xhfc_su.c:1071
+sub setup_su {
+ my $port = shift;
+ my $bchan = shift;
+ my $portnum = $port->{PORT_NUM};
+ my $port_mode_exch = $port->{PORT_MODE_EXCH};
+ my $bri_nt = $port->{BRI_NT};
+
+ BRI::gen "#--------------------------- setup_su($portnum, $bchan)";
+ #main::logit "setup_su(portnum=$portnum, bchan=$bchan, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)";
+ $port->{CTRL0} |= (1 << $bchan) | $bri_nt;
+ $port->{CTRL2} |= ($port_mode_exch << 7) | (1 << $bchan);
+ su_sel($portnum); # Select port
+ BRI::gen "$portnum WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0: V_B1_TX_EN | V_SU_MD | (NT/TE)
+ BRI::gen "$portnum WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2: V_B1_RX_EN
+}
+
+sub xhfc_ph_command {
+ my $port = shift;
+ my $cmd = shift;
+ my $portnum = $port->{PORT_NUM};
+ #main::logit "xhfc_ph_command(portnum=$portnum)";
+ if ("$cmd" eq "HFC_L1_ACTIVATE_TE") {
+ su_sel($portnum); # Select port
+ BRI::gen "$portnum WD 30 60"; # A_SU_WR_STA = (M_SU_ACT & 0x03)
+ # (set activation)
+ } elsif ("$cmd" eq "HFC_L1_FORCE_DEACTIVATE_TE") {
+ su_sel($portnum); # Select port
+ BRI::gen "$portnum WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02)
+ # (set deactivation)
+ } elsif ("$cmd" eq "HFC_L1_ACTIVATE_NT") {
+ su_sel($portnum); # Select port
+ BRI::gen "$portnum WD 30 E0"; # A_SU_WR_STA = (M_SU_ACT & 0x03) | 0x80
+ # (set activation + NT)
+ } elsif ("$cmd" eq "HFC_L1_DEACTIVATE_NT") {
+ su_sel($portnum); # Select port
+ BRI::gen "$portnum WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02)
+ # (set deactivation)
+ }
+}
+
+
+sub zthfc_startup {
+ my $port = shift;
+ my $portnum = $port->{PORT_NUM};
+ my $port_mode_exch = $port->{PORT_MODE_EXCH};
+ my $bri_nt = $port->{BRI_NT};
+ #main::logit "zthfc_startup(portnum=$portnum, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)";
+
+ # PCM <-> ST/Up Configuration
+ foreach my $chan ( 0, 1 ) {
+ $port->setup_fifo($chan, 0, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM
+ $port->setup_fifo($chan, 1, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM
+ $port->setup_su($chan); # zap_xhfc_su.c:194
+ }
+
+ # Zaptel chan 2 used as HDLC D-Channel
+ $port->setup_fifo(2, 0, 0x05, 2, 0); # D-TX: zap_xhfc_su.c:205
+ $port->setup_fifo(2, 1, 0x05, 2, 0); # D-RX: zap_xhfc_su.c:206
+ # E-chan, Echo channel is ignored
+
+
+ # enable this port's state machine
+ su_sel($portnum); # Select port
+ # A_SU_WR_STA: reset port state machine
+ BRI::gen "$portnum WD 30 00";
+ if ("$bri_nt" == 0) {
+ $port->xhfc_ph_command("HFC_L1_ACTIVATE_TE");
+ } else {
+ $port->xhfc_ph_command("HFC_L1_ACTIVATE_NT");
+ }
+}
+
+package main;
+
+logit "Starting '$0'";
+
+#------------------------------------------- Instance detection
+
+# zap_xhfc_su.c:895
+sub init_xhfc($) {
+ my $portnum = shift;
+ main::logit "init_xhfc($portnum)";
+ BRI::gen "#--------------------------- init_xhfc";
+ BRI::gen "$portnum WD 0D 00"; # r_FIFO_MD: 16 fifos,
+ # 64 bytes for TX and RX each (FIFO mode config)
+
+ # software reset to enable R_FIFO_MD setting
+ BRI::gen "$portnum WD 00 08"; # R_CIRM = M_SRES (soft reset)
+ # --> WAIT 5u
+ BRI::gen "$portnum WD 00 00"; # R_CIRM = 0 (zero it to deactivate reset)
+
+ # amplitude
+ BRI::gen "$portnum WD 46 80"; # R_PWM_MD: (PWM output mode register)
+ # PWM push to zero only
+ BRI::gen "$portnum WD 39 18"; # R_PWM1: (modulator register for PWM1)
+ # set duty cycle
+
+ BRI::gen "$portnum WD 0C 11"; # R_FIFO_THRES: (FIFO fill lvl control register)
+ # RX/TX threshold = 16 bytes
+
+ # --> Wait until (R_STATUS & (M_BUSY | M_PCM_INIT))
+ # M_BUSY status will be checked after fifo selection
+ BRI::gen "$portnum WD 0F 80";
+ # set PCM !master mode
+ BRI::gen "$portnum WD 14 08"; # R_PCM_MD0 = PCM slave mode, F0IO duration is 2 HFC_PCLK's
+
+ # (C4IO, F0IO are inputs)
+
+ # set pll adjust
+ # WD 14 90 # R_PCM_MD0: Index value to select
+ # the register at address 15
+ # WD 15 2C # R_PCM_MD1: V_PLL_ADJ (DPLL adjust speed), C4IO is 16.384MHz(128 time slots)
+ # in the last slot of PCM frame
+ BRI::gen "$portnum WI 14 98 20"; # R_PCM_MD1: V_PLL_ADJ
+ # (DPLL adjust speed) in the
+ # last slot of PCM frame
+
+ BRI::gen "$portnum WD 4C 03"; # GPIOGPIO function (not PWM) on GPIO0 and GPIO1 pins
+ BRI::gen "$portnum WD 4A 03"; # Output enable for GPIO0 and GPIO1 pins
+}
+
+my @port_type = (
+ { 'BRI_NT' => 1 },
+ { 'BRI_NT' => 0 }
+ );
+
+# zap_xhfc_su.c:175
+sub main() {
+ my $subunit;
+ my $subunits_mask = pack("C", $ENV{UNIT_SUBUNITS_DIR});
+ my @direction = split(//, unpack("b*", $subunits_mask));
+
+ #logit "main(): UNIT_TYPE=$ENV{UNIT_TYPE} UNIT_SUBUNITS_DIR=[@direction]";
+ if(!$opts{o}) {
+ foreach my $var (qw(XBUS_NAME UNIT_NUMBER UNIT_TYPE UNIT_SUBUNITS UNIT_SUBUNITS_DIR XBUS_REVISION XBUS_CONNECTOR)) {
+ die "Missing mandatory '$var' environment variable" unless defined $var;
+ }
+ }
+ # Turn off multi-byte packet reception before initialization started
+ # Otherwise we mess with registers while the FPGA firmware tries to
+ # send us packets.
+ BRI::multibyte(0);
+
+ # Port initialization
+ for($subunit = 0; $subunit < $ENV{UNIT_SUBUNITS}; $subunit++) {
+ my $is_nt = $direction[$subunit];
+
+ main::select_subunit($subunit);
+ if(($subunit % 4) == 0) { # A new xhfc chip
+ #logit "main(): Initializing chip";
+ init_xhfc($subunit); # zap_xhfc_su.c:1173 in setup_instance()
+ }
+ #logit "main(): Initializing subunit $subunit is_nt=$is_nt";
+ my $p = BRI::Port->new(
+ 'PORT_NUM' => $subunit,
+ 'BRI_NT' => $is_nt,
+ 'PORT_MODE_UP' => 0,
+ 'PORT_MODE_EXCH' => 0
+ );
+ # zap_XHfc_su.c:1186 in setup_instance()
+ $p->init_su;
+ $p->zthfc_startup;
+ }
+ # Turn on multi-byte packet reception when ports initialization finished
+ BRI::multibyte(1);
+}
+
+main;
+
+logit "Ending '$0'";
+
+close REG;
+close STDERR;
+exit 0;