From: Frank Rowand <frank.rowand@sonymobile.com>

GPL v2

This is a work in progress patch.

TODO:

	- dt_stat is very slow.  Try to improve performance.

/proc/device-tree and /sys/devices provide visibility
into the state and data of

   - Flattened Device Tree
   - Expanded Device Tree
   - Devices

dt_stat probes this information to provide several reports

dt_node_info packages the information from dt_stat in an easy to scan summary

Dependency:
   requires device tree information to be present in sysfs

Tested:
   only on Linux 4.1-rc2 dragonboard

   Might work as early as Linux 3.17.  Please let me know
   if it works for you on versions before 4.1.


-----  EXAMPLE 1  -------------------------------------------------------------

$ dt_node_info coincell
===== devices
/sys/devices/platform/soc/fc4cf000.spmi/spmi-0/0-00/fc4cf000.spmi:pm8941@0:qcom,coincell@2800 /soc/spmi@fc4cf000/pm8941
@0/qcom,coincell@2800

===== nodes
/soc/spmi@fc4cf000/pm8941@0/qcom,coincell@2800 qcom,pm8941-coincell

===== nodes bound to a driver
/soc/spmi@fc4cf000/pm8941@0/qcom,coincell@2800 qcom,pm8941-coincell

===== nodes with a device
/soc/spmi@fc4cf000/pm8941@0/qcom,coincell@2800 qcom,pm8941-coincell

===== nodes not bound to a driver

===== nodes without a device

-----  EXAMPLE 2  -------------------------------------------------------------

$ dt_node_info
===== devices
/sys/devices/platform/clock-controller /clock-controller
/sys/devices/platform/cpu-pmu /cpu-pmu
/sys/devices/platform/soc /soc
/sys/devices/platform/soc/f9000000.interrupt-controller /soc/interrupt-controller@f9000000
/sys/devices/platform/soc/f9012000.power-controller /soc/power-controller@f9012000
/sys/devices/platform/soc/f9016000.clock-controller /soc/clock-controller@f9016000
/sys/devices/platform/soc/f9020000.timer /soc/timer@f9020000
/sys/devices/platform/soc/f9088000.clock-controller /soc/clock-controller@f9088000
/sys/devices/platform/soc/f9089000.power-controller /soc/power-controller@f9089000
/sys/devices/platform/soc/f908a000.clock-controller /soc/clock-controller@f908a000
/sys/devices/platform/soc/f9098000.clock-controller /soc/clock-controller@f9098000
/sys/devices/platform/soc/f9099000.power-controller /soc/power-controller@f9099000
/sys/devices/platform/soc/f909a000.clock-controller /soc/clock-controller@f909a000
/sys/devices/platform/soc/f90a8000.clock-controller /soc/clock-controller@f90a8000
/sys/devices/platform/soc/f90a9000.power-controller /soc/power-controller@f90a9000
/sys/devices/platform/soc/f90aa000.clock-controller /soc/clock-controller@f90aa000
/sys/devices/platform/soc/f90b8000.clock-controller /soc/clock-controller@f90b8000
/sys/devices/platform/soc/f90b9000.power-controller /soc/power-controller@f90b9000
/sys/devices/platform/soc/f90ba000.clock-controller /soc/clock-controller@f90ba000
/sys/devices/platform/soc/f9824900.sdhci /soc/sdhci@f9824900
/sys/devices/platform/soc/f991e000.serial /soc/serial@f991e000
/sys/devices/platform/soc/f9967000.i2c /soc/i2c@f9967000
/sys/devices/platform/soc/f9967000.i2c/i2c-0 /soc/i2c@f9967000
/sys/devices/platform/soc/f9967000.i2c/i2c-0/0-0052 /soc/i2c@f9967000/eeprom@52
/sys/devices/platform/soc/f9bff000.rng /soc/rng@f9bff000
/sys/devices/platform/soc/fc400000.clock-controller /soc/clock-controller@fc400000
/sys/devices/platform/soc/fc4ab000.restart /soc/restart@fc4ab000
/sys/devices/platform/soc/fc4cf000.spmi /soc/spmi@fc4cf000
/sys/devices/platform/soc/fc4cf000.spmi/spmi-0 /soc/spmi@fc4cf000
/sys/devices/platform/soc/fc4cf000.spmi/spmi-0/0-00 /soc/spmi@fc4cf000/pm8941@0
/sys/devices/platform/soc/fc4cf000.spmi/spmi-0/0-01 /soc/spmi@fc4cf000/pm8941@1
/sys/devices/platform/soc/fc4cf000.spmi/spmi-0/0-04 /soc/spmi@fc4cf000/pm8841@4
/sys/devices/platform/soc/fc4cf000.spmi/spmi-0/0-05 /soc/spmi@fc4cf000/pm8841@5
/sys/devices/platform/soc/fd510000.pinctrl /soc/pinctrl@fd510000
/sys/devices/platform/soc/fd8c0000.clock-controller /soc/clock-controller@fd8c0000
/sys/devices/platform/timer /timer
/sys/devices/system/cpu/cpu0 /cpus/cpu@0
/sys/devices/system/cpu/cpu1 /cpus/cpu@1
/sys/devices/system/cpu/cpu2 /cpus/cpu@2
/sys/devices/system/cpu/cpu3 /cpus/cpu@3

