|
@@ -0,0 +1,1213 @@
|
|
|
+#!/usr/bin/perl
|
|
|
+
|
|
|
+# Copyright 2016 by Frank Rowand
|
|
|
+# Copyright 2016 by Gaurav Minocha
|
|
|
+#
|
|
|
+# This file is subject to the terms and conditions of the GNU General Public
|
|
|
+# License v2.
|
|
|
+
|
|
|
+use strict 'refs';
|
|
|
+use strict subs;
|
|
|
+
|
|
|
+use Getopt::Long;
|
|
|
+
|
|
|
+$VUFX = "160610a";
|
|
|
+
|
|
|
+$script_name = $0;
|
|
|
+$script_name =~ s|^.*/||;
|
|
|
+
|
|
|
+
|
|
|
+# ----- constants for print_flags()
|
|
|
+
|
|
|
+# Position in string $pr_flags. Range of 0..($num_pr_flags - 1).
|
|
|
+$pr_flag_pos_mcompatible = 0;
|
|
|
+$pr_flag_pos_driver = 1;
|
|
|
+$pr_flag_pos_mdriver = 2;
|
|
|
+$pr_flag_pos_config = 3;
|
|
|
+$pr_flag_pos_mconfig = 4;
|
|
|
+$pr_flag_pos_node_not_enabled = 5;
|
|
|
+$pr_flag_pos_white_list = 6;
|
|
|
+$pr_flag_pos_hard_coded = 7;
|
|
|
+$pr_flag_pos_config_hard_coded = 8;
|
|
|
+$pr_flag_pos_config_none = 9;
|
|
|
+$pr_flag_pos_config_m = 10;
|
|
|
+$pr_flag_pos_config_y = 11;
|
|
|
+$pr_flag_pos_config_test_fail = 12;
|
|
|
+
|
|
|
+$num_pr_flags = $pr_flag_pos_config_test_fail + 1;
|
|
|
+
|
|
|
+# flags in @pr_flag_value must be unique values to allow simple regular
|
|
|
+# expessions to work for --include_flags and --exclude_flags.
|
|
|
+# Convention: use upper case letters for potential issues or problems.
|
|
|
+
|
|
|
+@pr_flag_value = ('M', 'd', 'D', 'c', 'C', 'E', 'W', 'H', 'x', 'n', 'm', 'y', 'F');
|
|
|
+
|
|
|
+@pr_flag_help = (
|
|
|
+ "multiple compatibles found for this node",
|
|
|
+ "driver found for this compatible",
|
|
|
+ "multiple drivers found for this compatible",
|
|
|
+ "kernel config found for this driver",
|
|
|
+ "multiple config options found for this driver",
|
|
|
+ "node is not enabled",
|
|
|
+ "compatible is white listed",
|
|
|
+ "matching driver and/or kernel config is hard coded",
|
|
|
+ "kernel config hard coded in Makefile",
|
|
|
+ "one or more kernel config file options is not set",
|
|
|
+ "one or more kernel config file options is set to 'm'",
|
|
|
+ "one or more kernel config file options is set to 'y'",
|
|
|
+ "one of more kernel config file options fails to have correct value"
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+# -----
|
|
|
+
|
|
|
+%driver_config = (); # driver config array, indexed by driver source file
|
|
|
+%driver_count = (); # driver_cnt, indexed by compatible
|
|
|
+%compat_driver = (); # compatible driver array, indexed by compatible
|
|
|
+%existing_config = (); # existing config symbols present in given config file
|
|
|
+ # expected values are: "y", "m", a decimal number, a
|
|
|
+ # hex number, or a string
|
|
|
+
|
|
|
+# ----- magic compatibles, do not have a driver
|
|
|
+#
|
|
|
+# Will not search for drivers for these compatibles.
|
|
|
+
|
|
|
+%compat_white_list = (
|
|
|
+ 'none' => '1',
|
|
|
+ 'pci' => '1',
|
|
|
+ 'simple-bus' => '1',
|
|
|
+);
|
|
|
+
|
|
|
+# Will not search for drivers for these compatibles.
|
|
|
+#
|
|
|
+# These compatibles have a very large number of false positives.
|
|
|
+#
|
|
|
+# 'hardcoded_no_driver' is a magic value. Other code knows this
|
|
|
+# magic value. Do not use 'no_driver' here!
|
|
|
+#
|
|
|
+# Revisit each 'hardcoded_no_driver' to see how the compatible
|
|
|
+# is used. Are there drivers that can be provided?
|
|
|
+
|
|
|
+%driver_hard_code_list = (
|
|
|
+ 'cache' => ['hardcoded_no_driver'],
|
|
|
+ 'eeprom' => ['hardcoded_no_driver'],
|
|
|
+ 'gpio' => ['hardcoded_no_driver'],
|
|
|
+ 'gpio-keys' => ['drivers/input/keyboard/gpio_keys.c'],
|
|
|
+ 'i2c-gpio' => ['drivers/i2c/busses/i2c-gpio.c'],
|
|
|
+ 'isa' => ['arch/mips/mti-malta/malta-dt.c',
|
|
|
+ 'arch/x86/kernel/devicetree.c'],
|
|
|
+ 'led' => ['hardcoded_no_driver'],
|
|
|
+ 'm25p32' => ['hardcoded_no_driver'],
|
|
|
+ 'm25p64' => ['hardcoded_no_driver'],
|
|
|
+ 'm25p80' => ['hardcoded_no_driver'],
|
|
|
+ 'mtd-ram' => ['drivers/mtd/maps/physmap_of.c'],
|
|
|
+ 'pwm-backlight' => ['drivers/video/backlight/pwm_bl.c'],
|
|
|
+ 'spidev' => ['hardcoded_no_driver'],
|
|
|
+ 'syscon' => ['drivers/mfd/syscon.c'],
|
|
|
+ 'tlv320aic23' => ['hardcoded_no_driver'],
|
|
|
+ 'wm8731' => ['hardcoded_no_driver'],
|
|
|
+);
|
|
|
+
|
|
|
+# Use these config options instead of searching makefiles
|
|
|
+
|
|
|
+%driver_config_hard_code_list = (
|
|
|
+
|
|
|
+ # this one needed even if %driver_hard_code_list is empty
|
|
|
+ 'no_driver' => ['no_config'],
|
|
|
+ 'hardcoded_no_driver' => ['no_config'],
|
|
|
+
|
|
|
+ # drivers/usb/host/ehci-ppc-of.c
|
|
|
+ # drivers/usb/host/ehci-xilinx-of.c
|
|
|
+ # are included from:
|
|
|
+ # drivers/usb/host/ehci-hcd.c
|
|
|
+ # thus the search of Makefile for the included .c files is incorrect
|
|
|
+ # ehci-hcd.c wraps the includes with ifdef CONFIG_USB_EHCI_HCD_..._OF
|
|
|
+ #
|
|
|
+ # similar model for ohci-hcd.c (but no ohci-xilinx-of.c)
|
|
|
+ #
|
|
|
+ # similarly, uhci-hcd.c includes uhci-platform.c
|
|
|
+
|
|
|
+ 'drivers/usb/host/ehci-ppc-of.c' => ['CONFIG_USB_EHCI_HCD',
|
|
|
+ 'CONFIG_USB_EHCI_HCD_PPC_OF'],
|
|
|
+ 'drivers/usb/host/ohci-ppc-of.c' => ['CONFIG_USB_OHCI_HCD',
|
|
|
+ 'CONFIG_USB_OHCI_HCD_PPC_OF'],
|
|
|
+
|
|
|
+ 'drivers/usb/host/ehci-xilinx-of.c' => ['CONFIG_USB_EHCI_HCD',
|
|
|
+ 'CONFIG_USB_EHCI_HCD_XILINX'],
|
|
|
+
|
|
|
+ 'drivers/usb/host/uhci-platform.c' => ['CONFIG_USB_UHCI_HCD',
|
|
|
+ 'CONFIG_USB_UHCI_PLATFORM'],
|
|
|
+
|
|
|
+ # scan_makefile will find only one of these config options:
|
|
|
+ # ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
|
|
|
+ 'arch/arm/mach-imx/platsmp.c' => ['CONFIG_SOC_IMX6 && CONFIG_SMP',
|
|
|
+ 'CONFIG_SOC_LS1021A && CONFIG_SMP'],
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+# 'virt/kvm/arm/.*' are controlled by makefiles in other directories,
|
|
|
+# using relative paths, such as 'KVM := ../../../virt/kvm'. Do not
|
|
|
+# add complexity to find_kconfig() to deal with this. There is a long
|
|
|
+# term intent to change the kvm related makefiles to the normal kernel
|
|
|
+# style. After that is done, this entry can be removed from the
|
|
|
+# black_list_driver.
|
|
|
+
|
|
|
+@black_list_driver = (
|
|
|
+ # kvm no longer a problem after commit 503a62862e8f in 4.7-rc1
|
|
|
+ # 'virt/kvm/arm/.*',
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+sub usage()
|
|
|
+{
|
|
|
+ print
|
|
|
+"
|
|
|
+Usage: $script_name [options] device-tree...
|
|
|
+
|
|
|
+ device_tree is: dts_file | dtb_file | proc_device-tree
|
|
|
+
|
|
|
+
|
|
|
+Valid options:
|
|
|
+ -c FILE Read kernel config options from FILE
|
|
|
+ --config FILE synonym for 'c'
|
|
|
+ --config-format config file friendly output format
|
|
|
+ --exclude-flag FLAG exclude entries with a matching flag
|
|
|
+ -h Display this message and exit
|
|
|
+ --help synonym for 'h'
|
|
|
+ --black-list-driver use driver black list
|
|
|
+ --white-list-config use config white list
|
|
|
+ --white-list-driver use driver white list
|
|
|
+ --include-flag FLAG include only entries with a matching flag
|
|
|
+ --include-suspect include only entries with an uppercase flag
|
|
|
+ --short-name do not show the path portion of the node name
|
|
|
+ --show-lists report of white and black lists
|
|
|
+ --version Display program version and exit
|
|
|
+
|
|
|
+
|
|
|
+ Report driver source files that match the compatibles in the device
|
|
|
+ tree file and the kernel config options that enable the driver source
|
|
|
+ files.
|
|
|
+
|
|
|
+ This program must be run in the root directory of a Linux kernel
|
|
|
+ source tree.
|
|
|
+
|
|
|
+ The default format is a report that is intended to be easily human
|
|
|
+ scannable.
|
|
|
+
|
|
|
+ An alternate format can be selected by --config-format. This will
|
|
|
+ create output that can easily be edited to create a fragment that can
|
|
|
+ be appended to the existing kernel config file. Each entry consists of
|
|
|
+ multiple lines. The first line reports flags, the node path, compatible
|
|
|
+ value, driver file matching the compatible, configuration options, and
|
|
|
+ current values of the configuration options. For each configuration
|
|
|
+ option, the following lines report the current value and the value that
|
|
|
+ is required for the driver file to be included in the kernel.
|
|
|
+
|
|
|
+ If a large number of drivers or config options is listed for a node,
|
|
|
+ and the '$pr_flag_value[$pr_flag_pos_hard_coded]' flag is set consider using --white-list-config and/or
|
|
|
+ --white-list-driver. If the white list option suppresses the correct
|
|
|
+ entry please report that as a bug.
|
|
|
+
|
|
|
+ CAUTION:
|
|
|
+ This program uses heuristics to guess which driver(s) support each
|
|
|
+ compatible string and which config option(s) enables the driver(s).
|
|
|
+ Do not believe that the reported information is fully correct.
|
|
|
+ This program is intended to aid the process of determining the
|
|
|
+ proper kernel configuration for a device tree, but this is not
|
|
|
+ a fully automated process -- human involvement may still be
|
|
|
+ required!
|
|
|
+
|
|
|
+ The driver match heuristic used is to search for source files
|
|
|
+ containing the compatible string enclosed in quotes.
|
|
|
+
|
|
|
+ This program might not be able to find all drivers matching a
|
|
|
+ compatible string.
|
|
|
+
|
|
|
+ Some makefiles are overly clever. This program was not made
|
|
|
+ complex enough to handle them. If no config option is listed
|
|
|
+ for a driver, look at the makefile for the driver source file.
|
|
|
+ Even if a config option is listed for a driver, some other
|
|
|
+ available config options may not be listed.
|
|
|
+
|
|
|
+ FLAG values:
|
|
|
+";
|
|
|
+
|
|
|
+ for ($k = 0; $k < $num_pr_flags; $k++) {
|
|
|
+ printf " %s %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
|
|
|
+ }
|
|
|
+
|
|
|
+ print
|
|
|
+"
|
|
|
+ Upper case letters indicate potential issues or problems.
|
|
|
+
|
|
|
+ The flag:
|
|
|
+
|
|
|
+";
|
|
|
+
|
|
|
+ $k = $pr_flag_pos_hard_coded;
|
|
|
+ printf " %s %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
|
|
|
+
|
|
|
+ print
|
|
|
+"
|
|
|
+ will be set if the config or driver is in the white lists, even if
|
|
|
+ --white-list-config and --white-list-driver are not specified.
|
|
|
+ This is a hint that 1) many of these reported lines are likely to
|
|
|
+ be incorrect, and 2) using those options will reduce the number of
|
|
|
+ drivers and/or config options reported.
|
|
|
+
|
|
|
+ --white-list-config and --white-list-driver may not be accurate if this
|
|
|
+ program is not well maintained. Use them with appropriate skepticism.
|
|
|
+ Use the --show-lists option to report the values in the list.
|
|
|
+
|
|
|
+ Return value:
|
|
|
+ 0 if no error
|
|
|
+ 1 error processing command line
|
|
|
+ 2 unable to open or read kernel config file
|
|
|
+ 3 unable to open or process input device tree file(s)
|
|
|
+
|
|
|
+ EXAMPLES:
|
|
|
+
|
|
|
+ dt_to_config arch/arm/boot/dts/my_dts_file.dts
|
|
|
+
|
|
|
+ Basic report.
|
|
|
+
|
|
|
+ dt_to_config \\
|
|
|
+ --config \${KBUILD_OUTPUT}/.config \\
|
|
|
+ arch/\${ARCH}/boot/dts/my_dts_file.dts
|
|
|
+
|
|
|
+ Full report, with config file issues noted.
|
|
|
+
|
|
|
+ dt_to_config --include-suspect \\
|
|
|
+ --config \${KBUILD_OUTPUT}/.config \\
|
|
|
+ arch/\${ARCH}/boot/dts/my_dts_file.dts
|
|
|
+
|
|
|
+ Report of node / compatible string / driver tuples that should
|
|
|
+ be further investigated. A node may have multiple compatible
|
|
|
+ strings. A compatible string may be matched by multiple drivers.
|
|
|
+ A driver may have config file issues noted. The compatible string
|
|
|
+ and/or driver may be in the white lists.
|
|
|
+
|
|
|
+ dt_to_config --include-suspect --config-format \\
|
|
|
+ --config ${KBUILD_OUTPUT}/.config \\
|
|
|
+ arch/\${ARCH}/boot/dts/my_dts_file.dts
|
|
|
+
|
|
|
+ Report of node / compatible string / driver tuples that should
|
|
|
+ be further investigated. The report can be edited to uncomment
|
|
|
+ the config options to select the desired tuple for a given node.
|
|
|
+ A node may have multiple compatible strings. A compatible string
|
|
|
+ may be matched by multiple drivers. A driver may have config file
|
|
|
+ issues noted. The compatible string and/or driver may be in the
|
|
|
+ white lists.
|
|
|
+
|
|
|
+";
|
|
|
+}
|
|
|
+
|
|
|
+sub set_flag()
|
|
|
+{
|
|
|
+ # pr_flags_ref is a reference to $pr_flags
|
|
|
+
|
|
|
+ my $pr_flags_ref = shift;
|
|
|
+ my $pos = shift;
|
|
|
+
|
|
|
+ substr $$pr_flags_ref, $pos, 1, $pr_flag_value[$pos];
|
|
|
+
|
|
|
+ return $pr_flags;
|
|
|
+}
|
|
|
+
|
|
|
+sub print_flags()
|
|
|
+{
|
|
|
+ # return 1 if anything printed, else 0
|
|
|
+
|
|
|
+ # some fields of pn_arg_ref might not be used in this function, but
|
|
|
+ # extract all of them anyway.
|
|
|
+ my $pn_arg_ref = shift;
|
|
|
+
|
|
|
+ my $compat = $pn_arg_ref->{compat};
|
|
|
+ my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
|
|
|
+ my $config = $pn_arg_ref->{config};
|
|
|
+ my $config_cnt = $pn_arg_ref->{config_cnt};
|
|
|
+ my $driver = $pn_arg_ref->{driver};
|
|
|
+ my $driver_cnt = $pn_arg_ref->{driver_cnt};
|
|
|
+ my $full_node = $pn_arg_ref->{full_node};
|
|
|
+ my $node = $pn_arg_ref->{node};
|
|
|
+ my $node_enabled = $pn_arg_ref->{node_enabled};
|
|
|
+ my $white_list = $pn_arg_ref->{white_list};
|
|
|
+
|
|
|
+ my $pr_flags = '-' x $num_pr_flags;
|
|
|
+
|
|
|
+
|
|
|
+ # ----- set flags in $pr_flags
|
|
|
+
|
|
|
+ if ($compatible_cnt > 1) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_mcompatible);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($config_cnt > 1) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_mconfig);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($driver_cnt >= 1) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_driver);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($driver_cnt > 1) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_mdriver);
|
|
|
+ }
|
|
|
+
|
|
|
+ # These strings are the same way the linux kernel tests.
|
|
|
+ # The ePapr lists of values is slightly different.
|
|
|
+ if (!(
|
|
|
+ ($node_enabled eq "") ||
|
|
|
+ ($node_enabled eq "ok") ||
|
|
|
+ ($node_enabled eq "okay")
|
|
|
+ )) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_node_not_enabled);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($white_list) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_white_list);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exists($driver_hard_code_list{$compat}) ||
|
|
|
+ (exists($driver_config_hard_code_list{$driver}) &&
|
|
|
+ ($driver ne "no_driver"))) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_hard_coded);
|
|
|
+ }
|
|
|
+
|
|
|
+ my @configs = split(' && ', $config);
|
|
|
+ for $configs (@configs) {
|
|
|
+ $not = $configs =~ /^!/;
|
|
|
+ $configs =~ s/^!//;
|
|
|
+
|
|
|
+ if (($configs ne "no_config") && ($configs ne "no_makefile")) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (($config_cnt >= 1) &&
|
|
|
+ ($configs !~ /CONFIG_/) &&
|
|
|
+ (($configs ne "no_config") && ($configs ne "no_makefile"))) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_hard_coded);
|
|
|
+ }
|
|
|
+
|
|
|
+ my $existing_config = $existing_config{$configs};
|
|
|
+ if ($existing_config eq "m") {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_m);
|
|
|
+ # Possible fail, depends on whether built in or
|
|
|
+ # module is desired.
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
|
|
|
+ } elsif ($existing_config eq "y") {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_y);
|
|
|
+ if ($not) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
|
|
|
+ }
|
|
|
+ } elsif (($config_file) && ($configs =~ /CONFIG_/)) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_none);
|
|
|
+ if (!$not) {
|
|
|
+ &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # ----- include / exclude filters
|
|
|
+
|
|
|
+ if ($include_flag_pattern && ($pr_flags !~ m/$include_flag_pattern/)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($exclude_flag_pattern && ($pr_flags =~ m/$exclude_flag_pattern/)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($config_format) {
|
|
|
+ print "# ";
|
|
|
+ }
|
|
|
+ print "$pr_flags : ";
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub print_node()
|
|
|
+{
|
|
|
+ # return number of lines printed
|
|
|
+
|
|
|
+ # some fields of pn_arg_ref might not be used in this function, but
|
|
|
+ # extract all of them anyway.
|
|
|
+ my $pn_arg_ref = shift;
|
|
|
+
|
|
|
+ my $compat = $pn_arg_ref->{compat};
|
|
|
+ my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
|
|
|
+ my $config = $pn_arg_ref->{config};
|
|
|
+ my $config_cnt = $pn_arg_ref->{config_cnt};
|
|
|
+ my $driver = $pn_arg_ref->{driver};
|
|
|
+ my $driver_cnt = $pn_arg_ref->{driver_cnt};
|
|
|
+ my $full_node = $pn_arg_ref->{full_node};
|
|
|
+ my $node = $pn_arg_ref->{node};
|
|
|
+ my $node_enabled = $pn_arg_ref->{node_enabled};
|
|
|
+ my $white_list = $pn_arg_ref->{white_list};
|
|
|
+
|
|
|
+ my $separator;
|
|
|
+
|
|
|
+ if (! &print_flags($pn_arg_ref)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ($short_name) {
|
|
|
+ print "$node";
|
|
|
+ } else {
|
|
|
+ print "$full_node";
|
|
|
+ }
|
|
|
+ print " : $compat : $driver : $config : ";
|
|
|
+
|
|
|
+ my @configs = split(' && ', $config);
|
|
|
+
|
|
|
+ if ($config_file) {
|
|
|
+ for $configs (@configs) {
|
|
|
+ $configs =~ s/^!//;
|
|
|
+ my $existing_config = $existing_config{$configs};
|
|
|
+ if (!$existing_config) {
|
|
|
+ # check for /-m/, /-y/, or /-objs/
|
|
|
+ if ($configs !~ /CONFIG_/) {
|
|
|
+ $existing_config = "x";
|
|
|
+ };
|
|
|
+ };
|
|
|
+ if ($existing_config) {
|
|
|
+ print "$separator", "$existing_config";
|
|
|
+ $separator = ", ";
|
|
|
+ } else {
|
|
|
+ print "$separator", "n";
|
|
|
+ $separator = ", ";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ print "none";
|
|
|
+ }
|
|
|
+
|
|
|
+ print "\n";
|
|
|
+
|
|
|
+ if ($config_format) {
|
|
|
+ for $configs (@configs) {
|
|
|
+ $not = $configs =~ /^!/;
|
|
|
+ $configs =~ s/^!//;
|
|
|
+ my $existing_config = $existing_config{$configs};
|
|
|
+
|
|
|
+ if ($not) {
|
|
|
+ if ($configs !~ /CONFIG_/) {
|
|
|
+ print "# $configs\n";
|
|
|
+ } elsif ($existing_config eq "m") {
|
|
|
+ print "# $configs is m\n";
|
|
|
+ print "# $configs=n\n";
|
|
|
+ } elsif ($existing_config eq "y") {
|
|
|
+ print "# $configs is set\n";
|
|
|
+ print "# $configs=n\n";
|
|
|
+ } else {
|
|
|
+ print "# $configs is not set\n";
|
|
|
+ print "# $configs=n\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if ($configs !~ /CONFIG_/) {
|
|
|
+ print "# $configs\n";
|
|
|
+ } elsif ($existing_config eq "m") {
|
|
|
+ print "# $configs is m\n";
|
|
|
+ print "# $configs=y\n";
|
|
|
+ } elsif ($existing_config eq "y") {
|
|
|
+ print "# $configs is set\n";
|
|
|
+ print "# $configs=y\n";
|
|
|
+ } else {
|
|
|
+ print "# $configs is not set\n";
|
|
|
+ print "# $configs=y\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub scan_makefile
|
|
|
+{
|
|
|
+ my $pn_arg_ref = shift;
|
|
|
+ my $driver = shift;
|
|
|
+
|
|
|
+ # ----- Find Kconfig symbols that enable driver
|
|
|
+
|
|
|
+ my ($dir, $base) = $driver =~ m{(.*)/(.*).c};
|
|
|
+
|
|
|
+ my $makefile = $dir . "/Makefile";
|
|
|
+ if (! -r $makefile) {
|
|
|
+ $makefile = $dir . "/Kbuild";
|
|
|
+ }
|
|
|
+ if (! -r $makefile) {
|
|
|
+ my $config;
|
|
|
+
|
|
|
+ $config = 'no_makefile';
|
|
|
+ push @{ $driver_config{$driver} }, $config;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!open(MAKEFILE_FILE, "<", "$makefile")) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ my $line;
|
|
|
+ my @config;
|
|
|
+ my @if_config;
|
|
|
+ my @make_var;
|
|
|
+
|
|
|
+ NEXT_LINE:
|
|
|
+ while ($next_line = <MAKEFILE_FILE>) {
|
|
|
+ my $config;
|
|
|
+ my $if_config;
|
|
|
+ my $ifdef;
|
|
|
+ my $ifeq;
|
|
|
+ my $ifndef;
|
|
|
+ my $ifneq;
|
|
|
+ my $ifdef_config;
|
|
|
+ my $ifeq_config;
|
|
|
+ my $ifndef_config;
|
|
|
+ my $ifneq_config;
|
|
|
+
|
|
|
+ chomp($next_line);
|
|
|
+ $line = $line . $next_line;
|
|
|
+ if ($next_line =~ /\\$/) {
|
|
|
+ $line =~ s/\\$/ /;
|
|
|
+ next NEXT_LINE;
|
|
|
+ }
|
|
|
+ if ($line =~ /^\s*#/) {
|
|
|
+ $line = "";
|
|
|
+ next NEXT_LINE;
|
|
|
+ }
|
|
|
+
|
|
|
+ # ----- condition ... else ... endif
|
|
|
+
|
|
|
+ if ($line =~ /^([ ]\s*|)else\b/) {
|
|
|
+ $if_config = "!" . pop @if_config;
|
|
|
+ $if_config =~ s/^!!//;
|
|
|
+ push @if_config, $if_config;
|
|
|
+ $line =~ s/^([ ]\s*|)else\b//;
|
|
|
+ }
|
|
|
+
|
|
|
+ ($null, $ifeq_config, $ifeq_config_val ) = $line =~ /^([ ]\s*|)ifeq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
|
|
|
+ ($null, $ifneq_config, $ifneq_config_val) = $line =~ /^([ ]\s*|)ifneq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
|
|
|
+ ($null, $ifdef_config) = $line =~ /^([ ]\s*|)ifdef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
|
|
|
+ ($null, $ifndef_config) = $line =~ /^([ ]\s*|)ifndef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
|
|
|
+
|
|
|
+ ($null, $ifeq) = $line =~ /^([ ]\s*|)ifeq\b\s*(.*)/;
|
|
|
+ ($null, $ifneq) = $line =~ /^([ ]\s*|)ifneq\b\s*(.*)/;
|
|
|
+ ($null, $ifdef) = $line =~ /^([ ]\s*|)ifdef\b\s*(.*)/;
|
|
|
+ ($null, $ifndef) = $line =~ /^([ ]\s*|)ifndef\b\s*(.*)/;
|
|
|
+
|
|
|
+ # Order of tests is important. Prefer "CONFIG_*" regex match over
|
|
|
+ # less specific regex match.
|
|
|
+ if ($ifdef_config) {
|
|
|
+ $if_config = $ifdef_config;
|
|
|
+ } elsif ($ifeq_config) {
|
|
|
+ if ($ifeq_config_val =~ /y/) {
|
|
|
+ $if_config = $ifeq_config;
|
|
|
+ } else {
|
|
|
+ $if_config = "!" . $ifeq_config;
|
|
|
+ }
|
|
|
+ } elsif ($ifndef_config) {
|
|
|
+ $if_config = "!" . $ifndef_config;
|
|
|
+ } elsif ($ifneq_config) {
|
|
|
+ if ($ifneq_config_val =~ /y/) {
|
|
|
+ $if_config = "!" . $ifneq_config;
|
|
|
+ } else {
|
|
|
+ $if_config = $ifneq_config;
|
|
|
+ }
|
|
|
+ } elsif ($ifdef) {
|
|
|
+ $if_config = $ifdef;
|
|
|
+ } elsif ($ifeq) {
|
|
|
+ $if_config = $ifeq;
|
|
|
+ } elsif ($ifndef) {
|
|
|
+ $if_config = "!" . $ifndef;
|
|
|
+ } elsif ($ifneq) {
|
|
|
+ $if_config = "!" . $ifneq;
|
|
|
+ } else {
|
|
|
+ $if_config = "";
|
|
|
+ }
|
|
|
+ $if_config =~ s/^!!//;
|
|
|
+
|
|
|
+ if ($if_config) {
|
|
|
+ push @if_config, $if_config;
|
|
|
+ $line = "";
|
|
|
+ next NEXT_LINE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($line =~ /^([ ]\s*|)endif\b/) {
|
|
|
+ pop @if_config;
|
|
|
+ $line = "";
|
|
|
+ next NEXT_LINE;
|
|
|
+ }
|
|
|
+
|
|
|
+ # ----- simple CONFIG_* = *.[co] or xxx [+:?]*= *.[co]
|
|
|
+ # Most makefiles select on *.o, but
|
|
|
+ # arch/powerpc/boot/Makefile selects on *.c
|
|
|
+
|
|
|
+ ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$base.[co]\b/;
|
|
|
+
|
|
|
+ # ----- match a make variable instead of *.[co]
|
|
|
+ # Recursively expanded variables are not handled.
|
|
|
+
|
|
|
+ if (!$config) {
|
|
|
+ my $make_var;
|
|
|
+ ($make_var) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$base.[co]\b/;
|
|
|
+ if ($make_var) {
|
|
|
+ if ($make_var =~ /[a-zA-Z0-9]+-[ym]/) {
|
|
|
+ $config = $make_var;
|
|
|
+ } elsif ($make_var =~ /[a-zA-Z0-9]+-objs/) {
|
|
|
+ $config = $make_var;
|
|
|
+ } else {
|
|
|
+ push @make_var, $make_var;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$config) {
|
|
|
+ for $make_var (@make_var) {
|
|
|
+ ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$make_var\b/;
|
|
|
+ last if ($config);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$config) {
|
|
|
+ for $make_var (@make_var) {
|
|
|
+ ($config) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$make_var\b/;
|
|
|
+ last if ($config);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # ----- next if no config found
|
|
|
+
|
|
|
+ if (!$config) {
|
|
|
+ $line = "";
|
|
|
+ next NEXT_LINE;
|
|
|
+ }
|
|
|
+
|
|
|
+ for $if_config (@if_config) {
|
|
|
+ $config = $if_config . " && " . $config;
|
|
|
+ }
|
|
|
+
|
|
|
+ push @{ $driver_config{$driver} }, $config;
|
|
|
+
|
|
|
+ $line = "";
|
|
|
+ }
|
|
|
+
|
|
|
+ close(MAKEFILE_FILE);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub find_kconfig
|
|
|
+{
|
|
|
+ my $pn_arg_ref = shift;
|
|
|
+ my $driver = shift;
|
|
|
+
|
|
|
+ my $lines_printed = 0;
|
|
|
+ my @configs;
|
|
|
+
|
|
|
+ if (!@{ $driver_config{$driver} }) {
|
|
|
+ &scan_makefile($pn_arg_ref, $driver);
|
|
|
+ if (!@{ $driver_config{$driver} }) {
|
|
|
+ push @{ $driver_config{$driver} }, "no_config";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @configs = @{ $driver_config{$driver} };
|
|
|
+
|
|
|
+ $$pn_arg_ref{config_cnt} = $#configs + 1;
|
|
|
+ for my $config (@configs) {
|
|
|
+ $$pn_arg_ref{config} = $config;
|
|
|
+ $lines_printed += &print_node($pn_arg_ref);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $lines_printed;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub handle_compatible()
|
|
|
+{
|
|
|
+ my $full_node = shift;
|
|
|
+ my $node = shift;
|
|
|
+ my $compatible = shift;
|
|
|
+ my $node_enabled = shift;
|
|
|
+
|
|
|
+ my $compat;
|
|
|
+ my $lines_printed = 0;
|
|
|
+ my %pn_arg = ();
|
|
|
+
|
|
|
+ return if (!$node or !$compatible);
|
|
|
+
|
|
|
+ # Do not process compatible property of root node,
|
|
|
+ # it is used to match board, not to bind a driver.
|
|
|
+ return if ($node eq "/");
|
|
|
+
|
|
|
+ $pn_arg{full_node} = $full_node;
|
|
|
+ $pn_arg{node} = $node;
|
|
|
+ $pn_arg{node_enabled} = $node_enabled;
|
|
|
+
|
|
|
+ my @compatibles = split('", "', $compatible);
|
|
|
+
|
|
|
+ $compatibles[0] =~ s/^"//;
|
|
|
+ $compatibles[$#compatibles] =~ s/"$//;
|
|
|
+
|
|
|
+ $pn_arg{compatible_cnt} = $#compatibles + 1;
|
|
|
+
|
|
|
+ COMPAT:
|
|
|
+ for $compat (@compatibles) {
|
|
|
+
|
|
|
+ $pn_arg{compat} = $compat;
|
|
|
+ $pn_arg{driver_cnt} = 0;
|
|
|
+ $pn_arg{white_list} = 0;
|
|
|
+
|
|
|
+ if (exists($compat_white_list{$compat})) {
|
|
|
+ $pn_arg{white_list} = 1;
|
|
|
+ $pn_arg{driver} = "no_driver";
|
|
|
+ $pn_arg{config_cnt} = 1;
|
|
|
+ $pn_arg{config} = "no_config";
|
|
|
+ $lines_printed += &print_node(\%pn_arg);
|
|
|
+ next COMPAT;
|
|
|
+ }
|
|
|
+
|
|
|
+ # ----- if compat previously seen, use cached info
|
|
|
+
|
|
|
+ if (exists($compat_driver{$compat})) {
|
|
|
+ for my $driver (@{ $compat_driver{$compat} }) {
|
|
|
+ $pn_arg{driver} = $driver;
|
|
|
+ $pn_arg{driver_cnt} = $driver_count{$compat};
|
|
|
+ $pn_arg{config_cnt} = $#{ $driver_config{$driver}} + 1;
|
|
|
+
|
|
|
+ for my $config (@{ $driver_config{$driver} }) {
|
|
|
+ $pn_arg{config} = $config;
|
|
|
+ $lines_printed += &print_node(\%pn_arg);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!@{ $driver_config{$driver} }) {
|
|
|
+ # no config cached yet
|
|
|
+ # $driver in %driver_hard_code_list
|
|
|
+ # but not %driver_config_hard_code_list
|
|
|
+ $lines_printed += &find_kconfig(\%pn_arg, $driver);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ next COMPAT;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ # ----- Find drivers (source files that contain compatible)
|
|
|
+
|
|
|
+ # this will miss arch/sparc/include/asm/parport.h
|
|
|
+ # It is better to move the compatible out of the .h
|
|
|
+ # than to add *.h. to the files list, because *.h generates
|
|
|
+ # a lot of false negatives.
|
|
|
+ my $files = '"*.c"';
|
|
|
+ my $drivers = `git grep -l '"$compat"' -- $files`;
|
|
|
+ chomp($drivers);
|
|
|
+ if ($drivers eq "") {
|
|
|
+ $pn_arg{driver} = "no_driver";
|
|
|
+ $pn_arg{config_cnt} = 1;
|
|
|
+ $pn_arg{config} = "no_config";
|
|
|
+ push @{ $compat_driver{$compat} }, "no_driver";
|
|
|
+ $lines_printed += &print_node(\%pn_arg);
|
|
|
+ next COMPAT;
|
|
|
+ }
|
|
|
+
|
|
|
+ my @drivers = split("\n", $drivers);
|
|
|
+ $driver_count{$compat} = $#drivers + 1;
|
|
|
+ $pn_arg{driver_cnt} = $#drivers + 1;
|
|
|
+
|
|
|
+ DRIVER:
|
|
|
+ for my $driver (@drivers) {
|
|
|
+ push @{ $compat_driver{$compat} }, $driver;
|
|
|
+ $pn_arg{driver} = $driver;
|
|
|
+
|
|
|
+ # ----- if driver previously seen, use cached info
|
|
|
+
|
|
|
+ $pn_arg{config_cnt} = $#{ $driver_config{$driver} } + 1;
|
|
|
+ for my $config (@{ $driver_config{$driver} }) {
|
|
|
+ $pn_arg{config} = $config;
|
|
|
+ $lines_printed += &print_node(\%pn_arg);
|
|
|
+ }
|
|
|
+ if (@{ $driver_config{$driver} }) {
|
|
|
+ next DRIVER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($black_list_driver) {
|
|
|
+ for $black (@black_list_driver) {
|
|
|
+ next DRIVER if ($driver =~ /^$black$/);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ # ----- Find Kconfig symbols that enable driver
|
|
|
+
|
|
|
+ $lines_printed += &find_kconfig(\%pn_arg, $driver);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # White space (line) between nodes for readability.
|
|
|
+ # Each node may report several compatibles.
|
|
|
+ # For each compatible, multiple drivers may be reported.
|
|
|
+ # For each driver, multiple CONFIG_ options may be reported.
|
|
|
+ if ($lines_printed) {
|
|
|
+ print "\n";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+sub read_dts()
|
|
|
+{
|
|
|
+ my $file = shift;
|
|
|
+
|
|
|
+ my $compatible = "";
|
|
|
+ my $line;
|
|
|
+ my $node = "";
|
|
|
+ my $node_enabled = "";
|
|
|
+
|
|
|
+ if (! -r $file) {
|
|
|
+ print STDERR "file '$file' is not readable or does not exist\n";
|
|
|
+ exit 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!open(DT_FILE, "-|", "$dtx_diff $file")) {
|
|
|
+ print STDERR "\n";
|
|
|
+ print STDERR "shell command failed:\n";
|
|
|
+ print STDERR " $dtx_diff $file\n";
|
|
|
+ print STDERR "\n";
|
|
|
+ exit 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ FILE:
|
|
|
+ while ($line = <DT_FILE>) {
|
|
|
+ chomp($line);
|
|
|
+
|
|
|
+ if ($line =~ /{/) {
|
|
|
+
|
|
|
+ &handle_compatible($full_node, $node, $compatible,
|
|
|
+ $node_enabled);
|
|
|
+
|
|
|
+ while ($end_node_count-- > 0) {
|
|
|
+ pop @full_node;
|
|
|
+ };
|
|
|
+ $end_node_count = 0;
|
|
|
+ $full_node = @full_node[-1];
|
|
|
+
|
|
|
+ $node = $line;
|
|
|
+ $node =~ s/^\s*(.*)\s+\{.*/$1/;
|
|
|
+ $node =~ s/.*: //;
|
|
|
+ if ($node eq '/' ) {
|
|
|
+ $full_node = '/';
|
|
|
+ } elsif ($full_node ne '/') {
|
|
|
+ $full_node = $full_node . '/' . $node;
|
|
|
+ } else {
|
|
|
+ $full_node = '/' . $node;
|
|
|
+ }
|
|
|
+ push @full_node, $full_node;
|
|
|
+
|
|
|
+ $compatible = "";
|
|
|
+ $node_enabled = "";
|
|
|
+ next FILE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($line =~ /}/) {
|
|
|
+ $end_node_count++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($line =~ /(\s+|^)status =/) {
|
|
|
+ $node_enabled = $line;
|
|
|
+ $node_enabled =~ s/^\t*//;
|
|
|
+ $node_enabled =~ s/^status = "//;
|
|
|
+ $node_enabled =~ s/";$//;
|
|
|
+ next FILE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($line =~ /(\s+|^)compatible =/) {
|
|
|
+ # Extract all compatible entries for this device
|
|
|
+ # White space matching here and in handle_compatible() is
|
|
|
+ # precise, because input format is the output of dtc,
|
|
|
+ # which is invoked by dtx_diff.
|
|
|
+ $compatible = $line;
|
|
|
+ $compatible =~ s/^\t*//;
|
|
|
+ $compatible =~ s/^compatible = //;
|
|
|
+ $compatible =~ s/;$//;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &handle_compatible($full_node, $node, $compatible, $node_enabled);
|
|
|
+
|
|
|
+ close(DT_FILE);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub read_config_file()
|
|
|
+{
|
|
|
+ if (! -r $config_file) {
|
|
|
+ print STDERR "file '$config_file' is not readable or does not exist\n";
|
|
|
+ exit 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!open(CONFIG_FILE, "<", "$config_file")) {
|
|
|
+ print STDERR "open $config_file failed\n";
|
|
|
+ exit 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ my @line;
|
|
|
+
|
|
|
+ LINE:
|
|
|
+ while ($line = <CONFIG_FILE>) {
|
|
|
+ chomp($line);
|
|
|
+ next LINE if ($line =~ /^\s*#/);
|
|
|
+ next LINE if ($line =~ /^\s*$/);
|
|
|
+ @line = split /=/, $line;
|
|
|
+ $existing_config{@line[0]} = @line[1];
|
|
|
+ }
|
|
|
+
|
|
|
+ close(CONFIG_FILE);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub cmd_line_err()
|
|
|
+{
|
|
|
+ my $msg = shift;
|
|
|
+
|
|
|
+ print STDERR "\n";
|
|
|
+ print STDERR " ERROR processing command line options\n";
|
|
|
+ print STDERR " $msg\n" if ($msg ne "");
|
|
|
+ print STDERR "\n";
|
|
|
+ print STDERR " For help, type '$script_name --help'\n";
|
|
|
+ print STDERR "\n";
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# -----------------------------------------------------------------------------
|
|
|
+# program entry point
|
|
|
+
|
|
|
+Getopt::Long::Configure("no_ignore_case", "bundling");
|
|
|
+
|
|
|
+if (!GetOptions(
|
|
|
+ "c=s" => \$config_file,
|
|
|
+ "config=s" => \$config_file,
|
|
|
+ "config-format" => \$config_format,
|
|
|
+ "exclude-flag=s" => \@exclude_flag,
|
|
|
+ "h" => \$help,
|
|
|
+ "help" => \$help,
|
|
|
+ "black-list-driver" => \$black_list_driver,
|
|
|
+ "white-list-config" => \$white_list_config,
|
|
|
+ "white-list-driver" => \$white_list_driver,
|
|
|
+ "include-flag=s" => \@include_flag,
|
|
|
+ "include-suspect" => \$include_suspect,
|
|
|
+ "short-name" => \$short_name,
|
|
|
+ "show-lists" => \$show_lists,
|
|
|
+ "version" => \$version,
|
|
|
+ )) {
|
|
|
+
|
|
|
+ &cmd_line_err();
|
|
|
+
|
|
|
+ exit 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+my $exit_after_messages = 0;
|
|
|
+
|
|
|
+if ($version) {
|
|
|
+ print STDERR "\n$script_name $VUFX\n\n";
|
|
|
+ $exit_after_messages = 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if ($help) {
|
|
|
+ &usage;
|
|
|
+ $exit_after_messages = 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if ($show_lists) {
|
|
|
+
|
|
|
+ print "\n";
|
|
|
+ print "These compatibles are hard coded to have no driver.\n";
|
|
|
+ print "\n";
|
|
|
+ for my $compat (sort keys %compat_white_list) {
|
|
|
+ print " $compat\n";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ print "\n\n";
|
|
|
+ print "The driver for these compatibles is hard coded (white list).\n";
|
|
|
+ print "\n";
|
|
|
+ my $max_compat_len = 0;
|
|
|
+ for my $compat (sort keys %driver_hard_code_list) {
|
|
|
+ if (length $compat > $max_compat_len) {
|
|
|
+ $max_compat_len = length $compat;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for my $compat (sort keys %driver_hard_code_list) {
|
|
|
+ if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
|
|
|
+ my $first = 1;
|
|
|
+ for my $driver (@{ $driver_hard_code_list{$compat} }) {
|
|
|
+ if ($first) {
|
|
|
+ print " $compat";
|
|
|
+ print " " x ($max_compat_len - length $compat);
|
|
|
+ $first = 0;
|
|
|
+ } else {
|
|
|
+ print " ", " " x $max_compat_len;
|
|
|
+ }
|
|
|
+ print " $driver\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ print "\n\n";
|
|
|
+ print "The configuration option for these drivers is hard coded (white list).\n";
|
|
|
+ print "\n";
|
|
|
+ my $max_driver_len = 0;
|
|
|
+ for my $driver (sort keys %driver_config_hard_code_list) {
|
|
|
+ if (length $driver > $max_driver_len) {
|
|
|
+ $max_driver_len = length $driver;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for my $driver (sort keys %driver_config_hard_code_list) {
|
|
|
+ if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
|
|
|
+ my $first = 1;
|
|
|
+ for my $config (@{ $driver_config_hard_code_list{$driver} }) {
|
|
|
+ if ($first) {
|
|
|
+ print " $driver";
|
|
|
+ print " " x ($max_driver_len - length $driver);
|
|
|
+ $first = 0;
|
|
|
+ } else {
|
|
|
+ print " ", " " x $max_driver_len;
|
|
|
+ }
|
|
|
+ print " $config\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ print "\n\n";
|
|
|
+ print "These drivers are black listed.\n";
|
|
|
+ print "\n";
|
|
|
+ for my $driver (@black_list_driver) {
|
|
|
+ print " $driver\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ print "\n";
|
|
|
+
|
|
|
+ $exit_after_messages = 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if ($exit_after_messages) {
|
|
|
+ exit 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+$exclude_flag_pattern = "[";
|
|
|
+for my $exclude_flag (@exclude_flag) {
|
|
|
+ $exclude_flag_pattern = $exclude_flag_pattern . $exclude_flag;
|
|
|
+}
|
|
|
+$exclude_flag_pattern = $exclude_flag_pattern . "]";
|
|
|
+# clean up if empty
|
|
|
+$exclude_flag_pattern =~ s/^\[\]$//;
|
|
|
+
|
|
|
+
|
|
|
+$include_flag_pattern = "[";
|
|
|
+for my $include_flag (@include_flag) {
|
|
|
+ $include_flag_pattern = $include_flag_pattern . $include_flag;
|
|
|
+}
|
|
|
+$include_flag_pattern = $include_flag_pattern . "]";
|
|
|
+# clean up if empty
|
|
|
+$include_flag_pattern =~ s/^\[\]$//;
|
|
|
+
|
|
|
+
|
|
|
+if ($exclude_flag_pattern) {
|
|
|
+ my $found = 0;
|
|
|
+ for $pr_flag_value (@pr_flag_value) {
|
|
|
+ if ($exclude_flag_pattern =~ m/$pr_flag_value/) {
|
|
|
+ $found = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!$found) {
|
|
|
+ &cmd_line_err("invalid value for FLAG in --exclude-flag\n");
|
|
|
+ exit 1
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if ($include_flag_pattern) {
|
|
|
+ my $found = 0;
|
|
|
+ for $pr_flag_value (@pr_flag_value) {
|
|
|
+ if ($include_flag_pattern =~ m/$pr_flag_value/) {
|
|
|
+ $found = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!$found) {
|
|
|
+ &cmd_line_err("invalid value for FLAG in --include-flag\n");
|
|
|
+ exit 1
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if ($include_suspect) {
|
|
|
+ $include_flag_pattern =~ s/\[//;
|
|
|
+ $include_flag_pattern =~ s/\]//;
|
|
|
+ $include_flag_pattern = "[" . $include_flag_pattern . "A-Z]";
|
|
|
+}
|
|
|
+
|
|
|
+if ($exclude_flag_pattern =~ m/$include_flag_pattern/) {
|
|
|
+ &cmd_line_err("the same flag appears in both --exclude-flag and --include-flag or --include-suspect\n");
|
|
|
+ exit 1
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# ($#ARGV < 0) is valid for --help, --version
|
|
|
+if ($#ARGV < 0) {
|
|
|
+ &cmd_line_err("device-tree... is required");
|
|
|
+ exit 1
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if ($config_file) {
|
|
|
+ &read_config_file();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# avoid pushing duplicates for this value
|
|
|
+$driver = "hardcoded_no_driver";
|
|
|
+for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
|
|
|
+ push @{ $driver_config{$driver} }, $config;
|
|
|
+}
|
|
|
+
|
|
|
+if ($white_list_driver) {
|
|
|
+ for my $compat (keys %driver_hard_code_list) {
|
|
|
+ for my $driver (@{ $driver_hard_code_list{$compat} }) {
|
|
|
+ push @{ $compat_driver{$compat} }, $driver;
|
|
|
+ if ($driver ne "hardcoded_no_driver") {
|
|
|
+ $driver_count{$compat} = scalar @{ $compat_driver{$compat} };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if ($white_list_config) {
|
|
|
+ for my $driver (keys %driver_config_hard_code_list) {
|
|
|
+ if ($driver ne "hardcoded_no_driver") {
|
|
|
+ for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
|
|
|
+ push @{ $driver_config{$driver} }, $config;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (-x "scripts/dtc/dtx_diff") {
|
|
|
+ $dtx_diff = "scripts/dtc/dtx_diff";
|
|
|
+} else {
|
|
|
+
|
|
|
+ print STDERR "\n";
|
|
|
+ print STDERR "$script_name must be run from the root directory of a Linux kernel tree\n";
|
|
|
+ print STDERR "\n";
|
|
|
+ exit 3;
|
|
|
+}
|
|
|
+
|
|
|
+for $file (@ARGV) {
|
|
|
+ &read_dts($file);
|
|
|
+}
|