power: Allow for a dynamic cluster configuration

Change-Id: I542b36d26cad23f29e70ab70d996c95ca3ab11a7
diff --git a/power/include/samsung_power.h b/power/include/samsung_power.h
index a33d802..3cbf841 100644
--- a/power/include/samsung_power.h
+++ b/power/include/samsung_power.h
@@ -25,9 +25,14 @@
  * device tree.
  */
 
-#define CPU0_SYSFS_PATH "/sys/devices/system/cpu/cpu0"
-#define CPU4_SYSFS_PATH "/sys/devices/system/cpu/cpu4"
-#define CPU0_INTERACTIVE_PATH "/sys/devices/system/cpu/cpu0/cpufreq/interactive"
-#define CPU4_INTERACTIVE_PATH "/sys/devices/system/cpu/cpu4/cpufreq/interactive"
+static const char* CPU_SYSFS_PATHS[2] = {
+    "/sys/devices/system/cpu/cpu0",
+    "/sys/devices/system/cpu/cpu4"
+};
+
+static const char* CPU_INTERACTIVE_PATHS[2] = {
+    "/sys/devices/system/cpu/cpu0/cpufreq/interactive",
+    "/sys/devices/system/cpu/cpu4/cpufreq/interactive"
+};
 
 #endif // SAMSUNG_POWER_H
diff --git a/power/power.c b/power/power.c
index 99fd443..7b61748 100644
--- a/power/power.c
+++ b/power/power.c
@@ -28,7 +28,6 @@
 #include <unistd.h>
 
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #define LOG_TAG "SamsungPowerHAL"
 /* #define LOG_NDEBUG 0 */
@@ -40,26 +39,25 @@
 
 #include "samsung_power.h"
 
-#define BOOST_PATH             CPU0_INTERACTIVE_PATH "/boost"
-#define BOOSTPULSE_PATH        CPU0_INTERACTIVE_PATH "/boostpulse"
-#define CPU0_IO_IS_BUSY_PATH   CPU0_INTERACTIVE_PATH "/io_is_busy"
-#define CPU4_IO_IS_BUSY_PATH   CPU4_INTERACTIVE_PATH "/io_is_busy"
-#define CPU0_HISPEED_FREQ_PATH CPU0_INTERACTIVE_PATH "/hispeed_freq"
-#define CPU4_HISPEED_FREQ_PATH CPU4_INTERACTIVE_PATH "/hispeed_freq"
+#define BOOST_PATH        "/boost"
+#define BOOSTPULSE_PATH   "/boostpulse"
 
-#define CPU0_MAX_FREQ_PATH     CPU0_SYSFS_PATH "/cpufreq/scaling_max_freq"
-#define CPU4_MAX_FREQ_PATH     CPU4_SYSFS_PATH "/cpufreq/scaling_max_freq"
+#define IO_IS_BUSY_PATH   "/io_is_busy"
+#define HISPEED_FREQ_PATH "/hispeed_freq"
 
-#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
+#define MAX_FREQ_PATH     "/cpufreq/scaling_max_freq"
+
+#define CLUSTER_COUNT     ARRAY_SIZE(CPU_SYSFS_PATHS)
+#define PARAM_MAXLEN      10
+
+#define ARRAY_SIZE(a)     sizeof(a) / sizeof(a[0])
 
 struct samsung_power_module {
     struct power_module base;
     pthread_mutex_t lock;
     int boostpulse_fd;
-    char cpu0_hispeed_freq[10];
-    char cpu0_max_freq[10];
-    char cpu4_hispeed_freq[10];
-    char cpu4_max_freq[10];
+    char hispeed_freqs[CLUSTER_COUNT][PARAM_MAXLEN];
+    char max_freqs[CLUSTER_COUNT][PARAM_MAXLEN];
     char* touchscreen_power_path;
     char* touchkey_power_path;
 };
@@ -134,16 +132,60 @@
     close(fd);
 }
 
+static void cpu_sysfs_read(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN])
+{
+    char path[PATH_MAX];
+
+    for (unsigned int i = 0; i < ARRAY_SIZE(CPU_SYSFS_PATHS); i++) {
+        sprintf(path, "%s%s", CPU_SYSFS_PATHS[i], param);
+        sysfs_read(path, s[i], PARAM_MAXLEN);
+    }
+}
+
+static void cpu_sysfs_write(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN])
+{
+    char path[PATH_MAX];
+
+    for (unsigned int i = 0; i < ARRAY_SIZE(CPU_SYSFS_PATHS); i++) {
+        sprintf(path, "%s%s", CPU_SYSFS_PATHS[i], param);
+        sysfs_write(path, s[i]);
+    }
+}
+
+static void cpu_interactive_read(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN])
+{
+    char path[PATH_MAX];
+
+    for (unsigned int i = 0; i < ARRAY_SIZE(CPU_INTERACTIVE_PATHS); i++) {
+        sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[i], param);
+        sysfs_read(path, s[i], PARAM_MAXLEN);
+    }
+}
+
+static void cpu_interactive_write(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN])
+{
+    char path[PATH_MAX];
+
+    for (unsigned int i = 0; i < ARRAY_SIZE(CPU_INTERACTIVE_PATHS); i++) {
+        sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[i], param);
+        sysfs_write(path, s[i]);
+    }
+}
+
 static void boost(int32_t duration_us)
 {
     int fd;
+    char path[PATH_MAX];
 
     if (duration_us <= 0)
         return;
 
-    fd = open(BOOST_PATH, O_WRONLY);
+    // the boost node is only valid for the LITTLE cluster
+    sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[0], BOOST_PATH);
+
+    fd = open(path, O_WRONLY);
     if (fd < 0) {
-        ALOGE("Error opening %s", BOOST_PATH);
+        ALOGE("Error opening %s", path);
         return;
     }
 