===== nodes
/clock-controller qcom,krait-cc-v2
/cpu-pmu qcom,krait-pmu
/cpus/cpu@0 qcom,krait
/cpus/cpu@1 qcom,krait
/cpus/cpu@2 qcom,krait
/cpus/cpu@3 qcom,krait
/cpus/idle-states/spc qcom,idle-state-spcarm,idle-state
/cpus/l2-cache cache
/cpus/spmi@fc4cf000 qcom,spmi-pmic-arb
/cpus/spmi@fc4cf000/pm8841@4 qcom,pm8841
/cpus/spmi@fc4cf000/pm8841@5 qcom,pm8841
/cpus/spmi@fc4cf000/pm8941@0 qcom,pm8941
/cpus/spmi@fc4cf000/pm8941@1 qcom,pm8941
/soc simple-bus
/soc/clock-controller@f9016000 qcom,hfpll
/soc/clock-controller@f9088000 qcom,kpss-acc-v2
/soc/clock-controller@f908a000 qcom,hfpll
/soc/clock-controller@f9098000 qcom,kpss-acc-v2
/soc/clock-controller@f909a000 qcom,hfpll
/soc/clock-controller@f90a8000 qcom,kpss-acc-v2
/soc/clock-controller@f90aa000 qcom,hfpll
/soc/clock-controller@f90b8000 qcom,kpss-acc-v2
/soc/clock-controller@f90ba000 qcom,hfpll
/soc/clock-controller@fc400000 qcom,gcc-msm8974
/soc/clock-controller@fd8c0000 qcom,mmcc-msm8974
/soc/i2c@f9967000 qcom,i2c-qup-v2.1.1
/soc/i2c@f9967000/eeprom@52 atmel,24c128
/soc/interrupt-controller@f9000000 qcom,msm-qgic2
/soc/pinctrl@fd510000 qcom,msm8974-pinctrl
/soc/power-controller@f9012000 qcom,saw2
/soc/power-controller@f9089000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f9099000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f90a9000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f90b9000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/restart@fc4ab000 qcom,pshold
/soc/rng@f9bff000 qcom,prng
/soc/sdhci@f9824900 qcom,sdhci-msm-v4
/soc/sdhci@f98a4900 qcom,sdhci-msm-v4
/soc/serial@f991e000 qcom,msm-uartdm-v1.4qcom,msm-uartdm
/soc/spmi@fc4cf000 qcom,spmi-pmic-arb
/soc/spmi@fc4cf000/pm8841@4 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8841@5 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8941@0 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8941@0/qcom,coincell@2800 qcom,pm8941-coincell
/soc/spmi@fc4cf000/pm8941@1 qcom,spmi-pmic
/soc/timer@f9020000 arm,armv7-timer-mem
/timer arm,armv7-timer

===== nodes bound to a driver
/clock-controller qcom,krait-cc-v2
/cpu-pmu qcom,krait-pmu
/soc/clock-controller@fc400000 qcom,gcc-msm8974
/soc/clock-controller@fd8c0000 qcom,mmcc-msm8974
/soc/i2c@f9967000 qcom,i2c-qup-v2.1.1
/soc/pinctrl@fd510000 qcom,msm8974-pinctrl
/soc/restart@fc4ab000 qcom,pshold
/soc/rng@f9bff000 qcom,prng
/soc/sdhci@f9824900 qcom,sdhci-msm-v4
/soc/serial@f991e000 qcom,msm-uartdm-v1.4qcom,msm-uartdm
/soc/spmi@fc4cf000 qcom,spmi-pmic-arb
/soc/spmi@fc4cf000/pm8841@4 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8841@5 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8941@0 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8941@1 qcom,spmi-pmic

