Revert "Remove support for xpp drivers."
[dahdi/linux.git] / drivers / dahdi / xpp / init_card_6_30
1 #! /usr/bin/perl -w
2 use strict;
3
4 # Make warnings fatal
5 local $SIG{__WARN__} = sub { die @_ };
6
7 #
8 # Written by Oron Peled <oron@actcom.co.il>
9 # Copyright (C) 2017, Xorcom
10 #
11 # All rights reserved.
12 #
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2 of the License, or
16 # (at your option) any later version.
17 #
18 # See the file LICENSE in the top level of this tarball.
19 #
20
21 #
22 # $Id$
23 #
24 # Data format:
25 #       - A comment start with ';' or '#' until the end of line
26 #       - Blank lines are ignored
27 #       - Fields are whitespace separated (spaces or tabs)
28 #
29 # The fields are (in command line order):
30 #       1. SLIC select in decimal (range 0-7).
31 #          * is a special value which means ALL SLICS (only some registers
32 #          accept settings for ALL SLICS).
33 #       2. Command word:
34 #               - RD    Read Direct register.
35 #               - RS    Read Sub-register.
36 #               - WD    Write Direct register.
37 #               - WS    Write Sub-register.
38 #       3. Register number in hexadecimal.
39 #       4. Low data byte in hexadecimal. (for WD and WS commands).
40 #       5. High data byte in hexadecimal. (for WS command only).
41 #
42 #
43
44 package main;
45 use File::Basename;
46 use Getopt::Std;
47
48 my $program = basename("$0");
49 my $init_dir = dirname("$0");
50 BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
51 use XppConfig $init_dir;
52 my $unit_id;
53 my %opts;
54
55 getopts('o:', \%opts);
56
57 my %settings;
58 $settings{debug} = 0;
59 $settings{fxs_skip_calib} = 0;
60 my $chipregs;
61 my $command;
62 my $expander_cmd;
63 my $ring_registers;
64
65 sub logit {
66         print STDERR "$unit_id: @_\n";
67 }
68
69 sub debug {
70         logit @_ if $settings{debug};
71 }
72
73 # Arrange for error logging
74 if (-t STDERR) {
75         $unit_id = 'Interactive';
76         debug "Interactive startup";
77 } else {
78         $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
79         open (STDERR, "| logger -t $program -p kern.info") || die;
80         debug "Non Interactive startup";
81         foreach my $k (qw(
82                         XBUS_NAME
83                         XBUS_NUMBER
84                         XBUS_MODEL_STRING
85                         UNIT_NUMBER
86                         UNIT_TYPE
87                         UNIT_SUBUNITS
88                         UNIT_SUBUNITS_DIR
89                         XBUS_REVISION
90                         XBUS_CONNECTOR
91                         XBUS_LABEL)) {
92                 unless(defined $ENV{$k}) {
93                         logit "Missing ENV{$k}\n";
94                         die;
95                 }
96         }
97         logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
98         $chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
99                 $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
100         $command = "/proc/xpp/$ENV{XBUS_NAME}/command";
101         if(! -f $chipregs) {
102                 my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER});
103                 $chipregs = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs";
104                 logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
105                         if -f $chipregs;
106         }
107         $ring_registers = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/fxs_ring_registers",
108                 $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
109         logit "OLD DRIVER: missing '$ring_registers' -- fallback to hard-coded defaults"
110                 unless -f $ring_registers;
111 }
112
113 sub set_output() {
114         my $output;
115
116         if($opts{o}) {
117                 $output = $opts{o};
118         } else {
119                 # No subunits in FXS (everything is subunit 0)
120                 $output = $chipregs;
121         }
122         open(REG, ">$output") || die "Failed to open '$output': $!\n";
123         my $oldfh = select REG;
124         main::logit "# Setting output" if $opts{o};
125         return $oldfh;
126 }
127
128 sub mysleep($) {
129         my $timeout = shift;
130         select(undef,undef,undef,$timeout);
131 }
132
133 package FXS;
134
135 sub gen {
136         my $fmt = shift;
137         $| = 1;
138         printf "$fmt\n", @_;
139 }
140
141 my @SlicNums;
142
143 sub write_to_slic_file($) {
144         my $write_str = shift;
145
146         open(SLICS,">$chipregs") or
147                 die("Failed writing to chipregs file $chipregs");
148         print SLICS $write_str;
149         close(SLICS) or die "Failed writing '$write_str' to '$chipregs': $!";
150         main::mysleep(0.001);
151
152 }
153
154 sub write_to_ring_register($) {
155         my $write_str = shift;
156
157         open(SLICS,">$ring_registers") or
158                 die("Failed writing to ring_registers file $ring_registers");
159         print SLICS $write_str;
160         close(SLICS) or die "Failed writing '$write_str' to '$ring_registers': $!";
161         main::mysleep(0.001);
162 }
163
164 sub read_reg($$$;$) {
165         my $slic = shift;
166         my $addr = shift;
167         my $direct = shift;
168         my $bits_shift = shift;
169         $bits_shift = 0 unless defined $bits_shift;
170         my $addr_low;
171         my $addr_high;
172         main::debug("read_reg: $slic, $addr, $direct");
173         $addr_low = $addr & 0xFF;
174         $addr_high = $addr >> 8;
175
176         my $str;
177         if ($direct eq 'D') {
178                 $str = sprintf "%s RD %02X",
179                         $slic, $addr_low;
180         } else {
181                 $str  = sprintf "%s RR %02X %02X",
182                         $slic, $addr_low, $addr_high;
183         }
184         write_to_slic_file($str);
185
186         my $retries = 10;
187         my $reply = "";
188         # If the command queue is long, we may need to wait...
189 WAIT_RESULTS:
190         {
191                 my @results;
192
193                 # The time to sleep is a tradeoff:
194                 #   - Too long is a waste of time.
195                 #   - Too short will cause many retries, wastes time.
196                 # So the current value (after trial and error) is...
197                 main::mysleep(0.013);
198                 open(SLICS,$chipregs) or
199                         die("Failed reading from chipregs file $chipregs");
200                 while(<SLICS>){
201                         s/#.*//;
202                         next unless /\S/;
203                         if ($direct eq 'D') {
204                                 @results = /^\s*(\d+)\s+[RW][DR]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/;
205                         } else {
206                                 @results = /^\s*(\d+)\s+[RW][DR]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/;
207                         }
208                         if(($direct eq 'D' && @results != 4) || ($direct eq 'R' && @results != 7)) {
209                                 main::logit "Failed reading from '$chipregs' ($direct, $slic,$addr)";
210                                 die;
211                         }
212                 }
213                 close(SLICS);
214                 my $read_addr;
215                 if ($direct eq 'D') {
216                         $read_addr = hex($results[1]);
217                 } else {
218                         $read_addr = hex(sprintf "0x$results[2]$results[1]");
219                 }
220                 if($results[0] ne $slic || $read_addr ne $addr) {
221                         # We read obsolete values, need to wait some more
222                         if(--$retries) {
223                                 main::debug "$slic R$direct $addr -- retry (@results, $read_addr)";
224                                 redo WAIT_RESULTS;
225                         } else {
226                                 main::logit "Failed: $slic R$direct $addr returned @results, $addr";
227                                 die;
228                         }
229                 }
230                 # Good.
231                 $results[0] = "";
232                 $results[1] = "";
233                 if ($direct eq 'R') {
234                         $results[2] = "";
235                 }
236                 foreach my $val (@results) {
237                         $reply = sprintf("%s%s", $val, $reply);
238                 }
239                 $reply = hex(sprintf("0x%s", $reply));
240
241         }
242         return $reply >> $bits_shift;
243 }
244
245 # TODO: rearange arguments
246 sub write_reg{#($$$) {
247         my $slic = shift;
248         my $reg = shift;
249         my $val = shift;
250
251         my $str  = sprintf "%s WD %02X %02X",
252                 $slic, $reg, $val;
253         main::debug("write_reg: $slic, $reg, $val");
254         write_to_slic_file($str);
255 }
256
257 #
258 # BITS:
259 # 3  - port num
260 # 1  - read/write
261 # 1  - Register / RAM
262 # 11 - address
263 # 29 - data
264 sub write_ram($$$$) {
265         my $slic = shift;
266         my $addr = shift;
267         my $value = shift;
268         my $bits_shift = shift;
269         my $addr_low;
270         my $addr_high;
271         my $value_0;
272         my $value_1;
273         my $value_2;
274         my $value_3;
275         my $log_output = sprintf("write_ram: %s, %4d, 0x%08X", $slic, $addr, $value);
276         main::debug($log_output);
277         $value = $value << $bits_shift;
278         $addr_low = $addr & 0xFF;
279         $addr_high = $addr >> 8;
280
281         $value_0 = $value & 0xFF;
282         $value >>= 8;
283         $value_1 = $value & 0xFF;
284         $value >>= 8;
285         $value_2 = $value & 0xFF;
286         $value >>= 8;
287         $value_3 = $value & 0xFF;
288
289         my $str  = sprintf "%s WR %02X %02X %02X %02X %02X %02X",
290                 $slic, $addr_low, $addr_high,
291                 $value_0, $value_1, $value_2, $value_3;
292         write_to_slic_file($str);
293 }
294
295 sub set_user_mode {
296         my $slic = shift;
297         my $on = shift;
298         my $current = read_reg($slic, 0x7E, 'D');
299         $current &= 0x1;
300         $on &= 0x1;
301         main::debug("::set_user_mode($slic, $on): " . $current . " -> " . $on . "\n");
302         return 1 if $current == $on;
303         write_reg($slic, 126, 0x02);
304         write_reg($slic, 126, 0x08);
305         write_reg($slic, 126, 0x0E);
306         write_reg($slic, 126, 0x00);
307         return 1;
308 }
309
310 sub init_early() {
311         # I/O Expander initialization
312         $expander_cmd = sprintf "echo 0A 00 0F %1d0 05 08 00 00 00 FF > %s",
313                 $ENV{UNIT_NUMBER}, $command;            # enable outputs for Greed LEDs
314         system("$expander_cmd");
315         $expander_cmd = sprintf "echo 0A 00 0F %1d0 05 08 01 00 AA 55 > %s",
316                 $ENV{UNIT_NUMBER}, $command;            # enable outputs for Red LEDs and relays
317         system("$expander_cmd");
318         $expander_cmd = sprintf "echo 0A 00 0F %1d0 05 08 0D 00 AA AA > %s",
319                 $ENV{UNIT_NUMBER}, $command;            # enable pull-ups for inputs
320         system("$expander_cmd");
321 }
322
323 sub load_patch($) {
324         my $slics_ref = shift;
325         my @slics = @{ $slics_ref };
326         my $slic;
327
328         main::debug "Loading patch based on si3226x_patch_C_TSS_ISO_2014JUN18.c";
329         foreach $slic (@slics) {
330                 FXS::set_user_mode($slic, 1);           # Turn on user mode
331         }
332         write_reg('*', 81, 0x00);       # JMPEN, disable the patch
333
334         main::debug "=====Patch data======";
335         my @patch_data_array = (
336                         141541,
337                         540867,
338                         141541,
339                         543427,
340                         141541,
341                         553155,
342                         141541,
343                         577731,
344                         141541,
345                         579779,
346                         141541,
347                         581315,
348                         141541,
349                         592579,
350                         141541,
351                         633027,
352                         141541,
353                         637635,
354                         141541,
355                         639683,
356                         141541,
357                         650947,
358                         141541,
359                         651459,
360                         141541,
361                         651971,
362                         141541,
363                         652483,
364                         141541,
365                         652995,
366                         141541,
367                         653507,
368                         736,
369                         491712,
370                         452200,
371                         141541,
372                         491200,
373                         5733,
374                         524290,
375                         142565,
376                         550083,
377                         3685,
378                         519266,
379                         5220,
380                         144098,
381                         550083,
382                         3685,
383                         524291,
384                         141541,
385                         551619,
386                         5221,
387                         3682,
388                         524292,
389                         5,
390                         141541,
391                         135362,
392                         98021,
393                         727745,
394                         474213,
395                         17637,
396                         557251,
397                         101093,
398                         557251,
399                         473701,
400                         515653,
401                         843365,
402                         188002,
403                         843355,
404                         145125,
405                         560835,
406                         524290,
407                         660069,
408                         518053,
409                         517224,
410                         518244,
411                         142565,
412                         564419,
413                         524288,
414                         521733,
415                         843365,
416                         188002,
417                         524315,
418                         145125,
419                         568003,
420                         843365,
421                         522850,
422                         523387,
423                         147685,
424                         573123,
425                         522363,
426                         145125,
427                         575171,
428                         521826,
429                         141541,
430                         575683,
431                         518757,
432                         521826,
433                         141541,
434                         575683,
435                         521824,
436                         522245,
437                         522338,
438                         141541,
439                         716481,
440                         173669,
441                         523845,
442                         141541,
443                         730304,
444                         523877,
445                         141541,
446                         690368,
447                         614117,
448                         588995,
449                         457221,
450                         558181,
451                         457122,
452                         457333,
453                         143077,
454                         588995,
455                         144608,
456                         587971,
457                         524292,
458                         141541,
459                         588483,
460                         524304,
461                         671746,
462                         558181,
463                         410018,
464                         437365,
465                         143586,
466                         100034,
467                         141541,
468                         98498,
469                         550117,
470                         619715,
471                         558181,
472                         410018,
473                         403061,
474                         143077,
475                         619715,
476                         524290,
477                         143589,
478                         608963,
479                         402533,
480                         524290,
481                         400901,
482                         29189,
483                         431717,
484                         408133,
485                         432741,
486                         406085,
487                         392805,
488                         407621,
489                         792165,
490                         405573,
491                         406629,
492                         792133,
493                         408677,
494                         431680,
495                         432645,
496                         409189,
497                         392785,
498                         402949,
499                         141541,
500                         630979,
501                         560741,
502                         400482,
503                         398852,
504                         143077,
505                         615107,
506                         402533,
507                         398946,
508                         400901,
509                         29186,
510                         400389,
511                         141541,
512                         630979,
513                         400997,
514                         262242,
515                         143077,
516                         618691,
517                         524291,
518                         400901,
519                         29189,
520                         141541,
521                         630979,
522                         558181,
523                         407458,
524                         524309,
525                         694789,
526                         558085,
527                         694789,
528                         403045,
529                         524290,
530                         143077,
531                         630979,
532                         405605,
533                         792133,
534                         408165,
535                         431685,
536                         406117,
537                         432709,
538                         407653,
539                         392768,
540                         402949,
541                         694789,
542                         560645,
543                         694789,
544                         743525,
545                         119426,
546                         141541,
547                         1003201,
548                         560741,
549                         524290,
550                         143584,
551                         636099,
552                         141541,
553                         191682,
554                         694789,
555                         141541,
556                         859842,
557                         171109,
558                         170565,
559                         141541,
560                         963776,
561                         524291,
562                         144613,
563                         641731,
564                         199685,
565                         667365,
566                         644803,
567                         431717,
568                         197189,
569                         136805,
570                         198725,
571                         170597,
572                         262242,
573                         524291,
574                         144613,
575                         647875,
576                         170501,
577                         667365,
578                         886464,
579                         136805,
580                         180293,
581                         141541,
582                         886464,
583                         524293,
584                         524293,
585                         524293,
586                         524293,
587                         524293,
588                         524293,
589                 );
590
591         write_ram('*', 1358, 0x00000000, 3);            # PRAM_ADDR, reset the patch RAM address
592         foreach my $val (@patch_data_array) {
593                 write_ram('*', 1359, $val, 12); # PRAM_DATA, shl 12, addr auto inc
594         }
595
596         main::debug "=====Patch entries======";         # lowest 8 entries are registers
597         my @patch_entries_array = (
598                         950,
599                         4347,
600                         3431,
601                         1425,
602                         1347,
603                         4287,
604                         4006,
605                         4469,
606                         1881,
607                         1720,
608                 );
609
610         my $jmp_table_low = 82;
611         my $jmp_table_high = 1597;
612         foreach my $val (@patch_entries_array) {
613                 last if $val == 0;
614                 if ($jmp_table_low <= 97) {
615                         write_reg('*', $jmp_table_low, $val & 0xFF);# JMPnLO
616                         $jmp_table_low++;
617                         write_reg('*', $jmp_table_low, $val >> 8  );# JMPnHI
618                         $jmp_table_low++;
619                 } else {
620                         write_ram('*', $jmp_table_high, $val & 0x1FFF, 3);      # shl 3
621                         $jmp_table_high++;
622                 }
623         }
624
625         write_ram('*', 448, 0x06182014, 3);             # PATCH_ID, shl 3, a unique code which is a hash of the patch.
626
627         main::debug "=====Patch support======";
628         my @patch_support_addr_array = (
629                         800,
630                         795,
631                         799,
632                         798,
633                         794,
634                         787,
635                         786,
636                         782,
637                         892,
638                         893,
639                         925,
640                         926,
641                         1014,
642                         1020,
643                         1021,
644                         1022,
645                         333,
646                         334,
647                         352,
648                 );
649         my @patch_support_data_array = (
650                         0x200000,
651                         0x7D80000,
652                         0x69580EA,
653                         0x82C58C,
654                         0x1500000,
655                         0x0,
656                         0x320000,
657                         0x0,
658                         0x400000,
659                         0x0,
660                         0xA00000,
661                         0x1F00000,
662                         0x2D8000,
663                         0x0,
664                         0x2075F60,
665                         0x220335B,
666                         0x0,
667                         0x0,
668                         0x0,
669                 );
670         for (my $i = 0; $i < @patch_support_addr_array; $i++) {
671                 my $addr = $patch_support_addr_array[$i];
672                 my $val = $patch_support_data_array[$i];
673                 write_ram('*', $addr, $val, 3);
674         }
675
676         if ($settings{debug}) {
677                 foreach $slic (@slics) {
678                         main::debug "=====Verify patch=======";
679                         my $read_val;
680                         # PRAM_ADDR, reset the patch RAM address:
681                         write_ram($slic, 1358, 0x00000000, 3);
682                         foreach my $val (@patch_data_array) {
683                                 # PRAM_DATA, shr 12, addr auto inc
684                                 $read_val = read_reg($slic, 1359, 'R', 12);
685                                 if ($val != $read_val) {
686                                         printf "0x%X =? 0x%X\n", $val, $read_val;
687                                         printf "patch verification failed\n";
688                                         exit 0;
689                                 }
690                         }
691                         main::debug "Patch has been verified!";
692
693                         main::debug "=====Verify patch entries=======";
694                         $jmp_table_low = 82;
695                         $jmp_table_high = 1597;
696                         foreach my $val (@patch_entries_array) {
697                                 last if $val == 0;
698                                 if ($jmp_table_low <= 97) {
699                                         $read_val = read_reg($slic, $jmp_table_low, 'D');# JMPnLO
700                                         $jmp_table_low++;
701                                         $read_val |= read_reg($slic, $jmp_table_low, 'D') << 8;# JMPnHI
702                                         $jmp_table_low++;
703                                 } else {
704                                         $read_val = read_reg($slic, $jmp_table_high, 'R', 3);   # PRAM_DATA, shr 3
705                                         $read_val &= 0x1FFF;
706                                         $jmp_table_high++;
707                                 }
708                                 if ($val != $read_val) {
709                                         printf "0x%X =? 0x%X\n", $val, $read_val;
710                                         printf "patch entries verification failed\n";
711                                         exit 0;
712                                 }
713                         }
714                         main::debug "Patch entries has been verified!";
715
716                         main::debug "=====Verify patch support=======";
717                         for (my $i = 0; $i < @patch_support_addr_array; $i++) {
718                                 my $addr = $patch_support_addr_array[$i];
719                                 my $val = $patch_support_data_array[$i];
720                                 $read_val = read_reg($slic, $addr, 'R', 3);
721                                 if ($val != $read_val) {
722                                         printf "0x%X =? 0x%X\n", $val, $read_val;
723                                         printf "Patch support verification failed\n";
724                                         exit 0;
725                                 }
726                         }
727                 main::debug "patch support has been verified!";
728                 }
729         }
730
731         write_reg('*', 81, 0x01);                       # JMPEN, enable the patch
732         write_reg('*', 05, 0x00);                       # RAM_ADDR_HI, back to normal RAM access
733         foreach $slic (@slics) {
734                 FXS::set_user_mode($slic, 0);                   # Turn off user mode
735         }
736 }
737
738 sub load_general_params($) {
739         my $slics_ref = shift;
740         my @slics = @{ $slics_ref };
741         my $slic;
742
743         main::debug "Loading patch based on si3226x_patch_C_TSS_ISO_2014JUN18.c";
744         foreach $slic (@slics) {
745                 FXS::set_user_mode($slic, 1);           # Turn on user mode
746         }
747
748         write_reg('*', 47, 0x00);               # ENHANCE
749         write_reg('*', 80, 0x2F);               # AUTO
750
751         write_ram('*',  764, 0x0050C480, 3);    #BAT_HYST
752         # Ringing parameters 65Vrms 0Vdc 20Hz LPR
753         # Loop = 500.0 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms
754         # Rprot = 30 ohms, Type = LPR, Waveform = SINE
755         write_ram('*',  637, 0x15E5200E, 3);    #ringing impedance = 100 ohms
756         write_ram('*',  766, 0xA3D705, 3);      #VBATL_EXPECT 10 V
757         write_ram('*',  767, 0xA3D705, 3);      #VBATH_EXPECT 10 V
758         write_ram('*',  768, 0x5ED285F, 3);     #VBATR_EXPECT 92.6 V
759         write_ram('*',  768, 0xFFF0000, 3);     #PWRSAVE_TIMER
760         write_ram('*',  916, 0x0F5C28F, 3);     #OFFHOOK_THRESH
761         write_ram('*',  919, 0x00F00000, 3);    #VBAT_TRACK_MIN
762         write_ram('*',  920, 0x02000000, 3);    #VBAT_TRACK_MIN_RNG
763         write_ram('*',  970, 0x00800000, 3);    #THERM_DBI
764
765         write_ram('*', 1004, 0x00F18900, 3);    #DCDC_VERR
766         write_ram('*', 1005, 0x0080C480, 3);    #DCDC_VERR_HYST
767         write_ram('*', 1006, 0x00800000, 3);    #DCDC_OITHRESH_LO
768         write_ram('*', 1007, 0x01F00000, 3);    #DCDC_OITHRESH_HI
769         write_ram('*', 1540, 0x00200000, 3);    #PD_UVLO
770         write_ram('*', 1541, 0x00300000, 3);    #PD_OVLO
771         write_ram('*', 1542, 0x00200000, 3);    #PD_OCLO
772
773         write_ram('*', 1545, 0x00C00000, 3);    #DCDC_UVHYST, (94v - 90v -1) / 0.257v = 12
774         write_ram('*', 1546, 0x03D00000, 3);    #DCDC_UVTHRESH, 94v / 1.543v = 61
775         write_ram('*', 1547, 0x1200000, 3);     #DCDC_OVTHRESH
776
777         write_ram('*', 1554, 0x07700000, 3);  #DCDC_UVPOL
778
779         write_ram('*', 1558, 0x00000000, 3);    #DCDC_VREF_CTRL
780         write_ram('*', 1560, 0x00200000, 3);    #DCDC_RNGTYPE
781         write_ram('*', 1585, 0x00300000, 3);    #DCDC_ANA_GAIN
782         write_ram('*', 1586, 0x00300000, 3);    #DCDC_ANA_TOFF
783         write_ram('*', 1587, 0x00100000, 3);    #DCDC_ANA_TONMIN
784         write_ram('*', 1588, 0x00FFC000, 3);    #DCDC_ANA_TONMAX
785         write_ram('*', 1589, 0x00F00000, 3);    #DCDC_ANA_DSHIFT
786         write_ram('*', 1590, 0x0FDA4000, 3);    #DCDC_ANA_LPOLY
787
788         write_ram('*', 759, 0x07FEB800, 3);     # COEF_P_HVIC
789         write_ram('*', 756, 0x0048D15B, 3);     # P_TH_HVIC
790
791         write_ram('*', 967, 0x03A2E8BA, 3);     # SCALE_KAUDIO
792
793         #             /* GC RAM locations that moved from RevB to RevC */
794         write_ram('*', 1018, 0x03000000, 3);    # LKG_OFHK_OFFSET
795         write_ram('*', 1017, 0x05000000, 3);    # LKG_LB_OFFSET
796         write_ram('*', 1013, 0x02200000, 3);    # VBATH_DELTA
797         write_ram('*', 1012, 0x03700000, 3);    # UVTHRESH_MAX
798         write_ram('*', 1011, 0x04F80200, 3);    # UVTHRESH_SCALE
799         write_ram('*', 1010, 0x00A23000, 3);    # UVTHRESH_BIAS
800
801         # /* Hardcoded mods to default settings */
802         write_reg('*',   98, 0x80);             #PDN
803         write_ram('*', 626, 0x723F235, 3);      # ROW0_C2
804         write_ram('*', 627, 0x57A9804, 3);      # ROW1_C2
805         write_ram('*', 918, 0x36000, 3);        # XTALK_TIMER
806         write_ram('*', 1616, 0x1100000, 3);     # DCDC_CPUMP_LP_MASK
807
808         #/* Smart VOV Default Settings - set here in case no ring preset is loaded */
809         write_ram('*', 973, 0xFFFFFF, 3);       # VOV_DCDC_SLOPE
810         write_ram('*', 974, 0xA18937, 3);       # VOV_DCDC_OS
811         write_ram('*', 975, 0xE49BA5, 3);       # VOV_RING_BAT_MAX
812
813         write_ram('*', 516, 0x10038D, 3);       # VDIFFLPF
814         write_ram('*', 513, 0x4EDDB9, 3);       # ILOOPLPF
815         write_ram('*', 514, 0x806D6, 3);        # ILONGLPF
816         write_ram('*', 517, 0x10059F, 3);       # VCMLPF
817         write_ram('*', 708, 0xF0000, 3);        # CM_SPEEDUP_TIMER
818         write_ram('*', 709, 0x106240, 3);       # VCM_TH
819
820         # /* Prevent Ref Osc from powering down in PLL Freerun mode (pd_ref_osc) */
821 #       write_ram('*', 709, 0x106240, 3);       # PWRSAVE_CTRL_LO shall be arithmetic here
822
823         # batType == VCM_HYST
824         write_ram('*', 1565, 0xC00000, 3);      #
825         write_ram('*',  750, 0x0306280, 3);     #VCM_HYST
826         write_ram('*',  971, 0x2A00000, 3);     #LPR_SCALE
827         write_ram('*',  972, 0x061EB80, 3);     #LPR_CM_OS
828         write_ram('*', 1565, 0x0A00000, 3);     #DCDC_OIMASK
829         write_ram('*', 1643, 0x000000, 3);      #DCDC_OV_DEBOUNCE
830         write_ram('*', 1641, 0x0D00000, 3);     #DCDC_UV_DEBOUNCE
831
832         write_ram('*', 1512, 0x00200000, 3);    # PD_OFFLD_DAC
833         write_ram('*', 1513, 0x00200000, 3);    # PD_OFFLD_GM
834         write_ram('*', 1592, 0x0300000, 3);     #DCDC_PD_ANA
835         write_ram('*',  897, 0x0480CBF, 3);     #P_TH_OFFLOAD
836
837         write_reg('*',   35, 0x03);             #OFFLOAD
838
839         write_ram('*', 1553, 0x00000000, 3);    #DCDC_SWDRV_POL
840         write_ram('*',  860, 0x008B9ACA, 3);    # IRING_LIM (90.000 mA)
841
842         foreach $slic (@slics) {
843                 FXS::set_user_mode($slic, 0);           # Turn on user mode
844         }
845
846 # Loading Coeff before cal to ensure accurate zsynth results in OHT
847 # This set of coefficients are for the following input parameters:
848 # Device = Si3217x, R1 = 600, R2 = 0, C = 0, R_surge = 20, R_fuse = 24, 10.txt
849 # Generated on 9/30/2009 2:51:17 PM
850         # TXACEQ
851         write_ram('*',  540, 0x07F55480, 3);    #TXACEQ_CO
852         write_ram('*',  541, 0x000D6400, 3);    #TXACEQ_C1
853         write_ram('*',  542, 0x00011A00, 3);    #TXACEQ_C2
854         write_ram('*',  543, 0x1FFD7F00, 3);    #TXACEQ_C3
855
856         # RXACEQ
857         write_ram('*',  546, 0x07F04900, 3);    #RXACEQ_CO
858         write_ram('*',  547, 0x00126A00, 3);    #RXACEQ_C1
859         write_ram('*',  548, 0x1FFE1D00, 3);    #RXACEQ_C2
860         write_ram('*',  549, 0x1FFC9480, 3);    #RXACEQ_C3
861
862         # ECFIR/ECIIR
863         write_ram('*',  563, 0x0012A580, 3);    #ECFIR_C2
864         write_ram('*',  564, 0x1FE59900, 3);    #ECFIR_C3
865         write_ram('*',  565, 0x01BCB180, 3);    #ECFIR_C4
866         write_ram('*',  566, 0x00790780, 3);    #ECFIR_C5
867         write_ram('*',  567, 0x02113380, 3);    #ECFIR_C6
868         write_ram('*',  568, 0x1F172380, 3);    #ECFIR_C7
869         write_ram('*',  569, 0x00805080, 3);    #ECFIR_C8
870         write_ram('*',  570, 0x1FD6E600, 3);    #ECFIR_C9
871         write_ram('*',  571, 0x1FFDF800, 3);    #ECIIR_B0
872         write_ram('*',  572, 0x00010980, 3);    #ECIIR_B1
873         write_ram('*',  573, 0x0E46D280, 3);    #ECIIR_A1
874         write_ram('*',  574, 0x19B4F900, 3);    #ECIIR_A2
875
876         # ZSYNTH
877         write_ram('*',  653, 0x007A8C00, 3);    #ZSYNTH_B0
878         write_ram('*',  654, 0x1F0BB880, 3);    #ZSYNTH_B1
879         write_ram('*',  655, 0x0079BD00, 3);    #ZSYNTH_B2
880         write_ram('*',  656, 0x0FF66D00, 3);    #ZSYNTH_A1
881         write_ram('*',  657, 0x18099080, 3);    #ZSYNTH_A2
882
883         write_reg('*',   45, 0x59);             #RA
884
885         # TXGAIN/RXGAIN
886         write_ram('*',  544, 0x08769A80, 3);    #TXACGAIN
887         write_ram('*',  545, 0x0141E080, 3);    #RXACGAIN
888         write_ram('*',  906, 0x0141E080, 3);    #RXACGAIN_SAVE
889
890         # RXACHPF
891         write_ram('*',  658, 0x07AC0400, 3);    #RXACHPF_B0_1
892         write_ram('*',  659, 0x1853FC80, 3);    #RXACHPF_B1_1
893         write_ram('*',  660, 0x07580880, 3);    #RXACHPF_A1_1
894
895         write_ram('*',  666, 0x8000000, 3);     #RXACHPF_GAIN
896
897         foreach $slic (@slics) {
898                 FXS::set_user_mode($slic, 1);           # Turn on user mode
899         }
900         write_reg('*', 98, 0x80);                       # Power up MADC
901         foreach $slic (@slics) {
902                 FXS::set_user_mode($slic, 0);                   # Turn off user mode
903         }
904 }
905
906 sub calibrate_slics($$$) {
907         my $cal0 = shift;
908         my $cal1 = shift;
909         my $cal2 = shift;
910
911         main::debug "Calibrating channels @SlicNums";
912         write_reg('*', 26, $cal0);              # CAL0
913         write_reg('*', 27, $cal1);              # CAL1
914         write_reg('*', 28, $cal2);              # CAL2
915         write_reg('*', 29, 0x80);               # CAL3, CAL_EN
916
917         # wait until all slics have finished calibration, or for timeout
918         # time periods in seconds:
919         my $sleep_time = 0.001;
920         my $timeout_time = 0.600; # Maximum from the spec
921         my @curr_slics = @SlicNums;
922         my $sleep_cnt = 0;
923 CALIB_LOOP:
924         while(1) {
925                 main::mysleep($sleep_time);
926                 my @next_slics;
927                 for my $slic (@curr_slics) {
928                         my $val = read_reg($slic, 29, 'D');
929                         main::debug("checking slic $slic: $val.");
930                         push(@next_slics, $slic) if ($val & 0x80) != 0;
931                 }
932                 @curr_slics = @next_slics;
933                 last unless @curr_slics;
934                 if ($sleep_cnt * $sleep_time > $timeout_time) {
935                         main::logit("Auto Calibration: Exiting on timeout: $timeout_time.");
936                         last CALIB_LOOP;
937                 }
938                 main::debug("auto_calibrate not done yet($sleep_cnt): @curr_slics");
939                 $sleep_cnt++;
940         }
941         #log_calib_params();
942
943 }
944
945 sub dc_powerup($) {
946         my $slics_ref = shift;
947         my @slics = @{ $slics_ref };
948
949         foreach my $slic (@slics) {
950                 FXS::set_user_mode($slic, 1);   # Turn on user mode
951         }
952         write_ram('*', 1538, 0x700000, 3);      # PD_DCDC, In case OV or UV previously occurred
953 #       write_ram('*', 1555, 0x100000, 3);      # DCDC_CPUMP, Turn on charge pump
954         main::mysleep(0.010);
955 #       write_ram('*', 1538, 0x00600000, 3);    # start up converter
956         main::mysleep(0.500);
957         write_ram('*', 1555, 0x000000, 3);      # DCDC_CPUMP, Turn off charge pump
958         write_ram('*', 1542, 0x300000, 3);      # PD_OCLO
959         write_ram('*', 1551, 0x00000000, 3);    # sClear DCDC status
960         main::mysleep(0.030);
961         write_ram('*', 1538, 0x00400000, 3);
962         foreach my $slic (@slics) {
963                 FXS::set_user_mode($slic, 0);   # Turn off user mode
964         }
965 }
966
967 sub read_defaults() {
968         if(XppConfig::read_config(\%settings)) {
969                 main::logit "Defaults from $settings{xppconf}";
970         } else {
971                 main::logit "No defaults file, use hard-coded defaults.";
972         }
973 }
974
975 sub soft_reset() {
976         write_reg('*', 1, 0x03);                # RESET
977 }
978
979 # Try to identify which slics are valid
980 sub check_slics() {
981         my @slics;
982         main::debug "check_slics()";
983         foreach my $slic (0 .. 7) {
984                 my $value = read_reg($slic, 0, 'D');
985                 #main::logit sprintf "Slic($slic): RD 00 0x%X\n", $value;
986                 next if($value != 0xC3);
987                 write_reg($slic, 14, 0x40);
988                 $value = read_reg($slic, 14, 'D');
989                 #main::logit sprintf "Slic($slic): RD 14 0x%X\n", $value;
990                 next if($value != 0x40);
991                 $value = read_reg($slic, 3, 'D') & 0x1F;
992                 #main::logit sprintf "Slic($slic): RD 03 0x%X\n", $value;
993                 push(@slics, $slic) if $value == 0x1F;
994         }
995         main::logit "Found " . scalar(@slics) . " SLICS (@slics)";
996         return @slics;
997 }
998
999 sub load_custom_preset($) {
1000         my $slics_ref = shift;
1001         my @slics = @{ $slics_ref };
1002         my $slic;
1003
1004         main::debug "Loading patch based on si3226x_patch_C_TSS_ISO_2014JUN18.c";
1005         foreach $slic (@slics) {
1006                 FXS::set_user_mode($slic, 1);           # Turn on user mode
1007         }
1008         write_ram('*',  755, 0x00050000, 3);    #RTPER
1009         write_ram('*',  844, 0x7EFE000, 3);     #RINGFR = 20Hz
1010         write_ram('*',  845, 0x00208847, 3);    #RINGAMP = 53 Vrms open circuit with 100ohm ring impedance
1011         write_ram('*',  846, 0x00000000, 3);    #RINGPHAS
1012         write_ram('*',  843, 0x00000000, 3);    #RINGOF
1013         write_ram('*',  637, 0x15E5200E, 3);    #SLOPE_RING (100.000 ohms)
1014         write_ram('*',  848, 0x007B9068, 3);    #RTACTH (68.236 mA)
1015         write_ram('*',  847, 0x0FFFFFFF, 3);    #RTDCTH (450.000 mA) */
1016         write_ram('*',  850, 0x00006000, 3);    #RTACDB (75.000 ms)
1017         write_ram('*',  849, 0x00006000, 3);    #RTDCDB (75.000 ms)
1018         write_ram('*',  753, 0x00C49BA0, 3);    # VOV_RING_BAT (12.000 v)
1019         write_ram('*',  896, 0x00000000, 3);    # VOV_RING_GND (0.000 v)
1020         write_ram('*',  975, 0xE49BA5, 3);#vov_ring_bat_max = ~14V
1021
1022         write_reg('*',   39, 0x80);             #RINGTALO
1023         write_reg('*',   40, 0x3E);             #RINGTAHI
1024         write_reg('*',   41, 0x00);             #RINGTILO
1025         write_reg('*',   42, 0x7D);             #RINGTIHI
1026         write_reg('*',   38, 0x80);             #RINGCON Both timers are disabled; enable LPR
1027         write_ram('*',  483, 0x28C000, 3);#delta_vcm: This means ring side needs 2v extra.
1028         write_ram('*',  973, 0xFFFFFF, 3);# slope_vov_dcdc
1029         write_ram('*',  974, 0xA18937, 3);# vov_dcdc_os = ~10v
1030         write_ram('*',  509, 0x00C49BA0, 3);# VOV_RING_BAT (12.000 v)
1031         write_ram('*',  975, 0xE49BA5, 3);#vov_ring_bat_max = ~14V
1032         write_ram('*',  971, 0x2A00000, 3);# scale for LPR amplitude, full scale 28-bit
1033         write_ram('*',  972, 0x61EB80, 3);# 6v CM offset
1034         write_ram('*',  970, 0x800000, 3);#
1035
1036
1037 # DC_FEED:
1038         write_ram('*', 634, 0x1C8A024C, 3);     # SLOPE_VLIM
1039         write_ram('*', 635, 0x1E3081AA, 3);     # SLOPE_RFEED
1040         write_ram('*', 636, 0x0040A0E0, 3);     # SLOPE_ILIM
1041         write_ram('*', 638, 0x1B27130B, 3);     # SLOPE_DELTA1
1042         write_ram('*', 639, 0x1DD87A3E, 3);     # SLOPE_DELTA2
1043         write_ram('*', 640, 0x034A1036, 3);     # V_VLIM (28.000 v)
1044         write_ram('*', 641, 0x03A446AC, 3);     # V_RFEED (31.000 v)
1045         write_ram('*', 642, 0x034A0E48, 3);     # V_ILIM  (28.000 v)
1046         write_ram('*', 643, 0x01363429, 3);     # CONST_RFEED (15.000 mA)
1047         write_ram('*', 644, 0x0045CBC2, 3);     # CONST_ILIM = 15 mA
1048         write_ram('*', 645, 0x00222A30, 3);     # I_VLIM = 0.000 mA
1049         write_ram('*', 853, 0x005B0AFB, 3);     # LCRONHK (10.000 mA)
1050         write_ram('*', 852, 0x006D4060, 3);     # LCROFFHK (12.000 mA)
1051         write_ram('*', 701, 0x00008000, 3);     # LCRDBI (5.000 ms)
1052         write_ram('*', 858, 0x0048D595, 3);     # LONGHITH (8.000 mA)
1053         write_ram('*', 859, 0x003FBAE2, 3);     # LONGLOTH (7.000 mA)
1054         write_ram('*', 702, 0x00008000, 3);     # LONGDBI (5.000 ms)
1055         write_ram('*', 854, 0x000F0000, 3);     # LCRMASK (150.000 ms)
1056         write_ram('*', 855, 0x00080000, 3);     # LCRMASK_POLREV (80.000 ms)
1057         write_ram('*', 856, 0x00140000, 3);     # LCRMASK_STATE (200.000 ms)
1058         write_ram('*', 857, 0x00140000, 3);     # LCRMASK_LINECAP (200.000 ms)
1059         write_ram('*', 748, 0x01BA5E35, 3);     # VCM_OH (27.000 v)
1060         write_ram('*', 752, 0x0051EB85, 3);     # VOV_BAT (5.000 v)
1061         write_ram('*', 751, 0x00415F45, 3);     # VOV_GND (3.990 v)
1062
1063         write_reg('*', 46, 0x04);       # zcal_en
1064         write_reg('*', 23, 0x10);       # DTMF_EN = 1  Enable Interupts in IRQ2 Register 19
1065         write_reg('*', 24, 0x03);       # P_HVIC_IE = 1, P_THERM_IE = 1  Enable Interupts in IRQ3 Register 20
1066
1067         write_reg('*', 66, 0x00);       # USERSTAT
1068         write_reg('*', 71, 0x00);       # DIAG1
1069         write_ram('*', 799, 95 * 1074 * 1000, 3);    #PRAM_VBATH_NEON = -95 V
1070         write_ram('*', 786, 70 * 65536, 3);    #PRAM_LCRMASK_MWI = 70 mSec
1071
1072         foreach $slic (@slics) {
1073                 FXS::set_linefeed($slic, 1);
1074         }
1075         write_ram('*', 918, 0x36000, 3);
1076
1077         foreach $slic (@slics) {
1078                 FXS::set_user_mode($slic, 1);           # Turn on user mode
1079         }
1080         write_ram('*', 1018, 0x03000000, 3);    # LKG_OFHK_OFFSET
1081         write_ram('*', 1017, 0x05000000, 3);    # LKG_LB_OFFSET
1082
1083         foreach $slic (@slics) {
1084                 if (($slic & 0x01) == 0) {
1085                         FXS::set_linefeed($slic, 0);
1086                         write_ram($slic, 1538, 0x00600000, 3);
1087                 } else {
1088                         write_ram($slic & 0xFE, 1538, 0x00400000, 3);
1089                 }
1090                 FXS::set_user_mode($slic, 0);           # Turn off user mode
1091         }
1092 }
1093
1094 sub configure_pcm($) {
1095         my $slic = shift;
1096         main::debug "Configure_pcm()";
1097         my $pcm_offset = $slic * 8;
1098         write_reg($slic, 12, $pcm_offset);      #PCMTXLO
1099         write_reg($slic, 13, 0x00);             #PCMTXHI
1100         write_reg($slic, 14, $pcm_offset);      #PCMTXLO
1101         write_reg($slic, 15, 0x00);             #PCMTXHI
1102
1103         write_reg($slic, 11, 0x11);             #PCMMODE, u-Law
1104
1105 #       write_reg($slic, 43, 0x00);             #LOOPBACK
1106 #       write_reg($slic, 44, 0x00);             #DIGCON
1107 }
1108
1109 sub set_linefeed($$) {
1110         my $slic = shift;
1111         my $lfd = shift;
1112         write_reg($slic, 30, $lfd);             #LINEFEED
1113 }
1114
1115 sub overwrite_ring_registers() {
1116 }
1117
1118 package main;
1119
1120 main::logit "Starting '$0' (@SlicNums)\n";
1121
1122 FXS::read_defaults();
1123 FXS::soft_reset();
1124 @SlicNums = FXS::check_slics();
1125 FXS::init_early();
1126 FXS::load_patch(\@SlicNums);
1127 FXS::load_general_params(\@SlicNums);
1128
1129 if($settings{fxs_skip_calib}) {
1130         main::logit "==== WARNING: SKIPPED SLIC CALIBRATION =====";
1131 } else {
1132         FXS::calibrate_slics(0x00, 0x00, 0x01);
1133         main::mysleep(0.060);
1134         FXS::dc_powerup(\@SlicNums);
1135         FXS::calibrate_slics(0x00, 0xC0, 0x18); # remaining cals (except mads, lb)
1136         main::mysleep(0.700);
1137         foreach my $slic (@SlicNums) {
1138                 FXS::set_linefeed($slic, 0);
1139                 FXS::set_linefeed($slic, 1);
1140         }
1141         main::mysleep(1.000);
1142
1143 }
1144 FXS::load_custom_preset(\@SlicNums);
1145 foreach my $slic (@SlicNums) {
1146         FXS::configure_pcm($slic);
1147         FXS::set_linefeed($slic, 1);
1148 }
1149
1150 set_output;
1151 while(<DATA>) {
1152         chomp;
1153         s/[#;].*$//;            # remove comments
1154         s/^\s+//;               # trim whitespace
1155         s/\s+$//;               # trim whitespace
1156         s/\t+/ /g;              # replace tabs with spaces (for logs)
1157         next unless /\S/;       # Skip empty lines
1158         main::debug "writing: '$_'";
1159         print "$_\n";
1160 }
1161 close REG;
1162 FXS::overwrite_ring_registers();
1163
1164 main::debug "Ending '$0'";
1165 close STDERR;
1166 exit 0;
1167
1168 # ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
1169
1170 __DATA__