aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/driver-api/media/drivers/ccs/mk-ccs-regs')
-rwxr-xr-xDocumentation/driver-api/media/drivers/ccs/mk-ccs-regs480
1 files changed, 480 insertions, 0 deletions
diff --git a/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs b/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs
new file mode 100755
index 000000000000..3d3152b45821
--- /dev/null
+++ b/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs
@@ -0,0 +1,480 @@
+#!/usr/bin/perl -w
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+# Copyright (C) 2019--2020 Intel Corporation
+
+use Getopt::Long qw(:config no_ignore_case);
+use File::Basename;
+
+my $ccsregs = "ccs-regs.asc";
+my $header;
+my $regarray;
+my $limitc;
+my $limith;
+my $kernel;
+my $help;
+
+GetOptions("ccsregs|c=s" => \$ccsregs,
+ "header|e=s" => \$header,
+ "regarray|r=s" => \$regarray,
+ "limitc|l=s" => \$limitc,
+ "limith|L=s" => \$limith,
+ "kernel|k" => \$kernel,
+ "help|h" => \$help) or die "can't parse options";
+
+$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
+
+if (defined $help) {
+ print <<EOH
+$0 - Create CCS register definitions for C
+
+usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
+
+ -c ccs register file
+ -e header file name
+ -r register description array file name
+ -l limit and capability array file name
+ -L limit and capability header file name
+ -k generate files for kernel space consumption
+EOH
+ ;
+ exit 0;
+}
+
+my $lh_hdr = ! defined $kernel
+ ? '#include "ccs-os.h"' . "\n"
+ : "#include <linux/bits.h>\n#include <linux/types.h>\n";
+my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32';
+my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16';
+
+open(my $R, "< $ccsregs") or die "can't open $ccsregs";
+
+open(my $H, "> $header") or die "can't open $header";
+my $A;
+if (defined $regarray) {
+ open($A, "> $regarray") or die "can't open $regarray";
+}
+open(my $LC, "> $limitc") or die "can't open $limitc";
+open(my $LH, "> $limith") or die "can't open $limith";
+
+my %this;
+
+sub is_limit_reg($) {
+ my $addr = hex $_[0];
+
+ return 0 if $addr < 0x40; # weed out status registers
+ return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers
+
+ return 1;
+}
+
+my $uc_header = basename uc $header;
+$uc_header =~ s/[^A-Z0-9]/_/g;
+
+my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";
+my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause";
+my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n";
+
+for my $fh ($A, $LC) {
+ print $fh "// $license\n$copyright$note\n" if defined $fh;
+}
+
+for my $fh ($H, $LH) {
+ print $fh "/* $license */\n$copyright$note\n";
+}
+
+print $H <<EOF
+#ifndef __${uc_header}__
+#define __${uc_header}__
+
+EOF
+ ;
+
+print $H <<EOF
+#include <linux/bits.h>
+
+#include <media/v4l2-cci.h>
+
+EOF
+ if defined $kernel;
+
+print $H "#define CCS_FL_BASE " .
+ (defined $kernel ? "CCI_REG_PRIVATE_SHIFT" : 16) . "\n";
+
+my $flag = -1;
+my $all_flags;
+
+sub bit_def($) {
+ my $bit = shift @_;
+
+ if (defined $kernel) {
+ return "BIT$bit" if $bit =~ /^\(.*\)$/;
+ return "BIT($bit)";
+ }
+ return "(1U << $bit)";
+}
+
+sub flag_str($$) {
+ my ($flag, $check) = @_;
+
+ $$flag++;
+
+ my $flag_str = !$$flag ? "CCS_FL_BASE" : "(CCS_FL_BASE + $$flag)";
+
+ $flag_str = bit_def($flag_str);
+
+ $$check .= " | " if defined $$check;
+
+ $$check .= $flag_str;
+
+ return $flag_str;
+}
+
+if (! defined $kernel) {
+ print $H "#define CCS_FL_16BIT " . flag_str(\$flag, \$all_flags) . "\n";
+ print $H "#define CCS_FL_32BIT " . flag_str(\$flag, \$all_flags) . "\n";
+}
+
+print $H "#define CCS_FL_FLOAT_IREAL " . flag_str(\$flag, \$all_flags) . "\n";
+print $H "#define CCS_FL_IREAL " . flag_str(\$flag, \$all_flags) . "\n";
+print $H "#define CCS_BUILD_BUG \\
+ BUILD_BUG_ON(~CCI_REG_PRIVATE_MASK & ($all_flags))\n"
+ if defined $kernel;
+
+print $H <<EOF
+
+#define CCS_R_ADDR(r) ((r) & 0xffff)
+
+EOF
+ if ! defined $kernel;
+
+print $A <<EOF
+#include <stdint.h>
+#include <stdio.h>
+#include "ccs-extra.h"
+#include "ccs-regs.h"
+
+EOF
+ if defined $A;
+
+my $uc_limith = basename uc $limith;
+$uc_limith =~ s/[^A-Z0-9]/_/g;
+
+print $LH <<EOF
+#ifndef __${uc_limith}__
+#define __${uc_limith}__
+
+$lh_hdr
+struct ccs_limit {
+ $uint32_t reg;
+ $uint16_t size;
+ $uint16_t flags;
+ const char *name;
+};
+
+EOF
+ ;
+print $LH "#define CCS_L_FL_SAME_REG " . bit_def(0) . "\n\n";
+
+print $LH <<EOF
+extern const struct ccs_limit ccs_limits[];
+
+EOF
+ ;
+
+print $LC <<EOF
+#include "ccs-limits.h"
+#include "ccs-regs.h"
+
+const struct ccs_limit ccs_limits[] = {
+EOF
+ ;
+
+my $limitcount = 0;
+my $argdescs;
+my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";
+
+sub name_split($$) {
+ my ($name, $addr) = @_;
+ my $args;
+
+ $name =~ /([^\(]+?)(\(.*)/;
+ ($name, $args) = ($1, $2);
+ $args = [split /,\s*/, $args];
+ foreach my $t (@$args) {
+ $t =~ s/[\(\)]//g;
+ $t =~ s/\//\\\//g;
+ }
+
+ return ($name, $addr, $args);
+}
+
+sub tabconv($) {
+ $_ = shift;
+
+ my @l = split "\n", $_;
+
+ map {
+ s/ {8,8}/\t/g;
+ s/\t\K +//;
+ } @l;
+
+ return (join "\n", @l) . "\n";
+}
+
+sub elem_bits(@) {
+ my @flags = @_;
+
+ return 16 if grep /^16$/, @flags;
+ return 32 if grep /^32$/, @flags;
+ return 8;
+}
+
+sub arr_size($) {
+ my $this = $_[0];
+ my $size = $this->{elsize};
+ my $h = $this->{argparams};
+
+ foreach my $arg (@{$this->{args}}) {
+ my $apref = $h->{$arg};
+
+ $size *= $apref->{max} - $apref->{min} + 1;
+ }
+
+ return $size;
+}
+
+sub print_args($$$) {
+ my ($this, $postfix, $is_same_reg) = @_;
+ my ($args, $argparams, $name) =
+ ($this->{args}, $this->{argparams}, $this->{name});
+ my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;
+ my @mins;
+ my @sorted_args = @{$this->{sorted_args}};
+ my $lim_arg;
+ my $size = arr_size($this);
+
+ $argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";
+
+ foreach my $sorted_arg (@sorted_args) {
+ push @mins, $argparams->{$sorted_arg}->{min};
+ }
+
+ foreach my $sorted_arg (@sorted_args) {
+ my $h = $argparams->{$sorted_arg};
+
+ $argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";
+
+ $lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}";
+ }
+
+ $argdescs .= "};\n\n";
+
+ $reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .
+ "), $size, sizeof($varname) / sizeof(*$varname)," .
+ " \"" . (lc $name) . "\", $varname },\n";
+
+ print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .
+ $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") .
+ ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n"
+ if is_limit_reg $this->{base_addr};
+}
+
+my $hdr_data;
+
+while (<$R>) {
+ chop;
+ s/^\s*//;
+ next if /^[#;]/ || /^$/;
+ if (s/^-\s*//) {
+ if (s/^b\s*//) {
+ my ($bit, $addr) = split /\t+/;
+ $bit = uc $bit;
+ $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n";
+ } elsif (s/^f\s*//) {
+ s/[,\.-]/_/g;
+ my @a = split /\s+/;
+ my ($msb, $lsb, $this_field) = reverse @a;
+ @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", },
+ { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } );
+ $this{"field"} = $this_field;
+ foreach my $ar (@a) {
+ #print $ar->{fmt}."\n";
+ $hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n";
+ }
+ } elsif (s/^e\s*//) {
+ s/[,\.-]/_/g;
+ my ($enum, $addr) = split /\s+/;
+ $enum = uc $enum;
+ $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n";
+ } elsif (s/^l\s*//) {
+ my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;
+ my $size;
+
+ foreach my $num ($min, $max) {
+ $num = hex $num if $num =~ /0x/i;
+ }
+
+ $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n";
+ $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n";
+
+ my $h = $this{argparams};
+
+ $h->{$arg} = { "min" => $min,
+ "max" => $max,
+ "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize,
+ "discontig" => \@discontig };
+
+ $this{discontig} = $arg if @discontig;
+
+ next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};
+
+ my $reg_formula = "$this{addr}";
+ my $lim_formula;
+
+ chop $reg_formula;
+
+ $reg_formula = "(" . $reg_formula if $this{flagstring} ne "";
+
+ foreach my $arg (@{$this{args}}) {
+ my $d = $h->{$arg}->{discontig};
+ my $times = $h->{$arg}->{elsize} != 1 ?
+ " * " . $h->{$arg}->{elsize} : "";
+
+ if (@$d) {
+ my ($lim, $offset) = split /,/, $d->[0];
+
+ $reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";
+ } else {
+ $reg_formula .= " + ($arg)$times";
+ }
+
+ $lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times";
+ }
+
+ $reg_formula .= ")";
+ $lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;
+
+ print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) .
+ $this{arglist}, $reg_formula .
+ (($this{flagstring} eq "") ? "" :
+ " | " . $this{flagstring} . ")") . "\n");
+
+ print $H tabconv $hdr_data;
+ undef $hdr_data;
+
+ # Sort arguments in descending order by size
+ @{$this{sorted_args}} = sort {
+ $h->{$a}->{elsize} <= $h->{$b}->{elsize}
+ } @{$this{args}};
+
+ if (defined $this{discontig}) {
+ my $da = $this{argparams}->{$this{discontig}};
+ my ($first_discontig) = split /,/, $da->{discontig}->[0];
+ my $max = $da->{max};
+
+ $da->{max} = $first_discontig - 1;
+ print_args(\%this, "", 0);
+
+ $da->{min} = $da->{max} + 1;
+ $da->{max} = $max;
+ print_args(\%this, $first_discontig, 1);
+ } else {
+ print_args(\%this, "", 0);
+ }
+
+ next unless is_limit_reg $this{base_addr};
+
+ print $LH tabconv sprintf "#define %-63s%s\n",
+ "CCS_L_" . (uc $this{name}) . "_OFFSET(" .
+ (join ", ", @{$this{args}}) . ")", "($lim_formula)";
+ }
+
+ if (! @{$this{args}}) {
+ print $H tabconv($hdr_data);
+ undef $hdr_data;
+ }
+
+ next;
+ }
+
+ my ($name, $addr, @flags) = split /\t+/, $_;
+ my $args = [];
+
+ my $sp;
+
+ ($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;
+
+ $name =~ s/[,\.-]/_/g;
+
+ my $flagstring = "";
+ my $bits = elem_bits(@flags);
+ if (! defined $kernel) {
+ $flagstring .= "| CCS_FL_16BIT " if $bits == 16;
+ $flagstring .= "| CCS_FL_32BIT " if $bits == 32;
+ }
+ $flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;
+ $flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;
+ $flagstring =~ s/^\| //;
+ $flagstring =~ s/ $//;
+ $flagstring = "($flagstring)" if $flagstring =~ /\|/;
+ my $base_addr = $addr;
+ $addr = "CCI_REG$bits($addr)" if defined $kernel;
+
+ if ($flagstring ne "" && !@$args) {
+ $addr = "($addr | $flagstring)";
+ $flagstring = "";
+ }
+
+ my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : "";
+ $hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr
+ if !@$args;
+
+ $name =~ s/\(.*//;
+
+ %this = ( name => $name,
+ addr => $addr,
+ flagstring => $flagstring,
+ base_addr => $base_addr,
+ argparams => {},
+ args => $args,
+ arglist => $arglist,
+ elsize => $bits / 8,
+ );
+
+ if (!@$args) {
+ $reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \"" . (lc $name) . "\", NULL },\n";
+ print $H tabconv $hdr_data;
+ undef $hdr_data;
+
+ print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .
+ $this{elsize} . ", 0, \"$name\" },\n"
+ if is_limit_reg $this{base_addr};
+ }
+
+ print $LH tabconv sprintf "#define %-63s%s\n",
+ "CCS_L_" . (uc $this{name}), $limitcount++
+ if is_limit_reg $this{base_addr};
+}
+
+if (defined $A) {
+ print $A $argdescs, $reglist;
+
+ print $A "\t{ 0 }\n";
+
+ print $A "};\n";
+}
+
+print $H "\n#endif /* __${uc_header}__ */\n";
+
+print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;
+
+print $LH "\n#endif /* __${uc_limith}__ */\n";
+
+print $LC "\t{ 0 } /* Guardian */\n";
+print $LC "};\n";
+
+close($R);
+close($H);
+close($A) if defined $A;
+close($LC);
+close($LH);