===== nodes with a device
/clock-controller qcom,krait-cc-v2
/cpu-pmu qcom,krait-pmu
/cpus/cpu@0 qcom,krait
/cpus/cpu@1 qcom,krait
/cpus/cpu@2 qcom,krait
/cpus/cpu@3 qcom,krait
/soc simple-bus
/soc/clock-controller@f9016000 qcom,hfpll
/soc/clock-controller@f9088000 qcom,kpss-acc-v2
/soc/clock-controller@f908a000 qcom,hfpll
/soc/clock-controller@f9098000 qcom,kpss-acc-v2
/soc/clock-controller@f909a000 qcom,hfpll
/soc/clock-controller@f90a8000 qcom,kpss-acc-v2
/soc/clock-controller@f90aa000 qcom,hfpll
/soc/clock-controller@f90b8000 qcom,kpss-acc-v2
/soc/clock-controller@f90ba000 qcom,hfpll
/soc/clock-controller@fc400000 qcom,gcc-msm8974
/soc/clock-controller@fd8c0000 qcom,mmcc-msm8974
/soc/i2c@f9967000 qcom,i2c-qup-v2.1.1
/soc/i2c@f9967000 qcom,i2c-qup-v2.1.1
/soc/i2c@f9967000/eeprom@52 atmel,24c128
/soc/interrupt-controller@f9000000 qcom,msm-qgic2
/soc/pinctrl@fd510000 qcom,msm8974-pinctrl
/soc/power-controller@f9012000 qcom,saw2
/soc/power-controller@f9089000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f9099000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f90a9000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f90b9000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/restart@fc4ab000 qcom,pshold
/soc/rng@f9bff000 qcom,prng
/soc/sdhci@f9824900 qcom,sdhci-msm-v4
/soc/serial@f991e000 qcom,msm-uartdm-v1.4qcom,msm-uartdm
/soc/spmi@fc4cf000 qcom,spmi-pmic-arb
/soc/spmi@fc4cf000 qcom,spmi-pmic-arb
/soc/spmi@fc4cf000/pm8841@4 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8841@5 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8941@0 qcom,spmi-pmic
/soc/spmi@fc4cf000/pm8941@1 qcom,spmi-pmic
/soc/timer@f9020000 arm,armv7-timer-mem
/timer arm,armv7-timer

===== nodes not bound to a driver
/cpus/cpu@0 qcom,krait
/cpus/cpu@1 qcom,krait
/cpus/cpu@2 qcom,krait
/cpus/cpu@3 qcom,krait
/cpus/idle-states/spc qcom,idle-state-spcarm,idle-state
/cpus/l2-cache cache
/cpus/spmi@fc4cf000 qcom,spmi-pmic-arb
/cpus/spmi@fc4cf000/pm8841@4 qcom,pm8841
/cpus/spmi@fc4cf000/pm8841@5 qcom,pm8841
/cpus/spmi@fc4cf000/pm8941@0 qcom,pm8941
/cpus/spmi@fc4cf000/pm8941@1 qcom,pm8941
/soc simple-bus
/soc/clock-controller@f9016000 qcom,hfpll
/soc/clock-controller@f9088000 qcom,kpss-acc-v2
/soc/clock-controller@f908a000 qcom,hfpll
/soc/clock-controller@f9098000 qcom,kpss-acc-v2
/soc/clock-controller@f909a000 qcom,hfpll
/soc/clock-controller@f90a8000 qcom,kpss-acc-v2
/soc/clock-controller@f90aa000 qcom,hfpll
/soc/clock-controller@f90b8000 qcom,kpss-acc-v2
/soc/clock-controller@f90ba000 qcom,hfpll
/soc/i2c@f9967000/eeprom@52 atmel,24c128
/soc/interrupt-controller@f9000000 qcom,msm-qgic2
/soc/power-controller@f9012000 qcom,saw2
/soc/power-controller@f9089000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f9099000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f90a9000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/power-controller@f90b9000 qcom,msm8974-saw2-v2.1-cpuqcom,saw2
/soc/sdhci@f98a4900 qcom,sdhci-msm-v4
/soc/spmi@fc4cf000/pm8941@0/qcom,coincell@2800 qcom,pm8941-coincell
/soc/timer@f9020000 arm,armv7-timer-mem
/timer arm,armv7-timer

