x86/smpboot: Init apic mapping before usage
[cascardo/linux.git] / scripts / dtc / dt_to_config
1 #!/usr/bin/perl
2
3 # Copyright 2016 by Frank Rowand
4 # Copyright 2016 by Gaurav Minocha
5 #
6 # This file is subject to the terms and conditions of the GNU General Public
7 # License v2.
8
9 use strict 'refs';
10 use strict subs;
11
12 use Getopt::Long;
13
14 $VUFX = "160610a";
15
16 $script_name = $0;
17 $script_name =~ s|^.*/||;
18
19
20 # ----- constants for print_flags()
21
22 # Position in string $pr_flags.  Range of 0..($num_pr_flags - 1).
23 $pr_flag_pos_mcompatible       = 0;
24 $pr_flag_pos_driver            = 1;
25 $pr_flag_pos_mdriver           = 2;
26 $pr_flag_pos_config            = 3;
27 $pr_flag_pos_mconfig           = 4;
28 $pr_flag_pos_node_not_enabled  = 5;
29 $pr_flag_pos_white_list        = 6;
30 $pr_flag_pos_hard_coded        = 7;
31 $pr_flag_pos_config_hard_coded = 8;
32 $pr_flag_pos_config_none       = 9;
33 $pr_flag_pos_config_m          = 10;
34 $pr_flag_pos_config_y          = 11;
35 $pr_flag_pos_config_test_fail  = 12;
36
37 $num_pr_flags = $pr_flag_pos_config_test_fail + 1;
38
39 # flags in @pr_flag_value must be unique values to allow simple regular
40 # expessions to work for --include_flags and --exclude_flags.
41 # Convention: use upper case letters for potential issues or problems.
42
43 @pr_flag_value = ('M', 'd', 'D', 'c', 'C', 'E', 'W', 'H', 'x', 'n', 'm', 'y', 'F');
44
45 @pr_flag_help = (
46     "multiple compatibles found for this node",
47     "driver found for this compatible",
48     "multiple drivers found for this compatible",
49     "kernel config found for this driver",
50     "multiple config options found for this driver",
51     "node is not enabled",
52     "compatible is white listed",
53     "matching driver and/or kernel config is hard coded",
54     "kernel config hard coded in Makefile",
55     "one or more kernel config file options is not set",
56     "one or more kernel config file options is set to 'm'",
57     "one or more kernel config file options is set to 'y'",
58     "one of more kernel config file options fails to have correct value"
59 );
60
61
62 # -----
63
64 %driver_config = ();   # driver config array, indexed by driver source file
65 %driver_count = ();    # driver_cnt, indexed by compatible
66 %compat_driver = ();   # compatible driver array, indexed by compatible
67 %existing_config = (); # existing config symbols present in given config file
68                        # expected values are: "y", "m", a decimal number, a
69                        # hex number, or a string
70
71 # ----- magic compatibles, do not have a driver
72 #
73 # Will not search for drivers for these compatibles.
74
75 %compat_white_list = (
76        'none'                  => '1',
77        'pci'                   => '1',
78        'simple-bus'            => '1',
79 );
80
81 # Will not search for drivers for these compatibles.
82 #
83 # These compatibles have a very large number of false positives.
84 #
85 # 'hardcoded_no_driver' is a magic value.  Other code knows this
86 # magic value.  Do not use 'no_driver' here!
87 #
88 # Revisit each 'hardcoded_no_driver' to see how the compatible
89 # is used.  Are there drivers that can be provided?
90
91 %driver_hard_code_list = (
92        'cache'                 => ['hardcoded_no_driver'],
93        'eeprom'                => ['hardcoded_no_driver'],
94        'gpio'                  => ['hardcoded_no_driver'],
95        'gpio-keys'             => ['drivers/input/keyboard/gpio_keys.c'],
96        'i2c-gpio'              => ['drivers/i2c/busses/i2c-gpio.c'],
97        'isa'                   => ['arch/mips/mti-malta/malta-dt.c',
98                                     'arch/x86/kernel/devicetree.c'],
99        'led'                   => ['hardcoded_no_driver'],
100        'm25p32'                => ['hardcoded_no_driver'],
101        'm25p64'                => ['hardcoded_no_driver'],
102        'm25p80'                => ['hardcoded_no_driver'],
103        'mtd-ram'               => ['drivers/mtd/maps/physmap_of.c'],
104        'pwm-backlight'         => ['drivers/video/backlight/pwm_bl.c'],
105        'spidev'                => ['hardcoded_no_driver'],
106        'syscon'                => ['drivers/mfd/syscon.c'],
107        'tlv320aic23'           => ['hardcoded_no_driver'],
108        'wm8731'                => ['hardcoded_no_driver'],
109 );
110
111 # Use these config options instead of searching makefiles
112
113 %driver_config_hard_code_list = (
114
115        # this one needed even if %driver_hard_code_list is empty
116        'no_driver'                             => ['no_config'],
117        'hardcoded_no_driver'                   => ['no_config'],
118
119        # drivers/usb/host/ehci-ppc-of.c
120        # drivers/usb/host/ehci-xilinx-of.c
121        #  are included from:
122        #    drivers/usb/host/ehci-hcd.c
123        #  thus the search of Makefile for the included .c files is incorrect
124        # ehci-hcd.c wraps the includes with ifdef CONFIG_USB_EHCI_HCD_..._OF
125        #
126        # similar model for ohci-hcd.c (but no ohci-xilinx-of.c)
127        #
128        # similarly, uhci-hcd.c includes uhci-platform.c
129
130        'drivers/usb/host/ehci-ppc-of.c'        => ['CONFIG_USB_EHCI_HCD',
131                                                    'CONFIG_USB_EHCI_HCD_PPC_OF'],
132        'drivers/usb/host/ohci-ppc-of.c'        => ['CONFIG_USB_OHCI_HCD',
133                                                    'CONFIG_USB_OHCI_HCD_PPC_OF'],
134
135        'drivers/usb/host/ehci-xilinx-of.c'     => ['CONFIG_USB_EHCI_HCD',
136                                                    'CONFIG_USB_EHCI_HCD_XILINX'],
137
138        'drivers/usb/host/uhci-platform.c'      => ['CONFIG_USB_UHCI_HCD',
139                                                    'CONFIG_USB_UHCI_PLATFORM'],
140
141        # scan_makefile will find only one of these config options:
142        #    ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
143        'arch/arm/mach-imx/platsmp.c'           => ['CONFIG_SOC_IMX6 && CONFIG_SMP',
144                                                    'CONFIG_SOC_LS1021A && CONFIG_SMP'],
145 );
146
147
148 # 'virt/kvm/arm/.*' are controlled by makefiles in other directories,
149 # using relative paths, such as 'KVM := ../../../virt/kvm'.  Do not
150 # add complexity to find_kconfig() to deal with this.  There is a long
151 # term intent to change the kvm related makefiles to the normal kernel
152 # style.  After that is done, this entry can be removed from the
153 # black_list_driver.
154
155 @black_list_driver = (
156        # kvm no longer a problem after commit 503a62862e8f in 4.7-rc1
157        # 'virt/kvm/arm/.*',
158 );
159
160
161 sub usage()
162 {
163        print
164 "
165 Usage: $script_name [options] device-tree...
166
167     device_tree is: dts_file | dtb_file | proc_device-tree
168
169
170 Valid options:
171      -c FILE             Read kernel config options from FILE
172     --config FILE        synonym for 'c'
173     --config-format      config file friendly output format
174     --exclude-flag FLAG  exclude entries with a matching flag
175      -h                  Display this message and exit
176     --help               synonym for 'h'
177     --black-list-driver  use driver black list
178     --white-list-config  use config white list
179     --white-list-driver  use driver white list
180     --include-flag FLAG  include only entries with a matching flag
181     --include-suspect    include only entries with an uppercase flag
182     --short-name         do not show the path portion of the node name
183     --show-lists         report of white and black lists
184     --version            Display program version and exit
185
186
187   Report driver source files that match the compatibles in the device
188   tree file and the kernel config options that enable the driver source
189   files.
190
191   This program must be run in the root directory of a Linux kernel
192   source tree.
193
194   The default format is a report that is intended to be easily human
195   scannable.
196
197   An alternate format can be selected by --config-format.  This will
198   create output that can easily be edited to create a fragment that can
199   be appended to the existing kernel config file.  Each entry consists of
200   multiple lines.  The first line reports flags, the node path, compatible
201   value, driver file matching the compatible, configuration options, and
202   current values of the configuration options.  For each configuration
203   option, the following lines report the current value and the value that
204   is required for the driver file to be included in the kernel.
205
206   If a large number of drivers or config options is listed for a node,
207   and the '$pr_flag_value[$pr_flag_pos_hard_coded]' flag is set consider using --white-list-config and/or
208   --white-list-driver.  If the white list option suppresses the correct
209   entry please report that as a bug.
210
211   CAUTION:
212      This program uses heuristics to guess which driver(s) support each
213      compatible string and which config option(s) enables the driver(s).
214      Do not believe that the reported information is fully correct.
215      This program is intended to aid the process of determining the
216      proper kernel configuration for a device tree, but this is not
217      a fully automated process -- human involvement may still be
218      required!
219
220      The driver match heuristic used is to search for source files
221      containing the compatible string enclosed in quotes.
222
223      This program might not be able to find all drivers matching a
224      compatible string.
225
226      Some makefiles are overly clever.  This program was not made
227      complex enough to handle them.  If no config option is listed
228      for a driver, look at the makefile for the driver source file.
229      Even if a config option is listed for a driver, some other
230      available config options may not be listed.
231
232   FLAG values:
233 ";
234
235        for ($k = 0; $k < $num_pr_flags; $k++) {
236                printf "     %s   %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
237        }
238
239        print
240 "
241      Upper case letters indicate potential issues or problems.
242
243   The flag:
244
245 ";
246
247        $k = $pr_flag_pos_hard_coded;
248        printf "     %s   %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
249
250        print
251 "
252   will be set if the config or driver is in the white lists, even if
253   --white-list-config and --white-list-driver are not specified.
254   This is a hint that 1) many of these reported lines are likely to
255   be incorrect, and 2) using those options will reduce the number of
256   drivers and/or config options reported.
257
258   --white-list-config and --white-list-driver may not be accurate if this
259   program is not well maintained.  Use them with appropriate skepticism.
260   Use the --show-lists option to report the values in the list.
261
262   Return value:
263     0   if no error
264     1   error processing command line
265     2   unable to open or read kernel config file
266     3   unable to open or process input device tree file(s)
267
268   EXAMPLES:
269
270      dt_to_config arch/arm/boot/dts/my_dts_file.dts
271
272        Basic report.
273
274      dt_to_config \\
275         --config \${KBUILD_OUTPUT}/.config \\
276         arch/\${ARCH}/boot/dts/my_dts_file.dts
277
278        Full report, with config file issues noted.
279
280      dt_to_config --include-suspect \\
281         --config \${KBUILD_OUTPUT}/.config \\
282         arch/\${ARCH}/boot/dts/my_dts_file.dts
283
284        Report of node / compatible string / driver tuples that should
285        be further investigated.  A node may have multiple compatible
286        strings.  A compatible string may be matched by multiple drivers.
287        A driver may have config file issues noted.  The compatible string
288        and/or driver may be in the white lists.
289
290      dt_to_config --include-suspect --config-format \\
291         --config ${KBUILD_OUTPUT}/.config \\
292         arch/\${ARCH}/boot/dts/my_dts_file.dts
293
294        Report of node / compatible string / driver tuples that should
295        be further investigated.  The report can be edited to uncomment
296        the config options to select the desired tuple for a given node.
297        A node may have multiple compatible strings.  A compatible string
298        may be matched by multiple drivers.  A driver may have config file
299        issues noted.  The compatible string and/or driver may be in the
300        white lists.
301
302 ";
303 }
304
305 sub set_flag()
306 {
307        # pr_flags_ref is a reference to $pr_flags
308
309        my $pr_flags_ref = shift;
310        my $pos          = shift;
311
312        substr $$pr_flags_ref, $pos, 1, $pr_flag_value[$pos];
313
314        return $pr_flags;
315 }
316
317 sub print_flags()
318 {
319        # return 1 if anything printed, else 0
320
321        # some fields of pn_arg_ref might not be used in this function, but
322        # extract all of them anyway.
323        my $pn_arg_ref     = shift;
324
325        my $compat         = $pn_arg_ref->{compat};
326        my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
327        my $config         = $pn_arg_ref->{config};
328        my $config_cnt     = $pn_arg_ref->{config_cnt};
329        my $driver         = $pn_arg_ref->{driver};
330        my $driver_cnt     = $pn_arg_ref->{driver_cnt};
331        my $full_node      = $pn_arg_ref->{full_node};
332        my $node           = $pn_arg_ref->{node};
333        my $node_enabled   = $pn_arg_ref->{node_enabled};
334        my $white_list     = $pn_arg_ref->{white_list};
335
336        my $pr_flags       = '-' x $num_pr_flags;
337
338
339        # ----- set flags in $pr_flags
340
341        if ($compatible_cnt > 1) {
342                &set_flag(\$pr_flags, $pr_flag_pos_mcompatible);
343        }
344
345        if ($config_cnt > 1) {
346                &set_flag(\$pr_flags, $pr_flag_pos_mconfig);
347        }
348
349        if ($driver_cnt >= 1) {
350                &set_flag(\$pr_flags, $pr_flag_pos_driver);
351        }
352
353        if ($driver_cnt > 1) {
354                &set_flag(\$pr_flags, $pr_flag_pos_mdriver);
355        }
356
357        # These strings are the same way the linux kernel tests.
358        # The ePapr lists of values is slightly different.
359        if (!(
360              ($node_enabled eq "") ||
361              ($node_enabled eq "ok") ||
362              ($node_enabled eq "okay")
363             )) {
364                &set_flag(\$pr_flags, $pr_flag_pos_node_not_enabled);
365        }
366
367        if ($white_list) {
368                &set_flag(\$pr_flags, $pr_flag_pos_white_list);
369        }
370
371        if (exists($driver_hard_code_list{$compat}) ||
372            (exists($driver_config_hard_code_list{$driver}) &&
373             ($driver ne "no_driver"))) {
374                &set_flag(\$pr_flags, $pr_flag_pos_hard_coded);
375        }
376
377        my @configs = split(' && ', $config);
378        for $configs (@configs) {
379                $not = $configs =~ /^!/;
380                $configs =~ s/^!//;
381
382                if (($configs ne "no_config") && ($configs ne "no_makefile")) {
383                        &set_flag(\$pr_flags, $pr_flag_pos_config);
384                }
385
386                if (($config_cnt >= 1) &&
387                    ($configs !~ /CONFIG_/) &&
388                    (($configs ne "no_config") && ($configs ne "no_makefile"))) {
389                        &set_flag(\$pr_flags, $pr_flag_pos_config_hard_coded);
390                }
391
392                my $existing_config = $existing_config{$configs};
393                if ($existing_config eq "m") {
394                        &set_flag(\$pr_flags, $pr_flag_pos_config_m);
395                        # Possible fail, depends on whether built in or
396                        # module is desired.
397                        &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
398                } elsif ($existing_config eq "y") {
399                        &set_flag(\$pr_flags, $pr_flag_pos_config_y);
400                        if ($not) {
401                                &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
402                        }
403                } elsif (($config_file) && ($configs =~ /CONFIG_/)) {
404                        &set_flag(\$pr_flags, $pr_flag_pos_config_none);
405                        if (!$not) {
406                                &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
407                        }
408                }
409        }
410
411        # ----- include / exclude filters
412
413        if ($include_flag_pattern && ($pr_flags !~ m/$include_flag_pattern/)) {
414                return 0;
415        }
416
417        if ($exclude_flag_pattern && ($pr_flags =~ m/$exclude_flag_pattern/)) {
418                return 0;
419        }
420
421        if ($config_format) {
422                print "# ";
423        }
424        print "$pr_flags : ";
425
426        return 1;
427 }
428
429
430 sub print_node()
431 {
432        # return number of lines printed
433
434        # some fields of pn_arg_ref might not be used in this function, but
435        # extract all of them anyway.
436        my $pn_arg_ref     = shift;
437
438        my $compat         = $pn_arg_ref->{compat};
439        my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
440        my $config         = $pn_arg_ref->{config};
441        my $config_cnt     = $pn_arg_ref->{config_cnt};
442        my $driver         = $pn_arg_ref->{driver};
443        my $driver_cnt     = $pn_arg_ref->{driver_cnt};
444        my $full_node      = $pn_arg_ref->{full_node};
445        my $node           = $pn_arg_ref->{node};
446        my $node_enabled   = $pn_arg_ref->{node_enabled};
447        my $white_list     = $pn_arg_ref->{white_list};
448
449        my $separator;
450
451        if (! &print_flags($pn_arg_ref)) {
452                return 0;
453        }
454
455
456        if ($short_name) {
457                print "$node";
458        } else {
459                print "$full_node";
460        }
461        print " : $compat : $driver : $config : ";
462
463        my @configs = split(' && ', $config);
464
465        if ($config_file) {
466                for $configs (@configs) {
467                        $configs =~ s/^!//;
468                        my $existing_config = $existing_config{$configs};
469                        if (!$existing_config) {
470                                # check for /-m/, /-y/, or /-objs/
471                                if ($configs !~ /CONFIG_/) {
472                                        $existing_config = "x";
473                                };
474                        };
475                        if ($existing_config) {
476                                print "$separator", "$existing_config";
477                                $separator = ", ";
478                        } else {
479                                print "$separator", "n";
480                                $separator = ", ";
481                        }
482                }
483        } else {
484                print "none";
485        }
486
487        print "\n";
488
489        if ($config_format) {
490                for $configs (@configs) {
491                        $not = $configs =~ /^!/;
492                        $configs =~ s/^!//;
493                        my $existing_config = $existing_config{$configs};
494
495                        if ($not) {
496                                if ($configs !~ /CONFIG_/) {
497                                        print "# $configs\n";
498                                } elsif ($existing_config eq "m") {
499                                        print "# $configs is m\n";
500                                        print "# $configs=n\n";
501                                } elsif ($existing_config eq "y") {
502                                        print "# $configs is set\n";
503                                        print "# $configs=n\n";
504                                } else {
505                                        print "# $configs is not set\n";
506                                        print "# $configs=n\n";
507                                }
508
509                        } else {
510                                if ($configs !~ /CONFIG_/) {
511                                        print "# $configs\n";
512                                } elsif ($existing_config eq "m") {
513                                        print "# $configs is m\n";
514                                        print "# $configs=y\n";
515                                } elsif ($existing_config eq "y") {
516                                        print "# $configs is set\n";
517                                        print "# $configs=y\n";
518                                } else {
519                                        print "# $configs is not set\n";
520                                        print "# $configs=y\n";
521                                }
522                        }
523                }
524        }
525
526        return 1;
527 }
528
529
530 sub scan_makefile
531 {
532        my $pn_arg_ref    = shift;
533        my $driver        = shift;
534
535        # ----- Find Kconfig symbols that enable driver
536
537        my ($dir, $base) = $driver =~ m{(.*)/(.*).c};
538
539        my $makefile = $dir . "/Makefile";
540        if (! -r $makefile) {
541                $makefile = $dir . "/Kbuild";
542        }
543        if (! -r $makefile) {
544                my $config;
545
546                $config = 'no_makefile';
547                push @{ $driver_config{$driver} }, $config;
548                return;
549        }
550
551        if (!open(MAKEFILE_FILE, "<", "$makefile")) {
552                return;
553        }
554
555        my $line;
556        my @config;
557        my @if_config;
558        my @make_var;
559
560        NEXT_LINE:
561        while ($next_line = <MAKEFILE_FILE>) {
562                my $config;
563                my $if_config;
564                my $ifdef;
565                my $ifeq;
566                my $ifndef;
567                my $ifneq;
568                my $ifdef_config;
569                my $ifeq_config;
570                my $ifndef_config;
571                my $ifneq_config;
572
573                chomp($next_line);
574                $line = $line . $next_line;
575                if ($next_line =~ /\\$/) {
576                        $line =~ s/\\$/ /;
577                        next NEXT_LINE;
578                }
579                if ($line =~ /^\s*#/) {
580                        $line = "";
581                        next NEXT_LINE;
582                }
583
584                # -----  condition ... else ... endif
585
586                if ($line =~ /^([ ]\s*|)else\b/) {
587                        $if_config = "!" . pop @if_config;
588                        $if_config =~ s/^!!//;
589                        push @if_config, $if_config;
590                        $line =~ s/^([ ]\s*|)else\b//;
591                }
592
593                ($null, $ifeq_config,  $ifeq_config_val )  = $line =~ /^([ ]\s*|)ifeq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
594                ($null, $ifneq_config, $ifneq_config_val)  = $line =~ /^([ ]\s*|)ifneq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
595                ($null, $ifdef_config)                     = $line =~ /^([ ]\s*|)ifdef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
596                ($null, $ifndef_config)                    = $line =~ /^([ ]\s*|)ifndef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
597
598                ($null, $ifeq)   = $line =~ /^([ ]\s*|)ifeq\b\s*(.*)/;
599                ($null, $ifneq)  = $line =~ /^([ ]\s*|)ifneq\b\s*(.*)/;
600                ($null, $ifdef)  = $line =~ /^([ ]\s*|)ifdef\b\s*(.*)/;
601                ($null, $ifndef) = $line =~ /^([ ]\s*|)ifndef\b\s*(.*)/;
602
603                # Order of tests is important.  Prefer "CONFIG_*" regex match over
604                # less specific regex match.
605                if ($ifdef_config) {
606                        $if_config = $ifdef_config;
607                } elsif ($ifeq_config) {
608                        if ($ifeq_config_val =~ /y/) {
609                                $if_config = $ifeq_config;
610                        } else {
611                                $if_config = "!" . $ifeq_config;
612                        }
613                } elsif ($ifndef_config) {
614                        $if_config = "!" . $ifndef_config;
615                } elsif ($ifneq_config) {
616                        if ($ifneq_config_val =~ /y/) {
617                                $if_config = "!" . $ifneq_config;
618                        } else {
619                                $if_config = $ifneq_config;
620                        }
621                } elsif ($ifdef) {
622                        $if_config = $ifdef;
623                } elsif ($ifeq) {
624                        $if_config = $ifeq;
625                } elsif ($ifndef) {
626                        $if_config = "!" . $ifndef;
627                } elsif ($ifneq) {
628                        $if_config = "!" . $ifneq;
629                } else {
630                        $if_config = "";
631                }
632                $if_config =~ s/^!!//;
633
634                if ($if_config) {
635                        push @if_config, $if_config;
636                        $line = "";
637                        next NEXT_LINE;
638                }
639
640                if ($line =~ /^([ ]\s*|)endif\b/) {
641                        pop @if_config;
642                        $line = "";
643                        next NEXT_LINE;
644                }
645
646                # ----- simple CONFIG_* = *.[co]  or  xxx [+:?]*= *.[co]
647                # Most makefiles select on *.o, but
648                # arch/powerpc/boot/Makefile selects on *.c
649
650                ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$base.[co]\b/;
651
652                # ----- match a make variable instead of *.[co]
653                # Recursively expanded variables are not handled.
654
655                if (!$config) {
656                        my $make_var;
657                        ($make_var) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$base.[co]\b/;
658                        if ($make_var) {
659                                if ($make_var =~ /[a-zA-Z0-9]+-[ym]/) {
660                                        $config = $make_var;
661                                } elsif ($make_var =~ /[a-zA-Z0-9]+-objs/) {
662                                        $config = $make_var;
663                                } else {
664                                        push @make_var, $make_var;
665                                }
666                        }
667                }
668
669                if (!$config) {
670                        for $make_var (@make_var) {
671                                ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$make_var\b/;
672                                last if ($config);
673                        }
674                }
675
676                if (!$config) {
677                        for $make_var (@make_var) {
678                                ($config) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$make_var\b/;
679                                last if ($config);
680                        }
681                }
682
683                # ----- next if no config found
684
685                if (!$config) {
686                        $line = "";
687                        next NEXT_LINE;
688                }
689
690                for $if_config (@if_config) {
691                        $config = $if_config . " && " . $config;
692                }
693
694                push @{ $driver_config{$driver} }, $config;
695
696                $line = "";
697        }
698
699        close(MAKEFILE_FILE);
700
701 }
702
703
704 sub find_kconfig
705 {
706        my $pn_arg_ref    = shift;
707        my $driver        = shift;
708
709        my $lines_printed = 0;
710        my @configs;
711
712        if (!@{ $driver_config{$driver} }) {
713                &scan_makefile($pn_arg_ref, $driver);
714                if (!@{ $driver_config{$driver} }) {
715                        push @{ $driver_config{$driver} }, "no_config";
716                }
717        }
718
719        @configs = @{ $driver_config{$driver} };
720
721        $$pn_arg_ref{config_cnt} = $#configs + 1;
722        for my $config (@configs) {
723                $$pn_arg_ref{config} = $config;
724                $lines_printed += &print_node($pn_arg_ref);
725        }
726
727        return $lines_printed;
728 }
729
730
731 sub handle_compatible()
732 {
733        my $full_node     = shift;
734        my $node          = shift;
735        my $compatible    = shift;
736        my $node_enabled  = shift;
737
738        my $compat;
739        my $lines_printed = 0;
740        my %pn_arg        = ();
741
742        return if (!$node or !$compatible);
743
744        # Do not process compatible property of root node,
745        # it is used to match board, not to bind a driver.
746        return if ($node eq "/");
747
748        $pn_arg{full_node}    = $full_node;
749        $pn_arg{node}         = $node;
750        $pn_arg{node_enabled} = $node_enabled;
751
752        my @compatibles = split('", "', $compatible);
753
754        $compatibles[0] =~ s/^"//;
755        $compatibles[$#compatibles] =~ s/"$//;
756
757        $pn_arg{compatible_cnt} = $#compatibles + 1;
758
759        COMPAT:
760        for $compat (@compatibles) {
761
762                $pn_arg{compat}     = $compat;
763                $pn_arg{driver_cnt} = 0;
764                $pn_arg{white_list} = 0;
765
766                if (exists($compat_white_list{$compat})) {
767                        $pn_arg{white_list} = 1;
768                        $pn_arg{driver}     = "no_driver";
769                        $pn_arg{config_cnt} = 1;
770                        $pn_arg{config}     = "no_config";
771                        $lines_printed += &print_node(\%pn_arg);
772                        next COMPAT;
773                }
774
775                # ----- if compat previously seen, use cached info
776
777                if (exists($compat_driver{$compat})) {
778                        for my $driver (@{ $compat_driver{$compat} }) {
779                                $pn_arg{driver}     = $driver;
780                                $pn_arg{driver_cnt} = $driver_count{$compat};
781                                $pn_arg{config_cnt} = $#{ $driver_config{$driver}} + 1;
782
783                                for my $config (@{ $driver_config{$driver} }) {
784                                        $pn_arg{config} = $config;
785                                        $lines_printed += &print_node(\%pn_arg);
786                                }
787
788                                if (!@{ $driver_config{$driver} }) {
789                                        # no config cached yet
790                                        # $driver in %driver_hard_code_list
791                                        # but not %driver_config_hard_code_list
792                                        $lines_printed += &find_kconfig(\%pn_arg, $driver);
793                                }
794                        }
795                        next COMPAT;
796                }
797
798
799                # ----- Find drivers (source files that contain compatible)
800
801                # this will miss arch/sparc/include/asm/parport.h
802                # It is better to move the compatible out of the .h
803                # than to add *.h. to the files list, because *.h generates
804                # a lot of false negatives.
805                my $files = '"*.c"';
806                my $drivers = `git grep -l '"$compat"' -- $files`;
807                chomp($drivers);
808                if ($drivers eq "") {
809                        $pn_arg{driver} = "no_driver";
810                        $pn_arg{config_cnt} = 1;
811                        $pn_arg{config} = "no_config";
812                        push @{ $compat_driver{$compat} }, "no_driver";
813                        $lines_printed += &print_node(\%pn_arg);
814                        next COMPAT;
815                }
816
817                my @drivers = split("\n", $drivers);
818                $driver_count{$compat} = $#drivers + 1;
819                $pn_arg{driver_cnt}    = $#drivers + 1;
820
821                DRIVER:
822                for my $driver (@drivers) {
823                        push @{ $compat_driver{$compat} }, $driver;
824                        $pn_arg{driver} = $driver;
825
826                        # ----- if driver previously seen, use cached info
827
828                        $pn_arg{config_cnt} = $#{ $driver_config{$driver} } + 1;
829                        for my $config (@{ $driver_config{$driver} }) {
830                                $pn_arg{config} = $config;
831                                $lines_printed += &print_node(\%pn_arg);
832                        }
833                        if (@{ $driver_config{$driver} }) {
834                                next DRIVER;
835                        }
836
837                        if ($black_list_driver) {
838                                for $black (@black_list_driver) {
839                                        next DRIVER if ($driver =~ /^$black$/);
840                                }
841                        }
842
843
844                        # ----- Find Kconfig symbols that enable driver
845
846                        $lines_printed += &find_kconfig(\%pn_arg, $driver);
847
848                }
849        }
850
851        # White space (line) between nodes for readability.
852        # Each node may report several compatibles.
853        # For each compatible, multiple drivers may be reported.
854        # For each driver, multiple CONFIG_ options may be reported.
855        if ($lines_printed) {
856                print "\n";
857        }
858 }
859
860 sub read_dts()
861 {
862        my $file         = shift;
863
864        my $compatible   = "";
865        my $line;
866        my $node         = "";
867        my $node_enabled = "";
868
869        if (! -r $file) {
870                print STDERR "file '$file' is not readable or does not exist\n";
871                exit 3;
872        }
873
874        if (!open(DT_FILE, "-|", "$dtx_diff $file")) {
875                print STDERR "\n";
876                print STDERR "shell command failed:\n";
877                print STDERR "   $dtx_diff $file\n";
878                print STDERR "\n";
879                exit 3;
880        }
881
882        FILE:
883        while ($line = <DT_FILE>) {
884                chomp($line);
885
886                if ($line =~ /{/) {
887
888                        &handle_compatible($full_node, $node, $compatible,
889                                           $node_enabled);
890
891                        while ($end_node_count-- > 0) {
892                                pop @full_node;
893                        };
894                        $end_node_count = 0;
895                        $full_node = @full_node[-1];
896
897                        $node = $line;
898                        $node =~ s/^\s*(.*)\s+\{.*/$1/;
899                        $node =~ s/.*: //;
900                        if ($node eq '/' ) {
901                                $full_node = '/';
902                        } elsif ($full_node ne '/') {
903                                $full_node = $full_node . '/' . $node;
904                        } else {
905                                $full_node = '/' . $node;
906                        }
907                        push @full_node, $full_node;
908
909                        $compatible = "";
910                        $node_enabled = "";
911                        next FILE;
912                }
913
914                if ($line =~ /}/) {
915                        $end_node_count++;
916                }
917
918                if ($line =~ /(\s+|^)status =/) {
919                        $node_enabled = $line;
920                        $node_enabled =~ s/^\t*//;
921                        $node_enabled =~ s/^status = "//;
922                        $node_enabled =~ s/";$//;
923                        next FILE;
924                }
925
926                if ($line =~ /(\s+|^)compatible =/) {
927                        # Extract all compatible entries for this device
928                        # White space matching here and in handle_compatible() is
929                        # precise, because input format is the output of dtc,
930                        # which is invoked by dtx_diff.
931                        $compatible = $line;
932                        $compatible =~ s/^\t*//;
933                        $compatible =~ s/^compatible = //;
934                        $compatible =~ s/;$//;
935                }
936        }
937
938        &handle_compatible($full_node, $node, $compatible, $node_enabled);
939
940        close(DT_FILE);
941 }
942
943
944 sub read_config_file()
945 {
946        if (! -r $config_file) {
947                print STDERR "file '$config_file' is not readable or does not exist\n";
948                exit 2;
949        }
950
951        if (!open(CONFIG_FILE, "<", "$config_file")) {
952                print STDERR "open $config_file failed\n";
953                exit 2;
954        }
955
956        my @line;
957
958        LINE:
959        while ($line = <CONFIG_FILE>) {
960                chomp($line);
961                next LINE if ($line =~ /^\s*#/);
962                next LINE if ($line =~ /^\s*$/);
963                @line = split /=/, $line;
964                $existing_config{@line[0]} = @line[1];
965        }
966
967        close(CONFIG_FILE);
968 }
969
970
971 sub cmd_line_err()
972 {
973        my $msg = shift;
974
975        print STDERR "\n";
976        print STDERR "   ERROR processing command line options\n";
977        print STDERR "         $msg\n" if ($msg ne "");
978        print STDERR "\n";
979        print STDERR "   For help, type '$script_name --help'\n";
980        print STDERR "\n";
981 }
982
983
984 # -----------------------------------------------------------------------------
985 # program entry point
986
987 Getopt::Long::Configure("no_ignore_case", "bundling");
988
989 if (!GetOptions(
990        "c=s"               => \$config_file,
991        "config=s"          => \$config_file,
992        "config-format"     => \$config_format,
993        "exclude-flag=s"    => \@exclude_flag,
994        "h"                 => \$help,
995        "help"              => \$help,
996        "black-list-driver" => \$black_list_driver,
997        "white-list-config" => \$white_list_config,
998        "white-list-driver" => \$white_list_driver,
999        "include-flag=s"    => \@include_flag,
1000        "include-suspect"   => \$include_suspect,
1001        "short-name"        => \$short_name,
1002        "show-lists"        => \$show_lists,
1003        "version"           => \$version,
1004        )) {
1005
1006        &cmd_line_err();
1007
1008        exit 1;
1009 }
1010
1011
1012 my $exit_after_messages = 0;
1013
1014 if ($version) {
1015        print STDERR "\n$script_name  $VUFX\n\n";
1016        $exit_after_messages = 1;
1017 }
1018
1019
1020 if ($help) {
1021        &usage;
1022        $exit_after_messages = 1;
1023 }
1024
1025
1026 if ($show_lists) {
1027
1028        print "\n";
1029        print "These compatibles are hard coded to have no driver.\n";
1030        print "\n";
1031        for my $compat (sort keys %compat_white_list) {
1032                print "   $compat\n";
1033        }
1034
1035
1036        print "\n\n";
1037        print "The driver for these compatibles is hard coded (white list).\n";
1038        print "\n";
1039        my $max_compat_len = 0;
1040        for my $compat (sort keys %driver_hard_code_list) {
1041                if (length $compat > $max_compat_len) {
1042                        $max_compat_len = length $compat;
1043                }
1044        }
1045        for my $compat (sort keys %driver_hard_code_list) {
1046                if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
1047                        my $first = 1;
1048                        for my $driver (@{ $driver_hard_code_list{$compat} }) {
1049                                if ($first) {
1050                                        print "   $compat";
1051                                        print " " x ($max_compat_len - length $compat);
1052                                        $first = 0;
1053                                } else {
1054                                        print "   ", " " x $max_compat_len;
1055                                }
1056                                print "  $driver\n";
1057                        }
1058                }
1059        }
1060
1061
1062        print "\n\n";
1063        print "The configuration option for these drivers is hard coded (white list).\n";
1064        print "\n";
1065        my $max_driver_len = 0;
1066        for my $driver (sort keys %driver_config_hard_code_list) {
1067                if (length $driver > $max_driver_len) {
1068                        $max_driver_len = length $driver;
1069                }
1070        }
1071        for my $driver (sort keys %driver_config_hard_code_list) {
1072                if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
1073                        my $first = 1;
1074                        for my $config (@{ $driver_config_hard_code_list{$driver} }) {
1075                                if ($first) {
1076                                        print "   $driver";
1077                                        print " " x ($max_driver_len - length $driver);
1078                                        $first = 0;
1079                                } else {
1080                                        print "   ", " " x $max_driver_len;
1081                                }
1082                                print "  $config\n";
1083                        }
1084                }
1085        }
1086
1087
1088        print "\n\n";
1089        print "These drivers are black listed.\n";
1090        print "\n";
1091        for my $driver (@black_list_driver) {
1092                print "   $driver\n";
1093        }
1094
1095        print "\n";
1096
1097        $exit_after_messages = 1;
1098 }
1099
1100
1101 if ($exit_after_messages) {
1102        exit 0;
1103 }
1104
1105
1106 $exclude_flag_pattern = "[";
1107 for my $exclude_flag (@exclude_flag) {
1108        $exclude_flag_pattern = $exclude_flag_pattern . $exclude_flag;
1109 }
1110 $exclude_flag_pattern = $exclude_flag_pattern . "]";
1111 # clean up if empty
1112 $exclude_flag_pattern =~ s/^\[\]$//;
1113
1114
1115 $include_flag_pattern = "[";
1116 for my $include_flag (@include_flag) {
1117        $include_flag_pattern = $include_flag_pattern . $include_flag;
1118 }
1119 $include_flag_pattern = $include_flag_pattern . "]";
1120 # clean up if empty
1121 $include_flag_pattern =~ s/^\[\]$//;
1122
1123
1124 if ($exclude_flag_pattern) {
1125        my $found = 0;
1126        for $pr_flag_value (@pr_flag_value) {
1127                if ($exclude_flag_pattern =~ m/$pr_flag_value/) {
1128                        $found = 1;
1129                }
1130        }
1131        if (!$found) {
1132                &cmd_line_err("invalid value for FLAG in --exclude-flag\n");
1133                exit 1
1134        }
1135 }
1136
1137 if ($include_flag_pattern) {
1138        my $found = 0;
1139        for $pr_flag_value (@pr_flag_value) {
1140                if ($include_flag_pattern =~ m/$pr_flag_value/) {
1141                        $found = 1;
1142                }
1143        }
1144        if (!$found) {
1145                &cmd_line_err("invalid value for FLAG in --include-flag\n");
1146                exit 1
1147        }
1148 }
1149
1150 if ($include_suspect) {
1151        $include_flag_pattern =~ s/\[//;
1152        $include_flag_pattern =~ s/\]//;
1153        $include_flag_pattern = "[" . $include_flag_pattern . "A-Z]";
1154 }
1155
1156 if ($exclude_flag_pattern =~ m/$include_flag_pattern/) {
1157        &cmd_line_err("the same flag appears in both --exclude-flag and --include-flag or --include-suspect\n");
1158        exit 1
1159 }
1160
1161
1162 # ($#ARGV < 0) is valid for --help, --version
1163 if ($#ARGV < 0) {
1164        &cmd_line_err("device-tree... is required");
1165        exit 1
1166 }
1167
1168
1169 if ($config_file) {
1170        &read_config_file();
1171 }
1172
1173
1174 # avoid pushing duplicates for this value
1175 $driver = "hardcoded_no_driver";
1176 for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
1177        push @{ $driver_config{$driver} }, $config;
1178 }
1179
1180 if ($white_list_driver) {
1181        for my $compat (keys %driver_hard_code_list) {
1182                for my $driver (@{ $driver_hard_code_list{$compat} }) {
1183                        push @{ $compat_driver{$compat} }, $driver;
1184                        if ($driver ne "hardcoded_no_driver") {
1185                                $driver_count{$compat} = scalar @{ $compat_driver{$compat} };
1186                        }
1187                }
1188        }
1189 }
1190
1191 if ($white_list_config) {
1192        for my $driver (keys %driver_config_hard_code_list) {
1193                if ($driver ne "hardcoded_no_driver") {
1194                        for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
1195                                push @{ $driver_config{$driver} }, $config;
1196                        }
1197                }
1198        }
1199 }
1200
1201 if (-x "scripts/dtc/dtx_diff") {
1202        $dtx_diff = "scripts/dtc/dtx_diff";
1203 } else {
1204
1205        print STDERR "\n";
1206        print STDERR "$script_name must be run from the root directory of a Linux kernel tree\n";
1207        print STDERR "\n";
1208        exit 3;
1209 }
1210
1211 for $file (@ARGV) {
1212        &read_dts($file);
1213 }