Add a simple structure and search function to the common code that
can be used for looking up a set of addresses by type. The user
must supply the iomaps[] table, e.g.

struct iomap iomaps[] = {
{
    .type = "virtio_mmio",
    .nr = 4,
    .addrs = { 0x2000000, 0x2000200, 0x2000400, 0x2000600, },
},
{
    .type = NULL,
},
};

Also add a script scripts/gen-devtree-iomaps.pl that can generate
the iomaps table from an fdt, e.g.

fdtdump dtb | scripts/gen-devtree-iomaps.pl - virtio_mmio

Signed-off-by: Andrew Jones <[email protected]>

---
v2:
  - switch to kernel coding style
  - rework fdt parsing to enable extraction of properties. Extract
    the 'compatible' property.
  - add iomaps_find_compatible() to allow searching for iomaps by
    its 'compatible' property.
---
 README                        |   1 +
 lib/iomaps.c                  |  31 +++++++++++++
 lib/iomaps.h                  |  14 ++++++
 scripts/gen-devtree-iomaps.pl | 105 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 151 insertions(+)
 create mode 100644 lib/iomaps.c
 create mode 100644 lib/iomaps.h
 create mode 100755 scripts/gen-devtree-iomaps.pl

diff --git a/README b/README
index 0174679c05021..f834c61dc6112 100644
--- a/README
+++ b/README
@@ -20,6 +20,7 @@ Directory structure:
 .:             Makefile and config files for the tests
 ./config:      config files for the tests
 ./docs:                documentation files
+./scripts:     misc helper scripts
 ./lib:         general services for the tests
 ./lib/<ARCH>:  architecture dependent services for the tests
 ./<ARCH>:      the sources of the tests and the created objects/images
diff --git a/lib/iomaps.c b/lib/iomaps.c
new file mode 100644
index 0000000000000..f2263b79dce96
--- /dev/null
+++ b/lib/iomaps.c
@@ -0,0 +1,31 @@
+#include "libcflat.h"
+#include "iomaps.h"
+
+extern const struct iomap iomaps[];
+
+const struct iomap *iomaps_find_type(const char *type)
+{
+       const struct iomap *m = &iomaps[0];
+
+       while (m->type) {
+               if (strcmp(m->type, type) == 0)
+                       return m;
+               ++m;
+       }
+       return NULL;
+}
+
+const struct iomap *iomaps_find_compatible(const char *compat)
+{
+       const struct iomap *m = &iomaps[0];
+       const char *c;
+       int i;
+
+       while (m->type) {
+               for (i = 0, c = m->compats[0]; c != NULL; c = m->compats[++i])
+                       if (strcmp(c, compat) == 0)
+                               return m;
+               ++m;
+       }
+       return NULL;
+}
diff --git a/lib/iomaps.h b/lib/iomaps.h
new file mode 100644
index 0000000000000..76a1aa4720337
--- /dev/null
+++ b/lib/iomaps.h
@@ -0,0 +1,14 @@
+#ifndef _IOMAPS_H_
+#define _IOMAPS_H_
+#include "libcflat.h"
+
+struct iomap {
+       const char *type;
+       const char *compats[5];
+       u32 nr;
+       u32 addrs[64];
+};
+
+const struct iomap *iomaps_find_type(const char *type);
+const struct iomap *iomaps_find_compatible(const char *compat);
+#endif
diff --git a/scripts/gen-devtree-iomaps.pl b/scripts/gen-devtree-iomaps.pl
new file mode 100755
index 0000000000000..b48e85e48ab34
--- /dev/null
+++ b/scripts/gen-devtree-iomaps.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl -w
+use strict;
+use File::Temp qw/:POSIX/;
+
+my $dts = shift @ARGV;
+my @types = @ARGV;
+my $max_nr_addrs = 64;
+my $max_nr_compats = 4;
+
+if (!defined $dts || $#types < 0) {
+       print STDERR "Usage: gen-devtree-iomaps ".
+               "<dts-file|-> <addr-type> [addr-types...]\n";
+       exit 1;
+}
+
+my $dtb = tmpnam();
+system "dtc -I dts -O dtb $dts -o $dtb";
+
+my $g = join '|', map { $_ . '@' } @types;
+my @devs = grep { /$g/ } `fdtget -l $dtb / 2>/dev/null`;
+
+my %iomaps;
+foreach my $dev (@devs) {
+
+       chomp($dev);
+       my ($type, $addr) = split /@/, $dev;
+
+       if (!exists $iomaps{$type}) {
+
+               my $compatible = `fdtget $dtb /$dev compatible 2>/dev/null`;
+               chomp($compatible);
+               my @compats = split ' ', $compatible;
+
+               $iomaps{$type}{compats} = \@compats;
+               $iomaps{$type}{addrs} = [$addr];
+       } else {
+               push @{ $iomaps{$type}{addrs} }, $addr;
+       }
+}
+unlink $dtb;
+
+print <<EOF;
+/*
+ * Generated file. See gen-devtree-iomaps.pl
+ */
+#include "iomaps.h"
+EOF
+print "\nconst struct iomap iomaps[] = {\n";
+foreach my $type (keys %iomaps) {
+
+       my $compats = $iomaps{$type}{compats};
+       my $addrs = $iomaps{$type}{addrs};
+
+       my $nr_compats = $#{ $compats } + 1;
+       if ($nr_compats > $max_nr_compats) {
+               print STDERR "$type has $nr_compats compats, but iomaps can ".
+                       "only support up to $max_nr_compats.\n";
+               splice @{ $compats }, $max_nr_compats;
+       }
+
+       @{ $addrs } = sort @{ $addrs };
+
+       my $nr = $#{ $addrs } + 1;
+       if ($nr > $max_nr_addrs) {
+               print STDERR "$type has $nr addrs, but iomaps can ".
+                       "only support up to $max_nr_addrs.\n";
+               $nr = $max_nr_addrs;
+               splice @{ $addrs }, $nr;
+       }
+
+       @{ $addrs } = map { $_ = sprintf '0x%.8x', hex($_) } @{ $addrs };
+
+       print "{\n";
+       print "\t.type = \"$type\",\n";
+
+       print "\t.compats = {";
+       foreach my $compat (@{ $compats }) {
+               print " \"$compat\",";
+       }
+       print " NULL, },\n";
+
+       print "\t.nr = $nr,\n";
+       print "\t.addrs = {";
+       if ($nr < 5) {
+               print ' ';
+               print join ', ', @{ $addrs };
+               print ", },\n";
+       } else {
+               print "\n";
+               for (my $i = 0; $i < $nr; $i += 5) {
+                       print "\t\t";
+                       my $j = $i;
+                       while ($j < $i + 4 && $j < $nr - 1) {
+                               print $addrs->[$j] . ", ";
+                               ++$j;
+                       }
+                       print $addrs->[$j] . ",\n";
+               }
+               print "\t},\n";
+       }
+       print "},\n";
+}
+print "{\n\t.type = NULL,\n},\n";
+print "};\n";
+exit 0;
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to