2 # SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
3 # Copyright (C) 2019--2020 Intel Corporation
5 use Getopt
::Long
qw(:config no_ignore_case);
8 my $ccsregs = "ccs-regs.asc";
16 GetOptions
("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";
24 $help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
28 $0 - Create CCS register definitions for C
30 usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
34 -r register description array file name
35 -l limit and capability array file name
36 -L limit and capability header file name
37 -k generate files for kernel space consumption
43 my $lh_hdr = ! defined $kernel
44 ?
'#include "ccs-os.h"' . "\n"
45 : "#include <linux/bits.h>\n#include <linux/types.h>\n";
46 my $uint32_t = ! defined $kernel ?
'uint32_t' : 'u32';
47 my $uint16_t = ! defined $kernel ?
'uint16_t' : 'u16';
49 open(my $R, "< $ccsregs") or die "can't open $ccsregs";
51 open(my $H, "> $header") or die "can't open $header";
53 if (defined $regarray) {
54 open($A, "> $regarray") or die "can't open $regarray";
56 open(my $LC, "> $limitc") or die "can't open $limitc";
57 open(my $LH, "> $limith") or die "can't open $limith";
64 return 0 if $addr < 0x40; # weed out status registers
65 return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers
70 my $uc_header = basename
uc $header;
71 $uc_header =~ s/[^A-Z0-9]/_/g;
73 my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";
74 my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause";
75 my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n";
77 for my $fh ($A, $LC) {
78 print $fh "// $license\n$copyright$note\n" if defined $fh;
81 for my $fh ($H, $LH) {
82 print $fh "/* $license */\n$copyright$note\n";
86 #ifndef __${uc_header}__
87 #define __${uc_header}__
93 #include <linux/bits.h>
95 #include <media/v4l2-cci.h>
100 print $H "#define CCS_FL_BASE " .
101 (defined $kernel ?
"CCI_REG_PRIVATE_SHIFT" : 16) . "\n";
109 if (defined $kernel) {
110 return "BIT$bit" if $bit =~ /^\(.*\)$/;
113 return "(1U << $bit)";
117 my ($flag, $check) = @_;
121 my $flag_str = !$$flag ?
"CCS_FL_BASE" : "(CCS_FL_BASE + $$flag)";
123 $flag_str = bit_def
($flag_str);
125 $$check .= " | " if defined $$check;
127 $$check .= $flag_str;
132 if (! 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";
137 print $H "#define CCS_FL_FLOAT_IREAL " . flag_str
(\
$flag, \
$all_flags) . "\n";
138 print $H "#define CCS_FL_IREAL " . flag_str
(\
$flag, \
$all_flags) . "\n";
139 print $H "#define CCS_BUILD_BUG \\
140 BUILD_BUG_ON(~CCI_REG_PRIVATE_MASK & ($all_flags))\n"
145 #define CCS_R_ADDR(r) ((r) & 0xffff)
148 if ! defined $kernel;
153 #include "ccs-extra.h"
154 #include "ccs-regs.h"
159 my $uc_limith = basename
uc $limith;
160 $uc_limith =~ s/[^A-Z0-9]/_/g;
163 #ifndef __${uc_limith}__
164 #define __${uc_limith}__
176 print $LH "#define CCS_L_FL_SAME_REG " . bit_def
(0) . "\n\n";
179 extern const struct ccs_limit ccs_limits[];
185 #include "ccs-limits.h"
186 #include "ccs-regs.h"
188 const struct ccs_limit ccs_limits[] = {
194 my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";
197 my ($name, $addr) = @_;
200 $name =~ /([^\(]+?)(\(.*)/;
201 ($name, $args) = ($1, $2);
202 $args = [split /,\s*/, $args];
203 foreach my $t (@
$args) {
208 return ($name, $addr, $args);
214 my @l = split "\n", $_;
221 return (join "\n", @l) . "\n";
227 return 16 if grep /^16$/, @flags;
228 return 32 if grep /^32$/, @flags;
234 my $size = $this->{elsize
};
235 my $h = $this->{argparams
};
237 foreach my $arg (@
{$this->{args
}}) {
238 my $apref = $h->{$arg};
240 $size *= $apref->{max
} - $apref->{min
} + 1;
246 sub 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;
252 my @sorted_args = @
{$this->{sorted_args
}};
254 my $size = arr_size
($this);
256 $argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";
258 foreach my $sorted_arg (@sorted_args) {
259 push @mins, $argparams->{$sorted_arg}->{min
};
262 foreach my $sorted_arg (@sorted_args) {
263 my $h = $argparams->{$sorted_arg};
265 $argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";
267 $lim_arg .= defined $lim_arg ?
", $h->{min}" : "$h->{min}";
270 $argdescs .= "};\n\n";
272 $reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .
273 "), $size, sizeof($varname) / sizeof(*$varname)," .
274 " \"" . (lc $name) . "\", $varname },\n";
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
};
287 next if /^[#;]/ || /^$/;
290 my ($bit, $addr) = split /\t+/;
292 $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this
{name
}}) ."_$bit", bit_def
($addr) . "\n";
293 } elsif (s/^f\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";
304 } elsif (s/^e\s*//) {
306 my ($enum, $addr) = split /\s+/;
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+/;
313 foreach my $num ($min, $max) {
314 $num = hex $num if $num =~ /0x/i;
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";
320 my $h = $this{argparams
};
322 $h->{$arg} = { "min" => $min,
324 "elsize" => $elsize =~ /^0x/ ?
hex $elsize : $elsize,
325 "discontig" => \
@discontig };
327 $this{discontig
} = $arg if @discontig;
329 next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};
331 my $reg_formula = "$this{addr}";
336 $reg_formula = "(" . $reg_formula if $this{flagstring
} ne "";
338 foreach my $arg (@
{$this{args
}}) {
339 my $d = $h->{$arg}->{discontig
};
340 my $times = $h->{$arg}->{elsize
} != 1 ?
341 " * " . $h->{$arg}->{elsize
} : "";
344 my ($lim, $offset) = split /,/, $d->[0];
346 $reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";
348 $reg_formula .= " + ($arg)$times";
351 $lim_formula .= (defined $lim_formula ?
" + " : "") . "($arg)$times";
355 $lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;
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");
362 print $H tabconv
$hdr_data;
365 # Sort arguments in descending order by size
366 @
{$this{sorted_args
}} = sort {
367 $h->{$a}->{elsize
} <= $h->{$b}->{elsize
}
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
};
375 $da->{max
} = $first_discontig - 1;
376 print_args
(\
%this, "", 0);
378 $da->{min
} = $da->{max
} + 1;
380 print_args
(\
%this, $first_discontig, 1);
382 print_args
(\
%this, "", 0);
385 next unless is_limit_reg
$this{base_addr
};
387 print $LH tabconv
sprintf "#define %-63s%s\n",
388 "CCS_L_" . (uc $this{name
}) . "_OFFSET(" .
389 (join ", ", @
{$this{args
}}) . ")", "($lim_formula)";
392 if (! @
{$this{args
}}) {
393 print $H tabconv
($hdr_data);
400 my ($name, $addr, @flags) = split /\t+/, $_;
405 ($name, $addr, $args) = name_split
($name, $addr) if /\(.*\)/;
407 $name =~ s/[,\.-]/_/g;
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;
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;
423 if ($flagstring ne "" && !@
$args) {
424 $addr = "($addr | $flagstring)";
428 my $arglist = @
$args ?
"(" . (join ", ", @
$args) . ")" : "";
429 $hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr
434 %this = ( name
=> $name,
436 flagstring
=> $flagstring,
437 base_addr
=> $base_addr,
445 $reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \"" . (lc $name) . "\", NULL },\n";
446 print $H tabconv
$hdr_data;
449 print $LC tabconv
sprintf "\t{ CCS_R_" . (uc $name) . ", " .
450 $this{elsize
} . ", 0, \"$name\" },\n"
451 if is_limit_reg
$this{base_addr
};
454 print $LH tabconv
sprintf "#define %-63s%s\n",
455 "CCS_L_" . (uc $this{name
}), $limitcount++
456 if is_limit_reg
$this{base_addr
};
460 print $A $argdescs, $reglist;
462 print $A "\t{ 0 }\n";
467 print $H "\n#endif /* __${uc_header}__ */\n";
469 print $LH tabconv
sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;
471 print $LH "\n#endif /* __${uc_limith}__ */\n";
473 print $LC "\t{ 0 } /* Guardian */\n";
478 close($A) if defined $A;