skip pins missing from pintctrl
[linux-gpio-pinout] / gpio.pl
diff --git a/gpio.pl b/gpio.pl
index 5395ac5..3a31ade 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
@@ -79,7 +81,7 @@ while(<DATA>) {
 
 if ( ! $opt_pins && ! $pins ) {
        my $glob = $model;
-       my $glob =~ s/^(\w+).*$/$1/;
+       $glob =~ s/^(\w+).*$/$1/;
        my @pins = glob "pins/${glob}*";
        warn "# possible pins: ",dump( \@pins );
        $opt_pins = $pins[0];
@@ -158,6 +160,45 @@ 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;
@@ -167,10 +208,42 @@ while(<$pio>) {
        # 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);
+       annotate_pin $pin, join(' ',@p) if ! $opt_svg;
 }
 close($pio);
 
+} # have_sunxi_pio
+
+
+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;
 
@@ -373,8 +446,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 ) {