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