added gpio-ir-tx for IR board from RM Mini 3
[linux-gpio-pinout] / gpio.pl
diff --git a/gpio.pl b/gpio.pl
index 99134ac..99e1703 100755 (executable)
--- a/gpio.pl
+++ b/gpio.pl
@@ -17,6 +17,7 @@ my $opt_lines = 0;
 my $opt_read = '';
 my $opt_pins = '';
 my $opt_color = 0;
+my $opt_pinmux = 0;
 GetOptions(
        'svg!' => \$opt_svg,
        'alt!' => \$opt_alt,
@@ -30,6 +31,7 @@ GetOptions(
        'read=s' => \$opt_read,
        'pins=s' => \$opt_pins,
        'color' => \$opt_color,
+       'pinmux' => \$opt_pinmux,
 );
 
 # svg font hints
@@ -45,28 +47,37 @@ sub slurp {
 }
 
 my $pins;
+my $include = 0;
 
 my $model = slurp('/proc/device-tree/model');
 $model =~ s/\x00$//; # strip kernel NULL
 warn "# model [$model]";
+if ( $opt_pins ) {
+       $model = $opt_pins;
+       $model =~ s/^.*\///; # strip dir
+       $model =~ s/\..+$//; # strip extension
+       $include = 1;
+       warn "# $opt_pins model [$model] $include";
+}
+warn "# $opt_pins model [$model] $include";
 
+OPEN_PINS_AGAIN:
 open(DATA, '<', $opt_pins) if $opt_pins;
 
 my @lines;
 my $line_i = 0;
 
-my $include = 0;
 while(<DATA>) {
        chomp;
        if ( m/^#\s(.+)/ ) {
-               warn "MODEL [$1] == [$model] ?\n";
                if ( $model =~ m/$1/ ) {
                        $include = 1;
                } else {
                        $include = 0;
                }
-       } elsif ( $include || $opt_pins ) {
-               push @{ $pins->{$1} }, $line_i while ( m/\t(\w+\d+)/g );
+               warn "MODEL [$1] == [$model] include: $include\n";
+       } elsif ( $include ) {
+               push @{ $pins->{$1} }, $line_i while ( m/\t\s*(\w+\d+)/g );
 
                push @lines, $_;
 
@@ -76,6 +87,16 @@ while(<DATA>) {
        }
 }
 
+if ( ! $opt_pins && ! $pins ) {
+       my $glob = $model;
+       $glob =~ s/^(\w+).*$/$1/;
+       my @pins = glob "pins/${glob}*";
+       die "pins/${glob} NOT FOUND for this board, please create one and contribute" unless @pins;
+       warn "# possible pins: ",dump( \@pins );
+       $opt_pins = $pins[0];
+       goto OPEN_PINS_AGAIN;
+}
+
 die "add pin definition for # $model" unless $pins;
 
 #warn "# lines ",dump( \@lines );
@@ -97,6 +118,24 @@ my $device;
 my $pin;
 my $function;
 
+sub annotate_pin {
+       my ($pin, $note) = @_;
+       if ( $pins->{$pin} ) {
+               foreach my $line ( @{$pins->{$pin}} ) {
+                       my $t = $lines[$line];
+                       if ( $opt_svg ) {
+                               $t =~ s/$pin/$note/;
+                       } else {
+                               $t =~ s/$pin/$pin $note/ || warn "can't find $pin in [$t]";
+                       }
+                       $lines[$line] = $t;
+                       warn "# $line: $lines[$line]\n";
+               }
+       } else {
+               warn "IGNORED: pin $pin function $note\n";
+       }
+}
+
 open(my $fh, '<', $opt_read . '/sys/kernel/debug/pinctrl/pinctrl-maps');
 while(<$fh>) {
        chomp;
@@ -116,21 +155,7 @@ while(<$fh>) {
                if ( $device && $pin && $function ) {
                        push @{ $pin_function->{$pin} }, "$device $function";
 
-                       if ( $pins->{$pin} ) {
-                               foreach my $line ( @{$pins->{$pin}} ) {
-                                       my $t = $lines[$line];
-                                       if ( $opt_svg ) {
-                                               $t =~ s/$pin/[$device $function]/;
-                                       } else {
-                                               $t =~ s/$pin/$pin [$device $function]/ || warn "can't find $pin in [$t]";
-                                       }
-                                       $lines[$line] = $t;
-                                       warn "# $line: $lines[$line]\n";
-                               }
-                       } else {
-                               warn "IGNORED: pin $pin function $function\n";
-                       }
-
+                       annotate_pin $pin, "[$device $function]";
                } else {
                        warn "missing one of ",dump( $device, $pin, $function );
                }
@@ -144,6 +169,118 @@ while(<$fh>) {
 
 warn "# pin_function = ",dump($pin_function);
 
+
+# insert kernel gpio info
+my $linux_gpio_name;
+open(my $pins_fh, '<', (glob "/sys/kernel/debug/pinctrl/*/pins")[0]);
+while(<$pins_fh>) {
+       if ( m/^pin (\d+) \(([^\)]+)\)/ ) {
+               $linux_gpio_name->{$1} = $2;
+       }
+}
+warn "# linux_gpio_name = ",dump( $linux_gpio_name );
+
+
+my $gpio_debug;
+open(my $gpio_fh, '<', '/sys/kernel/debug/gpio');
+while(<$gpio_fh>) {
+       if (m/|/ ) {
+               s/^\s+//;
+               s/\s+$//;
+               my @l = split(/\s*[\(\|\)]\s*/, $_);
+               warn "XXX ", dump( \@l );
+               if ( $l[0] =~ m/gpio-(\d+)/ ) {
+                       if ( my $pin = $linux_gpio_name->{$1} ) {
+                               $gpio_debug->{ $pin } = $l[2];
+                               $l[3] =~ s/\s\s+/ /g;
+                               annotate_pin $pin, qq{"$l[2]" $l[3]};
+                       } else {
+                               warn "FIXME can't find $1 in ",dump( $linux_gpio_name );
+                       }
+               }
+       }
+
+}
+warn "# gpio_debug = ",dump( $gpio_debug );
+
+
+
+my $have_sunxi_pio = `which sunxi-pio`;
+if ( $have_sunxi_pio ) {
+
+open(my $pio, '-|', 'sunxi-pio -m print');
+while(<$pio>) {
+       chomp;
+       s/[<>]+/ /g;
+       my @p = split(/\s+/,$_);
+       warn "# pio ",dump(\@p);
+       # annotate input 0 and output 1 pins
+#      annotate_pin $p[0], ( $p[1] ? 'O' : 'I' ) . ':' . $p[4] if $p[1] == 0 || $p[1] == 1;
+       my $pin = shift @p;
+       annotate_pin $pin, join(' ',@p) if ! $opt_svg;
+}
+close($pio);
+
+} # have_sunxi_pio
+
+my $have_raspi_gpio = `which raspi-gpio`;
+if ( $have_raspi_gpio ) {
+
+my @gpio_pins;
+
+open(my $pio, '-|', 'raspi-gpio get');
+while(<$pio>) {
+       chomp;
+       if ( m/^\s*GPIO (\d+): (.+)/ ) {
+               my $pin = 'gpio' . $1 * 1; # we need * 1 to strip leading zero
+               push @gpio_pins, $1;
+               annotate_pin $pin, $2 if ! $opt_svg;
+       }
+}
+close($pio);
+
+open(my $pio, '-|', 'raspi-gpio funcs '.join(',',@gpio_pins));
+while(<$pio>) {
+       chomp;
+       s/,\s/ /g;
+       if (m/^(\d+)\s+(.*)/) {
+               annotate_pin 'gpio'.$1,"($2)" if $opt_alt;
+       }
+}
+close($pio);
+
+} # have_raspi_gpio
+
+
+my $pinmux;
+my $pinmux_path = (glob("/sys/kernel/debug/pinctrl/*/pinmux-functions"))[0];
+if ( $opt_pinmux && -e $pinmux_path ) {
+       open(my $mux, '<', $pinmux_path);
+       while(<$mux>) {
+               chomp;
+               if ( m/function: (\w+), groups = \[ (.*) \]/ ) {
+                       my ( $func, $pins ) = ( $1, $2 );
+                       foreach ( split(/\s+/,$pins) ) {
+                               push @{ $pinmux->{$_} }, $func;
+                       }
+               } else {
+                       warn "IGNORED [$pinmux_path] [$_]\n";
+               }
+       }
+
+       foreach my $pin ( keys %$pinmux ) {
+               if ( exists $pins->{$pin} ) {
+                       annotate_pin $pin, '{' . join(' ', @{$pinmux->{$pin}}) . '}';
+               } else {
+                       warn "IGNORED mux on $pin\n";
+               }
+       }
+
+       warn "# pinmux = ",dump( $pinmux );
+}
+
+
+
 my @max_len = ( 0,0,0,0 );
 my @line_parts;
 
@@ -346,8 +483,37 @@ sub line {
 
 my $last_cut_mark = 0;
 
+sub connector {
+       my ( $from, $to ) = @_;
+       warn "# connector $from - $to ",dump( $line_parts[$from], $line_parts[$to] );
+       if ( $opt_vertical ) {
+               foreach my $i ( 0 .. int(($to-$from)/2) ) {
+                       my $t = $line_parts[$from + $i];
+                               $line_parts[$from + $i] = $line_parts[$to - $i];
+                                                         $line_parts[$to - $i] = $t;
+               }
+       }
+}
+
+my $from;
+my $to;
+foreach my $i ( 0 .. $#line_parts ) {
+       next if $line_parts[$i]->[0] =~ m/^###/;
+       if (exists $line_parts[$i]->[1]) {
+               if (! $from) {
+                       $from = $i;
+               } else {
+                       $to = $i;
+               }
+       } elsif ($from && $to) {
+               connector $from => $to;
+               $from = $to = undef;
+       }
+}
+connector $from => $to if $from && $to;
+
 foreach my $i ( 0 .. $#line_parts ) {
-       $i = $#line_parts - $i if $opt_vertical;
+#      $i = $#line_parts - $i if $opt_vertical;
        my $line = $line_parts[$i];
 
        if ( $opt_svg ) {
@@ -440,118 +606,6 @@ if ( $opt_svg ) {
 
 }
 
+# you can add pin definitions below, but they should go into pins/
 __DATA__
-# Cubietech Cubieboard
-## U14 (Next to SATA connector)
-###    SPI0
-48     PI13 (SPI0-MISO/UART6-RX/EINT25)        47      PI11 (SPI0-CLK/UART5-RX/EINT23)
-46     PI12 (SPI0-MOSI/UART6-TX/EINT24)        45      PI10 (SPI0-CS/UART5-TX/EINT22)
-###    LCD
-44     3.3V (nc in 2012-08-08)                 43      VCC-5V
-42     Ground                                  41      SPDIF
-40     PB10 (LCD0-SCK/LCD-PIO1)                39      PB11 (LCD0-SDA/LCD-PIO2)
-38     Ground                                  37      PH7 (LCD0-BL-EN/LCD-PIO0/UART5-RX/EINT7)
-36     XN_TP (TP-X2)                           35      YN_TP (TP-Y2)
-34     XP_TP (TP-X1)                           33      YP_TP (TP-Y1)
-32     PD25 (LCDDE)                            31      PB2 (PWM0)
-30     PD26 (LCDHSYNC/VGA-HSYNC)               29      PD24 (LCDCLK)
-28     PD23 (LCDD23)                           27      PD27 (LCDVSYNC/VGA-VSYNC)
-26     PD21 (LCDD21)                           25      PD22 (LCDD22)
-24     PD19 (LCDD19/LVDS1N3)                   23      PD20 (LCDD20)
-22     PD17 (LCDD17/LVDS1NC)                   21      PD18 (LCDD18/LVDS1P3)
-20     Ground                                  19      PD16 (LCDD16/LVDS1PC)
-18     PD14 (LCDD14/LVDS1P2)                   17      PD15 (LCDD15/LVDS1N2)
-16     PD12 (LCDD12/LVDS1P1)                   15      PD13 (LCDD13/LVDS1N1)
-14     PD10 (LCDD10/LVDS1P0)                   13      PD11 (LCDD11/LVDS1N0)
-12     PD8 (LCDD8/LVDS0P3)                     11      PD9 (LCDD9/LVDS0N3)
-10     PD7 (LCDD7/LVDS0NC)                     9       Ground
-8      PD5 (LCDD5/LVDS0N2)                     7       PD6 (LCDD6/LVDS0PC)
-6      PD3 (LCDD3/LVDS0N1)                     5       PD4 (LCDD4/LNVS0P2)
-4      PD1 (LCDD1/LVDS0N0)                     3       PD2 (LCDD2/LVDS0P1)
-2      Ground                                  1       PD0 (LCDD0/LVDSP0)
-
-## U15 (Between Ethernet port and USB ports)
-### CSI1/TS
-1      VCC-5V                                  2       PH15 (CSI1-PWR/EINT15)
-3      CSI1-IO-2V8                             4       PH14 (CSI1-RST#/EINT14)
-5      PG0 (CSI1-PCLK/SDC1-CMD)                6       PB18 (TWI1-SCK)
-7      PB19 (TWI1-SDA)                         8       PG3 (CSI1-VSYNC/SDC1-D1)
-9      PG2 (CSI1-HSYNC/SDC1-D0)                10      PG1 (CSI1-MCLK/SDC1-CLK)
-11     PG4 (CSI1-D0/SDC1-D2)                   12      PG5 (CSI1-D1/SDC1-D3)
-13     PG6 (CSI1-D2/UART3-TX)                  14      PG7 (CSI1-D3/UART3-RX)
-15     PG8 (CSI1-D4/UART3-RTS)                 16      PG9 (CSI1-D5/UART3-CTS)
-17     PG10 (CSI1-D6/UART4-TX)                 18      PG11 (CSI1-D7/UART4-RX)
-19     Ground                                  20      Ground
-###    Analog SDIO3
-21     FMINL                                   22      PI4 (SDC3-CMD)
-23     FMINR                                   24      PI5 (SDC3-CLK)
-25     Ground                                  26      PI6 (SDC3-D0)
-27     VGA-R                                   28      PI7 (SDC3-D1)
-29     VGA-G                                   30      PI8 (SDC3-D2)
-31     VGA-B                                   32      PI9 (SDC3-D3)
-###    CSI0/TS
-33     LCD1-VSYNC                              34      PE4 (CSI0-D0)
-35     LCD1-HSYNC                              36      PE5 (CSI0-D1)
-37     Ground                                  38      PE6 (CSI0-D2)
-39     AVCC                                    40      PE7 (CSI0-D3)
-41     LRADC0                                  42      PE8 (CSI0-D4)
-43     CVBS                                    44      PE9 (CSI0-D5)
-45     HPL                                     46      PE10 (CSI0-D6)
-47     HPR                                     48      PE11 (CSI0-D7)
-
-## DEBUG serial (middle of board)
-4      PB22 (UART0-TX)
-3      PB23 (UART0-RX)
-2      VCC-3V3
-1      GND
-
-
-# Lamobo R1
-## CON3 rpi DIP26-254
-1      3.3v                    2       5v     
-3      PB20 SDA.1              4       5V     
-5      PB21 SCL.1              6       0v     
-7      PI3 PWM1                8       PH0 UART3_TX
-9      0v                      10      PH1 UART3_RX
-11     PI19 UART2_RX           12      PH2
-13     PI18 UART2_TX           14      0v     
-15     PI17 UART2_CTS          16      PH21 CAN_RX 
-17     3.3v                    18      PH20 CAN_TX 
-19     PI12 SPI0_MOSI          20      0v     
-21     PI13 SPI0_MISO          22      PI16 UART2_RTS   
-23     PI11 SPI0_SCLK          24      PI10 SPI0_CS0    
-25     0v                      26      PI14 SPI0_CS1
-
-## J13 DIP2-254
-2      PB22 UART0_TX
-1      PB23 UART0_RX
-
-## J12 DIP8-254
-8      GND                     7       GND
-6      PI20 UART7_TX           5       PH3
-4      PI21 UART7_RX           3       PH5
-2      3V3                     1       SATA-5V
-
-# Raspberry Pi
-1      3.3v                    2       5v
-3      gpio2 (SDA.1)           4       5v
-5      gpio3 (SCL.1)           6       0v
-7      gpio4 (WPi 7)           8       gpio14  (TxD)
-9      0v                      10      gpio15  (RxD)
-11     gpio17 (WPi 0)          12      gpio18  (WPi 1)
-13     gpio27 (WPi 2)          14      0v
-15     gpio22 (WPi 3)          16      gpio23  (WPi 4)
-17     3.3v                    18      gpio24  (WPi 5)
-19     gpio10 (MOSI)           20      0v
-21     gpio9 (MISO)            22      gpio25  (WPi 6) 
-23     gpio11 (SCLK)           24      gpio8   (CE0)
-25     0v                      26      gpio7   (CE1)
-# Raspberry Pi 3 Model B Rev 1.2
-27     gpio0 (SDA.0)           28      gpio1   (SCL.0)
-29     gpio5 (WPi 21)          30      0v
-31     gpio6 (WPi 22)          32      gpio12  (WPi 26)
-33     gpio13 (WPi 23)         34      0v
-35     gpio19 (WPi 24)         36      gpio16  (WPi 27)
-37     gpio26 (WPi 25)         38      gpio20  (WPi 28)
-39     0v                      40      gpio21  (WPi 29)