17266c5fe268d063d93654dc2d986328243c185ecJohn Stultz/* 27266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * Copyright (C) 2013 The Android Open Source Project 37266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * 47266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * Licensed under the Apache License, Version 2.0 (the "License"); 57266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * you may not use this file except in compliance with the License. 67266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * You may obtain a copy of the License at 77266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * 87266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * http://www.apache.org/licenses/LICENSE-2.0 97266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * 107266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * Unless required by applicable law or agreed to in writing, software 117266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * distributed under the License is distributed on an "AS IS" BASIS, 127266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * See the License for the specific language governing permissions and 147266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * limitations under the License. 157266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * 167266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * Based on the FlounderPowerHAL 177266c5fe268d063d93654dc2d986328243c185ecJohn Stultz */ 187266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 197266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <dirent.h> 207266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <errno.h> 217266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <string.h> 227266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <sys/types.h> 237266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <sys/stat.h> 247266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <fcntl.h> 257266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <unistd.h> 267266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <stdlib.h> 277266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <stdbool.h> 284c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz#include <pthread.h> 294c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz#include <semaphore.h> 307266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <cutils/properties.h> 317266c5fe268d063d93654dc2d986328243c185ecJohn Stultz//#define LOG_NDEBUG 0 327266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 337266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define LOG_TAG "HiKeyPowerHAL" 347266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <utils/Log.h> 357266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 367266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <hardware/hardware.h> 377266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#include <hardware/power.h> 387266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3917e1124421f655cef38b901016caa58fbbea467dJohn Stultz#define SCHEDTUNE_BOOST_PATH "/dev/stune/top-app/schedtune.boost" 404c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz#define SCHEDTUNE_BOOST_NORM "10" 414c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz#define SCHEDTUNE_BOOST_INTERACTIVE "40" 424c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz#define SCHEDTUNE_BOOST_TIME_NS 1000000000LL 43127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz#define INTERACTIVE_BOOSTPULSE_PATH "/sys/devices/system/cpu/cpufreq/interactive/boostpulse" 44127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz#define INTERACTIVE_IO_IS_BUSY_PATH "/sys/devices/system/cpu/cpufreq/interactive/io_is_busy" 457266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define CPU_MAX_FREQ_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" 467266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define LOW_POWER_MAX_FREQ "729000" 477266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define NORMAL_MAX_FREQ "1200000" 487266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define SVELTE_PROP "ro.boot.svelte" 497266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define SVELTE_MAX_FREQ_PROP "ro.config.svelte.max_cpu_freq" 507266c5fe268d063d93654dc2d986328243c185ecJohn Stultz#define SVELTE_LOW_POWER_MAX_FREQ_PROP "ro.config.svelte.low_power_max_cpu_freq" 517266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 527266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstruct hikey_power_module { 537266c5fe268d063d93654dc2d986328243c185ecJohn Stultz struct power_module base; 547266c5fe268d063d93654dc2d986328243c185ecJohn Stultz pthread_mutex_t lock; 554c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz /* interactive gov boost values */ 567266c5fe268d063d93654dc2d986328243c185ecJohn Stultz int boostpulse_fd; 577266c5fe268d063d93654dc2d986328243c185ecJohn Stultz int boostpulse_warned; 584c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz /* EAS schedtune values */ 594c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz int schedtune_boost_fd; 604c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz long long deboost_time; 614c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz sem_t signal_lock; 627266c5fe268d063d93654dc2d986328243c185ecJohn Stultz}; 637266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 647266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstatic bool low_power_mode = false; 657266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 667266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstatic char *max_cpu_freq = NORMAL_MAX_FREQ; 677266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstatic char *low_power_max_cpu_freq = LOW_POWER_MAX_FREQ; 687266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 69e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz 70e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz#define container_of(addr, struct_name, field_name) \ 71e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz ((struct_name *)((char *)(addr) - offsetof(struct_name, field_name))) 72e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz 73e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz 74cc14758ff0497beb73d3ecc7abf8ed05302f2151Dmitry Shmidtstatic int sysfs_write(const char *path, char *s) 757266c5fe268d063d93654dc2d986328243c185ecJohn Stultz{ 767266c5fe268d063d93654dc2d986328243c185ecJohn Stultz char buf[80]; 777266c5fe268d063d93654dc2d986328243c185ecJohn Stultz int len; 787266c5fe268d063d93654dc2d986328243c185ecJohn Stultz int fd = open(path, O_WRONLY); 797266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 807266c5fe268d063d93654dc2d986328243c185ecJohn Stultz if (fd < 0) { 817266c5fe268d063d93654dc2d986328243c185ecJohn Stultz strerror_r(errno, buf, sizeof(buf)); 827266c5fe268d063d93654dc2d986328243c185ecJohn Stultz ALOGE("Error opening %s: %s\n", path, buf); 83cc14758ff0497beb73d3ecc7abf8ed05302f2151Dmitry Shmidt return fd; 847266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } 857266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 867266c5fe268d063d93654dc2d986328243c185ecJohn Stultz len = write(fd, s, strlen(s)); 877266c5fe268d063d93654dc2d986328243c185ecJohn Stultz if (len < 0) { 887266c5fe268d063d93654dc2d986328243c185ecJohn Stultz strerror_r(errno, buf, sizeof(buf)); 897266c5fe268d063d93654dc2d986328243c185ecJohn Stultz ALOGE("Error writing to %s: %s\n", path, buf); 907266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } 917266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 927266c5fe268d063d93654dc2d986328243c185ecJohn Stultz close(fd); 93cc14758ff0497beb73d3ecc7abf8ed05302f2151Dmitry Shmidt return len; 947266c5fe268d063d93654dc2d986328243c185ecJohn Stultz} 957266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 964c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz#define NSEC_PER_SEC 1000000000LL 974c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzstatic long long gettime_ns(void) 984c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 994c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz struct timespec ts; 1004c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 1014c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz clock_gettime(CLOCK_MONOTONIC, &ts); 1024c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; 1034c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 1044c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 1054c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzstatic void nanosleep_ns(long long ns) 1064c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 1074c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz struct timespec ts; 1084c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz ts.tv_sec = ns/NSEC_PER_SEC; 1094c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz ts.tv_nsec = ns%NSEC_PER_SEC; 1104c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz nanosleep(&ts, NULL); 1114c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 1124c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 113c579371efd42b552781e72ee721fbd540409d231John Stultz/*[interactive cpufreq gov funcs]*********************************************/ 114e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultzstatic void interactive_power_init(struct hikey_power_module __unused *hikey) 1157266c5fe268d063d93654dc2d986328243c185ecJohn Stultz{ 11665de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz int32_t is_svelte = property_get_int32(SVELTE_PROP, 0); 11765de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz 118cc14758ff0497beb73d3ecc7abf8ed05302f2151Dmitry Shmidt if (sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate", 119cc14758ff0497beb73d3ecc7abf8ed05302f2151Dmitry Shmidt "20000") < 0) 120cc14758ff0497beb73d3ecc7abf8ed05302f2151Dmitry Shmidt return; 1217266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_slack", 1227266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "20000"); 1237266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time", 1247266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "80000"); 1257266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", 1267266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "1200000"); 1277266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", 1287266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "99"); 1297266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/target_loads", 1307266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "65 729000:75 960000:85"); 1317266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", 1327266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "20000"); 1337266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration", 1347266c5fe268d063d93654dc2d986328243c185ecJohn Stultz "1000000"); 1357266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/io_is_busy", "0"); 1367266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 13765de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz if (is_svelte) { 13865de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz char prop_buffer[PROPERTY_VALUE_MAX]; 139127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz int len = property_get(SVELTE_MAX_FREQ_PROP, prop_buffer, 140127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz LOW_POWER_MAX_FREQ); 14165de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz 14265de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz max_cpu_freq = strndup(prop_buffer, len); 143127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz len = property_get(SVELTE_LOW_POWER_MAX_FREQ_PROP, prop_buffer, 144127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz LOW_POWER_MAX_FREQ); 14565de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz low_power_max_cpu_freq = strndup(prop_buffer, len); 14665de27c56b9b9b9cdbfacf50ff07d84c385755d5John Stultz } 1477266c5fe268d063d93654dc2d986328243c185ecJohn Stultz} 1487266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 1497266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstatic void power_set_interactive(struct power_module __unused *module, int on) 1507266c5fe268d063d93654dc2d986328243c185ecJohn Stultz{ 1517266c5fe268d063d93654dc2d986328243c185ecJohn Stultz ALOGV("power_set_interactive: %d\n", on); 1527266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 1537266c5fe268d063d93654dc2d986328243c185ecJohn Stultz /* 1547266c5fe268d063d93654dc2d986328243c185ecJohn Stultz * Lower maximum frequency when screen is off. 1557266c5fe268d063d93654dc2d986328243c185ecJohn Stultz */ 1567266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write(CPU_MAX_FREQ_PATH, 1577266c5fe268d063d93654dc2d986328243c185ecJohn Stultz (!on || low_power_mode) ? low_power_max_cpu_freq : max_cpu_freq); 158127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz sysfs_write(INTERACTIVE_IO_IS_BUSY_PATH, on ? "1" : "0"); 1597266c5fe268d063d93654dc2d986328243c185ecJohn Stultz ALOGV("power_set_interactive: %d done\n", on); 1607266c5fe268d063d93654dc2d986328243c185ecJohn Stultz} 1617266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 16264b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultzstatic int interactive_boostpulse(struct hikey_power_module *hikey) 1637266c5fe268d063d93654dc2d986328243c185ecJohn Stultz{ 1647266c5fe268d063d93654dc2d986328243c185ecJohn Stultz char buf[80]; 1657266c5fe268d063d93654dc2d986328243c185ecJohn Stultz int len; 1667266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 16764b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz if (hikey->boostpulse_fd < 0) 168127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz hikey->boostpulse_fd = open(INTERACTIVE_BOOSTPULSE_PATH, O_WRONLY); 1697266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 17064b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz if (hikey->boostpulse_fd < 0) { 17164b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz if (!hikey->boostpulse_warned) { 17264b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz strerror_r(errno, buf, sizeof(buf)); 173127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz ALOGE("Error opening %s: %s\n", INTERACTIVE_BOOSTPULSE_PATH, 17464b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz buf); 17564b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz hikey->boostpulse_warned = 1; 1767266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } 17764b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz return hikey->boostpulse_fd; 1787266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } 1797266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 18064b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz len = write(hikey->boostpulse_fd, "1", 1); 18164b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz if (len < 0) { 18264b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz strerror_r(errno, buf, sizeof(buf)); 18364b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz ALOGE("Error writing to %s: %s\n", 184127e1cc406c82b11c4b2e9e0f7cafc047af9fea1John Stultz INTERACTIVE_BOOSTPULSE_PATH, buf); 18564b54ca01d3420a70aaeb15304bf08cf285d776aJohn Stultz return -1; 1865e1546bfc86f492bde7b7c9449d2f9531e313640John Stultz } 1875e1546bfc86f492bde7b7c9449d2f9531e313640John Stultz return 0; 1885e1546bfc86f492bde7b7c9449d2f9531e313640John Stultz} 1895e1546bfc86f492bde7b7c9449d2f9531e313640John Stultz 1904c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz/*[schedtune functions]*******************************************************/ 1914c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 1924c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzint schedtune_sysfs_boost(struct hikey_power_module *hikey, char* booststr) 1934c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 1944c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz char buf[80]; 1954c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz int len; 1964c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 1974c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if (hikey->schedtune_boost_fd < 0) 1984c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return hikey->schedtune_boost_fd; 1994c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2004c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz len = write(hikey->schedtune_boost_fd, booststr, 2); 2014c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if (len < 0) { 2024c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz strerror_r(errno, buf, sizeof(buf)); 2034c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz ALOGE("Error writing to %s: %s\n", SCHEDTUNE_BOOST_PATH, buf); 2044c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz } 2054c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return len; 2064c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 2074c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2084c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzstatic void* schedtune_deboost_thread(void* arg) 2094c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 2104c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz struct hikey_power_module *hikey = (struct hikey_power_module *)arg; 2114c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2124c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz while(1) { 2134c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz sem_wait(&hikey->signal_lock); 2144c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz while(1) { 2154c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz long long now, sleeptime = 0; 2164c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2174c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz pthread_mutex_lock(&hikey->lock); 2184c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz now = gettime_ns(); 2194c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if (hikey->deboost_time > now) { 2204c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz sleeptime = hikey->deboost_time - now; 2214c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz pthread_mutex_unlock(&hikey->lock); 2224c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz nanosleep_ns(sleeptime); 2234c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz continue; 2244c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz } 2254c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2264c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz schedtune_sysfs_boost(hikey, SCHEDTUNE_BOOST_NORM); 2274c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz hikey->deboost_time = 0; 2284c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz pthread_mutex_unlock(&hikey->lock); 2294c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz break; 2304c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz } 2314c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz } 2324c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return NULL; 2334c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 234c579371efd42b552781e72ee721fbd540409d231John Stultz 2354c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzstatic int schedtune_boost(struct hikey_power_module *hikey) 2364c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 2374c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz long long now; 2384c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2394c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if (hikey->schedtune_boost_fd < 0) 2404c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return hikey->schedtune_boost_fd; 2414c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2424c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz now = gettime_ns(); 2434c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if (!hikey->deboost_time) { 2444c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz schedtune_sysfs_boost(hikey, SCHEDTUNE_BOOST_INTERACTIVE); 2454c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz sem_post(&hikey->signal_lock); 2464c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz } 2474c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz hikey->deboost_time = now + SCHEDTUNE_BOOST_TIME_NS; 2484c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2494c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return 0; 2504c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 2514c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2524c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzstatic void schedtune_power_init(struct hikey_power_module *hikey) 2534c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 2544c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz char buf[50]; 2554c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz pthread_t tid; 2564c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2574c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2584c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz hikey->deboost_time = 0; 2594c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz sem_init(&hikey->signal_lock, 0, 1); 2604c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2614c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz hikey->schedtune_boost_fd = open(SCHEDTUNE_BOOST_PATH, O_WRONLY); 2624c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if (hikey->schedtune_boost_fd < 0) { 2634c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz strerror_r(errno, buf, sizeof(buf)); 2644c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz ALOGE("Error opening %s: %s\n", SCHEDTUNE_BOOST_PATH, buf); 2654c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz } 2664c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2674c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz pthread_create(&tid, NULL, schedtune_deboost_thread, hikey); 2684c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 2694c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2704c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz/*[generic functions]*********************************************************/ 271c579371efd42b552781e72ee721fbd540409d231John Stultzstatic void hikey_power_init(struct power_module __unused *module) 272c579371efd42b552781e72ee721fbd540409d231John Stultz{ 273e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz struct hikey_power_module *hikey = container_of(module, 274e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz struct hikey_power_module, base); 275e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz interactive_power_init(hikey); 2764c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz schedtune_power_init(hikey); 2774c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz} 2784c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz 2794c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultzstatic void hikey_hint_interaction(struct hikey_power_module *mod) 2804c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz{ 2814c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz /* Try interactive cpufreq boosting first */ 2824c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if(!interactive_boostpulse(mod)) 2834c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return; 2844c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz /* Then try EAS schedtune boosting */ 2854c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz if(!schedtune_boost(mod)) 2864c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz return; 287c579371efd42b552781e72ee721fbd540409d231John Stultz} 288c579371efd42b552781e72ee721fbd540409d231John Stultz 2897266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstatic void hikey_power_hint(struct power_module *module, power_hint_t hint, 2907266c5fe268d063d93654dc2d986328243c185ecJohn Stultz void *data) 2917266c5fe268d063d93654dc2d986328243c185ecJohn Stultz{ 292e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz struct hikey_power_module *hikey = container_of(module, 293e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz struct hikey_power_module, base); 2947266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 2957266c5fe268d063d93654dc2d986328243c185ecJohn Stultz pthread_mutex_lock(&hikey->lock); 2967266c5fe268d063d93654dc2d986328243c185ecJohn Stultz switch (hint) { 2977266c5fe268d063d93654dc2d986328243c185ecJohn Stultz case POWER_HINT_INTERACTION: 2984c1a82b68af9de1acd9afbb00c0e4967242d5c0bJohn Stultz hikey_hint_interaction(hikey); 2997266c5fe268d063d93654dc2d986328243c185ecJohn Stultz break; 3007266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3017266c5fe268d063d93654dc2d986328243c185ecJohn Stultz case POWER_HINT_VSYNC: 3027266c5fe268d063d93654dc2d986328243c185ecJohn Stultz break; 3037266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3047266c5fe268d063d93654dc2d986328243c185ecJohn Stultz case POWER_HINT_LOW_POWER: 3057266c5fe268d063d93654dc2d986328243c185ecJohn Stultz if (data) { 3067266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write(CPU_MAX_FREQ_PATH, low_power_max_cpu_freq); 3077266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } else { 3087266c5fe268d063d93654dc2d986328243c185ecJohn Stultz sysfs_write(CPU_MAX_FREQ_PATH, max_cpu_freq); 3097266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } 3107266c5fe268d063d93654dc2d986328243c185ecJohn Stultz low_power_mode = data; 3117266c5fe268d063d93654dc2d986328243c185ecJohn Stultz break; 3127266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3137266c5fe268d063d93654dc2d986328243c185ecJohn Stultz default: 3147266c5fe268d063d93654dc2d986328243c185ecJohn Stultz break; 3157266c5fe268d063d93654dc2d986328243c185ecJohn Stultz } 3167266c5fe268d063d93654dc2d986328243c185ecJohn Stultz pthread_mutex_unlock(&hikey->lock); 3177266c5fe268d063d93654dc2d986328243c185ecJohn Stultz} 3187266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 319ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultzstatic void set_feature(struct power_module *module, feature_t feature, int state) 320ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz{ 321e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz struct hikey_power_module *hikey = container_of(module, 322e150ab36321e4692cd7a55adc75a027ffcd71a8aJohn Stultz struct hikey_power_module, base); 323ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz switch (feature) { 324ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz default: 3250ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt ALOGW("Error setting the feature %d and state %d, it doesn't exist\n", 3260ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt feature, state); 327ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz break; 328ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz } 329ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz} 330ab1f6a7a7d238b7f693ef7cd72be09ddbacbf490John Stultz 3310ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidtstatic int power_open(const hw_module_t* __unused module, const char* name, 33296c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi hw_device_t** device) 33396c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi{ 33496c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi int retval = 0; /* 0 is ok; -1 is error */ 33596c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi ALOGD("%s: enter; name=%s", __FUNCTION__, name); 33696c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi 33796c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi if (strcmp(name, POWER_HARDWARE_MODULE_ID) == 0) { 33896c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi power_module_t *dev = (power_module_t *)calloc(1, 33996c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi sizeof(power_module_t)); 34096c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi 34196c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi if (dev) { 34296c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi /* Common hw_device_t fields */ 34396c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->common.tag = HARDWARE_DEVICE_TAG; 34496c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->common.module_api_version = POWER_MODULE_API_VERSION_0_5; 34596c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->common.hal_api_version = HARDWARE_HAL_API_VERSION; 34696c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi 34796c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->init = hikey_power_init; 34896c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->powerHint = hikey_power_hint; 34996c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->setInteractive = power_set_interactive; 35096c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi dev->setFeature = set_feature; 35196c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi 35296c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi *device = (hw_device_t*)dev; 35396c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi } else 35496c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi retval = -ENOMEM; 35596c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi } else { 35696c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi retval = -EINVAL; 35796c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi } 35896c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi 35996c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi ALOGD("%s: exit %d", __FUNCTION__, retval); 36096c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi return retval; 36196c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi} 36296c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi 3637266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstatic struct hw_module_methods_t power_module_methods = { 36496c621c19a98065147c7a052f49f33ba4ab5e4e1Ruchi Kandoi .open = power_open, 3657266c5fe268d063d93654dc2d986328243c185ecJohn Stultz}; 3667266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3677266c5fe268d063d93654dc2d986328243c185ecJohn Stultzstruct hikey_power_module HAL_MODULE_INFO_SYM = { 3680ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .base = { 3690ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .common = { 3700ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .tag = HARDWARE_MODULE_TAG, 3710ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .module_api_version = POWER_MODULE_API_VERSION_0_2, 3720ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .hal_api_version = HARDWARE_HAL_API_VERSION, 3730ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .id = POWER_HARDWARE_MODULE_ID, 3740ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .name = "HiKey Power HAL", 3750ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .author = "The Android Open Source Project", 3760ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .methods = &power_module_methods, 3777266c5fe268d063d93654dc2d986328243c185ecJohn Stultz }, 3787266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3790ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .init = hikey_power_init, 3800ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .setInteractive = power_set_interactive, 3810ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .powerHint = hikey_power_hint, 3820ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .setFeature = set_feature, 3837266c5fe268d063d93654dc2d986328243c185ecJohn Stultz }, 3847266c5fe268d063d93654dc2d986328243c185ecJohn Stultz 3850ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .lock = PTHREAD_MUTEX_INITIALIZER, 3860ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .boostpulse_fd = -1, 3870ea8f4dfe2bca68cb6fc6ec5acffa697a51e71e7Dmitry Shmidt .boostpulse_warned = 0, 3887266c5fe268d063d93654dc2d986328243c185ecJohn Stultz}; 389