===== nodes without a device
/cpus/idle-states/spc qcom,idle-state-spcarm,idle-state
/cpus/l2-cache cache
/cpus/spmi@fc4cf000 qcom,spmi-pmic-arb
/cpus/spmi@fc4cf000/pm8841@4 qcom,pm8841
/cpus/spmi@fc4cf000/pm8841@5 qcom,pm8841
/cpus/spmi@fc4cf000/pm8941@0 qcom,pm8941
/cpus/spmi@fc4cf000/pm8941@1 qcom,pm8941
/soc/sdhci@f98a4900 qcom,sdhci-msm-v4
/soc/spmi@fc4cf000/pm8941@0/qcom,coincell@2800 qcom,pm8941-coincell



Signed-off-by: Frank Rowand <frank.rowand@sonymobile.com>
---
 dt_node_info |   27 ++++++
 dt_stat      |  249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 276 insertions(+)

Index: b/dt_node_info
===================================================================
--- /dev/null
+++ b/dt_node_info
@@ -0,0 +1,27 @@
+#! /bin/sh
+
+
+echo ===== devices
+dt_stat --d   | grep "$1"
+echo
+
+echo ===== nodes
+dt_stat --n   | grep "$1"
+echo
+
+echo ===== nodes bound to a driver
+dt_stat --nb  | grep "$1"
+echo
+
+echo ===== nodes with a device
+dt_stat --nd  | grep "$1"
+echo
+
+echo ===== nodes not bound to a driver
+dt_stat --nxb | grep "$1"
+echo
+
+echo ===== nodes without a device
+dt_stat --nxd | grep "$1"
+echo
+
Index: b/dt_stat
===================================================================
--- /dev/null
+++ b/dt_stat
@@ -0,0 +1,249 @@
+#! /bin/sh
+
+# author: Frank Rowand  frank.rowand@sonymobile.com
+# license: GPL V2
+
+#_______________________________________________________________________________
+
+script=`basename $0`
+help=0
+
+
+cmd_d=0
+cmd_n=0
+cmd_nb=0
+cmd_nd=0
+cmd_nxb=0
+cmd_nxd=0
+
+
+while [[ $# -gt 0 ]] ; do
+
+	case $1 in
+
+		-h | -help | --help )
+			help=1
+			shift $#
+			;;
+
+		--d )
+			cmd_d=1
+			shift
+			;;
+
+		--n )
+			cmd_n=1
+			shift
+			;;
+
+		--nb )
+			cmd_nb=1
+			shift
+			;;
+
+		--nd )
+			cmd_nd=1
+			shift
+			;;
+
+		--nxb)
+			cmd_nxb=1
+			shift
+			;;
+
+		--nxd )
+			cmd_nxd=1
+			shift
+			;;
+
+		* )
+			break
+			;;
+	esac
+
+done
+
+if [ $# -gt 0 ] ; then
+	help=1
+fi
+
+
+#_______________________________________________________________________________
+
+PDT="/proc/device-tree/"
+
+
+#_______________________________________________________________________________
+
+if [[ ${help} -eq 1 ]] ; then
+
+echo ""                                                                      >&2
+echo "usage:"                                                                >&2
+echo "   ${script}"                                                          >&2
+echo ""                                                                      >&2
+echo "      -h         synonym for --help"                                   >&2
+echo "      -help      synonym for --help"                                   >&2
+echo "      --help     print this message and exit"                          >&2
+echo ""                                                                      >&2
+echo "      --d        report devices"                                       >&2
+echo "      --n        report nodes"                                         >&2
+echo "      --nb       report nodes bound to a driver"                       >&2
+echo "      --nd       report nodes with a device"                           >&2
+echo "      --nxb      report nodes not bound to a driver"                   >&2
+echo "      --nxd      report nodes without a device"                        >&2
+echo ""                                                                      >&2
+echo "   Reports about nodes in ${PDT}"                                      >&2
+echo "   Nodes without a compatible string are not reported"                 >&2
+echo ""                                                                      >&2
+echo "   data fields reported:"                                              >&2
+echo "      --d        Device Node"                                          >&2
+echo "      --n        Node Compatible"                                      >&2
+echo "      --nb       Node Compatible"                                      >&2
+echo "      --nd       Node Compatible Device Driver"                        >&2
+echo "      --nxb      Node Compatible"                                      >&2
+echo "      --nxd      Node Compatible"                                      >&2
+echo ""                                                                      >&2
+
+exit 1
+
+fi
+
+
+#_______________________________________________________________________________
+
+
+if [[ ! -d /sys/devices ]] ; then
+
+echo ""                                                                      >&2
+echo "ERROR: /sys/devices is not a directory"                                >&2
+echo ""                                                                      >&2
+
+exit 1
+
+fi
+
+
+if [[ ! -d ${PDT} ]] ; then
+
+echo ""                                                                      >&2
+echo "ERROR: ${PDT} is not a directory"                                      >&2
+echo ""                                                                      >&2
+
+exit 1
+
+fi
+
+
+# ==============================================================================
+# COLLECT DATA
+
+#-----  nodes of devices with an OF_FULLNAME in uevent
+
+nodes_dev=$(
+	for dev in `find /sys/devices -name uevent`; do
+		grep '^OF_FULLNAME=' ${dev} | sed -e 's|OF_FULLNAME=||'
+	done | sort
+	)
+
+
+#-----  nodes with a device that has been bound to a driver
+
+nodes_dev_bound=$(
+	for uevent in `find /sys/devices -name uevent`; do
+		if [[ -d $(dirname ${uevent})/driver ]]; then
+			grep '^OF_FULLNAME=' ${uevent} | sed -e 's|OF_FULLNAME=||'
+		fi
+	done | sort
+	)
+
+
+#-----  nodes with a compatible property
+
+nodes_compatible=$( \
+	for node in `find ${PDT} -name compatible`; do
+		echo $(dirname ${node}) | sed -e 's|\/proc\/device-tree||'
+	done | sort
+	)
+
+
+# ==============================================================================
+# REPORTS
+
+#-----  devices with an OF_FULLNAME in uevent
+
+if [[ ${cmd_d} -eq 1 ]] ; then
+	for dev in `find /sys/devices -name uevent`; do
+		if grep -q '^OF_FULLNAME' ${dev} ; then
+			node=$(grep '^OF_FULLNAME' ${dev} | sed -e 's|OF_FULLNAME=||')
+			echo $(dirname ${dev}) ${node}
+		fi
+	done | sort
+fi
+
+
+#-----  nodes with a compatible property
+
+if [[ ${cmd_n} -eq 1 ]] ; then
+	for node in ${nodes_compatible} ; do
+		echo ${node} $(cat ${PDT}/${node}/compatible)
+	done
+fi
+
+
+#-----  nodes with device bound to driver
+
+if [[ ${cmd_nb} -eq 1 ]] ; then
+	for node in ${nodes_dev_bound} ; do
+		echo ${node} $(cat ${PDT}/${node}/compatible)
+	done
+fi
+
+
+#-----  nodes with a device
+
+if [[ ${cmd_nd} -eq 1 ]] ; then
+	for uevent in `find /sys/devices -name uevent`; do
+		if [[ -d $(dirname ${uevent})/driver ]]; then
+			node=$(  grep '^OF_FULLNAME=' ${uevent} | sed -e 's|OF_FULLNAME=||')
+			if [[ "${node}" != "" ]] ; then
+				dev=$(dirname ${uevent})
+				# driver might be empty
+				driver=$(grep '^DRIVER=' ${uevent} | sed -e 's|DRIVER=||' )
+				compatible=$(cat ${PDT}/${node}/compatible)
+				echo ${node} ${compatible} ${dev} ${driver}
+			fi
+		fi
+	done | sort
+fi
+
+
+#-----  nodes not bound to a driver
+
+if [[ ${cmd_nxb} -eq 1 ]] ; then
+	for node in ${nodes_compatible}; do
+		if ! echo ${nodes_dev_bound} | grep -E -q "(^| )${node}( |\$)"; then
+			echo ${node} $(cat ${PDT}/${node}/compatible)
+		fi
+	done
+fi
+
+
+#-----  nodes without a device
+
+if [[ ${cmd_nxd} -eq 1 ]] ; then
+	for node in ${nodes_compatible}; do
+		if ! echo ${nodes_dev} | grep -E -q "(^| )${node}( |\$)"; then
+			echo ${node} $(cat ${PDT}/${node}/compatible)
+		fi
+	done
+fi
+
+
+# ==============================================================================
+# ______________________________________________________________________________
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ______________________________________________________________________________
+#  vi config follows:
+#
+#  add "set modelines" to ~/.exrc or ~/.vimrc to set tabs automatically
+#  ex:set tabstop=3 shiftwidth=3 sts=3:
