Loading Documentation/devicetree/bindings/cpufreq/msm-cpufreq.txt 0 → 100644 +47 −0 Original line number Diff line number Diff line Qualcomm MSM CPUfreq device msm-cpufreq is a device that represents the list of usable CPU frequencies and provides a device handle for the CPUfreq driver to get the CPU and cache clocks. Required properties: - compatible: Must be "qcom,msm-cpufreq" - qcom,cpufreq-table, or qcom,cpufreq-table-<X>: A list of usable CPU frequencies (KHz). Use "qcom,cpufreq-table" if all CPUs in the system should share same list of frequencies. Use "qcom,cpufreq-table-<cpuid>" to describe different CPU freq tables for different CPUs. The table should be listed only for the first CPU if multiple CPUs are synchronous. Optional properties: - clock-names: When DT based binding of clock is available, this provides a list of CPU subsystem clocks. "cpuX_clk" for every CPU that's present. "l2_clk" when an async cache/CCI is present. Optional properties: - qcom,governor-per-policy: This property denotes that governor tunables should be associated with each cpufreq policy group instead of being global. Example: qcom,msm-cpufreq { compatible = "qcom,msm-cpufreq"; qcom,cpufreq-table = < 300000 >, < 422400 >, < 652800 >, < 729600 >, < 883200 >, < 960000 >, < 1036800 >, < 1190400 >, < 1267200 >, < 1497600 >, < 1574400 >, < 1728000 >, < 1958400 >, < 2265600 >; }; drivers/cpufreq/Kconfig +11 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,17 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. config CPU_BOOST tristate "Event base short term CPU freq boost" depends on CPU_FREQ help This driver boosts the frequency of one or more CPUs based on various events that might occur in the system. As of now, the events it reacts to are: - Migration of important threads from one CPU to another. If in doubt, say N. config CPU_FREQ_GOV_SCHEDUTIL bool "'schedutil' cpufreq policy governor" depends on CPU_FREQ && SMP Loading drivers/cpufreq/Kconfig.arm +6 −0 Original line number Diff line number Diff line Loading @@ -292,3 +292,9 @@ config ACPI_CPPC_CPUFREQ support for its operation. If in doubt, say N. config CPU_FREQ_MSM bool "MSM CPUFreq support" depends on CPU_FREQ help This enables the CPUFreq driver for Qualcomm Technologies, Inc. CPUs. drivers/cpufreq/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o Loading Loading @@ -60,6 +61,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ) += mediatek-cpufreq.o obj-$(CONFIG_CPU_FREQ_MSM) += qcom-cpufreq.o obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o Loading @@ -85,7 +87,6 @@ obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o ################################################################################## # PowerPC platform drivers obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o Loading drivers/cpufreq/cpu-boost.c 0 → 100644 +310 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define pr_fmt(fmt) "cpu-boost: " fmt #include <linux/kernel.h> #include <linux/init.h> #include <linux/cpufreq.h> #include <linux/cpu.h> #include <linux/sched.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/time.h> struct cpu_sync { int cpu; unsigned int input_boost_min; unsigned int input_boost_freq; }; static DEFINE_PER_CPU(struct cpu_sync, sync_info); static struct workqueue_struct *cpu_boost_wq; static struct work_struct input_boost_work; static bool input_boost_enabled; static unsigned int input_boost_ms = 40; module_param(input_boost_ms, uint, 0644); static struct delayed_work input_boost_rem; static u64 last_input_time; #define MIN_INPUT_INTERVAL (150 * USEC_PER_MSEC) static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) { int i, ntokens = 0; unsigned int val, cpu; const char *cp = buf; bool enabled = false; while ((cp = strpbrk(cp + 1, " :"))) ntokens++; /* single number: apply to all CPUs */ if (!ntokens) { if (sscanf(buf, "%u\n", &val) != 1) return -EINVAL; for_each_possible_cpu(i) per_cpu(sync_info, i).input_boost_freq = val; goto check_enable; } /* CPU:value pair */ if (!(ntokens % 2)) return -EINVAL; cp = buf; for (i = 0; i < ntokens; i += 2) { if (sscanf(cp, "%u:%u", &cpu, &val) != 2) return -EINVAL; if (cpu >= num_possible_cpus()) return -EINVAL; per_cpu(sync_info, cpu).input_boost_freq = val; cp = strnchr(cp, PAGE_SIZE - (cp - buf), ' '); cp++; } check_enable: for_each_possible_cpu(i) { if (per_cpu(sync_info, i).input_boost_freq) { enabled = true; break; } } input_boost_enabled = enabled; return 0; } static int get_input_boost_freq(char *buf, const struct kernel_param *kp) { int cnt = 0, cpu; struct cpu_sync *s; for_each_possible_cpu(cpu) { s = &per_cpu(sync_info, cpu); cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%d:%u ", cpu, s->input_boost_freq); } cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "\n"); return cnt; } static const struct kernel_param_ops param_ops_input_boost_freq = { .set = set_input_boost_freq, .get = get_input_boost_freq, }; module_param_cb(input_boost_freq, ¶m_ops_input_boost_freq, NULL, 0644); /* * The CPUFREQ_ADJUST notifier is used to override the current policy min to * make sure policy min >= boost_min. The cpufreq framework then does the job * of enforcing the new policy. */ static int boost_adjust_notify(struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_policy *policy = data; unsigned int cpu = policy->cpu; struct cpu_sync *s = &per_cpu(sync_info, cpu); unsigned int ib_min = s->input_boost_min; switch (val) { case CPUFREQ_ADJUST: if (!ib_min) break; pr_debug("CPU%u policy min before boost: %u kHz\n", cpu, policy->min); pr_debug("CPU%u boost min: %u kHz\n", cpu, ib_min); cpufreq_verify_within_limits(policy, ib_min, UINT_MAX); pr_debug("CPU%u policy min after boost: %u kHz\n", cpu, policy->min); break; } return NOTIFY_OK; } static struct notifier_block boost_adjust_nb = { .notifier_call = boost_adjust_notify, }; static void update_policy_online(void) { unsigned int i; /* Re-evaluate policy to trigger adjust notifier for online CPUs */ get_online_cpus(); for_each_online_cpu(i) { pr_debug("Updating policy for CPU%d\n", i); cpufreq_update_policy(i); } put_online_cpus(); } static void do_input_boost_rem(struct work_struct *work) { unsigned int i; struct cpu_sync *i_sync_info; /* Reset the input_boost_min for all CPUs in the system */ pr_debug("Resetting input boost min for all CPUs\n"); for_each_possible_cpu(i) { i_sync_info = &per_cpu(sync_info, i); i_sync_info->input_boost_min = 0; } /* Update policies for all online CPUs */ update_policy_online(); } static void do_input_boost(struct work_struct *work) { unsigned int i; struct cpu_sync *i_sync_info; cancel_delayed_work_sync(&input_boost_rem); /* Set the input_boost_min for all CPUs in the system */ pr_debug("Setting input boost min for all CPUs\n"); for_each_possible_cpu(i) { i_sync_info = &per_cpu(sync_info, i); i_sync_info->input_boost_min = i_sync_info->input_boost_freq; } /* Update policies for all online CPUs */ update_policy_online(); queue_delayed_work(cpu_boost_wq, &input_boost_rem, msecs_to_jiffies(input_boost_ms)); } static void cpuboost_input_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { u64 now; if (!input_boost_enabled) return; now = ktime_to_us(ktime_get()); if (now - last_input_time < MIN_INPUT_INTERVAL) return; if (work_pending(&input_boost_work)) return; queue_work(cpu_boost_wq, &input_boost_work); last_input_time = ktime_to_us(ktime_get()); } static int cpuboost_input_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct input_handle *handle; int error; handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); if (!handle) return -ENOMEM; handle->dev = dev; handle->handler = handler; handle->name = "cpufreq"; error = input_register_handle(handle); if (error) goto err2; error = input_open_device(handle); if (error) goto err1; return 0; err1: input_unregister_handle(handle); err2: kfree(handle); return error; } static void cpuboost_input_disconnect(struct input_handle *handle) { input_close_device(handle); input_unregister_handle(handle); kfree(handle); } static const struct input_device_id cpuboost_ids[] = { /* multi-touch touchscreen */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT_MASK(EV_ABS) }, .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y) }, }, /* touchpad */ { .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, .absbit = { [BIT_WORD(ABS_X)] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, }, /* Keypad */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT, .evbit = { BIT_MASK(EV_KEY) }, }, { }, }; static struct input_handler cpuboost_input_handler = { .event = cpuboost_input_event, .connect = cpuboost_input_connect, .disconnect = cpuboost_input_disconnect, .name = "cpu-boost", .id_table = cpuboost_ids, }; static int cpu_boost_init(void) { int cpu, ret; struct cpu_sync *s; cpu_boost_wq = alloc_workqueue("cpuboost_wq", WQ_HIGHPRI, 0); if (!cpu_boost_wq) return -EFAULT; INIT_WORK(&input_boost_work, do_input_boost); INIT_DELAYED_WORK(&input_boost_rem, do_input_boost_rem); for_each_possible_cpu(cpu) { s = &per_cpu(sync_info, cpu); s->cpu = cpu; } cpufreq_register_notifier(&boost_adjust_nb, CPUFREQ_POLICY_NOTIFIER); ret = input_register_handler(&cpuboost_input_handler); return 0; } late_initcall(cpu_boost_init); Loading
Documentation/devicetree/bindings/cpufreq/msm-cpufreq.txt 0 → 100644 +47 −0 Original line number Diff line number Diff line Qualcomm MSM CPUfreq device msm-cpufreq is a device that represents the list of usable CPU frequencies and provides a device handle for the CPUfreq driver to get the CPU and cache clocks. Required properties: - compatible: Must be "qcom,msm-cpufreq" - qcom,cpufreq-table, or qcom,cpufreq-table-<X>: A list of usable CPU frequencies (KHz). Use "qcom,cpufreq-table" if all CPUs in the system should share same list of frequencies. Use "qcom,cpufreq-table-<cpuid>" to describe different CPU freq tables for different CPUs. The table should be listed only for the first CPU if multiple CPUs are synchronous. Optional properties: - clock-names: When DT based binding of clock is available, this provides a list of CPU subsystem clocks. "cpuX_clk" for every CPU that's present. "l2_clk" when an async cache/CCI is present. Optional properties: - qcom,governor-per-policy: This property denotes that governor tunables should be associated with each cpufreq policy group instead of being global. Example: qcom,msm-cpufreq { compatible = "qcom,msm-cpufreq"; qcom,cpufreq-table = < 300000 >, < 422400 >, < 652800 >, < 729600 >, < 883200 >, < 960000 >, < 1036800 >, < 1190400 >, < 1267200 >, < 1497600 >, < 1574400 >, < 1728000 >, < 1958400 >, < 2265600 >; };
drivers/cpufreq/Kconfig +11 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,17 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. config CPU_BOOST tristate "Event base short term CPU freq boost" depends on CPU_FREQ help This driver boosts the frequency of one or more CPUs based on various events that might occur in the system. As of now, the events it reacts to are: - Migration of important threads from one CPU to another. If in doubt, say N. config CPU_FREQ_GOV_SCHEDUTIL bool "'schedutil' cpufreq policy governor" depends on CPU_FREQ && SMP Loading
drivers/cpufreq/Kconfig.arm +6 −0 Original line number Diff line number Diff line Loading @@ -292,3 +292,9 @@ config ACPI_CPPC_CPUFREQ support for its operation. If in doubt, say N. config CPU_FREQ_MSM bool "MSM CPUFreq support" depends on CPU_FREQ help This enables the CPUFreq driver for Qualcomm Technologies, Inc. CPUs.
drivers/cpufreq/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o Loading Loading @@ -60,6 +61,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ) += mediatek-cpufreq.o obj-$(CONFIG_CPU_FREQ_MSM) += qcom-cpufreq.o obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o Loading @@ -85,7 +87,6 @@ obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o ################################################################################## # PowerPC platform drivers obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o Loading
drivers/cpufreq/cpu-boost.c 0 → 100644 +310 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define pr_fmt(fmt) "cpu-boost: " fmt #include <linux/kernel.h> #include <linux/init.h> #include <linux/cpufreq.h> #include <linux/cpu.h> #include <linux/sched.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/time.h> struct cpu_sync { int cpu; unsigned int input_boost_min; unsigned int input_boost_freq; }; static DEFINE_PER_CPU(struct cpu_sync, sync_info); static struct workqueue_struct *cpu_boost_wq; static struct work_struct input_boost_work; static bool input_boost_enabled; static unsigned int input_boost_ms = 40; module_param(input_boost_ms, uint, 0644); static struct delayed_work input_boost_rem; static u64 last_input_time; #define MIN_INPUT_INTERVAL (150 * USEC_PER_MSEC) static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) { int i, ntokens = 0; unsigned int val, cpu; const char *cp = buf; bool enabled = false; while ((cp = strpbrk(cp + 1, " :"))) ntokens++; /* single number: apply to all CPUs */ if (!ntokens) { if (sscanf(buf, "%u\n", &val) != 1) return -EINVAL; for_each_possible_cpu(i) per_cpu(sync_info, i).input_boost_freq = val; goto check_enable; } /* CPU:value pair */ if (!(ntokens % 2)) return -EINVAL; cp = buf; for (i = 0; i < ntokens; i += 2) { if (sscanf(cp, "%u:%u", &cpu, &val) != 2) return -EINVAL; if (cpu >= num_possible_cpus()) return -EINVAL; per_cpu(sync_info, cpu).input_boost_freq = val; cp = strnchr(cp, PAGE_SIZE - (cp - buf), ' '); cp++; } check_enable: for_each_possible_cpu(i) { if (per_cpu(sync_info, i).input_boost_freq) { enabled = true; break; } } input_boost_enabled = enabled; return 0; } static int get_input_boost_freq(char *buf, const struct kernel_param *kp) { int cnt = 0, cpu; struct cpu_sync *s; for_each_possible_cpu(cpu) { s = &per_cpu(sync_info, cpu); cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%d:%u ", cpu, s->input_boost_freq); } cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "\n"); return cnt; } static const struct kernel_param_ops param_ops_input_boost_freq = { .set = set_input_boost_freq, .get = get_input_boost_freq, }; module_param_cb(input_boost_freq, ¶m_ops_input_boost_freq, NULL, 0644); /* * The CPUFREQ_ADJUST notifier is used to override the current policy min to * make sure policy min >= boost_min. The cpufreq framework then does the job * of enforcing the new policy. */ static int boost_adjust_notify(struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_policy *policy = data; unsigned int cpu = policy->cpu; struct cpu_sync *s = &per_cpu(sync_info, cpu); unsigned int ib_min = s->input_boost_min; switch (val) { case CPUFREQ_ADJUST: if (!ib_min) break; pr_debug("CPU%u policy min before boost: %u kHz\n", cpu, policy->min); pr_debug("CPU%u boost min: %u kHz\n", cpu, ib_min); cpufreq_verify_within_limits(policy, ib_min, UINT_MAX); pr_debug("CPU%u policy min after boost: %u kHz\n", cpu, policy->min); break; } return NOTIFY_OK; } static struct notifier_block boost_adjust_nb = { .notifier_call = boost_adjust_notify, }; static void update_policy_online(void) { unsigned int i; /* Re-evaluate policy to trigger adjust notifier for online CPUs */ get_online_cpus(); for_each_online_cpu(i) { pr_debug("Updating policy for CPU%d\n", i); cpufreq_update_policy(i); } put_online_cpus(); } static void do_input_boost_rem(struct work_struct *work) { unsigned int i; struct cpu_sync *i_sync_info; /* Reset the input_boost_min for all CPUs in the system */ pr_debug("Resetting input boost min for all CPUs\n"); for_each_possible_cpu(i) { i_sync_info = &per_cpu(sync_info, i); i_sync_info->input_boost_min = 0; } /* Update policies for all online CPUs */ update_policy_online(); } static void do_input_boost(struct work_struct *work) { unsigned int i; struct cpu_sync *i_sync_info; cancel_delayed_work_sync(&input_boost_rem); /* Set the input_boost_min for all CPUs in the system */ pr_debug("Setting input boost min for all CPUs\n"); for_each_possible_cpu(i) { i_sync_info = &per_cpu(sync_info, i); i_sync_info->input_boost_min = i_sync_info->input_boost_freq; } /* Update policies for all online CPUs */ update_policy_online(); queue_delayed_work(cpu_boost_wq, &input_boost_rem, msecs_to_jiffies(input_boost_ms)); } static void cpuboost_input_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { u64 now; if (!input_boost_enabled) return; now = ktime_to_us(ktime_get()); if (now - last_input_time < MIN_INPUT_INTERVAL) return; if (work_pending(&input_boost_work)) return; queue_work(cpu_boost_wq, &input_boost_work); last_input_time = ktime_to_us(ktime_get()); } static int cpuboost_input_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct input_handle *handle; int error; handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); if (!handle) return -ENOMEM; handle->dev = dev; handle->handler = handler; handle->name = "cpufreq"; error = input_register_handle(handle); if (error) goto err2; error = input_open_device(handle); if (error) goto err1; return 0; err1: input_unregister_handle(handle); err2: kfree(handle); return error; } static void cpuboost_input_disconnect(struct input_handle *handle) { input_close_device(handle); input_unregister_handle(handle); kfree(handle); } static const struct input_device_id cpuboost_ids[] = { /* multi-touch touchscreen */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT_MASK(EV_ABS) }, .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y) }, }, /* touchpad */ { .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, .absbit = { [BIT_WORD(ABS_X)] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, }, /* Keypad */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT, .evbit = { BIT_MASK(EV_KEY) }, }, { }, }; static struct input_handler cpuboost_input_handler = { .event = cpuboost_input_event, .connect = cpuboost_input_connect, .disconnect = cpuboost_input_disconnect, .name = "cpu-boost", .id_table = cpuboost_ids, }; static int cpu_boost_init(void) { int cpu, ret; struct cpu_sync *s; cpu_boost_wq = alloc_workqueue("cpuboost_wq", WQ_HIGHPRI, 0); if (!cpu_boost_wq) return -EFAULT; INIT_WORK(&input_boost_work, do_input_boost); INIT_DELAYED_WORK(&input_boost_rem, do_input_boost_rem); for_each_possible_cpu(cpu) { s = &per_cpu(sync_info, cpu); s->cpu = cpu; } cpufreq_register_notifier(&boost_adjust_nb, CPUFREQ_POLICY_NOTIFIER); ret = input_register_handler(&cpuboost_input_handler); return 0; } late_initcall(cpu_boost_init);