mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
ACPI: PCC: Mailbox and generic updates for v6.7
Main updates include: 1. Addition of support for Type 4 PCC subspace that enables platform notification handling (Huisong Li). 2. Support for the shared interrupt amongst multiple PCC subspaces/ channels (Huisong Li). 3. Consolidation of PCC shared memory region command and status bitfields definitions that were duplicated and scattered across multiple PCC client drivers (Sudeep Holla). -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmUf3y8ACgkQAEG6vDF+ 4phTng/+Jp8DG6bNQidDLndQeUyiB2Ip9iPN72ucBVla9ZxWg7cQ2ljvmgOBI0AY V9DeBOXrkwln1TNaSxF5oyse8aUD6pU3e+V5QcTfUVFl9xUOVkgmlcV8RJOsHQyu h42P/ZsTg/TmiXOP6XUDWxS5Gdr0quYGl5Jk8YWFCdfvmj/k2/b5F+dLRujjWaZY EzaFWGoF8xavi96uqbzi0q9cAuqZtnhpPeP9ZzIhTYjDNMIyBRd7Paq7ESlq3omH 8W4zRkRaxPsNYmjAs2mnaOPQDy4gt1taJrRnQHwiebq2Gtqj6iNF1HT//hbYwL+d dZjccM9J0bP0n7459dwJugOumRSByZgwh4UT+lHdKeJmWmoZpoTXjkBfRjdg2piv DdE9ap2Wn+1xW7OF6lpeH75nFWo+/MRVufYU6mQ+7Zt1Ez0K9JTFm2VWo2fZqTx3 TG8LhjDX1SL12/e4kp+37z2RIpjkW5sf1m5uzTZzLwDwGUkKB1TZtU8MCK81erlA c9bmU9BtPhnft4CaAipwhnwyDPUUXCxVUpL3E5uknlBUU+1B7JyuaEarfQFg6I1Y JiZk11abrRQpva1myU16IYmuPiM1XJ9Mc5RCO0URv+tDoTEHpm707nbRn0jZgCNz O6DcUdES0bA2bySJ1kWfQfdghHSiHphzl15I4L/J69eMRToEFpk= =bZ1a -----END PGP SIGNATURE----- Merge tag 'acpi-pcc-updates-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux Merge ACPI PCC changes for v6.7 from Sudeep Holla: "ACPI: PCC: Mailbox and generic updates for v6.7 Main updates include: 1. Addition of support for Type 4 PCC subspace that enables platform notification handling (Huisong Li). 2. Support for the shared interrupt amongst multiple PCC subspaces/ channels (Huisong Li). 3. Consolidation of PCC shared memory region command and status bitfields definitions that were duplicated and scattered across multiple PCC client drivers (Sudeep Holla)." * tag 'acpi-pcc-updates-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: soc: kunpeng_hccs: Migrate to use generic PCC shmem related macros hwmon: (xgene) Migrate to use generic PCC shmem related macros i2c: xgene-slimpro: Migrate to use generic PCC shmem related macros ACPI: PCC: Add PCC shared memory region command and status bitfields mailbox: pcc: Support shared interrupt for multiple subspaces mailbox: pcc: Add support for platform notification handling
This commit is contained in:
commit
aa2e505c80
@ -57,12 +57,6 @@
|
||||
(MSG_TYPE_SET(MSG_TYPE_PWRMGMT) | \
|
||||
MSG_SUBTYPE_SET(hndl) | TPC_CMD_SET(cmd) | type)
|
||||
|
||||
/* PCC defines */
|
||||
#define PCC_SIGNATURE_MASK 0x50424300
|
||||
#define PCCC_GENERATE_DB_INT BIT(15)
|
||||
#define PCCS_CMD_COMPLETE BIT(0)
|
||||
#define PCCS_SCI_DOORBEL BIT(1)
|
||||
#define PCCS_PLATFORM_NOTIFICATION BIT(3)
|
||||
/*
|
||||
* Arbitrary retries in case the remote processor is slow to respond
|
||||
* to PCC commands
|
||||
@ -142,15 +136,15 @@ static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
|
||||
|
||||
/* Write signature for subspace */
|
||||
WRITE_ONCE(generic_comm_base->signature,
|
||||
cpu_to_le32(PCC_SIGNATURE_MASK | ctx->mbox_idx));
|
||||
cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx));
|
||||
|
||||
/* Write to the shared command region */
|
||||
WRITE_ONCE(generic_comm_base->command,
|
||||
cpu_to_le16(MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT));
|
||||
cpu_to_le16(MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR));
|
||||
|
||||
/* Flip CMD COMPLETE bit */
|
||||
val = le16_to_cpu(READ_ONCE(generic_comm_base->status));
|
||||
val &= ~PCCS_CMD_COMPLETE;
|
||||
val &= ~PCC_STATUS_CMD_COMPLETE;
|
||||
WRITE_ONCE(generic_comm_base->status, cpu_to_le16(val));
|
||||
|
||||
/* Copy the message to the PCC comm space */
|
||||
@ -544,7 +538,7 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg)
|
||||
msg = generic_comm_base + 1;
|
||||
/* Check if platform sends interrupt */
|
||||
if (!xgene_word_tst_and_clr(&generic_comm_base->status,
|
||||
PCCS_SCI_DOORBEL))
|
||||
PCC_STATUS_SCI_DOORBELL))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -566,7 +560,7 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg)
|
||||
TPC_CMD(((u32 *)msg)[0]) == TPC_ALARM))) {
|
||||
/* Check if platform completes command */
|
||||
if (xgene_word_tst_and_clr(&generic_comm_base->status,
|
||||
PCCS_CMD_COMPLETE)) {
|
||||
PCC_STATUS_CMD_COMPLETE)) {
|
||||
ctx->sync_msg.msg = ((u32 *)msg)[0];
|
||||
ctx->sync_msg.param1 = ((u32 *)msg)[1];
|
||||
ctx->sync_msg.param2 = ((u32 *)msg)[2];
|
||||
|
@ -91,14 +91,6 @@
|
||||
|
||||
#define SLIMPRO_IIC_MSG_DWORD_COUNT 3
|
||||
|
||||
/* PCC related defines */
|
||||
#define PCC_SIGNATURE 0x50424300
|
||||
#define PCC_STS_CMD_COMPLETE BIT(0)
|
||||
#define PCC_STS_SCI_DOORBELL BIT(1)
|
||||
#define PCC_STS_ERR BIT(2)
|
||||
#define PCC_STS_PLAT_NOTIFY BIT(3)
|
||||
#define PCC_CMD_GENERATE_DB_INT BIT(15)
|
||||
|
||||
struct slimpro_i2c_dev {
|
||||
struct i2c_adapter adapter;
|
||||
struct device *dev;
|
||||
@ -160,11 +152,11 @@ static void slimpro_i2c_pcc_rx_cb(struct mbox_client *cl, void *msg)
|
||||
|
||||
/* Check if platform sends interrupt */
|
||||
if (!xgene_word_tst_and_clr(&generic_comm_base->status,
|
||||
PCC_STS_SCI_DOORBELL))
|
||||
PCC_STATUS_SCI_DOORBELL))
|
||||
return;
|
||||
|
||||
if (xgene_word_tst_and_clr(&generic_comm_base->status,
|
||||
PCC_STS_CMD_COMPLETE)) {
|
||||
PCC_STATUS_CMD_COMPLETE)) {
|
||||
msg = generic_comm_base + 1;
|
||||
|
||||
/* Response message msg[1] contains the return value. */
|
||||
@ -186,10 +178,10 @@ static void slimpro_i2c_pcc_tx_prepare(struct slimpro_i2c_dev *ctx, u32 *msg)
|
||||
cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx));
|
||||
|
||||
WRITE_ONCE(generic_comm_base->command,
|
||||
cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INT));
|
||||
cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR));
|
||||
|
||||
status = le16_to_cpu(READ_ONCE(generic_comm_base->status));
|
||||
status &= ~PCC_STS_CMD_COMPLETE;
|
||||
status &= ~PCC_STATUS_CMD_COMPLETE;
|
||||
WRITE_ONCE(generic_comm_base->status, cpu_to_le16(status));
|
||||
|
||||
/* Copy the message to the PCC comm space */
|
||||
|
@ -91,6 +91,14 @@ struct pcc_chan_reg {
|
||||
* @cmd_update: PCC register bundle for the command complete update register
|
||||
* @error: PCC register bundle for the error status register
|
||||
* @plat_irq: platform interrupt
|
||||
* @type: PCC subspace type
|
||||
* @plat_irq_flags: platform interrupt flags
|
||||
* @chan_in_use: this flag is used just to check if the interrupt needs
|
||||
* handling when it is shared. Since only one transfer can occur
|
||||
* at a time and mailbox takes care of locking, this flag can be
|
||||
* accessed without a lock. Note: the type only support the
|
||||
* communication from OSPM to Platform, like type3, use it, and
|
||||
* other types completely ignore it.
|
||||
*/
|
||||
struct pcc_chan_info {
|
||||
struct pcc_mbox_chan chan;
|
||||
@ -100,12 +108,17 @@ struct pcc_chan_info {
|
||||
struct pcc_chan_reg cmd_update;
|
||||
struct pcc_chan_reg error;
|
||||
int plat_irq;
|
||||
u8 type;
|
||||
unsigned int plat_irq_flags;
|
||||
bool chan_in_use;
|
||||
};
|
||||
|
||||
#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
|
||||
static struct pcc_chan_info *chan_info;
|
||||
static int pcc_chan_count;
|
||||
|
||||
static int pcc_send_data(struct mbox_chan *chan, void *data);
|
||||
|
||||
/*
|
||||
* PCC can be used with perf critical drivers such as CPPC
|
||||
* So it makes sense to locally cache the virtual address and
|
||||
@ -221,6 +234,41 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags)
|
||||
return acpi_register_gsi(NULL, interrupt, trigger, polarity);
|
||||
}
|
||||
|
||||
static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan)
|
||||
{
|
||||
return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) ==
|
||||
ACPI_LEVEL_SENSITIVE;
|
||||
}
|
||||
|
||||
static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan)
|
||||
{
|
||||
u64 val;
|
||||
int ret;
|
||||
|
||||
ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if (!pchan->cmd_complete.gas)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Judge if the channel respond the interrupt based on the value of
|
||||
* command complete.
|
||||
*/
|
||||
val &= pchan->cmd_complete.status_mask;
|
||||
|
||||
/*
|
||||
* If this is PCC slave subspace channel, and the command complete
|
||||
* bit 0 indicates that Platform is sending a notification and OSPM
|
||||
* needs to respond this interrupt to process this command.
|
||||
*/
|
||||
if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
|
||||
return !val;
|
||||
|
||||
return !!val;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcc_mbox_irq - PCC mailbox interrupt handler
|
||||
* @irq: interrupt number
|
||||
@ -236,16 +284,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
|
||||
int ret;
|
||||
|
||||
pchan = chan->con_priv;
|
||||
|
||||
ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
|
||||
if (ret)
|
||||
if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE &&
|
||||
!pchan->chan_in_use)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (val) { /* Ensure GAS exists and value is non-zero */
|
||||
val &= pchan->cmd_complete.status_mask;
|
||||
if (!val)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
if (!pcc_mbox_cmd_complete_check(pchan))
|
||||
return IRQ_NONE;
|
||||
|
||||
ret = pcc_chan_reg_read(&pchan->error, &val);
|
||||
if (ret)
|
||||
@ -262,6 +306,16 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
|
||||
|
||||
mbox_chan_received_data(chan, NULL);
|
||||
|
||||
/*
|
||||
* The PCC slave subspace channel needs to set the command complete bit
|
||||
* and ring doorbell after processing message.
|
||||
*
|
||||
* The PCC master subspace channel clears chan_in_use to free channel.
|
||||
*/
|
||||
if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
|
||||
pcc_send_data(chan, NULL);
|
||||
pchan->chan_in_use = false;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -340,7 +394,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return pcc_chan_reg_read_modify_write(&pchan->db);
|
||||
ret = pcc_chan_reg_read_modify_write(&pchan->db);
|
||||
if (!ret && pchan->plat_irq > 0)
|
||||
pchan->chan_in_use = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,11 +411,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
|
||||
static int pcc_startup(struct mbox_chan *chan)
|
||||
{
|
||||
struct pcc_chan_info *pchan = chan->con_priv;
|
||||
unsigned long irqflags;
|
||||
int rc;
|
||||
|
||||
if (pchan->plat_irq > 0) {
|
||||
rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0,
|
||||
MBOX_IRQ_NAME, chan);
|
||||
irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ?
|
||||
IRQF_SHARED | IRQF_ONESHOT : 0;
|
||||
rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq,
|
||||
irqflags, MBOX_IRQ_NAME, chan);
|
||||
if (unlikely(rc)) {
|
||||
dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n",
|
||||
pchan->plat_irq);
|
||||
@ -463,6 +524,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
|
||||
pcct_ss->platform_interrupt);
|
||||
return -EINVAL;
|
||||
}
|
||||
pchan->plat_irq_flags = pcct_ss->flags;
|
||||
|
||||
if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
|
||||
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;
|
||||
@ -484,6 +546,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
|
||||
"PLAT IRQ ACK");
|
||||
}
|
||||
|
||||
if (pcc_chan_plat_irq_can_be_shared(pchan) &&
|
||||
!pchan->plat_irq_ack.gas) {
|
||||
pr_err("PCC subspace has level IRQ with no ACK register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -698,6 +766,7 @@ static int pcc_mbox_probe(struct platform_device *pdev)
|
||||
|
||||
pcc_parse_subspace_shmem(pchan, pcct_entry);
|
||||
|
||||
pchan->type = pcct_entry->type;
|
||||
pcct_entry = (struct acpi_subtable_header *)
|
||||
((unsigned long) pcct_entry + pcct_entry->length);
|
||||
}
|
||||
|
@ -31,10 +31,6 @@
|
||||
|
||||
#include "kunpeng_hccs.h"
|
||||
|
||||
/* PCC defines */
|
||||
#define HCCS_PCC_SIGNATURE_MASK 0x50434300
|
||||
#define HCCS_PCC_STATUS_CMD_COMPLETE BIT(0)
|
||||
|
||||
/*
|
||||
* Arbitrary retries in case the remote processor is slow to respond
|
||||
* to PCC commands
|
||||
@ -187,7 +183,7 @@ static int hccs_check_chan_cmd_complete(struct hccs_dev *hdev)
|
||||
* deadline_us(timeout_us) until PCC command complete bit is set(cond)
|
||||
*/
|
||||
ret = readw_poll_timeout(&comm_base->status, status,
|
||||
status & HCCS_PCC_STATUS_CMD_COMPLETE,
|
||||
status & PCC_STATUS_CMD_COMPLETE,
|
||||
HCCS_POLL_STATUS_TIME_INTERVAL_US,
|
||||
cl_info->deadline_us);
|
||||
if (unlikely(ret))
|
||||
@ -208,7 +204,7 @@ static int hccs_pcc_cmd_send(struct hccs_dev *hdev, u8 cmd,
|
||||
int ret;
|
||||
|
||||
/* Write signature for this subspace */
|
||||
tmp.signature = HCCS_PCC_SIGNATURE_MASK | hdev->chan_id;
|
||||
tmp.signature = PCC_SIGNATURE | hdev->chan_id;
|
||||
/* Write to the shared command region */
|
||||
tmp.command = cmd;
|
||||
/* Clear cmd complete bit */
|
||||
|
@ -18,7 +18,20 @@ struct pcc_mbox_chan {
|
||||
u16 min_turnaround_time;
|
||||
};
|
||||
|
||||
/* Generic Communications Channel Shared Memory Region */
|
||||
#define PCC_SIGNATURE 0x50434300
|
||||
/* Generic Communications Channel Command Field */
|
||||
#define PCC_CMD_GENERATE_DB_INTR BIT(15)
|
||||
/* Generic Communications Channel Status Field */
|
||||
#define PCC_STATUS_CMD_COMPLETE BIT(0)
|
||||
#define PCC_STATUS_SCI_DOORBELL BIT(1)
|
||||
#define PCC_STATUS_ERROR BIT(2)
|
||||
#define PCC_STATUS_PLATFORM_NOTIFY BIT(3)
|
||||
/* Initiator Responder Communications Channel Flags */
|
||||
#define PCC_CMD_COMPLETION_NOTIFY BIT(0)
|
||||
|
||||
#define MAX_PCC_SUBSPACES 256
|
||||
|
||||
#ifdef CONFIG_PCC
|
||||
extern struct pcc_mbox_chan *
|
||||
pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id);
|
||||
|
Loading…
Reference in New Issue
Block a user