@@ -156,9 +198,14 @@
 
 static void boostpulse_open(struct samsung_power_module *samsung_pwr)
 {
-    samsung_pwr->boostpulse_fd = open(BOOSTPULSE_PATH, O_WRONLY);
+    char path[PATH_MAX];
+
+    // the boostpulse node is only valid for the LITTLE cluster
+    sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[0], BOOSTPULSE_PATH);
+
+    samsung_pwr->boostpulse_fd = open(path, O_WRONLY);
     if (samsung_pwr->boostpulse_fd < 0) {
-        ALOGE("Error opening %s: %s\n", BOOSTPULSE_PATH, strerror(errno));
+        ALOGE("Error opening %s: %s\n", path, strerror(errno));
     }
 }
 
@@ -172,7 +219,8 @@
 
     len = write(boostpulse_fd, "1", 1);
     if (len < 0) {
-        ALOGE("Error writing to %s: %s", BOOSTPULSE_PATH, strerror(errno));
+        ALOGE("Error writing to %s%s: %s", CPU_INTERACTIVE_PATHS[0], BOOSTPULSE_PATH,
+                strerror(errno));
     }
 }
 
@@ -184,7 +232,6 @@
                               int profile)
 {
     int rc;
-    struct stat sb;
 
     if (profile < 0 || profile >= PROFILE_MAX) {
         return;
@@ -199,34 +246,19 @@
     switch (profile) {
         case PROFILE_POWER_SAVE:
             // Grab value set by init.*.rc
-            sysfs_read(CPU0_HISPEED_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq,
-                       sizeof(samsung_pwr->cpu0_hispeed_freq));
+            cpu_interactive_read(HISPEED_FREQ_PATH, samsung_pwr->hispeed_freqs);
             // Limit to hispeed freq
-            sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq);
-            rc = stat(CPU4_MAX_FREQ_PATH, &sb);
-            if (rc == 0) {
-                sysfs_read(CPU4_HISPEED_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq,
-                           sizeof(samsung_pwr->cpu4_hispeed_freq));
-                sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq);
-            }
+            cpu_sysfs_write(MAX_FREQ_PATH, samsung_pwr->hispeed_freqs);
             ALOGV("%s: set powersave mode", __func__);
             break;
         case PROFILE_BALANCED:
             // Restore normal max freq
-            sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq);
-            rc = stat(CPU4_MAX_FREQ_PATH, &sb);
-            if (rc == 0) {
-                sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq);
-            }
+            cpu_sysfs_write(MAX_FREQ_PATH, samsung_pwr->max_freqs);
             ALOGV("%s: set balanced mode", __func__);
             break;
         case PROFILE_HIGH_PERFORMANCE:
             // Restore normal max freq
-            sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq);
-            rc = stat(CPU4_MAX_FREQ_PATH, &sb);
-            if (rc == 0) {
-                sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq);
-            }
+            cpu_sysfs_write(MAX_FREQ_PATH, samsung_pwr->max_freqs);
             ALOGV("%s: set performance mode", __func__);
             break;
         default:
@@ -311,25 +343,8 @@
 
 static void init_cpufreqs(struct samsung_power_module *samsung_pwr)
 {
-    int rc;
-    struct stat sb;
-
-    sysfs_read(CPU0_HISPEED_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq,
-               sizeof(samsung_pwr->cpu0_hispeed_freq));
-    sysfs_read(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq,
-               sizeof(samsung_pwr->cpu0_max_freq));
-    ALOGV("%s: CPU 0 hispeed freq: %s", __func__, samsung_pwr->cpu0_hispeed_freq);
-    ALOGV("%s: CPU 0 max freq: %s", __func__, samsung_pwr->cpu0_max_freq);
-
-    rc = stat(CPU4_HISPEED_FREQ_PATH, &sb);
-    if (rc == 0) {
-        sysfs_read(CPU4_HISPEED_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq,
-                   sizeof(samsung_pwr->cpu4_hispeed_freq));
-        sysfs_read(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq,
-                   sizeof(samsung_pwr->cpu4_max_freq));
-        ALOGV("%s: CPU 4 hispeed freq: %s", __func__, samsung_pwr->cpu4_hispeed_freq);
-        ALOGV("%s: CPU 4 max freq: %s", __func__, samsung_pwr->cpu4_max_freq);
-    }
+    cpu_interactive_read(HISPEED_FREQ_PATH, samsung_pwr->hispeed_freqs);
+    cpu_sysfs_read(MAX_FREQ_PATH, samsung_pwr->max_freqs);
 }
 
 static void init_touch_input_power_path(struct samsung_power_module *samsung_pwr)
@@ -376,11 +391,12 @@
 static void samsung_power_set_interactive(struct power_module *module, int on)
 {
     struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
-    struct stat sb;
     int panel_brightness;
     char button_state[2];
     int rc;
     static bool touchkeys_blocked = false;
+    char ON[CLUSTER_COUNT][PARAM_MAXLEN]  = {"1", "1"};
+    char OFF[CLUSTER_COUNT][PARAM_MAXLEN] = {"0", "0"};
 
     ALOGV("power_set_interactive: %d", on);
 
@@ -432,11 +448,7 @@
     }
 
 out:
-    sysfs_write(CPU0_IO_IS_BUSY_PATH, on ? "1" : "0");
-    rc = stat(CPU4_IO_IS_BUSY_PATH, &sb);
-    if (rc == 0) {
-        sysfs_write(CPU4_IO_IS_BUSY_PATH, on ? "1" : "0");
-    }
+    cpu_interactive_write(IO_IS_BUSY_PATH, on ? ON : OFF);
 
     ALOGV("power_set_interactive: %d done", on);
 }