brintos

brintos / linux-shallow public Read only

0
0
Text · 11.4 KiB · 3d3152b Raw
481 lines · plain
1#!/usr/bin/perl -w2# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause3# Copyright (C) 2019--2020 Intel Corporation4 5use Getopt::Long qw(:config no_ignore_case);6use File::Basename;7 8my $ccsregs = "ccs-regs.asc";9my $header;10my $regarray;11my $limitc;12my $limith;13my $kernel;14my $help;15 16GetOptions("ccsregs|c=s" => \$ccsregs,17	   "header|e=s" => \$header,18	   "regarray|r=s" => \$regarray,19	   "limitc|l=s" => \$limitc,20	   "limith|L=s" => \$limith,21	   "kernel|k" => \$kernel,22	   "help|h" => \$help) or die "can't parse options";23 24$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;25 26if (defined $help) {27	print <<EOH28$0 - Create CCS register definitions for C29 30usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]31 32	-c ccs register file33	-e header file name34	-r register description array file name35	-l limit and capability array file name36	-L limit and capability header file name37	-k generate files for kernel space consumption38EOH39	  ;40	exit 0;41}42 43my $lh_hdr = ! defined $kernel44	? '#include "ccs-os.h"' . "\n"45	: "#include <linux/bits.h>\n#include <linux/types.h>\n";46my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32';47my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16';48 49open(my $R, "< $ccsregs") or die "can't open $ccsregs";50 51open(my $H, "> $header") or die "can't open $header";52my $A;53if (defined $regarray) {54	open($A, "> $regarray") or die "can't open $regarray";55}56open(my $LC, "> $limitc") or die "can't open $limitc";57open(my $LH, "> $limith") or die "can't open $limith";58 59my %this;60 61sub is_limit_reg($) {62	my $addr = hex $_[0];63 64	return 0 if $addr < 0x40; # weed out status registers65	return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers66 67	return 1;68}69 70my $uc_header = basename uc $header;71$uc_header =~ s/[^A-Z0-9]/_/g;72 73my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";74my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause";75my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n";76 77for my $fh ($A, $LC) {78	print $fh "// $license\n$copyright$note\n" if defined $fh;79}80 81for my $fh ($H, $LH) {82	print $fh "/* $license */\n$copyright$note\n";83}84 85print $H <<EOF86#ifndef __${uc_header}__87#define __${uc_header}__88 89EOF90  ;91 92print $H <<EOF93#include <linux/bits.h>94 95#include <media/v4l2-cci.h>96 97EOF98	if defined $kernel;99 100print $H "#define CCS_FL_BASE		" .101    (defined $kernel ? "CCI_REG_PRIVATE_SHIFT" : 16) . "\n";102 103my $flag = -1;104my $all_flags;105 106sub bit_def($) {107	my $bit = shift @_;108 109	if (defined $kernel) {110		return "BIT$bit" if $bit =~ /^\(.*\)$/;111		return "BIT($bit)";112	}113	return "(1U << $bit)";114}115 116sub flag_str($$) {117	my ($flag, $check) = @_;118 119	$$flag++;120 121	my $flag_str = !$$flag ? "CCS_FL_BASE" : "(CCS_FL_BASE + $$flag)";122 123	$flag_str = bit_def($flag_str);124 125	$$check .= " | " if defined $$check;126 127	$$check .= $flag_str;128 129	return $flag_str;130}131 132if (! defined $kernel) {133	print $H "#define CCS_FL_16BIT		" . flag_str(\$flag, \$all_flags) . "\n";134	print $H "#define CCS_FL_32BIT		" . flag_str(\$flag, \$all_flags) . "\n";135}136 137print $H "#define CCS_FL_FLOAT_IREAL	" . flag_str(\$flag, \$all_flags) . "\n";138print $H "#define CCS_FL_IREAL		" . flag_str(\$flag, \$all_flags) . "\n";139print $H "#define CCS_BUILD_BUG \\140	BUILD_BUG_ON(~CCI_REG_PRIVATE_MASK & ($all_flags))\n"141    if defined $kernel;142 143print $H <<EOF144 145#define CCS_R_ADDR(r)		((r) & 0xffff)146 147EOF148    if ! defined $kernel;149 150print $A <<EOF151#include <stdint.h>152#include <stdio.h>153#include "ccs-extra.h"154#include "ccs-regs.h"155 156EOF157	if defined $A;158 159my $uc_limith = basename uc $limith;160$uc_limith =~ s/[^A-Z0-9]/_/g;161 162print $LH <<EOF163#ifndef __${uc_limith}__164#define __${uc_limith}__165 166$lh_hdr167struct ccs_limit {168	$uint32_t reg;169	$uint16_t size;170	$uint16_t flags;171	const char *name;172};173 174EOF175  ;176print $LH "#define CCS_L_FL_SAME_REG	" . bit_def(0) . "\n\n";177 178print $LH <<EOF179extern const struct ccs_limit ccs_limits[];180 181EOF182  ;183 184print $LC <<EOF185#include "ccs-limits.h"186#include "ccs-regs.h"187 188const struct ccs_limit ccs_limits[] = {189EOF190  ;191 192my $limitcount = 0;193my $argdescs;194my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";195 196sub name_split($$) {197	my ($name, $addr) = @_;198	my $args;199 200	$name =~ /([^\(]+?)(\(.*)/;201	($name, $args) = ($1, $2);202	$args = [split /,\s*/, $args];203	foreach my $t (@$args) {204		$t =~ s/[\(\)]//g;205		$t =~ s/\//\\\//g;206	}207 208	return ($name, $addr, $args);209}210 211sub tabconv($) {212	$_ = shift;213 214	my @l = split "\n", $_;215 216	map {217		s/ {8,8}/\t/g;218		s/\t\K +//;219	} @l;220 221	return (join "\n", @l) . "\n";222}223 224sub elem_bits(@) {225	my @flags = @_;226 227	return 16 if grep /^16$/, @flags;228	return 32 if grep /^32$/, @flags;229	return 8;230}231 232sub arr_size($) {233	my $this = $_[0];234	my $size = $this->{elsize};235	my $h = $this->{argparams};236 237	foreach my $arg (@{$this->{args}}) {238		my $apref = $h->{$arg};239 240		$size *= $apref->{max} - $apref->{min} + 1;241	}242 243	return $size;244}245 246sub print_args($$$) {247	my ($this, $postfix, $is_same_reg) = @_;248	my ($args, $argparams, $name) =249	  ($this->{args}, $this->{argparams}, $this->{name});250	my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;251	my @mins;252	my @sorted_args = @{$this->{sorted_args}};253	my $lim_arg;254	my $size = arr_size($this);255 256	$argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";257 258	foreach my $sorted_arg (@sorted_args) {259		push @mins, $argparams->{$sorted_arg}->{min};260	}261 262	foreach my $sorted_arg (@sorted_args) {263		my $h = $argparams->{$sorted_arg};264 265		$argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";266 267		$lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}";268	}269 270	$argdescs .= "};\n\n";271 272	$reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .273	  "), $size, sizeof($varname) / sizeof(*$varname)," .274	    " \"" . (lc $name) . "\", $varname },\n";275 276	print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .277	  $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") .278	    ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n"279	      if is_limit_reg $this->{base_addr};280}281 282my $hdr_data;283 284while (<$R>) {285	chop;286	s/^\s*//;287	next if /^[#;]/ || /^$/;288	if (s/^-\s*//) {289		if (s/^b\s*//) {290			my ($bit, $addr) = split /\t+/;291			$bit = uc $bit;292			$hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n";293		} elsif (s/^f\s*//) {294			s/[,\.-]/_/g;295			my @a = split /\s+/;296			my ($msb, $lsb, $this_field) = reverse @a;297		        @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", },298			       { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } );299			$this{"field"} = $this_field;300			foreach my $ar (@a) {301				#print $ar->{fmt}."\n";302				$hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n";303			}304		} elsif (s/^e\s*//) {305			s/[,\.-]/_/g;306			my ($enum, $addr) = split /\s+/;307			$enum = uc $enum;308			$hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n";309		} elsif (s/^l\s*//) {310			my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;311			my $size;312 313			foreach my $num ($min, $max) {314				$num = hex $num if $num =~ /0x/i;315			}316 317			$hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n";318			$hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n";319 320			my $h = $this{argparams};321 322			$h->{$arg} = { "min" => $min,323				       "max" => $max,324				       "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize,325				       "discontig" => \@discontig };326 327			$this{discontig} = $arg if @discontig;328 329			next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};330 331			my $reg_formula = "$this{addr}";332			my $lim_formula;333 334			chop $reg_formula;335 336			$reg_formula = "(" . $reg_formula if $this{flagstring} ne "";337 338			foreach my $arg (@{$this{args}}) {339				my $d = $h->{$arg}->{discontig};340				my $times = $h->{$arg}->{elsize} != 1 ?341				  " * " . $h->{$arg}->{elsize} : "";342 343				if (@$d) {344					my ($lim, $offset) = split /,/, $d->[0];345 346					$reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";347				} else {348					$reg_formula .= " + ($arg)$times";349				}350 351				$lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times";352			}353 354			$reg_formula .= ")";355			$lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;356 357			print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) .358						 $this{arglist}, $reg_formula .359						 (($this{flagstring} eq "") ? "" :360						  " | " . $this{flagstring} . ")") . "\n");361 362			print $H tabconv $hdr_data;363			undef $hdr_data;364 365			# Sort arguments in descending order by size366			@{$this{sorted_args}} = sort {367				$h->{$a}->{elsize} <= $h->{$b}->{elsize}368			} @{$this{args}};369 370			if (defined $this{discontig}) {371				my $da = $this{argparams}->{$this{discontig}};372				my ($first_discontig) = split /,/, $da->{discontig}->[0];373				my $max = $da->{max};374 375				$da->{max} = $first_discontig - 1;376				print_args(\%this, "", 0);377 378				$da->{min} = $da->{max} + 1;379				$da->{max} = $max;380				print_args(\%this, $first_discontig, 1);381			} else {382				print_args(\%this, "", 0);383			}384 385			next unless is_limit_reg $this{base_addr};386 387			print $LH tabconv sprintf "#define %-63s%s\n",388			  "CCS_L_" . (uc $this{name}) . "_OFFSET(" .389			    (join ", ", @{$this{args}}) . ")", "($lim_formula)";390		}391 392		if (! @{$this{args}}) {393			print $H tabconv($hdr_data);394			undef $hdr_data;395		}396 397		next;398	}399 400	my ($name, $addr, @flags) = split /\t+/, $_;401	my $args = [];402 403	my $sp;404 405	($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;406 407	$name =~ s/[,\.-]/_/g;408 409	my $flagstring = "";410	my $bits = elem_bits(@flags);411	if (! defined $kernel) {412		$flagstring .= "| CCS_FL_16BIT " if $bits == 16;413		$flagstring .= "| CCS_FL_32BIT " if $bits == 32;414	}415	$flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;416	$flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;417	$flagstring =~ s/^\| //;418	$flagstring =~ s/ $//;419	$flagstring = "($flagstring)" if $flagstring =~ /\|/;420	my $base_addr = $addr;421	$addr = "CCI_REG$bits($addr)" if defined $kernel;422 423	if ($flagstring ne "" && !@$args) {424		$addr = "($addr | $flagstring)";425		$flagstring = "";426	}427 428	my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : "";429	$hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr430	  if !@$args;431 432	$name =~ s/\(.*//;433 434	%this = ( name => $name,435		  addr => $addr,436		  flagstring => $flagstring,437		  base_addr => $base_addr,438		  argparams => {},439		  args => $args,440		  arglist => $arglist,441		  elsize => $bits / 8,442		);443 444	if (!@$args) {445		$reglist .= "\t{ CCS_R_" . (uc $name) . ", 1,  0, \"" . (lc $name) . "\", NULL },\n";446		print $H tabconv $hdr_data;447		undef $hdr_data;448 449		print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .450		  $this{elsize} . ", 0, \"$name\" },\n"451		    if is_limit_reg $this{base_addr};452	}453 454	print $LH tabconv sprintf "#define %-63s%s\n",455	  "CCS_L_" . (uc $this{name}), $limitcount++456	    if is_limit_reg $this{base_addr};457}458 459if (defined $A) {460	print $A $argdescs, $reglist;461 462	print $A "\t{ 0 }\n";463 464	print $A "};\n";465}466 467print $H "\n#endif /* __${uc_header}__ */\n";468 469print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;470 471print $LH "\n#endif /* __${uc_limith}__ */\n";472 473print $LC "\t{ 0 } /* Guardian */\n";474print $LC "};\n";475 476close($R);477close($H);478close($A) if defined $A;479close($LC);480close($LH);481