[RFC 1/2] ACPI: Add support for Platform Communication Channel

Mark Brown broonie at kernel.org
Fri May 30 03:17:04 PDT 2014


On Tue, May 27, 2014 at 04:29:58PM -0400, Ashwin Chaugule wrote:
> 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.

This looks an awful lot like a mailbox - should it be integrated with
the mailbox system that Jassi (CCed) has been working on getting
upstream?  Not deleting any context for Jassi's benefit.

> 
> Signed-off-by: Ashwin Chaugule <ashwin.chaugule at linaro.org>
> ---
>  drivers/acpi/Kconfig  |  10 +++
>  drivers/acpi/Makefile |   2 +-
>  drivers/acpi/pcc.c    | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 203 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/acpi/pcc.c
> 
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index ff5c83c..8f40e52 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -352,6 +352,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..328ca93
> --- /dev/null
> +++ b/drivers/acpi/pcc.c
> @@ -0,0 +1,192 @@
> +/*
> + *	Copyright (C) 2014 Linaro Ltd.
> + *	Author:	Ashwin Chaugule <ashwin.chaugule at 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 PCC_CMD_COMPLETE	0x1
> +#define PCC_VERSION			"0.1"
> +
> +struct pcc_ss_desc {
> +	struct acpi_pcct_subspace *pcc_ss_ptr;
> +	raw_spinlock_t lock;
> +};
> +
> +/* Array of Type 0 PCC Subspace descriptors */
> +struct pcc_ss_desc pcc_ss_arr[MAX_PCC_SUBSPACES];
> +
> +/* 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].pcc_ss_ptr;
> +
> +	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].pcc_ss_ptr;
> +	struct acpi_pcct_shared_memory *generic_comm_base =
> +		(struct acpi_pcct_shared_memory *)base_addr;
> +	struct acpi_generic_address doorbell;
> +	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;
> +	}
> +
> +	raw_spin_lock(&pcc_ss_arr[ss_idx].lock);
> +
> +	/* 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);
> +
> +	/* Write Subspace MAGIC value so platform can identify destination. */
> +	iowrite32((PCCS_SS_SIG_MAGIC | ss_idx), &generic_comm_base->signature);
> +
> +	/* Flip CMD COMPLETE 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);
> +
> +	raw_spin_unlock(&pcc_ss_arr[ss_idx].lock);
> +
> +	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;
> +
> +	if (total_ss <= MAX_PCC_SUBSPACES) {
> +		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;
> +		}
> +
> +		pcc_ss_arr[total_ss].pcc_ss_ptr = pcct_ss;
> +		raw_spin_lock_init(&pcc_ss_arr[total_ss].lock);
> +
> +		total_ss++;
> +	} else {
> +		pr_err("No more space for PCC subspaces.\n");
> +		return -ENOSPC;
> +	}
> +
> +	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;
> +	}
> +
> +	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);
> -- 
> 1.8.3.2
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140530/121c531c/attachment-0001.sig>


More information about the linux-arm-kernel mailing list