This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5728: Pin configuration script

Part Number: AM5728

Hi,

I have some questions for " am57xx_generate_pin_config_data.pl " written in  SPRAC44.

Please see the below.

1) What is "am57xx_generate_pin_config_data.pl" script file? According to the sparc44, it is written in the below.

Custom IO Delay Output Conversion Script for U-boot: The u-boot bootloader includes a perl script
that takes the generic output from the PinMux tool (genericFileFormatPadConf.txt and
genericFileFormatIOdelay.txt) and makes it usable in u-boot. This script
(am57xx_generate_pin_config_data.pl) is available in Appendix B. Usage notes are included in
Appendix C. These notes describe how to run the script, and where to include the generated .h files in the
u-boot source.

As you know, when customer uses Manual IO Timing Modes,  customer must calculate values to be set in the CFG_x_IN, CFG_x_OEN and CFG_c_OUT registers by using A_DELAY and G_DELAY seeds. Is this pearl script to calculate values of CFG register?

2) If the above my understanding is correct, how do I use this script? Also, according to E2E (https://e2e.ti.com/support/arm/sitara_arm/f/791/p/555288/2030921) , this script seems to be some issues. Is this script no problem?

3) My customer has some files made by PMT.

PinmuxConfigSummary.csv

genericFileFormatPadConf.txt

generifFileFormatIOdelay.txt

boardPadDelayTune.h

boardPadDelayInit.c

boardPadDelayDevice.c

boardPadDelay.h

Are these files needed for pl script? My customer does not use Linux OS. Does customer have to calculate values of CFG register by themselves?

Please advise me.

I appreciate your quick reply.

Best regards,

