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