This series contains experimental patchwork for PCC and CPPC as defined in the current ACPI5.0a spec. The PCC patch was tested on an ARMv7 platform and on a hacked up PCC emulator. The CPPC part is only compile tested. Both are very much a WIP. Any feedback and help with testing would be highly appreciated!
Ashwin Chaugule (2): ACPI: Add support for Platform Communication Channel CPPC: Initial support for Collaborative Processor Performance Control
arch/arm64/Kconfig | 2 + drivers/acpi/Kconfig | 10 ++ drivers/acpi/Makefile | 2 +- drivers/acpi/pcc.c | 209 +++++++++++++++++++++++++++++ drivers/cpufreq/Kconfig | 11 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc-cpufreq.c | 298 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/pcc.c create mode 100644 drivers/cpufreq/cppc-cpufreq.c
ACPI 5.0a+ spec defines a generic mode of communication between the OS and a platform such as the BMC. This medium (PCC) is typically used by CPPC (ACPI CPU Performance management), RAS (ACPI reliability protocol) and MPST (ACPI Memory power states).
This patch adds initial support for PCC to be usable by the aforementioned PCC clients.
Signed-off-by: Ashwin Chaugule ashwin.chaugule@linaro.org --- drivers/acpi/Kconfig | 10 +++ drivers/acpi/Makefile | 2 +- drivers/acpi/pcc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 drivers/acpi/pcc.c
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index cbc5dfc..8893fa5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -361,6 +361,16 @@ config ACPI_REDUCED_HARDWARE_ONLY
If you are unsure what to do, do not enable this option.
+config ACPI_PCC + bool "ACPI Platform Communication Channel" + def_bool n + depends on ACPI + help + Enable this option if your platform supports PCC as defined in the + ACPI spec 5.0a+. PCC is a generic mechanism for the OS to communicate + with a platform such as a BMC. PCC is typically used by CPPC, RAS + and MPST. + source "drivers/acpi/apei/Kconfig"
config ACPI_EXTLOG diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index fc133d4..d8aa613 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -74,7 +74,7 @@ obj-$(CONFIG_ACPI_HED) += hed.o obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o - +obj-$(CONFIG_ACPI_PCC) += pcc.o # processor has its own "processor." module_param namespace processor-y := processor_driver.o processor_throttling.o processor-y += processor_idle.o processor_thermal.o diff --git a/drivers/acpi/pcc.c b/drivers/acpi/pcc.c new file mode 100644 index 0000000..7961ad6 --- /dev/null +++ b/drivers/acpi/pcc.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * Author: Ashwin Chaugule ashwin.chaugule@linaro.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include <linux/acpi.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> +#include <linux/ioctl.h> +#include <linux/vmalloc.h> + +#include <acpi/actbl.h> + +#define MAX_PCC_SUBSPACES 256 +#define PCCS_SS_SIG_MAGIC 0x50434300 +#define GEN_SCI_SHIFT 0x15 +#define PCC_CMD_COMPLETE 0x1 + +/* Array of pointers to Type 0 Generic Communication Subspace Structures */ +struct acpi_pcct_subspace *pcc_ss_arr[MAX_PCC_SUBSPACES]; + +/* + * TODO: Serialize OSPM control flow per PCC channel. + */ +static DEFINE_SPINLOCK(pcc_lock); + +/* Total number of subspaces detected in PCCT. */ +static int total_ss; + +/* + * PCC clients call this function to get a base address of their + * Communication channel + */ +int get_pcc_comm_channel(u32 ss_idx, u64 __iomem *addr, int *len) +{ + struct acpi_pcct_subspace *pcct_subspace = pcc_ss_arr[ss_idx]; + + if (pcct_subspace) { + *addr = pcct_subspace->base_address; + *len = pcct_subspace->length; + } else + return -EINVAL; + + return 0; +} + +/* Send PCC cmd on behalf of this (subspace id) PCC client */ +u16 send_pcc_cmd(u8 cmd, u8 sci, u32 ss_idx, u64 __iomem *base_addr) +{ + struct acpi_pcct_subspace *pcct_subspace = pcc_ss_arr[ss_idx]; + struct acpi_pcct_shared_memory *generic_comm_base = + (struct acpi_pcct_shared_memory *)base_addr; + struct acpi_generic_address doorbell; + u16 pcc_cmd; + u64 doorbell_preserve; + u64 doorbell_val; + u64 doorbell_write; + /* + * Min time in usec that OSPM is expected to wait + * before sending the next PCC cmd. + */ + u16 cmd_delay = pcct_subspace->min_turnaround_time; + + if (!generic_comm_base) { + pr_err("No Generic Communication Channel provided.\n"); + return -EINVAL; + } + + spin_lock(&pcc_lock); + + /* TODO: Add support for SCI. */ + pcc_cmd |= cmd; + + /* Get doorbell details for this subspace. */ + doorbell = pcct_subspace->doorbell_register; + doorbell_preserve = pcct_subspace->preserve_mask; + doorbell_write = pcct_subspace->write_mask; + + /* Loop until CMD complete bit is set. For prev cmds. */ + while (!(ioread16(&generic_comm_base->status) & PCC_CMD_COMPLETE)) + udelay(cmd_delay); + + /* Write to the shared comm region. */ + iowrite16(cmd, &generic_comm_base->command); + + iowrite32((PCCS_SS_SIG_MAGIC | ss_idx), &generic_comm_base->signature); + + /* Flip CMD COMPLETE bit */ + /* TODO: When we add SCI support then preserve SCI status bit. */ + iowrite16(0, &generic_comm_base->status); + + /* Sync notification from OSPM to Platform. */ + acpi_read(&doorbell_val, &doorbell); + acpi_write((doorbell_val & doorbell_preserve) | doorbell_write, + &doorbell); + + /* Wait for Platform to consume. */ + while (!(ioread16(&generic_comm_base->status) & PCC_CMD_COMPLETE)) + udelay(cmd_delay); + + spin_unlock(&pcc_lock); + + /* PCC clients should check for ERR */ + return generic_comm_base->status; +} + +static int parse_pcc_subspace(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_pcct_subspace *pcct_ss; + + pcct_ss = (struct acpi_pcct_subspace*) header; + + if (pcct_ss->header.type != ACPI_PCCT_TYPE_GENERIC_SUBSPACE) { + pr_err("Incorrect PCC Subspace type detected\n"); + return -EINVAL; + } + + /* TODO: Replace with idr API. */ + pcc_ss_arr[total_ss++] = pcct_ss; + + return 0; +} + +static int __init pcc_probe(void) +{ + acpi_status status = AE_OK; + acpi_size pcct_tbl_header_size; + struct acpi_table_pcct *pcct_tbl; + + /* Search for PCCT */ + status = acpi_get_table_with_size(ACPI_SIG_PCCT, 0, + (struct acpi_table_header **)&pcct_tbl, + &pcct_tbl_header_size); + + if (ACPI_SUCCESS(status) && !pcct_tbl) { + pr_warn("PCCT header not found.\n"); + status = AE_NOT_FOUND; + goto out_err; + } + + /* Found PCCT. Enumerate PCC subspaces. + * Currently there is only type of Subspace + * defined in the ACPI 5.0 spec. If there + * is more than one type, then we'll need + * to rework this to parse multiple types of + * subspaces. + */ + status = acpi_table_parse_entries(ACPI_SIG_PCCT, + sizeof(struct acpi_table_pcct), ACPI_PCCT_TYPE_GENERIC_SUBSPACE, + parse_pcc_subspace, MAX_PCC_SUBSPACES); + + if (ACPI_SUCCESS(status)) + pr_err("Error parsing PCC subspaces from PCCT\n"); + + pr_info("Detected %d PCC Subspaces\n", total_ss); + +out_err: + return (ACPI_SUCCESS(status) ? 1 : 0); +} + +static int __init pcc_init(void) +{ + int ret; + + if (acpi_disabled) + return -ENODEV; + + /* Check if PCC support is available. */ + ret = pcc_probe(); + + if (ret) { + pr_debug("PCC probe failed.\n"); + return -EINVAL; + } + + return ret; +} + +device_initcall(pcc_init);
Add initial support for CPPC as defined in the ACPI5.0a spec.
Signed-off-by: Ashwin Chaugule ashwin.chaugule@linaro.org --- arch/arm64/Kconfig | 2 + drivers/cpufreq/Kconfig | 11 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc-cpufreq.c | 298 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 drivers/cpufreq/cppc-cpufreq.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 94cc542..434d577 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -325,6 +325,8 @@ endmenu
menu "CPU Power Management"
+source "drivers/cpufreq/Kconfig" + source "drivers/cpuidle/Kconfig"
endmenu diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 3a7202d..a2712a1 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -222,13 +222,22 @@ config GENERIC_CPUFREQ_CPU0
If in doubt, say N.
+config CPPC_CPUFREQ + bool "CPPC CPUFreq driver" + depends on ACPI && ACPI_PCC + default n + help + CPPC is Collaborative Processor Performance Control. It allows the OS + to request CPU performance in an abstract manner and lets the platform + (e.g. BMC) interpret it in a way that is specific to that platform. + menu "x86 CPU frequency scaling drivers" depends on X86 source "drivers/cpufreq/Kconfig.x86" endmenu
menu "ARM CPU frequency scaling drivers" -depends on ARM +depends on ARM || ARM64 source "drivers/cpufreq/Kconfig.arm" endmenu
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 0fd80cb..08c2aa1 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o
obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o
+obj-$(CONFIG_CPPC_CPUFREQ) += cppc-cpufreq.o ################################################################################## # x86 drivers. # Link order matters. K8 is preferred to ACPI because of firmware bugs in early diff --git a/drivers/cpufreq/cppc-cpufreq.c b/drivers/cpufreq/cppc-cpufreq.c new file mode 100644 index 0000000..437eb89 --- /dev/null +++ b/drivers/cpufreq/cppc-cpufreq.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * Author: Ashwin Chaugule ashwin.chaugule@linaro.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#include <linux/acpi.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <acpi/actbl.h> + +#define MAX_CPPC_PCC_ENT 15 +#define CPPC_EN 1 + +#define CMD_COMPLETE 1 + +/* PCC Commands used by CPPC */ +enum cppc_ppc_cmds { + CMD_READ, + CMD_WRITE, + RESERVED, +}; + +#define PCC_SUBSPACE_IDX 2 + +struct cpc_desc { + unsigned int num_entries; + unsigned int version; + struct acpi_generic_address pcc_regs[MAX_CPPC_PCC_ENT]; +}; + +/* These are indexes into the per-cpu pcc_regs[] */ +enum cppc_pcc_regs { + HIGHEST_PERF, // Highest Performance + NOMINAL_PERF, // Nominal Performance + LOW_NON_LINEAR_PERF, // Lowest Nonlinear Performance + LOWEST_PERF, // Lowest Performance + GUARANTEED_PERF, // Guaranteed Performance Register + DESIRED_PERF, // Desired Performance Register + MIN_PERF, // Minimum Performance Register + MAX_PERF, // Maximum Performance Register + PERF_REDUC_TOLERANCE, // Performance Reduction Tolerance Register + TIME_WINDOW, // Time Window Register + CTR_WRAP_TIME, // Counter Wraparound Time + NOMINAL_CTR, // Nominal Counter Register + DELIVERED_CTR, // Delivered Counter Register + PERF_LIMITED, // Performance Limited Register + ENABLE // Enable Register +}; + +static struct cpc_desc __percpu *cpc_desc; + +/* PCC Shared COMM region base address for this client */ +static u64 pcc_comm_base_addr; /* Returned by the Subspace structure */ +static void __iomem *comm_base_addr; /* For use after ioremap */ + +extern int get_pcc_comm_channel(u32 ss_idx, u64* addr, int *len); +extern u16 send_pcc_cmd(u8 cmd, u8 sci, u32 ss_idx, u64 * __iomem base_addr); + +static u64 past_delivered; +static u64 past_nominal; + +static unsigned int cppc_get_freq(unsigned int cpu) +{ + struct cpc_desc *current_cpu_cpc = per_cpu(cpc_desc, cpu); + u64 curr_delivered, curr_nominal, curr_perf; + u16 status; + + status = send_pcc_cmd(CMD_READ, 0, PCC_SUBSPACE_IDX, comm_base_addr); + if (status & CMD_COMPLETE) { + acpi_read(&curr_delivered, ¤t_cpu_cpc->pcc_regs[DELIVERED_CTR]); + acpi_read(&curr_nominal, ¤t_cpu_cpc->pcc_regs[NOMINAL_CTR]); + + /* XXX: Check for overflow regs. */ + curr_perf = (curr_nominal) * ((curr_delivered - past_delivered) + / (curr_nominal - past_nominal)); + } else { + pr_err("Failed to get Delivered Perf for CPU:%d\n", cpu); + return -EINVAL; + } + + return curr_perf; +} + +/* For each CPU, get its _CPC table and extract its Perf thresholds. */ +static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + unsigned int cpu = policy->cpu; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj, *pcc_obj; + struct cpc_desc *current_cpu_cpc = per_cpu(cpc_desc, cpu); + struct acpi_generic_address *gas_t; + char proc_name[11]; + unsigned int num_ent, ret = 0, i; + acpi_handle handle; + acpi_status status; + u16 pcc_status; + + /* Search for this CPU's _CPC and populate its info. */ + sprintf(proc_name, "\_SB.CPU%d", cpu); + + status = acpi_get_handle(NULL, proc_name, &handle); + if (ACPI_FAILURE(status)) { + ret = -ENODEV; + goto out_free; + } + + if (!acpi_has_method(handle, "_CPC")) { + ret = -ENODEV; + goto out_free; + } + + status = acpi_evaluate_object(handle, "_CPC", NULL, &output); + if (ACPI_FAILURE(status)) { + ret = -ENODEV; + goto out_free; + } + + out_obj = (union acpi_object *) output.pointer; + if (out_obj->type != ACPI_TYPE_PACKAGE) { + ret = -ENODEV; + goto out_free; + } + + num_ent = out_obj->package.count; + current_cpu_cpc->num_entries = num_ent; + + /* Iterate through each entry in _CPC */ + for (i=0; i<num_ent; i++) { + pcc_obj = &out_obj->package.elements[i]; + + if (pcc_obj->type != ACPI_TYPE_BUFFER) { + pr_err("Malformed PCC entry in CPC table\n"); + ret = -EINVAL; + goto out_free; + } + + gas_t = (struct acpi_generic_address *)pcc_obj->buffer.pointer; + + /* Get PCC parameters for each CPPC register. */ + current_cpu_cpc->pcc_regs[i] = (struct acpi_generic_address) { + .space_id = gas_t->space_id, + .bit_width = gas_t->bit_width, + .bit_offset = gas_t->bit_offset, + .access_width = gas_t->access_width, + /* PCC communication space begins 8 bytes after PCCT shared mem header */ + .address = (u64) (comm_base_addr + 8 + (u64) gas_t->address), + }; + } + + /* Get the MAX and MIN Thresholds for this CPU. */ + pcc_status = send_pcc_cmd(CMD_READ, 0, PCC_SUBSPACE_IDX, comm_base_addr); + if (pcc_status & CMD_COMPLETE) { + u64 max, min; + /*XXX: policy needs to be modified to take in all 64bits. */ + acpi_read(&max, ¤t_cpu_cpc->pcc_regs[HIGHEST_PERF]); + policy->max = (u32) max; + acpi_read(&min, ¤t_cpu_cpc->pcc_regs[LOWEST_PERF]); + policy->min = (u32) min; + } else { + ret = -ENODEV; + pr_err("Failed to get CPPC parameters for CPU:%d\n", cpu); + goto out_free; + } + + /* XXX: Is policy->related_cpus filled up via _PSD info? */ + + /* XXX: Populate this CPUs freq table data.*/ + /* Enable CPPC on this CPU */ + acpi_write(CPPC_EN, ¤t_cpu_cpc->pcc_regs[ENABLE]); + pcc_status = send_pcc_cmd(CMD_WRITE, 0, PCC_SUBSPACE_IDX, comm_base_addr); + if (pcc_status & CMD_COMPLETE) { + ret = -EINVAL; + pr_debug("Failed to init CPPC on CPU:%d\n", cpu); + } + +out_free: + kfree(output.pointer); + return ret; +} + +static int cppc_cpufreq_verify(struct cpufreq_policy *policy) +{ + cpufreq_verify_within_cpu_limits(policy); + return 0; +} + +static int cppc_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int cpu = policy->cpu; + struct cpc_desc *current_cpu_cpc = per_cpu(cpc_desc, cpu); + struct cpufreq_freqs freqs; + u16 status; + + freqs.old = policy->cur; + freqs.new = target_freq; + + cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + + /* Set CPU Perf thresholds and current desired perf value. */ + acpi_write(policy->max, ¤t_cpu_cpc->pcc_regs[MAX_PERF]); + + acpi_write(policy->min, ¤t_cpu_cpc->pcc_regs[MIN_PERF]); + + acpi_write(target_freq, ¤t_cpu_cpc->pcc_regs[DESIRED_PERF]); + + status = send_pcc_cmd(CMD_WRITE, 0, PCC_SUBSPACE_IDX, comm_base_addr); + if (status & CMD_COMPLETE) { + pr_debug("Failed to set target CPU perf for CPU:%d, status:%d\n", + cpu, status); + return -EINVAL; + } + + return 0; +} + +static int cppc_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + iounmap(comm_base_addr); + free_percpu(cpc_desc); + return 0; +} + +static struct cpufreq_driver cppc_cpufreq_driver = { + .get = cppc_get_freq, + .verify = cppc_cpufreq_verify, +/* XXX: setpolicy gives us a high and low range for CPU perf, + * but doesnt give what is current desired CPU perf value ? + */ +// .setpolicy = cppc_cpufreq_setpolicy, + .target = cppc_cpufreq_target, + .init = cppc_cpufreq_cpu_init, + .exit = cppc_cpufreq_cpu_exit, + .name = "cppc-cpufreq", +}; + +static int __init cppc_cpufreq_init(void) +{ + int ret; + int len; + + if (acpi_disabled) + return 0; + + /* Per CPU descriptors for _CPC. */ + cpc_desc = alloc_percpu(struct cpc_desc); + + if (!cpc_desc) { + ret = -ENOMEM; + pr_debug("No mem for CPC descriptors\n"); + goto out_err; + } + + /* PCC Subspace Communication region for CPPC. */ + ret = get_pcc_comm_channel(PCC_SUBSPACE_IDX, &pcc_comm_base_addr, &len); + + if (ret) { + pr_err("No PCC Communication channel found\n"); + ret = -ENODEV; + goto out_err; + } + + /* Base address returned from PCC subspace desc needs to ioremap'd. + * Used by the client to send/recv data from platform. + */ + comm_base_addr = ioremap_nocache(pcc_comm_base_addr, len); + + if (comm_base_addr) { + pr_err("Could not map PCC communicate channel\n"); + ret = -ENOMEM; + goto out_err; + } + + /* Plug into CPUFreq subsystem. */ + ret = cpufreq_register_driver(&cppc_cpufreq_driver); + return ret; + +out_err: + free_percpu(cpc_desc); + return ret; +} + +late_initcall(cppc_cpufreq_init); +/*XXX: Add kmod support */
Hello,
On 6 May 2014 10:10, Ashwin Chaugule ashwin.chaugule@linaro.org wrote:
Add initial support for CPPC as defined in the ACPI5.0a spec.
Signed-off-by: Ashwin Chaugule ashwin.chaugule@linaro.org
arch/arm64/Kconfig | 2 + drivers/cpufreq/Kconfig | 11 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc-cpufreq.c | 298 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 drivers/cpufreq/cppc-cpufreq.c
In case anyone wants to try the latest revisions of the CPPC and PCC drivers, I've set up a git repo at:
https://git.linaro.org/people/ashwin.chaugule/leg-kernel.git/shortlog/refs/h...
I would greatly appreciate any feedback and help with testing these on your platforms.
Cheers, Ashwin
On 05/06/2014 08:10 AM, Ashwin Chaugule wrote:
This series contains experimental patchwork for PCC and CPPC as defined in the current ACPI5.0a spec. The PCC patch was tested on an ARMv7 platform and on a hacked up PCC emulator. The CPPC part is only compile tested. Both are very much a WIP. Any feedback and help with testing would be highly appreciated!
Ashwin Chaugule (2): ACPI: Add support for Platform Communication Channel CPPC: Initial support for Collaborative Processor Performance Control
arch/arm64/Kconfig | 2 + drivers/acpi/Kconfig | 10 ++ drivers/acpi/Makefile | 2 +- drivers/acpi/pcc.c | 209 +++++++++++++++++++++++++++++ drivers/cpufreq/Kconfig | 11 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc-cpufreq.c | 298 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/pcc.c create mode 100644 drivers/cpufreq/cppc-cpufreq.c
I think I'm liking this patch set. There are a couple of minor things -- e.g., alignment of the comments in the definition of enum cppc_pcc_regs -- but for the most part, looks pretty good.
For upstreaming, I think it would be wise to provide a way to test this (as part of the patch set) so it can be demonstrated it works to most anyone that wants to try it. If that could be done in such a way so that it's arch-independent, that would be even cooler. Barring that, I think it's critical that others know how to reproduce what's been done, so at a minimum there needs to be detailed data on how to test this.
On 5/7/2014 3:04 PM, Al Stone wrote:
On 05/06/2014 08:10 AM, Ashwin Chaugule wrote:
This series contains experimental patchwork for PCC and CPPC as defined in the current ACPI5.0a spec. The PCC patch was tested on an ARMv7 platform and on a hacked up PCC emulator. The CPPC part is only compile tested. Both are very much a WIP. Any feedback and help with testing would be highly appreciated!
Ashwin Chaugule (2): ACPI: Add support for Platform Communication Channel CPPC: Initial support for Collaborative Processor Performance Control
arch/arm64/Kconfig | 2 + drivers/acpi/Kconfig | 10 ++ drivers/acpi/Makefile | 2 +- drivers/acpi/pcc.c | 209 +++++++++++++++++++++++++++++ drivers/cpufreq/Kconfig | 11 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc-cpufreq.c | 298 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/pcc.c create mode 100644 drivers/cpufreq/cppc-cpufreq.c
I think I'm liking this patch set. There are a couple of minor things -- e.g., alignment of the comments in the definition of enum cppc_pcc_regs -- but for the most part, looks pretty good.
For upstreaming, I think it would be wise to provide a way to test this (as part of the patch set) so it can be demonstrated it works to most anyone that wants to try it. If that could be done in such a way so that it's arch-independent, that would be even cooler. Barring that, I think it's critical that others know how to reproduce what's been done, so at a minimum there needs to be detailed data on how to test this.
HP plans to test it on an x86 platform of ours that has the firmware support and will post results. We'd like to see one driver that supports x86 and ARM.
-- ljk
Hi Al,
On 7 May 2014 15:04, Al Stone al.stone@linaro.org wrote:
On 05/06/2014 08:10 AM, Ashwin Chaugule wrote:
This series contains experimental patchwork for PCC and CPPC as defined in the current ACPI5.0a spec. The PCC patch was tested on an ARMv7 platform and on a hacked up PCC emulator. The CPPC part is only compile tested. Both are very much a WIP. Any feedback and help with testing would be highly appreciated!
Ashwin Chaugule (2): ACPI: Add support for Platform Communication Channel CPPC: Initial support for Collaborative Processor Performance Control
arch/arm64/Kconfig | 2 + drivers/acpi/Kconfig | 10 ++ drivers/acpi/Makefile | 2 +- drivers/acpi/pcc.c | 209 +++++++++++++++++++++++++++++ drivers/cpufreq/Kconfig | 11 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc-cpufreq.c | 298 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/pcc.c create mode 100644 drivers/cpufreq/cppc-cpufreq.c
I think I'm liking this patch set. There are a couple of minor things -- e.g., alignment of the comments in the definition of enum cppc_pcc_regs -- but for the most part, looks pretty good.
Thanks! I'll fix this in the next revision.
For upstreaming, I think it would be wise to provide a way to test this (as part of the patch set) so it can be demonstrated it works to most anyone that wants to try it. If that could be done in such a way so that it's arch-independent, that would be even cooler. Barring that, I think it's critical that others know how to reproduce what's been done, so at a minimum there needs to be detailed data on how to test this.
I started documenting this under "PCC driver testing" here - https://wiki.linaro.org/LEG/Engineering/Kernel/ACPI/PowerManagement/CPPC The links to the test code and emulator will be updated as soon as I resolve some git issues with my account on git.linaro.org.
Cheers, Ashwin