Merge tag 'Smack-for-5.11-io_uring-fix' of git://github.com/cschaufler/smack-next
[linux-2.6-microblaze.git] / Documentation / driver-api / media / drivers / ccs / mk-ccs-regs
1 #!/usr/bin/perl -w
2 # SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
3 # Copyright (C) 2019--2020 Intel Corporation
4
5 use Getopt::Long qw(:config no_ignore_case);
6 use File::Basename;
7
8 my $ccsregs = "ccs-regs.asc";
9 my $header;
10 my $regarray;
11 my $limitc;
12 my $limith;
13 my $kernel;
14 my $help;
15
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";
23
24 $help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
25
26 if (defined $help) {
27         print <<EOH
28 $0 - Create CCS register definitions for C
29
30 usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
31
32         -c ccs register file
33         -e header file name
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
38 EOH
39           ;
40         exit 0;
41 }
42
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';
48
49 open(my $R, "< $ccsregs") or die "can't open $ccsregs";
50
51 open(my $H, "> $header") or die "can't open $header";
52 my $A;
53 if (defined $regarray) {
54         open($A, "> $regarray") or die "can't open $regarray";
55 }
56 open(my $LC, "> $limitc") or die "can't open $limitc";
57 open(my $LH, "> $limith") or die "can't open $limith";
58
59 my %this;
60
61 sub is_limit_reg($) {
62         my $addr = hex $_[0];
63
64         return 0 if $addr < 0x40; # weed out status registers
65         return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers
66
67         return 1;
68 }
69
70 my $uc_header = basename uc $header;
71 $uc_header =~ s/[^A-Z0-9]/_/g;
72
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
76 for my $fh ($A, $LC) {
77         print $fh "// $license\n$copyright\n" if defined $fh;
78 }
79
80 for my $fh ($H, $LH) {
81         print $fh "/* $license */\n$copyright\n";
82 }
83
84 sub bit_def($) {
85         my $bit = shift @_;
86
87         return "BIT($bit)" if defined $kernel;
88         return "(1U << $bit)" if $bit =~ /^[a-zA-Z0-9_]+$/;
89         return "(1U << ($bit))";
90 }
91
92 print $H <<EOF
93 #ifndef __${uc_header}__
94 #define __${uc_header}__
95
96 EOF
97   ;
98
99 print $H "#include <linux/bits.h>\n\n" if defined $kernel;
100
101 print $H <<EOF
102 #define CCS_FL_BASE             16
103 EOF
104   ;
105
106 print $H "#define CCS_FL_16BIT          " . bit_def("CCS_FL_BASE") . "\n";
107 print $H "#define CCS_FL_32BIT          " . bit_def("CCS_FL_BASE + 1") . "\n";
108 print $H "#define CCS_FL_FLOAT_IREAL    " . bit_def("CCS_FL_BASE + 2") . "\n";
109 print $H "#define CCS_FL_IREAL          " . bit_def("CCS_FL_BASE + 3") . "\n";
110
111 print $H <<EOF
112 #define CCS_R_ADDR(r)           ((r) & 0xffff)
113
114 EOF
115   ;
116
117 print $A <<EOF
118 #include <stdint.h>
119 #include <stdio.h>
120 #include "ccs-extra.h"
121 #include "ccs-regs.h"
122
123 EOF
124         if defined $A;
125
126 my $uc_limith = basename uc $limith;
127 $uc_limith =~ s/[^A-Z0-9]/_/g;
128
129 print $LH <<EOF
130 #ifndef __${uc_limith}__
131 #define __${uc_limith}__
132
133 $lh_hdr
134 struct ccs_limit {
135         $uint32_t reg;
136         $uint16_t size;
137         $uint16_t flags;
138         const char *name;
139 };
140
141 EOF
142   ;
143 print $LH "#define CCS_L_FL_SAME_REG    " . bit_def(0) . "\n\n";
144
145 print $LH <<EOF
146 extern const struct ccs_limit ccs_limits[];
147
148 EOF
149   ;
150
151 print $LC <<EOF
152 #include "ccs-limits.h"
153 #include "ccs-regs.h"
154
155 const struct ccs_limit ccs_limits[] = {
156 EOF
157   ;
158
159 my $limitcount = 0;
160 my $argdescs;
161 my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";
162
163 sub name_split($$) {
164         my ($name, $addr) = @_;
165         my $args;
166
167         $name =~ /([^\(]+?)(\(.*)/;
168         ($name, $args) = ($1, $2);
169         $args = [split /,\s*/, $args];
170         foreach my $t (@$args) {
171                 $t =~ s/[\(\)]//g;
172                 $t =~ s/\//\\\//g;
173         }
174
175         return ($name, $addr, $args);
176 }
177
178 sub tabconv($) {
179         $_ = shift;
180
181         my @l = split "\n", $_;
182
183         map {
184                 s/ {8,8}/\t/g;
185                 s/\t\K +//;
186         } @l;
187
188         return (join "\n", @l) . "\n";
189 }
190
191 sub elem_size(@) {
192         my @flags = @_;
193
194         return 2 if grep /^16$/, @flags;
195         return 4 if grep /^32$/, @flags;
196         return 1;
197 }
198
199 sub arr_size($) {
200         my $this = $_[0];
201         my $size = $this->{elsize};
202         my $h = $this->{argparams};
203
204         foreach my $arg (@{$this->{args}}) {
205                 my $apref = $h->{$arg};
206
207                 $size *= $apref->{max} - $apref->{min} + 1;
208         }
209
210         return $size;
211 }
212
213 sub print_args($$$) {
214         my ($this, $postfix, $is_same_reg) = @_;
215         my ($args, $argparams, $name) =
216           ($this->{args}, $this->{argparams}, $this->{name});
217         my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;
218         my @mins;
219         my @sorted_args = @{$this->{sorted_args}};
220         my $lim_arg;
221         my $size = arr_size($this);
222
223         $argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";
224
225         foreach my $sorted_arg (@sorted_args) {
226                 push @mins, $argparams->{$sorted_arg}->{min};
227         }
228
229         foreach my $sorted_arg (@sorted_args) {
230                 my $h = $argparams->{$sorted_arg};
231
232                 $argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";
233
234                 $lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}";
235         }
236
237         $argdescs .= "};\n\n";
238
239         $reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .
240           "), $size, sizeof($varname) / sizeof(*$varname)," .
241             " \"" . (lc $name) . "\", $varname },\n";
242
243         print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .
244           $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") .
245             ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n"
246               if is_limit_reg $this->{base_addr};
247 }
248
249 my $hdr_data;
250
251 while (<$R>) {
252         chop;
253         s/^\s*//;
254         next if /^[#;]/ || /^$/;
255         if (s/^-\s*//) {
256                 if (s/^b\s*//) {
257                         my ($bit, $addr) = split /\t+/;
258                         $bit = uc $bit;
259                         $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n";
260                 } elsif (s/^f\s*//) {
261                         s/[,\.-]/_/g;
262                         my @a = split /\s+/;
263                         my ($msb, $lsb, $this_field) = reverse @a;
264                         @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", },
265                                { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } );
266                         $this{"field"} = $this_field;
267                         foreach my $ar (@a) {
268                                 #print $ar->{fmt}."\n";
269                                 $hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n";
270                         }
271                 } elsif (s/^e\s*//) {
272                         s/[,\.-]/_/g;
273                         my ($enum, $addr) = split /\s+/;
274                         $enum = uc $enum;
275                         $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n";
276                 } elsif (s/^l\s*//) {
277                         my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;
278                         my $size;
279
280                         foreach my $num ($min, $max) {
281                                 $num = hex $num if $num =~ /0x/i;
282                         }
283
284                         $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n";
285                         $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n";
286
287                         my $h = $this{argparams};
288
289                         $h->{$arg} = { "min" => $min,
290                                        "max" => $max,
291                                        "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize,
292                                        "discontig" => \@discontig };
293
294                         $this{discontig} = $arg if @discontig;
295
296                         next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};
297
298                         my $reg_formula = "($this{addr}";
299                         my $lim_formula;
300
301                         foreach my $arg (@{$this{args}}) {
302                                 my $d = $h->{$arg}->{discontig};
303                                 my $times = $h->{$arg}->{elsize} != 1 ?
304                                   " * " . $h->{$arg}->{elsize} : "";
305
306                                 if (@$d) {
307                                         my ($lim, $offset) = split /,/, $d->[0];
308
309                                         $reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";
310                                 } else {
311                                         $reg_formula .= " + ($arg)$times";
312                                 }
313
314                                 $lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times";
315                         }
316
317                         $reg_formula .= ")\n";
318                         $lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;
319
320                         print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) .
321                           $this{arglist}, $reg_formula);
322
323                         print $H tabconv $hdr_data;
324                         undef $hdr_data;
325
326                         # Sort arguments in descending order by size
327                         @{$this{sorted_args}} = sort {
328                                 $h->{$a}->{elsize} <= $h->{$b}->{elsize}
329                         } @{$this{args}};
330
331                         if (defined $this{discontig}) {
332                                 my $da = $this{argparams}->{$this{discontig}};
333                                 my ($first_discontig) = split /,/, $da->{discontig}->[0];
334                                 my $max = $da->{max};
335
336                                 $da->{max} = $first_discontig - 1;
337                                 print_args(\%this, "", 0);
338
339                                 $da->{min} = $da->{max} + 1;
340                                 $da->{max} = $max;
341                                 print_args(\%this, $first_discontig, 1);
342                         } else {
343                                 print_args(\%this, "", 0);
344                         }
345
346                         next unless is_limit_reg $this{base_addr};
347
348                         print $LH tabconv sprintf "#define %-63s%s\n",
349                           "CCS_L_" . (uc $this{name}) . "_OFFSET(" .
350                             (join ", ", @{$this{args}}) . ")", "($lim_formula)";
351                 }
352
353                 if (! @{$this{args}}) {
354                         print $H tabconv($hdr_data);
355                         undef $hdr_data;
356                 }
357
358                 next;
359         }
360
361         my ($name, $addr, @flags) = split /\t+/, $_;
362         my $args = [];
363
364         my $sp;
365
366         ($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;
367
368         $name =~ s/[,\.-]/_/g;
369
370         my $flagstring = "";
371         my $size = elem_size(@flags);
372         $flagstring .= "| CCS_FL_16BIT " if $size eq "2";
373         $flagstring .= "| CCS_FL_32BIT " if $size eq "4";
374         $flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;
375         $flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;
376         $flagstring =~ s/^\| //;
377         $flagstring =~ s/ $//;
378         $flagstring = "($flagstring)" if $flagstring =~ /\|/;
379         my $base_addr = $addr;
380         $addr = "($addr | $flagstring)" if $flagstring ne "";
381
382         my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : "";
383         $hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr
384           if !@$args;
385
386         $name =~ s/\(.*//;
387
388         %this = ( name => $name,
389                   addr => $addr,
390                   base_addr => $base_addr,
391                   argparams => {},
392                   args => $args,
393                   arglist => $arglist,
394                   elsize => $size,
395                 );
396
397         if (!@$args) {
398                 $reglist .= "\t{ CCS_R_" . (uc $name) . ", 1,  0, \"" . (lc $name) . "\", NULL },\n";
399                 print $H tabconv $hdr_data;
400                 undef $hdr_data;
401
402                 print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .
403                   $this{elsize} . ", 0, \"$name\" },\n"
404                     if is_limit_reg $this{base_addr};
405         }
406
407         print $LH tabconv sprintf "#define %-63s%s\n",
408           "CCS_L_" . (uc $this{name}), $limitcount++
409             if is_limit_reg $this{base_addr};
410 }
411
412 if (defined $A) {
413         print $A $argdescs, $reglist;
414
415         print $A "\t{ 0 }\n";
416
417         print $A "};\n";
418 }
419
420 print $H "\n#endif /* __${uc_header}__ */\n";
421
422 print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;
423
424 print $LH "\n#endif /* __${uc_limith}__ */\n";
425
426 print $LC "\t{ 0 } /* Guardian */\n";
427 print $LC "};\n";
428
429 close($R);
430 close($H);
431 close($A) if defined $A;
432 close($LC);
433 close($LH);