/* * CPPC (Collaborative Processor Performance Control) methods used by CPUfreq drivers. * * (C) Copyright 2014, 2015 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; version 2 * of the License. * * CPPC describes a few methods for controlling CPU performance using * information from a per CPU table called CPC. This table is described in * the ACPI v5.0+ specification. The table consists of a list of * registers which may be memory mapped or hardware registers and also may * include some static integer values. * * CPU performance is on an abstract continuous scale as against a discretized * P-state scale which is tied to CPU frequency only. In brief, the basic * operation involves: * * - OS makes a CPU performance request. (Can provide min and max bounds) * * - Platform (such as BMC) is free to optimize request within requested bounds * depending on power/thermal budgets etc. * * - Platform conveys its decision back to OS * * The communication between OS and platform occurs through another medium * called (PCC) Platform Communication Channel. This is a generic mailbox like * mechanism which includes doorbell semantics to indicate register updates. * See drivers/mailbox/pcc.c for details on PCC. * * Finer details about the PCC and CPPC spec are available in the ACPI v5.1 and * above specifications. */#define pr_fmt(fmt) "ACPI CPPC: " fmt#include<linux/cpufreq.h>#include<linux/delay.h>#include<linux/iopoll.h>#include<linux/ktime.h>#include<linux/rwsem.h>#include<linux/wait.h>#include<acpi/cppc_acpi.h>structcppc_pcc_data{structmbox_chan*pcc_channel;void__iomem*pcc_comm_addr;boolpcc_channel_acquired;unsignedintdeadline_us;unsignedintpcc_mpar,pcc_mrtt,pcc_nominal;boolpending_pcc_write_cmd;/* Any pending/batched PCC write cmds? */boolplatform_owns_pcc;/* Ownership of PCC subspace */unsignedintpcc_write_cnt;/* Running count of PCC write commands *//* * Lock to provide controlled access to the PCC channel. * * For performance critical usecases(currently cppc_set_perf) * We need to take read_lock and check if channel belongs to OSPM * before reading or writing to PCC subspace * We need to take write_lock before transferring the channel * ownership to the platform via a Doorbell * This allows us to batch a number of CPPC requests if they happen * to originate in about the same time * * For non-performance critical usecases(init) * Take write_lock for all purposes which gives exclusive access */structrw_semaphorepcc_lock;/* Wait queue for CPUs whose requests were batched */wait_queue_head_tpcc_write_wait_q;ktime_tlast_cmd_cmpl_time;ktime_tlast_mpar_reset;intmpar_count;intrefcount;};/* Array to represent the PCC channel per subspace ID */staticstructcppc_pcc_data*pcc_data[MAX_PCC_SUBSPACES];/* The cpu_pcc_subspace_idx contains per CPU subspace ID */staticDEFINE_PER_CPU(