vexpress: Setup IRQ affinity to A7s for TC2

On TC2, to maximise power savings, it helps to affine the IRQs to the
A7s. Now that the cpu to parts mapping is available via /proc/cpuinfo,
this patch introduces a script to parse this file and build a mask of
particular CPU type and change the IRQ affinity to this mask.

The patch also makes the necessary changes to platform specific init
script to call above script and affine the IRQs to the A7s.

Lastly, it changes the makefile to include the new script in the target.

Change-Id: I2fd2840acd4602d9145c7c2f2e839e5dda09ff99
Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
diff --git a/device.mk b/device.mk
index dc29086..934d313 100644
--- a/device.mk
+++ b/device.mk
@@ -17,7 +17,8 @@
     device/linaro/vexpress/init.v2p-aarch64.rc:root/init.v2p-aarch64.rc \
     device/linaro/vexpress/ueventd.v2p-aarch64.rc:root/ueventd.v2p-aarch64.rc \
     device/linaro/vexpress/init.vexpress.sh:system/etc/init.vexpress.sh \
-    device/linaro/vexpress/initlogo.rle:root/initlogo.rle
+    device/linaro/vexpress/initlogo.rle:root/initlogo.rle \
+    device/linaro/vexpress/set_irq_affinity.sh:root/set_irq_affinity.sh
 
 PRODUCT_CHARACTERISTICS := tablet,nosdcard
 
diff --git a/init.arm-versatileexpress.rc b/init.arm-versatileexpress.rc
index a71e491..b7d7c8b 100644
--- a/init.arm-versatileexpress.rc
+++ b/init.arm-versatileexpress.rc
@@ -33,6 +33,12 @@
     chown system system /sys/class/graphics/fb0/fit_to_screen
     chown system system /sys/class/graphics/fb1/overlays
 
+# setup IRQ affinity to the A7s
+service setirqaffinity /set_irq_affinity.sh 0xc07
+    class main
+    user root
+    oneshot
+
 service faketsd /system/bin/faketsd
     class main
     user bluetooth
diff --git a/set_irq_affinity.sh b/set_irq_affinity.sh
new file mode 100755
index 0000000..fbf8fa4
--- /dev/null
+++ b/set_irq_affinity.sh
@@ -0,0 +1,45 @@
+#!/system/bin/sh
+
+# This script sets the default affinity to the processors with the given part id.
+#   - part id is in hex (as seen in /proc/cpuinfo)
+
+function build_mask_from_part_id {
+    local IFS
+    local mask
+    local ref_part_id
+
+    ref_part_id=$1
+    IFS=$'\n'
+
+    for line in `cat /proc/cpuinfo`
+    do
+        IFS=':'
+        set -A tokens $line
+
+        if [ "${line#'processor'}" != "$line" ]
+        then
+            cpu="${tokens[1]##' '}"
+        elif [ "${line#'CPU part'}" != "$line" ]
+        then
+            part_id="${tokens[1]##' '}"
+
+            if [ "$part_id" == "$ref_part_id" ]
+            then
+                (( mask |= 1 << $cpu ))
+            fi
+        fi
+    done
+    echo $(printf "%x" $mask)
+}
+
+ref_part_id=$(echo $1 | tr '[A-Z]' '[a-z]')
+mask=$(build_mask_from_part_id $ref_part_id)
+[ -z "$mask" ] && exit
+
+echo $mask > /proc/irq/default_smp_affinity
+
+for i in `ls /proc/irq`
+do
+    affinity_file="/proc/irq/$i/smp_affinity"
+    [ -e $affinity_file ] && echo $mask > $affinity_file
+done