Michi

  • The Pinmux team have been notified. They will respond here.
  • Hi Michi,

    Michi Yama said:
    What is "am57xx_generate_pin_config_data.pl" script file?

    It's just a script that reformats the generic format from pinmux into uboot friendly format. 

    Michi Yama said:
    Is this pearl script to calculate values of CFG register?

    No, it exports the A/G delay parameters that are needed for the calculation. Each die has its precise personal coarse/fine elements that need to be read from each chip.

    Michi Yama said:
    2) If the above my understanding is correct, how do I use this script? Also, according to E2E (https://e2e.ti.com/support/arm/sitara_arm/f/791/p/555288/2030921) , this script seems to be some issues. Is this script no problem?

    I will reply in that thread as well... I don't see any issues with the script. Attached the script itself for your convenience and also a sample uboot output file just generated from the genericFileFormat files (I just clicked on a bunch of peripheral in pinmux GUI)

    #!/usr/bin/perl -w
    #
    # (C) Copyright 2016
    # Texas Instruments, <ti.com>#
    # SPDX-License-Identifier:      GPL-2.0+
    #
    
    use strict;
    use warnings;
    use Getopt::Std;
    
    #---------------------------------------- Data
    my %options = ();
    my $iodelay_file;
    my $padconf_file;
    my $output_format;
    my %iodelay_array;
    my %iopad_array;
    
    # For New operations: update the two arrays
    my %operations_help = (
    	iopad =>	  "Generate IO Pad header data",
    	iodelay =>	  "Generate IO Delay header data",
    );
    my %operations_array = (
    	iopad   => \&operation_iopad,
    	iodelay => \&operation_iodelay,
    );
    
    #---------------------------------------- Main flow
    getopts( "hp:d:o:", \%options );
    
    if ( $options{h} ) {
    	do_help("Usage:");
    }
    
    $iodelay_file  = $options{d} if defined $options{d};
    $padconf_file  = $options{p} if defined $options{p};
    $output_format = $options{o} if defined $options{o};
    
    # check for sanity
    do_help("Error: Missing file parameters!")
      if !defined $iodelay_file && !defined $padconf_file;
    do_help("Error: Missing output format!") if !defined $output_format;
    do_help("Error: iodelay file '$iodelay_file' is not readable")
      if defined $iodelay_file && !-r "$iodelay_file";
    do_help("Error: padconf file '$padconf_file' is not readable")
      if defined $padconf_file && !-r "$padconf_file";
    do_help("Error: Unknown Output format '$output_format'")
      if !exists( $operations_array{$output_format} );
    
    # read input files
    do_read_iopad($padconf_file)   if defined $padconf_file;
    do_read_iodelay($iodelay_file) if defined $iodelay_file;
    
    # Now, execute the corresponding operation
    $operations_array{$output_format}->();
    
    exit 0;
    
    #---------------------------------------- Subroutines
    
    # Help subroutine.. uses the argument of some error or print message..
    sub do_help
    {
    	my $operation;
    
    	print "@_\n";
    	print "$0 [-h] -p padconf_file -d iodelay_file -o output_format\n";
    	print "Where";
    	print "\t-h provides this help text\n";
    	print
    "\t-p padconf_file is the generic pad config output file provided by PMT(PinMux Tool)\n";
    	print
    "\t-d iodelay_file is the generic iodelay output file provided by PMT(PinMux Tool)\n";
    	print "\t-o output_format , where output_format is one of:\n";
    
    	foreach $operation ( keys %operations_array ) {
    		print "\t\t $operation - $operations_help{$operation}\n";
    	}
    	exit 0;
    }
    
    # read into an associative array of array indexed by register address
    # allows us to do operations and offsets and sorts. unfortunately with ballname,
    # we dont have exactly an unique key considering that multiple idoelay registers
    # have the same ballname
    sub do_read_file
    {
    	my $file  = $_[0];
    	my $iopad = $_[1];
    	my $fh;
    	my $row;
    	my @iopad_row;
    	my $register;
    	my $skip = 0;
    
    	open( $fh, '<', $file )
    	  or do_help("Error: unable to open IOPAD $file for read");
    
    	while ( $row = <$fh> ) {
    
    		chomp($row);
    
    		# get rid of commented lines including single line and multiline
    		next if $skip == 1;
    		if ( $row =~ /\/\*/ ) { $skip = 1 if !$row =~ /\*\//; next; }
    		if ( $row =~ /\*\// ) { $skip = 0; next; }
    
    		# get rid of Empty lines
    		next if $row =~ /^$/;
    
    		# Now, Human readable to CSV
    		$row =~ s/\s\s*/,/g;
    		@iopad_row = split( ',', $row );
    		$register  = $iopad_row[0];
    		@iopad_row = splice @iopad_row, 1, $#iopad_row;
    		if ($iopad) {
    			$iopad_array{$register} = [@iopad_row];
    		} else {
    			$iodelay_array{$register} = [@iopad_row];
    		}
    	}
    
    	close($fh);
    }
    
    # tiny lil wrapper
    sub do_read_iopad
    {
    	do_read_file( $_[0], 1 );
    }
    
    # tiny lil wrapper
    sub do_read_iodelay
    {
    	do_read_file( $_[0], 0 );
    }
    
    #---- the various operations----
    sub operation_iopad()
    {
    	my $register;
    
    	do_help("Error: I need iodelay file for this option")
    	  if !defined $iodelay_file;
    	do_help("Error: I need padconf file for this option")
    	  if !defined $padconf_file;
    
    	foreach $register ( sort keys %iopad_array ) {
    		my @val;
    		my $reg_val;
    		my $reg_name;
    		my $ball_name;
    		my $mux0;
    		my $mux;
    		my $reg_dec;
    		my $slew_control;
    		my $input_en;
    		my $pull_active;
    		my $pull_up;
    		my $compare_val;
    		my $compare_hex;
    		my $val_mux0_name;
    		my $val_mux_mode;
    		my $val_pull;
    		my $val_delay_mode;
    		my $val_virtual_mode;
    		my $val_manual_mode;
    
    		@val = @{ $iopad_array{$register} };
    
    # register_address(hex)        register_value(hex)     ball_name(string)       register_name(string)   mux_mode0_name(string)  muxed_mode_name(string)
    		( $reg_val, $ball_name, $reg_name, $mux0, $mux ) = @val;
    
    		$reg_dec = hex($reg_val);
    
    		#pulls and mux mode
    		$slew_control = $reg_dec & ( 1 << 19 );
    		$input_en     = $reg_dec & (1 << 18 );
    		$pull_up      = $reg_dec & (1 << 17 );
    		$pull_active  = $reg_dec & (1 << 16 );
    		$compare_val = $slew_control | $input_en | $pull_up | $pull_active;
    		$compare_hex = sprintf( "0x%08x", $compare_val );
    		if ( $compare_hex =~ /0x00010000/ ) { $val_pull = "PIN_OUTPUT"; }
    		elsif ( $compare_hex =~ /0x00030000/ ) {
    			$val_pull = "PIN_OUTPUT";
    		} elsif ( $compare_hex =~ /0x00020000/ ) {
    			$val_pull = "PIN_OUTPUT_PULLUP";
    		} elsif ( $compare_hex =~ /0x00000000/ ) {
    			$val_pull = "PIN_OUTPUT_PULLDOWN";
    		} elsif ( $compare_hex =~ /0x00080000/ ) {
    			$val_pull = "PIN_OUTPUT_PULLDOWN | SLEWCONTROL";
    		} elsif ( $compare_hex =~ /0x00050000/ ) {
    			$val_pull = "PIN_INPUT";
    		} elsif ( $compare_hex =~ /0x000c0000/ ) {
    			$val_pull = "PIN_INPUT_SLEW";
    		} elsif ( $compare_hex =~ /0x00060000/ ) {
    			$val_pull = "PIN_INPUT_PULLUP";
    		} elsif ( $compare_hex =~ /0x00040000/ ) {
    			$val_pull = "PIN_INPUT_PULLDOWN";
    		} elsif ( $compare_hex =~ /0x000e0000/ ) {
    			$val_pull = "PIN_INPUT_PULLUP | SLEWCONTROL";
    		}
    
    		# Uggh.. unknown definition?
    		else { $val_pull = $compare_hex; }
    
    		# virtual mode definition
    		$val_virtual_mode = ( $reg_dec >> 4 ) & 15;
    		$val_delay_mode = "MODESELECT" if $reg_dec & (1 << 8 );
    
    		# Am i Manual mode with VIRTUAL_MODE0 ?
    		if ( defined $val_delay_mode && $val_virtual_mode == 0 ) {
    			my $iodr;
    
    			#This could be manual mode!
    			foreach $iodr ( keys %iodelay_array ) {
    				my @iodv;
    				my $iod_a_delay;
    				my $iod_g_delay;
    				my $iod_reg_name;
    				my $iod_ball;
    				my $na = "N/A";
    
    				@iodv = @{ $iodelay_array{$iodr} };
    				( $iod_a_delay, $iod_g_delay, $iod_reg_name, $iod_ball ) =
    				  @iodv;
    				if ( !$ball_name =~ /$iod_ball/ ) { next; }
    				if ( $iod_a_delay =~ /$na/ && $iod_g_delay =~ /$na/ ) { next; }
    
    				# if either one is defined, we are manual mode
    				$val_manual_mode = "MANUAL_MODE";
    			}
    
    		}
    
    		# mux mode
    		$val_mux_mode = $reg_dec & 15;
    
    		# register defines is mux_mode0 name
    		# CTRL_CORE_PAD_GPMC_AD0 -> is GPMC_AD0
    		$val_mux0_name = substr $reg_name, 14;
    		print "\{$val_mux0_name, (M$val_mux_mode | $val_pull";
    		if ( defined $val_delay_mode ) {
    			if ( defined $val_manual_mode ) {
    				print " | $val_manual_mode";
    			} else {
    				printf " | VIRTUAL_MODE$val_virtual_mode";
    			}
    		}
    		printf(")},\t/* $mux0.$mux */\n");
    	}
    }
    
    sub operation_iodelay()
    {
    	my $register;
    	my @val;
    
    	do_help("Error: I need iodelay file for this option")
    	  if !defined $iodelay_file;
    
    	foreach $register ( sort keys %iodelay_array ) {
    		my @iodv;
    		my $iodelay_base = 0x4844A000;
    		my $reg_dec;
    		my $offset;
    		my $iod_a_delay;
    		my $iod_g_delay;
    		my $iod_reg_name;
    		my $iod_ball;
    		my $na = "N/A";
    		my $val_a;
    		my $val_g;
    		my $val_offset;
    
    		@iodv = @{ $iodelay_array{$register} };
    		( $iod_a_delay, $iod_g_delay, $iod_reg_name, $iod_ball ) = @iodv;
    		next if $iod_a_delay =~ /$na/ && $iod_g_delay =~ /$na/;
    		if ( $iod_a_delay =~ /$na/ ) {
    			$val_a = 0;
    		} else {
    			$val_a = $iod_a_delay;
    		}
    		if ( $iod_g_delay =~ /$na/ ) {
    			$val_g = 0;
    		} else {
    			$val_g = $iod_g_delay;
    		}
    		$reg_dec    = hex($register);
    		$offset     = $reg_dec - $iodelay_base;
    		$val_offset = sprintf( "0x%04X", $offset );
    		print "{$val_offset, $val_a, $val_g},\t/* $iod_reg_name */\n";
    	}
    }

    padconf.h

    Michi Yama said:
    Are these files needed for pl script? My customer does not use Linux OS. Does customer have to calculate values of CFG register by themselves?

    No, these files are for the PDK so not needed by you then.

    Thanks,

    Alex

  • Dear Alex-san,

    Thank you for your quick reply. It is very helpful for me.

    Please let me ask more questions.

    You said that the script file exports the A/G delay parameters that are needed for the calculation. Are these exported A/G delay parameters same as A_DELAY and G_DELAY values described in AM5728 data manual?
    And, customer must calculate the value for CFG registers by themselves? Isn't there any source code for calculation?

    I appreciate your quick reply again.

    Best regards,
    Michi
  • Hi Michi-san,

    Michi Yama said:
    Are these exported A/G delay parameters same as A_DELAY and G_DELAY values described in AM5728 data manual?

     

    Correct, the same A_DELAY and G_DELAY described in data manual, and also in the formula described in TRM subsection "18.4.6.1.6 Manual IO Timing Modes".

    Michi Yama said:
    And, customer must calculate the value for CFG registers by themselves? Isn't there any source code for calculation?

    Well yes, this needs to be done for each chip. Sample source code is not in my scope. We will ping SW team for comments if there is any available. 

    Thanks,

    Alex

     

  • Dear Alex-san,

    Thank you for your support.

    You said "Sample source code is not in my scope. We will ping SW team for comments if there is any available. "

    Have you had the comment of SW team? My customer says, the sample source code should be offered from TI.
    As you said, each die has its precise personal coarse/fine elements that need to be read from each chip. For this, source code is
    needed.

    I know many customer uses AM57xx device. How do they achieve this without sample source code? If processor SDK support it, please let me know its code.

    Best regards,
    Michi
  • Hi Michi-san,

    Thanks for reminding, I haven't received feedback yet. I will re-ping the SW team again. 

    Thanks

    Alex

  • Hi Michi,

    Not sure what you mean by sample code.
    The drivers that take care of the pinctrl settins & the pinctrl IODelay settings are:
    drivers/pinctrl/pincrtl-single.c
    drivers/pinctrl/pinmux.c
    drivers/pinctrl/pinctrl-ti-iodelay.c

    Best Regards,
    Yordan